Compare commits

...

737 Commits

Author SHA1 Message Date
dependabot[bot]
8f27958e20
Bump ruff from 0.11.5 to 0.11.6 (#5828)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-17 21:43:49 -10:00
Stefan Agner
6fad7d14e1
Avoid using host system socket for logs tests (#5825)
Make sure we mock the systemd journal gateway socket for tests. This
makes the test work on systems which have systemd-journal-gatewayd
installed.
2025-04-17 16:23:34 +02:00
dependabot[bot]
f7317134e3
Bump sentry-sdk from 2.26.0 to 2.26.1 (#5824)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 09:20:46 +02:00
dependabot[bot]
9d8db27701
Bump sentry-sdk from 2.25.1 to 2.26.0 (#5822)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.25.1 to 2.26.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.25.1...2.26.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-16 08:38:36 +02:00
dependabot[bot]
7da3a34304
Bump codecov/codecov-action from 5.4.0 to 5.4.2 (#5823) 2025-04-15 08:25:45 +02:00
Stefan Agner
d413e0dcb9
Drop typing-extensions from requirements (#5821)
The dependency typing-extensions has been added with #3848, but not
used much. With the update to Python 3.11 in #4666 the necessary types
are now available from the Python standard library, making
typing-extensions unused. Remove the now unnecessary typing-extensions
from the dependencies.
2025-04-11 10:40:24 +02:00
dependabot[bot]
542ab0411c
Bump typing-extensions from 4.13.1 to 4.13.2 (#5817)
Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.13.1 to 4.13.2.
- [Release notes](https://github.com/python/typing_extensions/releases)
- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/python/typing_extensions/compare/4.13.1...4.13.2)

---
updated-dependencies:
- dependency-name: typing-extensions
  dependency-version: 4.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 09:45:33 +02:00
dependabot[bot]
999789f7ce
Bump ruff from 0.11.4 to 0.11.5 (#5818)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.4 to 0.11.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.4...0.11.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.11.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 09:31:52 +02:00
dependabot[bot]
de105f8cb7
Bump debugpy from 1.8.13 to 1.8.14 (#5819)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.13 to 1.8.14.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.8.13...v1.8.14)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-version: 1.8.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 09:31:38 +02:00
dependabot[bot]
b37b0ff744
Bump urllib3 from 2.3.0 to 2.4.0 (#5820)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.3.0...2.4.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 09:31:25 +02:00
dependabot[bot]
db330ab58a
Update wheel requirement from ~=0.45.0 to ~=0.46.1 (#5816)
Updates the requirements on [wheel](https://github.com/pypa/wheel) to permit the latest version.
- [Release notes](https://github.com/pypa/wheel/releases)
- [Changelog](https://github.com/pypa/wheel/blob/main/docs/news.rst)
- [Commits](https://github.com/pypa/wheel/compare/0.45.0...0.46.1)

---
updated-dependencies:
- dependency-name: wheel
  dependency-version: 0.46.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 09:47:43 +02:00
Mike Degatano
4a00caa2e8
Fix mypy issues in docker, hardware and homeassistant modules (#5805)
* Fix mypy issues in docker and hardware modules

* Fix mypy issues in homeassistant module

* Fix async_send_command typing

* Fixes from feedback
2025-04-08 12:52:58 -04:00
Stefan Agner
59a7e9519d
Fix root path requests (#5815)
* Fix root path requests

Since #5759 we've tried to access the path explicitly. However, this
raises KeyError exception when trying to access the proxied root path
(e.g. http://supervisor/core/api/). Before #5759 get was used, which
lead to no exception, but instead inserted a `None` into the path.

It seems aiohttp doesn't provide a path when the root is accessed. So
simply convert this to no path as well by setting path to an empty
string.

* Add rudimentary pytest for regular proxy requets
2025-04-07 11:09:45 +02:00
dependabot[bot]
dedf5df5ad
Bump ruff from 0.11.3 to 0.11.4 (#5814)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.3 to 0.11.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.3...0.11.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.11.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 09:47:12 +02:00
dependabot[bot]
d09b686269
Bump pytest-cov from 6.1.0 to 6.1.1 (#5813)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 6.1.0 to 6.1.1.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v6.1.0...v6.1.1)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-version: 6.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 09:24:59 +02:00
dependabot[bot]
9b8f03fa00
Bump dbus-fast from 2.44.0 to 2.44.1 (#5807)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.44.0 to 2.44.1.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.44.0...v2.44.1)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-version: 2.44.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 09:37:09 +02:00
dependabot[bot]
2a3d0fdf61
Bump sentry-sdk from 2.25.0 to 2.25.1 (#5804)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.25.0 to 2.25.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.25.0...2.25.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.25.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 09:18:35 +02:00
dependabot[bot]
eaae40718b
Bump ruff from 0.11.2 to 0.11.3 (#5809)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.2 to 0.11.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.2...0.11.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.11.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 09:08:08 +02:00
dependabot[bot]
5a88128cec
Bump typing-extensions from 4.12.2 to 4.13.1 (#5808)
Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.12.2 to 4.13.1.
- [Release notes](https://github.com/python/typing_extensions/releases)
- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/python/typing_extensions/compare/4.12.2...4.13.1)

---
updated-dependencies:
- dependency-name: typing-extensions
  dependency-version: 4.13.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 08:52:39 +02:00
github-actions[bot]
62b3259d9c
Update frontend to version 20250401.0 (#5687)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-02 10:46:50 +02:00
dependabot[bot]
5e05af26a8
Bump dbus-fast from 2.43.0 to 2.44.0 (#5800)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.43.0 to 2.44.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.43.0...v2.44.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 10:36:31 +02:00
dependabot[bot]
c5186101d3
Bump pytest-cov from 6.0.0 to 6.1.0 (#5799)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 6.0.0 to 6.1.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v6.0.0...v6.1.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 09:26:00 +02:00
dependabot[bot]
86cf083902
Bump aiohttp from 3.11.15 to 3.11.16 (#5801)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.11.15 to 3.11.16.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.11.15...v3.11.16)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 09:25:43 +02:00
Mike Degatano
5c1f7ed18d
Switch iter_chunked to iter_chunks (#5798)
* Switch iter_chunked to iter_any

* iter_chunks not iter_any
2025-04-01 21:49:33 +02:00
dependabot[bot]
d051cbcafb
Bump aiohttp from 3.11.14 to 3.11.15 (#5795)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.11.14 to 3.11.15.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.11.14...v3.11.15)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-version: 3.11.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 11:31:00 +02:00
dependabot[bot]
798af687cf
Bump sentry-sdk from 2.24.1 to 2.25.0 (#5796)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.24.1 to 2.25.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.24.1...2.25.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 10:13:01 +02:00
Mike Degatano
01a682cfaa
Fix mypy issues in backups and dbus (#5792)
* Fix mypy issues in backups module

* Fix mypy issues in dbus module

* Fix mypy issues in api after rebase

* TypedDict to dataclass and other small fixes

* Finish fixing mypy errors in dbus

* local_where must exist

* Fix references to name in tests
2025-03-31 17:03:54 -04:00
dependabot[bot]
67b9a44160
Bump coverage from 7.7.1 to 7.8.0 (#5793) 2025-03-30 21:05:11 -10:00
Stefan Agner
8fe17d9270
Improve Home Assistant Core WebSocket proxy implementation (#5790)
* Improve Home Assistant Core WebSocket proxy implementation

This change removes unnecessary task creation for every WebSocket
message and instead creates just two tasks, one for each direction.
This improves performance by about factor of 3 when measuring 1000
WebSocket requests to Core (from ~530ms to ~160ms).

While at it, also handle all WebSocket message related to closing the
WebSocket and report all other errors as warnings instead of just info.

* Improve logging and error handling

* Add WS client error test case

* Use asyncio.gather directly

* Use asyncio.wait to handle exceptions gracefully

* Drop cancellation handling and correctly wait for the other proxy task
2025-03-28 10:35:49 +01:00
Jan Čermák
0a684bdb12
Add API for swap configuration (#5770)
* Add API for swap configuration

Add HTTP API for swap size and swappiness to /os/config/swap. Individual
options can be set in JSON and are calling the DBus API added in OS
Agent 1.7.x, available since OS 15.0. Check for presence of OS of the
required version and return 404 if the criteria are not met.

* Fix type hints and reboot_required logic

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Fix formatting after adding suggestions from GH

* Address @mdegat01 review comments

- Improve swap options validation
- Add swap to the 'all' property of dbus agent
- Use APINotFound with reason instead of HTTPNotFound
- Reorder API routes

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-03-27 17:53:46 +01:00
Mike Degatano
9222a3c9c0
Report stage with error in jobs (#5784)
* Report stage with error in jobs

* Copy doesn't lose track of the successful copies

* Add stage to errors in api output test

* revert unneessary change to import

* Add tests for a bit more coverage of copy_additional_locations
2025-03-27 10:07:06 -04:00
Jan Čermák
92cadb4c55
Fix /supervisor/reload after refactoring (#5791)
As discussed in [1], refactoring in #5759 changed signature of the
reload method and CLI now gets unexpected schema when `ha su reload` is
called. Change the method to return None as before and add a test for a
proper body content.

[1] https://github.com/home-assistant/supervisor/pull/5759/files#diff-1b4ed26f31e52ff5fe53efdc695eebacb1e46411f23cce58295591b2b20cd3faR238
2025-03-27 10:03:57 -04:00
Mike Degatano
8b3bf547d7
Skip corrupt registry files in backups (#5789) 2025-03-27 10:32:28 +01:00
Stefan Agner
81fc15d6ac
Handle unexpected WebSocket messages during auth (#5788)
* Handle unexpected WebSocket messages during auth

When an add-on does not respond or closes the WebSocket connection
during the authentication phase Supervisor does not handle errors
gracefully. Simply log such unexpected authentication to avoid
unnecessary stack traces in the log and make such cases no longer
appear on Sentry.

* Add pytest

* Introduce a timeout of 10s
2025-03-26 22:13:59 +01:00
Stefan Agner
63b507a589
Rate limit D-Bus errors (#5787)
It seems that some systems continously run into D-Bus errors
overwhelming the system itself but also generating lots of errors on
Sentry. Rate limit D-Bus errors to 3 for every message every 30s.
2025-03-26 17:02:58 +01:00
dependabot[bot]
af9b1e5b1e
Bump orjson from 3.10.12 to 3.10.16 (#5783)
Bumps [orjson](https://github.com/ijl/orjson) from 3.10.12 to 3.10.16.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.10.12...3.10.16)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 09:36:12 +01:00
dependabot[bot]
062103ae24
Bump setuptools from 78.0.2 to 78.1.0 (#5785) 2025-03-26 07:33:50 +01:00
dependabot[bot]
48807a65dd
Bump home-assistant/wheels from 2025.02.0 to 2025.03.0 (#5786) 2025-03-26 07:33:15 +01:00
Mike Degatano
0636e49fe2
Enable mypy part 1 (addons and api) (#5759)
* Fix mypy issues in addons

* Fix mypy issues in api

* fix docstring

* Brackets instead of get with default
2025-03-25 15:06:35 -04:00
dependabot[bot]
543d6efec4
Bump sentry-sdk from 2.24.0 to 2.24.1 (#5781)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.24.0 to 2.24.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.24.0...2.24.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 10:28:34 +01:00
Mike Degatano
80f7f07341
Add blockbuster option to API (#5746)
* Add blockbuster option to API

* cache not lru_cache
2025-03-25 09:40:43 +01:00
dependabot[bot]
ec721c41c1
Bump actions/setup-python from 5.4.0 to 5.5.0 (#5780)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.4.0...v5.5.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 08:23:24 +01:00
dependabot[bot]
03ca32ced4
Bump setuptools from 77.0.3 to 78.0.2 (#5782) 2025-03-25 07:48:51 +01:00
Jan Čermák
cb16a34401
Remove WipeDevice method from OS Agent DBus mock (#5744)
WipeDevice method was dropped from OS Agent code in [1]. Remove it from
the mock class to sync with the current API. There is no usage of
WipeDevice in the Supervisor codebase, only ScheduleWipeDevice is
called.

[1] https://github.com/home-assistant/os-agent/pull/225
2025-03-24 15:09:01 +01:00
dependabot[bot]
d756fd7e14
Bump dbus-fast from 2.39.6 to 2.43.0 (#5777)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.39.6 to 2.43.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.39.6...v2.43.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 11:07:01 +01:00
dependabot[bot]
c559bd47c3
Bump sentry-sdk from 2.23.1 to 2.24.0 (#5778) 2025-03-24 07:36:50 +01:00
dependabot[bot]
a2b3427be9
Bump ruff from 0.11.1 to 0.11.2 (#5779) 2025-03-24 07:28:40 +01:00
dependabot[bot]
6a2d7bad03
Bump coverage from 7.7.0 to 7.7.1 (#5776) 2025-03-24 07:23:53 +01:00
dependabot[bot]
cfdefbf043
Bump home-assistant/builder from 2025.02.0 to 2025.03.0 (#5774)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2025.02.0 to 2025.03.0.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2025.02.0...2025.03.0)

---
updated-dependencies:
- dependency-name: home-assistant/builder
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 21:43:41 +01:00
dependabot[bot]
d7e3dc41ff
Bump actions/download-artifact from 4.2.0 to 4.2.1 (#5769)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.2.0...v4.2.1)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-03-21 21:28:03 +01:00
dependabot[bot]
9afb50242b
Bump setuptools from 77.0.1 to 77.0.3 (#5772)
Bumps [setuptools](https://github.com/pypa/setuptools) from 77.0.1 to 77.0.3.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v77.0.1...v77.0.3)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-03-21 21:27:44 +01:00
dependabot[bot]
52b02d1235
Bump actions/upload-artifact from 4.6.1 to 4.6.2 (#5767)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.6.1...v4.6.2)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 21:07:23 +01:00
dependabot[bot]
84bc72d485
Bump ruff from 0.11.0 to 0.11.1 (#5771)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.0 to 0.11.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.0...0.11.1)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 21:01:54 +01:00
dependabot[bot]
bd772bb28a
Bump pylint from 3.3.4 to 3.3.6 (#5773)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.3.4 to 3.3.6.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.3.4...v3.3.6)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 20:59:17 +01:00
dependabot[bot]
fd2c7c3cc3
Bump getsentry/action-release from 3.1.0 to 3.1.1 (#5775) 2025-03-21 07:38:27 +01:00
dependabot[bot]
a7f139d3e1
Bump setuptools from 76.1.0 to 77.0.1 (#5766)
Bumps [setuptools](https://github.com/pypa/setuptools) from 76.1.0 to 77.0.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v76.1.0...v77.0.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 11:31:11 +01:00
dependabot[bot]
8a45e0fd85
Bump blockbuster from 1.5.23 to 1.5.24 (#5764)
Bumps [blockbuster](https://github.com/cbornet/blockbuster) from 1.5.23 to 1.5.24.
- [Release notes](https://github.com/cbornet/blockbuster/releases)
- [Commits](https://github.com/cbornet/blockbuster/commits)

---
updated-dependencies:
- dependency-name: blockbuster
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 11:08:57 +01:00
dependabot[bot]
52290b485b
Bump actions/cache from 4.2.2 to 4.2.3 (#5768) 2025-03-20 08:19:33 +01:00
dependabot[bot]
525d0fd8ea
Bump pre-commit from 4.1.0 to 4.2.0 (#5765) 2025-03-19 08:27:43 +01:00
dependabot[bot]
40c83f4c1e
Bump actions/download-artifact from 4.1.9 to 4.2.0 (#5763) 2025-03-19 07:34:25 +01:00
dependabot[bot]
99088ad880
Bump sentry-sdk from 2.22.0 to 2.23.1 (#5760)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.22.0 to 2.23.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.22.0...2.23.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 13:43:53 +01:00
dependabot[bot]
37c077205a
Bump setuptools from 76.0.0 to 76.1.0 (#5761)
Bumps [setuptools](https://github.com/pypa/setuptools) from 76.0.0 to 76.1.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v76.0.0...v76.1.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 12:01:03 +01:00
dependabot[bot]
ac5f9dcb59
Bump coverage from 7.6.12 to 7.7.0 (#5755) 2025-03-17 08:40:30 +01:00
dependabot[bot]
6a9269c052
Bump ruff from 0.10.0 to 0.11.0 (#5757) 2025-03-17 08:28:29 +01:00
dependabot[bot]
de615bfc1d
Bump docker/login-action from 3.3.0 to 3.4.0 (#5758) 2025-03-17 08:12:38 +01:00
dependabot[bot]
3ee639b133
Bump aiohttp from 3.11.13 to 3.11.14 (#5754)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-16 20:40:31 -10:00
dependabot[bot]
632e569347
Bump dbus-fast from 2.39.5 to 2.39.6 (#5756)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.39.5 to 2.39.6.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.39.5...v2.39.6)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-16 20:40:23 -10:00
Mike Degatano
cc74831113
Fix none error in mapping wireless fields (#5749) 2025-03-14 11:18:52 +01:00
dependabot[bot]
78c6868ad3
Bump dbus-fast from 2.39.3 to 2.39.5 (#5752)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.39.3 to 2.39.5.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.39.3...v2.39.5)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 10:06:44 +01:00
dependabot[bot]
f5f6e8b659
Bump ruff from 0.9.10 to 0.10.0 (#5751)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.10 to 0.10.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.10...0.10.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 09:50:13 +01:00
dependabot[bot]
c91a815cca
Bump attrs from 25.2.0 to 25.3.0 (#5750)
Bumps [attrs](https://github.com/sponsors/hynek) from 25.2.0 to 25.3.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: attrs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-14 09:45:04 +01:00
dependabot[bot]
1efe01c21f
Bump dbus-fast from 2.37.0 to 2.39.3 (#5736)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.37.0 to 2.39.3.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.37.0...v2.39.3)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 14:36:35 -04:00
dependabot[bot]
c54ff06e0f
Bump attrs from 25.1.0 to 25.2.0 (#5748)
Bumps [attrs](https://github.com/sponsors/hynek) from 25.1.0 to 25.2.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: attrs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 16:41:48 +01:00
Mike Degatano
5facf4e790
Fix logging error for invalid password for backup (#5747)
* Fix logging error for invalid password for backup

* Improved test
2025-03-12 15:21:10 -04:00
Wendelin
34752466d5
Remove release assets tarball on frontend update (#5743)
* Remove release assets tarball on frontend update

* Fix path to the removed tarball

---------

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>
2025-03-12 10:10:27 +01:00
dependabot[bot]
20ea71f7ff
Bump astroid from 3.3.8 to 3.3.9 (#5742)
Bumps [astroid](https://github.com/pylint-dev/astroid) from 3.3.8 to 3.3.9.
- [Release notes](https://github.com/pylint-dev/astroid/releases)
- [Changelog](https://github.com/pylint-dev/astroid/blob/main/ChangeLog)
- [Commits](https://github.com/pylint-dev/astroid/compare/v3.3.8...v3.3.9)

---
updated-dependencies:
- dependency-name: astroid
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 10:53:54 +01:00
dependabot[bot]
ac27e3ac0d
Bump ruff from 0.9.9 to 0.9.10 (#5741)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.9 to 0.9.10.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.9...0.9.10)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:15:24 +01:00
dependabot[bot]
b31e3ce234
Bump setuptools from 75.8.2 to 76.0.0 (#5740)
Bumps [setuptools](https://github.com/pypa/setuptools) from 75.8.2 to 76.0.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v75.8.2...v76.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:12:38 +01:00
Mike Degatano
e1c9c8b786
Finish out effort of adding and enabling blockbuster in tests (#5735)
* Finish out effort of adding and enabling blockbuster

* Skip getting addon file size until securetar fixed

* Fix test for devcontainer and blocking I/O

* Fix docker fixture and load_config to post_init
2025-03-07 13:29:24 +01:00
dependabot[bot]
23e03a95f4
Bump getsentry/action-release from 3.0.0 to 3.1.0 (#5737)
Bumps [getsentry/action-release](https://github.com/getsentry/action-release) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/getsentry/action-release/releases)
- [Changelog](https://github.com/getsentry/action-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/action-release/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: getsentry/action-release
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 13:12:33 +01:00
Stefan Agner
a2b8df0a6a
Use Sentry helper function to report warnings (#5734)
* Use Sentry helper function to report warnings

Don't use Sentry directly but the existing helper function.

* Add pytest that Sentry is by default off

* Address ruff

* Address ruff
2025-03-06 23:45:48 +01:00
Mike Degatano
6ef4f3cc67
Add blockbuster library and find I/O from unit tests (#5731)
* Add blockbuster library and find I/O from unit tests

* Fix lint and test issue

* Fixes from feedback

* Avoid modifying webapp object in executor

* Split su options validation and only validate timezone on change
2025-03-06 16:40:13 -05:00
dependabot[bot]
1fb4d1cc11
Bump dbus-fast from 2.35.1 to 2.37.0 (#5733)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.35.1 to 2.37.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.35.1...v2.37.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 12:21:13 +01:00
dependabot[bot]
65b1729314
Bump jinja2 from 3.1.5 to 3.1.6 (#5732)
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.5...3.1.6)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-06 09:44:59 +01:00
Stefan Agner
c7e3d86e2d
Revert "Enable Sentry asyncio integration (#5685)" (#5729)
This essentially reverts PR #5685.

The Sentry `AsyncioIntegration` replaces the asyncio task factory with
its instrumentalized version, which reports all execeptions which
aren't handled *within* a task to Sentry.

However, we quite often run tasks and handle exceptions outside, e.g.
this commen pattern (example from `MountManager` `reload()``):

```python
results = await asyncio.gather(
    *[mount.update() for mount in mounts], return_exceptions=True
)
... create resolution issues from results with exceptions ...
```

Here, asyncio.gather() uses ensure_future(), which converts the
co-routines to tasks. These Sentry instrumented tasks will then report
exceptions to Sentry, even though we handle exceptions gracefully.

So the `AsyncioIntegration` doesn't work for our use case, and causes
unnecessary noise in Sentry. Disable it again.
2025-03-05 12:31:30 +01:00
dependabot[bot]
5d06ebe430
Bump dbus-fast from 2.34.0 to 2.35.1 (#5728)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.34.0 to 2.35.1.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.34.0...v2.35.1)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-05 09:06:01 +01:00
dependabot[bot]
5aba616ba4
Bump debugpy from 1.8.12 to 1.8.13 (#5727)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.12 to 1.8.13.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.8.12...v1.8.13)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-05 09:05:52 +01:00
Mike Degatano
767f435090
Call core post init (#5725) 2025-03-05 09:05:23 +01:00
Stefan Agner
26024053ed
Fix add-on store repository getting removed without internet (#5717)
* Fix add-on store repository getting removed without internet

Currently, when a git command error happens in `pull()`, we declare
the repository as corrupt. Subsequent system autofix runs then execute
the reset resolution, which essentially removes the git repository from
the system.

In situations where the Internet fails right between the last
Supervisor connectivity check and the add-on store repository update
(the connectivity checks are throttled to once every 10 minutes while
connectivity is considered good), or if the outage is only partial
(e.g. reaching connectivity check works but the store repository is not
reachable), this leads to a git command error which declares the
repository as corrupt just as well, and ultimately leads to the removal
of the add-on store repository from the local system.

Run a git ls-remote first, which is used as an extra connectivity check.
This will also avoid removing the repository if Internet connectivity
works but the git provider is temporary down or not reachable.

That said, it will also fail if the repository is no longer present.
But this case needs extra handling anyways.

* Run git ls-remote in executor
2025-03-04 21:09:46 +01:00
Mike Degatano
324b059970
Move write of core state to executor (#5720) 2025-03-04 17:49:53 +01:00
Stefan Agner
76e916a07e
Make sure to close file stream after backup upload (#5723)
* Make sure to close file stream after backup upload

Currently the file stream does not get closed before importing the file
stream. It seems the test case didn't catch that, presumably because
it is a race condition if the bytes get flushed to disk or not.

Properly close the stream before continue handling the file.

* Close file stream in executor

* Add comment about closing twice is fine
2025-03-04 16:11:25 +01:00
Mike Degatano
582b128ad9
Finish migrating read_text to executor (#5698)
* Move read_text to executor

* switch to async_capture_exception

* Finish moving read_text to executor

* Cover read_bytes and some write_text calls as well

* Fix await issues

* Fix format_message
2025-03-04 11:45:44 +01:00
dependabot[bot]
c01d788c4c
Bump getsentry/action-release from 1.10.4 to 3.0.0 (#5721)
Bumps [getsentry/action-release](https://github.com/getsentry/action-release) from 1.10.4 to 3.0.0.
- [Release notes](https://github.com/getsentry/action-release/releases)
- [Changelog](https://github.com/getsentry/action-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/action-release/compare/v1.10.4...v3.0.0)

---
updated-dependencies:
- dependency-name: getsentry/action-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-04 11:44:44 +01:00
Jan Čermák
8fb66bcf18
Stop streaming logs when client closes connection (#5722)
When connection is closed by the client, the journal_logs_reader
generator still returns new lines, trying to write each one of them to
the closed transport. With debug logging enabled, this can end up in an
endless loop. To fix that, break out of the loop immediately after the
connection is reset.
2025-03-04 10:08:44 +01:00
Stefan Agner
fdd96ae21c
Fix add-on repair log message (#5719) 2025-03-03 18:49:24 -05:00
Stefan Agner
1355ef192d
Exclude non-Supervisor Server Error codes from Sentry reporting (#5718)
* Exclude non-Supervisor Server Error codes from Sentry reporting

Exclude status codes 502 Bad Gateway and 503 Service Unavailable from
Sentry aiohttp integration. These are returned by Supervisor itself
when acting as a proxy for Home Assistant Core. These aren't errors of
Supervisor.

* ruff check
2025-03-03 23:10:59 +01:00
Stefan Agner
f8bab20728
Replace non-unicode characters for add-on static files (#5712)
* Replace non-unicode characters for add-on static files

Add-on documentation and changelog get read and returned as text file.
However, in case the original author used non-unicode characters, or
the file corrupted, loading currently fails with an UnicodeDecodeError.

Let's just use the built-in replace error handling of Python, so they
appear for the user as  non-unicode characters by replacing them with
the official unicode replacement character "�".

* Remove superflous parameter for binary files

* ruff format

* Add pytests
2025-03-03 20:14:39 +01:00
Stefan Agner
9a3702bc1a
Avoid loading add-on store repositories too early (#5716)
When initially loading the store manager, update_repositories makes
sure that all repositories are actually present. If they are for some
reason corrupted or content is missing, we currently still trying
to load them which leads to an unnecessary warning:

```
2025-03-03 11:55:54.324 WARNING (SyncWorker_1) [supervisor.store.data] No repository information exists at /data/addons/git/a0d7b954
...
2025-03-03 11:55:54.343 INFO (MainThread) [supervisor.store.git] Cloning add-on https://github.com/hassio-addons/repository repository
```

Since update_repositories always loads the data, simply remove the
superfluous earlier loading attempt.

While at it, also improve the cloning/update log messages to make it
clear what repository is cloned/updated.
2025-03-03 19:01:47 +01:00
Jan Čermák
a7c6699f6a
Only log all ClientConnectionResets when returning logs (#5715)
* Suppress all ClientConnectionReset when returning logs

In #5358 we started suppressing ClientConnectionReset when logs are
returned from the Journal Gateway and the client ends connection
unexpectedly. The connection can be closed also when the headers are
returned, so ignore also that error.

Refs #5606

* Log ClientConnectionResetError as DEBUG instead of suppressing it
2025-03-03 13:51:40 +01:00
dependabot[bot]
fa7626f83a
Bump cryptography from 44.0.1 to 44.0.2 (#5709)
Bumps [cryptography](https://github.com/pyca/cryptography) from 44.0.1 to 44.0.2.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/44.0.1...44.0.2)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 13:48:42 +01:00
dependabot[bot]
84b265a2e0
Bump pytest from 8.3.4 to 8.3.5 (#5710) 2025-03-03 08:25:11 +01:00
dependabot[bot]
debcafa962
Bump ruff from 0.9.8 to 0.9.9 (#5711) 2025-03-03 08:13:55 +01:00
dependabot[bot]
4634ef82c6
Bump home-assistant/wheels from 2024.11.0 to 2025.02.0 (#5708) 2025-03-03 07:15:55 +01:00
Mike Degatano
5b18fb6b12
No executor task in sentry call when not initialized (#5703) 2025-03-01 10:46:11 -05:00
Stefan Agner
d42ec12ae8
Fix cloning of add-on store repository (#5701)
* Fix cloning of add-on store repository

Since #5669, the add-on store reset no longer deletes the root
directory. However, if the root directory is not present, the current
code no longer invokes cloning, instead tries to load the git
repository directly.

With this change, the code clones whenever there is no .git directory,
which works for both cases.

* Fix pytest
2025-03-01 16:17:07 +01:00
Mike Degatano
86133f8ecd
Move read_text to executor (#5688)
* Move read_text to executor

* Fix issues found by coderabbit

* formated to formatted

* switch to async_capture_exception

* Find and replace got one too many

* Update patch mock to async_capture_exception

* Drop Sentry capture from format_message

The error handling got introduced in #2052, however, #2100 essentially
makes sure there will never be a byte object passed to this function.
And even if, the Sentry aiohttp plug-in will properly catch such an
exception.

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2025-03-01 16:02:43 +01:00
Stefan Agner
12c951f62d
Fix tests in devcontainer by removing resolution center (#5702)
Since #5696 we don't need to load the resolution center early. In fact,
with #5686 this is even problematic for pytests in devcontainer, since
the Supervisor Core state is valid and this causes AppArmor evaluations
to run (and fail).

Actually, #5696 removed the resolution center. #5686 brought it
accidentally back. This was seemingly a merge error.
2025-03-01 16:00:49 +01:00
Stefan Agner
fcb3e2eb55
Update Supervisor bug form (#5700)
Update Supervisor bug form to reflect today's naming in the frontend.
2025-03-01 13:06:44 +01:00
Stefan Agner
176e511180
Capture warnings and report to sentry (#5697)
By default, warnings are simply printed to stderr. This makes them
easy to miss in the log. Capture warnings and user Python logger to log
them with warning level.

Also, if the message is an instance of Exception (which it typically
is), report the warning to Sentry. This is e.g. useful for asyncio
RuntimeWarning warnings "coroutine was never awaited".
2025-02-28 21:28:40 +01:00
Stefan Agner
696dcf6149
Initialize Supervisor Core state in constructor (#5686)
* Initialize Supervisor Core state in constructor

Make sure the Supervisor Core state is set to a value early on. This
makes sure that the state is always of type CoreState, and makes sure
that any use of the state can rely on it being an actual value from the
CoreState enum.

This fixes Sentry filter during early startup, where the state
previously was None. Because of that, the Sentry filter tried to
collect more Context, which lead to an exception and not reporting
errors.

* Fix pytest

It seems that with initializing the state early, the pytest actually
runs a system evaluation with:
Starting system evaluation with state initialize

Before it did that with:
Starting system evaluation with state None

It detects that the container runs as privileged, and declares the
system as unhealthy.

It is unclear to me why coresys.core.healthy was checked in this
context, it doesn't seem useful. Just remove the check, and validate
the state through the getter instead.

* Update supervisor/core.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Make sure Supervisor container is privileged in pytest

With the Supervisor Core state being valid now, some evaluations
now actually run when loading the resolution center. This leads to
Supervisor getting declared unhealthy due to not running in a privileged
container under pytest.

Fake the host container to be privileged to make evaluations not
causing the system to be declared unhealthy under pytest.

* Avoid writing actual Supervisor run state file

With the Supervisor Core state being valid from the very start, we end
up writing a state everytime.

Instead of actually writing a state file, simply validate the the
necessary calls are being made. This is more conform to typical unit
tests and avoids writing a file for every test.

* Extend WebSocket client fixture and use it consistently

Extend the ha_ws_client WebSocket client fixture to set Supervisor Core
into run state and clear all pending messages.

Currently only some tests use the ha_ws_client WebSocket client fixture.
Use it consistently for all tests.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-02-28 18:01:55 +01:00
Stefan Agner
8030b346e0
Load resolution evaluation, check and fixups early (#5696)
* Load resolution evaluation, check and fixups early

Before #5652, these modules were loaded in the constructor, hence early
in `initialize_coresys()`. Moving them late actually exposed an issue
where NetworkManager connectivity setter couldn't get the
`connectivity_check` evaluation, leading to an exception early in
bootstrap.

Technically, it might be safe to load the resolution modules only in
`Core.connect()`, however then we'd have to load them separately for
pytest. Let's go conservative and load them the same place where they
got loaded before #5652.

* Load resolution modules in a single executor call

* Fix pytest
2025-02-28 16:59:22 +01:00
Stefan Agner
53d97ce0c6
Improve plug-in update error message (#5695)
The current error message does not share any information about the
underlying problem why updating failed. Print the error to the logs.
2025-02-28 09:34:35 -05:00
Stefan Agner
77523f7bec
Avoid space in update link of frontend update PR (#5694)
A newline is converted to a space as per YAML folding rules. The space
breaks markdown parsing of the link. Use a single line for the target
version link.
2025-02-28 13:13:11 +01:00
Stefan Agner
f4d69f1811
Make advanced logs error test work in all test environments (#5692)
When developing/testing in a Supervised environment, the
systemd-journal-gatewayd socket is actually available. Mock the
socket Path file to make the test independent of the pytest
environment.
2025-02-28 12:59:20 +01:00
Stefan Agner
cf5a0dc548
Add body with update information to frontend update prs (#5691)
Overwrite the default body with useful version update information and
a link to the new release.

Also rename the title and use lower caps for local shell variables.
2025-02-28 11:57:30 +01:00
dependabot[bot]
a8cc3ae6ef
Bump actions/cache from 4.2.1 to 4.2.2 (#5690)
Bumps [actions/cache](https://github.com/actions/cache) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 10:21:43 +01:00
Stefan Agner
362bd8fd21
Enable Sentry asyncio integration (#5685)
Enable the Sentry asyncio integration. This makes sure that exception
in non-awaited tasks get reported to sentry.

While at it, use partial instead of lambda for the filter function.
2025-02-28 09:57:11 +01:00
Mike Degatano
2274de969f
File open calls to executor (#5678) 2025-02-28 09:56:59 +01:00
dependabot[bot]
dfed251c7a
Bump ruff from 0.9.7 to 0.9.8 (#5689)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.7 to 0.9.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.7...0.9.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-28 09:33:00 +01:00
Mike Degatano
151d4bdd73
Temporary directory to executor (#5673)
* Move temporary directory usage to executor

* Use temp_folder.name in Path constructor
2025-02-27 17:58:55 +01:00
Stefan Agner
c5d4ebcd48
Correctly handle aiohttp requests in Sentry reporting (#5681)
* Correctly handle aiohttp requests

The request header seems to be a dictionary in current Sentry SDK.
The previous code actually failed with an exception when trying to
unpack the header. However, it seems that Exceptions are not handled
or printed in this filter function, so those issues were simply
swallowed.

The new code has been tested to correctly sanitize and report issues
during aiohttp requests.

* Fix pytests
2025-02-27 15:54:51 +01:00
Stefan Agner
0ad559adcd
Add more context to Sentry reports early during startup (#5682)
* Initialize machine information before Sentry

* Set user and machine for all reports

Now that we initialize machine earlier we can report user and machine
for all events, even before Supervisor is completely initialized.

Also use the new tag format which is a dictionary.

Note that it seems that with the current Sentry SDK version the
AioHttpIntegration no longer sets the URL as a tag. So sanitation is
no longer reuqired.

* Update pytests
2025-02-27 15:45:11 +01:00
Stefan Agner
39f5b91f12
Use await for all FileConfiguration calls (#5683)
Some calls got missed in PR #5652. Update all calls to await the
save_data() coroutine.
2025-02-27 15:38:57 +01:00
dependabot[bot]
ddee79d209
Bump codecov/codecov-action from 5.3.1 to 5.4.0 (#5680)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.1 to 5.4.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.3.1...v5.4.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 09:04:24 +01:00
dependabot[bot]
ff111253d5
Bump setuptools from 75.8.1 to 75.8.2 (#5679)
Bumps [setuptools](https://github.com/pypa/setuptools) from 75.8.1 to 75.8.2.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v75.8.1...v75.8.2)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-27 09:04:03 +01:00
Mike Degatano
31193abb7b
FileConfiguration uses executor for I/O (#5652)
* FileConfiguration uses executor for I/O

* Fix credentials tests

* Remove migrate_system_env as its very deprecated
2025-02-26 19:11:11 +01:00
Stefan Agner
ae266e1692
Improve Supervisor restart detection message (#5672)
The word "reboot" is usually used when a operating system is restarted.
The current log message could be interpreted that the Supervisor
detected an operating system reboot.

Use restart to make it clear that the Supervisor detected a restart of
itself.
2025-02-26 13:10:40 -05:00
dependabot[bot]
c315a15816
Bump securetar from 2025.2.0 to 2025.2.1 (#5671)
* Bump securetar from 2025.2.0 to 2025.2.1

Bumps [securetar](https://github.com/pvizeli/securetar) from 2025.2.0 to 2025.2.1.
- [Release notes](https://github.com/pvizeli/securetar/releases)
- [Commits](https://github.com/pvizeli/securetar/compare/2025.2.0...2025.2.1)

---
updated-dependencies:
- dependency-name: securetar
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Handle new AddFileError where atomic_contents_add is used

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2025-02-26 09:30:22 -05:00
dependabot[bot]
3bd732147c
Bump actions/download-artifact from 4.1.8 to 4.1.9 (#5675)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-26 08:51:39 +01:00
dependabot[bot]
ddbde93a6d
Bump setuptools from 75.8.0 to 75.8.1 (#5676)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-26 08:51:16 +01:00
dependabot[bot]
6db11a8ade
Bump home-assistant/builder from 2024.08.2 to 2025.02.0 (#5674)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-26 08:46:38 +01:00
Stefan Agner
42e78408a7
Fix add-on store reset (#5669)
Make sure that add-on store resets do not delete the root folder. This
is important so that successive reset attempts do not fail (the
directory passed to `remove_folder` must exist, otherwise find fails
with an non-zero exit code).

While at it, handle find errors properly and report errors as critical.
2025-02-25 17:11:34 +01:00
Stefan Agner
15e8940c7f
Improve D-Bus timeout error handling (#5664)
* Improve D-Bus timeout error handling

Typically D-Bus timeouts are related to systemd activation timing out
after 25s. The current dbus-fast timeout of 10s is well below that
so we never get the actual D-Bus error. This increases the dbus-fast
timeout to 30s, which will make sure we wait long enought to get the
actual D-Bus error from the broker.

Note that this should not slow down a typical system, since we tried
three times each waiting for 10s. With the new error handling typically
we'll end up waiting 25s and then receive the actual D-Bus error. There
is no point in waiting for multiple D-Bus/systemd caused timeouts.

* Create D-Bus TimedOut exception
2025-02-25 17:11:23 +01:00
dependabot[bot]
644ec45ded
Bump aiohttp from 3.11.12 to 3.11.13 (#5665)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 12:02:45 +01:00
Stefan Agner
a8d2743f56
Define CPU architecture to fix armhf builds (#5670) 2025-02-25 11:36:35 +01:00
dependabot[bot]
0acef4a6e6
Bump dbus-fast from 2.33.0 to 2.34.0 (#5666)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 09:15:24 +01:00
Stefan Agner
5733db94aa
Revert "Fix add-on store reset"
This reverts commit da8c6cf1117e1b3d9522a293912376f5d455b389.
2025-02-25 09:10:27 +01:00
Stefan Agner
da8c6cf111
Fix add-on store reset
Make sure that add-on store resets do not delete the root folder. This
is important so that successive reset attempts do not fail (the
directory passed to `remove_folder` must exist, otherwise find fails
with an non-zero exit code).

While at it, handle find errors properly and report errors as critical.
2025-02-25 09:02:09 +01:00
Stefan Agner
802ee25a8b
Build Python wheels for Python 3.13 (#5667) 2025-02-25 08:48:07 +01:00
Stefan Agner
ce8b107f1e
Handle OS errors on backup create (#5662)
* Handle permission error on backup create

Make sure we handle (write) permission errors when creating a backup.

* Introduce BackupFileExistError and BackupPermissionError exceptions

* Make error messages a bit more uniform

* Drop use of exclusive mode

SecureTar does not handle exclusive mode nicely. Drop use of it for now.
2025-02-24 21:34:23 +01:00
Stefan Agner
32936e5de0
Handle non-zero subprocess exits (#5660)
With PR #5634 (which had the goal to remove I/O in event loop for backup
operations) the semantics of `remove_folder` changed slightly: Non-zero
exits of subprocesses were no longer handled, but lead to a
CalledProcessError.

Now to restore the semantics of `remove_folder` we should simply log an
error. However, this semantic change actually uncovered a potential
problem in deployed systems: There are 34 users on beta channel which
regularly seem to run `FixupStoreExecuteReset`, and with the semantic
change we see those errors in Sentry.

An obvious problem could be no storage. But in a quick test that would
not execute the repair in first place since the fixup has the job
condition `FREE_SPACE` set. So the problem is likely elsewhere.

With this change, we log the stderr of find, while still raising the
exception. With that we should get more context in Sentry to see what
could be the underlying error.
2025-02-24 12:30:39 +01:00
dependabot[bot]
c35746c3e1
Bump actions/upload-artifact from 4.6.0 to 4.6.1 (#5659) 2025-02-24 08:33:31 +01:00
dependabot[bot]
392dd9f904
Bump zlib-fast from 0.2.0 to 0.2.1 (#5658) 2025-02-24 08:31:37 +01:00
github-actions[bot]
d8f792950b
Autoupdate frontend to version 20250221.0 (#5616)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-22 21:44:20 +01:00
dependabot[bot]
1f6cdc3018
Bump sigstore/cosign-installer from 3.8.0 to 3.8.1 (#5654)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-21 19:36:11 +01:00
dependabot[bot]
616f1903b7
Bump ruff from 0.9.6 to 0.9.7 (#5653) 2025-02-21 14:50:51 +01:00
Stefan Agner
997a51fc42
Remove I/O in event loop for add-on backup and restore (#5649)
* Remove I/O in event loop for add-on backup and restore

Remove I/O in event loop for add-on backup and restore operations. On
backup, this moves the add-on shutdown before metadata is stored in the
backup, which slightly lenghens the time the add-on is actually stopped.

However, the biggest contributor here is likely adding the image
itself if it is a local backup. However, since that is the minority of
cases, I've opted for simplicity over optimizing for this case.

* Use partial to explicitly bind arguments
2025-02-21 00:24:36 +01:00
dependabot[bot]
cda6325be4
Bump actions/cache from 4.2.0 to 4.2.1 (#5650) 2025-02-20 09:07:48 +01:00
Stefan Agner
c8cc6fe003
Remove I/O in event loop for Home Assistant Core backup (#5648)
* Remove I/O in event loop for Home Assistant Core backup

The Home Assistant Core backup still contains some I/O in the event
loop. Move all I/O into the executor.

* Update supervisor/homeassistant/module.py

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-02-19 20:11:37 +01:00
Stefan Agner
34939cfe52
Remove I/O in event loop for backup load, import and remove (#5647)
* Avoid IO in event loop when removing backup

* Refactor backup size calculation

Currently size is lazy loaded when required via properties. This
however is blocking the async event loop.

Backup sizes don't change. Instead of lazy loading the size of a backup
simply determine it on loading/after creation.

* Fix tests for backup size change

* Avoid IO in event loop when loading backups

* Avoid IO in event loop when importing a backup
2025-02-19 16:00:17 +01:00
Stefan Agner
37bc703bbb
Disable uv cache when creating container image (#5646)
We don't intent to run uv again, so the cache is not really useful.
The cache directory size is around 80MB, however, the files are mostly
hardlinks to the original files in `/usr/local/lib/python3.13/site-packages`
so the actual saving is much smaller.
2025-02-19 10:45:22 +01:00
Stefan Agner
5f8e41b441
Capture errors correctly while copying backups (#5644)
Make sure we correctly capture errors while copying backups by using
the current job instance.
2025-02-19 09:12:36 +01:00
Stefan Agner
606db3585c
Remove I/O in event loop for backup create and restore operations (#5634)
* Remove I/O from backup create() function

* Move mount check into exectutor thread

* Remove I/O from backup open() function

* Remove I/O from _folder_save()

* Refactor remove_folder and remove_folder_with_excludes

Make remove_folder and remove_folder_with_excludes synchronous
functions which need to be run in an executor thread to be safely used
in asyncio. This makes them better composable with other I/O operations
like checking for file existence etc.

* Fix logger typo

* Use return values for functions running in an exectutor

* Move location check into a separate function

* Fix extract
2025-02-18 20:59:09 +01:00
Robert Resch
4054749eb2
Use uv to install supervisor (#5642) 2025-02-18 14:54:23 -05:00
Robert Resch
ad5827d33f
Bump uv to 0.6.1 (#5641)
* Bump uv to 0.6.0

* Bump uv to 0.6.1
2025-02-18 19:26:36 +01:00
Jan Čermák
249464e928
Generate Python bytecode for site-packages during build (#5640)
Since transition from pip to uv in #5152, Supervisor container doesn't
contain bytecode for site-packages anymore, and because our AppArmor
profile denies mkdir operations, the compiled *.pyc files are never
created. Enable uv --compile option to opt for the same behavior as pip
had, to fix of the AA errors and the potential penalty of compilation on
every import.
2025-02-18 18:44:37 +01:00
dependabot[bot]
3bc55c054a
Bump sentry-sdk from 2.21.0 to 2.22.0 (#5638)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.21.0 to 2.22.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.21.0...2.22.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-18 12:28:17 +01:00
Stefan Agner
4c108eea64
Always validate Backup before restoring (#5632)
* Validate Backup always before restoring

Since #5519 we check the encryption password early in restore case.
This has the side effect that we check the file existance early too.
However, in the non-encryption case, the file is not checked early.

This PR changes the behavior to always validate the backup file before
restoring, ensuring both encryption and non-encryption cases are
handled consistently.

In particular, the last case of test_restore_immediate_errors actually
validates that behavior. That test should actually have failed so far.
But it seems that because we validate the backup shortly after freeze
anyways, the exception still got raised early enough.

A simply `await asyncio.sleep(10)` right after the freeze makes the
test case fail. With this change, the test works consistently.

* Address pylint

* Fix backup_manager tests

* Drop warning message
2025-02-14 18:19:35 +01:00
Stefan Agner
9b2dbd634d
Avoid exception when handling closed WebSocket connection (#5630)
When delivering multiple messages to Core, and the first fails with a
connection error, the second message will also fail with the same error.
But at this point the connection is already clsoed, which leads to an
exception in the exception handler. Avoid this compunding error by
checking if the connection is still exists before trying to close.

Fixes: #5629
2025-02-14 13:12:56 +01:00
dependabot[bot]
2cb2a48184
Bump securetar from 2025.1.4 to 2025.2.0 (#5628)
Bumps [securetar](https://github.com/pvizeli/securetar) from 2025.1.4 to 2025.2.0.
- [Release notes](https://github.com/pvizeli/securetar/releases)
- [Commits](https://github.com/pvizeli/securetar/compare/2025.1.4...2025.2.0)

---
updated-dependencies:
- dependency-name: securetar
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-14 11:05:21 +01:00
dependabot[bot]
ed5a0b511e
Bump sentry-sdk from 2.20.0 to 2.21.0 (#5625)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.20.0 to 2.21.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.20.0...2.21.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-13 10:32:49 +01:00
dependabot[bot]
1475dcb50b
Bump cryptography from 44.0.0 to 44.0.1 (#5621)
Bumps [cryptography](https://github.com/pyca/cryptography) from 44.0.0 to 44.0.1.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/44.0.0...44.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-02-12 13:43:01 +01:00
dependabot[bot]
5cd7f6fd84
Bump coverage from 7.6.11 to 7.6.12 (#5622) 2025-02-12 08:04:09 +01:00
Mike Degatano
52cc17fa3f
Delay initial version fetch until there is connectivity (#5603)
* Delay inital version fetch until there is connectivity

* Add test

* Only mock get not whole websession object

* drive delayed fetch off of supervisor connectivity not host

* Fix test to not rely on sleep guessing to track tasks

* Use fixture to remove job throttle temporarily
2025-02-11 13:22:33 +01:00
dependabot[bot]
fa6949f4e4
Bump getsentry/action-release from 1.10.2 to 1.10.4 (#5619)
Bumps [getsentry/action-release](https://github.com/getsentry/action-release) from 1.10.2 to 1.10.4.
- [Release notes](https://github.com/getsentry/action-release/releases)
- [Changelog](https://github.com/getsentry/action-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/action-release/compare/v1.10.2...v1.10.4)

---
updated-dependencies:
- dependency-name: getsentry/action-release
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 11:39:24 +01:00
dependabot[bot]
63a4cee770
Bump ruff from 0.9.5 to 0.9.6 (#5618) 2025-02-11 07:48:02 +01:00
dependabot[bot]
7aed0c1b0d
Bump getsentry/action-release from 1.10.1 to 1.10.2 (#5615) 2025-02-10 07:57:30 +01:00
dependabot[bot]
de592a6ef4
Bump coverage from 7.6.10 to 7.6.11 (#5614) 2025-02-10 07:57:14 +01:00
dependabot[bot]
ff7086c0d0
Bump getsentry/action-release from 1.9.0 to 1.10.1 (#5611)
Bumps [getsentry/action-release](https://github.com/getsentry/action-release) from 1.9.0 to 1.10.1.
- [Release notes](https://github.com/getsentry/action-release/releases)
- [Changelog](https://github.com/getsentry/action-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/action-release/compare/v1.9.0...v1.10.1)

---
updated-dependencies:
- dependency-name: getsentry/action-release
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-07 11:30:45 +01:00
dependabot[bot]
ef0352ecd6
Bump ruff from 0.9.4 to 0.9.5 (#5612) 2025-02-07 09:18:45 +01:00
Stefan Agner
7348745049
Print the exact reason if the WebSocket event to Core fails (#5609)
* Print the exact reason if the WebSocket event to Core fails

* Improve error at backup end too, fix tests

* Fix text

* Address ruff check issue
2025-02-06 18:17:46 +01:00
github-actions[bot]
2078044062
Autoupdate frontend to version 20250205.0 (#5543)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-06 17:34:18 +01:00
Stefan Agner
d254937590
Drop Docker config from Supervisor backup (#5605)
* Drop Docker config from Supervisor backup

The Docker config is part of the main backup metadata. Because we
consolidate encrypted and unencrypted backups today, this leads to
potential bugs when restoring a backup.

* Drop obsolete encrypt/decrypt functions

* Drop unused Backup Job stage
2025-02-06 11:15:56 +01:00
dependabot[bot]
9a8e52d1fc
Bump aiohttp from 3.11.11 to 3.11.12 (#5608)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 09:37:03 +01:00
dependabot[bot]
6e7fac5493
Bump dbus-fast from 2.32.0 to 2.33.0 (#5607)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.32.0 to 2.33.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.32.0...v2.33.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 09:28:19 +01:00
Mike Degatano
129a37a1f4
Prevent race condition with location reload and backups list (#5602) 2025-02-05 14:24:37 +01:00
dependabot[bot]
01382e774e
Bump sigstore/cosign-installer from 3.7.0 to 3.8.0 (#5604)
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.7.0...v3.8.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-05 09:16:40 +01:00
Stefan Agner
9164d35615
Fix restoring unencrypted backup in corner case (#5600)
* Fix restoring unencrypted backup in corner case

If a backup has a encrypted and unencrypted location, and the encrypted
location is beeing restored first, the encryption key is still cached.
When the user restores the unencrypted backup next, it will fail because
the Supervisor tries to use encryption key still.

* Add integration test for restoring backups with and without encryption

* Rename _validate_location_password to _set_location_password

* Reload backup metadata from restore location

* Revert "Reload backup metadata from restore location"

This reverts commit 9b47a1cfe9a2682a0908e08cd143373744084fb7.

* Make pytest work/punt the ball on docker config restore issue

* Address pylint error
2025-02-04 17:53:22 +01:00
Stefan Agner
58df65541c
Handle non-existing file in Backup password check too (#5599)
* Handle non-existing file in Backup password check too

Make sure we handle a non-existing backup file also when validating
the password.

* Update supervisor/backups/manager.py

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>

* Add test case and fix password check when multiple locations

* Mock default backup unprotected by default

Instead of setting the protected property which we might not use
everywhere, simply mock the default backup to be unprotected.

* Fix mock of protected backup

* Introduce test for validate_password

Testing showed that validate_password doesn't return anything. Extend
tests to cover this case and fix the actual code.

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-02-04 11:23:05 +01:00
Mike Degatano
4c04f364a3
Use full match in homeassistant backup excludes (#5597) 2025-02-03 13:47:12 +01:00
Mike Degatano
7f39538231
Update cache if a backup file is missing (#5596)
* Update cache if a backup file is missing

* Remove references to single file reload
2025-02-03 13:46:57 +01:00
dependabot[bot]
be98e0c0f4
Bump dbus-fast from 2.30.2 to 2.32.0 (#5598)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.30.2 to 2.32.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.30.2...v2.32.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:29:59 +01:00
Stefan Agner
9491b1ff89
Avoid reordering add-on repositories on Backup load (#5595)
* Avoid reordering add-on repositories on Backup load

The `ensure_builtin_repositories` function uses a set to deduplicate
items, which sometimes led to a change of order in elements. This is
problematic when deduplicating Backups.

Simply avoid mangling the list of add-on repositories on load. Instead
rely on `update_repositories` which uses the same function to ensure
built-in repositories when loading the store configuration and restoring
a backup file.

* Update tests

* ruff format

* ruff check

* ruff check fixes

* ruff format

* Update tests/store/test_validate.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Simplify test

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-01-31 12:10:47 -05:00
Stefan Agner
30cbb039d0
Handle non-existing backup file (#5590)
* Make the API return 404 for non-existing backup files

* Introduce BackupFileNotFoundError exception

* Return 404 on full restore as well

* Fix remaining API tests

* Improve error handling in delete

* Fix pytest

* Fix tests and change error handling to agreed logic

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-01-31 14:27:24 +01:00
Jan Čermák
1aabca9489
Make sure the oldest boot ID is included in the boot list (#5591)
If the system is running for a long time, or the logging is particularly
chatty, the Systemd journal message we use to detect boot will be
rotated out of the journal. Currently we only handled it if there was
one boot, but we usually always missed the oldest boot if there were
more boots.

Adjust the method for getting boot IDs to always get the very first log
line in the journal instead of the last one, and make sure its boot ID
is included in the list.
2025-01-31 11:55:05 +01:00
Stefan Agner
28a87db515
Avoid test failure by not checking exact size of backup (#5594)
* Avoid test failure by not checking exact size of backup

This is a workaround for the fact that the backup size is not exactly
the same every time. This is due to the fact that the inner gziped tar
file can vary in size due to difference in json file (key order) and
potentially also different field values (UUID, backup slug).

It seems that sorting the keys makes the actual difference today, but
this has runtime overhead and might not catch all cases.

Simply check if size property is there and a number bigger than 0
instead.

* Fix pytest
2025-01-31 11:30:43 +01:00
dependabot[bot]
05b648629f
Bump ruff from 0.9.3 to 0.9.4 (#5592)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.3 to 0.9.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.3...0.9.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-31 08:27:43 +01:00
dependabot[bot]
d1d8446480
Bump pylint from 3.3.3 to 3.3.4 (#5586) 2025-01-29 08:17:18 +01:00
Mike Degatano
8b897ba537
Fix bug when uploading backup to a mount (#5585) 2025-01-28 18:30:37 +01:00
Mike Degatano
c8f1b222c0
Add sizes per location and support .local (#5581) 2025-01-28 11:41:51 +01:00
dependabot[bot]
257e2ceb82
Bump actions/setup-python from 5.3.0 to 5.4.0 (#5583)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.3.0...v5.4.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 11:36:24 +01:00
dependabot[bot]
67a27cae40
Bump securetar from 2025.1.3 to 2025.1.4 (#5582)
Bumps [securetar](https://github.com/pvizeli/securetar) from 2025.1.3 to 2025.1.4.
- [Release notes](https://github.com/pvizeli/securetar/releases)
- [Commits](https://github.com/pvizeli/securetar/compare/2025.1.3...2025.1.4)

---
updated-dependencies:
- dependency-name: securetar
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 11:35:28 +01:00
Stefan Agner
8ff9c08e82
Support systemd-journal-gatewayd using a TCP socket (#5576) 2025-01-27 13:57:59 +01:00
Stefan Agner
1b0aa30881
Extend backup upload API with file name parameter (#5568)
* Extend backup upload API with file name parameter

Add a query parameter which allows to specify the file name on upload.
All locations will store the backup with the same file name.

* ruff format

* Update tests to cover bad filename

* Fix ruff check error

* Drop unnecessary logging
2025-01-27 10:01:29 +01:00
dependabot[bot]
2a8d2d2b48
Bump codecov/codecov-action from 5.3.0 to 5.3.1 (#5580)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.0 to 5.3.1.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.3.0...v5.3.1)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:07:39 +01:00
dependabot[bot]
44bd787276
Bump attrs from 24.3.0 to 25.1.0 (#5579)
Bumps [attrs](https://github.com/sponsors/hynek) from 24.3.0 to 25.1.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: attrs
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:07:21 +01:00
Stefan Agner
690f1c07a7
Use version which is treated CalVer by AwesomeVersion (#5572)
* Use version which is treated CalVer by AwesomeVersion

The current dev version `99.9.9dev` is treated as unkown version type
by AwesomeVersion. This prevents the version from comparing with
actual Supervisor versions, e.g. from an exsiting backup file.

Make the development version a valid CalVer version so development
versions can handle non-development backups.

* Bump to year 9999
2025-01-24 09:59:50 +01:00
dependabot[bot]
8e185a8413
Bump pytest-aiohttp from 1.0.5 to 1.1.0 (#5573)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-24 08:34:21 +01:00
dependabot[bot]
1f7df73964
Bump codecov/codecov-action from 5.2.0 to 5.3.0 (#5575)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-24 08:34:05 +01:00
dependabot[bot]
a10afc45b1
Bump ruff from 0.9.2 to 0.9.3 (#5574) 2025-01-24 07:30:28 +01:00
Mike Degatano
61a2101d8a
Backup protected status can vary per location (#5569)
* Backup protected status can vary per location

* Fix test_backup_remove_error test

* Update supervisor/backups/backup.py

* Add Docker registry configuration to backup metadata

* Make use of backup location fixture

* Address pylint

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2025-01-23 15:05:35 -05:00
Stefan Agner
088832c253
Extend backup API with file name field (#5567)
* Extend backup API with file name field

Allow to specify a backup file name when creating a backup. This allows
for user friendly backup file names. If none is specified, the current
behavior remains (backup file name is the backup slug).

* Check passed file name using regex

* Use custom filename on download only if backup file name is backup slug

* ruff format

* Remove path from location for download file name
2025-01-23 15:24:47 +01:00
dependabot[bot]
a545b680b3
Bump codecov/codecov-action from 5.1.2 to 5.2.0 (#5571)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-23 08:52:49 +01:00
dependabot[bot]
805017eabf
Bump dbus-fast from 2.28.0 to 2.30.2 (#5562)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.28.0 to 2.30.2.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.28.0...v2.30.2)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 12:06:41 +01:00
Stefan Agner
b7412b0679
Update Python to 3.13 (#5564)
* Bump Supervisor to Python 3.13

* Update ruff configuration to 0.9.1

Adjust pyproject.toml for ruff 0.9.1. Also make sure that latest version
of ruff is used in pre-commit.

* Set default configuration for pytest-asyncio

* Run ruff check

* Drop deprecated decorator no_type_check_decorator

The upstream PR (https://github.com/python/cpython/issues/106309) says
this never got really implemented by type checkers.

* Bump devcontainer to latest release
2025-01-21 11:57:30 +01:00
dependabot[bot]
fff3bfd01e
Bump pre-commit from 4.0.1 to 4.1.0 (#5566) 2025-01-21 07:40:07 +01:00
dependabot[bot]
5f165a79ba
Bump actions/stale from 9.0.0 to 9.1.0 (#5565) 2025-01-21 07:39:51 +01:00
dependabot[bot]
0d3acd1aca
Bump release-drafter/release-drafter from 6.0.0 to 6.1.0 (#5563) 2025-01-20 08:09:23 +01:00
dependabot[bot]
463f196472
Bump securetar from 2024.11.0 to 2025.1.3 (#5553)
* Bump securetar from 2024.11.0 to 2025.1.3

Bumps [securetar](https://github.com/pvizeli/securetar) from 2024.11.0 to 2025.1.3.
- [Release notes](https://github.com/pvizeli/securetar/releases)
- [Commits](https://github.com/pvizeli/securetar/compare/2024.11.0...2025.1.3)

---
updated-dependencies:
- dependency-name: securetar
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Use file_filter and add test for addon backup_exclude

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2025-01-17 11:18:55 +01:00
dependabot[bot]
52d5df6778
Bump ruff from 0.9.1 to 0.9.2 (#5558)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-17 08:28:19 +01:00
dependabot[bot]
ce75c85e65
Bump debugpy from 1.8.11 to 1.8.12 (#5559) 2025-01-17 07:42:59 +01:00
puddly
12fd61142d
Trigger rescan on device remove (#5447) 2025-01-16 18:16:47 +01:00
Mike Degatano
0073227785
Add env on core restart due to restore (#5548)
* Add env on core restart due to restore

* Move is_restore to backup manager
2025-01-16 18:15:06 +01:00
Stefan Agner
89a215cc1f
Revert "Bump dbus-fast from 2.28.0 to 2.29.0 (#5551)" (#5555)
This reverts commit da6bdfa7953807081e181e46b801e425a08b20f4.
2025-01-16 12:51:16 +01:00
Stefan Agner
b2aece8208
Revert "Bump orjson from 3.10.12 to 3.10.13 (#5514)" (#5554)
This reverts commit dbd37d657515aca26eeabe5a3cdb239128b34a41.
2025-01-16 11:35:48 +01:00
Mike Degatano
600bf91c4f
Sort jobs by creation in API (#5545)
* Sort jobs by creation in API

* Fix tests missing new field

* Fix sorting logic around child jobs
2025-01-16 09:51:44 +01:00
dependabot[bot]
da6bdfa795
Bump dbus-fast from 2.28.0 to 2.29.0 (#5551)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.28.0 to 2.29.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.28.0...v2.29.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-16 09:51:29 +01:00
dependabot[bot]
5d4894a1ba
Bump getsentry/action-release from 1.8.0 to 1.9.0 (#5552)
Bumps [getsentry/action-release](https://github.com/getsentry/action-release) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/getsentry/action-release/releases)
- [Changelog](https://github.com/getsentry/action-release/blob/master/docs/publishing-a-release.md)
- [Commits](https://github.com/getsentry/action-release/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: getsentry/action-release
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-16 09:51:03 +01:00
Stefan Agner
d4c047bd01
Add tun to static device list in hardware manager (#5547)
Some devices are provided by kernel modules which potentially get loaded
later at startup. Those are not listed by udev, and hence add-ons do
not get permissions for these types of devices as long as the kernel
module is not loaded.

Typically, such devices are created by the kmod-static-nodes.service
systemd service. Ideally, we would read the output of that service and
add those specifically. However, there are very few devices which
use static nodes, and we actually only really interested in tun. So
let's simply add this static node in case udev does not list it already.
2025-01-15 09:56:32 +01:00
dependabot[bot]
6183b9719c
Bump sentry-sdk from 2.19.2 to 2.20.0 (#5549)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.19.2 to 2.20.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.19.2...2.20.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 09:54:07 +01:00
Alexander Akhmetov
f02d67ee47
Add support for CAP_CHECKPOINT_RESTORE privileges (#5426) 2025-01-14 11:28:36 +01:00
Stefan Agner
bd156ebb53
Add X-Accel-Buffering to disable buffers in proxies (#5544) 2025-01-14 10:42:41 +01:00
Wendelin
b07236b544
Add frontend auto update workflow (#5501)
* Remove git submodule

* Add frontend auto update workflow

* Update .github/workflows/update_frontend.yml

Co-authored-by: Stefan Agner <stefan@agner.ch>

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2025-01-13 12:35:54 +01:00
dependabot[bot]
5928a31fc4
Bump dbus-fast from 2.24.4 to 2.28.0 (#5532)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.24.4 to 2.28.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.24.4...v2.28.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 11:38:46 +01:00
dependabot[bot]
3a71ea7003
Bump ruff from 0.9.0 to 0.9.1 (#5542)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.0...0.9.1)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 11:38:12 +01:00
dependabot[bot]
96900b1f1b
Bump actions/upload-artifact from 4.5.0 to 4.6.0 (#5534)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-11 13:28:31 +01:00
dependabot[bot]
65b39661a6
Bump getsentry/action-release from 1.7.0 to 1.8.0 (#5535)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-11 13:27:24 +01:00
dependabot[bot]
18251ae8ae
Bump ruff from 0.8.6 to 0.9.0 (#5538) 2025-01-11 13:06:45 +01:00
dependabot[bot]
c418e0ea76
Bump setuptools from 75.7.0 to 75.8.0 (#5536) 2025-01-11 12:33:30 +01:00
dependabot[bot]
74b009ccd7
Bump ruff from 0.8.5 to 0.8.6 (#5528)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-06 12:18:44 +01:00
dependabot[bot]
d2631bf398
Bump setuptools from 75.6.0 to 75.7.0 (#5529) 2025-01-06 08:12:21 +01:00
dependabot[bot]
c62358d851
Bump ruff from 0.8.4 to 0.8.5 (#5522)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-03 10:19:05 +01:00
dependabot[bot]
e3af04701a
Bump gitpython from 3.1.43 to 3.1.44 (#5523)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-03 09:54:05 +01:00
Stefan Agner
c2f6e319f2
Check password early on backup restore (#5519)
Introduce a validate password method which only peaks into the archive
to validate the password before starting the actual restore process.
This makes sure that a wrong password returns an error even when
restoring the backup in background.
2024-12-31 13:58:12 +01:00
Stefan Agner
61b37877be
Avoid lingering tasks when using background backup tasks (#5518)
When a backup tasks is run in background, but actually has an error
early the secondary event task to release the callee is lingering around
still, ultimately leading to a "Task was destroyed but it is pending!"
asyncio error.

Make sure we cancel the event task in case the backup returns early.
2024-12-31 13:16:18 +01:00
Stefan Agner
e72c5a037b
Drop dead folder restore code (#5517)
The inner function _folder_restore has been converted to a Job with
PR #4802. The inner function is no longer used. Drop this dead code.
2024-12-31 13:16:04 +01:00
Stefan Agner
578383411c
Fix backup remove for alternate locations (#5515)
Currently the API converts backup locations on network mounts to
the Supervisor's Mount representation. However, the locations stored
in the backup representations is a dictionary with the location
string as key.

Make sure to use the backup location string to validate the remove
requests. This fixes removing backups from network storage mounts.
2024-12-30 14:18:11 +01:00
dependabot[bot]
dbd37d6575
Bump orjson from 3.10.12 to 3.10.13 (#5514)
Bumps [orjson](https://github.com/ijl/orjson) from 3.10.12 to 3.10.13.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.10.12...3.10.13)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 11:16:25 +01:00
dependabot[bot]
c7cf1e7593
Bump pulsectl from 24.11.0 to 24.12.0 (#5512)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 24.11.0 to 24.12.0.
- [Changelog](https://github.com/mk-fg/python-pulse-control/blob/master/CHANGES.rst)
- [Commits](https://github.com/mk-fg/python-pulse-control/compare/24.11.0...24.12.0)

---
updated-dependencies:
- dependency-name: pulsectl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 09:28:16 +01:00
dependabot[bot]
c06fb069ab
Bump coverage from 7.6.9 to 7.6.10 (#5513) 2024-12-27 08:03:29 +01:00
dependabot[bot]
b6c2259bd7
Bump pylint from 3.3.2 to 3.3.3 (#5511)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 09:00:09 +01:00
dependabot[bot]
d0b7cc8ab3
Bump astroid from 3.3.7 to 3.3.8 (#5510) 2024-12-24 08:18:42 +01:00
dependabot[bot]
0f77021bcc
Bump astroid from 3.3.6 to 3.3.7 (#5507)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-12-23 14:26:07 +01:00
dependabot[bot]
b44e6d8cd3
Bump urllib3 from 2.2.3 to 2.3.0 (#5504)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.3 to 2.3.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.2.3...2.3.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 12:40:52 +01:00
dependabot[bot]
dfe9e94f87
Bump jinja2 from 3.1.4 to 3.1.5 (#5503)
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.4...3.1.5)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 12:40:38 +01:00
Stefan Agner
53ccc5249a
Add astroid to pytest requirements (#5506) 2024-12-23 12:27:49 +01:00
dependabot[bot]
5993818c16
Bump ruff from 0.8.3 to 0.8.4 (#5500)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-20 10:23:28 +01:00
dependabot[bot]
a631dea01a
Bump codecov/codecov-action from 5.1.1 to 5.1.2 (#5499)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5.1.1...v5.1.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-19 18:40:22 +01:00
J. Nick Koston
c5b85b2831
Bump aiohttp to 3.11.11 (#5498)
changelog: https://github.com/aio-libs/aiohttp/compare/v3.11.10...v3.11.11

https://github.com/aio-libs/aiohttp/releases/tag/v3.11.11
2024-12-18 23:14:36 +01:00
Stefan Agner
3c1920e4e1
Bump frontend to 20241127.8 release (#5495) 2024-12-18 15:54:40 +01:00
dependabot[bot]
ca6ae7f4ce
Bump actions/upload-artifact from 4.4.3 to 4.5.0 (#5494) 2024-12-18 07:45:01 +01:00
dependabot[bot]
031ad0dbe6
Bump attrs from 24.2.0 to 24.3.0 (#5492)
Bumps [attrs](https://github.com/sponsors/hynek) from 24.2.0 to 24.3.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: attrs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 14:11:40 +01:00
Mike Degatano
d8101ddba8
Use status 404 in more places when appropriate (#5480) 2024-12-17 11:18:32 +01:00
Mike Degatano
de68868788
Restore backup from specific location (#5491) 2024-12-17 11:09:32 +01:00
Mike Degatano
90590ae2de
Add all addons flag to partial backups (#5490) 2024-12-16 18:25:58 +01:00
dependabot[bot]
5e6bef7189
Bump debugpy from 1.8.9 to 1.8.11 (#5488) 2024-12-16 07:27:26 +01:00
dependabot[bot]
7ab5555087
Bump ruff from 0.8.2 to 0.8.3 (#5483)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-13 09:22:18 +01:00
Mike Degatano
02ceb713ea
Add location to backup download and remove APIs (#5482) 2024-12-12 19:44:40 +01:00
Mike Degatano
774aef74e8
Backup not found returns 404 instead of 400 (#5479) 2024-12-10 22:30:07 +01:00
dependabot[bot]
045454b597
Bump ciso8601 from 2.3.1 to 2.3.2 (#5478)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-10 08:24:28 +01:00
Mike Degatano
829193fe84
Support CGroup v2 on Supervised with manual restarts (#5419) 2024-12-09 15:09:54 +01:00
Mike Degatano
1f893117cc
Fix backup consolidate and upload duplicate (#5472) 2024-12-09 10:03:49 +01:00
dependabot[bot]
9008009727
Bump sentry-sdk from 2.19.1 to 2.19.2 (#5476)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 08:27:33 +01:00
dependabot[bot]
3bf3bffabf
Bump coverage from 7.6.8 to 7.6.9 (#5475)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 08:17:26 +01:00
Mike Degatano
d44e995aed
Add size in bytes to backups (#5473) 2024-12-07 10:27:23 +01:00
dependabot[bot]
5a22599b93
Bump orjson from 3.10.7 to 3.10.12 (#5449)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 21:19:14 +01:00
dependabot[bot]
ae60e947f3
Bump sentry-sdk from 2.19.0 to 2.19.1 (#5467)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 11:51:27 -06:00
dependabot[bot]
8115fd98bc
Bump ruff from 0.8.1 to 0.8.2 (#5468)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-06 11:51:11 -06:00
dependabot[bot]
3201061ada
Bump codecov/codecov-action from 5.0.7 to 5.1.1 (#5470) 2024-12-06 08:22:42 +01:00
dependabot[bot]
b68caecbce
Bump actions/cache from 4.1.2 to 4.2.0 (#5469) 2024-12-06 08:22:16 +01:00
J. Nick Koston
5e780293c7
Bump aiohttp to 3.11.10 (#5466)
changelog: https://github.com/aio-libs/aiohttp/compare/v3.11.9...v3.11.10
2024-12-05 23:44:19 -05:00
Mike Degatano
6e32144e9a
Fix and extend cloud backup support (#5464)
* Fix and extend cloud backup support

* Clean up task for cloud backup and remove by location

* Args to kwargs on backup methods

* Fix backup remove error test and typing clean up
2024-12-05 00:07:04 -05:00
dependabot[bot]
9b52fee0a3
Bump aiohttp from 3.11.8 to 3.11.9 (#5461)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 14:43:08 +01:00
dependabot[bot]
7af4b17430
Bump cryptography from 43.0.3 to 44.0.0 (#5456)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 13:15:27 +01:00
dependabot[bot]
4195c0fb33
Bump pytest from 8.3.3 to 8.3.4 (#5462) 2024-12-02 08:42:13 +01:00
dependabot[bot]
8fe1cfbb20
Bump coverage from 7.6.7 to 7.6.8 (#5451) 2024-12-02 08:41:58 +01:00
dependabot[bot]
623c532c9e
Bump pylint from 3.3.1 to 3.3.2 (#5460) 2024-12-02 08:05:04 +01:00
dependabot[bot]
3a904383af
Bump ruff from 0.8.0 to 0.8.1 (#5459)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 16:47:50 -06:00
dependabot[bot]
28299affef
Bump aiohttp from 3.11.7 to 3.11.8 (#5457) 2024-11-28 07:35:49 +01:00
Mike Degatano
11ca772ada
Disable backup complete ws message (#5452) 2024-11-26 09:08:12 +01:00
Mike Degatano
42e704d563
Fix flaky backup test (#5453) 2024-11-26 00:47:00 +01:00
dependabot[bot]
ec7241c0fd
Bump ruff from 0.7.4 to 0.8.0 (#5450)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.7.4 to 0.8.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.7.4...0.8.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 08:51:31 +01:00
Mike Degatano
d11d59dd92
Add null check on user path in mounts (#5446) 2024-11-22 09:54:21 -05:00
dependabot[bot]
7a55f58a5f
Bump debugpy from 1.8.8 to 1.8.9 (#5444)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-22 08:55:42 +01:00
dependabot[bot]
0b5b5f7fd4
Bump sentry-sdk from 2.18.0 to 2.19.0 (#5443)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-22 08:52:40 +01:00
dependabot[bot]
56f3d384d6
Bump aiohttp from 3.11.6 to 3.11.7 (#5442)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-22 08:43:45 +01:00
dependabot[bot]
29117bb90b
Bump securetar from 2024.2.1 to 2024.11.0 (#5445)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-22 08:43:26 +01:00
Mike Degatano
5519f6a53b
Add support for cloud backups in Core (#5438)
* Add support for cloud backups in Core

* Test cases and small fixes identified

* Add test for partial reload no file failure
2024-11-21 18:14:20 -05:00
dependabot[bot]
a45d507bee
Bump setuptools from 75.5.0 to 75.6.0 (#5440)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 08:12:18 +01:00
dependabot[bot]
0a663b5c27
Bump codecov/codecov-action from 5.0.4 to 5.0.7 (#5441)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 08:06:37 +01:00
dependabot[bot]
0f1fed525c
Bump aiohttp from 3.11.4 to 3.11.6 (#5436)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 09:06:59 +01:00
dependabot[bot]
209cddc843
Bump codecov/codecov-action from 5.0.2 to 5.0.4 (#5437)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 08:45:11 +01:00
dependabot[bot]
4e0de93096
Bump aiohttp from 3.11.2 to 3.11.4 (#5434)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 08:26:46 +01:00
dependabot[bot]
3b6c5d5d33
Bump ruff from 0.7.3 to 0.7.4 (#5428)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 08:57:09 +01:00
dependabot[bot]
0843971e95
Bump dbus-fast from 2.24.3 to 2.24.4 (#5430)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 08:56:01 +01:00
dependabot[bot]
12d7496cd1
Bump codecov/codecov-action from 5.0.0 to 5.0.2 (#5427)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 08:55:35 +01:00
dependabot[bot]
ed34348c80
Bump coverage from 7.6.5 to 7.6.7 (#5429) 2024-11-18 07:59:39 +01:00
dependabot[bot]
fefb83558a
Bump aiohttp from 3.10.11 to 3.11.2 (#5421)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-15 10:33:11 +01:00
dependabot[bot]
93a0ae4030
Bump coverage from 7.6.4 to 7.6.5 (#5424)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-15 09:44:08 +01:00
dependabot[bot]
5394cff296
Bump codecov/codecov-action from 4.6.0 to 5.0.0 (#5422)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-15 09:40:59 +01:00
dependabot[bot]
ca3e6da943
Bump setuptools from 75.4.0 to 75.5.0 (#5417)
Bumps [setuptools](https://github.com/pypa/setuptools) from 75.4.0 to 75.5.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v75.4.0...v75.5.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-14 09:43:19 -05:00
Mike Degatano
756a5f8836
Increase time between update checks (#5413) 2024-11-14 09:42:03 +01:00
Mike Degatano
a8e7bb670e
Remove unhealthy after failed update on startup (#5412) 2024-11-14 09:41:47 +01:00
J. Nick Koston
687d7652a0
Bump aiohttp to 3.10.11 (#5414) 2024-11-13 19:28:02 +01:00
dependabot[bot]
9f414ee9da
Bump setuptools from 75.3.0 to 75.4.0 (#5411) 2024-11-12 07:13:53 +01:00
dependabot[bot]
67c2f8eb83
Bump ruff from 0.7.2 to 0.7.3 (#5403) 2024-11-11 08:13:57 +01:00
dependabot[bot]
c033d5ce8d
Bump home-assistant/wheels from 2024.07.1 to 2024.11.0 (#5404) 2024-11-11 08:12:22 +01:00
dependabot[bot]
fd056f3840
Update wheel requirement from ~=0.40.0 to ~=0.45.0 (#5402) 2024-11-11 07:21:31 +01:00
dependabot[bot]
e3488b8a08
Bump debugpy from 1.8.7 to 1.8.8 (#5400)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 08:43:41 +01:00
Mike Degatano
e1e5d3a8f2
Create addon boot failed issue for repair (#5397)
* Create addon boot failed issue for repair

* MDont make new objects for contains checks
2024-11-07 13:39:15 -05:00
Wendelin
473662e56d
Bump frontend 2024.11.07 (#5399) 2024-11-07 16:46:32 +01:00
Wendelin
b29bc23487
Bump frontend 2024.11.06.1 (#5394) 2024-11-06 14:13:30 +01:00
Wendelin
54817ef562
Bump frontend 2024.11.06 (#5393) 2024-11-06 11:21:22 +01:00
dependabot[bot]
dd8abf738e
Bump sentry-sdk from 2.17.0 to 2.18.0 (#5392)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.17.0 to 2.18.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.17.0...2.18.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 08:15:18 +01:00
Mike Degatano
55e58d39d9
Add fallback for boot IDs query (#5391) 2024-11-05 08:01:46 +01:00
Wendelin
ac5ce4cc9e
Bump frontend 2024.11.04.2 (#5390) 2024-11-04 12:07:37 -05:00
dependabot[bot]
2525467a2e
Bump pulsectl from 24.8.0 to 24.11.0 (#5388)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 24.8.0 to 24.11.0.
- [Changelog](https://github.com/mk-fg/python-pulse-control/blob/master/CHANGES.rst)
- [Commits](https://github.com/mk-fg/python-pulse-control/commits)

---
updated-dependencies:
- dependency-name: pulsectl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 08:23:15 +00:00
Wendelin
81066aab83
Bump frontend 2024.11.04 (#5383)
* Bump frontend 2024.10.31

* Bump frontend 2024.11.04
2024-11-04 08:21:27 +00:00
dependabot[bot]
93f4b24e72
Bump ruff from 0.7.1 to 0.7.2 (#5386) 2024-11-04 09:00:36 +01:00
Mike Degatano
9a07ff7fc4
Update supervisor immediately on new version (#5375)
* Update supervisor immediately on new version

* Switch reload updater task
2024-10-30 12:12:43 -04:00
dependabot[bot]
1a278f2590
Bump setuptools from 75.2.0 to 75.3.0 (#5379)
Bumps [setuptools](https://github.com/pypa/setuptools) from 75.2.0 to 75.3.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v75.2.0...v75.3.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-30 10:47:46 -04:00
dependabot[bot]
93472ed6dd
Bump pytest-cov from 5.0.0 to 6.0.0 (#5378)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 5.0.0 to 6.0.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v5.0.0...v6.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-30 10:47:19 -04:00
dependabot[bot]
dcaf2653b8
Bump colorlog from 6.8.2 to 6.9.0 (#5377)
Bumps [colorlog](https://github.com/borntyping/python-colorlog) from 6.8.2 to 6.9.0.
- [Release notes](https://github.com/borntyping/python-colorlog/releases)
- [Commits](https://github.com/borntyping/python-colorlog/compare/v6.8.2...v6.9.0)

---
updated-dependencies:
- dependency-name: colorlog
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-30 10:46:47 -04:00
Wendelin
0714d7845a
Bump frontend 2024.10.29 (#5374)
* Bump frontend 2024.10

* Bump frontend 2024.10.29
2024-10-30 08:29:57 -04:00
dependabot[bot]
8f2269d871
Bump ruff from 0.7.0 to 0.7.1 (#5371)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-25 15:20:45 +02:00
dependabot[bot]
c7487e004d
Bump actions/setup-python from 5.2.0 to 5.3.0 (#5372)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-25 14:53:08 +02:00
dependabot[bot]
09d3edf526
Bump actions/checkout from 4.2.1 to 4.2.2 (#5370) 2024-10-24 08:19:46 +02:00
dependabot[bot]
9c99bf368f
Bump actions/cache from 4.1.1 to 4.1.2 (#5366)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 08:40:18 +02:00
Jan Čermák
6f196c9dea
Suppress ClientConnectionResetError when returning logs (#5358)
When client requests (or more often follows) some busy logs and closes
the connection while the StreamWriter tries to write into it, an
exception is raised. This should be harmless, and unless there's another
way to handle this gracefully (I'm not aware of), then it should be safe
to ignore the exception in this context.
2024-10-21 10:11:22 +02:00
dependabot[bot]
fcac17f335
Bump coverage from 7.6.3 to 7.6.4 (#5365)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 09:04:55 +02:00
dependabot[bot]
f5a026cdd8
Bump cryptography from 43.0.1 to 43.0.3 (#5364)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-21 09:02:50 +02:00
dependabot[bot]
c6488c1ee3
Bump ruff from 0.6.9 to 0.7.0 (#5359)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-18 08:41:51 +02:00
dependabot[bot]
f47d0d2867
Bump sentry-sdk from 2.16.0 to 2.17.0 (#5360)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-18 08:39:06 +02:00
dependabot[bot]
96df335b36
Bump setuptools from 75.1.0 to 75.2.0 (#5357)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-17 08:29:15 +02:00
Jan Čermák
cc9a931baa
Fix Supervisor log fallback for the /follow endpoint (#5354)
When an error occurs when streaming Supervisor logs, the fallback method
receives the follow kwarg as well, which is invalid for the Docker log
handler:

 TypeError: APISupervisor.logs() got an unexpected keyword argument 'follow'

The exception is still printed to the logs but with all the extra noise
caused by this error. Removing the argument makes the stack trace more
comprehensible and the fallback actually works as desired.
2024-10-16 09:04:24 +02:00
dependabot[bot]
95c638991d
Bump coverage from 7.6.2 to 7.6.3 (#5351) 2024-10-14 08:16:23 +02:00
Stefan Agner
e2ada42001
Fix log follow mode without range header (#5347) 2024-10-11 19:54:53 +02:00
dependabot[bot]
22e50b4ace
Bump aiohttp from 3.10.9 to 3.10.10 (#5345)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-11 10:31:09 +02:00
dependabot[bot]
334484de7f
Bump debugpy from 1.8.6 to 1.8.7 (#5346)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-11 10:12:26 +02:00
Stefan Agner
180a7c3990
Throttle connectivity check on connectivity issue (#5342)
* Throttle connectivity check on connectivity issue

If Supervisor detects a connectivity issue, currenlty every function
which requires internet get delayed by 10s due to the connectivity
check. This especially slows down initial startup when there are
connectivity issues. It is unlikely to resolve immeaditly, so throttle
the connectivity check to check every 30s.

* Fix pytest

* Reset throttle in test and refactor helper

* CodeRabbit suggestion

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2024-10-10 22:57:16 +02:00
dependabot[bot]
d5f33de808
Bump coverage from 7.6.1 to 7.6.2 (#5344)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.1 to 7.6.2.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.6.1...7.6.2)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-10 09:46:41 +02:00
dependabot[bot]
6539f0df6f
Bump actions/upload-artifact from 4.4.2 to 4.4.3 (#5343)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.2 to 4.4.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.4.2...v4.4.3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-10 09:46:18 +02:00
Stefan Agner
1504278223
Recreate aiohttp session on connectivity check (#5332)
It seems to actually get a proper connectivity check run, we need a new
vanilla ClientSession() object.
2024-10-09 21:41:46 +02:00
Jan Čermák
9f3767b23d
Return cursor of the first host logs entry via headers (#5333)
* Return cursor of the first host logs entry via headers

Return first entry's cursor via custom `X-First-Cursor` header that can
be consumed by the client and used for continual requesting of the
historic logs. Once the first fetch returns data, the cursor can be
supplied as the first argument to the Range header in another call,
fetching accurate slice of the journal with the previous log entries
using the `Range: entries=cursor[[:num_skip]:num_entries]` syntax.

Let's say we fetch logs with the Range header `entries=:-19:20` (to
fetch very last 20 lines of the logs, see below why not
`entries:-20:20`) and we get `cursor50` as the reply (the actual value
will be much more complex and with no guaranteed format). To fetch
previous slice of the logs, we use `entries=cursor50:-20:20`, which
would return 20 lines previous to `cursor50` and `cursor30` in the
cursor header. This way we can go all the way back to the history.

One problem with the cursor is that it's not possible to determine when
the negative num_skip points beyond the first log entry. In that case
the client either needs to know what the first entry is (via
`entries=:0:1`) or can iterate naively and stop once two subsequent
requests return the same first cursor.

Another caveat, even though it's unlikely it will be hit in real usage,
is that it's not possible to fetch the last line only - if no cursor is
provided, negative num_skip argument is needed, and in that case we're
pointing one record back from the current cursor, which is the previous
record. The least we can return without knowing any cursor is thus
`entries=👎2` (where the `2` can be omitted, however with
`entries=👎1` we would lose the last line). This also explains why
different `num_skip` and `num_entries` must be used for the first fetch.

* Fix typo (fallback->callback)

* Refactor journal_logs_reader to always return the cursor

* Update tests for new cursor handling
2024-10-09 20:27:29 +02:00
Jan Čermák
e0d7985369
Fix number of lines returned with host logs' query argument (#5334)
If no cursor is specified and negative num_skip is used, we're pointing
one record back from the last one, so host logs always returned 101
lines as the default. This was also the case of the lines query argument
that used the number directly as num_skip. Instead of doing that, point
N-1 records to the back and then get N records. Handle 1 record and
invalid numbers silently to avoid the need for error handling in
unpractical edge cases.
2024-10-09 20:27:18 +02:00
Stefan Agner
2968a5717c
Update DNS plug-in on network change (#5331)
* Update DNS plug-in on network change

Restart the DNS plug-in when the primary network changes network
changes. This makes sure any potential host OS DNS configuration
changes get picked up by the DNS plug-in as well.

* Add a test case

---------

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2024-10-09 20:16:36 +02:00
Matheson Steplock
e2b25fe7ce
Drop support for Debian 11 Bullseye (#5335) 2024-10-09 12:18:45 +02:00
dependabot[bot]
8601f5c49a
Bump sentry-sdk from 2.15.0 to 2.16.0 (#5338)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.15.0 to 2.16.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.15.0...2.16.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 11:19:47 +02:00
dependabot[bot]
42279461e0
Bump pre-commit from 4.0.0 to 4.0.1 (#5337)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 11:19:31 +02:00
dependabot[bot]
409447d6ca
Bump actions/cache from 4.1.0 to 4.1.1 (#5340)
Bumps [actions/cache](https://github.com/actions/cache) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 11:19:02 +02:00
dependabot[bot]
5b313db49d
Bump time-machine from 2.15.0 to 2.16.0 (#5336)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 09:27:57 +02:00
dependabot[bot]
d64618600d
Bump actions/upload-artifact from 4.4.1 to 4.4.2 (#5339)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-09 09:26:23 +02:00
dependabot[bot]
1ee01b1d5e
Bump actions/checkout from 4.2.0 to 4.2.1 (#5329)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-08 09:04:52 +02:00
dependabot[bot]
af590202c3
Bump actions/upload-artifact from 4.4.0 to 4.4.1 (#5330)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-08 09:04:36 +02:00
dependabot[bot]
12ca2fb624
Bump ruff from 0.6.8 to 0.6.9 (#5326)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 09:22:50 +02:00
dependabot[bot]
ea95f83742
Bump dbus-fast from 2.24.2 to 2.24.3 (#5328)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 09:18:12 +02:00
dependabot[bot]
e4d4da601c
Bump aiohttp from 3.10.8 to 3.10.9 (#5327)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 09:01:00 +02:00
dependabot[bot]
0582f6fd39
Bump pre-commit from 3.8.0 to 4.0.0 (#5325)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 08:45:43 +02:00
dependabot[bot]
f254af8326
Bump actions/cache from 4.0.2 to 4.1.0 (#5323)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 08:40:52 +02:00
dependabot[bot]
3333770246
Bump sigstore/cosign-installer from 3.6.0 to 3.7.0 (#5324)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-07 08:37:08 +02:00
Stefan Agner
ee5ded29ac
Allow Supervisor token authentication from landing page (#5321)
The landing page provides the Supervisor token as authentication, so
consider the landingpage as new enough too.
2024-10-03 18:17:13 +02:00
dependabot[bot]
f530db98ff
Bump cpe from 1.3.0 to 1.3.1 (#5320)
* Bump cpe from 1.3.0 to 1.3.1

Bumps [cpe](https://github.com/nilp0inter/cpe) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/nilp0inter/cpe/releases)
- [Changelog](https://github.com/nilp0inter/cpe/blob/main/NEWS.txt)
- [Commits](https://github.com/nilp0inter/cpe/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: cpe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Revert "Suppress SyntaxWarning from CPE until fixed (#5227)"

This reverts commit c95df56e8db545e1ebb8959164a341579ad8f8f8.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-10-03 18:08:19 +02:00
dependabot[bot]
911f9d661f
Bump sentry-sdk from 2.14.0 to 2.15.0 (#5319)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 09:55:24 +02:00
dependabot[bot]
9935eac146
Bump codecov/codecov-action from 4.5.0 to 4.6.0 (#5318)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 08:25:59 +02:00
Darren Griffin
eae2c9e221
Add OHF logo to README (#5316) 2024-09-30 18:42:08 +02:00
Paulus Schoutsen
1a67fe8a83
Exclude Text-to-Speech cache from backups (#5313) 2024-09-30 08:41:18 +02:00
J. Nick Koston
3af565267b
Bump aiohttp to 3.10.8 (#5314) 2024-09-30 08:40:31 +02:00
dependabot[bot]
d09460a971
Bump ruff from 0.6.7 to 0.6.8 (#5312)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.7 to 0.6.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.7...0.6.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-27 09:22:38 +02:00
dependabot[bot]
c65329442a
Bump actions/checkout from 4.1.7 to 4.2.0 (#5310)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.7...v4.2.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-26 09:13:30 +02:00
dependabot[bot]
48430dfa28
Bump pylint from 3.3.0 to 3.3.1 (#5311)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.3.0...v3.3.1)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-26 09:13:00 +02:00
dependabot[bot]
70e2de372d
Bump debugpy from 1.8.5 to 1.8.6 (#5309)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.5 to 1.8.6.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.8.5...v1.8.6)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 17:58:41 +02:00
dependabot[bot]
75784480ab
Bump pylint from 3.2.7 to 3.3.0 (#5306)
* Bump pylint from 3.2.7 to 3.3.0

Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.2.7 to 3.3.0.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.2.7...v3.3.0)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Set positional arguments limit to 10

This makes the current codebase pass with pylint 3.3.0 while still
warning in case many positional arguments are used.

* Move to design section

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-09-25 17:57:55 +02:00
J. Nick Koston
8a70ba841d
Bump aiohttp to 3.10.6 (#5308) 2024-09-24 22:28:00 +02:00
dependabot[bot]
77733829d7
Bump ruff from 0.6.6 to 0.6.7 (#5307)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-23 09:46:50 +02:00
dependabot[bot]
d4b67f1946
Bump ruff from 0.6.5 to 0.6.6 (#5305) 2024-09-20 09:40:55 +02:00
dependabot[bot]
51ab138bb1
Bump setuptools from 75.0.0 to 75.1.0 (#5303)
Bumps [setuptools](https://github.com/pypa/setuptools) from 75.0.0 to 75.1.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v75.0.0...v75.1.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 09:20:42 +02:00
dependabot[bot]
b81413c8b2
Bump ruff from 0.6.4 to 0.6.5 (#5301)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.4 to 0.6.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.4...0.6.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 10:52:19 +02:00
dependabot[bot]
2ec33c6ef3
Bump setuptools from 74.1.2 to 75.0.0 (#5302)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-16 08:57:28 +02:00
dependabot[bot]
68b2c38c7c
Bump urllib3 from 2.2.2 to 2.2.3 (#5299)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.2 to 2.2.3.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.2.2...2.2.3)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 10:50:19 +02:00
Stefan Agner
1ca22799d1
Improve WiFi settings error handling (#5293)
* Improve WiFi settings error handling

Currently, the frontend potentially provides no WiFi settings dictionary
but still tries to update other (IP address) settings on the interface.
This leads to a stack trace since network manager is not able to fetch
the WiFi settings from the settings dictionary. Simply fill out what
we can and let NetworkManager provide an error.

Also allow to disable a network interface which has no configuration.
This avoids an error when switching to auto and back to disabled then
press save on a new wireless network interface.

* Add debug message when already disabled

* Add pytest for incomplete WiFi settings as psoted by frontend

Simulate the frontend posting no WiFi settings. Make sure the Supervisor
handles this gracefully.
2024-09-11 17:53:36 +02:00
dependabot[bot]
549dddcb11
Bump pytest from 8.3.2 to 8.3.3 (#5297) 2024-09-11 09:19:44 +02:00
dependabot[bot]
131af90469
Bump sentry-sdk from 2.13.0 to 2.14.0 (#5296)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.13.0 to 2.14.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.13.0...2.14.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 12:55:35 +02:00
dependabot[bot]
c7c39da7c6
Bump ruff from 0.6.3 to 0.6.4 (#5294)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.3 to 0.6.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.3...0.6.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 09:09:51 +02:00
dependabot[bot]
8310c426f0
Bump dbus-fast from 2.24.0 to 2.24.2 (#5295)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.24.0 to 2.24.2.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.24.0...v2.24.2)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-09 09:09:39 +02:00
dependabot[bot]
bb8f91e39a
Bump orjson from 3.9.15 to 3.10.7 (#5238)
Bumps [orjson](https://github.com/ijl/orjson) from 3.9.15 to 3.10.7.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.9.15...3.10.7)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 10:42:45 +02:00
dependabot[bot]
a359b9a3d5
Bump actions/upload-artifact from 4.3.6 to 4.4.0 (#5284)
* Bump actions/upload-artifact from 4.3.6 to 4.4.0

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.6 to 4.4.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.6...v4.4.0)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Explicitly include hidden files

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-09-05 10:38:27 +02:00
dependabot[bot]
e130ebad1f
Bump setuptools from 74.0.0 to 74.1.2 (#5291)
Bumps [setuptools](https://github.com/pypa/setuptools) from 74.0.0 to 74.1.2.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v74.0.0...v74.1.2)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-05 09:19:37 +02:00
Stefan Agner
f5b996b66c
Make network API replace IP/WiFi settings (#5283)
* Allow to set user DNS through API with auto mode

Currently it is only possible to set DNS servers when in static mode.
However, there are use cases to set DNS servers when in auto mode as
well, e.g. if no local DNS server is provided by the DHCP, or the provided
DNS turns out to be non-working.

* Fix use separate data structure for IP configuration fallout

Make sure gateway is correctly converted to the internal IP
representation. Fix type info.

* Overwrite WiFi settings completely too

* Add test for DNS configuration

* Run ruff format

* ruff format

* Use schema validation as source for API defaults

Instead of using replace() simply set the API defaults in the API
schema.

* Revert "Use schema validation as source for API defaults"

This reverts commit 885506fd37395eb6cea9c787ee23349dac780b75.

* Use explicit dataclass initialization

This avoid the unnecessary replaces from before. It also makes it more
obvious that this part of the API doesn't patch existing settings.
2024-09-05 09:19:13 +02:00
Jan Čermák
05e0c7c3ab
Add "lines" and "verbose" query parameters for advanced logs (#5287)
Since headers are clumsy considering the Core proxy between the frontend
and Supervisor, add a way to adjust number of lines and verbose log
format using query parameters as well. If both query parameters and
headers are supplied, prefer the former, as it's more prominent when
reading through the request logs.
2024-09-04 16:11:37 +02:00
dependabot[bot]
6c1203e4bf
Bump cryptography from 43.0.0 to 43.0.1 (#5289)
Bumps [cryptography](https://github.com/pyca/cryptography) from 43.0.0 to 43.0.1.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/43.0.0...43.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-04 08:42:43 +02:00
dependabot[bot]
5fbcaa8edd
Bump pylint from 3.2.6 to 3.2.7 (#5285)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.2.6 to 3.2.7.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.2.6...v3.2.7)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-02 09:51:35 +02:00
Stefan Agner
00d217b5f7
Make IPv4 and IPv6 parse errors raise an API error (#5282)
* Make IPv4 and IPv6 parse errors raise an API error

Currently, IP address parsing errors lead to an execption which is not
handled by the `api_validate()` call. By using concrete IPv4 and IPv6
types and `vol.Coerce()` parsing errors are properly handled.

* ruff format

* ruff check
2024-08-30 18:20:20 +02:00
Stefan Agner
c0e35376f3
Improve connection settings tests (#5278)
* Improve connection settings fixture

Make the connection settings fixture behave more closely to the actual
NetworkManager. The behavior has been tested with NetworkManager 1.42.4
(Debian 12) and 1.44.2 (HAOS 13.1). This likely behaves similar in older
versions too.

* Introduce separate skeleton and settings for wireless

Instead of having a combined network settings object which has
Ethernet and Wirless settings, create a separate settings object for
wireless.

* Handle addresses/address-data property like NetworkManager

* Address ruff check

* Improve network API test

Add a test which changes from "static" to "auto". Validate that settings
are updated accordingly. Specifically, today this does clear the DNS
setting (by not providing the property).

* ruff format

* ruff check

* Complete TEST_INTERFACE rename

* Add partial network update as test case
2024-08-30 16:07:04 +02:00
Mike Degatano
2be84e1282
Keep shared images on update (#5268)
* Test stub for keeping shared images after update

* Keep shared images on addon update

* ImageNotFound should only skip the one image not all

* Fix tests and nonetype error

* Normalize logic between two cleanup methods
2024-08-30 15:29:13 +02:00
Jan Čermák
08f10c96ef
Persist currently selected slot on successful boot (#5276)
When boot slot is selected manually in GRUB, the system boots into this
slot and marks it as good. However, the boot order is not changed, so in
the next boot (after an explicit or unexpected reboot) HAOS returns to
the version in the other slot. This might be confusing because if the
system has been running for some time, the user can forget they have
changed the boot slot to fix issue they had.

This gets more confusing if the "other" boot slot is selected manually
three times in a row. Let's say we have ORDER="A B". This means that
every time GRUB starts, it wants to boot slot A. If the slot B is
selected instead, only A_TRY is incremented, system boots into slot B
and marks slot B as good (B_OK=1, B_TRY=0). On another boot, this
repeats, yet A_TRY is incremented again. Until it reaches 3, the slot A
would be always chosen automatically, only after that it would boot to
slot B, presuming slot A is dead. The ORDER variable will be still
unchanged though.

This commit only makes sure that when the system is marked as healthy,
the slot is both marked as good AND active, updating the ORDER variable
as well. Because the X_TRY counter is incremented by GRUB, if we want
the other slot not to be marked as bad, we need to adjust the logic in
OS's grub.cfg as well, because Supervisor can't know whether it's
apppropriate to change other slot's state or not.

I also took the courtesy to adjust the logging a bit, to include the
stack trace in the error log if marking the slot fails somehow.
2024-08-30 15:18:44 +02:00
dependabot[bot]
12f8ccdf02
Bump ruff from 0.6.2 to 0.6.3 (#5280)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.2 to 0.6.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.2...0.6.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 10:13:08 +02:00
dependabot[bot]
d63e78cf34
Bump deepmerge from 1.1.1 to 2.0 (#5279)
Bumps [deepmerge](https://github.com/toumorokoshi/deepmerge) from 1.1.1 to 2.0.
- [Release notes](https://github.com/toumorokoshi/deepmerge/releases)
- [Commits](https://github.com/toumorokoshi/deepmerge/compare/v1.1.1...v2.0)

---
updated-dependencies:
- dependency-name: deepmerge
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 10:12:50 +02:00
dependabot[bot]
65d97ca924
Bump actions/setup-python from 5.1.1 to 5.2.0 (#5281)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.1.1 to 5.2.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.1.1...v5.2.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-30 10:11:57 +02:00
dependabot[bot]
5770cafea9
Bump setuptools from 73.0.1 to 74.0.0 (#5277)
Bumps [setuptools](https://github.com/pypa/setuptools) from 73.0.1 to 74.0.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v73.0.1...v74.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 09:32:19 +02:00
Mike Degatano
0177cd9528
Add manual_only option to addon boot config (#5272)
* Add manual_forced option to addon boot config

* Include client library in pull request template

* Add boot_config to api output so frontend can use it

* `manual_forced` to `manual_only`
2024-08-27 17:59:52 +02:00
dependabot[bot]
91a8fae9b5
Bump dbus-fast from 2.23.0 to 2.24.0 (#5274)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.23.0 to 2.24.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.23.0...v2.24.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 08:49:24 +02:00
dependabot[bot]
f16a4ce3ef
Bump pulsectl from 24.4.0 to 24.8.0 (#5273)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 24.4.0 to 24.8.0.
- [Changelog](https://github.com/mk-fg/python-pulse-control/blob/master/CHANGES.rst)
- [Commits](https://github.com/mk-fg/python-pulse-control/commits)

---
updated-dependencies:
- dependency-name: pulsectl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 08:49:11 +02:00
dependabot[bot]
306f63c75b
Bump ruff from 0.6.1 to 0.6.2 (#5269) 2024-08-24 06:54:34 +02:00
Stefan Agner
2a0312318d
Use single quotes in f-strings (#5267)
Instead of using double quotes in f-strings use single quotes. This
works with Python 3.11 too. We don't use Python 3.11 anymore, but is
useful when running pytest on Debian bookworm natively, which comes
with Python 3.11.
2024-08-23 16:16:08 +02:00
Stefan Agner
695a23a454
Minimize D-Bus requirements for tests (#5265)
This PR minimizes the D-Bus requirements for tests. It does this by
using dbus-daemon directly instead of dbus-launch. The latter is meant
for graphical applications and therefor has X11 dependencies. It also
leaves the D-Bus daemon running after the tests are done. This will
accumulate dbus-daemon processes over time which is not ideal.

I've also considered using dbus-run-session since it is meant to launch
processes with a private D-Bus session. For Python tests one could
launch it like so:
dbus-run-session -- python3 -m pytest ...

Then `DBUS_SESSION_BUS_ADDRESS` would be used automatically by the
`MessageBus` class. However, to keep the current behavior of the tests,
launching the D-Bus daemon manually is the better option.
2024-08-22 19:04:34 +02:00
dependabot[bot]
7366673eea
Bump sentry-sdk from 2.10.0 to 2.13.0 (#5246)
* Bump sentry-sdk from 2.10.0 to 2.13.0

Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.10.0 to 2.13.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.10.0...2.13.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Replace deprecated apis with new ones

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2024-08-22 10:04:32 +02:00
dependabot[bot]
53fa0fe215
Bump dbus-fast from 2.22.1 to 2.23.0 (#5264)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.22.1 to 2.23.0.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.22.1...v2.23.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-22 10:00:50 +02:00
Stefan Agner
1ba621be60
Use separate data structure for IP configuration (#5262)
* Use separate data structure for IP configuration

So far we use the same IpConfig data structure to represent the users
IP setting and the currently applied IP configuration.

This commit separates the two in IpConfig (for the currently applied
IP configuration) and IpSetting (representing the user provided IP
setting).

* Use custom string constants for connection settings

Use separate string constants for all connection settings. This makes
it easier to search where a particular NetworkManager connection
setting is used.

* Use Python typing for IpAddress in IpProperties

* Address pytest issue
2024-08-22 08:08:55 +02:00
Stefan Agner
5117364625
Bump cosign to v2.4.0 (#5263)
Follow the builder bump of 2024.08.2 and use cosign v2.4.0 for
Supervisor too.
2024-08-21 14:30:12 -04:00
Mike Degatano
986b92aee4
Keep shared images on addon uninstall (#5259)
* Keep shared images on addon uninstall

* Add missing step for mocking new addon in store
2024-08-21 11:14:57 +02:00
dependabot[bot]
12d26b05af
Bump setuptools from 73.0.0 to 73.0.1 (#5261)
Bumps [setuptools](https://github.com/pypa/setuptools) from 73.0.0 to 73.0.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v73.0.0...v73.0.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 09:50:02 +02:00
dependabot[bot]
e6c9704505
Bump home-assistant/builder from 2024.08.1 to 2024.08.2 (#5260)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2024.08.1 to 2024.08.2.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2024.08.1...2024.08.2)

---
updated-dependencies:
- dependency-name: home-assistant/builder
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 09:38:59 +02:00
Stefan Agner
8ab396d77c
Improve and extend error handling on D-Bus connect (#5245)
* Improve and extend error handling on D-Bus connect

Avoid initializing the Supervisor board since it does not support the
Properties interface (see https://github.com/home-assistant/os-agent/issues/206).

This prevents the following somewhat confusing warning:
  No OS-Agent support on the host. Some Host functions have been disabled.

The OS Agent is actually installed on the host, it is just a single
object which caused issues. No functionalty was actually lost, as the
Supervisor board object has no features currently, and all other
interfaces got properly initialized still (thanks to gather()).

Print warnings more fine graned so it is clear which object exactly
causes an issue. Also print a log message on the lowest layer when an
error occures on calling D-Bus. This allows to easier track the actual
D-Bus error source.

Fixes: #5241

* Fix tests

* Use local variable

* Avoid stack trace when board support fails to load

* Fix tests

* Use override mechanism to disable Properties support

Instead of disable loading of Supervised entirly override initialization
to prevent loading the Properties interface.

* Revert "Fix tests"

This reverts commit 1e3c491ace2ebef60945c45573acd8d4464ea83e.
2024-08-20 17:55:53 +02:00
dependabot[bot]
8438448843
Bump aiohttp from 3.10.4 to 3.10.5 (#5255)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.10.4 to 3.10.5.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.10.4...v3.10.5)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-20 11:23:27 +02:00
dependabot[bot]
362edb9a61
Bump setuptools from 72.2.0 to 73.0.0 (#5256)
Bumps [setuptools](https://github.com/pypa/setuptools) from 72.2.0 to 73.0.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v72.2.0...v73.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-20 11:22:42 +02:00
dependabot[bot]
1ff53e1853
Bump ruff from 0.6.0 to 0.6.1 (#5254)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.0 to 0.6.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.0...0.6.1)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-19 14:02:32 +02:00
dependabot[bot]
cfd28dbb5c
Bump aiohttp from 3.10.3 to 3.10.4 (#5253)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.10.3 to 3.10.4.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.10.3...v3.10.4)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-19 13:38:08 +02:00
dependabot[bot]
cbec558289
Bump ruff from 0.5.7 to 0.6.0 (#5252)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.5.7 to 0.6.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.7...0.6.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-16 08:40:24 +02:00
dependabot[bot]
ca3a2937d0
Bump home-assistant/builder from 2024.03.5 to 2024.08.1 (#5250)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-15 09:31:33 +02:00
dependabot[bot]
3e67fc12c5
Bump setuptools from 72.1.0 to 72.2.0 (#5247)
Bumps [setuptools](https://github.com/pypa/setuptools) from 72.1.0 to 72.2.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v72.1.0...v72.2.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-14 11:01:30 +02:00
Stefan Agner
f6faa18409
Bump pre-commit ruff to 0.5.7 and reformat (#5242)
It seems that the codebase is not formatted with the latest ruff
version. This PR reformats the codebase with ruff 0.5.7.
2024-08-13 20:53:56 +02:00
dependabot[bot]
21ae2c2e54
Bump cpe from 1.2.1 to 1.3.0 (#5243)
Bumps [cpe](https://github.com/nilp0inter/cpe) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/nilp0inter/cpe/releases)
- [Changelog](https://github.com/nilp0inter/cpe/blob/develop/NEWS.txt)
- [Commits](https://github.com/nilp0inter/cpe/compare/v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: cpe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-13 16:09:20 +02:00
Mike Degatano
eb3986bea2
Allow core to mark addons as system managed (#5145)
* Allow core to mark addons as system managed

* System managed options only settable by Home Assistant
2024-08-13 15:14:42 +02:00
dependabot[bot]
5d6738ced8
Bump aiohttp from 3.10.2 to 3.10.3 (#5240)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-12 09:05:42 +02:00
dependabot[bot]
2f2fecddf2
Bump pyyaml from 6.0.1 to 6.0.2 (#5230)
Bumps [pyyaml](https://github.com/yaml/pyyaml) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/main/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/6.0.1...6.0.2)

---
updated-dependencies:
- dependency-name: pyyaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-09 12:15:48 +02:00
dependabot[bot]
218ba3601e
Bump orjson from 3.9.15 to 3.10.6 (#5169)
Bumps [orjson](https://github.com/ijl/orjson) from 3.9.15 to 3.10.6.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.9.15...3.10.6)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-09 11:12:27 +02:00
J. Nick Koston
4c3f60c44b
Bump aiohttp to 3.10.2, drop aiohttp-fast-url-dispatcher (#5236)
aiohttp-fast-url-dispatcher is not needed for 3.10.x

changelog: https://github.com/aio-libs/aiohttp/compare/v3.9.5...v3.10.2
2024-08-09 10:44:29 +02:00
dependabot[bot]
cb85e5e464
Bump ruff from 0.5.6 to 0.5.7 (#5237)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.5.6 to 0.5.7.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.6...0.5.7)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-09 10:41:30 +02:00
dependabot[bot]
5b46235872
Bump time-machine from 2.14.2 to 2.15.0 (#5229)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 09:05:56 +02:00
dependabot[bot]
70f675ac82
Bump sigstore/cosign-installer from 3.5.0 to 3.6.0 (#5234)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-08 08:53:54 +02:00
dependabot[bot]
bf0c714ea4
Bump attrs from 24.1.0 to 24.2.0 (#5231)
Bumps [attrs](https://github.com/sponsors/hynek) from 24.1.0 to 24.2.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: attrs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-07 15:38:43 +02:00
Mike Degatano
c95df56e8d
Suppress SyntaxWarning from CPE until fixed (#5227) 2024-08-07 15:37:30 +02:00
dependabot[bot]
5f3d851954
Bump actions/upload-artifact from 4.3.5 to 4.3.6 (#5232)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-07 09:05:38 +02:00
dependabot[bot]
10c69dcdae
Bump ruff from 0.5.5 to 0.5.6 (#5221)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.5.5 to 0.5.6.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.5...0.5.6)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-06 09:10:52 +02:00
dependabot[bot]
bdd81ce3a9
Bump debugpy from 1.8.2 to 1.8.5 (#5225)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.2 to 1.8.5.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.8.2...v1.8.5)

---
updated-dependencies:
- dependency-name: debugpy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-06 08:38:52 +02:00
Mike Degatano
17ee234be4
Fix resp may be undefined end_backup issue (#5224) 2024-08-05 17:02:11 +02:00
dependabot[bot]
61034dfa7b
Bump attrs from 23.2.0 to 24.1.0 (#5219)
Bumps [attrs](https://github.com/sponsors/hynek) from 23.2.0 to 24.1.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: attrs
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 09:41:21 +02:00
dependabot[bot]
185cd362fb
Bump coverage from 7.6.0 to 7.6.1 (#5222)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.0 to 7.6.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.6.0...7.6.1)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 09:38:06 +02:00
dependabot[bot]
e2ca357774
Bump dirhash from 0.4.1 to 0.5.0 (#5223)
Bumps [dirhash](https://github.com/andhus/dirhash-python) from 0.4.1 to 0.5.0.
- [Release notes](https://github.com/andhus/dirhash-python/releases)
- [Changelog](https://github.com/andhus/dirhash-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/andhus/dirhash-python/compare/v0.4.1...v0.5.0)

---
updated-dependencies:
- dependency-name: dirhash
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-05 09:37:40 +02:00
dependabot[bot]
3dea7fc4e8
Bump actions/upload-artifact from 4.3.4 to 4.3.5 (#5217) 2024-08-05 08:36:00 +02:00
dependabot[bot]
01ba591bc9
Bump setuptools from 72.0.0 to 72.1.0 (#5212)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-30 10:12:58 +02:00
dependabot[bot]
640b7d46e3
Bump ruff from 0.5.4 to 0.5.5 (#5208)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 12:01:43 +02:00
dependabot[bot]
d6560c51ee
Bump pre-commit from 3.7.1 to 3.8.0 (#5210)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 11:39:50 +02:00
dependabot[bot]
3e9b1938c6
Bump pytest from 8.3.1 to 8.3.2 (#5207)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.1 to 8.3.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.1...8.3.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 11:26:14 +02:00
dependabot[bot]
44ce8de71f
Bump setuptools from 71.1.0 to 72.0.0 (#5211)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-29 11:08:13 +02:00
Mike Degatano
0bbd15bfda
Restrict stopping core during migrations with force option (#5205) 2024-07-25 17:14:45 +02:00
Mike Degatano
591b9a4d87
Stop backup if pre backup failed in Core (#5203)
* Stop backup if pre backup failed in Core

* Fix API tests

* Partial backup in ci since there's no Home assistant

* Add ssl folder to partial backup

* Allow backups when Home Assistant is not running

* Undo change to skip db test
2024-07-25 17:08:43 +02:00
Mike Degatano
5ee7d16687
Add hard-coded image fallback for plugins for offline start (#5204) 2024-07-25 13:45:38 +02:00
Erik Montnemery
4ab4350c58
Add support for offline DB migration (#5202)
* Add support for offline DB migration

* Format code
2024-07-23 15:27:16 -04:00
dependabot[bot]
4ea7133fa8
Bump docker/login-action from 3.2.0 to 3.3.0 (#5201)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 09:22:20 +02:00
dependabot[bot]
627d67f9d0
Bump cryptography from 42.0.8 to 43.0.0 (#5199)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 11:59:07 +02:00
dependabot[bot]
eb37655598
Bump pylint from 3.2.5 to 3.2.6 (#5198)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.2.5 to 3.2.6.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.2.5...v3.2.6)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:07:15 +02:00
dependabot[bot]
19b62dd0d4
Bump pytest from 8.2.2 to 8.3.1 (#5197)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:04:13 +02:00
dependabot[bot]
b2ad1ceea3
Bump sentry-sdk from 2.9.0 to 2.10.0 (#5188)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 10:03:25 +02:00
dependabot[bot]
c1545b5b78
Bump ruff from 0.5.3 to 0.5.4 (#5196)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.5.3 to 0.5.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.5.3...0.5.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 09:45:47 +02:00
dependabot[bot]
2c2f04ba85
Bump setuptools from 71.0.3 to 71.1.0 (#5200)
Bumps [setuptools](https://github.com/pypa/setuptools) from 71.0.3 to 71.1.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v71.0.3...v71.1.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-22 09:45:31 +02:00
Andrew Leech
77e7bf51b7
Only read wifi strength from active connections. (#5184) 2024-07-19 12:36:25 +02:00
Mike Degatano
a42d71dcef
Small cleanup to pyproject.toml (#5191) 2024-07-19 09:09:13 +02:00
dependabot[bot]
1ff0432f4d
Bump ruff from 0.5.2 to 0.5.3 (#5192)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-19 09:07:06 +02:00
dependabot[bot]
54afd6e1c8
Bump setuptools from 71.0.1 to 71.0.3 (#5193)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-19 09:06:43 +02:00
dependabot[bot]
458c493a74
Bump ruff from 0.5.1 to 0.5.2 (#5186)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-18 08:52:23 +02:00
dependabot[bot]
8ac8ecb17e
Bump setuptools from 70.3.0 to 71.0.1 (#5190)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-18 08:51:36 +02:00
Mike Degatano
eac167067e
Ignore false positive no-member error (#5189) 2024-07-18 08:43:59 +02:00
Mike Degatano
aa7f4aafeb
Migrate supervisor devcontainer from pip to uv (#5170) 2024-07-12 10:26:45 +02:00
dependabot[bot]
d2183fa12b
Bump coverage from 7.5.4 to 7.6.0 (#5185)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.5.4 to 7.6.0.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.5.4...7.6.0)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-12 10:25:20 +02:00
dependabot[bot]
928f32bb4f
Bump sentry-sdk from 2.8.0 to 2.9.0 (#5183)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-11 08:57:33 +02:00
dependabot[bot]
cbe21303c4
Bump actions/setup-python from 5.1.0 to 5.1.1 (#5182)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.1.0...v5.1.1)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-11 08:17:35 +02:00
dependabot[bot]
94987c04b8
Bump setuptools from 70.2.0 to 70.3.0 (#5181)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-10 08:37:23 +02:00
dependabot[bot]
d4ba46a846
Bump home-assistant/wheels from 2024.01.0 to 2024.07.1 (#5178)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 08:29:09 +02:00
dependabot[bot]
1a22d83895
Bump sentry-sdk from 2.7.1 to 2.8.0 (#5179)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 08:27:46 +02:00
dependabot[bot]
6b73bf5c28
Bump aiohttp-fast-url-dispatcher from 0.3.0 to 0.3.1 (#5175) 2024-07-08 08:41:48 +02:00
dependabot[bot]
c9c9451c36
Bump ruff from 0.5.0 to 0.5.1 (#5176) 2024-07-08 08:39:34 +02:00
dependabot[bot]
1882d448ea
Bump actions/download-artifact from 4.1.7 to 4.1.8 (#5174) 2024-07-08 08:35:57 +02:00
dependabot[bot]
2f11c9c9e3
Bump actions/upload-artifact from 4.3.3 to 4.3.4 (#5173) 2024-07-08 08:34:07 +02:00
Mike Degatano
02bdc4b555
Use uv instead of pip in Supervisor (#5152)
* Migrate supervisor image from pip to uv

* Set python paths

* Put in i386 conditional to match core

* Semicolons within if statements
2024-07-03 11:51:16 -04:00
dependabot[bot]
1a1ee50d9d
Bump voluptuous from 0.15.1 to 0.15.2 (#5168)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-03 09:57:11 +02:00
dependabot[bot]
50dc09d1a9
Bump setuptools from 70.1.1 to 70.2.0 (#5167)
Bumps [setuptools](https://github.com/pypa/setuptools) from 70.1.1 to 70.2.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v70.1.1...v70.2.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:29:38 +02:00
dependabot[bot]
130efd340c
Bump time-machine from 2.14.1 to 2.14.2 (#5165)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 08:47:00 +02:00
dependabot[bot]
00bc13c049
Bump pylint from 3.2.4 to 3.2.5 (#5166)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 08:43:39 +02:00
dependabot[bot]
3caad67f61
Bump sentry-sdk from 2.7.0 to 2.7.1 (#5164)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-30 15:27:42 +02:00
dependabot[bot]
13783f0d4a
Bump ruff from 0.4.10 to 0.5.0 (#5163)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-28 08:39:34 +02:00
dependabot[bot]
eae97ba3f4
Bump pylint from 3.2.3 to 3.2.4 (#5160)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.2.3...v3.2.4)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 09:05:11 +02:00
dependabot[bot]
134dad7357
Bump sentry-sdk from 2.6.0 to 2.7.0 (#5161)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.6.0 to 2.7.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.6.0...2.7.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 09:04:42 +02:00
dependabot[bot]
1c4d2e8dec
Bump voluptuous from 0.15.0 to 0.15.1 (#5162)
Bumps [voluptuous](https://github.com/alecthomas/voluptuous) from 0.15.0 to 0.15.1.
- [Release notes](https://github.com/alecthomas/voluptuous/releases)
- [Changelog](https://github.com/alecthomas/voluptuous/blob/master/CHANGELOG.md)
- [Commits](https://github.com/alecthomas/voluptuous/compare/0.15.0...0.15.1)

---
updated-dependencies:
- dependency-name: voluptuous
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-27 08:48:44 +02:00
dependabot[bot]
f2d7be3aac
Bump dbus-fast from 2.21.3 to 2.22.1 (#5159)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 09:26:21 +02:00
dependabot[bot]
d06edb2dd6
Bump debugpy from 1.8.1 to 1.8.2 (#5158)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:50:33 +02:00
dependabot[bot]
7fa15b334a
Bump setuptools from 70.1.0 to 70.1.1 (#5156)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 08:35:34 +02:00
Mike Degatano
ffb4e2d6d7
Bump Supervisor to Alpine 3.20 (#5151) 2024-06-25 08:37:10 +02:00
dependabot[bot]
bd8047ae9c
Bump awesomeversion from 24.2.0 to 24.6.0 (#5153)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 08:25:24 +02:00
Mike Degatano
49bc0624af
Ignore dns-data field in network settings update (#5147) 2024-06-24 15:47:58 -04:00
dependabot[bot]
5e1d764eb3
Bump coverage from 7.5.3 to 7.5.4 (#5150)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-24 08:41:30 +02:00
dependabot[bot]
0064d93d75
Bump dirhash from 0.4.0 to 0.4.1 (#5149)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-24 08:40:15 +02:00
dependabot[bot]
5a838ecfe7
Bump voluptuous from 0.14.2 to 0.15.0 (#5148)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-24 08:36:04 +02:00
Pascal Vizeli
c37b5effd7
Add music assistant to the builtin repositories (#5128)
* Add music assistant to the builtin repositories

* Fix tests

* Fix tests some more

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-06-21 12:17:21 +02:00
dependabot[bot]
ca7f3e8acb
Bump ruff from 0.4.9 to 0.4.10 (#5143)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-21 09:27:10 +02:00
Stefan Agner
b0cdb91d5e
Fix uninstall of add-on on fixup (#5142) 2024-06-21 08:54:46 +02:00
Mike Degatano
4829eb8ae1
Await uninstall of addon in fixup (#5141) 2024-06-20 21:50:45 +02:00
Mike Degatano
1bb814b793
Home Assistant watchdog attempts safe mode after max fails (#5124)
* Home Assistant watchdog attempts safe mode after max fails

* Remove duplicate line

* Refactor and logging change from feedback

* Update supervisor/misc/tasks.py

* Fix log text check in test

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-06-20 21:50:29 +02:00
dependabot[bot]
918fcb7d62
Bump sentry-sdk from 2.5.1 to 2.6.0 (#5140)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-20 11:39:26 +02:00
dependabot[bot]
bbfd899564
Bump setuptools from 70.0.0 to 70.1.0 (#5139)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-20 09:11:45 +02:00
dependabot[bot]
12c4d9da87
Bump urllib3 from 2.2.1 to 2.2.2 (#5138)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-18 07:52:04 +02:00
dependabot[bot]
6b4fd9b6b8
Bump ruff from 0.4.8 to 0.4.9 (#5137)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.8 to 0.4.9.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.4.8...v0.4.9)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-17 09:05:58 +02:00
dependabot[bot]
07c22f4a60
Bump codecov/codecov-action from 4.4.1 to 4.5.0 (#5136)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-14 09:27:41 +02:00
dependabot[bot]
252e1e2ac0
Bump actions/checkout from 4.1.6 to 4.1.7 (#5134)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.6...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-13 09:17:05 +02:00
dependabot[bot]
b684c8673e
Bump sentry-sdk from 2.5.0 to 2.5.1 (#5130)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.5.0 to 2.5.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.5.0...2.5.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 09:01:06 +02:00
dependabot[bot]
547f42439d
Bump typing-extensions from 4.12.1 to 4.12.2 (#5129)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-10 08:49:42 +02:00
dependabot[bot]
c51ceb000f
Bump sentry-sdk from 2.4.0 to 2.5.0 (#5126)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 09:19:18 +02:00
dependabot[bot]
4cbede1bc8
Bump pylint from 3.2.2 to 3.2.3 (#5127)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 09:01:27 +02:00
dependabot[bot]
5eac8c7780
Bump ruff from 0.4.7 to 0.4.8 (#5125)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.7 to 0.4.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.4.7...v0.4.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-06 08:37:25 +02:00
Mike Degatano
ab78d87304
Add safe mode option to core rebuild (#5120)
* Add safe mode option to core rebuild

* Adding logging for increased traceability
2024-06-05 15:44:07 -04:00
dependabot[bot]
09166e3867
Bump cryptography from 42.0.7 to 42.0.8 (#5121)
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.7 to 42.0.8.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.7...42.0.8)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-05 15:38:13 -04:00
dependabot[bot]
8a5c813cdd
Bump sentry-sdk from 2.3.1 to 2.4.0 (#5123)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.3.1 to 2.4.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.3.1...2.4.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-05 15:37:41 -04:00
dependabot[bot]
4200622f43
Bump pytest from 8.2.1 to 8.2.2 (#5122)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-05 08:43:01 +02:00
Mike Degatano
c4452a85b4
Fix addon in wrong state after restore (#5111)
* Fix addon in wrong state after restore

* Do not stop docker monitor for a shutdown
2024-06-04 16:17:43 +02:00
Mike Degatano
e57de4a3c1
Add uninstall addon suggestion to detached_addon_removed (#5105) 2024-06-03 10:38:34 -04:00
dependabot[bot]
9fd2c91c55
Bump ruff from 0.4.6 to 0.4.7 (#5116)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 10:29:23 +02:00
dependabot[bot]
fbd70013a8
Bump typing-extensions from 4.12.0 to 4.12.1 (#5117)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 09:54:10 +02:00
dependabot[bot]
8d18f3e66e
Bump requests from 2.32.2 to 2.32.3 (#5115)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-30 08:52:20 +02:00
Richard P
5f5754e860
Add Exception handling when processing udev devices (#5088)
* Add Exception handling to UDEV reading and parsing

Khadas VIM4 UDEV returns something that python crapps its pants about. The exception just allows it to continue.

* Add an exception print

Added an exception print for the times things go bad.

* Split exception handling

The exception is not fatal when parsing error happens on one node. print it and continue.

* cleanups

* swapped functions

device.device_node   function bails very badly!  It raises no exceptions to the top but complains and errors

* Update supervisor/hardware/manager.py

Co-authored-by: Stefan Agner <stefan@agner.ch>

* Update supervisor/hardware/manager.py

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2024-05-29 15:33:15 -04:00
dependabot[bot]
974c882b9a
Bump docker/login-action from 3.1.0 to 3.2.0 (#5114)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-29 08:50:25 +02:00
dependabot[bot]
a9ea90096b
Bump ruff from 0.4.5 to 0.4.6 (#5113)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-29 08:26:23 +02:00
dependabot[bot]
45c72c426e
Bump coverage from 7.5.2 to 7.5.3 (#5112)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-29 08:26:10 +02:00
dependabot[bot]
4e5b75fe19
Bump coverage from 7.5.1 to 7.5.2 (#5109)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 08:37:29 +02:00
dependabot[bot]
3cd617e68f
--- (#5099)
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 09:33:15 +02:00
dependabot[bot]
ddff02f73b
Bump docker from 7.0.0 to 7.1.0 (#5106)
Bumps [docker](https://github.com/docker/docker-py) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/7.0.0...7.1.0)

---
updated-dependencies:
- dependency-name: docker
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 08:52:21 +02:00
dependabot[bot]
b59347b3d3
Bump typing-extensions from 4.11.0 to 4.12.0 (#5107)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 08:32:48 +02:00
dependabot[bot]
1dc769076f
Bump sentry-sdk from 2.2.1 to 2.3.1 (#5108)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 08:25:53 +02:00
Mike Degatano
f150a19c0f
Create issue for detached addons (#5084)
* Create issue for detached addons

* Separate issues into missing and removed
2024-05-23 09:36:59 +02:00
dependabot[bot]
c4bc1e3824
Bump ruff from 0.4.4 to 0.4.5 (#5103)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-23 08:33:52 +02:00
Mike Degatano
eca99b69db
Max retries for auto applying addon image fixup (#5051)
* Max retries for auto applying addon image fixup

* Update supervisor/resolution/fixups/addon_execute_repair.py

Co-authored-by: Stefan Agner <stefan@agner.ch>

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-05-22 11:54:02 +02:00
dependabot[bot]
043af72847
Bump setuptools from 69.5.1 to 70.0.0 (#5100)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-22 09:33:26 +02:00
dependabot[bot]
05c7b6c639
Bump sentry-sdk from 2.2.0 to 2.2.1 (#5101)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-22 08:16:31 +02:00
dependabot[bot]
3385c99f1f
--- (#5095)
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 17:06:19 +02:00
dependabot[bot]
895117f857
--- (#5094)
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 17:05:23 +02:00
dependabot[bot]
9e3135e2de
--- (#5093)
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 17:05:00 +02:00
Stefan Agner
9a1c517437
Pin Python requets package (#5097)
Make sure Python requests package is pinned to a known version. This is
required by docker-py for instance. This fixes current CI builds.
2024-05-21 14:52:24 +02:00
Mike Degatano
c0c0c4b7ad
Fix doc and changelog API response for orphaned addons (#5082)
* Fix doc and changelog API response for orphaned addons

* Use correct terminology in tests
2024-05-21 09:02:01 +02:00
dependabot[bot]
be6e39fed0
Bump pylint from 3.1.1 to 3.2.1 (#5090)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-20 09:30:42 +02:00
dependabot[bot]
b384921ee0
Bump pytest from 8.2.0 to 8.2.1 (#5089)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-20 09:29:26 +02:00
dependabot[bot]
0d05a6eae3
Bump sentry-sdk from 2.1.1 to 2.2.0 (#5085)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-17 15:19:01 +02:00
dependabot[bot]
430aef68c6
Bump actions/checkout from 4.1.5 to 4.1.6 (#5086)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-17 10:40:37 +02:00
Stefan Agner
eac6070e12
Don't process hardware events when landing page is running (#5079) 2024-05-15 08:56:37 +02:00
dependabot[bot]
6693b7c2e6
Bump codecov/codecov-action from 4.3.1 to 4.4.0 (#5080)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-15 08:49:07 +02:00
dependabot[bot]
7898c3e433
Bump pylint from 3.1.0 to 3.1.1 (#5078)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 10:11:19 +02:00
dependabot[bot]
420ecd064e
Bump pyudev from 0.24.1 to 0.24.3 (#5074)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 09:29:49 +02:00
dependabot[bot]
4289be53f8
Bump pre-commit from 3.7.0 to 3.7.1 (#5075)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-13 09:14:14 +02:00
dependabot[bot]
29b41b564e
Bump ruff from 0.4.3 to 0.4.4 (#5072)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.4.3...v0.4.4)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-10 12:48:18 +02:00
dependabot[bot]
998eb69583
Bump dbus-fast from 2.21.1 to 2.21.2 (#5071)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.21.1 to 2.21.2.
- [Release notes](https://github.com/bluetooth-devices/dbus-fast/releases)
- [Changelog](https://github.com/Bluetooth-Devices/dbus-fast/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bluetooth-devices/dbus-fast/compare/v2.21.1...v2.21.2)

---
updated-dependencies:
- dependency-name: dbus-fast
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-10 12:48:09 +02:00
Stefan Agner
8ebc097ff4
Revert "Bump orjson from 3.9.15 to 3.10.3 (#5057)" (#5068)
This reverts commit 71e91328f1c225d774ba9492e133147470427744.

It is not proven that the segfaults seen in Core are resolved. Since
we are shipping a bugfix release, conservatively revert back to 3.9.15.
2024-05-07 16:02:34 +02:00
Mike Degatano
c05984ca49
Fix no changelog API response (#5064)
* Fix no changelog API response

* Add comment reasoning HTTP 200 for no changelog

Co-authored-by: Stefan Agner <stefan@agner.ch>

* Apply suggestions from code review

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>

---------

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-05-07 10:41:16 +02:00
dependabot[bot]
1a700c3013
Bump sentry-sdk from 2.0.1 to 2.1.1 (#5067)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.0.1 to 2.1.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.0.1...2.1.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 10:17:12 +02:00
dependabot[bot]
a9c92cdec8
Bump cryptography from 42.0.6 to 42.0.7 (#5066)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 09:23:56 +02:00
dependabot[bot]
da8b938d5b
Bump actions/checkout from 4.1.4 to 4.1.5 (#5065) 2024-05-07 08:26:00 +02:00
dependabot[bot]
71e91328f1
Bump orjson from 3.9.15 to 3.10.3 (#5057)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 22:46:12 +02:00
dependabot[bot]
6356be4c52
Bump jinja2 from 3.1.3 to 3.1.4 (#5061)
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.3...3.1.4)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 11:14:01 +02:00
dependabot[bot]
e26e5440b6
Bump ruff from 0.4.2 to 0.4.3 (#5060)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.2 to 0.4.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.4.2...v0.4.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 11:13:04 +02:00
dependabot[bot]
fecfbd1a3e
Bump coverage from 7.5.0 to 7.5.1 (#5059)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.5.0 to 7.5.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.5.0...7.5.1)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 11:12:49 +02:00
dependabot[bot]
c00d6dfc76
Bump cryptography from 42.0.5 to 42.0.6 (#5058) 2024-05-06 10:00:57 +02:00
dependabot[bot]
85be66d90d
Bump codecov/codecov-action from 4.3.0 to 4.3.1 (#5054)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-02 09:02:54 +02:00
Mike Degatano
1ac506b391
Skip udisks listener on failure to connect (#5049) 2024-05-01 10:50:48 +02:00
dependabot[bot]
f7738b77de
Bump pytest from 8.1.1 to 8.2.0 (#5046)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.1.1 to 8.2.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.1.1...8.2.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-30 15:55:34 -04:00
Mike Degatano
824037bb7d
Bump pytest-asyncio to 0.23.6 (#5048) 2024-04-30 15:46:44 -04:00
Stefan Agner
221292ad14
Mark issues in FixupBase abstract (#5033)
Since #5024 all fixups have an associated issue. Generally, it is
generally better to have an issue for every fixup so that things
can be mapped to repairs in Core easily. Let's mark the issues property
as abstract to indicate subclasses are required to implement it.
2024-04-29 16:24:58 -04:00
dependabot[bot]
16f8c75e9f
Bump sentry-sdk from 1.45.0 to 2.0.1 (#5047)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-29 17:33:36 +02:00
dependabot[bot]
90a37079f1
Bump ruff from 0.4.1 to 0.4.2 (#5043)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-26 10:07:04 +02:00
J. Nick Koston
798092af5e
Revert orjson to 3.9.15 due to segmentation faults (#5041)
https://github.com/ijl/orjson/issues/479
2024-04-25 17:48:48 +02:00
Jan Čermák
2a622a929d
Limit reporting of errors in Supervisor logs fallback (#5040)
We do not need to capture HostNotSupported errors to Sentry. The only
possible code path this error might come from is where the Journal
Gateway Daemon socket is unavailable, which is already reported as an
"Unsupported system" repair.
2024-04-25 10:44:21 +02:00
dependabot[bot]
ca8eeaa68c
Bump actions/download-artifact from 4.1.6 to 4.1.7 (#5039)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.6...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-25 09:25:11 +02:00
dependabot[bot]
d1b8ac1249
Bump actions/checkout from 4.1.3 to 4.1.4 (#5038)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.3 to 4.1.4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.3...v4.1.4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-25 09:15:34 +02:00
dependabot[bot]
3f629c4d60
Bump coverage from 7.4.4 to 7.5.0 (#5037)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-24 09:52:18 +02:00
dependabot[bot]
3fa910e68b
Bump actions/download-artifact from 4.1.5 to 4.1.6 (#5034)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.5 to 4.1.6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.5...v4.1.6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 09:06:04 +02:00
dependabot[bot]
e3cf2989c9
Bump actions/upload-artifact from 4.3.2 to 4.3.3 (#5035)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.2...v4.3.3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 09:05:50 +02:00
dependabot[bot]
136b2f402d
Bump dirhash from 0.3.0 to 0.4.0 (#5036)
Bumps [dirhash](https://github.com/andhus/dirhash-python) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/andhus/dirhash-python/releases)
- [Changelog](https://github.com/andhus/dirhash-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/andhus/dirhash-python/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: dirhash
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 09:05:06 +02:00
Mike Degatano
8d18d2d9c6
Use signals to recognize new disks immediately (#5023)
* Use signals to recognize new disks immediately

* Add test for disabled data disk issue

* Add mock of UDisks2 base service to test

* Apply suggestions from code review

* Shutdown manager first to avoid potential race conditions

* Update tests/dbus_service_mocks/udisks2.py

Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Jan Čermák <sairon@users.noreply.github.com>
2024-04-22 16:35:03 +02:00
Mike Degatano
f18213361a
Add issues field to create full backup suggestion (#5024) 2024-04-22 09:58:22 +02:00
Jan Čermák
18d9d32bca
Fix Supervisor logs fallback (#5022)
Supervisor logs fallback in get_supervisor_logs didn't work properly
because the exception was caught in api_process_raw instead. This was
not discovered in tests because the side effect raised OSError, which
isn't handled there.

To address that, I split the advanced_logs to two functions, one being a
wrapped API handler, one being plain function returning response without
any additional error handling. The tests now check for both cases of
errors (HassioError and random generic Python error).

Refs #5021
2024-04-22 09:42:12 +02:00
dependabot[bot]
1246e429c9
Bump ruff from 0.4.0 to 0.4.1 (#5032)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.4.0 to 0.4.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.4.0...v0.4.1)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-22 09:14:49 +02:00
dependabot[bot]
77bc46bc37
Bump actions/checkout from 4.1.2 to 4.1.3 (#5031)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-22 08:50:53 +02:00
dependabot[bot]
ce16963c94
Bump actions/upload-artifact from 4.3.1 to 4.3.2 (#5025)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.1...v4.3.2)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-19 09:41:14 +02:00
dependabot[bot]
a70e8cfe58
Bump actions/download-artifact from 4.1.4 to 4.1.5 (#5026)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.4 to 4.1.5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.4...v4.1.5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-19 09:41:06 +02:00
dependabot[bot]
ba922a1aaa
Bump ruff from 0.3.7 to 0.4.0 (#5027)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.3.7 to 0.4.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.3.7...v0.4.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-19 09:40:19 +02:00
dependabot[bot]
b09230a884
Bump aiohttp from 3.9.4 to 3.9.5 (#5020)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.4 to 3.9.5.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.4...v3.9.5)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-17 09:01:18 +02:00
dependabot[bot]
f1cb9ca08e
Bump orjson from 3.9.15 to 3.10.1 (#5019)
Bumps [orjson](https://github.com/ijl/orjson) from 3.9.15 to 3.10.1.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.9.15...3.10.1)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-17 08:59:30 +02:00
Mike Degatano
06513e88c6
Allow restarting core in safe mode (#5017) 2024-04-17 08:54:56 +02:00
dependabot[bot]
b4a79bd068
Bump setuptools from 69.2.0 to 69.5.1 (#5018) 2024-04-15 08:58:39 +02:00
Mike Degatano
dfd8fe84e0
Mount manager reload mounts all failed mounts (#5014)
* Mount manager reload mounts all failed mounts

* Remove invalid part of mount manager reload test
2024-04-12 12:02:29 +02:00
J. Nick Koston
4857c2e243
Bump aiohttp to 3.9.4 (#4899) 2024-04-12 08:51:07 +02:00
dependabot[bot]
7d384f6160
Bump ruff from 0.3.5 to 0.3.7 (#5015)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-12 08:45:52 +02:00
Mike Degatano
672a7621f9
Adopt a disabled data disk (#5010) 2024-04-11 13:53:19 -04:00
Mike Degatano
f0e2fb3f57
Addon load should not fail due to docker error (#5011) 2024-04-11 15:06:57 +02:00
dependabot[bot]
8c3a520512
Bump sentry-sdk from 1.44.1 to 1.45.0 (#5012)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.44.1 to 1.45.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.44.1...1.45.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-11 08:56:48 +02:00
dependabot[bot]
22e50d56db
Bump sigstore/cosign-installer from 3.4.0 to 3.5.0 (#5013)
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-11 08:55:50 +02:00
Mike Degatano
a0735f3585
Allow adoption of existing data disk (#4991)
* Allow adoption of existing data disk

* Fix existing tests

* Add test cases and fix image issues

* Fix addon build test

* Run checks during setup not startup

* Addon load mimics plugin and HA load for docker part

* Default image accessible in except
2024-04-10 11:36:18 +02:00
Mike Degatano
50a2e8fde3
Allow adoption of existing data disk (#4991)
* Allow adoption of existing data disk

* Fix existing tests

* Add test cases and fix image issues

* Fix addon build test

* Run checks during setup not startup

* Addon load mimics plugin and HA load for docker part

* Default image accessible in except
2024-04-10 10:25:22 +02:00
dependabot[bot]
55ed63cc79
Bump dirhash from 0.2.1 to 0.3.0 (#5006)
Bumps [dirhash](https://github.com/andhus/dirhash-python) from 0.2.1 to 0.3.0.
- [Release notes](https://github.com/andhus/dirhash-python/releases)
- [Changelog](https://github.com/andhus/dirhash-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/andhus/dirhash-python/compare/v0.2.1...v0.3.0)

---
updated-dependencies:
- dependency-name: dirhash
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 09:28:28 +02:00
dependabot[bot]
97e9dfff3f
Bump codecov/codecov-action from 4.2.0 to 4.3.0 (#5007)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 09:26:36 +02:00
dependabot[bot]
501c9579fb
Bump pulsectl from 23.5.2 to 24.4.0 (#5003)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 23.5.2 to 24.4.0.
- [Changelog](https://github.com/mk-fg/python-pulse-control/blob/master/CHANGES.rst)
- [Commits](https://github.com/mk-fg/python-pulse-control/commits)

---
updated-dependencies:
- dependency-name: pulsectl
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 10:06:44 +02:00
dependabot[bot]
f9aedadee6
Bump typing-extensions from 4.10.0 to 4.11.0 (#5002)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 08:52:23 +02:00
Stefan Agner
c3c17b2bc3
Increase DNS timeout for CoreDNS users (#5000)
* Increase DNS timeout for CoreDNS users

CoreDNS forward plug-in fails in ~6s, then fallback triggers.
However, the default timeout of glibc and musl is 5s. Increase
default timeout to make sure CoreDNS fallback is working
on first query.

* Pass option as list
2024-04-05 09:40:57 +02:00
Jan Čermák
a894c4589e
Use Systemd Journal API for all logs endpoints in API (#4972)
* Use Systemd Journal API for all logs endpoints in API

Replace all logs endpoints using container logs with wrapped
advanced_logs function, adding possibility to get logs from previous
boots and following the logs. Supervisor logs are an excetion where
Docker logs are still used - in case an exception is raised while
accessing the Systemd logs, they're used as fallback - otherwise we
wouldn't have an easy way to see what went wrong.

* Refactor testing of advanced logs endpoints to a common method

* Send error while fetching Supervisor logs to Sentry; minor cleanup

* Properly handle errors and use consistent content type in logs endpoints

* Replace api_process_custom with reworked api_process_raw per @mdegat01 suggestion
2024-04-04 12:09:08 +02:00
dependabot[bot]
56a8a1b5a1
Bump sentry-sdk from 1.44.0 to 1.44.1 (#4999)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.44.0 to 1.44.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.44.0...1.44.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 09:12:48 +02:00
dependabot[bot]
be3f7a6c37
Bump codecov/codecov-action from 4.1.1 to 4.2.0 (#4998)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.1.1 to 4.2.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.1.1...v4.2.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-04 08:43:36 +02:00
Jan Čermák
906e400ab7
Fix submounts of /dev being read-only with Docker 25+ (#4997)
As described in #4996, Docker 25+ changes made sub-mounts of the /dev
filesystem to be mounted read-only. Revert to the previous behavior by
adjusting the ReadOnlyNonRecursive option. Cleaner way would be to
upstream support for setting this option via Mount class arguments, so
this change is meant to be rather a hotfix for the issue. Even better
approach would be mounting /dev non-recursively, and taking care of
creating all necessary filesystems when creating containers in
Supervisor.
2024-04-02 21:07:53 +02:00
Stefan Agner
a9265afd4c
Format NetworkManager connection name correctly for VLANs (#4986)
* Format NetworkManager connection name correctly for VLANs

Make sure NetworkManager connections are named correctly for VLANs
as well (<interface-name>.<vlan-id>).

* Avoid extending VLAN configuration name
2024-04-02 21:07:39 +02:00
Stefan Agner
d26058ac80
Update base images to 3.12-alpine3.19 (#4995) 2024-04-02 12:25:32 +02:00
dependabot[bot]
ebd1f30606
Bump ruff from 0.3.4 to 0.3.5 (#4994)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.3.4 to 0.3.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.3.4...v0.3.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 08:38:36 +02:00
dependabot[bot]
c78e077649
Bump gitpython from 3.1.42 to 3.1.43 (#4993)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.42 to 3.1.43.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.42...3.1.43)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 08:36:40 +02:00
dependabot[bot]
07619223b0
Bump aiodns from 3.1.1 to 3.2.0 (#4992)
Bumps [aiodns](https://github.com/saghul/aiodns) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/saghul/aiodns/releases)
- [Changelog](https://github.com/saghul/aiodns/blob/master/ChangeLog)
- [Commits](https://github.com/saghul/aiodns/compare/v3.1.1...v3.2.0)

---
updated-dependencies:
- dependency-name: aiodns
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 08:36:22 +02:00
dependabot[bot]
25c326ec6c
Bump sentry-sdk from 1.43.0 to 1.44.0 (#4990)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-29 08:26:41 +01:00
dependabot[bot]
df167b94c2
Bump codecov/codecov-action from 4.1.0 to 4.1.1 (#4984)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-27 08:33:54 +01:00
dependabot[bot]
3730908881
Bump actions/setup-python from 5.0.0 to 5.1.0 (#4983)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-27 08:00:28 +01:00
dependabot[bot]
975dc1bc11
Bump ruff from 0.3.3 to 0.3.4 (#4975)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 11:33:17 +01:00
dependabot[bot]
31409f0c32
Bump time-machine from 2.14.0 to 2.14.1 (#4981)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2024-03-25 09:47:47 +01:00
dependabot[bot]
b19273227b
Bump pytest-cov from 4.1.0 to 5.0.0 (#4980)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 09:45:36 +01:00
dependabot[bot]
f89179fb03
Bump pre-commit from 3.6.2 to 3.7.0 (#4979) 2024-03-25 09:02:43 +01:00
Mike Degatano
90c971f9f1
Unsupported if wrong image used on virtualization (#4968)
* Unsupported if wrong image used on virtualization

* Add generic-aarch64 as supported image

* Add virtualization field to API

* Change startup to setup in check
2024-03-21 18:08:48 +01:00
Jan Čermák
d685780a4a
Fix IncompleteReadError happening sometimes when reading Systemd logs (#4974)
Sometimes an empty line is returned from readuntil when EOF is reached,
which seems to be caused by a race of the EOF check in the loop and
later check in readuntil. With this fix, I am not able to reproduce the
issue anymore.
2024-03-21 15:58:53 +01:00
dependabot[bot]
b6bc8b7b7c
Bump sentry-sdk from 1.42.0 to 1.43.0 (#4973)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.42.0 to 1.43.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.42.0...1.43.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-20 22:49:15 +01:00
dependabot[bot]
92daba898f
Bump actions/cache from 4.0.1 to 4.0.2 (#4969)
Bumps [actions/cache](https://github.com/actions/cache) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-20 17:16:45 +01:00
Mike Degatano
138843591e
Bump cosign to v2.2.3 and builder to 2024.03.5 (#4971)
* Bump cosign to v2.2.3 and builder to 2024.03.4

* Bump builder to 2024.03.5

* Bump other builder action to 2024.03.5
2024-03-20 17:00:12 +01:00
Jan Čermák
0814552b2a
Use Journal Export Format for host (advanced) logs (#4963)
* Use Journal Export Format for host (advanced) logs

Add methods for handling Journal Export Format and use it for fetching
of host logs. This is foundation for colored streaming logs for other
endpoints as well.

* Make pylint happier - remove extra pass statement

* Rewrite journal gateway tests to mock ClientResponse's StreamReader

* Handle connection refused error when connecting to journal-gatewayd

* Use SYSTEMD_JOURNAL_GATEWAYD_SOCKET global path also for connection

* Use parsing algorithm suggested by @agners in review

* Fix timestamps in formatting, always use UTC for now

* Add tests for Accept header in host logs

* Apply suggestions from @agners

Co-authored-by: Stefan Agner <stefan@agner.ch>

* Bail out of parsing earlier if field is not in required fields

* Fix parsing issue discovered in the wild and add test case

* Make verbose formatter more tolerant

* Use some bytes' native functions for some minor optimizations

* Move MalformedBinaryEntryError to exceptions module, add test for it

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-03-20 09:00:45 +01:00
Mike Degatano
0e0fadd72d
Fix some expected boot slot fields are optional (#4964)
* Fix some expected boot slot fields are optional

* Move stuff around to make pylint happy
2024-03-18 18:30:10 +01:00
dependabot[bot]
5426bd4392
Bump ruff from 0.3.2 to 0.3.3 (#4966)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.3.2 to 0.3.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.3.2...v0.3.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-18 08:29:33 +01:00
James Ross
3520a65099
Restore lost continue statement (#4965)
Commit 140b769a42156b476b92edc5eb8cbff3455c6bd0 separated the `continue` from its block, so this puts it back
2024-03-17 21:16:54 -04:00
Stefan Agner
b15a5c2c87
Add full year and milliseconds to log timestamp (#4954)
This synchronizes log timestamps with how Home Assistant Core formats
them: Using the full 4 digit year and milliseconds precision.

See also https://github.com/home-assistant/core/pull/74518.
2024-03-15 17:50:01 +01:00
Mike Degatano
a8af04ff82
Cache existence of addon paths (#4944)
* Cache existence of addon paths

* Always update submodules

* Switch to an always cached model

* Cache on store addon only

* Fix tests

* refresh_cache to refresh_path_cache

* Fix name change in test

* Move logic into StoreManager
2024-03-15 16:43:26 +01:00
Mike Degatano
2148de45a0
Allow client to change boot slot via API (#4945)
* Allow client to change boot slot via API

* Wrap call to rauc in job that checks for OS

* Reboot after changing the active boot slot

* Add test cases and clean up

* BootName to BootSlot

* Fix test

* Rename boot_name to boot_slot

* Fix tests after field change
2024-03-15 10:36:37 -04:00
dependabot[bot]
c4143dacee
Bump coverage from 7.4.3 to 7.4.4 (#4962) 2024-03-15 08:38:29 +01:00
dependabot[bot]
a8025e77b3
Bump setuptools from 69.1.1 to 69.2.0 (#4958)
Bumps [setuptools](https://github.com/pypa/setuptools) from 69.1.1 to 69.2.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v69.1.1...v69.2.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 09:39:45 +01:00
dependabot[bot]
dd1e76be93
Bump docker/login-action from 3.0.0 to 3.1.0 (#4957)
Bumps [docker/login-action](https://github.com/docker/login-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 09:06:03 +01:00
dependabot[bot]
36f997959a
Bump sentry-sdk from 1.41.0 to 1.42.0 (#4959)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.41.0 to 1.42.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.41.0...1.42.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 09:05:38 +01:00
dependabot[bot]
c1faed163a
Bump actions/checkout from 4.1.1 to 4.1.2 (#4956)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-13 10:37:12 +01:00
Mike Degatano
9ca927dbe7
Watchdog does not start core before supervisor (#4955) 2024-03-13 09:08:27 +01:00
dependabot[bot]
02c6011818
Bump ruff from 0.3.1 to 0.3.2 (#4951)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.3.1 to 0.3.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.3.1...v0.3.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 10:06:41 +01:00
dependabot[bot]
2e96b16396
Bump pytest from 8.1.0 to 8.1.1 (#4952)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.1.0 to 8.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.1.0...8.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 09:40:54 +01:00
dependabot[bot]
53b8de6c1c
Bump sentry-sdk from 1.40.6 to 1.41.0 (#4950)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-08 13:49:50 +01:00
dependabot[bot]
daea9f893c
Bump pytest-timeout from 2.2.0 to 2.3.1 (#4949)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-08 11:45:20 +01:00
dependabot[bot]
d1b5b1734c
Bump ruff from 0.3.0 to 0.3.1 (#4946)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.3.0 to 0.3.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.3.0...v0.3.1)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-07 09:13:37 +01:00
Mike Degatano
74a5899626
Remove discovery config validation from supervisor (#4937)
* Remove discovery config validation from supervisor

* Remove invalid test

* Change validation to require a dictionary for compatibility
2024-03-05 16:25:15 +01:00
Mike Degatano
202ebf6d4e
Set core timeout from S6_SERVICES_GRACETIME (#4938) 2024-03-04 11:14:51 -05:00
Mike Degatano
2c7b417e25
APIForbidden should result in 403 status (#4943) 2024-03-04 11:09:17 -05:00
Stefan Agner
bb5e138134
Proxy WebSocket close messages as well (#4942)
We can "proxy" WebSocket close messages just as well as any
other WebSocket message. This avoids an error print in the Supervisor
logs whenever any one side of the connection closes.
2024-03-04 10:31:27 -05:00
dependabot[bot]
3a2c3e2f84
Bump pytest from 8.0.2 to 8.1.0 (#4941)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.2 to 8.1.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.0.2...8.1.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-04 10:56:41 +01:00
dependabot[bot]
d5be0c34ac
Bump actions/download-artifact from 4.1.3 to 4.1.4 (#4939)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.3 to 4.1.4.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.3...v4.1.4)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-04 10:56:26 +01:00
dependabot[bot]
ea5431ef2b
Bump time-machine from 2.13.0 to 2.14.0 (#4940)
Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.13.0 to 2.14.0.
- [Changelog](https://github.com/adamchainz/time-machine/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/time-machine/compare/2.13.0...2.14.0)

---
updated-dependencies:
- dependency-name: time-machine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-04 10:56:12 +01:00
dependabot[bot]
9c4cdcd11f
Bump ruff from 0.2.2 to 0.3.0 (#4935)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.2.2 to 0.3.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.2.2...v0.3.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 09:57:31 +01:00
dependabot[bot]
e5ef6333e4
Bump actions/cache from 4.0.0 to 4.0.1 (#4936)
Bumps [actions/cache](https://github.com/actions/cache) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-01 09:57:05 +01:00
Mike Degatano
98779a48b1
Fix check used for addon auto update (#4933)
* Fix check used for addon auto update

* Move timedelta to other side

Co-authored-by: Stefan Agner <stefan@agner.ch>

---------

Co-authored-by: Stefan Agner <stefan@agner.ch>
2024-02-29 11:22:21 -05:00
Mike Degatano
9d4848ee77
Add an admin only device wipe API (#4934)
* Add an admin only device wipe API

* Fix pylint issue
2024-02-29 10:29:52 -05:00
Mike Degatano
5126820619
Allow removing addon config on uninstall (#4913) 2024-02-29 10:24:51 -05:00
Mike Degatano
8b5c808e8c
Allow listing of HA users via admin CLI (#4912)
* Allow listing of HA users via admin CLI

* Filter out system generated users and fields
2024-02-28 13:30:37 -05:00
dependabot[bot]
9c75996c40
Bump pytest from 8.0.1 to 8.0.2 (#4931)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.0.1...8.0.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-28 11:16:39 +01:00
dependabot[bot]
d524778e42
Bump sentry-sdk from 1.40.5 to 1.40.6 (#4930)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.40.5 to 1.40.6.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.40.5...1.40.6)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-28 11:16:24 +01:00
dependabot[bot]
52d4bc660e
Bump codecov/codecov-action from 4.0.2 to 4.1.0 (#4927)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.2 to 4.1.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.0.2...v4.1.0)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 09:59:01 +01:00
dependabot[bot]
8884696a6c
Bump actions/download-artifact from 4.1.2 to 4.1.3 (#4926)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 09:58:21 +01:00
dependabot[bot]
d493ccde28
Bump pytest from 7.4.4 to 8.0.1 (#4901)
* Bump pytest from 7.4.4 to 8.0.1

Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.4 to 8.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.4...8.0.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update pytest-asyncio to 0.23.5

* Set scope to function on fixture

* Unthrottle by patching last call to prevent carryover

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2024-02-27 09:57:44 +01:00
J. Nick Koston
1ececaaaa2
Bump securetar to 2024.2.1 (#4925) 2024-02-26 10:47:47 -10:00
dependabot[bot]
91b48ad432
Bump pylint from 3.0.3 to 3.1.0 (#4921)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v3.0.3...v3.1.0)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 11:02:23 -05:00
dependabot[bot]
f3fe40a19f
Bump codecov/codecov-action from 4.0.1 to 4.0.2 (#4923)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 10:22:43 -05:00
dependabot[bot]
cf4b29c425
Bump orjson from 3.9.14 to 3.9.15 (#4922)
Bumps [orjson](https://github.com/ijl/orjson) from 3.9.14 to 3.9.15.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.9.14...3.9.15)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 10:22:17 -05:00
dependabot[bot]
4344e14a9d
Bump coverage from 7.4.1 to 7.4.3 (#4920)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.4.1 to 7.4.3.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.4.1...7.4.3)

---
updated-dependencies:
- dependency-name: coverage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 10:18:32 -05:00
dependabot[bot]
df935ec423
Bump typing-extensions from 4.9.0 to 4.10.0 (#4919)
Bumps [typing-extensions](https://github.com/python/typing_extensions) from 4.9.0 to 4.10.0.
- [Release notes](https://github.com/python/typing_extensions/releases)
- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/python/typing_extensions/commits)

---
updated-dependencies:
- dependency-name: typing-extensions
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 10:18:02 -05:00
dependabot[bot]
e7f9f7504e
Bump setuptools from 69.1.0 to 69.1.1 (#4918)
Bumps [setuptools](https://github.com/pypa/setuptools) from 69.1.0 to 69.1.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v69.1.0...v69.1.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 10:15:20 -05:00
dependabot[bot]
5721b2353a
Bump cryptography from 42.0.3 to 42.0.5 (#4917)
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.3 to 42.0.5.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.3...42.0.5)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 10:14:50 -05:00
Mike Degatano
c9de846d0e
Fix missing apis from addons with manager role (#4908)
* Allow mount control from addons with manager role

* Allow available_updates and refresh_updates too
2024-02-21 11:36:29 -05:00
dependabot[bot]
a598108c26
Bump sentry-sdk from 1.40.4 to 1.40.5 (#4905)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.40.4 to 1.40.5.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.40.4...1.40.5)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-20 09:19:15 +01:00
dependabot[bot]
5467aa399d
Bump ruff from 0.2.1 to 0.2.2 (#4904)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.2.1...v0.2.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-19 10:37:44 +01:00
dependabot[bot]
da052b074a
Bump urllib3 from 2.2.0 to 2.2.1 (#4903) 2024-02-19 08:07:18 +01:00
dependabot[bot]
90c035edd0
Bump pre-commit from 3.6.1 to 3.6.2 (#4902) 2024-02-19 07:52:18 +01:00
dependabot[bot]
fc4eb44a24
Bump cryptography from 42.0.2 to 42.0.3 (#4895)
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.2 to 42.0.3.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.2...42.0.3)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
2024-02-16 22:10:43 +01:00
Stefan Agner
a71111b378
Fix autoupdate time compare (#4897)
* Fix autoupdate time compare

Make sure both timestamps are UTC, otherwise Python complains with:
TypeError: can't compare offset-naive and offset-aware datetimes

* Use correect attribute

---------

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2024-02-16 15:40:54 +01:00
dependabot[bot]
52e0c7e484
Bump gitpython from 3.1.41 to 3.1.42 (#4894)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-16 15:31:31 +01:00
Stefan Agner
e32970f191
Fix new complaint by ruff 0.2.1 (#4898) 2024-02-16 14:35:31 +01:00
dependabot[bot]
897cc36017
Bump sentry-sdk from 1.40.3 to 1.40.4 (#4891)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.40.3 to 1.40.4.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.40.3...1.40.4)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 09:24:58 +01:00
dependabot[bot]
d79c575860
Bump orjson from 3.9.13 to 3.9.14 (#4890)
Bumps [orjson](https://github.com/ijl/orjson) from 3.9.13 to 3.9.14.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.9.13...3.9.14)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-14 09:24:52 +01:00
J. Nick Koston
1f19f84edd
Create backups files without having to copy inner tarballs (#4884)
* Create backups files without having to copy inner tarballs

needs https://github.com/pvizeli/securetar/pull/33

* fix writing json

* fix writing json

* fixes

* fixes

* ensure cleaned up

* need ./

* fix type

* Bump securetar to 2024.2.0

changelog: https://github.com/pvizeli/securetar/compare/2023.12.0...2024.2.0

* backup file is now created sooner

* reorder so comment still makes sense
2024-02-14 09:24:43 +01:00
dependabot[bot]
27c37b8b84
Bump ruff from 0.1.14 to 0.2.1 (#4877)
* Bump ruff from 0.1.14 to 0.2.1

Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.14 to 0.2.1.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.14...v0.2.1)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update .pre-commit-config.yaml

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2024-02-14 09:11:26 +01:00
J. Nick Koston
06a5dd3153
Bump securetar to 2024.2.0 (#4888) 2024-02-12 19:34:04 +01:00
Mike Degatano
b5bf270d22
Mount status checks look at connection (#4882)
* Mount status checks look at connection

* Fix tests and refactor to fixture

* Fix test
2024-02-12 17:32:54 +01:00
dependabot[bot]
8e71d69a64
Bump setuptools from 69.0.3 to 69.1.0 (#4885) 2024-02-12 08:31:08 +01:00
dependabot[bot]
06edb6f8a8
Bump pre-commit from 3.6.0 to 3.6.1 (#4887) 2024-02-12 08:20:35 +01:00
dependabot[bot]
dca82ec0a1
Bump sentry-sdk from 1.40.2 to 1.40.3 (#4886) 2024-02-12 08:20:00 +01:00
dependabot[bot]
9c82ce4103
Bump debugpy from 1.8.0 to 1.8.1 (#4881)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-09 08:14:07 +01:00
dependabot[bot]
8a23a9eb1b
Bump sentry-sdk from 1.40.1 to 1.40.2 (#4880) 2024-02-08 07:25:48 +01:00
dependabot[bot]
e1b7e515df
Bump sentry-sdk from 1.40.0 to 1.40.1 (#4879)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 08:19:23 +01:00
dependabot[bot]
c8ff335ed7
Bump awesomeversion from 23.11.0 to 24.2.0 (#4878)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 07:54:04 +01:00
dependabot[bot]
5736da8ab7
Bump actions/download-artifact from 4.1.1 to 4.1.2 (#4876)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.1.1 to 4.1.2.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4.1.1...v4.1.2)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 08:59:19 +01:00
dependabot[bot]
060bba4dce
Bump actions/upload-artifact from 4.3.0 to 4.3.1 (#4875)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.0...v4.3.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-06 08:59:06 +01:00
Mike Degatano
4c573991d2
Improve error handling when mounts fail (#4872) 2024-02-05 16:24:53 -05:00
Mike Degatano
7fd6dce55f
Migrate to Ruff for lint and format (#4852)
* Migrate to Ruff for lint and format

* Fix pylint issues

* DBus property sets into normal awaitable methods

* Fix tests relying on separate tasks in connect

* Fixes from feedback
2024-02-05 11:37:39 -05:00
dependabot[bot]
1861d756e9
Bump voluptuous from 0.14.1 to 0.14.2 (#4874)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 08:49:14 +01:00
dependabot[bot]
c36c041f5e
Bump orjson from 3.9.12 to 3.9.13 (#4873)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-05 08:45:23 +01:00
dependabot[bot]
c3d877bdd2
Bump cryptography from 42.0.1 to 42.0.2 (#4860)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 11:11:50 +01:00
dependabot[bot]
1242030d4a
Bump codecov/codecov-action from 3.1.6 to 4.0.1 (#4869)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 08:50:53 +01:00
dependabot[bot]
1626e74608
Bump release-drafter/release-drafter from 5.25.0 to 6.0.0 (#4868)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-02 08:50:38 +01:00
dependabot[bot]
b1b913777f
Bump sigstore/cosign-installer from 3.3.0 to 3.4.0 (#4864)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 08:53:35 +01:00
Stefan Agner
190894010c
Reset failed API call counter on successful API call (#4862)
* Reset failed API call counter on successful API call

Make sure to reset the failed API call counter after a successful
API call. While at it also update the log messages a bit to make it
clearer what the problem is exactly.

* Address pytest changes
2024-01-31 11:41:21 -05:00
Stefan Agner
765265723c
Explicitly log when API requests timeout (#4861)
Currently a timeout leads to a log entry which simply states:
"Error on call http://172.30.32.1:8123/api/core/state: ". From this,
it is not immeaditly clear what the problem is. This commit adds
a log entry which explicitly states that the request timed out.
2024-01-31 10:17:24 -05:00
dependabot[bot]
7e20502379
Bump urllib3 from 2.1.0 to 2.2.0 (#4859)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.1.0...2.2.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 10:13:34 -05:00
dependabot[bot]
366fc30e9d
Bump sentry-sdk from 1.39.2 to 1.40.0 (#4858)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.39.2 to 1.40.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.39.2...1.40.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 10:11:11 -05:00
dependabot[bot]
aa91788a69
Bump codecov/codecov-action from 3.1.5 to 3.1.6 (#4857)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 08:09:52 +01:00
J. Nick Koston
375789b019
Use orjson encoder for websocket messages (#4854)
I missed that these need to have dumps passed
2024-01-30 09:00:27 -05:00
Mike Degatano
140b769a42
Auto updates to new version delay for 24 hours (#4838) 2024-01-30 08:58:28 -05:00
Mike Degatano
88d718271d
Fix serialization issue adding error to job (#4853) 2024-01-30 12:21:02 +01:00
dependabot[bot]
6ed26cdd1f
Bump aiohttp from 3.9.2 to 3.9.3 (#4855)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 21:36:01 -10:00
J. Nick Koston
d1851fa607
Significantly speed up creating backups with isal via zlib-fast (#4843) 2024-01-29 10:25:43 -10:00
dependabot[bot]
e846157c52
Bump aiohttp from 3.9.1 to 3.9.2 (#4848)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.1 to 3.9.2.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.1...v3.9.2)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 14:35:54 -05:00
dependabot[bot]
e190bb4c1a
Bump colorlog from 6.8.0 to 6.8.2 (#4846)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 08:53:39 +01:00
dependabot[bot]
137fbe7acd
Bump coverage from 7.4.0 to 7.4.1 (#4849) 2024-01-29 08:28:43 +01:00
dependabot[bot]
9ccdb2ae3a
Bump cryptography from 41.0.7 to 42.0.1 (#4837)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-28 20:54:01 +01:00
dependabot[bot]
f5f7515744
Bump codecov/codecov-action from 3.1.4 to 3.1.5 (#4840)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-28 20:36:45 +01:00
Mike Degatano
ddadbec7e3
Addon devs can block auto update for breaking versions (#4832) 2024-01-26 08:08:03 +01:00
dependabot[bot]
d24543e103
Bump actions/upload-artifact from 4.2.0 to 4.3.0 (#4835)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-24 08:29:27 +01:00
Mike Degatano
f80c4c9565
Fix bootstrap log typo (#4833) 2024-01-23 17:34:43 -10:00
Mike Degatano
480b383782
Add background option to backup APIs (#4802)
* Add background option to backup APIs

* Fix decorator tests

* Working error handling, initial test cases

* Change to schedule_job and always return job id

* Add tests

* Reorder call at/later args

* Validation errors return immediately in background

* None is invalid option for background

* Must pop the background option from body
2024-01-22 12:09:15 -05:00
dependabot[bot]
d3efd4c24b
Bump orjson from 3.9.10 to 3.9.12 (#4825)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-19 08:44:12 +01:00
dependabot[bot]
67a0acffa2
Bump actions/upload-artifact from 4.1.0 to 4.2.0 (#4824) 2024-01-19 07:38:07 +01:00
dependabot[bot]
41b07da399
Bump dbus-fast from 2.21.0 to 2.21.1 (#4822)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-17 08:20:06 +01:00
dependabot[bot]
a6ce55d5b5
Bump actions/cache from 3.3.3 to 4.0.0 (#4821) 2024-01-17 07:24:40 +01:00
Stefan Agner
98c01fe1b3
Fix add-on rebuild with ingress (#4819) 2024-01-15 07:53:25 -10:00
dependabot[bot]
51df986222
Bump actions/upload-artifact from 4.0.0 to 4.1.0 (#4818)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 09:15:27 +01:00
J. Nick Koston
9c625f93a5
Fix dirhash failing to import pkg_resources (#4817) 2024-01-14 11:20:35 +01:00
dependabot[bot]
7101d47e2e
Bump getsentry/action-release from 1.6.0 to 1.7.0 (#4805)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-14 11:13:21 +01:00
J. Nick Koston
eb85be2770
Improve json performance by porting core orjson utils (#4816)
* Improve json performance by porting core orjson utils

* port relevant tests

* pylint

* add test for read_json_file

* add test for read_json_file

* remove workaround for core issue we do not have here

---------

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2024-01-13 19:19:01 +01:00
Mike Degatano
2da27937a5
Update python to 3.12 (#4815)
* Update python to 3.12

* Fix tests and deprecations

* Fix other references to 3.11

* build.json doesn't exist
2024-01-13 16:35:07 +01:00
dependabot[bot]
2a29b801a4
Bump jinja2 from 3.1.2 to 3.1.3 (#4810)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 09:52:44 +01:00
dependabot[bot]
57e65714b0
Bump actions/download-artifact from 4.1.0 to 4.1.1 (#4809)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 09:35:09 +01:00
dependabot[bot]
0ae40cb51c
Bump gitpython from 3.1.40 to 3.1.41 (#4808)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 09:31:31 +01:00
dependabot[bot]
ddd195dfc6
Bump sentry-sdk from 1.39.1 to 1.39.2 (#4811)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 09:29:34 +01:00
dependabot[bot]
54b9f23ec5
Bump actions/cache from 3.3.2 to 3.3.3 (#4813)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-12 09:25:51 +01:00
dependabot[bot]
242dd3e626
Bump home-assistant/wheels from 2023.10.5 to 2024.01.0 (#4804) 2024-01-08 08:16:11 +01:00
dependabot[bot]
1b8acb5b60
Bump home-assistant/builder from 2023.12.0 to 2024.01.0 (#4800)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-05 08:19:40 +01:00
dependabot[bot]
a7ab96ab12
Bump flake8 from 6.1.0 to 7.0.0 (#4799)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-05 08:18:05 +01:00
dependabot[bot]
06ab11cf87
Bump attrs from 23.1.0 to 23.2.0 (#4793)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-02 16:57:05 +01:00
dependabot[bot]
1410a1b06e
Bump pytest from 7.4.3 to 7.4.4 (#4792) 2024-01-01 14:55:37 +01:00
Mike Degatano
5baf19f7a3
Migrate to pyproject.toml where possible (#4770)
* Migrate to pyproject.toml where possible

* Share requirements and fix version import

* Fix issues with timezone in tests
2023-12-29 11:46:01 +01:00
Mike Degatano
6c66a7ba17
Improve error handling in backup restore (#4791) 2023-12-29 11:45:50 +01:00
4382 changed files with 25119 additions and 508571 deletions

View File

@ -1,38 +1,51 @@
{
"name": "Supervisor dev",
"image": "ghcr.io/home-assistant/devcontainer:supervisor",
"image": "ghcr.io/home-assistant/devcontainer:2-supervisor",
"containerEnv": {
"WORKSPACE_DIRECTORY": "${containerWorkspaceFolder}"
},
"remoteEnv": {
"PATH": "${containerEnv:VIRTUAL_ENV}/bin:${containerEnv:PATH}"
},
"appPort": ["9123:8123", "7357:4357"],
"postCreateCommand": "bash devcontainer_bootstrap",
"postCreateCommand": "bash devcontainer_setup",
"postStartCommand": "bash devcontainer_bootstrap",
"runArgs": ["-e", "GIT_EDITOR=code --wait", "--privileged"],
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"charliermarsh.ruff",
"ms-python.pylint",
"ms-python.vscode-pylance",
"visualstudioexptteam.vscodeintellicode",
"esbenp.prettier-vscode"
"redhat.vscode-yaml",
"esbenp.prettier-vscode",
"GitHub.vscode-pull-request-github"
],
"settings": {
"python.defaultInterpreterPath": "/home/vscode/.local/ha-venv/bin/python",
"python.pythonPath": "/home/vscode/.local/ha-venv/bin/python",
"python.terminal.activateEnvInCurrentTerminal": true,
"python.testing.pytestArgs": ["--no-cov"],
"pylint.importStrategy": "fromEnvironment",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true,
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/usr/bin/zsh"
}
},
"terminal.integrated.defaultProfile.linux": "zsh",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true,
"python.pythonPath": "/usr/local/bin/python3",
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--target-version", "py311"],
"python.formatting.blackPath": "/usr/local/bin/black"
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
}
},
"mounts": ["type=volume,target=/var/lib/docker"]
"mounts": [
"type=volume,target=/var/lib/docker",
"type=volume,target=/mnt/supervisor"
]
}

View File

@ -26,7 +26,7 @@ body:
attributes:
label: What type of installation are you running?
description: >
If you don't know, can be found in [Settings -> System -> Repairs -> System Information](https://my.home-assistant.io/redirect/system_health/).
If you don't know, can be found in [Settings -> System -> Repairs -> (three dot menu) -> System Information](https://my.home-assistant.io/redirect/system_health/).
It is listed as the `Installation Type` value.
options:
- Home Assistant OS
@ -72,9 +72,9 @@ body:
validations:
required: true
attributes:
label: System Health information
label: System information
description: >
System Health information can be found in the top right menu in [Settings -> System -> Repairs](https://my.home-assistant.io/redirect/repairs/).
The System information can be found in [Settings -> System -> Repairs -> (three dot menu) -> System Information](https://my.home-assistant.io/redirect/system_health/).
Click the copy button at the bottom of the pop-up and paste it here.
[![Open your Home Assistant instance and show health information about your system.](https://my.home-assistant.io/badges/system_health.svg)](https://my.home-assistant.io/redirect/system_health/)
@ -83,8 +83,9 @@ body:
label: Supervisor diagnostics
placeholder: "drag-and-drop the diagnostics data file here (do not copy-and-paste the content)"
description: >-
Supervisor diagnostics can be found in [Settings -> Integrations](https://my.home-assistant.io/redirect/integrations/).
Find the card that says `Home Assistant Supervisor`, open its menu and select 'Download diagnostics'.
Supervisor diagnostics can be found in [Settings -> Devices & services](https://my.home-assistant.io/redirect/integrations/).
Find the card that says `Home Assistant Supervisor`, open it, and select the three dot menu of the Supervisor integration entry
and select 'Download diagnostics'.
**Please drag-and-drop the downloaded file into the textbox below. Do not copy and paste its contents.**
- type: textarea

View File

@ -38,6 +38,7 @@
- This PR is related to issue:
- Link to documentation pull request:
- Link to cli pull request:
- Link to client library pull request:
## Checklist
@ -52,12 +53,14 @@
- [ ] Local tests pass. **Your PR cannot be merged unless tests pass**
- [ ] There is no commented out code in this PR.
- [ ] I have followed the [development checklist][dev-checklist]
- [ ] The code has been formatted using Black (`black --fast supervisor tests`)
- [ ] The code has been formatted using Ruff (`ruff format supervisor tests`)
- [ ] Tests have been added to verify that the new code works.
If API endpoints of add-on configuration are added/changed:
If API endpoints or add-on configuration are added/changed:
- [ ] Documentation added/updated for [developers.home-assistant.io][docs-repository]
- [ ] [CLI][cli-repository] updated (if necessary)
- [ ] [Client library][client-library-repository] updated (if necessary)
<!--
Thank you for contributing <3
@ -67,3 +70,5 @@ If API endpoints of add-on configuration are added/changed:
[dev-checklist]: https://developers.home-assistant.io/docs/en/development_checklist.html
[docs-repository]: https://github.com/home-assistant/developers.home-assistant
[cli-repository]: https://github.com/home-assistant/cli
[client-library-repository]: https://github.com/home-assistant-libs/python-supervisor-client/

View File

@ -33,7 +33,7 @@ on:
- setup.py
env:
DEFAULT_PYTHON: "3.11"
DEFAULT_PYTHON: "3.13"
BUILD_NAME: supervisor
BUILD_TYPE: supervisor
@ -53,7 +53,7 @@ jobs:
requirements: ${{ steps.requirements.outputs.changed }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
@ -75,7 +75,7 @@ jobs:
- name: Check if requirements files changed
id: requirements
run: |
if [[ "${{ steps.changed_files.outputs.all }}" =~ (requirements.txt|build.json) ]]; then
if [[ "${{ steps.changed_files.outputs.all }}" =~ (requirements.txt|build.yaml) ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
@ -92,7 +92,7 @@ jobs:
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
@ -106,9 +106,9 @@ jobs:
- name: Build wheels
if: needs.init.outputs.requirements == 'true'
uses: home-assistant/wheels@2023.10.5
uses: home-assistant/wheels@2025.03.0
with:
abi: cp311
abi: cp313
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
@ -125,20 +125,20 @@ jobs:
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
if: needs.init.outputs.publish == 'true'
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Install Cosign
if: needs.init.outputs.publish == 'true'
uses: sigstore/cosign-installer@v3.3.0
uses: sigstore/cosign-installer@v3.8.1
with:
cosign-release: "v2.0.2"
cosign-release: "v2.4.0"
- name: Install dirhash and calc hash
if: needs.init.outputs.publish == 'true'
run: |
pip3 install dirhash
pip3 install setuptools dirhash
dir_hash="$(dirhash "${{ github.workspace }}/supervisor" -a sha256 --match "*.py")"
echo "${dir_hash}" > rootfs/supervisor.sha256
@ -149,7 +149,7 @@ jobs:
- name: Login to GitHub Container Registry
if: needs.init.outputs.publish == 'true'
uses: docker/login-action@v3.0.0
uses: docker/login-action@v3.4.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@ -160,7 +160,7 @@ jobs:
run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV
- name: Build supervisor
uses: home-assistant/builder@2023.12.0
uses: home-assistant/builder@2025.03.0
with:
args: |
$BUILD_ARGS \
@ -178,7 +178,7 @@ jobs:
steps:
- name: Checkout the repository
if: needs.init.outputs.publish == 'true'
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Initialize git
if: needs.init.outputs.publish == 'true'
@ -203,11 +203,11 @@ jobs:
timeout-minutes: 60
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Build the Supervisor
if: needs.init.outputs.publish != 'true'
uses: home-assistant/builder@2023.12.0
uses: home-assistant/builder@2025.03.0
with:
args: |
--test \

View File

@ -8,7 +8,7 @@ on:
pull_request: ~
env:
DEFAULT_PYTHON: "3.11"
DEFAULT_PYTHON: "3.13"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
concurrency:
@ -25,15 +25,15 @@ jobs:
name: Prepare Python dependencies
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python
id: python
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: venv
key: |
@ -47,7 +47,7 @@ jobs:
pip install -r requirements.txt -r requirements_tests.txt
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: ${{ env.PRE_COMMIT_CACHE }}
lookup-only: true
@ -61,21 +61,21 @@ jobs:
. venv/bin/activate
pre-commit install-hooks
lint-black:
name: Check black
lint-ruff-format:
name: Check ruff-format
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: venv
key: |
@ -85,10 +85,67 @@ jobs:
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run black
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.2.3
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run ruff-format
run: |
. venv/bin/activate
black --target-version py311 --check supervisor tests setup.py
pre-commit run --hook-stage manual ruff-format --all-files --show-diff-on-failure
env:
RUFF_OUTPUT_FORMAT: github
lint-ruff:
name: Check ruff
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.2.3
with:
path: venv
key: |
${{ runner.os }}-venv-${{ needs.prepare.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.2.3
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run ruff
run: |
. venv/bin/activate
pre-commit run --hook-stage manual ruff --all-files --show-diff-on-failure
env:
RUFF_OUTPUT_FORMAT: github
lint-dockerfile:
name: Check Dockerfile
@ -96,7 +153,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Register hadolint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
@ -111,15 +168,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: venv
key: |
@ -131,7 +188,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
@ -149,94 +206,21 @@ jobs:
. venv/bin/activate
pre-commit run --hook-stage manual check-executables-have-shebangs --all-files
lint-flake8:
name: Check flake8
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ needs.prepare.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register flake8 problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/flake8.json"
- name: Run flake8
run: |
. venv/bin/activate
flake8 supervisor tests
lint-isort:
name: Check isort
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ needs.prepare.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run isort
run: |
. venv/bin/activate
pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure
lint-json:
name: Check JSON
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: venv
key: |
@ -248,7 +232,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
@ -272,92 +256,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ needs.prepare.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
- name: Run pylint
run: |
. venv/bin/activate
pylint supervisor tests
lint-pyupgrade:
name: Check pyupgrade
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ needs.prepare.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run pyupgrade
run: |
. venv/bin/activate
pre-commit run --hook-stage manual pyupgrade --all-files --show-diff-on-failure
pytest:
runs-on: ubuntu-latest
needs: prepare
name: Run tests Python ${{ needs.prepare.outputs.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Install Cosign
uses: sigstore/cosign-installer@v3.3.0
with:
cosign-release: "v2.0.2"
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: venv
key: |
@ -370,7 +277,47 @@ jobs:
- name: Install additional system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libpulse0 libudev1 dbus dbus-x11
sudo apt-get install -y --no-install-recommends libpulse0
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
- name: Run pylint
run: |
. venv/bin/activate
pylint supervisor tests
pytest:
runs-on: ubuntu-latest
needs: prepare
name: Run tests Python ${{ needs.prepare.outputs.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Install Cosign
uses: sigstore/cosign-installer@v3.8.1
with:
cosign-release: "v2.4.0"
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.2.3
with:
path: venv
key: |
${{ runner.os }}-venv-${{ needs.prepare.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Install additional system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libpulse0 libudev1 dbus-daemon
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
@ -392,10 +339,11 @@ jobs:
-o console_output_style=count \
tests
- name: Upload coverage artifact
uses: actions/upload-artifact@v4.0.0
uses: actions/upload-artifact@v4.6.2
with:
name: coverage-${{ matrix.python-version }}
path: .coverage
include-hidden-files: true
coverage:
name: Process test coverage
@ -403,15 +351,15 @@ jobs:
needs: ["pytest", "prepare"]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.0.0
uses: actions/setup-python@v5.5.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.2
uses: actions/cache@v4.2.3
with:
path: venv
key: |
@ -422,7 +370,7 @@ jobs:
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Download all coverage artifacts
uses: actions/download-artifact@v4.1.0
uses: actions/download-artifact@v4.2.1
- name: Combine coverage results
run: |
. venv/bin/activate
@ -430,4 +378,4 @@ jobs:
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.4
uses: codecov/codecov-action@v5.4.2

View File

@ -1,30 +0,0 @@
{
"problemMatcher": [
{
"owner": "flake8-error",
"severity": "error",
"pattern": [
{
"regexp": "^(.*):(\\d+):(\\d+):\\s(E\\d{3}\\s.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
]
},
{
"owner": "flake8-warning",
"severity": "warning",
"pattern": [
{
"regexp": "^(.*):(\\d+):(\\d+):\\s([CDFNW]\\d{3}\\s.*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
]
}
]
}

View File

@ -11,7 +11,7 @@ jobs:
name: Release Drafter
steps:
- name: Checkout the repository
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
@ -36,7 +36,7 @@ jobs:
echo "version=$datepre.$newpost" >> "$GITHUB_OUTPUT"
- name: Run Release Drafter
uses: release-drafter/release-drafter@v5.25.0
uses: release-drafter/release-drafter@v6.1.0
with:
tag: ${{ steps.version.outputs.version }}
name: ${{ steps.version.outputs.version }}

View File

@ -10,9 +10,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.1.1
uses: actions/checkout@v4.2.2
- name: Sentry Release
uses: getsentry/action-release@v1.6.0
uses: getsentry/action-release@v3.1.1
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}

View File

@ -9,7 +9,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9.0.0
- uses: actions/stale@v9.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30

82
.github/workflows/update_frontend.yml vendored Normal file
View File

@ -0,0 +1,82 @@
name: Update frontend
on:
schedule: # once a day
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
check-version:
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check_version.outputs.skip || steps.check_existing_pr.outputs.skip }}
current_version: ${{ steps.check_version.outputs.current_version }}
latest_version: ${{ steps.latest_frontend_version.outputs.latest_tag }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get latest frontend release
id: latest_frontend_version
uses: abatilo/release-info-action@v1.3.3
with:
owner: home-assistant
repo: frontend
- name: Check if version is up to date
id: check_version
run: |
current_version="$(cat .ha-frontend-version)"
latest_version="${{ steps.latest_frontend_version.outputs.latest_tag }}"
echo "current_version=${current_version}" >> $GITHUB_OUTPUT
echo "LATEST_VERSION=${latest_version}" >> $GITHUB_ENV
if [[ ! "$current_version" < "$latest_version" ]]; then
echo "Frontend version is up to date"
echo "skip=true" >> $GITHUB_OUTPUT
fi
- name: Check if there is no open PR with this version
if: steps.check_version.outputs.skip != 'true'
id: check_existing_pr
env:
GH_TOKEN: ${{ github.token }}
run: |
PR=$(gh pr list --state open --base main --json title --search "Update frontend to version $LATEST_VERSION")
if [[ "$PR" != "[]" ]]; then
echo "Skipping - There is already a PR open for version $LATEST_VERSION"
echo "skip=true" >> $GITHUB_OUTPUT
fi
create-pr:
runs-on: ubuntu-latest
needs: check-version
if: needs.check-version.outputs.skip != 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Clear www folder
run: |
rm -rf supervisor/api/panel/*
- name: Update version file
run: |
echo "${{ needs.check-version.outputs.latest_version }}" > .ha-frontend-version
- name: Download release assets
uses: robinraju/release-downloader@v1
with:
repository: 'home-assistant/frontend'
tag: ${{ needs.check-version.outputs.latest_version }}
fileName: home_assistant_frontend_supervisor-${{ needs.check-version.outputs.latest_version }}.tar.gz
extract: true
out-file-path: supervisor/api/panel/
- name: Remove release assets archive
run: |
rm -f supervisor/api/panel/home_assistant_frontend_supervisor-*.tar.gz
- name: Create PR
uses: peter-evans/create-pull-request@v7
with:
commit-message: "Update frontend to version ${{ needs.check-version.outputs.latest_version }}"
branch: autoupdate-frontend
base: main
draft: true
sign-commits: true
title: "Update frontend to version ${{ needs.check-version.outputs.latest_version }}"
body: >
Update frontend from ${{ needs.check-version.outputs.current_version }} to
[${{ needs.check-version.outputs.latest_version }}](https://github.com/home-assistant/frontend/releases/tag/${{ needs.check-version.outputs.latest_version }})

4
.gitmodules vendored
View File

@ -1,4 +0,0 @@
[submodule "home-assistant-polymer"]
path = home-assistant-polymer
url = https://github.com/home-assistant/home-assistant-polymer
branch = dev

1
.ha-frontend-version Normal file
View File

@ -0,0 +1 @@
20250401.0

View File

@ -1,34 +1,15 @@
repos:
- repo: https://github.com/psf/black
rev: 23.1.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
hooks:
- id: black
- id: ruff
args:
- --safe
- --quiet
- --target-version
- py311
- --fix
- id: ruff-format
files: ^((supervisor|tests)/.+)?[^/]+\.py$
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.7.0
- pydocstyle==6.3.0
files: ^(supervisor|script|tests)/.+\.py$
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v5.0.0
hooks:
- id: check-executables-have-shebangs
stages: [manual]
- id: check-json
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.0
hooks:
- id: pyupgrade
args: [--py311-plus]

18
.vscode/tasks.json vendored
View File

@ -58,9 +58,23 @@
"problemMatcher": []
},
{
"label": "Flake8",
"label": "Ruff Check",
"type": "shell",
"command": "flake8 supervisor tests",
"command": "ruff check --fix supervisor tests",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Ruff Format",
"type": "shell",
"command": "ruff format supervisor tests",
"group": {
"kind": "test",
"isDefault": true

View File

@ -4,11 +4,13 @@ FROM ${BUILD_FROM}
ENV \
S6_SERVICES_GRACETIME=10000 \
SUPERVISOR_API=http://localhost \
CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1
CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1 \
UV_SYSTEM_PYTHON=true
ARG \
COSIGN_VERSION \
BUILD_ARCH
BUILD_ARCH \
QEMU_CPU
# Install base
WORKDIR /usr/src
@ -26,20 +28,24 @@ RUN \
yaml \
\
&& curl -Lso /usr/bin/cosign "https://github.com/home-assistant/cosign/releases/download/${COSIGN_VERSION}/cosign_${BUILD_ARCH}" \
&& chmod a+x /usr/bin/cosign
&& chmod a+x /usr/bin/cosign \
&& pip3 install uv==0.6.1
# Install requirements
COPY requirements.txt .
RUN \
export MAKEFLAGS="-j$(nproc)" \
&& pip3 install --only-binary=:all: \
-r ./requirements.txt \
if [ "${BUILD_ARCH}" = "i386" ]; then \
setarch="linux32"; \
else \
setarch=""; \
fi \
&& ${setarch} uv pip install --compile-bytecode --no-cache --no-build -r requirements.txt \
&& rm -f requirements.txt
# Install Home Assistant Supervisor
COPY . supervisor
RUN \
pip3 install -e ./supervisor \
uv pip install --no-cache -e ./supervisor \
&& python3 -m compileall ./supervisor/supervisor

View File

@ -30,3 +30,5 @@ Releases are done in 3 stages (channels) with this structure:
[development]: https://developers.home-assistant.io/docs/supervisor/development
[stable]: https://github.com/home-assistant/version/blob/master/stable.json
[![Home Assistant - A project from the Open Home Foundation](https://www.openhomefoundation.org/badges/home-assistant.png)](https://www.openhomefoundation.org/)

View File

@ -1,10 +1,10 @@
image: ghcr.io/home-assistant/{arch}-hassio-supervisor
build_from:
aarch64: ghcr.io/home-assistant/aarch64-base-python:3.11-alpine3.18
armhf: ghcr.io/home-assistant/armhf-base-python:3.11-alpine3.18
armv7: ghcr.io/home-assistant/armv7-base-python:3.11-alpine3.18
amd64: ghcr.io/home-assistant/amd64-base-python:3.11-alpine3.18
i386: ghcr.io/home-assistant/i386-base-python:3.11-alpine3.18
aarch64: ghcr.io/home-assistant/aarch64-base-python:3.13-alpine3.21
armhf: ghcr.io/home-assistant/armhf-base-python:3.13-alpine3.21
armv7: ghcr.io/home-assistant/armv7-base-python:3.13-alpine3.21
amd64: ghcr.io/home-assistant/amd64-base-python:3.13-alpine3.21
i386: ghcr.io/home-assistant/i386-base-python:3.13-alpine3.21
codenotary:
signer: notary@home-assistant.io
base_image: notary@home-assistant.io
@ -12,7 +12,7 @@ cosign:
base_identity: https://github.com/home-assistant/docker-base/.*
identity: https://github.com/home-assistant/supervisor/.*
args:
COSIGN_VERSION: 2.0.2
COSIGN_VERSION: 2.4.0
labels:
io.hass.type: supervisor
org.opencontainers.image.title: Home Assistant Supervisor

@ -1 +0,0 @@
Subproject commit 9d457d52e80fc936491f0e8ece773d90748889c4

View File

@ -1,45 +0,0 @@
[MASTER]
reports=no
jobs=2
good-names=id,i,j,k,ex,Run,_,fp,T,os
extension-pkg-whitelist=
ciso8601
# Reasons disabled:
# format - handled by black
# locally-disabled - it spams too much
# duplicate-code - unavoidable
# cyclic-import - doesn't test if both import on load
# abstract-class-not-used - is flaky, should not show up but does
# unused-argument - generic callbacks and setup methods create a lot of warnings
# too-many-* - are not enforced for the sake of readability
# too-few-* - same as too-many-*
# abstract-method - with intro of async there are always methods missing
disable=
format,
abstract-method,
cyclic-import,
duplicate-code,
locally-disabled,
no-else-return,
not-context-manager,
too-few-public-methods,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-many-lines,
too-many-locals,
too-many-public-methods,
too-many-return-statements,
too-many-statements,
unused-argument,
consider-using-with
[EXCEPTIONS]
overgeneral-exceptions=builtins.Exception
[TYPECHECK]
ignored-modules = distutils

374
pyproject.toml Normal file
View File

@ -0,0 +1,374 @@
[build-system]
requires = ["setuptools~=78.1.0", "wheel~=0.46.1"]
build-backend = "setuptools.build_meta"
[project]
name = "Supervisor"
dynamic = ["version", "dependencies"]
license = { text = "Apache-2.0" }
description = "Open-source private cloud os for Home-Assistant based on HassOS"
readme = "README.md"
authors = [
{ name = "The Home Assistant Authors", email = "hello@home-assistant.io" },
]
keywords = ["docker", "home-assistant", "api"]
requires-python = ">=3.13.0"
[project.urls]
"Homepage" = "https://www.home-assistant.io/"
"Source Code" = "https://github.com/home-assistant/supervisor"
"Bug Reports" = "https://github.com/home-assistant/supervisor/issues"
"Docs: Dev" = "https://developers.home-assistant.io/"
"Discord" = "https://www.home-assistant.io/join-chat/"
"Forum" = "https://community.home-assistant.io/"
[tool.setuptools]
platforms = ["any"]
zip-safe = false
include-package-data = true
[tool.setuptools.packages.find]
include = ["supervisor*"]
[tool.pylint.MAIN]
py-version = "3.13"
# Use a conservative default here; 2 should speed up most setups and not hurt
# any too bad. Override on command line as appropriate.
jobs = 2
persistent = false
extension-pkg-allow-list = ["ciso8601"]
[tool.pylint.BASIC]
class-const-naming-style = "any"
good-names = ["id", "i", "j", "k", "ex", "Run", "_", "fp", "T", "os"]
[tool.pylint."MESSAGES CONTROL"]
# Reasons disabled:
# format - handled by ruff
# abstract-method - with intro of async there are always methods missing
# cyclic-import - doesn't test if both import on load
# duplicate-code - unavoidable
# locally-disabled - it spams too much
# too-many-* - are not enforced for the sake of readability
# too-few-* - same as too-many-*
# unused-argument - generic callbacks and setup methods create a lot of warnings
disable = [
"format",
"abstract-method",
"cyclic-import",
"duplicate-code",
"locally-disabled",
"no-else-return",
"not-context-manager",
"too-few-public-methods",
"too-many-arguments",
"too-many-branches",
"too-many-instance-attributes",
"too-many-lines",
"too-many-locals",
"too-many-public-methods",
"too-many-return-statements",
"too-many-statements",
"unused-argument",
"consider-using-with",
# Handled by ruff
# Ref: <https://github.com/astral-sh/ruff/issues/970>
"await-outside-async", # PLE1142
"bad-str-strip-call", # PLE1310
"bad-string-format-type", # PLE1307
"bidirectional-unicode", # PLE2502
"continue-in-finally", # PLE0116
"duplicate-bases", # PLE0241
"format-needs-mapping", # F502
"function-redefined", # F811
# Needed because ruff does not understand type of __all__ generated by a function
# "invalid-all-format", # PLE0605
"invalid-all-object", # PLE0604
"invalid-character-backspace", # PLE2510
"invalid-character-esc", # PLE2513
"invalid-character-nul", # PLE2514
"invalid-character-sub", # PLE2512
"invalid-character-zero-width-space", # PLE2515
"logging-too-few-args", # PLE1206
"logging-too-many-args", # PLE1205
"missing-format-string-key", # F524
"mixed-format-string", # F506
"no-method-argument", # N805
"no-self-argument", # N805
"nonexistent-operator", # B002
"nonlocal-without-binding", # PLE0117
"not-in-loop", # F701, F702
"notimplemented-raised", # F901
"return-in-init", # PLE0101
"return-outside-function", # F706
"syntax-error", # E999
"too-few-format-args", # F524
"too-many-format-args", # F522
"too-many-star-expressions", # F622
"truncated-format-string", # F501
"undefined-all-variable", # F822
"undefined-variable", # F821
"used-prior-global-declaration", # PLE0118
"yield-inside-async-function", # PLE1700
"yield-outside-function", # F704
"anomalous-backslash-in-string", # W605
"assert-on-string-literal", # PLW0129
"assert-on-tuple", # F631
"bad-format-string", # W1302, F
"bad-format-string-key", # W1300, F
"bare-except", # E722
"binary-op-exception", # PLW0711
"cell-var-from-loop", # B023
# "dangerous-default-value", # B006, ruff catches new occurrences, needs more work
"duplicate-except", # B014
"duplicate-key", # F601
"duplicate-string-formatting-argument", # F
"duplicate-value", # F
"eval-used", # PGH001
"exec-used", # S102
# "expression-not-assigned", # B018, ruff catches new occurrences, needs more work
"f-string-without-interpolation", # F541
"forgotten-debug-statement", # T100
"format-string-without-interpolation", # F
# "global-statement", # PLW0603, ruff catches new occurrences, needs more work
"global-variable-not-assigned", # PLW0602
"implicit-str-concat", # ISC001
"import-self", # PLW0406
"inconsistent-quotes", # Q000
"invalid-envvar-default", # PLW1508
"keyword-arg-before-vararg", # B026
"logging-format-interpolation", # G
"logging-fstring-interpolation", # G
"logging-not-lazy", # G
"misplaced-future", # F404
"named-expr-without-context", # PLW0131
"nested-min-max", # PLW3301
# "pointless-statement", # B018, ruff catches new occurrences, needs more work
"raise-missing-from", # TRY200
# "redefined-builtin", # A001, ruff is way more stricter, needs work
"try-except-raise", # TRY203
"unused-argument", # ARG001, we don't use it
"unused-format-string-argument", #F507
"unused-format-string-key", # F504
"unused-import", # F401
"unused-variable", # F841
"useless-else-on-loop", # PLW0120
"wildcard-import", # F403
"bad-classmethod-argument", # N804
"consider-iterating-dictionary", # SIM118
"empty-docstring", # D419
"invalid-name", # N815
"line-too-long", # E501, disabled globally
"missing-class-docstring", # D101
"missing-final-newline", # W292
"missing-function-docstring", # D103
"missing-module-docstring", # D100
"multiple-imports", #E401
"singleton-comparison", # E711, E712
"subprocess-run-check", # PLW1510
"superfluous-parens", # UP034
"ungrouped-imports", # I001
"unidiomatic-typecheck", # E721
"unnecessary-direct-lambda-call", # PLC3002
"unnecessary-lambda-assignment", # PLC3001
"unneeded-not", # SIM208
"useless-import-alias", # PLC0414
"wrong-import-order", # I001
"wrong-import-position", # E402
"comparison-of-constants", # PLR0133
"comparison-with-itself", # PLR0124
# "consider-alternative-union-syntax", # UP007, typing extension
"consider-merging-isinstance", # PLR1701
# "consider-using-alias", # UP006, typing extension
"consider-using-dict-comprehension", # C402
"consider-using-generator", # C417
"consider-using-get", # SIM401
"consider-using-set-comprehension", # C401
"consider-using-sys-exit", # PLR1722
"consider-using-ternary", # SIM108
"literal-comparison", # F632
"property-with-parameters", # PLR0206
"super-with-arguments", # UP008
"too-many-branches", # PLR0912
"too-many-return-statements", # PLR0911
"too-many-statements", # PLR0915
"trailing-comma-tuple", # COM818
"unnecessary-comprehension", # C416
"use-a-generator", # C417
"use-dict-literal", # C406
"use-list-literal", # C405
"useless-object-inheritance", # UP004
"useless-return", # PLR1711
# "no-self-use", # PLR6301 # Optional plugin, not enabled
]
[tool.pylint.REPORTS]
score = false
[tool.pylint.TYPECHECK]
ignored-modules = ["distutils"]
[tool.pylint.FORMAT]
expected-line-ending-format = "LF"
[tool.pylint.EXCEPTIONS]
overgeneral-exceptions = ["builtins.BaseException", "builtins.Exception"]
[tool.pylint.DESIGN]
max-positional-arguments = 10
[tool.pytest.ini_options]
testpaths = ["tests"]
norecursedirs = [".git"]
log_format = "%(asctime)s.%(msecs)03d %(levelname)-8s %(threadName)s %(name)s:%(filename)s:%(lineno)s %(message)s"
log_date_format = "%Y-%m-%d %H:%M:%S"
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"
filterwarnings = [
"error",
"ignore:pkg_resources is deprecated as an API:DeprecationWarning:dirhash",
"ignore::pytest.PytestUnraisableExceptionWarning",
]
[tool.ruff]
lint.select = [
"B002", # Python does not support the unary prefix increment
"B007", # Loop control variable {name} not used within loop body
"B014", # Exception handler with duplicate exception
"B023", # Function definition does not bind loop variable {name}
"B026", # Star-arg unpacking after a keyword argument is strongly discouraged
"B904", # Use raise from to specify exception cause
"C", # complexity
"COM818", # Trailing comma on bare tuple prohibited
"D", # docstrings
"DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow()
"DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts)
"E", # pycodestyle
"F", # pyflakes/autoflake
"G", # flake8-logging-format
"I", # isort
"ICN001", # import concentions; {name} should be imported as {asname}
"N804", # First argument of a class method should be named cls
"N805", # First argument of a method should be named self
"N815", # Variable {name} in class scope should not be mixedCase
"PGH004", # Use specific rule codes when using noqa
"PLC0414", # Useless import alias. Import alias does not rename original package.
"PLC", # pylint
"PLE", # pylint
"PLR", # pylint
"PLW", # pylint
"Q000", # Double quotes found but single quotes preferred
"RUF006", # Store a reference to the return value of asyncio.create_task
"S102", # Use of exec detected
"S103", # bad-file-permissions
"S108", # hardcoded-temp-file
"S306", # suspicious-mktemp-usage
"S307", # suspicious-eval-usage
"S313", # suspicious-xmlc-element-tree-usage
"S314", # suspicious-xml-element-tree-usage
"S315", # suspicious-xml-expat-reader-usage
"S316", # suspicious-xml-expat-builder-usage
"S317", # suspicious-xml-sax-usage
"S318", # suspicious-xml-mini-dom-usage
"S319", # suspicious-xml-pull-dom-usage
"S320", # suspicious-xmle-tree-usage
"S601", # paramiko-call
"S602", # subprocess-popen-with-shell-equals-true
"S604", # call-with-shell-equals-true
"S608", # hardcoded-sql-expression
"S609", # unix-command-wildcard-injection
"SIM105", # Use contextlib.suppress({exception}) instead of try-except-pass
"SIM117", # Merge with-statements that use the same scope
"SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys()
"SIM201", # Use {left} != {right} instead of not {left} == {right}
"SIM208", # Use {expr} instead of not (not {expr})
"SIM212", # Use {a} if {a} else {b} instead of {b} if not {a} else {a}
"SIM300", # Yoda conditions. Use 'age == 42' instead of '42 == age'.
"SIM401", # Use get from dict with default instead of an if block
"T100", # Trace found: {name} used
"T20", # flake8-print
"TID251", # Banned imports
"TRY004", # Prefer TypeError exception for invalid type
"TRY203", # Remove exception handler; error is immediately re-raised
"UP", # pyupgrade
"W", # pycodestyle
]
lint.ignore = [
"D202", # No blank lines allowed after function docstring
"D203", # 1 blank line required before class docstring
"D213", # Multi-line docstring summary should start at the second line
"D406", # Section name should end with a newline
"D407", # Section name underlining
"E501", # line too long
"E731", # do not assign a lambda expression, use a def
# Ignore ignored, as the rule is now back in preview/nursery, which cannot
# be ignored anymore without warnings.
# https://github.com/astral-sh/ruff/issues/7491
# "PLC1901", # Lots of false positives
# False positives https://github.com/astral-sh/ruff/issues/5386
"PLC0208", # Use a sequence type instead of a `set` when iterating over values
"PLR0911", # Too many return statements ({returns} > {max_returns})
"PLR0912", # Too many branches ({branches} > {max_branches})
"PLR0913", # Too many arguments to function call ({c_args} > {max_args})
"PLR0915", # Too many statements ({statements} > {max_statements})
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
"UP006", # keep type annotation style as is
"UP007", # keep type annotation style as is
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
# May conflict with the formatter, https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
"W191",
"E111",
"E114",
"E117",
"D206",
"D300",
"Q000",
"Q001",
"Q002",
"Q003",
"COM812",
"COM819",
"ISC001",
"ISC002",
# Disabled because ruff does not understand type of __all__ generated by a function
"PLE0605",
]
[tool.ruff.lint.flake8-import-conventions.extend-aliases]
voluptuous = "vol"
[tool.ruff.lint.flake8-pytest-style]
fixture-parentheses = false
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"pytz".msg = "use zoneinfo instead"
[tool.ruff.lint.isort]
force-sort-within-sections = true
section-order = [
"future",
"standard-library",
"third-party",
"first-party",
"local-folder",
]
forced-separate = ["tests"]
known-first-party = ["supervisor", "tests"]
combine-as-imports = true
split-on-trailing-comma = false
[tool.ruff.lint.per-file-ignores]
# DBus Service Mocks must use typing and names understood by dbus-fast
"tests/dbus_service_mocks/*.py" = ["F722", "F821", "N815"]
[tool.ruff.lint.mccabe]
max-complexity = 25

View File

@ -1,6 +0,0 @@
[pytest]
asyncio_mode = auto
filterwarnings =
error
ignore:pkg_resources is deprecated as an API:DeprecationWarning:dirhash
ignore::pytest.PytestUnraisableExceptionWarning

View File

@ -1,27 +1,30 @@
aiodns==3.1.1
aiohttp==3.9.1
aiohttp-fast-url-dispatcher==0.3.0
async_timeout==4.0.3
aiodns==3.2.0
aiohttp==3.11.16
atomicwrites-homeassistant==1.4.1
attrs==23.1.0
awesomeversion==23.11.0
attrs==25.3.0
awesomeversion==24.6.0
blockbuster==1.5.24
brotli==1.1.0
ciso8601==2.3.1
colorlog==6.8.0
cpe==1.2.1
cryptography==41.0.7
debugpy==1.8.0
deepmerge==1.1.1
dirhash==0.2.1
docker==7.0.0
ciso8601==2.3.2
colorlog==6.9.0
cpe==1.3.1
cryptography==44.0.2
debugpy==1.8.14
deepmerge==2.0
dirhash==0.5.0
docker==7.1.0
faust-cchardet==2.1.19
gitpython==3.1.40
jinja2==3.1.2
pulsectl==23.5.2
pyudev==0.24.1
PyYAML==6.0.1
securetar==2023.12.0
sentry-sdk==1.39.1
voluptuous==0.14.1
dbus-fast==2.21.0
typing_extensions==4.9.0
gitpython==3.1.44
jinja2==3.1.6
log-rate-limit==1.4.2
orjson==3.10.16
pulsectl==24.12.0
pyudev==0.24.3
PyYAML==6.0.2
requests==2.32.3
securetar==2025.2.1
sentry-sdk==2.26.1
setuptools==78.1.0
voluptuous==0.15.2
dbus-fast==2.44.1
zlib-fast==0.2.1

View File

@ -1,16 +1,12 @@
black==23.12.1
coverage==7.4.0
flake8-docstrings==1.7.0
flake8==6.1.0
pre-commit==3.6.0
pydocstyle==6.3.0
pylint==3.0.3
pytest-aiohttp==1.0.5
pytest-asyncio==0.18.3
pytest-cov==4.1.0
pytest-timeout==2.2.0
pytest==7.4.3
pyupgrade==3.15.0
time-machine==2.13.0
typing_extensions==4.9.0
urllib3==2.1.0
astroid==3.3.9
coverage==7.8.0
pre-commit==4.2.0
pylint==3.3.6
pytest-aiohttp==1.1.0
pytest-asyncio==0.25.2
pytest-cov==6.1.1
pytest-timeout==2.3.1
pytest==8.3.5
ruff==0.11.6
time-machine==2.16.0
urllib3==2.4.0

View File

@ -1,30 +0,0 @@
#!/bin/bash
source "/etc/supervisor_scripts/common"
set -e
# Update frontend
git submodule update --init --recursive --remote
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
cd home-assistant-polymer
nvm install
script/bootstrap
# Download translations
start_docker
./script/translations_download
# build frontend
cd hassio
./script/build_hassio
# Copy frontend
rm -rf ../../supervisor/api/panel/*
cp -rf build/* ../../supervisor/api/panel/
# Reset frontend git
cd ..
git reset --hard HEAD
stop_docker

View File

@ -1,31 +0,0 @@
[isort]
multi_line_output = 3
include_trailing_comma=True
force_grid_wrap=0
line_length=88
indent = " "
force_sort_within_sections = true
sections = FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
default_section = THIRDPARTY
forced_separate = tests
combine_as_imports = true
use_parentheses = true
known_first_party = supervisor,tests
[flake8]
exclude = .venv,.git,.tox,docs,venv,bin,lib,deps,build
doctests = True
max-line-length = 88
# E501: line too long
# W503: Line break occurred before a binary operator
# E203: Whitespace before ':'
# D202 No blank lines allowed after function docstring
# W504 line break after binary operator
ignore =
E501,
W503,
E203,
D202,
W504
per-file-ignores =
tests/dbus_service_mocks/*.py: F821,F722

View File

@ -1,48 +1,28 @@
"""Home Assistant Supervisor setup."""
from pathlib import Path
import re
from setuptools import setup
from supervisor.const import SUPERVISOR_VERSION
RE_SUPERVISOR_VERSION = re.compile(r"^SUPERVISOR_VERSION =\s*(.+)$")
SUPERVISOR_DIR = Path(__file__).parent
REQUIREMENTS_FILE = SUPERVISOR_DIR / "requirements.txt"
CONST_FILE = SUPERVISOR_DIR / "supervisor/const.py"
REQUIREMENTS = REQUIREMENTS_FILE.read_text(encoding="utf-8")
CONSTANTS = CONST_FILE.read_text(encoding="utf-8")
def _get_supervisor_version():
for line in CONSTANTS.split("/n"):
if match := RE_SUPERVISOR_VERSION.match(line):
return match.group(1)
return "9999.09.9.dev9999"
setup(
name="Supervisor",
version=SUPERVISOR_VERSION,
license="BSD License",
author="The Home Assistant Authors",
author_email="hello@home-assistant.io",
url="https://home-assistant.io/",
description=("Open-source private cloud os for Home-Assistant" " based on HassOS"),
long_description=(
"A maintainless private cloud operator system that"
"setup a Home-Assistant instance. Based on HassOS"
),
keywords=["docker", "home-assistant", "api"],
zip_safe=False,
platforms="any",
packages=[
"supervisor.addons",
"supervisor.api",
"supervisor.backups",
"supervisor.dbus.network",
"supervisor.dbus.network.setting",
"supervisor.dbus",
"supervisor.discovery.services",
"supervisor.discovery",
"supervisor.docker",
"supervisor.homeassistant",
"supervisor.host",
"supervisor.jobs",
"supervisor.misc",
"supervisor.plugins",
"supervisor.resolution.checks",
"supervisor.resolution.evaluations",
"supervisor.resolution.fixups",
"supervisor.resolution",
"supervisor.security",
"supervisor.services.modules",
"supervisor.services",
"supervisor.store",
"supervisor.utils",
"supervisor",
],
include_package_data=True,
version=_get_supervisor_version(),
dependencies=REQUIREMENTS.split("/n"),
)

View File

@ -1,12 +1,22 @@
"""Main file for Supervisor."""
import asyncio
from concurrent.futures import ThreadPoolExecutor
import logging
from pathlib import Path
import sys
from supervisor import bootstrap
from supervisor.utils.logging import activate_log_queue_handler
import zlib_fast
# Enable fast zlib before importing supervisor
zlib_fast.enable()
# pylint: disable=wrong-import-position
from supervisor import bootstrap # noqa: E402
from supervisor.utils.blockbuster import activate_blockbuster # noqa: E402
from supervisor.utils.logging import activate_log_queue_handler # noqa: E402
# pylint: enable=wrong-import-position
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -44,10 +54,11 @@ if __name__ == "__main__":
_LOGGER.info("Initializing Supervisor setup")
coresys = loop.run_until_complete(bootstrap.initialize_coresys())
loop.set_debug(coresys.config.debug)
if coresys.config.detect_blocking_io:
activate_blockbuster()
loop.run_until_complete(coresys.core.connect())
bootstrap.supervisor_debugger(coresys)
bootstrap.migrate_system_env(coresys)
loop.run_until_complete(bootstrap.supervisor_debugger(coresys))
# Signal health startup for container
run_os_startup_check_cleanup()

View File

@ -1,9 +1,12 @@
"""Init file for Supervisor add-ons."""
import asyncio
from collections.abc import Awaitable
from contextlib import suppress
from copy import deepcopy
from datetime import datetime
import errno
from functools import partial
from ipaddress import IPv4Address
import logging
from pathlib import Path, PurePath
@ -15,11 +18,14 @@ from tempfile import TemporaryDirectory
from typing import Any, Final
import aiohttp
from awesomeversion import AwesomeVersion, AwesomeVersionCompareException
from deepmerge import Merger
from securetar import atomic_contents_add, secure_path
from securetar import AddFileError, atomic_contents_add, secure_path
import voluptuous as vol
from voluptuous.humanize import humanize_error
from supervisor.utils.dt import utc_from_timestamp
from ..bus import EventListener
from ..const import (
ATTR_ACCESS_TOKEN,
@ -42,13 +48,17 @@ from ..const import (
ATTR_SLUG,
ATTR_STATE,
ATTR_SYSTEM,
ATTR_SYSTEM_MANAGED,
ATTR_SYSTEM_MANAGED_CONFIG_ENTRY,
ATTR_TYPE,
ATTR_USER,
ATTR_UUID,
ATTR_VERSION,
ATTR_VERSION_TIMESTAMP,
ATTR_WATCHDOG,
DNS_SUFFIX,
AddonBoot,
AddonBootConfig,
AddonStartup,
AddonState,
BusEvent,
@ -72,12 +82,13 @@ from ..hardware.data import Device
from ..homeassistant.const import WSEvent, WSType
from ..jobs.const import JobExecutionLimit
from ..jobs.decorator import Job
from ..resolution.const import UnhealthyReason
from ..resolution.const import ContextType, IssueType, UnhealthyReason
from ..resolution.data import Issue
from ..store.addon import AddonStore
from ..utils import check_port
from ..utils.apparmor import adjust_profile
from ..utils.json import read_json_file, write_json_file
from ..utils.sentry import capture_exception
from ..utils.sentry import async_capture_exception
from .const import (
WATCHDOG_MAX_ATTEMPTS,
WATCHDOG_RETRY_SECONDS,
@ -129,17 +140,31 @@ class Addon(AddonModel):
super().__init__(coresys, slug)
self.instance: DockerAddon = DockerAddon(coresys, self)
self._state: AddonState = AddonState.UNKNOWN
self._manual_stop: bool = (
self.sys_hardware.helper.last_boot != self.sys_config.last_boot
)
self._manual_stop: bool = False
self._listeners: list[EventListener] = []
self._startup_event = asyncio.Event()
self._startup_task: asyncio.Task | None = None
self._boot_failed_issue = Issue(
IssueType.BOOT_FAIL, ContextType.ADDON, reference=self.slug
)
self._device_access_missing_issue = Issue(
IssueType.DEVICE_ACCESS_MISSING, ContextType.ADDON, reference=self.slug
)
def __repr__(self) -> str:
"""Return internal representation."""
return f"<Addon: {self.slug}>"
@property
def boot_failed_issue(self) -> Issue:
"""Get issue used if start on boot failed."""
return self._boot_failed_issue
@property
def device_access_missing_issue(self) -> Issue:
"""Get issue used if device access is missing and can't be automatically added."""
return self._device_access_missing_issue
@property
def state(self) -> AddonState:
"""Return state of the add-on."""
@ -157,6 +182,20 @@ class Addon(AddonModel):
if new_state == AddonState.STARTED or old_state == AddonState.STARTUP:
self._startup_event.set()
# Dismiss boot failed issue if present and we started
if (
new_state == AddonState.STARTED
and self.boot_failed_issue in self.sys_resolution.issues
):
self.sys_resolution.dismiss_issue(self.boot_failed_issue)
# Dismiss device access missing issue if present and we stopped
if (
new_state == AddonState.STOPPED
and self.device_access_missing_issue in self.sys_resolution.issues
):
self.sys_resolution.dismiss_issue(self.device_access_missing_issue)
self.sys_homeassistant.websocket.send_message(
{
ATTR_TYPE: WSType.SUPERVISOR_EVENT,
@ -175,6 +214,13 @@ class Addon(AddonModel):
async def load(self) -> None:
"""Async initialize of object."""
self._manual_stop = (
await self.sys_hardware.helper.last_boot() != self.sys_config.last_boot
)
if self.is_detached:
await super().refresh_path_cache()
self._listeners.append(
self.sys_bus.register_event(
BusEvent.DOCKER_CONTAINER_STATE_CHANGE, self.container_state_changed
@ -187,9 +233,20 @@ class Addon(AddonModel):
)
await self._check_ingress_port()
with suppress(DockerError):
default_image = self._image(self.data)
try:
await self.instance.attach(version=self.version)
# Ensure we are using correct image for this system
await self.instance.check_image(self.version, default_image, self.arch)
except DockerError:
_LOGGER.info("No %s addon Docker image %s found", self.slug, self.image)
with suppress(DockerError):
await self.instance.install(self.version, default_image, arch=self.arch)
self.persist[ATTR_IMAGE] = default_image
await self.save_persist()
@property
def ip_address(self) -> IPv4Address:
"""Return IP of add-on instance."""
@ -225,13 +282,41 @@ class Addon(AddonModel):
"""Return True if add-on is detached."""
return self.slug not in self.sys_store.data.addons
@property
def with_icon(self) -> bool:
"""Return True if an icon exists."""
if self.is_detached or not self.addon_store:
return super().with_icon
return self.addon_store.with_icon
@property
def with_logo(self) -> bool:
"""Return True if a logo exists."""
if self.is_detached or not self.addon_store:
return super().with_logo
return self.addon_store.with_logo
@property
def with_changelog(self) -> bool:
"""Return True if a changelog exists."""
if self.is_detached or not self.addon_store:
return super().with_changelog
return self.addon_store.with_changelog
@property
def with_documentation(self) -> bool:
"""Return True if a documentation exists."""
if self.is_detached or not self.addon_store:
return super().with_documentation
return self.addon_store.with_documentation
@property
def available(self) -> bool:
"""Return True if this add-on is available on this platform."""
return self._available(self.data_store)
@property
def version(self) -> str | None:
def version(self) -> AwesomeVersion:
"""Return installed version."""
return self.persist[ATTR_VERSION]
@ -261,7 +346,9 @@ class Addon(AddonModel):
@property
def boot(self) -> AddonBoot:
"""Return boot config with prio local settings."""
"""Return boot config with prio local settings unless config is forced."""
if self.boot_config == AddonBootConfig.MANUAL_ONLY:
return super().boot
return self.persist.get(ATTR_BOOT, super().boot)
@boot.setter
@ -269,6 +356,13 @@ class Addon(AddonModel):
"""Store user boot options."""
self.persist[ATTR_BOOT] = value
# Dismiss boot failed issue if present and boot at start disabled
if (
value == AddonBoot.MANUAL
and self._boot_failed_issue in self.sys_resolution.issues
):
self.sys_resolution.dismiss_issue(self._boot_failed_issue)
@property
def auto_update(self) -> bool:
"""Return if auto update is enable."""
@ -279,6 +373,28 @@ class Addon(AddonModel):
"""Set auto update."""
self.persist[ATTR_AUTO_UPDATE] = value
@property
def auto_update_available(self) -> bool:
"""Return if it is safe to auto update addon."""
if not self.need_update or not self.auto_update:
return False
for version in self.breaking_versions:
try:
# Must update to latest so if true update crosses a breaking version
if self.version < version:
return False
except AwesomeVersionCompareException:
# If version scheme changed, we may get compare exception
# If latest version >= breaking version then assume update will
# cross it as the version scheme changes
# If both versions have compare exception, ignore as its in the past
with suppress(AwesomeVersionCompareException):
if self.latest_version >= version:
return False
return True
@property
def watchdog(self) -> bool:
"""Return True if watchdog is enable."""
@ -294,6 +410,37 @@ class Addon(AddonModel):
else:
self.persist[ATTR_WATCHDOG] = value
@property
def system_managed(self) -> bool:
"""Return True if addon is managed by Home Assistant."""
return self.persist[ATTR_SYSTEM_MANAGED]
@system_managed.setter
def system_managed(self, value: bool) -> None:
"""Set system managed enable/disable."""
if not value and self.system_managed_config_entry:
self.system_managed_config_entry = None
self.persist[ATTR_SYSTEM_MANAGED] = value
@property
def system_managed_config_entry(self) -> str | None:
"""Return id of config entry managing this addon (if any)."""
if not self.system_managed:
return None
return self.persist.get(ATTR_SYSTEM_MANAGED_CONFIG_ENTRY)
@system_managed_config_entry.setter
def system_managed_config_entry(self, value: str | None) -> None:
"""Set ID of config entry managing this addon."""
if not self.system_managed:
_LOGGER.warning(
"Ignoring system managed config entry for %s because it is not system managed",
self.slug,
)
else:
self.persist[ATTR_SYSTEM_MANAGED_CONFIG_ENTRY] = value
@property
def uuid(self) -> str:
"""Return an API token for this add-on."""
@ -317,10 +464,15 @@ class Addon(AddonModel):
return None
@property
def latest_version(self) -> str:
def latest_version(self) -> AwesomeVersion:
"""Return version of add-on."""
return self.data_store[ATTR_VERSION]
@property
def latest_version_timestamp(self) -> datetime:
"""Return when latest version was first seen."""
return utc_from_timestamp(self.data_store[ATTR_VERSION_TIMESTAMP])
@property
def protected(self) -> bool:
"""Return if add-on is in protected mode."""
@ -366,9 +518,8 @@ class Addon(AddonModel):
def webui(self) -> str | None:
"""Return URL to webui or None."""
url = super().webui
if not url:
if not url or not (webui := RE_WEBUI.match(url)):
return None
webui = RE_WEBUI.match(url)
# extract arguments
t_port = webui.group("t_port")
@ -517,16 +668,15 @@ class Addon(AddonModel):
"""Is add-on loaded."""
return bool(self._listeners)
def save_persist(self) -> None:
async def save_persist(self) -> None:
"""Save data of add-on."""
self.sys_addons.data.save_data()
await self.sys_addons.data.save_data()
async def watchdog_application(self) -> bool:
"""Return True if application is running."""
url = super().watchdog
if not url:
url = self.watchdog_url
if not url or not (application := RE_WATCHDOG.match(url)):
return True
application = RE_WATCHDOG.match(url)
# extract arguments
t_port = int(application.group("t_port"))
@ -535,8 +685,10 @@ class Addon(AddonModel):
s_suffix = application.group("s_suffix") or ""
# search host port for this docker port
if self.host_network:
port = self.ports.get(f"{t_port}/tcp", t_port)
if self.host_network and self.ports:
port = self.ports.get(f"{t_port}/tcp")
if port is None:
port = t_port
else:
port = t_port
@ -570,7 +722,7 @@ class Addon(AddonModel):
try:
options = self.schema.validate(self.options)
write_json_file(self.path_options, options)
await self.sys_run_in_executor(write_json_file, self.path_options, options)
except vol.Invalid as ex:
_LOGGER.error(
"Add-on %s has invalid options: %s",
@ -601,9 +753,12 @@ class Addon(AddonModel):
for listener in self._listeners:
self.sys_bus.remove_listener(listener)
if self.path_data.is_dir():
_LOGGER.info("Removing add-on data folder %s", self.path_data)
await remove_data(self.path_data)
def remove_data_dir():
if self.path_data.is_dir():
_LOGGER.info("Removing add-on data folder %s", self.path_data)
remove_data(self.path_data)
await self.sys_run_in_executor(remove_data_dir)
async def _check_ingress_port(self):
"""Assign a ingress port if dynamic port selection is used."""
@ -622,14 +777,20 @@ class Addon(AddonModel):
)
async def install(self) -> None:
"""Install and setup this addon."""
self.sys_addons.data.install(self.addon_store)
if not self.addon_store:
raise AddonsError("Missing from store, cannot install!")
await self.sys_addons.data.install(self.addon_store)
await self.load()
if not self.path_data.is_dir():
_LOGGER.info(
"Creating Home Assistant add-on data folder %s", self.path_data
)
self.path_data.mkdir()
def setup_data():
if not self.path_data.is_dir():
_LOGGER.info(
"Creating Home Assistant add-on data folder %s", self.path_data
)
self.path_data.mkdir()
await self.sys_run_in_executor(setup_data)
# Setup/Fix AppArmor profile
await self.install_apparmor()
@ -640,7 +801,7 @@ class Addon(AddonModel):
self.latest_version, self.addon_store.image, arch=self.arch
)
except DockerError as err:
self.sys_addons.data.uninstall(self)
await self.sys_addons.data.uninstall(self)
raise AddonsError() from err
# Add to addon manager
@ -655,10 +816,12 @@ class Addon(AddonModel):
limit=JobExecutionLimit.GROUP_ONCE,
on_condition=AddonsJobError,
)
async def uninstall(self) -> None:
async def uninstall(
self, *, remove_config: bool, remove_image: bool = True
) -> None:
"""Uninstall and cleanup this addon."""
try:
await self.instance.remove()
await self.instance.remove(remove_image=remove_image)
except DockerError as err:
raise AddonsError() from err
@ -666,10 +829,17 @@ class Addon(AddonModel):
await self.unload()
# Cleanup audio settings
if self.path_pulse.exists():
with suppress(OSError):
self.path_pulse.unlink()
def cleanup_config_and_audio():
# Remove config if present and requested
if self.addon_config_used and remove_config:
remove_data(self.path_config)
# Cleanup audio settings
if self.path_pulse.exists():
with suppress(OSError):
self.path_pulse.unlink()
await self.sys_run_in_executor(cleanup_config_and_audio)
# Cleanup AppArmor profile
with suppress(HostAppArmorError):
@ -683,23 +853,23 @@ class Addon(AddonModel):
# Cleanup Ingress dynamic port assignment
if self.with_ingress:
await self.sys_ingress.del_dynamic_port(self.slug)
self.sys_create_task(self.sys_ingress.reload())
self.sys_ingress.del_dynamic_port(self.slug)
# Cleanup discovery data
for message in self.sys_discovery.list_messages:
if message.addon != self.slug:
continue
self.sys_discovery.remove(message)
await self.sys_discovery.remove(message)
# Cleanup services data
for service in self.sys_services.list_services:
if self.slug not in service.active:
continue
service.del_service_data(self)
await service.del_service_data(self)
# Remove from addon manager
self.sys_addons.data.uninstall(self)
await self.sys_addons.data.uninstall(self)
self.sys_addons.local.pop(self.slug)
@Job(
@ -713,6 +883,9 @@ class Addon(AddonModel):
Returns a Task that completes when addon has state 'started' (see start)
if it was running. Else nothing is returned.
"""
if not self.addon_store:
raise AddonsError("Missing from store, cannot update!")
old_image = self.image
# Cache data to prevent races with other updates to global
store = self.addon_store.clone()
@ -728,7 +901,7 @@ class Addon(AddonModel):
try:
_LOGGER.info("Add-on '%s' successfully updated", self.slug)
self.sys_addons.data.update(store)
await self.sys_addons.data.update(store)
await self._check_ingress_port()
# Cleanup
@ -769,7 +942,10 @@ class Addon(AddonModel):
except DockerError as err:
raise AddonsError() from err
self.sys_addons.data.update(self.addon_store)
if self.addon_store:
await self.sys_addons.data.update(self.addon_store)
await self._check_ingress_port()
_LOGGER.info("Add-on '%s' successfully rebuilt", self.slug)
finally:
@ -781,22 +957,25 @@ class Addon(AddonModel):
)
return out
def write_pulse(self) -> None:
async def write_pulse(self) -> None:
"""Write asound config to file and return True on success."""
pulse_config = self.sys_plugins.audio.pulse_client(
input_profile=self.audio_input, output_profile=self.audio_output
)
# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
# Write pulse config
try:
def write_pulse_config():
# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
self.path_pulse.write_text(pulse_config, encoding="utf-8")
try:
await self.sys_run_in_executor(write_pulse_config)
except OSError as err:
if err.errno == errno.EBADMSG:
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error(
"Add-on %s can't write pulse/client.config: %s", self.slug, err
)
@ -808,7 +987,7 @@ class Addon(AddonModel):
async def install_apparmor(self) -> None:
"""Install or Update AppArmor profile for Add-on."""
exists_local = self.sys_host.apparmor.exists(self.slug)
exists_addon = self.path_apparmor.exists()
exists_addon = await self.sys_run_in_executor(self.path_apparmor.exists)
# Nothing to do
if not exists_local and not exists_addon:
@ -820,11 +999,21 @@ class Addon(AddonModel):
return
# Need install/update
with TemporaryDirectory(dir=self.sys_config.path_tmp) as tmp_folder:
profile_file = Path(tmp_folder, "apparmor.txt")
tmp_folder: TemporaryDirectory | None = None
def install_update_profile() -> Path:
nonlocal tmp_folder
tmp_folder = TemporaryDirectory(dir=self.sys_config.path_tmp)
profile_file = Path(tmp_folder.name, "apparmor.txt")
adjust_profile(self.slug, self.path_apparmor, profile_file)
return profile_file
try:
profile_file = await self.sys_run_in_executor(install_update_profile)
await self.sys_host.apparmor.load_profile(self.slug, profile_file)
finally:
if tmp_folder:
await self.sys_run_in_executor(tmp_folder.cleanup)
async def uninstall_apparmor(self) -> None:
"""Remove AppArmor profile for Add-on."""
@ -896,14 +1085,14 @@ class Addon(AddonModel):
# Access Token
self.persist[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
self.save_persist()
await self.save_persist()
# Options
await self.write_options()
# Sound
if self.with_audio:
self.write_pulse()
await self.write_pulse()
def _check_addon_config_dir():
if self.path_config.is_dir():
@ -1051,6 +1240,25 @@ class Addon(AddonModel):
await self._backup_command(self.backup_post)
return None
def _is_excluded_by_filter(
self, origin_path: Path, arcname: str, item_arcpath: PurePath
) -> bool:
"""Filter out files from backup based on filters provided by addon developer.
This tests the dev provided filters against the full path of the file as
Supervisor sees them using match. This is done for legacy reasons, testing
against the relative path makes more sense and may be changed in the future.
"""
full_path = origin_path / item_arcpath.relative_to(arcname)
for exclude in self.backup_exclude:
if not full_path.match(exclude):
continue
_LOGGER.debug("Ignoring %s because of %s", full_path, exclude)
return True
return False
@Job(
name="addon_backup",
limit=JobExecutionLimit.GROUP_ONCE,
@ -1062,46 +1270,45 @@ class Addon(AddonModel):
Returns a Task that completes when addon has state 'started' (see start)
for cold backup. Else nothing is returned.
"""
wait_for_start: Awaitable[None] | None = None
with TemporaryDirectory(dir=self.sys_config.path_tmp) as temp:
temp_path = Path(temp)
def _addon_backup(
store_image: bool,
metadata: dict[str, Any],
apparmor_profile: str | None,
addon_config_used: bool,
):
"""Start the backup process."""
with TemporaryDirectory(dir=self.sys_config.path_tmp) as temp:
temp_path = Path(temp)
# store local image
if self.need_build:
# store local image
if store_image:
try:
self.instance.export_image(temp_path.joinpath("image.tar"))
except DockerError as err:
raise AddonsError() from err
# Store local configs/state
try:
await self.instance.export_image(temp_path.joinpath("image.tar"))
except DockerError as err:
raise AddonsError() from err
data = {
ATTR_USER: self.persist,
ATTR_SYSTEM: self.data,
ATTR_VERSION: self.version,
ATTR_STATE: _MAP_ADDON_STATE.get(self.state, self.state),
}
# Store local configs/state
try:
write_json_file(temp_path.joinpath("addon.json"), data)
except ConfigurationFileError as err:
raise AddonsError(
f"Can't save meta for {self.slug}", _LOGGER.error
) from err
# Store AppArmor Profile
if self.sys_host.apparmor.exists(self.slug):
profile = temp_path.joinpath("apparmor.txt")
try:
await self.sys_host.apparmor.backup_profile(self.slug, profile)
except HostAppArmorError as err:
write_json_file(temp_path.joinpath("addon.json"), metadata)
except ConfigurationFileError as err:
raise AddonsError(
"Can't backup AppArmor profile", _LOGGER.error
f"Can't save meta for {self.slug}", _LOGGER.error
) from err
# write into tarfile
def _write_tarfile():
"""Write tar inside loop."""
# Store AppArmor Profile
if apparmor_profile:
profile_backup_file = temp_path.joinpath("apparmor.txt")
try:
self.sys_host.apparmor.backup_profile(
apparmor_profile, profile_backup_file
)
except HostAppArmorError as err:
raise AddonsError(
"Can't backup AppArmor profile", _LOGGER.error
) from err
# Write tarfile
with tar_file as backup:
# Backup metadata
backup.add(temp, arcname=".")
@ -1110,32 +1317,56 @@ class Addon(AddonModel):
atomic_contents_add(
backup,
self.path_data,
excludes=self.backup_exclude,
file_filter=partial(
self._is_excluded_by_filter, self.path_data, "data"
),
arcname="data",
)
# Backup config
if self.addon_config_used:
if addon_config_used:
atomic_contents_add(
backup,
self.path_config,
excludes=self.backup_exclude,
file_filter=partial(
self._is_excluded_by_filter, self.path_config, "config"
),
arcname="config",
)
is_running = await self.begin_backup()
try:
_LOGGER.info("Building backup for add-on %s", self.slug)
await self.sys_run_in_executor(_write_tarfile)
except (tarfile.TarError, OSError) as err:
raise AddonsError(
f"Can't write tarfile {tar_file}: {err}", _LOGGER.error
) from err
finally:
if is_running:
wait_for_start = await self.end_backup()
wait_for_start: asyncio.Task | None = None
data = {
ATTR_USER: self.persist,
ATTR_SYSTEM: self.data,
ATTR_VERSION: self.version,
ATTR_STATE: _MAP_ADDON_STATE.get(self.state, self.state),
}
apparmor_profile = (
self.slug if self.sys_host.apparmor.exists(self.slug) else None
)
was_running = await self.begin_backup()
try:
_LOGGER.info("Building backup for add-on %s", self.slug)
await self.sys_run_in_executor(
partial(
_addon_backup,
store_image=self.need_build,
metadata=data,
apparmor_profile=apparmor_profile,
addon_config_used=self.addon_config_used,
)
)
_LOGGER.info("Finish backup for addon %s", self.slug)
except (tarfile.TarError, OSError, AddFileError) as err:
raise AddonsError(
f"Can't write tarfile {tar_file}: {err}", _LOGGER.error
) from err
finally:
if was_running:
wait_for_start = await self.end_backup()
_LOGGER.info("Finish backup for addon %s", self.slug)
return wait_for_start
@Job(
@ -1149,27 +1380,37 @@ class Addon(AddonModel):
Returns a Task that completes when addon has state 'started' (see start)
if addon is started after restore. Else nothing is returned.
"""
wait_for_start: Awaitable[None] | None = None
with TemporaryDirectory(dir=self.sys_config.path_tmp) as temp:
# extract backup
def _extract_tarfile():
"""Extract tar backup."""
wait_for_start: asyncio.Task | None = None
# Extract backup
def _extract_tarfile() -> tuple[TemporaryDirectory, dict[str, Any]]:
"""Extract tar backup."""
tmp = TemporaryDirectory(dir=self.sys_config.path_tmp)
try:
with tar_file as backup:
backup.extractall(path=Path(temp), members=secure_path(backup))
backup.extractall(
path=tmp.name,
members=secure_path(backup),
filter="fully_trusted",
)
try:
await self.sys_run_in_executor(_extract_tarfile)
except tarfile.TarError as err:
raise AddonsError(
f"Can't read tarfile {tar_file}: {err}", _LOGGER.error
) from err
data = read_json_file(Path(tmp.name, "addon.json"))
except:
tmp.cleanup()
raise
# Read backup data
try:
data = read_json_file(Path(temp, "addon.json"))
except ConfigurationFileError as err:
raise AddonsError() from err
return tmp, data
try:
tmp, data = await self.sys_run_in_executor(_extract_tarfile)
except tarfile.TarError as err:
raise AddonsError(
f"Can't read tarfile {tar_file}: {err}", _LOGGER.error
) from err
except ConfigurationFileError as err:
raise AddonsError() from err
try:
# Validate
try:
data = SCHEMA_ADDON_BACKUP(data)
@ -1189,7 +1430,7 @@ class Addon(AddonModel):
# Restore local add-on information
_LOGGER.info("Restore config for addon %s", self.slug)
restore_image = self._image(data[ATTR_SYSTEM])
self.sys_addons.data.restore(
await self.sys_addons.data.restore(
self.slug, data[ATTR_USER], data[ATTR_SYSTEM], restore_image
)
@ -1203,7 +1444,7 @@ class Addon(AddonModel):
if not await self.instance.exists():
_LOGGER.info("Restore/Install of image for addon %s", self.slug)
image_file = Path(temp, "image.tar")
image_file = Path(tmp.name, "image.tar")
if image_file.is_file():
with suppress(DockerError):
await self.instance.import_image(image_file)
@ -1217,29 +1458,29 @@ class Addon(AddonModel):
_LOGGER.info("Restore/Update of image for addon %s", self.slug)
with suppress(DockerError):
await self.instance.update(version, restore_image, self.arch)
self._check_ingress_port()
await self._check_ingress_port()
# Restore data and config
def _restore_data():
"""Restore data and config."""
temp_data = Path(temp, "data")
_LOGGER.info("Restoring data and config for addon %s", self.slug)
if self.path_data.is_dir():
remove_data(self.path_data)
if self.path_config.is_dir():
remove_data(self.path_config)
temp_data = Path(tmp.name, "data")
if temp_data.is_dir():
shutil.copytree(temp_data, self.path_data, symlinks=True)
else:
self.path_data.mkdir()
temp_config = Path(temp, "config")
temp_config = Path(tmp.name, "config")
if temp_config.is_dir():
shutil.copytree(temp_config, self.path_config, symlinks=True)
elif self.addon_config_used:
self.path_config.mkdir()
_LOGGER.info("Restoring data and config for addon %s", self.slug)
if self.path_data.is_dir():
await remove_data(self.path_data)
if self.path_config.is_dir():
await remove_data(self.path_config)
try:
await self.sys_run_in_executor(_restore_data)
except shutil.Error as err:
@ -1248,27 +1489,29 @@ class Addon(AddonModel):
) from err
# Restore AppArmor
profile_file = Path(temp, "apparmor.txt")
if profile_file.exists():
profile_file = Path(tmp.name, "apparmor.txt")
if await self.sys_run_in_executor(profile_file.exists):
try:
await self.sys_host.apparmor.load_profile(
self.slug, profile_file
)
except HostAppArmorError as err:
_LOGGER.error(
"Can't restore AppArmor profile for add-on %s", self.slug
"Can't restore AppArmor profile for add-on %s",
self.slug,
)
raise AddonsError() from err
finally:
# Is add-on loaded
if not self.loaded:
await self.load()
finally:
# Run add-on
if data[ATTR_STATE] == AddonState.STARTED:
wait_for_start = await self.start()
finally:
await self.sys_run_in_executor(tmp.cleanup)
_LOGGER.info("Finished restore for add-on %s", self.slug)
return wait_for_start
@ -1309,7 +1552,7 @@ class Addon(AddonModel):
except AddonsError as err:
attempts = attempts + 1
_LOGGER.error("Watchdog restart of addon %s failed!", self.name)
capture_exception(err)
await async_capture_exception(err)
else:
break
@ -1358,3 +1601,9 @@ class Addon(AddonModel):
ContainerState.UNHEALTHY,
]:
await self._restart_after_problem(event.state)
def refresh_path_cache(self) -> Awaitable[None]:
"""Refresh cache of existing paths."""
if self.is_detached or not self.addon_store:
return super().refresh_path_cache()
return self.addon_store.refresh_path_cache()

View File

@ -1,9 +1,10 @@
"""Supervisor add-on build environment."""
from __future__ import annotations
from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
from awesomeversion import AwesomeVersion
@ -22,7 +23,7 @@ from ..utils.common import FileConfiguration, find_one_filetype
from .validate import SCHEMA_BUILD_CONFIG
if TYPE_CHECKING:
from . import AnyAddon
from .manager import AnyAddon
class AddonBuild(FileConfiguration, CoreSysAttributes):
@ -33,23 +34,36 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
self.coresys: CoreSys = coresys
self.addon = addon
# Search for build file later in executor
super().__init__(None, SCHEMA_BUILD_CONFIG)
def _get_build_file(self) -> Path:
"""Get build file.
Must be run in executor.
"""
try:
build_file = find_one_filetype(
return find_one_filetype(
self.addon.path_location, "build", FILE_SUFFIX_CONFIGURATION
)
except ConfigurationFileError:
build_file = self.addon.path_location / "build.json"
return self.addon.path_location / "build.json"
super().__init__(build_file, SCHEMA_BUILD_CONFIG)
async def read_data(self) -> None:
"""Load data from file."""
if not self._file:
self._file = await self.sys_run_in_executor(self._get_build_file)
def save_data(self):
await super().read_data()
async def save_data(self):
"""Ignore save function."""
raise RuntimeError()
@cached_property
def arch(self) -> str:
"""Return arch of the add-on."""
return self.sys_arch.match(self.addon.arch)
return self.sys_arch.match([self.addon.arch])
@property
def base_image(self) -> str:
@ -67,13 +81,6 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
)
return self._data[ATTR_BUILD_FROM][self.arch]
@property
def dockerfile(self) -> Path:
"""Return Dockerfile path."""
if self.addon.path_location.joinpath(f"Dockerfile.{self.arch}").exists():
return self.addon.path_location.joinpath(f"Dockerfile.{self.arch}")
return self.addon.path_location.joinpath("Dockerfile")
@property
def squash(self) -> bool:
"""Return True or False if squash is active."""
@ -89,25 +96,40 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
"""Return additional Docker labels."""
return self._data[ATTR_LABELS]
@property
def is_valid(self) -> bool:
def get_dockerfile(self) -> Path:
"""Return Dockerfile path.
Must be run in executor.
"""
if self.addon.path_location.joinpath(f"Dockerfile.{self.arch}").exists():
return self.addon.path_location.joinpath(f"Dockerfile.{self.arch}")
return self.addon.path_location.joinpath("Dockerfile")
async def is_valid(self) -> bool:
"""Return true if the build env is valid."""
try:
def build_is_valid() -> bool:
return all(
[
self.addon.path_location.is_dir(),
self.dockerfile.is_file(),
self.get_dockerfile().is_file(),
]
)
try:
return await self.sys_run_in_executor(build_is_valid)
except HassioArchNotFound:
return False
def get_docker_args(self, version: AwesomeVersion):
"""Create a dict with Docker build arguments."""
args = {
def get_docker_args(self, version: AwesomeVersion, image: str | None = None):
"""Create a dict with Docker build arguments.
Must be run in executor.
"""
args: dict[str, Any] = {
"path": str(self.addon.path_location),
"tag": f"{self.addon.image}:{version!s}",
"dockerfile": str(self.dockerfile),
"tag": f"{image or self.addon.image}:{version!s}",
"dockerfile": str(self.get_dockerfile()),
"pull": True,
"forcerm": not self.sys_dev,
"squash": self.squash,

View File

@ -1,4 +1,5 @@
"""Add-on static data."""
from datetime import timedelta
from enum import StrEnum
@ -28,6 +29,7 @@ class MappingType(StrEnum):
ATTR_BACKUP = "backup"
ATTR_BREAKING_VERSIONS = "breaking_versions"
ATTR_CODENOTARY = "codenotary"
ATTR_READ_ONLY = "read_only"
ATTR_PATH = "path"

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor add-on data."""
from copy import deepcopy
from typing import Any
@ -37,7 +38,7 @@ class AddonsData(FileConfiguration, CoreSysAttributes):
"""Return local add-on data."""
return self._data[ATTR_SYSTEM]
def install(self, addon: AddonStore) -> None:
async def install(self, addon: AddonStore) -> None:
"""Set addon as installed."""
self.system[addon.slug] = deepcopy(addon.data)
self.user[addon.slug] = {
@ -45,26 +46,28 @@ class AddonsData(FileConfiguration, CoreSysAttributes):
ATTR_VERSION: addon.version,
ATTR_IMAGE: addon.image,
}
self.save_data()
await self.save_data()
def uninstall(self, addon: Addon) -> None:
async def uninstall(self, addon: Addon) -> None:
"""Set add-on as uninstalled."""
self.system.pop(addon.slug, None)
self.user.pop(addon.slug, None)
self.save_data()
await self.save_data()
def update(self, addon: AddonStore) -> None:
async def update(self, addon: AddonStore) -> None:
"""Update version of add-on."""
self.system[addon.slug] = deepcopy(addon.data)
self.user[addon.slug].update(
{ATTR_VERSION: addon.version, ATTR_IMAGE: addon.image}
)
self.save_data()
await self.save_data()
def restore(self, slug: str, user: Config, system: Config, image: str) -> None:
async def restore(
self, slug: str, user: Config, system: Config, image: str
) -> None:
"""Restore data to add-on."""
self.user[slug] = deepcopy(user)
self.system[slug] = deepcopy(system)
self.user[slug][ATTR_IMAGE] = image
self.save_data()
await self.save_data()

View File

@ -1,30 +1,29 @@
"""Supervisor add-on manager."""
import asyncio
from collections.abc import Awaitable
from contextlib import suppress
import logging
import tarfile
from typing import Union
from typing import Self, Union
from attr import evolve
from ..const import AddonBoot, AddonStartup, AddonState
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
AddonConfigurationError,
AddonsError,
AddonsJobError,
AddonsNotSupportedError,
CoreDNSError,
DockerAPIError,
DockerError,
DockerNotFound,
HassioError,
HomeAssistantAPIError,
)
from ..jobs.decorator import Job, JobCondition
from ..resolution.const import ContextType, IssueType, SuggestionType
from ..store.addon import AddonStore
from ..utils import check_exception_chain
from ..utils.sentry import capture_exception
from ..utils.sentry import async_capture_exception
from .addon import Addon
from .const import ADDON_UPDATE_CONDITIONS
from .data import AddonsData
@ -75,17 +74,27 @@ class AddonManager(CoreSysAttributes):
return addon
return None
async def load_config(self) -> Self:
"""Load config in executor."""
await self.data.read_data()
return self
async def load(self) -> None:
"""Start up add-on management."""
tasks = []
# Refresh cache for all store addons
tasks: list[Awaitable[None]] = [
store.refresh_path_cache() for store in self.store.values()
]
# Load all installed addons
for slug in self.data.system:
addon = self.local[slug] = Addon(self.coresys, slug)
tasks.append(self.sys_create_task(addon.load()))
tasks.append(addon.load())
# Run initial tasks
_LOGGER.info("Found %d installed add-ons", len(tasks))
_LOGGER.info("Found %d installed add-ons", len(self.data.system))
if tasks:
await asyncio.wait(tasks)
await asyncio.gather(*tasks)
# Sync DNS
await self.sync_dns()
@ -112,15 +121,14 @@ class AddonManager(CoreSysAttributes):
try:
if start_task := await addon.start():
wait_boot.append(start_task)
except AddonsError as err:
# Check if there is an system/user issue
if check_exception_chain(
err, (DockerAPIError, DockerNotFound, AddonConfigurationError)
):
addon.boot = AddonBoot.MANUAL
addon.save_persist()
except HassioError:
pass # These are already handled
self.sys_resolution.add_issue(
evolve(addon.boot_failed_issue),
suggestions=[
SuggestionType.EXECUTE_START,
SuggestionType.DISABLE_BOOT,
],
)
else:
continue
@ -129,6 +137,19 @@ class AddonManager(CoreSysAttributes):
# Ignore exceptions from waiting for addon startup, addon errors handled elsewhere
await asyncio.gather(*wait_boot, return_exceptions=True)
# After waiting for startup, create an issue for boot addons that are error or unknown state
# Ignore stopped as single shot addons can be run at boot and this is successful exit
# Timeout waiting for startup is not a failure, addon is probably just slow
for addon in tasks:
if addon.state in {AddonState.ERROR, AddonState.UNKNOWN}:
self.sys_resolution.add_issue(
evolve(addon.boot_failed_issue),
suggestions=[
SuggestionType.EXECUTE_START,
SuggestionType.DISABLE_BOOT,
],
)
async def shutdown(self, stage: AddonStartup) -> None:
"""Shutdown addons."""
tasks: list[Addon] = []
@ -149,7 +170,7 @@ class AddonManager(CoreSysAttributes):
await addon.stop()
except Exception as err: # pylint: disable=broad-except
_LOGGER.warning("Can't stop Add-on %s: %s", addon.slug, err)
capture_exception(err)
await async_capture_exception(err)
@Job(
name="addon_manager_install",
@ -173,13 +194,22 @@ class AddonManager(CoreSysAttributes):
_LOGGER.info("Add-on '%s' successfully installed", slug)
async def uninstall(self, slug: str) -> None:
@Job(name="addon_manager_uninstall")
async def uninstall(self, slug: str, *, remove_config: bool = False) -> None:
"""Remove an add-on."""
if slug not in self.local:
_LOGGER.warning("Add-on %s is not installed", slug)
return
await self.local[slug].uninstall()
shared_image = any(
self.local[slug].image == addon.image
and self.local[slug].version == addon.version
for addon in self.installed
if addon.slug != slug
)
await self.local[slug].uninstall(
remove_config=remove_config, remove_image=not shared_image
)
_LOGGER.info("Add-on '%s' successfully removed", slug)
@ -284,7 +314,7 @@ class AddonManager(CoreSysAttributes):
if slug not in self.local:
_LOGGER.debug("Add-on %s is not local available for restore", slug)
addon = Addon(self.coresys, slug)
had_ingress = False
had_ingress: bool | None = False
else:
_LOGGER.debug("Add-on %s is local available for restore", slug)
addon = self.local[slug]
@ -359,7 +389,7 @@ class AddonManager(CoreSysAttributes):
reference=addon.slug,
suggestions=[SuggestionType.EXECUTE_REPAIR],
)
capture_exception(err)
await async_capture_exception(err)
else:
add_host_coros.append(
self.sys_plugins.dns.add_host(

View File

@ -1,14 +1,18 @@
"""Init file for Supervisor add-ons."""
from abc import ABC, abstractmethod
from collections import defaultdict
from collections.abc import Callable
from collections.abc import Awaitable, Callable
from contextlib import suppress
from datetime import datetime
import logging
from pathlib import Path
from typing import Any
from awesomeversion import AwesomeVersion, AwesomeVersionException
from supervisor.utils.dt import utc_from_timestamp
from ..const import (
ATTR_ADVANCED,
ATTR_APPARMOR,
@ -43,7 +47,7 @@ from ..const import (
ATTR_JOURNALD,
ATTR_KERNEL_MODULES,
ATTR_LEGACY,
ATTR_LOCATON,
ATTR_LOCATION,
ATTR_MACHINE,
ATTR_MAP,
ATTR_NAME,
@ -71,6 +75,7 @@ from ..const import (
ATTR_URL,
ATTR_USB,
ATTR_VERSION,
ATTR_VERSION_TIMESTAMP,
ATTR_VIDEO,
ATTR_WATCHDOG,
ATTR_WEBUI,
@ -78,6 +83,7 @@ from ..const import (
SECURITY_DISABLE,
SECURITY_PROFILE,
AddonBoot,
AddonBootConfig,
AddonStage,
AddonStartup,
)
@ -90,6 +96,7 @@ from ..utils import version_is_new_enough
from .configuration import FolderMapping
from .const import (
ATTR_BACKUP,
ATTR_BREAKING_VERSIONS,
ATTR_CODENOTARY,
ATTR_PATH,
ATTR_READ_ONLY,
@ -113,6 +120,10 @@ class AddonModel(JobGroup, ABC):
coresys, JOB_GROUP_ADDON.format_map(defaultdict(str, slug=slug)), slug
)
self.slug: str = slug
self._path_icon_exists: bool = False
self._path_logo_exists: bool = False
self._path_changelog_exists: bool = False
self._path_documentation_exists: bool = False
@property
@abstractmethod
@ -140,10 +151,15 @@ class AddonModel(JobGroup, ABC):
return self.data[ATTR_OPTIONS]
@property
def boot(self) -> AddonBoot:
"""Return boot config with prio local settings."""
def boot_config(self) -> AddonBootConfig:
"""Return boot config."""
return self.data[ATTR_BOOT]
@property
def boot(self) -> AddonBoot:
"""Return boot config with prio local settings unless config is forced."""
return AddonBoot(self.data[ATTR_BOOT])
@property
def auto_update(self) -> bool | None:
"""Return if auto update is enable."""
@ -194,18 +210,6 @@ class AddonModel(JobGroup, ABC):
"""Return description of add-on."""
return self.data[ATTR_DESCRIPTON]
@property
def long_description(self) -> str | None:
"""Return README.md as long_description."""
readme = Path(self.path_location, "README.md")
# If readme not exists
if not readme.exists():
return None
# Return data
return readme.read_text(encoding="utf-8")
@property
def repository(self) -> str:
"""Return repository of add-on."""
@ -221,6 +225,11 @@ class AddonModel(JobGroup, ABC):
"""Return latest version of add-on."""
return self.data[ATTR_VERSION]
@property
def latest_version_timestamp(self) -> datetime:
"""Return when latest version was first seen."""
return utc_from_timestamp(self.data[ATTR_VERSION_TIMESTAMP])
@property
def version(self) -> AwesomeVersion:
"""Return version of add-on."""
@ -285,7 +294,7 @@ class AddonModel(JobGroup, ABC):
return self.data.get(ATTR_WEBUI)
@property
def watchdog(self) -> str | None:
def watchdog_url(self) -> str | None:
"""Return URL to for watchdog or None."""
return self.data.get(ATTR_WATCHDOG)
@ -501,22 +510,22 @@ class AddonModel(JobGroup, ABC):
@property
def with_icon(self) -> bool:
"""Return True if an icon exists."""
return self.path_icon.exists()
return self._path_icon_exists
@property
def with_logo(self) -> bool:
"""Return True if a logo exists."""
return self.path_logo.exists()
return self._path_logo_exists
@property
def with_changelog(self) -> bool:
"""Return True if a changelog exists."""
return self.path_changelog.exists()
return self._path_changelog_exists
@property
def with_documentation(self) -> bool:
"""Return True if a documentation exists."""
return self.path_documentation.exists()
return self._path_documentation_exists
@property
def supported_arch(self) -> list[str]:
@ -560,7 +569,7 @@ class AddonModel(JobGroup, ABC):
@property
def path_location(self) -> Path:
"""Return path to this add-on."""
return Path(self.data[ATTR_LOCATON])
return Path(self.data[ATTR_LOCATION])
@property
def path_icon(self) -> Path:
@ -597,7 +606,7 @@ class AddonModel(JobGroup, ABC):
return AddonOptions(self.coresys, raw_schema, self.name, self.slug)
@property
def schema_ui(self) -> list[dict[any, any]] | None:
def schema_ui(self) -> list[dict[Any, Any]] | None:
"""Create a UI schema for add-on options."""
raw_schema = self.data[ATTR_SCHEMA]
@ -620,6 +629,37 @@ class AddonModel(JobGroup, ABC):
"""Return Signer email address for CAS."""
return self.data.get(ATTR_CODENOTARY)
@property
def breaking_versions(self) -> list[AwesomeVersion]:
"""Return breaking versions of addon."""
return self.data[ATTR_BREAKING_VERSIONS]
async def long_description(self) -> str | None:
"""Return README.md as long_description."""
def read_readme() -> str | None:
readme = Path(self.path_location, "README.md")
# If readme not exists
if not readme.exists():
return None
# Return data
return readme.read_text(encoding="utf-8")
return await self.sys_run_in_executor(read_readme)
def refresh_path_cache(self) -> Awaitable[None]:
"""Refresh cache of existing paths."""
def check_paths():
self._path_icon_exists = self.path_icon.exists()
self._path_logo_exists = self.path_logo.exists()
self._path_changelog_exists = self.path_changelog.exists()
self._path_documentation_exists = self.path_documentation.exists()
return self.sys_run_in_executor(check_paths)
def validate_availability(self) -> None:
"""Validate if addon is available for current system."""
return self._validate_availability(self.data, logger=_LOGGER.error)

View File

@ -1,4 +1,5 @@
"""Add-on Options / UI rendering."""
import hashlib
import logging
from pathlib import Path
@ -136,7 +137,7 @@ class AddonOptions(CoreSysAttributes):
) from None
# prepare range
range_args = {}
range_args: dict[str, Any] = {}
for group_name in _SCHEMA_LENGTH_PARTS:
group_value = match.group(group_name)
if group_value:
@ -389,14 +390,14 @@ class UiOptions(CoreSysAttributes):
multiple: bool = False,
) -> None:
"""UI nested dict items."""
ui_node = {
ui_node: dict[str, Any] = {
"name": key,
"type": "schema",
"optional": True,
"multiple": multiple,
}
nested_schema = []
nested_schema: list[dict[str, Any]] = []
for c_key, c_value in option_dict.items():
# Nested?
if isinstance(c_value, list):
@ -412,7 +413,7 @@ def _create_device_filter(str_filter: str) -> dict[str, Any]:
"""Generate device Filter."""
raw_filter = dict(value.split("=") for value in str_filter.split(";"))
clean_filter = {}
clean_filter: dict[str, Any] = {}
for key, value in raw_filter.items():
if key == "subsystem":
clean_filter[key] = UdevSubsystem(value)

View File

@ -1,9 +1,10 @@
"""Util add-ons functions."""
from __future__ import annotations
import asyncio
import logging
from pathlib import Path
import subprocess
from typing import TYPE_CHECKING
from ..const import ROLE_ADMIN, ROLE_MANAGER, SECURITY_DISABLE, SECURITY_PROFILE
@ -45,6 +46,7 @@ def rating_security(addon: AddonModel) -> int:
privilege in addon.privileged
for privilege in (
Capabilities.BPF,
Capabilities.CHECKPOINT_RESTORE,
Capabilities.DAC_READ_SEARCH,
Capabilities.NET_ADMIN,
Capabilities.NET_RAW,
@ -84,18 +86,20 @@ def rating_security(addon: AddonModel) -> int:
return max(min(8, rating), 1)
async def remove_data(folder: Path) -> None:
"""Remove folder and reset privileged."""
try:
proc = await asyncio.create_subprocess_exec(
"rm", "-rf", str(folder), stdout=asyncio.subprocess.DEVNULL
)
def remove_data(folder: Path) -> None:
"""Remove folder and reset privileged.
_, error_msg = await proc.communicate()
Must be run in executor.
"""
try:
subprocess.run(
["rm", "-rf", str(folder)], stdout=subprocess.DEVNULL, text=True, check=True
)
except OSError as err:
error_msg = str(err)
except subprocess.CalledProcessError as procerr:
error_msg = procerr.stderr.strip()
else:
if proc.returncode == 0:
return
return
_LOGGER.error("Can't remove Add-on Data: %s", error_msg)

View File

@ -1,4 +1,5 @@
"""Validate add-ons options schema."""
import logging
import re
import secrets
@ -54,7 +55,7 @@ from ..const import (
ATTR_KERNEL_MODULES,
ATTR_LABELS,
ATTR_LEGACY,
ATTR_LOCATON,
ATTR_LOCATION,
ATTR_MACHINE,
ATTR_MAP,
ATTR_NAME,
@ -78,6 +79,8 @@ from ..const import (
ATTR_STATE,
ATTR_STDIN,
ATTR_SYSTEM,
ATTR_SYSTEM_MANAGED,
ATTR_SYSTEM_MANAGED_CONFIG_ENTRY,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_TRANSLATIONS,
@ -95,11 +98,11 @@ from ..const import (
ROLE_ALL,
ROLE_DEFAULT,
AddonBoot,
AddonBootConfig,
AddonStage,
AddonStartup,
AddonState,
)
from ..discovery.validate import valid_discovery_service
from ..docker.const import Capabilities
from ..validate import (
docker_image,
@ -112,6 +115,7 @@ from ..validate import (
)
from .const import (
ATTR_BACKUP,
ATTR_BREAKING_VERSIONS,
ATTR_CODENOTARY,
ATTR_PATH,
ATTR_READ_ONLY,
@ -189,20 +193,6 @@ def _warn_addon_config(config: dict[str, Any]):
name,
)
invalid_services: list[str] = []
for service in config.get(ATTR_DISCOVERY, []):
try:
valid_discovery_service(service)
except vol.Invalid:
invalid_services.append(service)
if invalid_services:
_LOGGER.warning(
"Add-on lists the following unknown services for discovery: %s. Please report this to the maintainer of %s",
", ".join(invalid_services),
name,
)
return config
@ -332,7 +322,9 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_STARTUP, default=AddonStartup.APPLICATION): vol.Coerce(
AddonStartup
),
vol.Optional(ATTR_BOOT, default=AddonBoot.AUTO): vol.Coerce(AddonBoot),
vol.Optional(ATTR_BOOT, default=AddonBootConfig.AUTO): vol.Coerce(
AddonBootConfig
),
vol.Optional(ATTR_INIT, default=True): vol.Boolean(),
vol.Optional(ATTR_ADVANCED, default=False): vol.Boolean(),
vol.Optional(ATTR_STAGE, default=AddonStage.STABLE): vol.Coerce(AddonStage),
@ -422,6 +414,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Coerce(int), vol.Range(min=10, max=300)
),
vol.Optional(ATTR_JOURNALD, default=False): vol.Boolean(),
vol.Optional(ATTR_BREAKING_VERSIONS, default=list): [version_tag],
},
extra=vol.REMOVE_EXTRA,
)
@ -480,6 +473,8 @@ SCHEMA_ADDON_USER = vol.Schema(
vol.Optional(ATTR_PROTECTED, default=True): vol.Boolean(),
vol.Optional(ATTR_INGRESS_PANEL, default=False): vol.Boolean(),
vol.Optional(ATTR_WATCHDOG, default=False): vol.Boolean(),
vol.Optional(ATTR_SYSTEM_MANAGED, default=False): vol.Boolean(),
vol.Optional(ATTR_SYSTEM_MANAGED_CONFIG_ENTRY, default=None): vol.Maybe(str),
},
extra=vol.REMOVE_EXTRA,
)
@ -488,7 +483,7 @@ SCHEMA_ADDON_SYSTEM = vol.All(
_migrate_addon_config(),
_SCHEMA_ADDON_CONFIG.extend(
{
vol.Required(ATTR_LOCATON): str,
vol.Required(ATTR_LOCATION): str,
vol.Required(ATTR_REPOSITORY): str,
vol.Required(ATTR_TRANSLATIONS, default=dict): {
str: SCHEMA_ADDON_TRANSLATIONS

View File

@ -1,20 +1,23 @@
"""Init file for Supervisor RESTful API."""
from dataclasses import dataclass
from functools import partial
import logging
from pathlib import Path
from typing import Any
from aiohttp import web
from aiohttp_fast_url_dispatcher import FastUrlDispatcher, attach_fast_url_dispatcher
from aiohttp import hdrs, web
from ..const import AddonState
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import APIAddonNotInstalled
from ..exceptions import APIAddonNotInstalled, HostNotSupportedError
from ..utils.sentry import async_capture_exception
from .addons import APIAddons
from .audio import APIAudio
from .auth import APIAuth
from .backups import APIBackups
from .cli import APICli
from .const import CONTENT_TYPE_TEXT
from .discovery import APIDiscovery
from .dns import APICoreDNS
from .docker import APIDocker
@ -36,7 +39,7 @@ from .security import APISecurity
from .services import APIServices
from .store import APIStore
from .supervisor import APISupervisor
from .utils import api_process
from .utils import api_process, api_process_raw
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -45,6 +48,14 @@ MAX_CLIENT_SIZE: int = 1024**2 * 16
MAX_LINE_SIZE: int = 24570
@dataclass(slots=True, frozen=True)
class StaticResourceConfig:
"""Configuration for a static resource."""
prefix: str
path: Path
class RestAPI(CoreSysAttributes):
"""Handle RESTful API for Supervisor."""
@ -65,14 +76,19 @@ class RestAPI(CoreSysAttributes):
"max_field_size": MAX_LINE_SIZE,
},
)
attach_fast_url_dispatcher(self.webapp, FastUrlDispatcher())
# service stuff
self._runner: web.AppRunner = web.AppRunner(self.webapp, shutdown_timeout=5)
self._site: web.TCPSite | None = None
# share single host API handler for reuse in logging endpoints
self._api_host: APIHost = APIHost()
self._api_host.coresys = coresys
async def load(self) -> None:
"""Register REST API Calls."""
static_resource_configs: list[StaticResourceConfig] = []
self._register_addons()
self._register_audio()
self._register_auth()
@ -91,7 +107,7 @@ class RestAPI(CoreSysAttributes):
self._register_network()
self._register_observer()
self._register_os()
self._register_panel()
static_resource_configs.extend(self._register_panel())
self._register_proxy()
self._register_resolution()
self._register_root()
@ -100,12 +116,54 @@ class RestAPI(CoreSysAttributes):
self._register_store()
self._register_supervisor()
if static_resource_configs:
def process_configs() -> list[web.StaticResource]:
return [
web.StaticResource(config.prefix, config.path)
for config in static_resource_configs
]
for resource in await self.sys_run_in_executor(process_configs):
self.webapp.router.register_resource(resource)
await self.start()
def _register_advanced_logs(self, path: str, syslog_identifier: str):
"""Register logs endpoint for a given path, returning logs for single syslog identifier."""
self.webapp.add_routes(
[
web.get(
f"{path}/logs",
partial(self._api_host.advanced_logs, identifier=syslog_identifier),
),
web.get(
f"{path}/logs/follow",
partial(
self._api_host.advanced_logs,
identifier=syslog_identifier,
follow=True,
),
),
web.get(
f"{path}/logs/boots/{{bootid}}",
partial(self._api_host.advanced_logs, identifier=syslog_identifier),
),
web.get(
f"{path}/logs/boots/{{bootid}}/follow",
partial(
self._api_host.advanced_logs,
identifier=syslog_identifier,
follow=True,
),
),
]
)
def _register_host(self) -> None:
"""Register hostcontrol functions."""
api_host = APIHost()
api_host.coresys = self.coresys
api_host = self._api_host
self.webapp.add_routes(
[
@ -179,9 +237,13 @@ class RestAPI(CoreSysAttributes):
[
web.get("/os/info", api_os.info),
web.post("/os/update", api_os.update),
web.get("/os/config/swap", api_os.config_swap_info),
web.post("/os/config/swap", api_os.config_swap_options),
web.post("/os/config/sync", api_os.config_sync),
web.post("/os/datadisk/move", api_os.migrate_data),
web.get("/os/datadisk/list", api_os.list_data),
web.post("/os/datadisk/wipe", api_os.wipe_data),
web.post("/os/boot-slot", api_os.set_boot_slot),
]
)
@ -219,6 +281,8 @@ class RestAPI(CoreSysAttributes):
web.get("/jobs/info", api_jobs.info),
web.post("/jobs/options", api_jobs.options),
web.post("/jobs/reset", api_jobs.reset),
web.get("/jobs/{uuid}", api_jobs.job_info),
web.delete("/jobs/{uuid}", api_jobs.remove_job),
]
)
@ -257,11 +321,11 @@ class RestAPI(CoreSysAttributes):
[
web.get("/multicast/info", api_multicast.info),
web.get("/multicast/stats", api_multicast.stats),
web.get("/multicast/logs", api_multicast.logs),
web.post("/multicast/update", api_multicast.update),
web.post("/multicast/restart", api_multicast.restart),
]
)
self._register_advanced_logs("/multicast", "hassio_multicast")
def _register_hardware(self) -> None:
"""Register hardware functions."""
@ -334,6 +398,7 @@ class RestAPI(CoreSysAttributes):
web.post("/auth", api_auth.auth),
web.post("/auth/reset", api_auth.reset),
web.delete("/auth/cache", api_auth.cache),
web.get("/auth/list", api_auth.list_users),
]
)
@ -347,7 +412,6 @@ class RestAPI(CoreSysAttributes):
web.get("/supervisor/ping", api_supervisor.ping),
web.get("/supervisor/info", api_supervisor.info),
web.get("/supervisor/stats", api_supervisor.stats),
web.get("/supervisor/logs", api_supervisor.logs),
web.post("/supervisor/update", api_supervisor.update),
web.post("/supervisor/reload", api_supervisor.reload),
web.post("/supervisor/restart", api_supervisor.restart),
@ -356,6 +420,39 @@ class RestAPI(CoreSysAttributes):
]
)
async def get_supervisor_logs(*args, **kwargs):
try:
return await self._api_host.advanced_logs_handler(
*args, identifier="hassio_supervisor", **kwargs
)
except Exception as err: # pylint: disable=broad-exception-caught
# Supervisor logs are critical, so catch everything, log the exception
# and try to return Docker container logs as the fallback
_LOGGER.exception(
"Failed to get supervisor logs using advanced_logs API"
)
if not isinstance(err, HostNotSupportedError):
# No need to capture HostNotSupportedError to Sentry, the cause
# is known and reported to the user using the resolution center.
await async_capture_exception(err)
kwargs.pop("follow", None) # Follow is not supported for Docker logs
return await api_supervisor.logs(*args, **kwargs)
self.webapp.add_routes(
[
web.get("/supervisor/logs", get_supervisor_logs),
web.get(
"/supervisor/logs/follow",
partial(get_supervisor_logs, follow=True),
),
web.get("/supervisor/logs/boots/{bootid}", get_supervisor_logs),
web.get(
"/supervisor/logs/boots/{bootid}/follow",
partial(get_supervisor_logs, follow=True),
),
]
)
def _register_homeassistant(self) -> None:
"""Register Home Assistant functions."""
api_hass = APIHomeAssistant()
@ -364,7 +461,6 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/core/info", api_hass.info),
web.get("/core/logs", api_hass.logs),
web.get("/core/stats", api_hass.stats),
web.post("/core/options", api_hass.options),
web.post("/core/update", api_hass.update),
@ -376,11 +472,12 @@ class RestAPI(CoreSysAttributes):
]
)
self._register_advanced_logs("/core", "homeassistant")
# Reroute from legacy
self.webapp.add_routes(
[
web.get("/homeassistant/info", api_hass.info),
web.get("/homeassistant/logs", api_hass.logs),
web.get("/homeassistant/stats", api_hass.stats),
web.post("/homeassistant/options", api_hass.options),
web.post("/homeassistant/restart", api_hass.restart),
@ -392,6 +489,8 @@ class RestAPI(CoreSysAttributes):
]
)
self._register_advanced_logs("/homeassistant", "homeassistant")
def _register_proxy(self) -> None:
"""Register Home Assistant API Proxy."""
api_proxy = APIProxy()
@ -427,24 +526,45 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/addons", api_addons.list),
web.get("/addons", api_addons.list_addons),
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
web.post("/addons/{addon}/start", api_addons.start),
web.post("/addons/{addon}/stop", api_addons.stop),
web.post("/addons/{addon}/restart", api_addons.restart),
web.post("/addons/{addon}/options", api_addons.options),
web.post("/addons/{addon}/sys_options", api_addons.sys_options),
web.post(
"/addons/{addon}/options/validate", api_addons.options_validate
),
web.get("/addons/{addon}/options/config", api_addons.options_config),
web.post("/addons/{addon}/rebuild", api_addons.rebuild),
web.get("/addons/{addon}/logs", api_addons.logs),
web.post("/addons/{addon}/stdin", api_addons.stdin),
web.post("/addons/{addon}/security", api_addons.security),
web.get("/addons/{addon}/stats", api_addons.stats),
]
)
@api_process_raw(CONTENT_TYPE_TEXT, error_type=CONTENT_TYPE_TEXT)
async def get_addon_logs(request, *args, **kwargs):
addon = api_addons.get_addon_for_request(request)
kwargs["identifier"] = f"addon_{addon.slug}"
return await self._api_host.advanced_logs(request, *args, **kwargs)
self.webapp.add_routes(
[
web.get("/addons/{addon}/logs", get_addon_logs),
web.get(
"/addons/{addon}/logs/follow",
partial(get_addon_logs, follow=True),
),
web.get("/addons/{addon}/logs/boots/{bootid}", get_addon_logs),
web.get(
"/addons/{addon}/logs/boots/{bootid}/follow",
partial(get_addon_logs, follow=True),
),
]
)
# Legacy routing to support requests for not installed addons
api_store = APIStore()
api_store.coresys = self.coresys
@ -474,7 +594,9 @@ class RestAPI(CoreSysAttributes):
web.post("/ingress/session", api_ingress.create_session),
web.post("/ingress/validate_session", api_ingress.validate_session),
web.get("/ingress/panels", api_ingress.panels),
web.view("/ingress/{token}/{path:.*}", api_ingress.handler),
web.route(
hdrs.METH_ANY, "/ingress/{token}/{path:.*}", api_ingress.handler
),
]
)
@ -485,7 +607,7 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/backups", api_backups.list),
web.get("/backups", api_backups.list_backups),
web.get("/backups/info", api_backups.info),
web.post("/backups/options", api_backups.options),
web.post("/backups/reload", api_backups.reload),
@ -512,7 +634,7 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/services", api_services.list),
web.get("/services", api_services.list_services),
web.get("/services/{service}", api_services.get_service),
web.post("/services/{service}", api_services.set_service),
web.delete("/services/{service}", api_services.del_service),
@ -526,7 +648,7 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/discovery", api_discovery.list),
web.get("/discovery", api_discovery.list_discovery),
web.get("/discovery/{uuid}", api_discovery.get_discovery),
web.delete("/discovery/{uuid}", api_discovery.del_discovery),
web.post("/discovery", api_discovery.set_discovery),
@ -542,7 +664,6 @@ class RestAPI(CoreSysAttributes):
[
web.get("/dns/info", api_dns.info),
web.get("/dns/stats", api_dns.stats),
web.get("/dns/logs", api_dns.logs),
web.post("/dns/update", api_dns.update),
web.post("/dns/options", api_dns.options),
web.post("/dns/restart", api_dns.restart),
@ -550,18 +671,17 @@ class RestAPI(CoreSysAttributes):
]
)
self._register_advanced_logs("/dns", "hassio_dns")
def _register_audio(self) -> None:
"""Register Audio functions."""
api_audio = APIAudio()
api_audio.coresys = self.coresys
api_host = APIHost()
api_host.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/audio/info", api_audio.info),
web.get("/audio/stats", api_audio.stats),
web.get("/audio/logs", api_audio.logs),
web.post("/audio/update", api_audio.update),
web.post("/audio/restart", api_audio.restart),
web.post("/audio/reload", api_audio.reload),
@ -574,6 +694,8 @@ class RestAPI(CoreSysAttributes):
]
)
self._register_advanced_logs("/audio", "hassio_audio")
def _register_mounts(self) -> None:
"""Register mounts endpoints."""
api_mounts = APIMounts()
@ -600,7 +722,6 @@ class RestAPI(CoreSysAttributes):
web.get("/store", api_store.store_info),
web.get("/store/addons", api_store.addons_list),
web.get("/store/addons/{addon}", api_store.addons_addon_info),
web.get("/store/addons/{addon}/{version}", api_store.addons_addon_info),
web.get("/store/addons/{addon}/icon", api_store.addons_addon_icon),
web.get("/store/addons/{addon}/logo", api_store.addons_addon_logo),
web.get(
@ -622,6 +743,8 @@ class RestAPI(CoreSysAttributes):
"/store/addons/{addon}/update/{version}",
api_store.addons_addon_update,
),
# Must be below others since it has a wildcard in resource path
web.get("/store/addons/{addon}/{version}", api_store.addons_addon_info),
web.post("/store/reload", api_store.reload),
web.get("/store/repositories", api_store.repositories_list),
web.get(
@ -651,10 +774,9 @@ class RestAPI(CoreSysAttributes):
]
)
def _register_panel(self) -> None:
def _register_panel(self) -> list[StaticResourceConfig]:
"""Register panel for Home Assistant."""
panel_dir = Path(__file__).parent.joinpath("panel")
self.webapp.add_routes([web.static("/app", panel_dir)])
return [StaticResourceConfig("/app", Path(__file__).parent.joinpath("panel"))]
def _register_docker(self) -> None:
"""Register docker configuration functions."""

View File

@ -1,15 +1,15 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import asyncio
from collections.abc import Awaitable
import logging
from typing import Any
from typing import Any, TypedDict
from aiohttp import web
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..addons.addon import Addon
from ..addons.manager import AnyAddon
from ..addons.utils import rating_security
from ..const import (
ATTR_ADDONS,
@ -62,7 +62,6 @@ from ..const import (
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
ATTR_MEMORY_USAGE,
ATTR_MESSAGE,
ATTR_NAME,
ATTR_NETWORK,
ATTR_NETWORK_DESCRIPTION,
@ -71,7 +70,6 @@ from ..const import (
ATTR_OPTIONS,
ATTR_PRIVILEGED,
ATTR_PROTECTED,
ATTR_PWNED,
ATTR_RATING,
ATTR_REPOSITORY,
ATTR_SCHEMA,
@ -81,13 +79,14 @@ from ..const import (
ATTR_STARTUP,
ATTR_STATE,
ATTR_STDIN,
ATTR_SYSTEM_MANAGED,
ATTR_SYSTEM_MANAGED_CONFIG_ENTRY,
ATTR_TRANSLATIONS,
ATTR_UART,
ATTR_UDEV,
ATTR_UPDATE_AVAILABLE,
ATTR_URL,
ATTR_USB,
ATTR_VALID,
ATTR_VERSION,
ATTR_VERSION_LATEST,
ATTR_VIDEO,
@ -95,6 +94,7 @@ from ..const import (
ATTR_WEBUI,
REQUEST_FROM,
AddonBoot,
AddonBootConfig,
)
from ..coresys import CoreSysAttributes
from ..docker.stats import DockerStats
@ -102,12 +102,13 @@ from ..exceptions import (
APIAddonNotInstalled,
APIError,
APIForbidden,
APINotFound,
PwnedError,
PwnedSecret,
)
from ..validate import docker_ports
from .const import ATTR_SIGNED, CONTENT_TYPE_BINARY
from .utils import api_process, api_process_raw, api_validate, json_loads
from .const import ATTR_BOOT_CONFIG, ATTR_REMOVE_CONFIG, ATTR_SIGNED
from .utils import api_process, api_validate, json_loads
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -126,16 +127,35 @@ SCHEMA_OPTIONS = vol.Schema(
}
)
# pylint: disable=no-value-for-parameter
SCHEMA_SYS_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_SYSTEM_MANAGED): vol.Boolean(),
vol.Optional(ATTR_SYSTEM_MANAGED_CONFIG_ENTRY): vol.Maybe(str),
}
)
SCHEMA_SECURITY = vol.Schema({vol.Optional(ATTR_PROTECTED): vol.Boolean()})
SCHEMA_UNINSTALL = vol.Schema(
{vol.Optional(ATTR_REMOVE_CONFIG, default=False): vol.Boolean()}
)
# pylint: enable=no-value-for-parameter
class OptionsValidateResponse(TypedDict):
"""Response object for options validate."""
message: str
valid: bool
pwned: bool | None
class APIAddons(CoreSysAttributes):
"""Handle RESTful API for add-on functions."""
def _extract_addon(self, request: web.Request) -> Addon:
"""Return addon, throw an exception it it doesn't exist."""
addon_slug: str = request.match_info.get("addon")
def get_addon_for_request(self, request: web.Request) -> Addon:
"""Return addon, throw an exception if it doesn't exist."""
addon_slug: str = request.match_info["addon"]
# Lookup itself
if addon_slug == "self":
@ -146,14 +166,14 @@ class APIAddons(CoreSysAttributes):
addon = self.sys_addons.get(addon_slug)
if not addon:
raise APIError(f"Addon {addon_slug} does not exist")
raise APINotFound(f"Addon {addon_slug} does not exist")
if not isinstance(addon, Addon) or not addon.is_installed:
raise APIAddonNotInstalled("Addon is not installed")
return addon
@api_process
async def list(self, request: web.Request) -> dict[str, Any]:
async def list_addons(self, request: web.Request) -> dict[str, Any]:
"""Return all add-ons or repositories."""
data_addons = [
{
@ -174,6 +194,7 @@ class APIAddons(CoreSysAttributes):
ATTR_URL: addon.url,
ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo,
ATTR_SYSTEM_MANAGED: addon.system_managed,
}
for addon in self.sys_addons.installed
]
@ -187,7 +208,7 @@ class APIAddons(CoreSysAttributes):
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return add-on information."""
addon: AnyAddon = self._extract_addon(request)
addon: Addon = self.get_addon_for_request(request)
data = {
ATTR_NAME: addon.name,
@ -195,13 +216,14 @@ class APIAddons(CoreSysAttributes):
ATTR_HOSTNAME: addon.hostname,
ATTR_DNS: addon.dns,
ATTR_DESCRIPTON: addon.description,
ATTR_LONG_DESCRIPTION: addon.long_description,
ATTR_LONG_DESCRIPTION: await addon.long_description(),
ATTR_ADVANCED: addon.advanced,
ATTR_STAGE: addon.stage,
ATTR_REPOSITORY: addon.repository,
ATTR_VERSION_LATEST: addon.latest_version,
ATTR_PROTECTED: addon.protected,
ATTR_RATING: rating_security(addon),
ATTR_BOOT_CONFIG: addon.boot_config,
ATTR_BOOT: addon.boot,
ATTR_OPTIONS: addon.options,
ATTR_SCHEMA: addon.schema_ui,
@ -261,6 +283,8 @@ class APIAddons(CoreSysAttributes):
ATTR_WATCHDOG: addon.watchdog,
ATTR_DEVICES: addon.static_devices
+ [device.path for device in addon.devices],
ATTR_SYSTEM_MANAGED: addon.system_managed,
ATTR_SYSTEM_MANAGED_CONFIG_ENTRY: addon.system_managed_config_entry,
}
return data
@ -268,7 +292,7 @@ class APIAddons(CoreSysAttributes):
@api_process
async def options(self, request: web.Request) -> None:
"""Store user options for add-on."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
# Update secrets for validation
await self.sys_homeassistant.secrets.reload()
@ -283,6 +307,10 @@ class APIAddons(CoreSysAttributes):
if ATTR_OPTIONS in body:
addon.options = body[ATTR_OPTIONS]
if ATTR_BOOT in body:
if addon.boot_config == AddonBootConfig.MANUAL_ONLY:
raise APIError(
f"Addon {addon.slug} boot option is set to {addon.boot_config} so it cannot be changed"
)
addon.boot = body[ATTR_BOOT]
if ATTR_AUTO_UPDATE in body:
addon.auto_update = body[ATTR_AUTO_UPDATE]
@ -298,13 +326,27 @@ class APIAddons(CoreSysAttributes):
if ATTR_WATCHDOG in body:
addon.watchdog = body[ATTR_WATCHDOG]
addon.save_persist()
await addon.save_persist()
@api_process
async def options_validate(self, request: web.Request) -> None:
async def sys_options(self, request: web.Request) -> None:
"""Store system options for an add-on."""
addon = self.get_addon_for_request(request)
# Validate/Process Body
body = await api_validate(SCHEMA_SYS_OPTIONS, request)
if ATTR_SYSTEM_MANAGED in body:
addon.system_managed = body[ATTR_SYSTEM_MANAGED]
if ATTR_SYSTEM_MANAGED_CONFIG_ENTRY in body:
addon.system_managed_config_entry = body[ATTR_SYSTEM_MANAGED_CONFIG_ENTRY]
await addon.save_persist()
@api_process
async def options_validate(self, request: web.Request) -> OptionsValidateResponse:
"""Validate user options for add-on."""
addon = self._extract_addon(request)
data = {ATTR_MESSAGE: "", ATTR_VALID: True, ATTR_PWNED: False}
addon = self.get_addon_for_request(request)
data = OptionsValidateResponse(message="", valid=True, pwned=False)
options = await request.json(loads=json_loads) or addon.options
@ -313,8 +355,8 @@ class APIAddons(CoreSysAttributes):
try:
options_schema.validate(options)
except vol.Invalid as ex:
data[ATTR_MESSAGE] = humanize_error(options, ex)
data[ATTR_VALID] = False
data["message"] = humanize_error(options, ex)
data["valid"] = False
if not self.sys_security.pwned:
return data
@ -325,27 +367,27 @@ class APIAddons(CoreSysAttributes):
await self.sys_security.verify_secret(secret)
continue
except PwnedSecret:
data[ATTR_PWNED] = True
data["pwned"] = True
except PwnedError:
data[ATTR_PWNED] = None
data["pwned"] = None
break
if self.sys_security.force and data[ATTR_PWNED] in (None, True):
data[ATTR_VALID] = False
if data[ATTR_PWNED] is None:
data[ATTR_MESSAGE] = "Error happening on pwned secrets check!"
if self.sys_security.force and data["pwned"] in (None, True):
data["valid"] = False
if data["pwned"] is None:
data["message"] = "Error happening on pwned secrets check!"
else:
data[ATTR_MESSAGE] = "Add-on uses pwned secrets!"
data["message"] = "Add-on uses pwned secrets!"
return data
@api_process
async def options_config(self, request: web.Request) -> None:
"""Validate user options for add-on."""
slug: str = request.match_info.get("addon")
slug: str = request.match_info["addon"]
if slug != "self":
raise APIForbidden("This can be only read by the Add-on itself!")
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
# Lookup/reload secrets
await self.sys_homeassistant.secrets.reload()
@ -357,19 +399,19 @@ class APIAddons(CoreSysAttributes):
@api_process
async def security(self, request: web.Request) -> None:
"""Store security options for add-on."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
body: dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
if ATTR_PROTECTED in body:
_LOGGER.warning("Changing protected flag for %s!", addon.slug)
addon.protected = body[ATTR_PROTECTED]
addon.save_persist()
await addon.save_persist()
@api_process
async def stats(self, request: web.Request) -> dict[str, Any]:
"""Return resource information."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
stats: DockerStats = await addon.stats()
@ -385,48 +427,47 @@ class APIAddons(CoreSysAttributes):
}
@api_process
def uninstall(self, request: web.Request) -> Awaitable[None]:
async def uninstall(self, request: web.Request) -> Awaitable[None]:
"""Uninstall add-on."""
addon = self._extract_addon(request)
return asyncio.shield(self.sys_addons.uninstall(addon.slug))
addon = self.get_addon_for_request(request)
body: dict[str, Any] = await api_validate(SCHEMA_UNINSTALL, request)
return await asyncio.shield(
self.sys_addons.uninstall(
addon.slug, remove_config=body[ATTR_REMOVE_CONFIG]
)
)
@api_process
async def start(self, request: web.Request) -> None:
"""Start add-on."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
if start_task := await asyncio.shield(addon.start()):
await start_task
@api_process
def stop(self, request: web.Request) -> Awaitable[None]:
"""Stop add-on."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
return asyncio.shield(addon.stop())
@api_process
async def restart(self, request: web.Request) -> None:
"""Restart add-on."""
addon: Addon = self._extract_addon(request)
addon: Addon = self.get_addon_for_request(request)
if start_task := await asyncio.shield(addon.restart()):
await start_task
@api_process
async def rebuild(self, request: web.Request) -> None:
"""Rebuild local build add-on."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
if start_task := await asyncio.shield(self.sys_addons.rebuild(addon.slug)):
await start_task
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return logs from add-on."""
addon = self._extract_addon(request)
return addon.logs()
@api_process
async def stdin(self, request: web.Request) -> None:
"""Write to stdin of add-on."""
addon = self._extract_addon(request)
addon = self.get_addon_for_request(request)
if not addon.with_stdin:
raise APIError(f"STDIN not supported the {addon.slug} add-on")

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor Audio RESTful API."""
import asyncio
from collections.abc import Awaitable
from dataclasses import asdict
@ -35,8 +36,7 @@ from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..host.sound import StreamType
from ..validate import version_tag
from .const import CONTENT_TYPE_BINARY
from .utils import api_process, api_process_raw, api_validate
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -111,11 +111,6 @@ class APIAudio(CoreSysAttributes):
raise APIError(f"Version {version} is already in use")
await asyncio.shield(self.sys_plugins.audio.update(version))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return Audio Docker logs."""
return self.sys_plugins.audio.logs()
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart Audio plugin."""
@ -129,7 +124,7 @@ class APIAudio(CoreSysAttributes):
@api_process
async def set_volume(self, request: web.Request) -> None:
"""Set audio volume on stream."""
source: StreamType = StreamType(request.match_info.get("source"))
source: StreamType = StreamType(request.match_info["source"])
application: bool = request.path.endswith("application")
body = await api_validate(SCHEMA_VOLUME, request)
@ -142,7 +137,7 @@ class APIAudio(CoreSysAttributes):
@api_process
async def set_mute(self, request: web.Request) -> None:
"""Mute audio volume on stream."""
source: StreamType = StreamType(request.match_info.get("source"))
source: StreamType = StreamType(request.match_info["source"])
application: bool = request.path.endswith("application")
body = await api_validate(SCHEMA_MUTE, request)
@ -155,7 +150,7 @@ class APIAudio(CoreSysAttributes):
@api_process
async def set_default(self, request: web.Request) -> None:
"""Set audio default stream."""
source: StreamType = StreamType(request.match_info.get("source"))
source: StreamType = StreamType(request.match_info["source"])
body = await api_validate(SCHEMA_DEFAULT, request)
await asyncio.shield(self.sys_host.sound.set_default(source, body[ATTR_NAME]))

View File

@ -1,6 +1,9 @@
"""Init file for Supervisor auth/SSO RESTful API."""
import asyncio
from collections.abc import Awaitable
import logging
from typing import Any
from aiohttp import BasicAuth, web
from aiohttp.hdrs import AUTHORIZATION, CONTENT_TYPE, WWW_AUTHENTICATE
@ -8,10 +11,19 @@ from aiohttp.web_exceptions import HTTPUnauthorized
import voluptuous as vol
from ..addons.addon import Addon
from ..const import ATTR_PASSWORD, ATTR_USERNAME, REQUEST_FROM
from ..const import ATTR_NAME, ATTR_PASSWORD, ATTR_USERNAME, REQUEST_FROM
from ..coresys import CoreSysAttributes
from ..exceptions import APIForbidden
from .const import CONTENT_TYPE_JSON, CONTENT_TYPE_URL
from ..utils.json import json_loads
from .const import (
ATTR_GROUP_IDS,
ATTR_IS_ACTIVE,
ATTR_IS_OWNER,
ATTR_LOCAL_ONLY,
ATTR_USERS,
CONTENT_TYPE_JSON,
CONTENT_TYPE_URL,
)
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -31,7 +43,7 @@ REALM_HEADER: dict[str, str] = {
class APIAuth(CoreSysAttributes):
"""Handle RESTful API for auth functions."""
def _process_basic(self, request: web.Request, addon: Addon) -> bool:
def _process_basic(self, request: web.Request, addon: Addon) -> Awaitable[bool]:
"""Process login request with basic auth.
Return a coroutine.
@ -41,7 +53,7 @@ class APIAuth(CoreSysAttributes):
def _process_dict(
self, request: web.Request, addon: Addon, data: dict[str, str]
) -> bool:
) -> Awaitable[bool]:
"""Process login with dict data.
Return a coroutine.
@ -67,7 +79,7 @@ class APIAuth(CoreSysAttributes):
# Json
if request.headers.get(CONTENT_TYPE) == CONTENT_TYPE_JSON:
data = await request.json()
data = await request.json(loads=json_loads)
return await self._process_dict(request, addon, data)
# URL encoded
@ -88,4 +100,22 @@ class APIAuth(CoreSysAttributes):
@api_process
async def cache(self, request: web.Request) -> None:
"""Process cache reset request."""
self.sys_auth.reset_data()
await self.sys_auth.reset_data()
@api_process
async def list_users(self, request: web.Request) -> dict[str, list[dict[str, Any]]]:
"""List users on the Home Assistant instance."""
return {
ATTR_USERS: [
{
ATTR_USERNAME: user[ATTR_USERNAME],
ATTR_NAME: user[ATTR_NAME],
ATTR_IS_OWNER: user[ATTR_IS_OWNER],
ATTR_IS_ACTIVE: user[ATTR_IS_ACTIVE],
ATTR_LOCAL_ONLY: user[ATTR_LOCAL_ONLY],
ATTR_GROUP_IDS: user[ATTR_GROUP_IDS],
}
for user in await self.sys_auth.list_users()
if user[ATTR_USERNAME]
]
}

View File

@ -1,16 +1,24 @@
"""Backups RESTful API."""
from __future__ import annotations
import asyncio
from collections.abc import Callable
import errno
from io import IOBase
import logging
from pathlib import Path
import re
from tempfile import TemporaryDirectory
from typing import Any
from typing import Any, cast
from aiohttp import web
from aiohttp import BodyPartReader, web
from aiohttp.hdrs import CONTENT_DISPOSITION
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..backups.backup import Backup
from ..backups.const import LOCATION_CLOUD_BACKUP, LOCATION_TYPE
from ..backups.validate import ALL_FOLDERS, FOLDER_HOMEASSISTANT, days_until_stale
from ..const import (
ATTR_ADDONS,
@ -19,77 +27,118 @@ from ..const import (
ATTR_CONTENT,
ATTR_DATE,
ATTR_DAYS_UNTIL_STALE,
ATTR_EXTRA,
ATTR_FILENAME,
ATTR_FOLDERS,
ATTR_HOMEASSISTANT,
ATTR_HOMEASSISTANT_EXCLUDE_DATABASE,
ATTR_LOCATON,
ATTR_JOB_ID,
ATTR_LOCATION,
ATTR_NAME,
ATTR_PASSWORD,
ATTR_PROTECTED,
ATTR_REPOSITORIES,
ATTR_SIZE,
ATTR_SIZE_BYTES,
ATTR_SLUG,
ATTR_SUPERVISOR_VERSION,
ATTR_TIMEOUT,
ATTR_TYPE,
ATTR_VERSION,
REQUEST_FROM,
BusEvent,
CoreState,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..exceptions import APIError, APIForbidden, APINotFound
from ..jobs import JobSchedulerOptions, SupervisorJob
from ..mounts.const import MountUsage
from ..mounts.mount import Mount
from ..resolution.const import UnhealthyReason
from .const import CONTENT_TYPE_TAR
from .const import (
ATTR_ADDITIONAL_LOCATIONS,
ATTR_BACKGROUND,
ATTR_LOCATION_ATTRIBUTES,
ATTR_LOCATIONS,
CONTENT_TYPE_TAR,
)
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
ALL_ADDONS_FLAG = "ALL"
LOCATION_LOCAL = ".local"
RE_SLUGIFY_NAME = re.compile(r"[^A-Za-z0-9]+")
RE_BACKUP_FILENAME = re.compile(r"^[^\\\/]+\.tar$")
# Backwards compatible
# Remove: 2022.08
_ALL_FOLDERS = ALL_FOLDERS + [FOLDER_HOMEASSISTANT]
def _ensure_list(item: Any) -> list:
"""Ensure value is a list."""
if not isinstance(item, list):
return [item]
return item
def _convert_local_location(item: str | None) -> str | None:
"""Convert local location value."""
if item in {LOCATION_LOCAL, ""}:
return None
return item
# pylint: disable=no-value-for-parameter
SCHEMA_RESTORE_PARTIAL = vol.Schema(
SCHEMA_FOLDERS = vol.All([vol.In(_ALL_FOLDERS)], vol.Unique())
SCHEMA_LOCATION = vol.All(vol.Maybe(str), _convert_local_location)
SCHEMA_LOCATION_LIST = vol.All(_ensure_list, [SCHEMA_LOCATION], vol.Unique())
SCHEMA_RESTORE_FULL = vol.Schema(
{
vol.Optional(ATTR_PASSWORD): vol.Maybe(str),
vol.Optional(ATTR_HOMEASSISTANT): vol.Boolean(),
vol.Optional(ATTR_ADDONS): vol.All([str], vol.Unique()),
vol.Optional(ATTR_FOLDERS): vol.All([vol.In(_ALL_FOLDERS)], vol.Unique()),
vol.Optional(ATTR_BACKGROUND, default=False): vol.Boolean(),
vol.Optional(ATTR_LOCATION): SCHEMA_LOCATION,
}
)
SCHEMA_RESTORE_FULL = vol.Schema({vol.Optional(ATTR_PASSWORD): vol.Maybe(str)})
SCHEMA_RESTORE_PARTIAL = SCHEMA_RESTORE_FULL.extend(
{
vol.Optional(ATTR_HOMEASSISTANT): vol.Boolean(),
vol.Optional(ATTR_ADDONS): vol.All([str], vol.Unique()),
vol.Optional(ATTR_FOLDERS): SCHEMA_FOLDERS,
}
)
SCHEMA_BACKUP_FULL = vol.Schema(
{
vol.Optional(ATTR_NAME): str,
vol.Optional(ATTR_FILENAME): vol.Match(RE_BACKUP_FILENAME),
vol.Optional(ATTR_PASSWORD): vol.Maybe(str),
vol.Optional(ATTR_COMPRESSED): vol.Maybe(vol.Boolean()),
vol.Optional(ATTR_LOCATON): vol.Maybe(str),
vol.Optional(ATTR_LOCATION): SCHEMA_LOCATION_LIST,
vol.Optional(ATTR_HOMEASSISTANT_EXCLUDE_DATABASE): vol.Boolean(),
vol.Optional(ATTR_BACKGROUND, default=False): vol.Boolean(),
vol.Optional(ATTR_EXTRA): dict,
}
)
SCHEMA_BACKUP_PARTIAL = SCHEMA_BACKUP_FULL.extend(
{
vol.Optional(ATTR_ADDONS): vol.All([str], vol.Unique()),
vol.Optional(ATTR_FOLDERS): vol.All([vol.In(_ALL_FOLDERS)], vol.Unique()),
vol.Optional(ATTR_ADDONS): vol.Or(
ALL_ADDONS_FLAG, vol.All([str], vol.Unique())
),
vol.Optional(ATTR_FOLDERS): SCHEMA_FOLDERS,
vol.Optional(ATTR_HOMEASSISTANT): vol.Boolean(),
}
)
SCHEMA_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_DAYS_UNTIL_STALE): days_until_stale,
}
)
SCHEMA_FREEZE = vol.Schema(
{
vol.Optional(ATTR_TIMEOUT): vol.All(int, vol.Range(min=1)),
}
)
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_DAYS_UNTIL_STALE): days_until_stale})
SCHEMA_FREEZE = vol.Schema({vol.Optional(ATTR_TIMEOUT): vol.All(int, vol.Range(min=1))})
SCHEMA_REMOVE = vol.Schema({vol.Optional(ATTR_LOCATION): SCHEMA_LOCATION_LIST})
class APIBackups(CoreSysAttributes):
@ -99,9 +148,19 @@ class APIBackups(CoreSysAttributes):
"""Return backup, throw an exception if it doesn't exist."""
backup = self.sys_backups.get(request.match_info.get("slug"))
if not backup:
raise APIError("Backup does not exist")
raise APINotFound("Backup does not exist")
return backup
def _make_location_attributes(self, backup: Backup) -> dict[str, dict[str, Any]]:
"""Make location attributes dictionary."""
return {
loc if loc else LOCATION_LOCAL: {
ATTR_PROTECTED: backup.all_locations[loc].protected,
ATTR_SIZE_BYTES: backup.all_locations[loc].size_bytes,
}
for loc in backup.locations
}
def _list_backups(self):
"""Return list of backups."""
return [
@ -111,8 +170,11 @@ class APIBackups(CoreSysAttributes):
ATTR_DATE: backup.date,
ATTR_TYPE: backup.sys_type,
ATTR_SIZE: backup.size,
ATTR_LOCATON: backup.location,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_LOCATION: backup.location,
ATTR_LOCATIONS: backup.locations,
ATTR_PROTECTED: backup.protected,
ATTR_LOCATION_ATTRIBUTES: self._make_location_attributes(backup),
ATTR_COMPRESSED: backup.compressed,
ATTR_CONTENT: {
ATTR_HOMEASSISTANT: backup.homeassistant_version is not None,
@ -121,10 +183,11 @@ class APIBackups(CoreSysAttributes):
},
}
for backup in self.sys_backups.list_backups
if backup.location != LOCATION_CLOUD_BACKUP
]
@api_process
async def list(self, request):
async def list_backups(self, request):
"""Return backup list."""
data_backups = self._list_backups()
@ -150,7 +213,7 @@ class APIBackups(CoreSysAttributes):
if ATTR_DAYS_UNTIL_STALE in body:
self.sys_backups.days_until_stale = body[ATTR_DAYS_UNTIL_STALE]
self.sys_backups.save_data()
await self.sys_backups.save_data()
@api_process
async def reload(self, _):
@ -180,125 +243,339 @@ class APIBackups(CoreSysAttributes):
ATTR_NAME: backup.name,
ATTR_DATE: backup.date,
ATTR_SIZE: backup.size,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_COMPRESSED: backup.compressed,
ATTR_PROTECTED: backup.protected,
ATTR_LOCATION_ATTRIBUTES: self._make_location_attributes(backup),
ATTR_SUPERVISOR_VERSION: backup.supervisor_version,
ATTR_HOMEASSISTANT: backup.homeassistant_version,
ATTR_LOCATON: backup.location,
ATTR_LOCATION: backup.location,
ATTR_LOCATIONS: backup.locations,
ATTR_ADDONS: data_addons,
ATTR_REPOSITORIES: backup.repositories,
ATTR_FOLDERS: backup.folders,
ATTR_HOMEASSISTANT_EXCLUDE_DATABASE: backup.homeassistant_exclude_database,
ATTR_EXTRA: backup.extra,
}
def _location_to_mount(self, body: dict[str, Any]) -> dict[str, Any]:
"""Change location field to mount if necessary."""
if not body.get(ATTR_LOCATON):
return body
def _location_to_mount(self, location: str | None) -> LOCATION_TYPE:
"""Convert a single location to a mount if possible."""
if not location or location == LOCATION_CLOUD_BACKUP:
return cast(LOCATION_TYPE, location)
body[ATTR_LOCATON] = self.sys_mounts.get(body[ATTR_LOCATON])
if body[ATTR_LOCATON].usage != MountUsage.BACKUP:
mount = self.sys_mounts.get(location)
if mount.usage != MountUsage.BACKUP:
raise APIError(
f"Mount {body[ATTR_LOCATON].name} is not used for backups, cannot backup to there"
f"Mount {mount.name} is not used for backups, cannot backup to there"
)
return mount
def _location_field_to_mount(self, body: dict[str, Any]) -> dict[str, Any]:
"""Change location field to mount if necessary."""
body[ATTR_LOCATION] = self._location_to_mount(body.get(ATTR_LOCATION))
return body
def _validate_cloud_backup_location(
self, request: web.Request, location: list[str | None] | str | None
) -> None:
"""Cloud backup location is only available to Home Assistant."""
if not isinstance(location, list):
location = [location]
if (
LOCATION_CLOUD_BACKUP in location
and request.get(REQUEST_FROM) != self.sys_homeassistant
):
raise APIForbidden(
f"Location {LOCATION_CLOUD_BACKUP} is only available for Home Assistant"
)
async def _background_backup_task(
self, backup_method: Callable, *args, **kwargs
) -> tuple[asyncio.Task, str]:
"""Start backup task in background and return task and job ID."""
event = asyncio.Event()
job, backup_task = cast(
tuple[SupervisorJob, asyncio.Task],
self.sys_jobs.schedule_job(
backup_method, JobSchedulerOptions(), *args, **kwargs
),
)
async def release_on_freeze(new_state: CoreState):
if new_state == CoreState.FREEZE:
event.set()
# Wait for system to get into freeze state before returning
# If the backup fails validation it will raise before getting there
listener = self.sys_bus.register_event(
BusEvent.SUPERVISOR_STATE_CHANGE, release_on_freeze
)
try:
event_task = self.sys_create_task(event.wait())
_, pending = await asyncio.wait(
(backup_task, event_task),
return_when=asyncio.FIRST_COMPLETED,
)
# It seems backup returned early (error or something), make sure to cancel
# the event task to avoid "Task was destroyed but it is pending!" errors.
if event_task in pending:
event_task.cancel()
return (backup_task, job.uuid)
finally:
self.sys_bus.remove_listener(listener)
@api_process
async def backup_full(self, request):
async def backup_full(self, request: web.Request):
"""Create full backup."""
body = await api_validate(SCHEMA_BACKUP_FULL, request)
locations: list[LOCATION_TYPE] | None = None
backup = await asyncio.shield(
self.sys_backups.do_backup_full(**self._location_to_mount(body))
if ATTR_LOCATION in body:
location_names: list[str | None] = body.pop(ATTR_LOCATION)
self._validate_cloud_backup_location(request, location_names)
locations = [
self._location_to_mount(location) for location in location_names
]
body[ATTR_LOCATION] = locations.pop(0)
if locations:
body[ATTR_ADDITIONAL_LOCATIONS] = locations
background = body.pop(ATTR_BACKGROUND)
backup_task, job_id = await self._background_backup_task(
self.sys_backups.do_backup_full, **body
)
if background and not backup_task.done():
return {ATTR_JOB_ID: job_id}
backup: Backup = await backup_task
if backup:
return {ATTR_SLUG: backup.slug}
return False
return {ATTR_JOB_ID: job_id, ATTR_SLUG: backup.slug}
raise APIError(
f"An error occurred while making backup, check job '{job_id}' or supervisor logs for details",
job_id=job_id,
)
@api_process
async def backup_partial(self, request):
async def backup_partial(self, request: web.Request):
"""Create a partial backup."""
body = await api_validate(SCHEMA_BACKUP_PARTIAL, request)
backup = await asyncio.shield(
self.sys_backups.do_backup_partial(**self._location_to_mount(body))
locations: list[LOCATION_TYPE] | None = None
if ATTR_LOCATION in body:
location_names: list[str | None] = body.pop(ATTR_LOCATION)
self._validate_cloud_backup_location(request, location_names)
locations = [
self._location_to_mount(location) for location in location_names
]
body[ATTR_LOCATION] = locations.pop(0)
if locations:
body[ATTR_ADDITIONAL_LOCATIONS] = locations
if body.get(ATTR_ADDONS) == ALL_ADDONS_FLAG:
body[ATTR_ADDONS] = list(self.sys_addons.local)
background = body.pop(ATTR_BACKGROUND)
backup_task, job_id = await self._background_backup_task(
self.sys_backups.do_backup_partial, **body
)
if background and not backup_task.done():
return {ATTR_JOB_ID: job_id}
backup: Backup = await backup_task
if backup:
return {ATTR_SLUG: backup.slug}
return False
return {ATTR_JOB_ID: job_id, ATTR_SLUG: backup.slug}
raise APIError(
f"An error occurred while making backup, check job '{job_id}' or supervisor logs for details",
job_id=job_id,
)
@api_process
async def restore_full(self, request):
async def restore_full(self, request: web.Request):
"""Full restore of a backup."""
backup = self._extract_slug(request)
body = await api_validate(SCHEMA_RESTORE_FULL, request)
self._validate_cloud_backup_location(
request, body.get(ATTR_LOCATION, backup.location)
)
background = body.pop(ATTR_BACKGROUND)
restore_task, job_id = await self._background_backup_task(
self.sys_backups.do_restore_full, backup, **body
)
return await asyncio.shield(self.sys_backups.do_restore_full(backup, **body))
if background and not restore_task.done() or await restore_task:
return {ATTR_JOB_ID: job_id}
raise APIError(
f"An error occurred during restore of {backup.slug}, check job '{job_id}' or supervisor logs for details",
job_id=job_id,
)
@api_process
async def restore_partial(self, request):
async def restore_partial(self, request: web.Request):
"""Partial restore a backup."""
backup = self._extract_slug(request)
body = await api_validate(SCHEMA_RESTORE_PARTIAL, request)
self._validate_cloud_backup_location(
request, body.get(ATTR_LOCATION, backup.location)
)
background = body.pop(ATTR_BACKGROUND)
restore_task, job_id = await self._background_backup_task(
self.sys_backups.do_restore_partial, backup, **body
)
return await asyncio.shield(self.sys_backups.do_restore_partial(backup, **body))
if background and not restore_task.done() or await restore_task:
return {ATTR_JOB_ID: job_id}
raise APIError(
f"An error occurred during restore of {backup.slug}, check job '{job_id}' or supervisor logs for details",
job_id=job_id,
)
@api_process
async def freeze(self, request):
async def freeze(self, request: web.Request):
"""Initiate manual freeze for external backup."""
body = await api_validate(SCHEMA_FREEZE, request)
await asyncio.shield(self.sys_backups.freeze_all(**body))
@api_process
async def thaw(self, request):
async def thaw(self, request: web.Request):
"""Begin thaw after manual freeze."""
await self.sys_backups.thaw_all()
@api_process
async def remove(self, request):
async def remove(self, request: web.Request):
"""Remove a backup."""
backup = self._extract_slug(request)
return self.sys_backups.remove(backup)
body = await api_validate(SCHEMA_REMOVE, request)
locations: list[LOCATION_TYPE] | None = None
async def download(self, request):
if ATTR_LOCATION in body:
self._validate_cloud_backup_location(request, body[ATTR_LOCATION])
locations = [self._location_to_mount(name) for name in body[ATTR_LOCATION]]
else:
self._validate_cloud_backup_location(request, backup.location)
await self.sys_backups.remove(backup, locations=locations)
@api_process
async def download(self, request: web.Request):
"""Download a backup file."""
backup = self._extract_slug(request)
# Query will give us '' for /backups, convert value to None
location = _convert_local_location(
request.query.get(ATTR_LOCATION, backup.location)
)
self._validate_cloud_backup_location(request, location)
if location not in backup.all_locations:
raise APIError(f"Backup {backup.slug} is not in location {location}")
_LOGGER.info("Downloading backup %s", backup.slug)
response = web.FileResponse(backup.tarfile)
filename = backup.all_locations[location].path
# If the file is missing, return 404 and trigger reload of location
if not await self.sys_run_in_executor(filename.is_file):
self.sys_create_task(self.sys_backups.reload(location))
return web.Response(status=404)
response = web.FileResponse(filename)
response.content_type = CONTENT_TYPE_TAR
response.headers[
CONTENT_DISPOSITION
] = f"attachment; filename={RE_SLUGIFY_NAME.sub('_', backup.name)}.tar"
download_filename = filename.name
if download_filename == f"{backup.slug}.tar":
download_filename = f"{RE_SLUGIFY_NAME.sub('_', backup.name)}.tar"
response.headers[CONTENT_DISPOSITION] = (
f"attachment; filename={download_filename}"
)
return response
@api_process
async def upload(self, request):
async def upload(self, request: web.Request):
"""Upload a backup file."""
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp_dir:
tar_file = Path(temp_dir, "backup.tar")
location: LOCATION_TYPE = None
locations: list[LOCATION_TYPE] | None = None
tmp_path = self.sys_config.path_tmp
if ATTR_LOCATION in request.query:
location_names: list[str] = request.query.getall(ATTR_LOCATION, [])
self._validate_cloud_backup_location(
request, cast(list[str | None], location_names)
)
# Convert empty string to None if necessary
locations = [
self._location_to_mount(location)
if _convert_local_location(location)
else None
for location in location_names
]
location = locations.pop(0)
if location and location != LOCATION_CLOUD_BACKUP:
tmp_path = cast(Mount, location).local_where
filename: str | None = None
if ATTR_FILENAME in request.query:
filename = request.query.get(ATTR_FILENAME)
try:
vol.Match(RE_BACKUP_FILENAME)(filename)
except vol.Invalid as ex:
raise APIError(humanize_error(filename, ex)) from None
temp_dir: TemporaryDirectory | None = None
backup_file_stream: IOBase | None = None
def open_backup_file() -> Path:
nonlocal temp_dir, backup_file_stream
temp_dir = TemporaryDirectory(dir=tmp_path.as_posix())
tar_file = Path(temp_dir.name, "backup.tar")
backup_file_stream = tar_file.open("wb")
return tar_file
def close_backup_file() -> None:
if backup_file_stream:
# Make sure it got closed, in case of exception. It is safe to
# close the file stream twice.
backup_file_stream.close()
if temp_dir:
temp_dir.cleanup()
try:
reader = await request.multipart()
contents = await reader.next()
try:
with tar_file.open("wb") as backup:
while True:
chunk = await contents.read_chunk()
if not chunk:
break
backup.write(chunk)
if not isinstance(contents, BodyPartReader):
raise APIError("Improperly formatted upload, could not read backup")
except OSError as err:
if err.errno == errno.EBADMSG:
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
_LOGGER.error("Can't write new backup file: %s", err)
return False
tar_file = await self.sys_run_in_executor(open_backup_file)
while chunk := await contents.read_chunk(size=2**16):
await self.sys_run_in_executor(
cast(IOBase, backup_file_stream).write, chunk
)
await self.sys_run_in_executor(cast(IOBase, backup_file_stream).close)
except asyncio.CancelledError:
return False
backup = await asyncio.shield(
self.sys_backups.import_backup(
tar_file,
filename,
location=location,
additional_locations=locations,
)
)
except OSError as err:
if err.errno == errno.EBADMSG and location in {
LOCATION_CLOUD_BACKUP,
None,
}:
self.sys_resolution.add_unhealthy_reason(
UnhealthyReason.OSERROR_BAD_MESSAGE
)
_LOGGER.error("Can't write new backup file: %s", err)
return False
backup = await asyncio.shield(self.sys_backups.import_backup(tar_file))
except asyncio.CancelledError:
return False
finally:
await self.sys_run_in_executor(close_backup_file)
if backup:
return {ATTR_SLUG: backup.slug}

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor HA cli RESTful API."""
import asyncio
import logging
from typing import Any

View File

@ -1,18 +1,26 @@
"""Const for API."""
from enum import StrEnum
CONTENT_TYPE_BINARY = "application/octet-stream"
CONTENT_TYPE_JSON = "application/json"
CONTENT_TYPE_PNG = "image/png"
CONTENT_TYPE_TAR = "application/tar"
CONTENT_TYPE_TEXT = "text/plain"
CONTENT_TYPE_URL = "application/x-www-form-urlencoded"
CONTENT_TYPE_X_LOG = "text/x-log"
COOKIE_INGRESS = "ingress_session"
ATTR_ADDITIONAL_LOCATIONS = "additional_locations"
ATTR_AGENT_VERSION = "agent_version"
ATTR_APPARMOR_VERSION = "apparmor_version"
ATTR_ATTRIBUTES = "attributes"
ATTR_AVAILABLE_UPDATES = "available_updates"
ATTR_BACKGROUND = "background"
ATTR_BOOT_CONFIG = "boot_config"
ATTR_BOOT_SLOT = "boot_slot"
ATTR_BOOT_SLOTS = "boot_slots"
ATTR_BOOT_TIMESTAMP = "boot_timestamp"
ATTR_BOOTS = "boots"
ATTR_BROADCAST_LLMNR = "broadcast_llmnr"
@ -30,25 +38,53 @@ ATTR_DT_UTC = "dt_utc"
ATTR_EJECTABLE = "ejectable"
ATTR_FALLBACK = "fallback"
ATTR_FILESYSTEMS = "filesystems"
ATTR_FORCE = "force"
ATTR_GROUP_IDS = "group_ids"
ATTR_IDENTIFIERS = "identifiers"
ATTR_IS_ACTIVE = "is_active"
ATTR_IS_OWNER = "is_owner"
ATTR_JOBS = "jobs"
ATTR_LLMNR = "llmnr"
ATTR_LLMNR_HOSTNAME = "llmnr_hostname"
ATTR_LOCAL_ONLY = "local_only"
ATTR_LOCATION_ATTRIBUTES = "location_attributes"
ATTR_LOCATIONS = "locations"
ATTR_MDNS = "mdns"
ATTR_MODEL = "model"
ATTR_MOUNTS = "mounts"
ATTR_MOUNT_POINTS = "mount_points"
ATTR_PANEL_PATH = "panel_path"
ATTR_REMOVABLE = "removable"
ATTR_REMOVE_CONFIG = "remove_config"
ATTR_REVISION = "revision"
ATTR_SAFE_MODE = "safe_mode"
ATTR_SEAT = "seat"
ATTR_SIGNED = "signed"
ATTR_STARTUP_TIME = "startup_time"
ATTR_STATUS = "status"
ATTR_SUBSYSTEM = "subsystem"
ATTR_SYSFS = "sysfs"
ATTR_SYSTEM_HEALTH_LED = "system_health_led"
ATTR_TIME_DETECTED = "time_detected"
ATTR_UPDATE_TYPE = "update_type"
ATTR_USE_NTP = "use_ntp"
ATTR_USAGE = "usage"
ATTR_USE_NTP = "use_ntp"
ATTR_USERS = "users"
ATTR_USER_PATH = "user_path"
ATTR_VENDOR = "vendor"
ATTR_VIRTUALIZATION = "virtualization"
class BootSlot(StrEnum):
"""Boot slots used by HAOS."""
A = "A"
B = "B"
class DetectBlockingIO(StrEnum):
"""Enable/Disable detection for blocking I/O in event loop."""
OFF = "off"
ON = "on"
ON_AT_STARTUP = "on_at_startup"

View File

@ -1,6 +1,9 @@
"""Init file for Supervisor network RESTful API."""
import logging
import logging
from typing import Any, cast
from aiohttp import web
import voluptuous as vol
from ..addons.addon import Addon
@ -15,8 +18,8 @@ from ..const import (
AddonState,
)
from ..coresys import CoreSysAttributes
from ..discovery.validate import valid_discovery_service
from ..exceptions import APIError, APIForbidden
from ..discovery import Message
from ..exceptions import APIForbidden, APINotFound
from .utils import api_process, api_validate, require_home_assistant
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -24,7 +27,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_DISCOVERY = vol.Schema(
{
vol.Required(ATTR_SERVICE): str,
vol.Optional(ATTR_CONFIG): vol.Maybe(dict),
vol.Required(ATTR_CONFIG): dict,
}
)
@ -32,16 +35,16 @@ SCHEMA_DISCOVERY = vol.Schema(
class APIDiscovery(CoreSysAttributes):
"""Handle RESTful API for discovery functions."""
def _extract_message(self, request):
def _extract_message(self, request: web.Request) -> Message:
"""Extract discovery message from URL."""
message = self.sys_discovery.get(request.match_info.get("uuid"))
message = self.sys_discovery.get(request.match_info["uuid"])
if not message:
raise APIError("Discovery message not found")
raise APINotFound("Discovery message not found")
return message
@api_process
@require_home_assistant
async def list(self, request):
async def list_discovery(self, request: web.Request) -> dict[str, Any]:
"""Show registered and available services."""
# Get available discovery
discovery = [
@ -52,12 +55,16 @@ class APIDiscovery(CoreSysAttributes):
ATTR_CONFIG: message.config,
}
for message in self.sys_discovery.list_messages
if (addon := self.sys_addons.get(message.addon, local_only=True))
and addon.state == AddonState.STARTED
if (
discovered := cast(
Addon, self.sys_addons.get(message.addon, local_only=True)
)
)
and discovered.state == AddonState.STARTED
]
# Get available services/add-ons
services = {}
services: dict[str, list[str]] = {}
for addon in self.sys_addons.all:
for name in addon.discovery:
services.setdefault(name, []).append(addon.slug)
@ -65,21 +72,12 @@ class APIDiscovery(CoreSysAttributes):
return {ATTR_DISCOVERY: discovery, ATTR_SERVICES: services}
@api_process
async def set_discovery(self, request):
async def set_discovery(self, request: web.Request) -> dict[str, str]:
"""Write data into a discovery pipeline."""
body = await api_validate(SCHEMA_DISCOVERY, request)
addon: Addon = request[REQUEST_FROM]
service = body[ATTR_SERVICE]
try:
valid_discovery_service(service)
except vol.Invalid:
_LOGGER.warning(
"Received discovery message for unknown service %s from addon %s. Please report this to the maintainer of the add-on",
service,
addon.name,
)
# Access?
if body[ATTR_SERVICE] not in addon.discovery:
_LOGGER.error(
@ -92,13 +90,13 @@ class APIDiscovery(CoreSysAttributes):
)
# Process discovery message
message = self.sys_discovery.send(addon, **body)
message = await self.sys_discovery.send(addon, **body)
return {ATTR_UUID: message.uuid}
@api_process
@require_home_assistant
async def get_discovery(self, request):
async def get_discovery(self, request: web.Request) -> dict[str, Any]:
"""Read data into a discovery message."""
message = self._extract_message(request)
@ -110,7 +108,7 @@ class APIDiscovery(CoreSysAttributes):
}
@api_process
async def del_discovery(self, request):
async def del_discovery(self, request: web.Request) -> None:
"""Delete data into a discovery message."""
message = self._extract_message(request)
addon = request[REQUEST_FROM]
@ -119,5 +117,4 @@ class APIDiscovery(CoreSysAttributes):
if message.addon != addon.slug:
raise APIForbidden("Can't remove discovery message")
self.sys_discovery.remove(message)
return True
await self.sys_discovery.remove(message)

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor DNS RESTful API."""
import asyncio
from collections.abc import Awaitable
import logging
@ -26,8 +27,8 @@ from ..const import (
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import dns_server_list, version_tag
from .const import ATTR_FALLBACK, ATTR_LLMNR, ATTR_MDNS, CONTENT_TYPE_BINARY
from .utils import api_process, api_process_raw, api_validate
from .const import ATTR_FALLBACK, ATTR_LLMNR, ATTR_MDNS
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -77,7 +78,7 @@ class APICoreDNS(CoreSysAttributes):
if restart_required:
self.sys_create_task(self.sys_plugins.dns.restart())
self.sys_plugins.dns.save_data()
await self.sys_plugins.dns.save_data()
@api_process
async def stats(self, request: web.Request) -> dict[str, Any]:
@ -105,11 +106,6 @@ class APICoreDNS(CoreSysAttributes):
raise APIError(f"Version {version} is already in use")
await asyncio.shield(self.sys_plugins.dns.update(version))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return DNS Docker logs."""
return self.sys_plugins.dns.logs()
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart CoreDNS plugin."""

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import logging
from typing import Any
@ -15,6 +16,7 @@ from ..const import (
ATTR_VERSION,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APINotFound
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -51,14 +53,17 @@ class APIDocker(CoreSysAttributes):
for hostname, registry in body.items():
self.sys_docker.config.registries[hostname] = registry
self.sys_docker.config.save_data()
await self.sys_docker.config.save_data()
@api_process
async def remove_registry(self, request: web.Request):
"""Delete a docker registry."""
hostname = request.match_info.get(ATTR_HOSTNAME)
if hostname not in self.sys_docker.config.registries:
raise APINotFound(f"Hostname {hostname} does not exist in registries")
del self.sys_docker.config.registries[hostname]
self.sys_docker.config.save_data()
await self.sys_docker.config.save_data()
@api_process
async def info(self, request: web.Request):

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor hardware RESTful API."""
import logging
from typing import Any
@ -16,7 +17,7 @@ from ..const import (
ATTR_SYSTEM,
)
from ..coresys import CoreSysAttributes
from ..dbus.udisks2 import UDisks2
from ..dbus.udisks2 import UDisks2Manager
from ..dbus.udisks2.block import UDisks2Block
from ..dbus.udisks2.drive import UDisks2Drive
from ..hardware.data import Device
@ -67,12 +68,15 @@ def filesystem_struct(fs_block: UDisks2Block) -> dict[str, Any]:
ATTR_NAME: fs_block.id_label,
ATTR_SYSTEM: fs_block.hint_system,
ATTR_MOUNT_POINTS: [
str(mount_point) for mount_point in fs_block.filesystem.mount_points
str(mount_point)
for mount_point in (
fs_block.filesystem.mount_points if fs_block.filesystem else []
)
],
}
def drive_struct(udisks2: UDisks2, drive: UDisks2Drive) -> dict[str, Any]:
def drive_struct(udisks2: UDisks2Manager, drive: UDisks2Drive) -> dict[str, Any]:
"""Return a dict with information of a disk to be used in the API."""
return {
ATTR_VENDOR: drive.vendor,

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import asyncio
from collections.abc import Awaitable
import logging
@ -34,10 +35,10 @@ from ..const import (
ATTR_WATCHDOG,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..exceptions import APIDBMigrationInProgress, APIError
from ..validate import docker_image, network_port, version_tag
from .const import CONTENT_TYPE_BINARY
from .utils import api_process, api_process_raw, api_validate
from .const import ATTR_FORCE, ATTR_SAFE_MODE
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -63,10 +64,34 @@ SCHEMA_UPDATE = vol.Schema(
}
)
SCHEMA_RESTART = vol.Schema(
{
vol.Optional(ATTR_SAFE_MODE, default=False): vol.Boolean(),
vol.Optional(ATTR_FORCE, default=False): vol.Boolean(),
}
)
SCHEMA_STOP = vol.Schema(
{
vol.Optional(ATTR_FORCE, default=False): vol.Boolean(),
}
)
class APIHomeAssistant(CoreSysAttributes):
"""Handle RESTful API for Home Assistant functions."""
async def _check_offline_migration(self, force: bool = False) -> None:
"""Check and raise if there's an offline DB migration in progress."""
if (
not force
and (state := await self.sys_homeassistant.api.get_api_state())
and state.offline_db_migration
):
raise APIDBMigrationInProgress(
"Offline database migration in progress, try again after it has completed"
)
@api_process
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return host information."""
@ -93,7 +118,10 @@ class APIHomeAssistant(CoreSysAttributes):
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_IMAGE in body:
self.sys_homeassistant.image = body[ATTR_IMAGE]
self.sys_homeassistant.set_image(body[ATTR_IMAGE])
self.sys_homeassistant.override_image = (
self.sys_homeassistant.image != self.sys_homeassistant.default_image
)
if ATTR_BOOT in body:
self.sys_homeassistant.boot = body[ATTR_BOOT]
@ -121,7 +149,7 @@ class APIHomeAssistant(CoreSysAttributes):
ATTR_BACKUPS_EXCLUDE_DATABASE
]
self.sys_homeassistant.save_data()
await self.sys_homeassistant.save_data()
@api_process
async def stats(self, request: web.Request) -> dict[Any, str]:
@ -145,6 +173,7 @@ class APIHomeAssistant(CoreSysAttributes):
async def update(self, request: web.Request) -> None:
"""Update Home Assistant."""
body = await api_validate(SCHEMA_UPDATE, request)
await self._check_offline_migration()
await asyncio.shield(
self.sys_homeassistant.core.update(
@ -154,9 +183,12 @@ class APIHomeAssistant(CoreSysAttributes):
)
@api_process
def stop(self, request: web.Request) -> Awaitable[None]:
async def stop(self, request: web.Request) -> Awaitable[None]:
"""Stop Home Assistant."""
return asyncio.shield(self.sys_homeassistant.core.stop())
body = await api_validate(SCHEMA_STOP, request)
await self._check_offline_migration(force=body[ATTR_FORCE])
return await asyncio.shield(self.sys_homeassistant.core.stop())
@api_process
def start(self, request: web.Request) -> Awaitable[None]:
@ -164,19 +196,24 @@ class APIHomeAssistant(CoreSysAttributes):
return asyncio.shield(self.sys_homeassistant.core.start())
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
async def restart(self, request: web.Request) -> None:
"""Restart Home Assistant."""
return asyncio.shield(self.sys_homeassistant.core.restart())
body = await api_validate(SCHEMA_RESTART, request)
await self._check_offline_migration(force=body[ATTR_FORCE])
await asyncio.shield(
self.sys_homeassistant.core.restart(safe_mode=body[ATTR_SAFE_MODE])
)
@api_process
def rebuild(self, request: web.Request) -> Awaitable[None]:
async def rebuild(self, request: web.Request) -> None:
"""Rebuild Home Assistant."""
return asyncio.shield(self.sys_homeassistant.core.rebuild())
body = await api_validate(SCHEMA_RESTART, request)
await self._check_offline_migration(force=body[ATTR_FORCE])
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return Home Assistant Docker logs."""
return self.sys_homeassistant.core.logs()
await asyncio.shield(
self.sys_homeassistant.core.rebuild(safe_mode=body[ATTR_SAFE_MODE])
)
@api_process
async def check(self, request: web.Request) -> None:

View File

@ -1,9 +1,11 @@
"""Init file for Supervisor host RESTful API."""
import asyncio
from contextlib import suppress
import logging
from typing import Any
from aiohttp import web
from aiohttp import ClientConnectionResetError, web
from aiohttp.hdrs import ACCEPT, RANGE
import voluptuous as vol
from voluptuous.error import CoerceInvalid
@ -27,8 +29,15 @@ from ..const import (
ATTR_TIMEZONE,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, HostLogError
from ..host.const import PARAM_BOOT_ID, PARAM_FOLLOW, PARAM_SYSLOG_IDENTIFIER
from ..exceptions import APIDBMigrationInProgress, APIError, HostLogError
from ..host.const import (
PARAM_BOOT_ID,
PARAM_FOLLOW,
PARAM_SYSLOG_IDENTIFIER,
LogFormat,
LogFormatter,
)
from ..utils.systemd_journal import journal_logs_reader
from .const import (
ATTR_AGENT_VERSION,
ATTR_APPARMOR_VERSION,
@ -38,26 +47,48 @@ from .const import (
ATTR_BROADCAST_MDNS,
ATTR_DT_SYNCHRONIZED,
ATTR_DT_UTC,
ATTR_FORCE,
ATTR_IDENTIFIERS,
ATTR_LLMNR_HOSTNAME,
ATTR_STARTUP_TIME,
ATTR_USE_NTP,
ATTR_VIRTUALIZATION,
CONTENT_TYPE_TEXT,
CONTENT_TYPE_X_LOG,
)
from .utils import api_process, api_validate
from .utils import api_process, api_process_raw, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
IDENTIFIER = "identifier"
BOOTID = "bootid"
DEFAULT_RANGE = 100
DEFAULT_LINES = 100
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_HOSTNAME): str})
# pylint: disable=no-value-for-parameter
SCHEMA_SHUTDOWN = vol.Schema(
{
vol.Optional(ATTR_FORCE, default=False): vol.Boolean(),
}
)
# pylint: enable=no-value-for-parameter
class APIHost(CoreSysAttributes):
"""Handle RESTful API for host functions."""
async def _check_ha_offline_migration(self, force: bool) -> None:
"""Check if HA has an offline migration in progress and raise if not forced."""
if (
not force
and (state := await self.sys_homeassistant.api.get_api_state())
and state.offline_db_migration
):
raise APIDBMigrationInProgress(
"Home Assistant offline database migration in progress, please wait until complete before shutting down host"
)
@api_process
async def info(self, request):
"""Return host information."""
@ -65,12 +96,13 @@ class APIHost(CoreSysAttributes):
ATTR_AGENT_VERSION: self.sys_dbus.agent.version,
ATTR_APPARMOR_VERSION: self.sys_host.apparmor.version,
ATTR_CHASSIS: self.sys_host.info.chassis,
ATTR_VIRTUALIZATION: self.sys_host.info.virtualization,
ATTR_CPE: self.sys_host.info.cpe,
ATTR_DEPLOYMENT: self.sys_host.info.deployment,
ATTR_DISK_FREE: self.sys_host.info.free_space,
ATTR_DISK_TOTAL: self.sys_host.info.total_space,
ATTR_DISK_USED: self.sys_host.info.used_space,
ATTR_DISK_LIFE_TIME: self.sys_host.info.disk_life_time,
ATTR_DISK_FREE: await self.sys_host.info.free_space(),
ATTR_DISK_TOTAL: await self.sys_host.info.total_space(),
ATTR_DISK_USED: await self.sys_host.info.used_space(),
ATTR_DISK_LIFE_TIME: await self.sys_host.info.disk_life_time(),
ATTR_FEATURES: self.sys_host.features,
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_LLMNR_HOSTNAME: self.sys_host.info.llmnr_hostname,
@ -98,14 +130,20 @@ class APIHost(CoreSysAttributes):
)
@api_process
def reboot(self, request):
async def reboot(self, request):
"""Reboot host."""
return asyncio.shield(self.sys_host.control.reboot())
body = await api_validate(SCHEMA_SHUTDOWN, request)
await self._check_ha_offline_migration(force=body[ATTR_FORCE])
return await asyncio.shield(self.sys_host.control.reboot())
@api_process
def shutdown(self, request):
async def shutdown(self, request):
"""Poweroff host."""
return asyncio.shield(self.sys_host.control.shutdown())
body = await api_validate(SCHEMA_SHUTDOWN, request)
await self._check_ha_offline_migration(force=body[ATTR_FORCE])
return await asyncio.shield(self.sys_host.control.shutdown())
@api_process
def reload(self, request):
@ -153,50 +191,94 @@ class APIHost(CoreSysAttributes):
raise APIError() from err
return possible_offset
@api_process
async def advanced_logs(
async def advanced_logs_handler(
self, request: web.Request, identifier: str | None = None, follow: bool = False
) -> web.StreamResponse:
"""Return systemd-journald logs."""
params = {}
log_formatter = LogFormatter.PLAIN
params: dict[str, Any] = {}
if identifier:
params[PARAM_SYSLOG_IDENTIFIER] = identifier
elif IDENTIFIER in request.match_info:
params[PARAM_SYSLOG_IDENTIFIER] = request.match_info.get(IDENTIFIER)
params[PARAM_SYSLOG_IDENTIFIER] = request.match_info[IDENTIFIER]
else:
params[PARAM_SYSLOG_IDENTIFIER] = self.sys_host.logs.default_identifiers
# host logs should be always verbose, no matter what Accept header is used
log_formatter = LogFormatter.VERBOSE
if BOOTID in request.match_info:
params[PARAM_BOOT_ID] = await self._get_boot_id(
request.match_info.get(BOOTID)
)
params[PARAM_BOOT_ID] = await self._get_boot_id(request.match_info[BOOTID])
if follow:
params[PARAM_FOLLOW] = ""
if ACCEPT in request.headers and request.headers[ACCEPT] not in [
CONTENT_TYPE_TEXT,
CONTENT_TYPE_X_LOG,
"*/*",
]:
raise APIError(
"Invalid content type requested. Only text/plain supported for now."
"Invalid content type requested. Only text/plain and text/x-log "
"supported for now."
)
if RANGE in request.headers:
range_header = request.headers.get(RANGE)
if "verbose" in request.query or request.headers[ACCEPT] == CONTENT_TYPE_X_LOG:
log_formatter = LogFormatter.VERBOSE
if "lines" in request.query:
lines = request.query.get("lines", DEFAULT_LINES)
try:
lines = int(lines)
except ValueError:
# If the user passed a non-integer value, just use the default instead of error.
lines = DEFAULT_LINES
finally:
# We can't use the entries= Range header syntax to refer to the last 1 line,
# and passing 1 to the calculation below would return the 1st line of the logs
# instead. Since this is really an edge case that doesn't matter much, we'll just
# return 2 lines at minimum.
lines = max(2, lines)
# entries=cursor[[:num_skip]:num_entries]
range_header = f"entries=:-{lines - 1}:{'' if follow else lines}"
elif RANGE in request.headers:
range_header = request.headers[RANGE]
else:
range_header = f"entries=:-{DEFAULT_RANGE}:"
range_header = (
f"entries=:-{DEFAULT_LINES - 1}:{'' if follow else DEFAULT_LINES}"
)
async with self.sys_host.logs.journald_logs(
params=params, range_header=range_header
params=params, range_header=range_header, accept=LogFormat.JOURNAL
) as resp:
try:
response = web.StreamResponse()
response.content_type = CONTENT_TYPE_TEXT
await response.prepare(request)
async for data in resp.content:
await response.write(data)
headers_returned = False
async for cursor, line in journal_logs_reader(resp, log_formatter):
try:
if not headers_returned:
if cursor:
response.headers["X-First-Cursor"] = cursor
response.headers["X-Accel-Buffering"] = "no"
await response.prepare(request)
headers_returned = True
await response.write(line.encode("utf-8") + b"\n")
except ClientConnectionResetError as err:
# When client closes the connection while reading busy logs, we
# sometimes get this exception. It should be safe to ignore it.
_LOGGER.debug(
"ClientConnectionResetError raised when returning journal logs: %s",
err,
)
break
except ConnectionResetError as ex:
raise APIError(
"Connection reset when trying to fetch data from systemd-journald."
) from ex
return response
@api_process_raw(CONTENT_TYPE_TEXT, error_type=CONTENT_TYPE_TEXT)
async def advanced_logs(
self, request: web.Request, identifier: str | None = None, follow: bool = False
) -> web.StreamResponse:
"""Return systemd-journald logs. Wrapped as standard API handler."""
return await self.advanced_logs_handler(request, identifier, follow)

View File

@ -1,4 +1,5 @@
"""Supervisor Add-on ingress service."""
import asyncio
from ipaddress import ip_address
import logging
@ -82,7 +83,7 @@ class APIIngress(CoreSysAttributes):
def _extract_addon(self, request: web.Request) -> Addon:
"""Return addon, throw an exception it it doesn't exist."""
token = request.match_info.get("token")
token = request.match_info["token"]
# Find correct add-on
addon = self.sys_ingress.get(token)
@ -131,7 +132,7 @@ class APIIngress(CoreSysAttributes):
@api_process
@require_home_assistant
async def validate_session(self, request: web.Request) -> dict[str, Any]:
async def validate_session(self, request: web.Request) -> None:
"""Validate session and extending how long it's valid for."""
data = await api_validate(VALIDATE_SESSION_DATA, request)
@ -146,14 +147,14 @@ class APIIngress(CoreSysAttributes):
"""Route data to Supervisor ingress service."""
# Check Ingress Session
session = request.cookies.get(COOKIE_INGRESS)
session = request.cookies.get(COOKIE_INGRESS, "")
if not self.sys_ingress.validate_session(session):
_LOGGER.warning("No valid ingress session %s", session)
raise HTTPUnauthorized()
# Process requests
addon = self._extract_addon(request)
path = request.match_info.get("path")
path = request.match_info.get("path", "")
session_data = self.sys_ingress.get_session_data(session)
try:
# Websocket
@ -182,7 +183,7 @@ class APIIngress(CoreSysAttributes):
for proto in request.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(",")
]
else:
req_protocols = ()
req_protocols = []
ws_server = web.WebSocketResponse(
protocols=req_protocols, autoclose=False, autoping=False
@ -276,8 +277,9 @@ class APIIngress(CoreSysAttributes):
response.content_type = content_type
try:
response.headers["X-Accel-Buffering"] = "no"
await response.prepare(request)
async for data in result.content.iter_chunked(4096):
async for data, _ in result.content.iter_chunks():
await response.write(data)
except (
@ -338,9 +340,10 @@ def _init_header(
headers[name] = value
# Update X-Forwarded-For
forward_for = request.headers.get(hdrs.X_FORWARDED_FOR)
connected_ip = ip_address(request.transport.get_extra_info("peername")[0])
headers[hdrs.X_FORWARDED_FOR] = f"{forward_for}, {connected_ip!s}"
if request.transport:
forward_for = request.headers.get(hdrs.X_FORWARDED_FOR)
connected_ip = ip_address(request.transport.get_extra_info("peername")[0])
headers[hdrs.X_FORWARDED_FOR] = f"{forward_for}, {connected_ip!s}"
return headers

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor Jobs RESTful API."""
import logging
from typing import Any
@ -6,6 +7,7 @@ from aiohttp import web
import voluptuous as vol
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, APINotFound, JobNotFound
from ..jobs import SupervisorJob
from ..jobs.const import ATTR_IGNORE_CONDITIONS, JobCondition
from .const import ATTR_JOBS
@ -21,10 +23,24 @@ SCHEMA_OPTIONS = vol.Schema(
class APIJobs(CoreSysAttributes):
"""Handle RESTful API for OS functions."""
def _list_jobs(self) -> list[dict[str, Any]]:
"""Return current job tree."""
def _extract_job(self, request: web.Request) -> SupervisorJob:
"""Extract job from request or raise."""
try:
return self.sys_jobs.get_job(request.match_info["uuid"])
except JobNotFound:
raise APINotFound("Job does not exist") from None
def _list_jobs(self, start: SupervisorJob | None = None) -> list[dict[str, Any]]:
"""Return current job tree.
Jobs are added to cache as they are created so by default they are in oldest to newest.
This is correct ordering for child jobs as it makes logical sense to present those in
the order they occurred within the parent. For the list as a whole, sort from newest
to oldest as its likely any client is most interested in the newer ones.
"""
# Initially sort oldest to newest so all child lists end up in correct order
jobs_by_parent: dict[str | None, list[SupervisorJob]] = {}
for job in self.sys_jobs.jobs:
for job in sorted(self.sys_jobs.jobs):
if job.internal:
continue
@ -33,10 +49,16 @@ class APIJobs(CoreSysAttributes):
else:
jobs_by_parent[job.parent_id].append(job)
# After parent-child organization, sort the root jobs only from newest to oldest
job_list: list[dict[str, Any]] = []
queue: list[tuple[list[dict[str, Any]], SupervisorJob]] = [
(job_list, job) for job in jobs_by_parent.get(None, [])
]
queue: list[tuple[list[dict[str, Any]], SupervisorJob]] = (
[(job_list, start)]
if start
else [
(job_list, job)
for job in sorted(jobs_by_parent.get(None, []), reverse=True)
]
)
while queue:
(current_list, current_job) = queue.pop(0)
@ -49,7 +71,10 @@ class APIJobs(CoreSysAttributes):
if current_job.uuid in jobs_by_parent:
queue.extend(
[(child_jobs, job) for job in jobs_by_parent.get(current_job.uuid)]
[
(child_jobs, job)
for job in jobs_by_parent.get(current_job.uuid, [])
]
)
return job_list
@ -70,11 +95,27 @@ class APIJobs(CoreSysAttributes):
if ATTR_IGNORE_CONDITIONS in body:
self.sys_jobs.ignore_conditions = body[ATTR_IGNORE_CONDITIONS]
self.sys_jobs.save_data()
await self.sys_jobs.save_data()
await self.sys_resolution.evaluate.evaluate_system()
@api_process
async def reset(self, request: web.Request) -> None:
"""Reset options for JobManager."""
self.sys_jobs.reset_data()
await self.sys_jobs.reset_data()
@api_process
async def job_info(self, request: web.Request) -> dict[str, Any]:
"""Get details of a job by ID."""
job = self._extract_job(request)
return self._list_jobs(job)[0]
@api_process
async def remove_job(self, request: web.Request) -> None:
"""Remove a completed job."""
job = self._extract_job(request)
if not job.done:
raise APIError(f"Job {job.uuid} is not done!")
self.sys_jobs.remove_job(job)

View File

@ -1,13 +1,17 @@
"""Handle security part of this API."""
from collections.abc import Callable
import logging
import re
from typing import Final
from urllib.parse import unquote
from aiohttp.web import Request, RequestHandler, Response, middleware
from aiohttp.web import Request, Response, middleware
from aiohttp.web_exceptions import HTTPBadRequest, HTTPForbidden, HTTPUnauthorized
from awesomeversion import AwesomeVersion
from supervisor.homeassistant.const import LANDINGPAGE
from ...addons.const import RE_SLUG
from ...const import (
REQUEST_FROM,
@ -20,7 +24,7 @@ from ...const import (
)
from ...coresys import CoreSys, CoreSysAttributes
from ...utils import version_is_new_enough
from ..utils import api_return_error, excract_supervisor_token
from ..utils import api_return_error, extract_supervisor_token
_LOGGER: logging.Logger = logging.getLogger(__name__)
_CORE_VERSION: Final = AwesomeVersion("2023.3.4")
@ -77,6 +81,13 @@ ADDONS_API_BYPASS: Final = re.compile(
r")$"
)
# Home Assistant only
CORE_ONLY_PATHS: Final = re.compile(
r"^(?:"
r"/addons/" + RE_SLUG + "/sys_options"
r")$"
)
# Policy role add-on API access
ADDONS_ROLE_ACCESS: dict[str, re.Pattern] = {
ROLE_DEFAULT: re.compile(
@ -103,6 +114,8 @@ ADDONS_ROLE_ACCESS: dict[str, re.Pattern] = {
r"|/addons(?:/" + RE_SLUG + r"/(?!security).+|/reload)?"
r"|/audio/.+"
r"|/auth/cache"
r"|/available_updates"
r"|/backups.*"
r"|/cli/.+"
r"|/core/.+"
r"|/dns/.+"
@ -112,16 +125,17 @@ ADDONS_ROLE_ACCESS: dict[str, re.Pattern] = {
r"|/hassos/.+"
r"|/homeassistant/.+"
r"|/host/.+"
r"|/mounts.*"
r"|/multicast/.+"
r"|/network/.+"
r"|/observer/.+"
r"|/os/.+"
r"|/os/(?!datadisk/wipe).+"
r"|/refresh_updates"
r"|/resolution/.+"
r"|/backups.*"
r"|/security/.+"
r"|/snapshots.*"
r"|/store.*"
r"|/supervisor/.+"
r"|/security/.+"
r")$"
),
ROLE_ADMIN: re.compile(
@ -166,9 +180,7 @@ class SecurityMiddleware(CoreSysAttributes):
return unquoted
@middleware
async def block_bad_requests(
self, request: Request, handler: RequestHandler
) -> Response:
async def block_bad_requests(self, request: Request, handler: Callable) -> Response:
"""Process request and tblock commonly known exploit attempts."""
if FILTERS.search(self._recursive_unquote(request.path)):
_LOGGER.warning(
@ -186,9 +198,7 @@ class SecurityMiddleware(CoreSysAttributes):
return await handler(request)
@middleware
async def system_validation(
self, request: Request, handler: RequestHandler
) -> Response:
async def system_validation(self, request: Request, handler: Callable) -> Response:
"""Check if core is ready to response."""
if self.sys_core.state not in (
CoreState.STARTUP,
@ -202,12 +212,10 @@ class SecurityMiddleware(CoreSysAttributes):
return await handler(request)
@middleware
async def token_validation(
self, request: Request, handler: RequestHandler
) -> Response:
async def token_validation(self, request: Request, handler: Callable) -> Response:
"""Check security access of this layer."""
request_from = None
supervisor_token = excract_supervisor_token(request)
request_from: CoreSysAttributes | None = None
supervisor_token = extract_supervisor_token(request)
# Blacklist
if BLACKLIST.match(request.path):
@ -229,6 +237,9 @@ class SecurityMiddleware(CoreSysAttributes):
if supervisor_token == self.sys_homeassistant.supervisor_token:
_LOGGER.debug("%s access from Home Assistant", request.path)
request_from = self.sys_homeassistant
elif CORE_ONLY_PATHS.match(request.path):
_LOGGER.warning("Attempted access to %s from client besides Home Assistant")
raise HTTPForbidden()
# Host
if supervisor_token == self.sys_plugins.cli.supervisor_token:
@ -272,10 +283,12 @@ class SecurityMiddleware(CoreSysAttributes):
raise HTTPForbidden()
@middleware
async def core_proxy(self, request: Request, handler: RequestHandler) -> Response:
async def core_proxy(self, request: Request, handler: Callable) -> Response:
"""Validate user from Core API proxy."""
if request[REQUEST_FROM] != self.sys_homeassistant or version_is_new_enough(
self.sys_homeassistant.version, _CORE_VERSION
if (
request[REQUEST_FROM] != self.sys_homeassistant
or self.sys_homeassistant.version == LANDINGPAGE
or version_is_new_enough(self.sys_homeassistant.version, _CORE_VERSION)
):
return await handler(request)

View File

@ -1,17 +1,17 @@
"""Inits file for supervisor mounts REST API."""
from typing import Any
from typing import Any, cast
from aiohttp import web
import voluptuous as vol
from ..const import ATTR_NAME, ATTR_STATE
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..exceptions import APIError, APINotFound
from ..mounts.const import ATTR_DEFAULT_BACKUP_MOUNT, MountUsage
from ..mounts.mount import Mount
from ..mounts.validate import SCHEMA_MOUNT_CONFIG
from .const import ATTR_MOUNTS
from ..mounts.validate import SCHEMA_MOUNT_CONFIG, MountData
from .const import ATTR_MOUNTS, ATTR_USER_PATH
from .utils import api_process, api_validate
SCHEMA_OPTIONS = vol.Schema(
@ -24,6 +24,13 @@ SCHEMA_OPTIONS = vol.Schema(
class APIMounts(CoreSysAttributes):
"""Handle REST API for mounting options."""
def _extract_mount(self, request: web.Request) -> Mount:
"""Extract mount from request or raise."""
name = request.match_info["mount"]
if name not in self.sys_mounts:
raise APINotFound(f"No mount exists with name {name}")
return self.sys_mounts.get(name)
@api_process
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return MountManager info."""
@ -32,7 +39,13 @@ class APIMounts(CoreSysAttributes):
if self.sys_mounts.default_backup_mount
else None,
ATTR_MOUNTS: [
mount.to_dict() | {ATTR_STATE: mount.state}
mount.to_dict()
| {
ATTR_STATE: mount.state,
ATTR_USER_PATH: mount.container_where.as_posix()
if mount.container_where
else None,
}
for mount in self.sys_mounts.mounts
],
}
@ -53,15 +66,15 @@ class APIMounts(CoreSysAttributes):
else:
self.sys_mounts.default_backup_mount = mount
self.sys_mounts.save_data()
await self.sys_mounts.save_data()
@api_process
async def create_mount(self, request: web.Request) -> None:
"""Create a new mount in supervisor."""
body = await api_validate(SCHEMA_MOUNT_CONFIG, request)
body = cast(MountData, await api_validate(SCHEMA_MOUNT_CONFIG, request))
if body[ATTR_NAME] in self.sys_mounts:
raise APIError(f"A mount already exists with name {body[ATTR_NAME]}")
if body["name"] in self.sys_mounts:
raise APIError(f"A mount already exists with name {body['name']}")
mount = Mount.from_dict(self.coresys, body)
await self.sys_mounts.create_mount(mount)
@ -74,19 +87,20 @@ class APIMounts(CoreSysAttributes):
if not self.sys_mounts.default_backup_mount:
self.sys_mounts.default_backup_mount = mount
self.sys_mounts.save_data()
await self.sys_mounts.save_data()
@api_process
async def update_mount(self, request: web.Request) -> None:
"""Update an existing mount in supervisor."""
name = request.match_info.get("mount")
current = self._extract_mount(request)
name_schema = vol.Schema(
{vol.Optional(ATTR_NAME, default=name): name}, extra=vol.ALLOW_EXTRA
{vol.Optional(ATTR_NAME, default=current.name): current.name},
extra=vol.ALLOW_EXTRA,
)
body = cast(
MountData,
await api_validate(vol.All(name_schema, SCHEMA_MOUNT_CONFIG), request),
)
body = await api_validate(vol.All(name_schema, SCHEMA_MOUNT_CONFIG), request)
if name not in self.sys_mounts:
raise APIError(f"No mount exists with name {name}")
mount = Mount.from_dict(self.coresys, body)
await self.sys_mounts.create_mount(mount)
@ -99,26 +113,26 @@ class APIMounts(CoreSysAttributes):
elif self.sys_mounts.default_backup_mount == mount:
self.sys_mounts.default_backup_mount = None
self.sys_mounts.save_data()
await self.sys_mounts.save_data()
@api_process
async def delete_mount(self, request: web.Request) -> None:
"""Delete an existing mount in supervisor."""
name = request.match_info.get("mount")
mount = await self.sys_mounts.remove_mount(name)
current = self._extract_mount(request)
mount = await self.sys_mounts.remove_mount(current.name)
# If it was a backup mount, reload backups
if mount.usage == MountUsage.BACKUP:
self.sys_create_task(self.sys_backups.reload())
self.sys_mounts.save_data()
await self.sys_mounts.save_data()
@api_process
async def reload_mount(self, request: web.Request) -> None:
"""Reload an existing mount in supervisor."""
name = request.match_info.get("mount")
await self.sys_mounts.reload_mount(name)
mount = self._extract_mount(request)
await self.sys_mounts.reload_mount(mount.name)
# If it's a backup mount, reload backups
if self.sys_mounts.get(name).usage == MountUsage.BACKUP:
if mount.usage == MountUsage.BACKUP:
self.sys_create_task(self.sys_backups.reload())

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor Multicast RESTful API."""
import asyncio
from collections.abc import Awaitable
import logging
@ -23,8 +24,7 @@ from ..const import (
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import version_tag
from .const import CONTENT_TYPE_BINARY
from .utils import api_process, api_process_raw, api_validate
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@ -69,11 +69,6 @@ class APIMulticast(CoreSysAttributes):
raise APIError(f"Version {version} is already in use")
await asyncio.shield(self.sys_plugins.multicast.update(version))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return Multicast Docker logs."""
return self.sys_plugins.multicast.logs()
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart Multicast plugin."""

View File

@ -1,8 +1,8 @@
"""REST API for network."""
import asyncio
from collections.abc import Awaitable
from dataclasses import replace
from ipaddress import ip_address, ip_interface
from ipaddress import IPv4Address, IPv4Interface, IPv6Address, IPv6Interface
from typing import Any
from aiohttp import web
@ -42,24 +42,34 @@ from ..const import (
DOCKER_NETWORK_MASK,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, HostNetworkNotFound
from ..exceptions import APIError, APINotFound, HostNetworkNotFound
from ..host.configuration import (
AccessPoint,
Interface,
InterfaceMethod,
IpConfig,
IpSetting,
VlanConfig,
WifiConfig,
)
from ..host.const import AuthMethod, InterfaceType, WifiMode
from .utils import api_process, api_validate
_SCHEMA_IP_CONFIG = vol.Schema(
_SCHEMA_IPV4_CONFIG = vol.Schema(
{
vol.Optional(ATTR_ADDRESS): [vol.Coerce(ip_interface)],
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv4Interface)],
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
vol.Optional(ATTR_GATEWAY): vol.Coerce(ip_address),
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(ip_address)],
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv4Address),
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv4Address)],
}
)
_SCHEMA_IPV6_CONFIG = vol.Schema(
{
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv6Interface)],
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv6Address),
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv6Address)],
}
)
@ -76,18 +86,18 @@ _SCHEMA_WIFI_CONFIG = vol.Schema(
# pylint: disable=no-value-for-parameter
SCHEMA_UPDATE = vol.Schema(
{
vol.Optional(ATTR_IPV4): _SCHEMA_IP_CONFIG,
vol.Optional(ATTR_IPV6): _SCHEMA_IP_CONFIG,
vol.Optional(ATTR_IPV4): _SCHEMA_IPV4_CONFIG,
vol.Optional(ATTR_IPV6): _SCHEMA_IPV6_CONFIG,
vol.Optional(ATTR_WIFI): _SCHEMA_WIFI_CONFIG,
vol.Optional(ATTR_ENABLED): vol.Boolean(),
}
)
def ipconfig_struct(config: IpConfig) -> dict[str, Any]:
def ipconfig_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
"""Return a dict with information about ip configuration."""
return {
ATTR_METHOD: config.method,
ATTR_METHOD: setting.method,
ATTR_ADDRESS: [address.with_prefixlen for address in config.address],
ATTR_NAMESERVERS: [str(address) for address in config.nameservers],
ATTR_GATEWAY: str(config.gateway) if config.gateway else None,
@ -122,8 +132,12 @@ def interface_struct(interface: Interface) -> dict[str, Any]:
ATTR_CONNECTED: interface.connected,
ATTR_PRIMARY: interface.primary,
ATTR_MAC: interface.mac,
ATTR_IPV4: ipconfig_struct(interface.ipv4) if interface.ipv4 else None,
ATTR_IPV6: ipconfig_struct(interface.ipv6) if interface.ipv6 else None,
ATTR_IPV4: ipconfig_struct(interface.ipv4, interface.ipv4setting)
if interface.ipv4 and interface.ipv4setting
else None,
ATTR_IPV6: ipconfig_struct(interface.ipv6, interface.ipv6setting)
if interface.ipv6 and interface.ipv6setting
else None,
ATTR_WIFI: wifi_struct(interface.wifi) if interface.wifi else None,
ATTR_VLAN: vlan_struct(interface.vlan) if interface.vlan else None,
}
@ -157,7 +171,7 @@ class APINetwork(CoreSysAttributes):
except HostNetworkNotFound:
pass
raise APIError(f"Interface {name} does not exist") from None
raise APINotFound(f"Interface {name} does not exist") from None
@api_process
async def info(self, request: web.Request) -> dict[str, Any]:
@ -180,14 +194,14 @@ class APINetwork(CoreSysAttributes):
@api_process
async def interface_info(self, request: web.Request) -> dict[str, Any]:
"""Return network information for a interface."""
interface = self._get_interface(request.match_info.get(ATTR_INTERFACE))
interface = self._get_interface(request.match_info[ATTR_INTERFACE])
return interface_struct(interface)
@api_process
async def interface_update(self, request: web.Request) -> None:
"""Update the configuration of an interface."""
interface = self._get_interface(request.match_info.get(ATTR_INTERFACE))
interface = self._get_interface(request.match_info[ATTR_INTERFACE])
# Validate data
body = await api_validate(SCHEMA_UPDATE, request)
@ -197,24 +211,26 @@ class APINetwork(CoreSysAttributes):
# Apply config
for key, config in body.items():
if key == ATTR_IPV4:
interface.ipv4 = replace(
interface.ipv4
or IpConfig(InterfaceMethod.STATIC, [], None, [], None),
**config,
interface.ipv4setting = IpSetting(
config.get(ATTR_METHOD, InterfaceMethod.STATIC),
config.get(ATTR_ADDRESS, []),
config.get(ATTR_GATEWAY),
config.get(ATTR_NAMESERVERS, []),
)
elif key == ATTR_IPV6:
interface.ipv6 = replace(
interface.ipv6
or IpConfig(InterfaceMethod.STATIC, [], None, [], None),
**config,
interface.ipv6setting = IpSetting(
config.get(ATTR_METHOD, InterfaceMethod.STATIC),
config.get(ATTR_ADDRESS, []),
config.get(ATTR_GATEWAY),
config.get(ATTR_NAMESERVERS, []),
)
elif key == ATTR_WIFI:
interface.wifi = replace(
interface.wifi
or WifiConfig(
WifiMode.INFRASTRUCTURE, "", AuthMethod.OPEN, None, None
),
**config,
interface.wifi = WifiConfig(
config.get(ATTR_MODE, WifiMode.INFRASTRUCTURE),
config.get(ATTR_SSID, ""),
config.get(ATTR_AUTH, AuthMethod.OPEN),
config.get(ATTR_PSK, None),
None,
)
elif key == ATTR_ENABLED:
interface.enabled = config
@ -231,7 +247,7 @@ class APINetwork(CoreSysAttributes):
@api_process
async def scan_accesspoints(self, request: web.Request) -> dict[str, Any]:
"""Scan and return a list of available networks."""
interface = self._get_interface(request.match_info.get(ATTR_INTERFACE))
interface = self._get_interface(request.match_info[ATTR_INTERFACE])
# Only wlan is supported
if interface.type != InterfaceType.WIRELESS:
@ -244,8 +260,10 @@ class APINetwork(CoreSysAttributes):
@api_process
async def create_vlan(self, request: web.Request) -> None:
"""Create a new vlan."""
interface = self._get_interface(request.match_info.get(ATTR_INTERFACE))
vlan = int(request.match_info.get(ATTR_VLAN))
interface = self._get_interface(request.match_info[ATTR_INTERFACE])
vlan = int(request.match_info.get(ATTR_VLAN, -1))
if vlan < 0:
raise APIError(f"Invalid vlan specified: {vlan}")
# Only ethernet is supported
if interface.type != InterfaceType.ETHERNET:
@ -256,24 +274,22 @@ class APINetwork(CoreSysAttributes):
vlan_config = VlanConfig(vlan, interface.name)
ipv4_config = None
ipv4_setting = None
if ATTR_IPV4 in body:
ipv4_config = IpConfig(
ipv4_setting = IpSetting(
body[ATTR_IPV4].get(ATTR_METHOD, InterfaceMethod.AUTO),
body[ATTR_IPV4].get(ATTR_ADDRESS, []),
body[ATTR_IPV4].get(ATTR_GATEWAY, None),
body[ATTR_IPV4].get(ATTR_NAMESERVERS, []),
None,
)
ipv6_config = None
ipv6_setting = None
if ATTR_IPV6 in body:
ipv6_config = IpConfig(
ipv6_setting = IpSetting(
body[ATTR_IPV6].get(ATTR_METHOD, InterfaceMethod.AUTO),
body[ATTR_IPV6].get(ATTR_ADDRESS, []),
body[ATTR_IPV6].get(ATTR_GATEWAY, None),
body[ATTR_IPV6].get(ATTR_NAMESERVERS, []),
None,
)
vlan_interface = Interface(
@ -284,8 +300,10 @@ class APINetwork(CoreSysAttributes):
True,
False,
InterfaceType.VLAN,
ipv4_config,
ipv6_config,
None,
ipv4_setting,
None,
ipv6_setting,
None,
vlan_config,
)

View File

@ -1,4 +1,5 @@
"""Init file for Supervisor Observer RESTful API."""
import asyncio
import logging
from typing import Any

View File

@ -1,7 +1,9 @@
"""Init file for Supervisor HassOS RESTful API."""
import asyncio
from collections.abc import Awaitable
import logging
import re
from typing import Any
from aiohttp import web
@ -19,22 +21,29 @@ from ..const import (
ATTR_POWER_LED,
ATTR_SERIAL,
ATTR_SIZE,
ATTR_STATE,
ATTR_SWAP_SIZE,
ATTR_SWAPPINESS,
ATTR_UPDATE_AVAILABLE,
ATTR_VERSION,
ATTR_VERSION_LATEST,
)
from ..coresys import CoreSysAttributes
from ..exceptions import BoardInvalidError
from ..exceptions import APINotFound, BoardInvalidError
from ..resolution.const import ContextType, IssueType, SuggestionType
from ..validate import version_tag
from .const import (
ATTR_BOOT_SLOT,
ATTR_BOOT_SLOTS,
ATTR_DATA_DISK,
ATTR_DEV_PATH,
ATTR_DEVICE,
ATTR_DISKS,
ATTR_MODEL,
ATTR_STATUS,
ATTR_SYSTEM_HEALTH_LED,
ATTR_VENDOR,
BootSlot,
)
from .utils import api_process, api_validate
@ -42,6 +51,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
# pylint: disable=no-value-for-parameter
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
SCHEMA_SET_BOOT_SLOT = vol.Schema({vol.Required(ATTR_BOOT_SLOT): vol.Coerce(BootSlot)})
SCHEMA_DISK = vol.Schema({vol.Required(ATTR_DEVICE): str})
SCHEMA_YELLOW_OPTIONS = vol.Schema(
@ -58,6 +68,15 @@ SCHEMA_GREEN_OPTIONS = vol.Schema(
vol.Optional(ATTR_SYSTEM_HEALTH_LED): vol.Boolean(),
}
)
RE_SWAP_SIZE = re.compile(r"^\d+([KMG](i?B)?|B)?$", re.IGNORECASE)
SCHEMA_SWAP_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_SWAP_SIZE): vol.Match(RE_SWAP_SIZE),
vol.Optional(ATTR_SWAPPINESS): vol.All(int, vol.Range(min=0, max=200)),
}
)
# pylint: enable=no-value-for-parameter
@ -74,6 +93,15 @@ class APIOS(CoreSysAttributes):
ATTR_BOARD: self.sys_os.board,
ATTR_BOOT: self.sys_dbus.rauc.boot_slot,
ATTR_DATA_DISK: self.sys_os.datadisk.disk_used_id,
ATTR_BOOT_SLOTS: {
slot.bootname: {
ATTR_STATE: slot.state,
ATTR_STATUS: slot.boot_status,
ATTR_VERSION: slot.bundle_version,
}
for slot in self.sys_os.slots
if slot.bootname
},
}
@api_process
@ -96,6 +124,17 @@ class APIOS(CoreSysAttributes):
await asyncio.shield(self.sys_os.datadisk.migrate_disk(body[ATTR_DEVICE]))
@api_process
def wipe_data(self, request: web.Request) -> Awaitable[None]:
"""Trigger data disk wipe on Host."""
return asyncio.shield(self.sys_os.datadisk.wipe_disk())
@api_process
async def set_boot_slot(self, request: web.Request) -> None:
"""Change the active boot slot and reboot into it."""
body = await api_validate(SCHEMA_SET_BOOT_SLOT, request)
await asyncio.shield(self.sys_os.set_boot_slot(body[ATTR_BOOT_SLOT]))
@api_process
async def list_data(self, request: web.Request) -> dict[str, Any]:
"""Return possible data targets."""
@ -130,15 +169,19 @@ class APIOS(CoreSysAttributes):
body = await api_validate(SCHEMA_GREEN_OPTIONS, request)
if ATTR_ACTIVITY_LED in body:
self.sys_dbus.agent.board.green.activity_led = body[ATTR_ACTIVITY_LED]
await self.sys_dbus.agent.board.green.set_activity_led(
body[ATTR_ACTIVITY_LED]
)
if ATTR_POWER_LED in body:
self.sys_dbus.agent.board.green.power_led = body[ATTR_POWER_LED]
await self.sys_dbus.agent.board.green.set_power_led(body[ATTR_POWER_LED])
if ATTR_SYSTEM_HEALTH_LED in body:
self.sys_dbus.agent.board.green.user_led = body[ATTR_SYSTEM_HEALTH_LED]
await self.sys_dbus.agent.board.green.set_user_led(
body[ATTR_SYSTEM_HEALTH_LED]
)
self.sys_dbus.agent.board.green.save_data()
await self.sys_dbus.agent.board.green.save_data()
@api_process
async def boards_yellow_info(self, request: web.Request) -> dict[str, Any]:
@ -155,15 +198,17 @@ class APIOS(CoreSysAttributes):
body = await api_validate(SCHEMA_YELLOW_OPTIONS, request)
if ATTR_DISK_LED in body:
self.sys_dbus.agent.board.yellow.disk_led = body[ATTR_DISK_LED]
await self.sys_dbus.agent.board.yellow.set_disk_led(body[ATTR_DISK_LED])
if ATTR_HEARTBEAT_LED in body:
self.sys_dbus.agent.board.yellow.heartbeat_led = body[ATTR_HEARTBEAT_LED]
await self.sys_dbus.agent.board.yellow.set_heartbeat_led(
body[ATTR_HEARTBEAT_LED]
)
if ATTR_POWER_LED in body:
self.sys_dbus.agent.board.yellow.power_led = body[ATTR_POWER_LED]
await self.sys_dbus.agent.board.yellow.set_power_led(body[ATTR_POWER_LED])
self.sys_dbus.agent.board.yellow.save_data()
await self.sys_dbus.agent.board.yellow.save_data()
self.sys_resolution.create_issue(
IssueType.REBOOT_REQUIRED,
ContextType.SYSTEM,
@ -179,3 +224,53 @@ class APIOS(CoreSysAttributes):
)
return {}
@api_process
async def config_swap_info(self, request: web.Request) -> dict[str, Any]:
"""Get swap settings."""
if (
not self.coresys.os.available
or not self.coresys.os.version
or self.coresys.os.version < "15.0"
):
raise APINotFound(
"Home Assistant OS 15.0 or newer required for swap settings"
)
return {
ATTR_SWAP_SIZE: self.sys_dbus.agent.swap.swap_size,
ATTR_SWAPPINESS: self.sys_dbus.agent.swap.swappiness,
}
@api_process
async def config_swap_options(self, request: web.Request) -> None:
"""Update swap settings."""
if (
not self.coresys.os.available
or not self.coresys.os.version
or self.coresys.os.version < "15.0"
):
raise APINotFound(
"Home Assistant OS 15.0 or newer required for swap settings"
)
body = await api_validate(SCHEMA_SWAP_OPTIONS, request)
reboot_required = False
if ATTR_SWAP_SIZE in body:
old_size = self.sys_dbus.agent.swap.swap_size
await self.sys_dbus.agent.swap.set_swap_size(body[ATTR_SWAP_SIZE])
reboot_required = reboot_required or old_size != body[ATTR_SWAP_SIZE]
if ATTR_SWAPPINESS in body:
old_swappiness = self.sys_dbus.agent.swap.swappiness
await self.sys_dbus.agent.swap.set_swappiness(body[ATTR_SWAPPINESS])
reboot_required = reboot_required or old_swappiness != body[ATTR_SWAPPINESS]
if reboot_required:
self.sys_resolution.create_issue(
IssueType.REBOOT_REQUIRED,
ContextType.SYSTEM,
suggestions=[SuggestionType.EXECUTE_REBOOT],
)

View File

@ -1 +1 @@
!function(){function n(n){var t=document.createElement("script");t.src=n,document.body.appendChild(t)}if(/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent))n("/api/hassio/app/frontend_es5/entrypoint-5yRSddAJzJ4.js");else try{new Function("import('/api/hassio/app/frontend_latest/entrypoint-qzB1D0O4L9U.js')")()}catch(t){n("/api/hassio/app/frontend_es5/entrypoint-5yRSddAJzJ4.js")}}()
!function(){function d(d){var e=document.createElement("script");e.src=d,document.body.appendChild(e)}if(/Edge?\/(12[4-9]|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(12[5-9]|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(109|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(17\.([5-9]|\d{2,})|(1[89]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(1{2}\d|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](12[4-9]|1[3-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(12[5-9]|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(12[4-9]|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/(2[5-9]|[3-9]\d|\d{3,})\.\d+|Home As{2}istant\/[\d.]+ \(.+; macOS (1[2-9]|[2-9]\d|\d{3,})\.\d+(\.\d+)?\)/.test(navigator.userAgent))try{new Function("import('/api/hassio/app/frontend_latest/entrypoint.35399ae87c70acf8.js')")()}catch(e){d("/api/hassio/app/frontend_es5/entrypoint.476bfed22da63267.js")}else d("/api/hassio/app/frontend_es5/entrypoint.476bfed22da63267.js")}()

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[1047],{32594:function(e,t,r){r.d(t,{U:function(){return n}});var n=function(e){return e.stopPropagation()}},75054:function(e,t,r){r.r(t),r.d(t,{HaTimeDuration:function(){return f}});var n,a=r(88962),i=r(33368),o=r(71650),d=r(82390),u=r(69205),l=r(70906),s=r(91808),c=r(68144),v=r(79932),f=(r(47289),(0,s.Z)([(0,v.Mo)("ha-selector-duration")],(function(e,t){var r=function(t){(0,u.Z)(n,t);var r=(0,l.Z)(n);function n(){var t;(0,o.Z)(this,n);for(var a=arguments.length,i=new Array(a),u=0;u<a;u++)i[u]=arguments[u];return t=r.call.apply(r,[this].concat(i)),e((0,d.Z)(t)),t}return(0,i.Z)(n)}(t);return{F:r,d:[{kind:"field",decorators:[(0,v.Cb)({attribute:!1})],key:"hass",value:void 0},{kind:"field",decorators:[(0,v.Cb)({attribute:!1})],key:"selector",value:void 0},{kind:"field",decorators:[(0,v.Cb)({attribute:!1})],key:"value",value:void 0},{kind:"field",decorators:[(0,v.Cb)()],key:"label",value:void 0},{kind:"field",decorators:[(0,v.Cb)()],key:"helper",value:void 0},{kind:"field",decorators:[(0,v.Cb)({type:Boolean})],key:"disabled",value:function(){return!1}},{kind:"field",decorators:[(0,v.Cb)({type:Boolean})],key:"required",value:function(){return!0}},{kind:"method",key:"render",value:function(){var e;return(0,c.dy)(n||(n=(0,a.Z)([' <ha-duration-input .label="','" .helper="','" .data="','" .disabled="','" .required="','" ?enableDay="','"></ha-duration-input> '])),this.label,this.helper,this.value,this.disabled,this.required,null===(e=this.selector.duration)||void 0===e?void 0:e.enable_day)}}]}}),c.oi))}}]);
//# sourceMappingURL=1047-g7fFLS9eP4I.js.map

View File

@ -1 +0,0 @@
{"version":3,"file":"1047-g7fFLS9eP4I.js","mappings":"yKAAO,IAAMA,EAAkB,SAACC,GAAE,OAAKA,EAAGD,iBAAiB,C,qLCQ9CE,G,UAAcC,EAAAA,EAAAA,GAAA,EAD1BC,EAAAA,EAAAA,IAAc,0BAAuB,SAAAC,EAAAC,GAAA,IACzBJ,EAAc,SAAAK,IAAAC,EAAAA,EAAAA,GAAAN,EAAAK,GAAA,IAAAE,GAAAC,EAAAA,EAAAA,GAAAR,GAAA,SAAAA,IAAA,IAAAS,GAAAC,EAAAA,EAAAA,GAAA,KAAAV,GAAA,QAAAW,EAAAC,UAAAC,OAAAC,EAAA,IAAAC,MAAAJ,GAAAK,EAAA,EAAAA,EAAAL,EAAAK,IAAAF,EAAAE,GAAAJ,UAAAI,GAAA,OAAAP,EAAAF,EAAAU,KAAAC,MAAAX,EAAA,OAAAY,OAAAL,IAAAX,GAAAiB,EAAAA,EAAAA,GAAAX,IAAAA,CAAA,QAAAY,EAAAA,EAAAA,GAAArB,EAAA,EAAAI,GAAA,OAAAkB,EAAdtB,EAAcuB,EAAA,EAAAC,KAAA,QAAAC,WAAA,EACxBC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,OAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,WAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,QAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,OAAUE,IAAA,QAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,OAAUE,IAAA,SAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,WAAAC,MAAA,kBAAmB,CAAK,IAAAL,KAAA,QAAAC,WAAA,EAEnDC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,WAAAC,MAAA,kBAAmB,CAAI,IAAAL,KAAA,SAAAI,IAAA,SAAAC,MAEnD,WAAmB,IAAAG,EACjB,OAAOC,EAAAA,EAAAA,IAAIC,IAAAA,GAAAC,EAAAA,EAAAA,GAAA,wIAEEC,KAAKC,MACJD,KAAKE,OACPF,KAAKP,MACDO,KAAKG,SACLH,KAAKI,SACkB,QADVR,EACZI,KAAKK,SAASC,gBAAQ,IAAAV,OAAA,EAAtBA,EAAwBW,WAG3C,IAAC,GA1BiCC,EAAAA,I","sources":["https://raw.githubusercontent.com/home-assistant/frontend/20230703.0/src/common/dom/stop_propagation.ts","https://raw.githubusercontent.com/home-assistant/frontend/20230703.0/src/components/ha-selector/ha-selector-duration.ts"],"names":["stopPropagation","ev","HaTimeDuration","_decorate","customElement","_initialize","_LitElement","_LitElement2","_inherits","_super","_createSuper","_this","_classCallCheck","_len","arguments","length","args","Array","_key","call","apply","concat","_assertThisInitialized","_createClass","F","d","kind","decorators","property","attribute","key","value","type","Boolean","_this$selector$durati","html","_templateObject","_taggedTemplateLiteral","this","label","helper","disabled","required","selector","duration","enable_day","LitElement"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"version":3,"file":"1081.91949d686e61cc12.js","sources":["https://raw.githubusercontent.com/home-assistant/frontend/20250401.0/src/components/ha-button-toggle-group.ts","https://raw.githubusercontent.com/home-assistant/frontend/20250401.0/src/components/ha-selector/ha-selector-button-toggle.ts"],"names":["_decorate","customElement","_initialize","_LitElement","F","constructor","args","d","kind","decorators","property","attribute","key","value","type","Boolean","queryAll","html","_t","_","this","buttons","map","button","iconPath","_t2","label","active","_handleClick","_t3","styleMap","width","fullWidth","length","dense","_this$_buttons","_buttons","forEach","async","updateComplete","shadowRoot","querySelector","style","margin","ev","currentTarget","fireEvent","static","css","_t4","LitElement","HaButtonToggleSelector","_this$selector$button","_this$selector$button2","_this$selector$button3","options","selector","button_toggle","option","translationKey","translation_key","localizeValue","localizedLabel","sort","a","b","caseInsensitiveStringCompare","hass","locale","language","toggleButtons","item","_valueChanged","_ev$detail","_this$value","stopPropagation","detail","target","disabled","undefined"],"mappings":"qXAWgCA,EAAAA,EAAAA,GAAA,EAD/BC,EAAAA,EAAAA,IAAc,4BAAyB,SAAAC,EAAAC,GAkIvC,OAAAC,EAlID,cACgCD,EAAoBE,WAAAA,IAAAC,GAAA,SAAAA,GAAAJ,EAAA,QAApBK,EAAA,EAAAC,KAAA,QAAAC,WAAA,EAC7BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,UAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,OAAUE,IAAA,SAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,IAAS,CAAEC,UAAW,aAAcG,KAAMC,WAAUH,IAAA,YAAAC,KAAAA,GAAA,OAClC,CAAK,IAAAL,KAAA,QAAAC,WAAA,EAEvBC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,QAAAC,KAAAA,GAAA,OAAgB,CAAK,IAAAL,KAAA,QAAAC,WAAA,EAEhDO,EAAAA,EAAAA,IAAS,eAAaJ,IAAA,WAAAC,WAAA,IAAAL,KAAA,SAAAI,IAAA,SAAAC,MAEvB,WACE,OAAOI,EAAAA,EAAAA,IAAIC,IAAAA,EAAAC,CAAA,uBAELC,KAAKC,QAAQC,KAAKC,GAClBA,EAAOC,UACHP,EAAAA,EAAAA,IAAIQ,IAAAA,EAAAN,CAAA,2GACOI,EAAOG,MACRH,EAAOC,SACND,EAAOV,MACNO,KAAKO,SAAWJ,EAAOV,MACxBO,KAAKQ,eAEhBX,EAAAA,EAAAA,IAAIY,IAAAA,EAAAV,CAAA,iHACMW,EAAAA,EAAAA,GAAS,CACfC,MAAOX,KAAKY,UACL,IAAMZ,KAAKC,QAAQY,OAAtB,IACA,YAGGb,KAAKc,MACLX,EAAOV,MACNO,KAAKO,SAAWJ,EAAOV,MACxBO,KAAKQ,aACXL,EAAOG,SAKxB,GAAC,CAAAlB,KAAA,SAAAI,IAAA,UAAAC,MAED,WAAoB,IAAAsB,EAEL,QAAbA,EAAAf,KAAKgB,gBAAQ,IAAAD,GAAbA,EAAeE,SAAQC,gBACff,EAAOgB,eAEXhB,EAAOiB,WAAYC,cAAc,UACjCC,MAAMC,OAAS,GAAG,GAExB,GAAC,CAAAnC,KAAA,SAAAI,IAAA,eAAAC,MAED,SAAqB+B,GACnBxB,KAAKO,OAASiB,EAAGC,cAAchC,OAC/BiC,EAAAA,EAAAA,GAAU1B,KAAM,gBAAiB,CAAEP,MAAOO,KAAKO,QACjD,GAAC,CAAAnB,KAAA,QAAAuC,QAAA,EAAAnC,IAAA,SAAAC,KAAAA,GAAA,OAEemC,EAAAA,EAAAA,IAAGC,IAAAA,EAAA9B,CAAA,u0CAzDoB+B,EAAAA,I,MCD5BC,GAAsBnD,EAAAA,EAAAA,GAAA,EADlCC,EAAAA,EAAAA,IAAc,+BAA4B,SAAAC,EAAAC,GA4F1C,OAAAC,EA5FD,cACmCD,EAAoBE,WAAAA,IAAAC,GAAA,SAAAA,GAAAJ,EAAA,QAApBK,EAAA,EAAAC,KAAA,QAAAC,WAAA,EAChCC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,OAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,WAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,OAAUE,IAAA,QAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,OAAUE,IAAA,QAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,OAAUE,IAAA,SAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,gBAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAG9BC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,WAAAC,KAAAA,GAAA,OAAmB,CAAK,IAAAL,KAAA,QAAAC,WAAA,EAEnDC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,WAAAC,KAAAA,GAAA,OAAmB,CAAI,IAAAL,KAAA,SAAAI,IAAA,SAAAC,MAEnD,WAAmB,IAAAuC,EAAAC,EAAAC,EACjB,MAAMC,GACuB,QAA3BH,EAAAhC,KAAKoC,SAASC,qBAAa,IAAAL,GAAS,QAATA,EAA3BA,EAA6BG,eAAO,IAAAH,OAAA,EAApCA,EAAsC9B,KAAKoC,GACvB,iBAAXA,EACFA,EACA,CAAE7C,MAAO6C,EAAQhC,MAAOgC,OAC1B,GAEDC,EAA4C,QAA9BN,EAAGjC,KAAKoC,SAASC,qBAAa,IAAAJ,OAAA,EAA3BA,EAA6BO,gBAEhDxC,KAAKyC,eAAiBF,GACxBJ,EAAQlB,SAASqB,IACf,MAAMI,EAAiB1C,KAAKyC,cAC1B,GAAGF,aAA0BD,EAAO7C,SAElCiD,IACFJ,EAAOhC,MAAQoC,EACjB,IAI2B,QAA/BR,EAAIlC,KAAKoC,SAASC,qBAAa,IAAAH,GAA3BA,EAA6BS,MAC/BR,EAAQQ,MAAK,CAACC,EAAGC,KACfC,EAAAA,EAAAA,IACEF,EAAEtC,MACFuC,EAAEvC,MACFN,KAAK+C,KAAKC,OAAOC,YAKvB,MAAMC,EAAgCf,EAAQjC,KAAKiD,IAAkB,CACnE7C,MAAO6C,EAAK7C,MACZb,MAAO0D,EAAK1D,UAGd,OAAOI,EAAAA,EAAAA,IAAIC,IAAAA,EAAAC,CAAA,iHACPC,KAAKM,MAEM4C,EACDlD,KAAKP,MACEO,KAAKoD,cAG5B,GAAC,CAAAhE,KAAA,SAAAI,IAAA,gBAAAC,MAED,SAAsB+B,GAAI,IAAA6B,EAAAC,EACxB9B,EAAG+B,kBAEH,MAAM9D,GAAiB,QAAT4D,EAAA7B,EAAGgC,cAAM,IAAAH,OAAA,EAATA,EAAW5D,QAAS+B,EAAGiC,OAAOhE,MACxCO,KAAK0D,eAAsBC,IAAVlE,GAAuBA,KAAqB,QAAhB6D,EAAMtD,KAAKP,aAAK,IAAA6D,EAAAA,EAAI,MAGrE5B,EAAAA,EAAAA,GAAU1B,KAAM,gBAAiB,CAC/BP,MAAOA,GAEX,GAAC,CAAAL,KAAA,QAAAuC,QAAA,EAAAnC,IAAA,SAAAC,KAAAA,GAAA,OAEemC,EAAAA,EAAAA,IAAGvB,IAAAA,EAAAN,CAAA,wLA5EuB+B,EAAAA,G"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([["12"],{5739:function(e,a,t){t.a(e,(async function(e,i){try{t.r(a),t.d(a,{HaNavigationSelector:()=>c});var d=t(73577),r=(t(71695),t(47021),t(57243)),n=t(50778),l=t(36522),o=t(63297),s=e([o]);o=(s.then?(await s)():s)[0];let u,h=e=>e,c=(0,d.Z)([(0,n.Mo)("ha-selector-navigation")],(function(e,a){return{F:class extends a{constructor(...a){super(...a),e(this)}},d:[{kind:"field",decorators:[(0,n.Cb)({attribute:!1})],key:"hass",value:void 0},{kind:"field",decorators:[(0,n.Cb)({attribute:!1})],key:"selector",value:void 0},{kind:"field",decorators:[(0,n.Cb)()],key:"value",value:void 0},{kind:"field",decorators:[(0,n.Cb)()],key:"label",value:void 0},{kind:"field",decorators:[(0,n.Cb)()],key:"helper",value:void 0},{kind:"field",decorators:[(0,n.Cb)({type:Boolean,reflect:!0})],key:"disabled",value(){return!1}},{kind:"field",decorators:[(0,n.Cb)({type:Boolean})],key:"required",value(){return!0}},{kind:"method",key:"render",value:function(){return(0,r.dy)(u||(u=h` <ha-navigation-picker .hass="${0}" .label="${0}" .value="${0}" .required="${0}" .disabled="${0}" .helper="${0}" @value-changed="${0}"></ha-navigation-picker> `),this.hass,this.label,this.value,this.required,this.disabled,this.helper,this._valueChanged)}},{kind:"method",key:"_valueChanged",value:function(e){(0,l.B)(this,"value-changed",{value:e.detail.value})}}]}}),r.oi);i()}catch(u){i(u)}}))}}]);
//# sourceMappingURL=12.ffa1bdc0a98802fa.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"12.ffa1bdc0a98802fa.js","sources":["https://raw.githubusercontent.com/home-assistant/frontend/20250401.0/src/components/ha-selector/ha-selector-navigation.ts"],"names":["HaNavigationSelector","_decorate","customElement","_initialize","_LitElement","F","constructor","args","d","kind","decorators","property","attribute","key","value","type","Boolean","reflect","html","_t","_","this","hass","label","required","disabled","helper","_valueChanged","ev","fireEvent","detail","LitElement"],"mappings":"mVAQaA,GAAoBC,EAAAA,EAAAA,GAAA,EADhCC,EAAAA,EAAAA,IAAc,4BAAyB,SAAAC,EAAAC,GAiCvC,OAAAC,EAjCD,cACiCD,EAAoBE,WAAAA,IAAAC,GAAA,SAAAA,GAAAJ,EAAA,QAApBK,EAAA,EAAAC,KAAA,QAAAC,WAAA,EAC9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,OAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,WAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,OAAUE,IAAA,QAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,OAAUE,IAAA,QAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,OAAUE,IAAA,SAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAEVC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,QAASC,SAAS,KAAOJ,IAAA,WAAAC,KAAAA,GAAA,OAAmB,CAAK,IAAAL,KAAA,QAAAC,WAAA,EAElEC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,WAAAC,KAAAA,GAAA,OAAmB,CAAI,IAAAL,KAAA,SAAAI,IAAA,SAAAC,MAEnD,WACE,OAAOI,EAAAA,EAAAA,IAAIC,IAAAA,EAAAC,CAAA,mKAECC,KAAKC,KACJD,KAAKE,MACLF,KAAKP,MACFO,KAAKG,SACLH,KAAKI,SACPJ,KAAKK,OACEL,KAAKM,cAG5B,GAAC,CAAAlB,KAAA,SAAAI,IAAA,gBAAAC,MAED,SAAsBc,IACpBC,EAAAA,EAAAA,GAAUR,KAAM,gBAAiB,CAAEP,MAAOc,EAAGE,OAAOhB,OACtD,IAAC,GA/BuCiB,EAAAA,I"}

View File

@ -0,0 +1,2 @@
(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([["1236"],{4121:function(){Intl.PluralRules&&"function"==typeof Intl.PluralRules.__addLocaleData&&Intl.PluralRules.__addLocaleData({data:{categories:{cardinal:["one","other"],ordinal:["one","two","few","other"]},fn:function(e,n){var t=String(e).split("."),a=!t[1],l=Number(t[0])==e,o=l&&t[0].slice(-1),r=l&&t[0].slice(-2);return n?1==o&&11!=r?"one":2==o&&12!=r?"two":3==o&&13!=r?"few":"other":1==e&&a?"one":"other"}},locale:"en"})}}]);
//# sourceMappingURL=1236.64ca65d0ea4d76d4.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"1236.64ca65d0ea4d76d4.js","sources":["/unknown/node_modules/@formatjs/intl-pluralrules/locale-data/en.js"],"names":["Intl","PluralRules","__addLocaleData","n","ord","s","String","split","v0","t0","Number","n10","slice","n100"],"mappings":"wHAEIA,KAAKC,aAA2D,mBAArCD,KAAKC,YAAYC,iBAC9CF,KAAKC,YAAYC,gBAAgB,CAAC,KAAO,CAAC,WAAa,CAAC,SAAW,CAAC,MAAM,SAAS,QAAU,CAAC,MAAM,MAAM,MAAM,UAAU,GAAK,SAASC,EAAGC,GAC3I,IAAIC,EAAIC,OAAOH,GAAGI,MAAM,KAAMC,GAAMH,EAAE,GAAII,EAAKC,OAAOL,EAAE,KAAOF,EAAGQ,EAAMF,GAAMJ,EAAE,GAAGO,OAAO,GAAIC,EAAOJ,GAAMJ,EAAE,GAAGO,OAAO,GACvH,OAAIR,EAAmB,GAAPO,GAAoB,IAARE,EAAa,MAC9B,GAAPF,GAAoB,IAARE,EAAa,MAClB,GAAPF,GAAoB,IAARE,EAAa,MACzB,QACQ,GAALV,GAAUK,EAAK,MAAQ,OAChC,GAAG,OAAS,M"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([["1295"],{21393:function(s,n,e){e.r(n)}}]);

Some files were not shown because too many files have changed in this diff Show More