Home Assistant Unofficial Reference 2024.12.1
update.py
Go to the documentation of this file.
1 """Update platform for Supervisor."""
2 
3 from __future__ import annotations
4 
5 from typing import Any
6 
7 from aiohasupervisor import SupervisorError
8 from aiohasupervisor.models import (
9  HomeAssistantUpdateOptions,
10  OSUpdate,
11  StoreAddonUpdate,
12 )
13 from awesomeversion import AwesomeVersion, AwesomeVersionStrategy
14 
16  UpdateEntity,
17  UpdateEntityDescription,
18  UpdateEntityFeature,
19 )
20 from homeassistant.config_entries import ConfigEntry
21 from homeassistant.const import ATTR_ICON, ATTR_NAME
22 from homeassistant.core import HomeAssistant
23 from homeassistant.exceptions import HomeAssistantError
24 from homeassistant.helpers.entity_platform import AddEntitiesCallback
25 
26 from .const import (
27  ADDONS_COORDINATOR,
28  ATTR_AUTO_UPDATE,
29  ATTR_CHANGELOG,
30  ATTR_VERSION,
31  ATTR_VERSION_LATEST,
32  DATA_KEY_ADDONS,
33  DATA_KEY_CORE,
34  DATA_KEY_OS,
35  DATA_KEY_SUPERVISOR,
36 )
37 from .entity import (
38  HassioAddonEntity,
39  HassioCoreEntity,
40  HassioOSEntity,
41  HassioSupervisorEntity,
42 )
43 
44 ENTITY_DESCRIPTION = UpdateEntityDescription(
45  name="Update",
46  key=ATTR_VERSION_LATEST,
47 )
48 
49 
51  hass: HomeAssistant,
52  config_entry: ConfigEntry,
53  async_add_entities: AddEntitiesCallback,
54 ) -> None:
55  """Set up Supervisor update based on a config entry."""
56  coordinator = hass.data[ADDONS_COORDINATOR]
57 
58  entities = [
60  coordinator=coordinator,
61  entity_description=ENTITY_DESCRIPTION,
62  ),
64  coordinator=coordinator,
65  entity_description=ENTITY_DESCRIPTION,
66  ),
67  ]
68 
69  entities.extend(
71  addon=addon,
72  coordinator=coordinator,
73  entity_description=ENTITY_DESCRIPTION,
74  )
75  for addon in coordinator.data[DATA_KEY_ADDONS].values()
76  )
77 
78  if coordinator.is_hass_os:
79  entities.append(
81  coordinator=coordinator,
82  entity_description=ENTITY_DESCRIPTION,
83  )
84  )
85 
86  async_add_entities(entities)
87 
88 
90  """Update entity to handle updates for the Supervisor add-ons."""
91 
92  _attr_supported_features = (
93  UpdateEntityFeature.INSTALL
94  | UpdateEntityFeature.BACKUP
95  | UpdateEntityFeature.RELEASE_NOTES
96  )
97 
98  @property
99  def _addon_data(self) -> dict:
100  """Return the add-on data."""
101  return self.coordinator.data[DATA_KEY_ADDONS][self._addon_slug_addon_slug]
102 
103  @property
104  def auto_update(self) -> bool:
105  """Return true if auto-update is enabled for the add-on."""
106  return self._addon_data_addon_data[ATTR_AUTO_UPDATE]
107 
108  @property
109  def title(self) -> str | None:
110  """Return the title of the update."""
111  return self._addon_data_addon_data[ATTR_NAME]
112 
113  @property
114  def latest_version(self) -> str | None:
115  """Latest version available for install."""
116  return self._addon_data_addon_data[ATTR_VERSION_LATEST]
117 
118  @property
119  def installed_version(self) -> str | None:
120  """Version installed and in use."""
121  return self._addon_data_addon_data[ATTR_VERSION]
122 
123  @property
124  def release_summary(self) -> str | None:
125  """Release summary for the add-on."""
126  return self._strip_release_notes_strip_release_notes()
127 
128  @property
129  def entity_picture(self) -> str | None:
130  """Return the icon of the add-on if any."""
131  if not self.availableavailableavailableavailable:
132  return None
133  if self._addon_data_addon_data[ATTR_ICON]:
134  return f"/api/hassio/addons/{self._addon_slug}/icon"
135  return None
136 
137  def _strip_release_notes(self) -> str | None:
138  """Strip the release notes to contain the needed sections."""
139  if (notes := self._addon_data_addon_data[ATTR_CHANGELOG]) is None:
140  return None
141 
142  if (
143  f"# {self.latest_version}" in notes
144  and f"# {self.installed_version}" in notes
145  ):
146  # Split the release notes to only what is between the versions if we can
147  new_notes = notes.split(f"# {self.installed_version}")[0]
148  if f"# {self.latest_version}" in new_notes:
149  # Make sure the latest version is still there.
150  # This can be False if the order of the release notes are not correct
151  # In that case we just return the whole release notes
152  return new_notes
153  return notes
154 
155  async def async_release_notes(self) -> str | None:
156  """Return the release notes for the update."""
157  return self._strip_release_notes_strip_release_notes()
158 
159  async def async_install(
160  self,
161  version: str | None = None,
162  backup: bool = False,
163  **kwargs: Any,
164  ) -> None:
165  """Install an update."""
166  try:
167  await self.coordinator.supervisor_client.store.update_addon(
168  self._addon_slug_addon_slug, StoreAddonUpdate(backup=backup)
169  )
170  except SupervisorError as err:
171  raise HomeAssistantError(f"Error updating {self.title}: {err}") from err
172 
173  await self.coordinator.force_info_update_supervisor()
174 
175 
177  """Update entity to handle updates for the Home Assistant Operating System."""
178 
179  _attr_supported_features = (
180  UpdateEntityFeature.INSTALL | UpdateEntityFeature.SPECIFIC_VERSION
181  )
182  _attr_title = "Home Assistant Operating System"
183 
184  @property
185  def latest_version(self) -> str:
186  """Return the latest version."""
187  return self.coordinator.data[DATA_KEY_OS][ATTR_VERSION_LATEST]
188 
189  @property
190  def installed_version(self) -> str:
191  """Return the installed version."""
192  return self.coordinator.data[DATA_KEY_OS][ATTR_VERSION]
193 
194  @property
195  def entity_picture(self) -> str | None:
196  """Return the icon of the entity."""
197  return "https://brands.home-assistant.io/homeassistant/icon.png"
198 
199  @property
200  def release_url(self) -> str | None:
201  """URL to the full release notes of the latest version available."""
202  version = AwesomeVersion(self.latest_versionlatest_versionlatest_version)
203  if version.dev or version.strategy == AwesomeVersionStrategy.UNKNOWN:
204  return "https://github.com/home-assistant/operating-system/commits/dev"
205  return (
206  f"https://github.com/home-assistant/operating-system/releases/tag/{version}"
207  )
208 
209  async def async_install(
210  self, version: str | None, backup: bool, **kwargs: Any
211  ) -> None:
212  """Install an update."""
213  try:
214  await self.coordinator.supervisor_client.os.update(
215  OSUpdate(version=version)
216  )
217  except SupervisorError as err:
218  raise HomeAssistantError(
219  f"Error updating Home Assistant Operating System: {err}"
220  ) from err
221 
222 
224  """Update entity to handle updates for the Home Assistant Supervisor."""
225 
226  _attr_supported_features = UpdateEntityFeature.INSTALL
227  _attr_title = "Home Assistant Supervisor"
228 
229  @property
230  def latest_version(self) -> str:
231  """Return the latest version."""
232  return self.coordinator.data[DATA_KEY_SUPERVISOR][ATTR_VERSION_LATEST]
233 
234  @property
235  def installed_version(self) -> str:
236  """Return the installed version."""
237  return self.coordinator.data[DATA_KEY_SUPERVISOR][ATTR_VERSION]
238 
239  @property
240  def auto_update(self) -> bool:
241  """Return true if auto-update is enabled for supervisor."""
242  return self.coordinator.data[DATA_KEY_SUPERVISOR][ATTR_AUTO_UPDATE]
243 
244  @property
245  def release_url(self) -> str | None:
246  """URL to the full release notes of the latest version available."""
247  version = AwesomeVersion(self.latest_versionlatest_versionlatest_version)
248  if version.dev or version.strategy == AwesomeVersionStrategy.UNKNOWN:
249  return "https://github.com/home-assistant/supervisor/commits/main"
250  return f"https://github.com/home-assistant/supervisor/releases/tag/{version}"
251 
252  @property
253  def entity_picture(self) -> str | None:
254  """Return the icon of the entity."""
255  return "https://brands.home-assistant.io/hassio/icon.png"
256 
257  async def async_install(
258  self, version: str | None, backup: bool, **kwargs: Any
259  ) -> None:
260  """Install an update."""
261  try:
262  await self.coordinator.supervisor_client.supervisor.update()
263  except SupervisorError as err:
264  raise HomeAssistantError(
265  f"Error updating Home Assistant Supervisor: {err}"
266  ) from err
267 
268 
270  """Update entity to handle updates for Home Assistant Core."""
271 
272  _attr_supported_features = (
273  UpdateEntityFeature.INSTALL
274  | UpdateEntityFeature.SPECIFIC_VERSION
275  | UpdateEntityFeature.BACKUP
276  )
277  _attr_title = "Home Assistant Core"
278 
279  @property
280  def latest_version(self) -> str:
281  """Return the latest version."""
282  return self.coordinator.data[DATA_KEY_CORE][ATTR_VERSION_LATEST]
283 
284  @property
285  def installed_version(self) -> str:
286  """Return the installed version."""
287  return self.coordinator.data[DATA_KEY_CORE][ATTR_VERSION]
288 
289  @property
290  def entity_picture(self) -> str | None:
291  """Return the icon of the entity."""
292  return "https://brands.home-assistant.io/homeassistant/icon.png"
293 
294  @property
295  def release_url(self) -> str | None:
296  """URL to the full release notes of the latest version available."""
297  version = AwesomeVersion(self.latest_versionlatest_versionlatest_version)
298  if version.dev:
299  return "https://github.com/home-assistant/core/commits/dev"
300  return f"https://{'rc' if version.beta else 'www'}.home-assistant.io/latest-release-notes/"
301 
302  async def async_install(
303  self, version: str | None, backup: bool, **kwargs: Any
304  ) -> None:
305  """Install an update."""
306  try:
307  await self.coordinator.supervisor_client.homeassistant.update(
308  HomeAssistantUpdateOptions(version=version, backup=backup)
309  )
310  except SupervisorError as err:
311  raise HomeAssistantError(
312  f"Error updating Home Assistant Core: {err}"
313  ) from err
None async_install(self, str|None version=None, bool backup=False, **Any kwargs)
Definition: update.py:164
None async_install(self, str|None version, bool backup, **Any kwargs)
Definition: update.py:304
None async_install(self, str|None version, bool backup, **Any kwargs)
Definition: update.py:211
None async_install(self, str|None version, bool backup, **Any kwargs)
Definition: update.py:259
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: update.py:54