diff --git a/homeassistant/components/hassio/__init__.py b/homeassistant/components/hassio/__init__.py index 8a69f553025..acc676bdf9f 100644 --- a/homeassistant/components/hassio/__init__.py +++ b/homeassistant/components/hassio/__init__.py @@ -51,6 +51,7 @@ from .auth import async_setup_auth_view from .const import ( ATTR_ADDON, ATTR_ADDONS, + ATTR_AUTO_UPDATE, ATTR_CHANGELOG, ATTR_DISCOVERY, ATTR_FOLDERS, @@ -98,6 +99,7 @@ DATA_INFO = "hassio_info" DATA_OS_INFO = "hassio_os_info" DATA_SUPERVISOR_INFO = "hassio_supervisor_info" DATA_ADDONS_CHANGELOGS = "hassio_addons_changelogs" +DATA_ADDONS_INFO = "hassio_addons_info" DATA_ADDONS_STATS = "hassio_addons_stats" HASSIO_UPDATE_INTERVAL = timedelta(minutes=5) @@ -422,6 +424,16 @@ def get_supervisor_info(hass): return hass.data.get(DATA_SUPERVISOR_INFO) +@callback +@bind_hass +def get_addons_info(hass): + """Return Addons info. + + Async friendly. + """ + return hass.data.get(DATA_ADDONS_INFO) + + @callback @bind_hass def get_addons_stats(hass): @@ -607,6 +619,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: changelog = await hassio.get_addon_changelog(slug) return (slug, changelog) + async def update_addon_info(slug): + """Return the info for an add-on.""" + info = await hassio.get_addon_info(slug) + return (slug, info) + async def update_info_data(now): """Update last available supervisor information.""" @@ -641,6 +658,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: *[update_addon_changelog(addon[ATTR_SLUG]) for addon in addons] ) ) + hass.data[DATA_ADDONS_INFO] = dict( + await asyncio.gather( + *[update_addon_info(addon[ATTR_SLUG]) for addon in addons] + ) + ) if ADDONS_COORDINATOR in hass.data: await hass.data[ADDONS_COORDINATOR].async_refresh() @@ -845,6 +867,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator): """Update data via library.""" new_data = {} supervisor_info = get_supervisor_info(self.hass) + addons_info = get_addons_info(self.hass) addons_stats = get_addons_stats(self.hass) addons_changelogs = get_addons_changelogs(self.hass) store_data = get_store(self.hass) @@ -858,6 +881,9 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator): addon[ATTR_SLUG]: { **addon, **((addons_stats or {}).get(addon[ATTR_SLUG], {})), + ATTR_AUTO_UPDATE: addons_info.get(addon[ATTR_SLUG], {}).get( + ATTR_AUTO_UPDATE, False + ), ATTR_CHANGELOG: (addons_changelogs or {}).get(addon[ATTR_SLUG]), ATTR_REPOSITORY: repositories.get( addon.get(ATTR_REPOSITORY), addon.get(ATTR_REPOSITORY, "") diff --git a/homeassistant/components/hassio/const.py b/homeassistant/components/hassio/const.py index 7f62748b835..8c27fdebb17 100644 --- a/homeassistant/components/hassio/const.py +++ b/homeassistant/components/hassio/const.py @@ -39,6 +39,7 @@ WS_TYPE_SUBSCRIBE = "supervisor/subscribe" EVENT_SUPERVISOR_EVENT = "supervisor_event" +ATTR_AUTO_UPDATE = "auto_update" ATTR_VERSION = "version" ATTR_VERSION_LATEST = "version_latest" ATTR_UPDATE_AVAILABLE = "update_available" diff --git a/homeassistant/components/hassio/update.py b/homeassistant/components/hassio/update.py index 41539aa21e0..d2953a0f801 100644 --- a/homeassistant/components/hassio/update.py +++ b/homeassistant/components/hassio/update.py @@ -24,6 +24,7 @@ from . import ( async_update_supervisor, ) from .const import ( + ATTR_AUTO_UPDATE, ATTR_CHANGELOG, ATTR_VERSION, ATTR_VERSION_LATEST, @@ -99,6 +100,11 @@ class SupervisorAddonUpdateEntity(HassioAddonEntity, UpdateEntity): """Return the add-on data.""" return self.coordinator.data[DATA_KEY_ADDONS][self._addon_slug] + @property + def auto_update(self): + """Return true if auto-update is enabled for the add-on.""" + return self._addon_data[ATTR_AUTO_UPDATE] + @property def title(self) -> str | None: """Return the title of the update.""" @@ -210,6 +216,7 @@ class SupervisorOSUpdateEntity(HassioOSEntity, UpdateEntity): class SupervisorSupervisorUpdateEntity(HassioSupervisorEntity, UpdateEntity): """Update entity to handle updates for the Home Assistant Supervisor.""" + _attr_auto_update = True _attr_supported_features = UpdateEntityFeature.INSTALL _attr_title = "Home Assistant Supervisor" diff --git a/tests/components/hassio/test_binary_sensor.py b/tests/components/hassio/test_binary_sensor.py index e48f8a6a481..ef114b90771 100644 --- a/tests/components/hassio/test_binary_sensor.py +++ b/tests/components/hassio/test_binary_sensor.py @@ -115,7 +115,15 @@ def mock_all(aioclient_mock, request): }, ) aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test/info", + json={"result": "ok", "data": {"auto_update": True}}, + ) aioclient_mock.get("http://127.0.0.1/addons/test2/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test2/info", + json={"result": "ok", "data": {"auto_update": False}}, + ) aioclient_mock.get( "http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}} ) diff --git a/tests/components/hassio/test_init.py b/tests/components/hassio/test_init.py index 30776fd5b17..1a50d9c3036 100644 --- a/tests/components/hassio/test_init.py +++ b/tests/components/hassio/test_init.py @@ -139,7 +139,15 @@ def mock_all(aioclient_mock, request): }, ) aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test/info", + json={"result": "ok", "data": {"auto_update": True}}, + ) aioclient_mock.get("http://127.0.0.1/addons/test2/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test2/info", + json={"result": "ok", "data": {"auto_update": False}}, + ) aioclient_mock.get( "http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}} ) diff --git a/tests/components/hassio/test_sensor.py b/tests/components/hassio/test_sensor.py index df309e94360..e6a35c4744d 100644 --- a/tests/components/hassio/test_sensor.py +++ b/tests/components/hassio/test_sensor.py @@ -108,7 +108,15 @@ def mock_all(aioclient_mock, request): }, ) aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test/info", + json={"result": "ok", "data": {"auto_update": True}}, + ) aioclient_mock.get("http://127.0.0.1/addons/test2/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test2/info", + json={"result": "ok", "data": {"auto_update": False}}, + ) aioclient_mock.get( "http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}} ) diff --git a/tests/components/hassio/test_update.py b/tests/components/hassio/test_update.py index 8442f01abf3..f9b7c201ba3 100644 --- a/tests/components/hassio/test_update.py +++ b/tests/components/hassio/test_update.py @@ -121,23 +121,37 @@ def mock_all(aioclient_mock, request): }, ) aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test/info", + json={"result": "ok", "data": {"auto_update": True}}, + ) aioclient_mock.get("http://127.0.0.1/addons/test2/changelog", text="") + aioclient_mock.get( + "http://127.0.0.1/addons/test2/info", + json={"result": "ok", "data": {"auto_update": False}}, + ) aioclient_mock.get( "http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}} ) @pytest.mark.parametrize( - "entity_id,expected", + "entity_id,expected_state, auto_update", [ - ("update.home_assistant_operating_system_update", "on"), - ("update.home_assistant_supervisor_update", "on"), - ("update.home_assistant_core_update", "on"), - ("update.test_update", "on"), - ("update.test2_update", "off"), + ("update.home_assistant_operating_system_update", "on", False), + ("update.home_assistant_supervisor_update", "on", True), + ("update.home_assistant_core_update", "on", False), + ("update.test_update", "on", True), + ("update.test2_update", "off", False), ], ) -async def test_update_entities(hass, entity_id, expected, aioclient_mock): +async def test_update_entities( + hass, + entity_id, + expected_state, + auto_update, + aioclient_mock, +): """Test update entities.""" config_entry = MockConfigEntry(domain=DOMAIN, data={}, unique_id=DOMAIN) config_entry.add_to_hass(hass) @@ -153,7 +167,10 @@ async def test_update_entities(hass, entity_id, expected, aioclient_mock): # Verify that the entity have the expected state. state = hass.states.get(entity_id) - assert state.state == expected + assert state.state == expected_state + + # Verify that the auto_update attribute is correct + assert state.attributes["auto_update"] is auto_update async def test_update_addon(hass, aioclient_mock):