Compare commits

...

135 Commits

Author SHA1 Message Date
dependabot[bot]
afa467a32b Bump pyupgrade from 3.13.0 to 3.14.0 (#4599)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 3.13.0 to 3.14.0.
- [Commits](https://github.com/asottile/pyupgrade/compare/v3.13.0...v3.14.0)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2023-10-03 13:35:10 -04:00
dependabot[bot]
274218d48e Bump pylint from 2.17.7 to 3.0.0 (#4600)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 19:32:18 +02:00
dependabot[bot]
7e73df26ab Bump coverage from 7.3.1 to 7.3.2 (#4598)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 19:29:46 +02:00
dependabot[bot]
ef8fc80c95 Bump actions/setup-python from 4.7.0 to 4.7.1 (#4597)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 08:51:10 +02:00
dependabot[bot]
05c39144e3 Bump urllib3 from 2.0.5 to 2.0.6 (#4596)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 08:18:08 +02:00
dependabot[bot]
f5cd35af47 Bump pylint from 2.17.6 to 2.17.7 (#4594)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 08:56:07 +02:00
dependabot[bot]
c69ecdafd0 Bump home-assistant/wheels from 2023.09.1 to 2023.10.1 (#4593)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 08:50:39 +02:00
Mike Degatano
fa90c247ec Correct /store/addons api output (#4589) 2023-09-29 09:17:39 -04:00
Mike Degatano
0cd7bd47bb Skip watchdog API test on landingpage (#4588)
* Skip watchdog API test on landingpage

* Skip check from task
2023-09-29 09:17:22 -04:00
dependabot[bot]
36d48d19fc Bump dbus-fast from 2.2.0 to 2.10.0 (#4583)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 2.2.0 to 2.10.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.2.0...v2.10.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>
2023-09-26 16:46:18 -04:00
Mike Degatano
9322b68d47 Change User LED to System Health LED (#4586) 2023-09-26 14:54:41 -04:00
dependabot[bot]
e11ff64b15 Bump pyupgrade from 3.10.1 to 3.13.0 (#4581)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 3.10.1 to 3.13.0.
- [Commits](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.13.0)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2023-09-26 14:36:00 -04:00
dependabot[bot]
3776dabfcf Bump cryptography from 41.0.3 to 41.0.4 (#4571)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 20:23:31 +02:00
dependabot[bot]
d4e5831f0f Bump gitpython from 3.1.36 to 3.1.37 (#4582)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 13:42:59 +02:00
dependabot[bot]
7b3b478e88 Bump pylint from 2.17.5 to 2.17.6 (#4584)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 09:41:08 +02:00
Chris Carini
f5afe13e91 Fix typos in docstrings (#4546)
* [typo] `Assitant` -> `Assistant`

* [typo] `an` -> `a`
2023-09-26 09:21:57 +02:00
dependabot[bot]
49ce468d83 Bump home-assistant/wheels from 2023.04.0 to 2023.09.1 (#4580)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:12:20 +02:00
dependabot[bot]
b26551c812 Bump home-assistant/builder from 2023.08.0 to 2023.09.0 (#4579)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 11:11:20 +02:00
dependabot[bot]
394ba580d2 Bump actions/checkout from 4.0.0 to 4.1.0 (#4578)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 10:53:19 +02:00
dependabot[bot]
2f7a54f5fd Bump urllib3 from 2.0.4 to 2.0.5 (#4572)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 11:04:19 +02:00
dependabot[bot]
360e085926 Bump time-machine from 2.12.0 to 2.13.0 (#4569)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-20 11:50:01 +02:00
dependabot[bot]
042921925d Bump typing-extensions from 4.7.1 to 4.8.0 (#4566)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 17:44:22 +02:00
Mike Degatano
dcf024387b Network backups skip free space check (#4563) 2023-09-19 16:28:39 +02:00
Mike Degatano
e1232bc9e7 Add support for green LEDs to API (#4556)
* Add support for green LEDs to API

* Save board config in supervisor and post on start

* Ignore no-value-for-parameter in validate
2023-09-14 09:27:12 -04:00
dependabot[bot]
d96598b5dd Bump sentry-sdk from 1.30.0 to 1.31.0 (#4562)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-14 09:03:51 +02:00
dependabot[bot]
2605f85668 Bump debugpy from 1.7.0 to 1.8.0 (#4559)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: debugpy
  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>
2023-09-13 08:57:38 +02:00
Mike Degatano
2c8e6ca0cd Switch from ruamel.yaml to pyyaml (#4555)
* Switch from ruamel.yaml to pyyaml

* Use CLoader and CDumper when available
2023-09-13 08:57:01 +02:00
Mike Degatano
0225f574be Only tell HA to refresh ingress on restore on change (#4552)
* Only tell HA to refresh ingress on restore on change

* Fix test expecting ingress change

* Assume ingress_panel is false for new addons
2023-09-13 08:50:32 +02:00
dependabot[bot]
34090bf2eb Bump docker/login-action from 2.2.0 to 3.0.0 (#4558)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-13 08:41:52 +02:00
Mike Degatano
5ae585ce13 Unmount mounts before backup restore (#4557) 2023-09-12 18:56:24 -04:00
dependabot[bot]
2bb10a32d7 Bump gitpython from 3.1.35 to 3.1.36 (#4553)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 10:22:55 +02:00
dependabot[bot]
435743dd2c Bump dbus-fast from 1.94.1 to 2.2.0 (#4550)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 1.94.1 to 2.2.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/v1.94.1...v2.2.0)

---
updated-dependencies:
- dependency-name: dbus-fast
  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>
2023-09-11 14:00:54 -04:00
dependabot[bot]
98589fba6d Bump black from 23.7.0 to 23.9.1 (#4549)
Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.9.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.7.0...23.9.1)

---
updated-dependencies:
- dependency-name: black
  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>
2023-09-11 12:43:50 -04:00
Mike Degatano
32da679e02 Ingress does not break when username missing (#4551) 2023-09-11 10:42:31 -04:00
Mike Degatano
44daffc65b Add freeze/thaw apis for external snapshots (#4538)
* Add freeze/thaw apis for external backups

* Error when thaw called before freeze

* Timeout must be > 0
2023-09-09 10:54:19 +02:00
Mike Degatano
0aafda1477 Mount names cannot include non-alphanumerics (#4545) 2023-09-09 10:54:04 +02:00
dependabot[bot]
60604e33b9 Bump debugpy from 1.6.7 to 1.7.0 (#4542)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.6.7 to 1.7.0.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.6.7...v1.7.0)

---
updated-dependencies:
- dependency-name: debugpy
  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>
2023-09-08 10:34:20 -04:00
dependabot[bot]
98268b377a Bump pytest from 7.4.1 to 7.4.2 (#4541)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.1 to 7.4.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/7.4.1...7.4.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>
2023-09-08 10:33:23 -04:00
dependabot[bot]
de54979471 Bump brotli from 1.0.9 to 1.1.0 (#4540)
Bumps [brotli](https://github.com/google/brotli) from 1.0.9 to 1.1.0.
- [Release notes](https://github.com/google/brotli/releases)
- [Changelog](https://github.com/google/brotli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/brotli/compare/v1.0.9...v1.1.0)

---
updated-dependencies:
- dependency-name: brotli
  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>
2023-09-08 10:32:45 -04:00
dependabot[bot]
ee6e339587 Bump pytest-aiohttp from 1.0.4 to 1.0.5 (#4535)
Bumps [pytest-aiohttp](https://github.com/aio-libs/pytest-aiohttp) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/aio-libs/pytest-aiohttp/releases)
- [Changelog](https://github.com/aio-libs/pytest-aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/pytest-aiohttp/compare/v1.0.4...v1.0.5)

---
updated-dependencies:
- dependency-name: pytest-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>
2023-09-08 10:21:11 -04:00
dependabot[bot]
c16cf89318 Bump coverage from 7.3.0 to 7.3.1 (#4534)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.3.0 to 7.3.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.3.0...7.3.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>
2023-09-08 10:04:31 -04:00
dependabot[bot]
c66cb7423e Bump actions/cache from 3.3.1 to 3.3.2 (#4544)
Bumps [actions/cache](https://github.com/actions/cache) from 3.3.1 to 3.3.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/v3.3.1...v3.3.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>
2023-09-08 09:37:38 -04:00
dependabot[bot]
f5bd95a519 Bump actions/upload-artifact from 3.1.2 to 3.1.3 (#4532)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3.1.2...v3.1.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>
2023-09-08 09:27:49 -04:00
dependabot[bot]
500f9ec1c1 Bump gitpython from 3.1.34 to 3.1.35 (#4539)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.34 to 3.1.35.
- [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.34...3.1.35)

---
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>
2023-09-08 09:19:54 -04:00
dependabot[bot]
a4713d4a1e Bump actions/checkout from 3.6.0 to 4.0.0 (#4527)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.0.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/v3.6.0...v4.0.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  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>
2023-09-06 15:35:10 -04:00
dependabot[bot]
04452dfb1a Bump pytest from 7.4.0 to 7.4.1 (#4523)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.0 to 7.4.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.0...7.4.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>
2023-09-06 14:58:56 -04:00
dependabot[bot]
69d09851d9 Bump pre-commit from 3.3.3 to 3.4.0 (#4522)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.3 to 3.4.0.
- [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/v3.3.3...v3.4.0)

---
updated-dependencies:
- dependency-name: pre-commit
  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>
2023-09-06 12:54:42 -04:00
Mike Degatano
1b649fe5cd Use newer StrEnum and IntEnum over Enum (#4521)
* Use newer StrEnum and IntEnum over Enum

* Fix validation issue and remove unnecessary .value calls

---------

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2023-09-06 12:21:04 -04:00
dependabot[bot]
38572a5a86 Bump gitpython from 3.1.32 to 3.1.34 (#4524)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.32 to 3.1.34.
- [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.32...3.1.34)

---
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>
2023-09-06 12:19:01 -04:00
dependabot[bot]
f5f51169e6 Bump sigstore/cosign-installer from 3.1.1 to 3.1.2 (#4525)
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.1.1...v3.1.2)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  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>
2023-09-05 11:55:41 +02:00
Mike Degatano
07c2178ae1 Add jobs to docker supervisor and use group wait (#4520) 2023-09-03 18:22:17 +02:00
Mike Degatano
f30d21361f Skip unnecessary mounts and privileges for landingpage (#4518)
* Skip unnecessary mounts for landingpage

* Remove privileged and cgroup rules from landingpage
2023-09-03 18:21:35 +02:00
Mike Degatano
6adb4fbcf7 Update store data in one task to prevent races (#4519)
* Update store data in one task to prevent races

* Always return a dictionary
2023-09-03 18:20:26 +02:00
dependabot[bot]
d73962bd7d Bump faust-cchardet from 2.1.18 to 2.1.19 (#4484)
Bumps [faust-cchardet](https://github.com/faust-streaming/cChardet) from 2.1.18 to 2.1.19.
- [Release notes](https://github.com/faust-streaming/cChardet/releases)
- [Changelog](https://github.com/faust-streaming/cChardet/blob/master/CHANGES.rst)
- [Commits](https://github.com/faust-streaming/cChardet/compare/v2.1.18...v2.1.19)

---
updated-dependencies:
- dependency-name: faust-cchardet
  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>
2023-09-01 11:18:51 +02:00
Mike Degatano
f4b43739da Skip plugin update on startup if supervisor out of date (#4515) 2023-09-01 11:18:22 +02:00
Mike Degatano
4838b280ad List current job tree in api (#4514) 2023-08-31 10:01:42 +02:00
Mike Degatano
f93b753c03 Backup and restore track progress in job (#4503)
* Backup and restore track progress in job

* Change to stage only updates and fix tests

* Leave HA alone if it wasn't restored

* skip check HA stage message when we don't check

* Change to helper to get current job

* Fix tests

* Mark jobs as internal to skip notifying HA
2023-08-30 16:01:03 -04:00
dependabot[bot]
de06361cb0 Bump dbus-fast from 1.93.0 to 1.94.1 (#4511)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 1.93.0 to 1.94.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/v1.93.0...v1.94.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>
2023-08-30 15:48:27 -04:00
dependabot[bot]
15ce48c8aa Bump sentry-sdk from 1.29.2 to 1.30.0 (#4513)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.29.2 to 1.30.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.29.2...1.30.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>
2023-08-30 15:28:51 -04:00
dependabot[bot]
38758d05a8 Bump actions/checkout from 3.5.3 to 3.6.0 (#4508)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-25 09:54:14 +02:00
Mike Degatano
a79fa14ee7 Don't notify listeners on CoreState.CLOSE (#4506) 2023-08-25 07:22:49 +02:00
Pascal Vizeli
1eb95b4d33 Remove old add-on state refresh (#4504) 2023-08-24 11:04:31 -04:00
dependabot[bot]
d04e47f5b3 Bump dbus-fast from 1.92.0 to 1.93.0 (#4501)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 1.92.0 to 1.93.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/v1.92.0...v1.93.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>
2023-08-23 17:12:49 -04:00
Mike Degatano
dad5118f21 Use dataclasses asdict for dataclasses (#4502) 2023-08-22 17:50:48 -04:00
Florian Bachmann
acc0e5c989 Allows the supervisor to send a session's user to addon with header X-Remote-User (#4152)
* Working draft for x-remote-user

* Renames prop to remote_user

* Allows to set in addon description whether it requests the username

* Fixes addon-options schema

* Sends user ID instead of username to addons

* Adds tests

* Removes configurability of remote-user forwarding

* Update const.py

* Also adds username header

* Fetches full user info object from homeassistant

* Cleaner validation and dataclasses

* Fixes linting

* Fixes linting

* Tries to fix test

* Updates tests

* Updates tests

* Updates tests

* Updates tests

* Updates tests

* Updates tests

* Updates tests

* Updates tests

* Resolves PR comments

* Linting

* Fixes tests

* Update const.py

* Removes header keys if not required

* Moves ignoring user ID headers if no session_data is given

* simplify

* fix lint with new job

---------

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
Co-authored-by: Pascal Vizeli <pascal.vizeli@syshack.ch>
2023-08-22 10:11:13 +02:00
dependabot[bot]
204fcdf479 Bump dbus-fast from 1.91.2 to 1.92.0 (#4500)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 1.91.2 to 1.92.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/v1.91.2...v1.92.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>
2023-08-21 11:03:02 +02:00
Mike Degatano
93ba8a3574 Add job names and references everywhere (#4495)
* Add job names and references everywhere

* Remove group names check and switch to const

* Ensure unique job names in decorator tests
2023-08-21 09:15:37 +02:00
dependabot[bot]
f2f9e3b514 Bump dbus-fast from 1.86.0 to 1.91.2 (#4485)
Bumps [dbus-fast](https://github.com/bluetooth-devices/dbus-fast) from 1.86.0 to 1.91.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/v1.86.0...v1.91.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>
2023-08-15 10:32:27 -04:00
Mike Degatano
61288559b3 Always stop the addon before restoring it (#4492)
* Always stop the addon before restoring it

* patch ingress refresh to avoid timeout
2023-08-15 13:08:45 +02:00
dependabot[bot]
bd2c99a455 Bump awesomeversion from 23.5.0 to 23.8.0 (#4494)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 10:38:43 +02:00
dependabot[bot]
1937348b24 Bump time-machine from 2.11.0 to 2.12.0 (#4493)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 09:55:26 +02:00
dependabot[bot]
b7b2fae325 Bump coverage from 7.2.7 to 7.3.0 (#4491)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 09:49:04 +02:00
dependabot[bot]
11115923b2 Bump async-timeout from 4.0.2 to 4.0.3 (#4488)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-11 12:13:28 +02:00
dependabot[bot]
295133d2e9 Bump home-assistant/builder from 2023.06.1 to 2023.08.0 (#4489)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-11 10:23:47 +02:00
Mike Degatano
3018b851c8 Missing an await in addon data (#4487) 2023-08-10 16:31:43 -04:00
Mike Degatano
222c3fd485 Address addon storage race condition (#4481)
* Address addon storage race condition

* Add some error test cases
2023-08-10 15:24:43 -04:00
Stefan Agner
9650fd2ba1 Extend container image name validator (#4480)
* Extend container image name validator

The current validator allows certain invalid names (e.g. upper
case), but disallows valid cases (such as ttl.sh/myimage).
Improve the container image validator to support more valid
options and at the same time disallow some of the invalid
options.

Note that this is not a complete/perfect validation still. A much
much more sophisticated regex would be necessary to be 100% accurate.
Also we format the string and replace {machine}/{arch} using Python
format strings. In that regard the image format in Supervisor deviates
from the Docker/OCI container image name format.

* Use an actual invalid image name in config validation
2023-08-10 12:58:33 -04:00
Stefan Agner
c88fd9a7d9 Add Home Assistant Green (#4486) 2023-08-10 17:31:37 +02:00
Mike Degatano
1611beccd1 Add job group execution limit option (#4457)
* Add job group execution limit option

* Fix pylint issues

* Assign variable before usage

* Cleanup jobs when done

* Remove isinstance check for performance

* Explicitly raise from None

* Add some more documentation info
2023-08-08 16:49:17 -04:00
Mike Degatano
71077fb0f7 Fallback on interface name if path is missing (#4479) 2023-08-07 20:53:25 -04:00
dependabot[bot]
9647fba98f Bump cryptography from 41.0.2 to 41.0.3 (#4468)
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3)

---
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>
2023-08-04 17:50:46 -04:00
Mike Degatano
86f004e45a Use udev path instead of mac or name for nm match (#4476) 2023-08-04 17:39:35 -04:00
Mike Degatano
a98334ede8 Cancel startup wait task on addon uninstallation (#4475)
* Cancel startup wait task on addon uninstallation

* Await startup task instead

* Suppress cancelled error
2023-08-04 16:28:44 -04:00
dependabot[bot]
e19c2d6805 Bump aiohttp from 3.8.4 to 3.8.5 (#4467)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.4 to 3.8.5.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/v3.8.5/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.4...v3.8.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-03 11:01:58 -04:00
dependabot[bot]
847736dab8 Bump sentry-sdk from 1.29.0 to 1.29.2 (#4470)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-02 09:24:42 +02:00
Mike Degatano
45f930ab21 Revert "Bump aiohttp from 3.8.4 to 3.8.5 (#4448)" (#4466)
This reverts commit b8178414a4.
2023-08-01 17:37:34 -04:00
dependabot[bot]
6ea54f1ddb Bump sentry-sdk from 1.28.1 to 1.29.0 (#4464)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-01 10:14:38 +02:00
Mike Degatano
81ce0a60f6 Missing an await on dns.write_hosts call (#4463) 2023-07-31 23:29:40 +02:00
dependabot[bot]
bf5d839c22 Bump flake8 from 6.0.0 to 6.1.0 (#4461)
Bumps [flake8](https://github.com/pycqa/flake8) from 6.0.0 to 6.1.0.
- [Commits](https://github.com/pycqa/flake8/compare/6.0.0...6.1.0)

---
updated-dependencies:
- dependency-name: flake8
  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>
2023-07-31 10:49:04 -04:00
dependabot[bot]
fc385cfac0 Bump pyupgrade from 3.9.0 to 3.10.1 (#4460)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 3.9.0 to 3.10.1.
- [Commits](https://github.com/asottile/pyupgrade/compare/v3.9.0...v3.10.1)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2023-07-31 10:22:21 -04:00
dependabot[bot]
12d55b8411 Bump pylint from 2.17.4 to 2.17.5 (#4456)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-27 09:01:16 +02:00
Mike Degatano
e60af93e2b List discovery only includes healthy addons (#4451)
Co-authored-by: Stefan Agner <stefan@agner.ch>
2023-07-22 23:27:42 +02:00
Mike Degatano
1691f0eac7 Temporary operations for backups take place in destination folder (#4452) 2023-07-21 22:49:31 -04:00
Mike Degatano
be4a6a1564 Allow discovery messages for unknown services with a warning (#4449)
* Allow discovery messages for unknown services with a warning

* Log at warning level and skip sentry report
2023-07-21 15:05:51 -04:00
J. Nick Koston
24c5613a50 Switch to using the get core state api call to check if the API is up (#4445)
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2023-07-20 13:43:44 +02:00
J. Nick Koston
5266927bf7 Avoid check_api_state in websocket _can_send if we are already connected (#4446) 2023-07-20 11:20:02 +02:00
dependabot[bot]
4bd2000174 Bump urllib3 from 2.0.3 to 2.0.4 (#4447)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-20 11:14:27 +02:00
dependabot[bot]
b8178414a4 Bump aiohttp from 3.8.4 to 3.8.5 (#4448)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-20 11:02:15 +02:00
J. Nick Koston
f9bc2f5993 Increase core websocket proxy maximum message size to 64MiB (#4443) 2023-07-19 20:02:42 +02:00
Mike Degatano
f1a72ee418 Include interface name in match-device settings (#4444) 2023-07-19 10:15:59 +02:00
dependabot[bot]
b19dcef5b7 Bump cryptography from 41.0.1 to 41.0.2 (#4434)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 21:58:35 +02:00
Mike Degatano
1f92ab42ca Reduce executor code for docker (#4438)
* Reduce executor code for docker

* Fix pylint errors and move import/export image

* Fix test and a couple other risky executor calls

* Fix dataclass and return

* Fix test case and add one for corrupt docker

* Add some coverage

* Undo changes to docker manager startup
2023-07-18 11:39:39 -04:00
dependabot[bot]
1f940a04fd Bump actions/setup-python from 4.6.1 to 4.7.0 (#4439)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 09:30:20 +02:00
dependabot[bot]
f771eaab5f Bump sentry-sdk from 1.28.0 to 1.28.1 (#4440)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 09:22:26 +02:00
dependabot[bot]
d1379a8154 Bump black from 23.3.0 to 23.7.0 (#4433)
Bumps [black](https://github.com/psf/black) from 23.3.0 to 23.7.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.3.0...23.7.0)

---
updated-dependencies:
- dependency-name: black
  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>
2023-07-13 15:27:00 -04:00
dependabot[bot]
e488f02557 Bump gitpython from 3.1.31 to 3.1.32 (#4435)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.31 to 3.1.32.
- [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.31...3.1.32)

---
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>
2023-07-11 13:55:17 +02:00
dependabot[bot]
f11cc86254 Bump time-machine from 2.10.0 to 2.11.0 (#4432)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 13:27:46 +02:00
dependabot[bot]
175667bfe8 Bump sentry-sdk from 1.27.1 to 1.28.0 (#4436)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 08:46:39 +02:00
dependabot[bot]
0a0f14ddea Bump pyupgrade from 3.8.0 to 3.9.0 (#4430)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 3.8.0 to 3.9.0.
- [Commits](https://github.com/asottile/pyupgrade/compare/v3.8.0...v3.9.0)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2023-07-10 08:54:19 +02:00
dependabot[bot]
9e08677ade Bump sentry-sdk from 1.27.0 to 1.27.1 (#4427)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-07 14:23:02 +02:00
Mike Degatano
abbf8b9b65 Identify network interfaces by mac over name (#4416)
* Identify network interfaces by mac over name

* Refactor long if statement into method
2023-07-06 16:26:19 -04:00
Mike Degatano
96d5fc244e Separate startup event from update check event (#4425)
* Separate startup event from update check event

* Add a queue for messages sent during startup
2023-07-06 12:45:37 -04:00
dependabot[bot]
3b38047fd4 Bump pyupgrade from 3.7.0 to 3.8.0 (#4418)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 3.7.0 to 3.8.0.
- [Commits](https://github.com/asottile/pyupgrade/compare/v3.7.0...v3.8.0)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2023-07-06 10:07:25 -04:00
dependabot[bot]
48e9e1c4f9 Bump sentry-sdk from 1.26.0 to 1.27.0 (#4422)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-05 10:49:32 +02:00
Bram Kragten
355961a1eb Update frontend (#4423) 2023-07-05 10:16:49 +02:00
Bram Kragten
e68190b6b6 Bump frontend (#4420) 2023-07-04 10:21:32 +02:00
dependabot[bot]
e7cc7e971f Bump typing-extensions from 4.7.0 to 4.7.1 (#4419)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-03 09:17:50 +02:00
dependabot[bot]
ee027eb510 Bump release-drafter/release-drafter from 5.23.0 to 5.24.0 (#4412)
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 5.23.0 to 5.24.0.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](https://github.com/release-drafter/release-drafter/compare/v5.23.0...v5.24.0)

---
updated-dependencies:
- dependency-name: release-drafter/release-drafter
  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>
2023-06-29 20:54:55 -04:00
dependabot[bot]
a584300bf3 Bump typing-extensions from 4.6.3 to 4.7.0 (#4413)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-29 11:07:30 +02:00
dependabot[bot]
16e1f839d7 Bump sigstore/cosign-installer from 3.1.0 to 3.1.1 (#4410)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-28 09:17:24 +02:00
Mike Degatano
c2123f0903 Ensure addon.start always returns coroutine (#4409) 2023-06-27 19:43:49 +02:00
Mike Degatano
9fbeb2a769 Add support for apparmor channels (#4408) 2023-06-27 19:12:42 +02:00
dependabot[bot]
3e0723ec24 Bump sigstore/cosign-installer from 3.0.5 to 3.1.0 (#4407)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 10:17:53 +02:00
Pascal Vizeli
3e5f1d96b5 Fix Tag (#4406) 2023-06-26 18:49:13 +02:00
dependabot[bot]
be87082502 Bump home-assistant/builder from 2023.06.0 to 2023.06.1 (#4404)
* Bump home-assistant/builder from 2023.06.0 to 2023.06.1

Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2023.06.0 to 2023.06.1.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2023.06.0...2023.06.1)

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

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

* Support cosign & ditch Codenotary

* use curl

* Not using docker.io anymore

---------

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>
2023-06-26 18:17:55 +02:00
dependabot[bot]
f997e51249 Bump pytest from 7.3.2 to 7.4.0 (#4405)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 12:00:01 +02:00
dependabot[bot]
456316fdd4 Bump sentry-sdk from 1.25.1 to 1.26.0 (#4401)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-23 16:57:36 +02:00
Mike Degatano
9a7d547394 Allow all characters in mount credentials (#4399)
* Allow all characters in mount credentials

* Fix permissions on credential files

* Fix pylint issue
2023-06-22 15:55:13 -04:00
Mike Degatano
d3031e2eae Use noserverino option in cifs mounts (#4398) 2023-06-21 18:49:03 +02:00
Joakim Sørensen
35bd66119a Allow specifying CIFS version (#4395)
* Allow specifying cifs_version

* cifs_version -> version
2023-06-21 12:08:56 -04:00
dependabot[bot]
9be3b47e0e Bump pyupgrade from 3.6.0 to 3.7.0 (#4393)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 3.6.0 to 3.7.0.
- [Commits](https://github.com/asottile/pyupgrade/compare/v3.6.0...v3.7.0)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2023-06-20 10:37:34 -04:00
Joakim Sørensen
4bed8c1327 Allow mounting CIFS as guest (#4384) 2023-06-20 10:20:06 -04:00
Mike Degatano
254ec2d1af Addon startup waits for healthy (#4376)
* Addon startup waits for healthy

* fix import for pylint

* wait_for to 5 in tests

* Adjust tests to simplify async tasks

* Remove wait_boot time from addons.boot tests

* Eliminate async task race conditions in tests
2023-06-20 10:13:15 -04:00
dependabot[bot]
e4ee3e4226 Bump time-machine from 2.9.0 to 2.10.0 (#4394)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 09:40:42 +02:00
Joakim Sørensen
65545e7218 Bump frontend to 3be601a3 (#4382) 2023-06-16 14:02:41 +02:00
1543 changed files with 12895 additions and 3928 deletions

View File

@@ -53,7 +53,7 @@ jobs:
requirements: ${{ steps.requirements.outputs.changed }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
with:
fetch-depth: 0
@@ -83,12 +83,16 @@ jobs:
name: Build ${{ matrix.arch }} supervisor
needs: init
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
strategy:
matrix:
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
with:
fetch-depth: 0
@@ -102,13 +106,13 @@ jobs:
- name: Build wheels
if: needs.init.outputs.requirements == 'true'
uses: home-assistant/wheels@2023.04.0
uses: home-assistant/wheels@2023.10.1
with:
abi: cp311
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
apk: "libffi-dev;openssl-dev"
apk: "libffi-dev;openssl-dev;yaml-dev"
skip-binary: aiohttp
env-file: true
requirements: "requirements.txt"
@@ -119,16 +123,33 @@ jobs:
with:
type: ${{ env.BUILD_TYPE }}
- name: Login to DockerHub
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
if: needs.init.outputs.publish == 'true'
uses: docker/login-action@v2.2.0
uses: actions/setup-python@v4.7.1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Install Cosign
if: needs.init.outputs.publish == 'true'
uses: sigstore/cosign-installer@v3.1.2
with:
cosign-release: "v2.0.2"
- name: Install dirhash and calc hash
if: needs.init.outputs.publish == 'true'
run: |
pip3 install dirhash
dir_hash="$(dirhash "${{ github.workspace }}/supervisor" -a sha256 --match "*.py")"
echo "${dir_hash}" > rootfs/supervisor.sha256
- name: Sign supervisor SHA256
if: needs.init.outputs.publish == 'true'
run: |
cosign sign-blob --yes rootfs/supervisor.sha256 --bundle rootfs/supervisor.sha256.sig
- name: Login to GitHub Container Registry
if: needs.init.outputs.publish == 'true'
uses: docker/login-action@v2.2.0
uses: docker/login-action@v3.0.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -139,55 +160,17 @@ jobs:
run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV
- name: Build supervisor
uses: home-assistant/builder@2023.06.0
uses: home-assistant/builder@2023.09.0
with:
args: |
$BUILD_ARGS \
--${{ matrix.arch }} \
--target /data \
--cosign \
--generic ${{ needs.init.outputs.version }}
env:
CAS_API_KEY: ${{ secrets.CAS_TOKEN }}
codenotary:
name: CAS signature
needs: init
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
if: needs.init.outputs.publish == 'true'
uses: actions/checkout@v3.5.3
with:
fetch-depth: 0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
if: needs.init.outputs.publish == 'true'
uses: actions/setup-python@v4.6.1
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Set version
if: needs.init.outputs.publish == 'true'
uses: home-assistant/actions/helpers/version@master
with:
type: ${{ env.BUILD_TYPE }}
- name: Install dirhash and calc hash
if: needs.init.outputs.publish == 'true'
id: dirhash
run: |
pip3 install dirhash
dir_hash="$(dirhash "${{ github.workspace }}/supervisor" -a sha256 --match "*.py")"
echo "::set-output name=dirhash::${dir_hash}"
- name: Signing Source
if: needs.init.outputs.publish == 'true'
uses: home-assistant/actions/helpers/codenotary@master
with:
source: hash://${{ steps.dirhash.outputs.dirhash }}
asset: supervisor-${{ needs.init.outputs.version }}
token: ${{ secrets.CAS_TOKEN }}
version:
name: Update version
needs: ["init", "run_supervisor"]
@@ -195,7 +178,7 @@ jobs:
steps:
- name: Checkout the repository
if: needs.init.outputs.publish == 'true'
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Initialize git
if: needs.init.outputs.publish == 'true'
@@ -216,15 +199,15 @@ jobs:
run_supervisor:
runs-on: ubuntu-latest
name: Run the Supervisor
needs: ["build", "codenotary", "init"]
needs: ["build", "init"]
timeout-minutes: 60
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Build the Supervisor
if: needs.init.outputs.publish != 'true'
uses: home-assistant/builder@2023.06.0
uses: home-assistant/builder@2023.09.0
with:
args: |
--test \
@@ -236,7 +219,7 @@ jobs:
if: needs.init.outputs.publish == 'true'
run: |
docker pull ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }}
docker tag ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }} homeassistant/amd64-hassio-supervisor:runner
docker tag ghcr.io/home-assistant/amd64-hassio-supervisor:${{ needs.init.outputs.version }} ghcr.io/home-assistant/amd64-hassio-supervisor:runner
- name: Create the Supervisor
run: |
@@ -253,7 +236,7 @@ jobs:
-e SUPERVISOR_NAME=hassio_supervisor \
-e SUPERVISOR_DEV=1 \
-e SUPERVISOR_MACHINE="qemux86-64" \
homeassistant/amd64-hassio-supervisor:runner
ghcr.io/home-assistant/amd64-hassio-supervisor:runner
- name: Start the Supervisor
run: docker start hassio_supervisor

View File

@@ -10,7 +10,6 @@ on:
env:
DEFAULT_PYTHON: "3.11"
PRE_COMMIT_HOME: ~/.cache/pre-commit
DEFAULT_CAS: v1.0.2
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
@@ -26,15 +25,15 @@ jobs:
name: Prepare Python dependencies
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python
id: python
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -48,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.1
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -67,15 +66,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -96,7 +95,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Register hadolint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
@@ -111,15 +110,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -131,7 +130,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -155,15 +154,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -187,15 +186,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -207,7 +206,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -228,15 +227,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -248,7 +247,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -272,15 +271,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -304,15 +303,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -324,7 +323,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -345,19 +344,19 @@ jobs:
name: Run tests Python ${{ needs.prepare.outputs.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Install CAS tools
uses: home-assistant/actions/helpers/cas@master
- name: Install Cosign
uses: sigstore/cosign-installer@v3.1.2
with:
version: ${{ env.DEFAULT_CAS }}
cosign-release: "v2.0.2"
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |
@@ -392,7 +391,7 @@ jobs:
-o console_output_style=count \
tests
- name: Upload coverage artifact
uses: actions/upload-artifact@v3.1.2
uses: actions/upload-artifact@v3.1.3
with:
name: coverage-${{ matrix.python-version }}
path: .coverage
@@ -403,15 +402,15 @@ jobs:
needs: ["pytest", "prepare"]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v4.6.1
uses: actions/setup-python@v4.7.1
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.3.1
uses: actions/cache@v3.3.2
with:
path: venv
key: |

View File

@@ -11,7 +11,7 @@ jobs:
name: Release Drafter
steps:
- name: Checkout the repository
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
with:
fetch-depth: 0
@@ -36,7 +36,7 @@ jobs:
echo "::set-output name=version::$datepre.$newpost"
- name: Run Release Drafter
uses: release-drafter/release-drafter@v5.23.0
uses: release-drafter/release-drafter@v5.24.0
with:
tag: ${{ steps.version.outputs.version }}
name: ${{ steps.version.outputs.version }}

View File

@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.5.3
uses: actions/checkout@v4.1.0
- name: Sentry Release
uses: getsentry/action-release@v1.4.1
env:

View File

@@ -7,7 +7,8 @@ ENV \
CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1
ARG \
CAS_VERSION
COSIGN_VERSION \
BUILD_ARCH
# Install base
WORKDIR /usr/src
@@ -21,19 +22,10 @@ RUN \
libpulse \
musl \
openssl \
&& apk add --no-cache --virtual .build-dependencies \
build-base \
go \
yaml \
\
&& git clone -b "v${CAS_VERSION}" --depth 1 \
https://github.com/codenotary/cas \
&& cd cas \
&& make cas \
&& mv cas /usr/bin/cas \
\
&& apk del .build-dependencies \
&& rm -rf /root/go /root/.cache \
&& rm -rf /usr/src/cas
&& curl -Lso /usr/bin/cosign "https://github.com/home-assistant/cosign/releases/download/${COSIGN_VERSION}/cosign_${BUILD_ARCH}" \
&& chmod a+x /usr/bin/cosign
# Install requirements
COPY requirements.txt .

View File

@@ -1,5 +1,4 @@
image: homeassistant/{arch}-hassio-supervisor
shadow_repository: ghcr.io/home-assistant
image: ghcr.io/home-assistant/{arch}-hassio-supervisor
build_from:
aarch64: ghcr.io/home-assistant/aarch64-base-python:3.11-alpine3.16
armhf: ghcr.io/home-assistant/armhf-base-python:3.11-alpine3.16
@@ -9,8 +8,11 @@ build_from:
codenotary:
signer: notary@home-assistant.io
base_image: notary@home-assistant.io
cosign:
base_identity: https://github.com/home-assistant/docker-base/.*
identity: https://github.com/home-assistant/supervisor/.*
args:
CAS_VERSION: 1.0.2
COSIGN_VERSION: 2.0.2
labels:
io.hass.type: supervisor
org.opencontainers.image.title: Home Assistant Supervisor

View File

@@ -1,26 +1,26 @@
aiodns==3.0.0
aiohttp==3.8.4
async_timeout==4.0.2
aiohttp==3.8.5
async_timeout==4.0.3
atomicwrites-homeassistant==1.4.1
attrs==23.1.0
awesomeversion==23.5.0
brotli==1.0.9
awesomeversion==23.8.0
brotli==1.1.0
ciso8601==2.3.0
colorlog==6.7.0
cpe==1.2.1
cryptography==41.0.1
debugpy==1.6.7
cryptography==41.0.4
debugpy==1.8.0
deepmerge==1.1.0
dirhash==0.2.1
docker==6.1.3
faust-cchardet==2.1.18
gitpython==3.1.31
faust-cchardet==2.1.19
gitpython==3.1.37
jinja2==3.1.2
pulsectl==23.5.2
pyudev==0.24.1
ruamel.yaml==0.17.21
PyYAML==6.0.1
securetar==2023.3.0
sentry-sdk==1.25.1
sentry-sdk==1.31.0
voluptuous==0.13.1
dbus-fast==1.86.0
typing_extensions==4.6.3
dbus-fast==2.10.0
typing_extensions==4.8.0

View File

@@ -1,16 +1,16 @@
black==23.3.0
coverage==7.2.7
black==23.9.1
coverage==7.3.2
flake8-docstrings==1.7.0
flake8==6.0.0
pre-commit==3.3.3
flake8==6.1.0
pre-commit==3.4.0
pydocstyle==6.3.0
pylint==2.17.4
pytest-aiohttp==1.0.4
pylint==3.0.0
pytest-aiohttp==1.0.5
pytest-asyncio==0.18.3
pytest-cov==4.1.0
pytest-timeout==2.1.0
pytest==7.3.2
pyupgrade==3.6.0
time-machine==2.9.0
typing_extensions==4.6.3
urllib3==2.0.3
pytest==7.4.2
pyupgrade==3.14.0
time-machine==2.13.0
typing_extensions==4.8.0
urllib3==2.0.6

View File

@@ -1,4 +0,0 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE03LvYuz79GTJx4uKp3w6NrSe5JZI
iBtgzzYi0YQYtZO/r+xFpgDJEa0gLHkXtl94fpqrFiN89In83lzaszbZtA==
-----END PUBLIC KEY-----

View File

@@ -1,8 +0,0 @@
{
"currentcontext": {
"LcHost": "cas.codenotary.com",
"LcPort": "443"
},
"schemaversion": 3,
"users": null
}

View File

@@ -1,5 +1,6 @@
"""Init file for Supervisor add-ons."""
import asyncio
from collections.abc import Awaitable
from contextlib import suppress
import logging
import tarfile
@@ -104,9 +105,13 @@ class AddonManager(CoreSysAttributes):
# Start Add-ons sequential
# avoid issue on slow IO
# Config.wait_boot is deprecated. Until addons update with healthchecks,
# add a sleep task for it to keep the same minimum amount of wait time
wait_boot: list[Awaitable[None]] = [asyncio.sleep(self.sys_config.wait_boot)]
for addon in tasks:
try:
await addon.start()
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(
@@ -121,7 +126,8 @@ class AddonManager(CoreSysAttributes):
_LOGGER.warning("Can't start Add-on %s", addon.slug)
await asyncio.sleep(self.sys_config.wait_boot)
# Ignore exceptions from waiting for addon startup, addon errors handled elsewhere
await asyncio.gather(*wait_boot, return_exceptions=True)
async def shutdown(self, stage: AddonStartup) -> None:
"""Shutdown addons."""
@@ -146,11 +152,14 @@ class AddonManager(CoreSysAttributes):
capture_exception(err)
@Job(
name="addon_manager_install",
conditions=ADDON_UPDATE_CONDITIONS,
on_condition=AddonsJobError,
)
async def install(self, slug: str) -> None:
"""Install an add-on."""
self.sys_jobs.current.reference = slug
if slug in self.local:
raise AddonsError(f"Add-on {slug} is already installed", _LOGGER.warning)
store = self.store.get(slug)
@@ -241,11 +250,20 @@ class AddonManager(CoreSysAttributes):
_LOGGER.info("Add-on '%s' successfully removed", slug)
@Job(
name="addon_manager_update",
conditions=ADDON_UPDATE_CONDITIONS,
on_condition=AddonsJobError,
)
async def update(self, slug: str, backup: bool | None = False) -> None:
"""Update add-on."""
async def update(
self, slug: str, backup: bool | None = False
) -> Awaitable[None] | None:
"""Update add-on.
Returns a coroutine that completes when addon has state 'started' (see addon.start)
if addon is started after update. Else nothing is returned.
"""
self.sys_jobs.current.reference = slug
if slug not in self.local:
raise AddonsError(f"Add-on {slug} is not installed", _LOGGER.error)
addon = self.local[slug]
@@ -288,10 +306,14 @@ class AddonManager(CoreSysAttributes):
await addon.install_apparmor()
# restore state
if last_state == AddonState.STARTED:
return (
await addon.start()
if last_state in [AddonState.STARTED, AddonState.STARTUP]
else None
)
@Job(
name="addon_manager_rebuild",
conditions=[
JobCondition.FREE_SPACE,
JobCondition.INTERNET_HOST,
@@ -299,8 +321,14 @@ class AddonManager(CoreSysAttributes):
],
on_condition=AddonsJobError,
)
async def rebuild(self, slug: str) -> None:
"""Perform a rebuild of local build add-on."""
async def rebuild(self, slug: str) -> Awaitable[None] | None:
"""Perform a rebuild of local build add-on.
Returns a coroutine that completes when addon has state 'started' (see addon.start)
if addon is started after rebuild. Else nothing is returned.
"""
self.sys_jobs.current.reference = slug
if slug not in self.local:
raise AddonsError(f"Add-on {slug} is not installed", _LOGGER.error)
addon = self.local[slug]
@@ -333,10 +361,14 @@ class AddonManager(CoreSysAttributes):
_LOGGER.info("Add-on '%s' successfully rebuilt", slug)
# restore state
if last_state == AddonState.STARTED:
return (
await addon.start()
if last_state in [AddonState.STARTED, AddonState.STARTUP]
else None
)
@Job(
name="addon_manager_restore",
conditions=[
JobCondition.FREE_SPACE,
JobCondition.INTERNET_HOST,
@@ -344,16 +376,26 @@ class AddonManager(CoreSysAttributes):
],
on_condition=AddonsJobError,
)
async def restore(self, slug: str, tar_file: tarfile.TarFile) -> None:
"""Restore state of an add-on."""
async def restore(
self, slug: str, tar_file: tarfile.TarFile
) -> Awaitable[None] | None:
"""Restore state of an add-on.
Returns a coroutine that completes when addon has state 'started' (see addon.start)
if addon is started after restore. Else nothing is returned.
"""
self.sys_jobs.current.reference = slug
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
else:
_LOGGER.debug("Add-on %s is local available for restore", slug)
addon = self.local[slug]
had_ingress = addon.ingress_panel
await addon.restore(tar_file)
wait_for_start = await addon.restore(tar_file)
# Check if new
if slug not in self.local:
@@ -361,12 +403,17 @@ class AddonManager(CoreSysAttributes):
self.local[slug] = addon
# Update ingress
if addon.with_ingress:
if had_ingress != addon.ingress_panel:
await self.sys_ingress.reload()
with suppress(HomeAssistantAPIError):
await self.sys_ingress.update_hass_panel(addon)
@Job(conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_HOST])
return wait_for_start
@Job(
name="addon_manager_repair",
conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_HOST],
)
async def repair(self) -> None:
"""Repair local add-ons."""
needs_repair: list[Addon] = []
@@ -404,6 +451,7 @@ class AddonManager(CoreSysAttributes):
async def sync_dns(self) -> None:
"""Sync add-ons DNS names."""
# Update hosts
add_host_coros: list[Awaitable[None]] = []
for addon in self.installed:
try:
if not await addon.instance.is_running():
@@ -418,10 +466,14 @@ class AddonManager(CoreSysAttributes):
)
capture_exception(err)
else:
self.sys_plugins.dns.add_host(
ipv4=addon.ip_address, names=[addon.hostname], write=False
add_host_coros.append(
self.sys_plugins.dns.add_host(
ipv4=addon.ip_address, names=[addon.hostname], write=False
)
)
await asyncio.gather(*add_host_coros)
# Write hosts files
with suppress(CoreDNSError):
self.sys_plugins.dns.write_hosts()
await self.sys_plugins.dns.write_hosts()

View File

@@ -99,6 +99,7 @@ RE_WATCHDOG = re.compile(
)
WATCHDOG_TIMEOUT = aiohttp.ClientTimeout(total=10)
STARTUP_TIMEOUT = 120
_OPTIONS_MERGER: Final = Merger(
type_strategies=[(dict, ["merge"])],
@@ -106,6 +107,14 @@ _OPTIONS_MERGER: Final = Merger(
type_conflict_strategies=["override"],
)
# Backups just need to know if an addon was running or not
# Map other addon states to those two
_MAP_ADDON_STATE = {
AddonState.STARTUP: AddonState.STARTED,
AddonState.ERROR: AddonState.STOPPED,
AddonState.UNKNOWN: AddonState.STOPPED,
}
class Addon(AddonModel):
"""Hold data for add-on inside Supervisor."""
@@ -119,54 +128,8 @@ class Addon(AddonModel):
self.sys_hardware.helper.last_boot != self.sys_config.last_boot
)
self._listeners: list[EventListener] = []
@Job(
name=f"addon_{slug}_restart_after_problem",
limit=JobExecutionLimit.THROTTLE_RATE_LIMIT,
throttle_period=WATCHDOG_THROTTLE_PERIOD,
throttle_max_calls=WATCHDOG_THROTTLE_MAX_CALLS,
on_condition=AddonsJobError,
)
async def restart_after_problem(addon: Addon, state: ContainerState):
"""Restart unhealthy or failed addon."""
attempts = 0
while await addon.instance.current_state() == state:
if not addon.in_progress:
_LOGGER.warning(
"Watchdog found addon %s is %s, restarting...",
addon.name,
state.value,
)
try:
if state == ContainerState.FAILED:
# Ensure failed container is removed before attempting reanimation
if attempts == 0:
with suppress(DockerError):
await addon.instance.stop(remove_container=True)
await addon.start()
else:
await addon.restart()
except AddonsError as err:
attempts = attempts + 1
_LOGGER.error(
"Watchdog restart of addon %s failed!", addon.name
)
capture_exception(err)
else:
break
if attempts >= WATCHDOG_MAX_ATTEMPTS:
_LOGGER.critical(
"Watchdog cannot restart addon %s, failed all %s attempts",
addon.name,
attempts,
)
break
await asyncio.sleep(WATCHDOG_RETRY_SECONDS)
self._restart_after_problem = restart_after_problem
self._startup_event = asyncio.Event()
self._startup_task: asyncio.Task | None = None
def __repr__(self) -> str:
"""Return internal representation."""
@@ -182,7 +145,13 @@ class Addon(AddonModel):
"""Set the add-on into new state."""
if self._state == new_state:
return
old_state = self._state
self._state = new_state
# Signal listeners about addon state change
if new_state == AddonState.STARTED or old_state == AddonState.STARTUP:
self._startup_event.set()
self.sys_homeassistant.websocket.send_message(
{
ATTR_TYPE: WSType.SUPERVISOR_EVENT,
@@ -592,6 +561,12 @@ class Addon(AddonModel):
async def unload(self) -> None:
"""Unload add-on and remove data."""
if self._startup_task:
# If we were waiting on startup, cancel that and let the task finish before proceeding
self._startup_task.cancel(f"Removing add-on {self.name} from system")
with suppress(asyncio.CancelledError):
await self._startup_task
for listener in self._listeners:
self.sys_bus.remove_listener(listener)
@@ -680,11 +655,32 @@ class Addon(AddonModel):
return False
return True
async def start(self) -> None:
"""Set options and start add-on."""
async def _wait_for_startup(self) -> None:
"""Wait for startup event to be set with timeout."""
try:
self._startup_task = self.sys_create_task(self._startup_event.wait())
await asyncio.wait_for(self._startup_task, STARTUP_TIMEOUT)
except asyncio.TimeoutError:
_LOGGER.warning(
"Timeout while waiting for addon %s to start, took more then %s seconds",
self.name,
STARTUP_TIMEOUT,
)
except asyncio.CancelledError as err:
_LOGGER.info("Wait for addon startup task cancelled due to: %s", err)
finally:
self._startup_task = None
async def start(self) -> Awaitable[None]:
"""Set options and start add-on.
Returns a coroutine that completes when addon has state 'started'.
For addons with a healthcheck, that is when they become healthy or unhealthy.
Addons without a healthcheck have state 'started' immediately.
"""
if await self.instance.is_running():
_LOGGER.warning("%s is already running!", self.slug)
return
return self._wait_for_startup()
# Access Token
self.persist[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
@@ -698,12 +694,15 @@ class Addon(AddonModel):
self.write_pulse()
# Start Add-on
self._startup_event.clear()
try:
await self.instance.run()
except DockerError as err:
self.state = AddonState.ERROR
raise AddonsError() from err
return self._wait_for_startup()
async def stop(self) -> None:
"""Stop add-on."""
self._manual_stop = True
@@ -713,11 +712,14 @@ class Addon(AddonModel):
self.state = AddonState.ERROR
raise AddonsError() from err
async def restart(self) -> None:
"""Restart add-on."""
async def restart(self) -> Awaitable[None]:
"""Restart add-on.
Returns a coroutine that completes when addon has state 'started' (see start).
"""
with suppress(AddonsError):
await self.stop()
await self.start()
return await self.start()
def logs(self) -> Awaitable[bytes]:
"""Return add-ons log output.
@@ -741,10 +743,7 @@ class Addon(AddonModel):
raise AddonsError() from err
async def write_stdin(self, data) -> None:
"""Write data to add-on stdin.
Return a coroutine.
"""
"""Write data to add-on stdin."""
if not self.with_stdin:
raise AddonsNotSupportedError(
f"Add-on {self.slug} does not support writing to stdin!", _LOGGER.error
@@ -772,9 +771,50 @@ class Addon(AddonModel):
_LOGGER.error,
) from err
async def backup(self, tar_file: tarfile.TarFile) -> None:
"""Backup state of an add-on."""
is_running = await self.is_running()
@Job(name="addon_begin_backup")
async def begin_backup(self) -> bool:
"""Execute pre commands or stop addon if necessary.
Returns value of `is_running`. Caller should not call `end_backup` if return is false.
"""
if not await self.is_running():
return False
if self.backup_mode == AddonBackupMode.COLD:
_LOGGER.info("Shutdown add-on %s for cold backup", self.slug)
try:
await self.instance.stop()
except DockerError as err:
raise AddonsError() from err
elif self.backup_pre is not None:
await self._backup_command(self.backup_pre)
return True
@Job(name="addon_end_backup")
async def end_backup(self) -> Awaitable[None] | None:
"""Execute post commands or restart addon if necessary.
Returns a coroutine that completes when addon has state 'started' (see start)
for cold backup. Else nothing is returned.
"""
if self.backup_mode is AddonBackupMode.COLD:
_LOGGER.info("Starting add-on %s again", self.slug)
return await self.start()
if self.backup_post is not None:
await self._backup_command(self.backup_post)
return None
@Job(name="addon_backup")
async def backup(self, tar_file: tarfile.TarFile) -> Awaitable[None] | None:
"""Backup state of an add-on.
Returns a coroutine 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)
@@ -790,7 +830,7 @@ class Addon(AddonModel):
ATTR_USER: self.persist,
ATTR_SYSTEM: self.data,
ATTR_VERSION: self.version,
ATTR_STATE: self.state,
ATTR_STATE: _MAP_ADDON_STATE.get(self.state, self.state),
}
# Store local configs/state
@@ -826,16 +866,7 @@ class Addon(AddonModel):
arcname="data",
)
if (
is_running
and self.backup_mode == AddonBackupMode.HOT
and self.backup_pre is not None
):
await self._backup_command(self.backup_pre)
elif is_running and self.backup_mode == AddonBackupMode.COLD:
_LOGGER.info("Shutdown add-on %s for cold backup", self.slug)
await self.instance.stop()
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)
@@ -844,20 +875,19 @@ class Addon(AddonModel):
f"Can't write tarfile {tar_file}: {err}", _LOGGER.error
) from err
finally:
if (
is_running
and self.backup_mode == AddonBackupMode.HOT
and self.backup_post is not None
):
await self._backup_command(self.backup_post)
elif is_running and self.backup_mode is AddonBackupMode.COLD:
_LOGGER.info("Starting add-on %s again", self.slug)
await self.start()
if is_running:
wait_for_start = await self.end_backup()
_LOGGER.info("Finish backup for addon %s", self.slug)
return wait_for_start
async def restore(self, tar_file: tarfile.TarFile) -> None:
"""Restore state of an add-on."""
async def restore(self, tar_file: tarfile.TarFile) -> Awaitable[None] | None:
"""Restore state of an add-on.
Returns a coroutine 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():
@@ -901,6 +931,11 @@ class Addon(AddonModel):
self.slug, data[ATTR_USER], data[ATTR_SYSTEM], restore_image
)
# Stop it first if its running
if await self.instance.is_running():
with suppress(DockerError):
await self.instance.stop()
# Check version / restore image
version = data[ATTR_VERSION]
if not await self.instance.exists():
@@ -918,9 +953,6 @@ class Addon(AddonModel):
_LOGGER.info("Restore/Update of image for addon %s", self.slug)
with suppress(DockerError):
await self.instance.update(version, restore_image)
else:
with suppress(DockerError):
await self.instance.stop()
# Restore data
def _restore_data():
@@ -958,9 +990,10 @@ class Addon(AddonModel):
# Run add-on
if data[ATTR_STATE] == AddonState.STARTED:
return await self.start()
wait_for_start = await self.start()
_LOGGER.info("Finished restore for add-on %s", self.slug)
return wait_for_start
def check_trust(self) -> Awaitable[None]:
"""Calculate Addon docker content trust.
@@ -969,17 +1002,64 @@ class Addon(AddonModel):
"""
return self.instance.check_trust()
@Job(
name="addon_restart_after_problem",
limit=JobExecutionLimit.GROUP_THROTTLE_RATE_LIMIT,
throttle_period=WATCHDOG_THROTTLE_PERIOD,
throttle_max_calls=WATCHDOG_THROTTLE_MAX_CALLS,
on_condition=AddonsJobError,
)
async def _restart_after_problem(self, state: ContainerState):
"""Restart unhealthy or failed addon."""
attempts = 0
while await self.instance.current_state() == state:
if not self.in_progress:
_LOGGER.warning(
"Watchdog found addon %s is %s, restarting...",
self.name,
state,
)
try:
if state == ContainerState.FAILED:
# Ensure failed container is removed before attempting reanimation
if attempts == 0:
with suppress(DockerError):
await self.instance.stop(remove_container=True)
await (await self.start())
else:
await (await self.restart())
except AddonsError as err:
attempts = attempts + 1
_LOGGER.error("Watchdog restart of addon %s failed!", self.name)
capture_exception(err)
else:
break
if attempts >= WATCHDOG_MAX_ATTEMPTS:
_LOGGER.critical(
"Watchdog cannot restart addon %s, failed all %s attempts",
self.name,
attempts,
)
break
await asyncio.sleep(WATCHDOG_RETRY_SECONDS)
async def container_state_changed(self, event: DockerContainerStateEvent) -> None:
"""Set addon state from container state."""
if event.name != self.instance.name:
return
if event.state in [
ContainerState.RUNNING,
if event.state == ContainerState.RUNNING:
self._manual_stop = False
self.state = (
AddonState.STARTUP if self.instance.healthcheck else AddonState.STARTED
)
elif event.state in [
ContainerState.HEALTHY,
ContainerState.UNHEALTHY,
]:
self._manual_stop = False
self.state = AddonState.STARTED
elif event.state == ContainerState.STOPPED:
self.state = AddonState.STOPPED
@@ -1000,4 +1080,4 @@ class Addon(AddonModel):
ContainerState.STOPPED,
ContainerState.UNHEALTHY,
]:
await self._restart_after_problem(self, event.state)
await self._restart_after_problem(event.state)

View File

@@ -1,11 +1,11 @@
"""Add-on static data."""
from datetime import timedelta
from enum import Enum
from enum import StrEnum
from ..jobs.const import JobCondition
class AddonBackupMode(str, Enum):
class AddonBackupMode(StrEnum):
"""Backup mode of an Add-on."""
HOT = "hot"

View File

@@ -1,5 +1,6 @@
"""Init file for Supervisor add-ons."""
from abc import ABC, abstractmethod
from collections import defaultdict
from collections.abc import Awaitable, Callable
from contextlib import suppress
import logging
@@ -79,9 +80,11 @@ from ..const import (
AddonStage,
AddonStartup,
)
from ..coresys import CoreSys, CoreSysAttributes
from ..coresys import CoreSys
from ..docker.const import Capabilities
from ..exceptions import AddonsNotSupportedError
from ..jobs.const import JOB_GROUP_ADDON
from ..jobs.job_group import JobGroup
from .const import ATTR_BACKUP, ATTR_CODENOTARY, AddonBackupMode
from .options import AddonOptions, UiOptions
from .validate import RE_SERVICE, RE_VOLUME
@@ -91,12 +94,14 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
Data = dict[str, Any]
class AddonModel(CoreSysAttributes, ABC):
class AddonModel(JobGroup, ABC):
"""Add-on Data layout."""
def __init__(self, coresys: CoreSys, slug: str):
"""Initialize data holder."""
self.coresys: CoreSys = coresys
super().__init__(
coresys, JOB_GROUP_ADDON.format_map(defaultdict(str, slug=slug)), slug
)
self.slug: str = slug
@property
@@ -673,10 +678,10 @@ class AddonModel(CoreSysAttributes, ABC):
"""Uninstall this add-on."""
return self.sys_addons.uninstall(self.slug)
def update(self, backup: bool | None = False) -> Awaitable[None]:
def update(self, backup: bool | None = False) -> Awaitable[Awaitable[None] | None]:
"""Update this add-on."""
return self.sys_addons.update(self.slug, backup=backup)
def rebuild(self) -> Awaitable[None]:
def rebuild(self) -> Awaitable[Awaitable[None] | None]:
"""Rebuild this add-on."""
return self.sys_addons.rebuild(self.slug)

View File

@@ -143,6 +143,8 @@ RE_MACHINE = re.compile(
r"|raspberrypi3"
r"|raspberrypi4-64"
r"|raspberrypi4"
r"|yellow"
r"|green"
r"|tinker"
r")$"
)
@@ -175,6 +177,20 @@ 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
@@ -196,9 +212,9 @@ def _migrate_addon_config(protocol=False):
name,
)
if value == "before":
config[ATTR_STARTUP] = AddonStartup.SERVICES.value
config[ATTR_STARTUP] = AddonStartup.SERVICES
elif value == "after":
config[ATTR_STARTUP] = AddonStartup.APPLICATION.value
config[ATTR_STARTUP] = AddonStartup.APPLICATION
# UART 2021-01-20
if "auto_uart" in config:
@@ -313,7 +329,7 @@ _SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_DOCKER_API, default=False): vol.Boolean(),
vol.Optional(ATTR_AUTH_API, default=False): vol.Boolean(),
vol.Optional(ATTR_SERVICES): [vol.Match(RE_SERVICE)],
vol.Optional(ATTR_DISCOVERY): [valid_discovery_service],
vol.Optional(ATTR_DISCOVERY): [str],
vol.Optional(ATTR_BACKUP_EXCLUDE): [str],
vol.Optional(ATTR_BACKUP_PRE): str,
vol.Optional(ATTR_BACKUP_POST): str,

View File

@@ -186,6 +186,8 @@ class RestAPI(CoreSysAttributes):
# Boards endpoints
self.webapp.add_routes(
[
web.get("/os/boards/green", api_os.boards_green_info),
web.post("/os/boards/green", api_os.boards_green_options),
web.get("/os/boards/yellow", api_os.boards_yellow_info),
web.post("/os/boards/yellow", api_os.boards_yellow_options),
web.get("/os/boards/{board}", api_os.boards_other_info),
@@ -485,6 +487,8 @@ class RestAPI(CoreSysAttributes):
web.get("/backups/info", api_backups.info),
web.post("/backups/options", api_backups.options),
web.post("/backups/reload", api_backups.reload),
web.post("/backups/freeze", api_backups.freeze),
web.post("/backups/thaw", api_backups.thaw),
web.post("/backups/new/full", api_backups.backup_full),
web.post("/backups/new/partial", api_backups.backup_partial),
web.post("/backups/new/upload", api_backups.upload),

View File

@@ -391,10 +391,11 @@ class APIAddons(CoreSysAttributes):
return asyncio.shield(addon.uninstall())
@api_process
def start(self, request: web.Request) -> Awaitable[None]:
async def start(self, request: web.Request) -> None:
"""Start add-on."""
addon = self._extract_addon(request)
return asyncio.shield(addon.start())
if start_task := await asyncio.shield(addon.start()):
await start_task
@api_process
def stop(self, request: web.Request) -> Awaitable[None]:
@@ -403,16 +404,18 @@ class APIAddons(CoreSysAttributes):
return asyncio.shield(addon.stop())
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
async def restart(self, request: web.Request) -> None:
"""Restart add-on."""
addon: Addon = self._extract_addon(request)
return asyncio.shield(addon.restart())
if start_task := await asyncio.shield(addon.restart()):
await start_task
@api_process
def rebuild(self, request: web.Request) -> Awaitable[None]:
async def rebuild(self, request: web.Request) -> None:
"""Rebuild local build add-on."""
addon = self._extract_addon(request)
return asyncio.shield(addon.rebuild())
if start_task := await asyncio.shield(addon.rebuild()):
await start_task
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:

View File

@@ -1,11 +1,11 @@
"""Init file for Supervisor Audio RESTful API."""
import asyncio
from collections.abc import Awaitable
from dataclasses import asdict
import logging
from typing import Any
from aiohttp import web
import attr
import voluptuous as vol
from ..const import (
@@ -76,15 +76,11 @@ class APIAudio(CoreSysAttributes):
ATTR_UPDATE_AVAILABLE: self.sys_plugins.audio.need_update,
ATTR_HOST: str(self.sys_docker.network.audio),
ATTR_AUDIO: {
ATTR_CARD: [attr.asdict(card) for card in self.sys_host.sound.cards],
ATTR_INPUT: [
attr.asdict(stream) for stream in self.sys_host.sound.inputs
],
ATTR_OUTPUT: [
attr.asdict(stream) for stream in self.sys_host.sound.outputs
],
ATTR_CARD: [asdict(card) for card in self.sys_host.sound.cards],
ATTR_INPUT: [asdict(stream) for stream in self.sys_host.sound.inputs],
ATTR_OUTPUT: [asdict(stream) for stream in self.sys_host.sound.outputs],
ATTR_APPLICATION: [
attr.asdict(stream) for stream in self.sys_host.sound.applications
asdict(stream) for stream in self.sys_host.sound.applications
],
},
}

View File

@@ -28,6 +28,7 @@ from ..const import (
ATTR_SIZE,
ATTR_SLUG,
ATTR_SUPERVISOR_VERSION,
ATTR_TIMEOUT,
ATTR_TYPE,
ATTR_VERSION,
)
@@ -80,6 +81,12 @@ SCHEMA_OPTIONS = vol.Schema(
}
)
SCHEMA_FREEZE = vol.Schema(
{
vol.Optional(ATTR_TIMEOUT): vol.All(int, vol.Range(min=1)),
}
)
class APIBackups(CoreSysAttributes):
"""Handle RESTful API for backups functions."""
@@ -142,7 +149,7 @@ class APIBackups(CoreSysAttributes):
self.sys_backups.save_data()
@api_process
async def reload(self, request):
async def reload(self, _):
"""Reload backup list."""
await asyncio.shield(self.sys_backups.reload())
return True
@@ -233,6 +240,17 @@ class APIBackups(CoreSysAttributes):
return await asyncio.shield(self.sys_backups.do_restore_partial(backup, **body))
@api_process
async def freeze(self, 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):
"""Begin thaw after manual freeze."""
await self.sys_backups.thaw_all()
@api_process
async def remove(self, request):
"""Remove a backup."""

View File

@@ -23,7 +23,6 @@ ATTR_CONNECTION_BUS = "connection_bus"
ATTR_DATA_DISK = "data_disk"
ATTR_DEVICE = "device"
ATTR_DEV_PATH = "dev_path"
ATTR_DISK_LED = "disk_led"
ATTR_DISKS = "disks"
ATTR_DRIVES = "drives"
ATTR_DT_SYNCHRONIZED = "dt_synchronized"
@@ -31,8 +30,8 @@ ATTR_DT_UTC = "dt_utc"
ATTR_EJECTABLE = "ejectable"
ATTR_FALLBACK = "fallback"
ATTR_FILESYSTEMS = "filesystems"
ATTR_HEARTBEAT_LED = "heartbeat_led"
ATTR_IDENTIFIERS = "identifiers"
ATTR_JOBS = "jobs"
ATTR_LLMNR = "llmnr"
ATTR_LLMNR_HOSTNAME = "llmnr_hostname"
ATTR_MDNS = "mdns"
@@ -40,7 +39,6 @@ ATTR_MODEL = "model"
ATTR_MOUNTS = "mounts"
ATTR_MOUNT_POINTS = "mount_points"
ATTR_PANEL_PATH = "panel_path"
ATTR_POWER_LED = "power_led"
ATTR_REMOVABLE = "removable"
ATTR_REVISION = "revision"
ATTR_SEAT = "seat"
@@ -48,6 +46,7 @@ ATTR_SIGNED = "signed"
ATTR_STARTUP_TIME = "startup_time"
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"

View File

@@ -1,6 +1,9 @@
"""Init file for Supervisor network RESTful API."""
import logging
import voluptuous as vol
from ..addons.addon import Addon
from ..const import (
ATTR_ADDON,
ATTR_CONFIG,
@@ -9,15 +12,18 @@ from ..const import (
ATTR_SERVICES,
ATTR_UUID,
REQUEST_FROM,
AddonState,
)
from ..coresys import CoreSysAttributes
from ..discovery.validate import valid_discovery_service
from ..exceptions import APIError, APIForbidden
from .utils import api_process, api_validate, require_home_assistant
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_DISCOVERY = vol.Schema(
{
vol.Required(ATTR_SERVICE): valid_discovery_service,
vol.Required(ATTR_SERVICE): str,
vol.Optional(ATTR_CONFIG): vol.Maybe(dict),
}
)
@@ -36,19 +42,19 @@ class APIDiscovery(CoreSysAttributes):
@api_process
@require_home_assistant
async def list(self, request):
"""Show register services."""
"""Show registered and available services."""
# Get available discovery
discovery = []
for message in self.sys_discovery.list_messages:
discovery.append(
{
ATTR_ADDON: message.addon,
ATTR_SERVICE: message.service,
ATTR_UUID: message.uuid,
ATTR_CONFIG: message.config,
}
)
discovery = [
{
ATTR_ADDON: message.addon,
ATTR_SERVICE: message.service,
ATTR_UUID: message.uuid,
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
]
# Get available services/add-ons
services = {}
@@ -62,11 +68,28 @@ class APIDiscovery(CoreSysAttributes):
async def set_discovery(self, request):
"""Write data into a discovery pipeline."""
body = await api_validate(SCHEMA_DISCOVERY, request)
addon = request[REQUEST_FROM]
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:
raise APIForbidden("Can't use discovery!")
_LOGGER.error(
"Add-on %s attempted to send discovery for service %s which is not listed in its config. Please report this to the maintainer of the add-on",
addon.name,
service,
)
raise APIForbidden(
"Add-ons must list services they provide via discovery in their config!"
)
# Process discovery message
message = self.sys_discovery.send(addon, **body)

View File

@@ -21,11 +21,18 @@ from ..const import (
ATTR_ICON,
ATTR_PANELS,
ATTR_SESSION,
ATTR_SESSION_DATA_USER_ID,
ATTR_TITLE,
HEADER_REMOTE_USER_DISPLAY_NAME,
HEADER_REMOTE_USER_ID,
HEADER_REMOTE_USER_NAME,
HEADER_TOKEN,
HEADER_TOKEN_OLD,
IngressSessionData,
IngressSessionDataUser,
)
from ..coresys import CoreSysAttributes
from ..exceptions import HomeAssistantAPIError
from .const import COOKIE_INGRESS
from .utils import api_process, api_validate, require_home_assistant
@@ -33,10 +40,23 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
VALIDATE_SESSION_DATA = vol.Schema({ATTR_SESSION: str})
"""Expected optional payload of create session request"""
SCHEMA_INGRESS_CREATE_SESSION_DATA = vol.Schema(
{
vol.Optional(ATTR_SESSION_DATA_USER_ID): str,
}
)
class APIIngress(CoreSysAttributes):
"""Ingress view to handle add-on webui routing."""
_list_of_users: list[IngressSessionDataUser]
def __init__(self) -> None:
"""Initialize APIIngress."""
self._list_of_users = []
def _extract_addon(self, request: web.Request) -> Addon:
"""Return addon, throw an exception it it doesn't exist."""
token = request.match_info.get("token")
@@ -71,7 +91,19 @@ class APIIngress(CoreSysAttributes):
@require_home_assistant
async def create_session(self, request: web.Request) -> dict[str, Any]:
"""Create a new session."""
session = self.sys_ingress.create_session()
schema_ingress_config_session_data = await api_validate(
SCHEMA_INGRESS_CREATE_SESSION_DATA, request
)
data: IngressSessionData | None = None
if ATTR_SESSION_DATA_USER_ID in schema_ingress_config_session_data:
user = await self._find_user_by_id(
schema_ingress_config_session_data[ATTR_SESSION_DATA_USER_ID]
)
if user:
data = IngressSessionData(user)
session = self.sys_ingress.create_session(data)
return {ATTR_SESSION: session}
@api_process
@@ -99,13 +131,14 @@ class APIIngress(CoreSysAttributes):
# Process requests
addon = self._extract_addon(request)
path = request.match_info.get("path")
session_data = self.sys_ingress.get_session_data(session)
try:
# Websocket
if _is_websocket(request):
return await self._handle_websocket(request, addon, path)
return await self._handle_websocket(request, addon, path, session_data)
# Request
return await self._handle_request(request, addon, path)
return await self._handle_request(request, addon, path, session_data)
except aiohttp.ClientError as err:
_LOGGER.error("Ingress error: %s", err)
@@ -113,7 +146,11 @@ class APIIngress(CoreSysAttributes):
raise HTTPBadGateway()
async def _handle_websocket(
self, request: web.Request, addon: Addon, path: str
self,
request: web.Request,
addon: Addon,
path: str,
session_data: IngressSessionData | None,
) -> web.WebSocketResponse:
"""Ingress route for websocket."""
if hdrs.SEC_WEBSOCKET_PROTOCOL in request.headers:
@@ -131,7 +168,7 @@ class APIIngress(CoreSysAttributes):
# Preparing
url = self._create_url(addon, path)
source_header = _init_header(request, addon)
source_header = _init_header(request, addon, session_data)
# Support GET query
if request.query_string:
@@ -157,11 +194,15 @@ class APIIngress(CoreSysAttributes):
return ws_server
async def _handle_request(
self, request: web.Request, addon: Addon, path: str
self,
request: web.Request,
addon: Addon,
path: str,
session_data: IngressSessionData | None,
) -> web.Response | web.StreamResponse:
"""Ingress route for request."""
url = self._create_url(addon, path)
source_header = _init_header(request, addon)
source_header = _init_header(request, addon, session_data)
# Passing the raw stream breaks requests for some webservers
# since we just need it for POST requests really, for all other methods
@@ -217,11 +258,35 @@ class APIIngress(CoreSysAttributes):
return response
async def _find_user_by_id(self, user_id: str) -> IngressSessionDataUser | None:
"""Find user object by the user's ID."""
try:
list_of_users = await self.sys_homeassistant.get_users()
except (HomeAssistantAPIError, TypeError) as err:
_LOGGER.error(
"%s error occurred while requesting list of users: %s", type(err), err
)
return None
def _init_header(request: web.Request, addon: str) -> CIMultiDict | dict[str, str]:
if list_of_users is not None:
self._list_of_users = list_of_users
return next((user for user in self._list_of_users if user.id == user_id), None)
def _init_header(
request: web.Request, addon: Addon, session_data: IngressSessionData | None
) -> CIMultiDict | dict[str, str]:
"""Create initial header."""
headers = {}
if session_data is not None:
headers[HEADER_REMOTE_USER_ID] = session_data.user.id
if session_data.user.username is not None:
headers[HEADER_REMOTE_USER_NAME] = session_data.user.username
if session_data.user.display_name is not None:
headers[HEADER_REMOTE_USER_DISPLAY_NAME] = session_data.user.display_name
# filter flags
for name, value in request.headers.items():
if name in (
@@ -234,6 +299,9 @@ def _init_header(request: web.Request, addon: str) -> CIMultiDict | dict[str, st
hdrs.SEC_WEBSOCKET_KEY,
istr(HEADER_TOKEN),
istr(HEADER_TOKEN_OLD),
istr(HEADER_REMOTE_USER_ID),
istr(HEADER_REMOTE_USER_NAME),
istr(HEADER_REMOTE_USER_DISPLAY_NAME),
):
continue
headers[name] = value

View File

@@ -6,7 +6,9 @@ from aiohttp import web
import voluptuous as vol
from ..coresys import CoreSysAttributes
from ..jobs import SupervisorJob
from ..jobs.const import ATTR_IGNORE_CONDITIONS, JobCondition
from .const import ATTR_JOBS
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -19,11 +21,45 @@ 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."""
jobs_by_parent: dict[str | None, list[SupervisorJob]] = {}
for job in self.sys_jobs.jobs:
if job.internal:
continue
if job.parent_id not in jobs_by_parent:
jobs_by_parent[job.parent_id] = [job]
else:
jobs_by_parent[job.parent_id].append(job)
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, [])
]
while queue:
(current_list, current_job) = queue.pop(0)
child_jobs: list[dict[str, Any]] = []
# We remove parent_id and instead use that info to represent jobs as a tree
job_dict = current_job.as_dict() | {"child_jobs": child_jobs}
job_dict.pop("parent_id")
current_list.append(job_dict)
if current_job.uuid in jobs_by_parent:
queue.extend(
[(child_jobs, job) for job in jobs_by_parent.get(current_job.uuid)]
)
return job_list
@api_process
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return JobManager information."""
return {
ATTR_IGNORE_CONDITIONS: self.sys_jobs.ignore_conditions,
ATTR_JOBS: self._list_jobs(),
}
@api_process

View File

@@ -195,7 +195,7 @@ class SecurityMiddleware(CoreSysAttributes):
CoreState.FREEZE,
):
return api_return_error(
message=f"System is not ready with state: {self.sys_core.state.value}"
message=f"System is not ready with state: {self.sys_core.state}"
)
return await handler(request)

View File

@@ -1,11 +1,11 @@
"""REST API for network."""
import asyncio
from collections.abc import Awaitable
from dataclasses import replace
from ipaddress import ip_address, ip_interface
from typing import Any
from aiohttp import web
import attr
import voluptuous as vol
from ..const import (
@@ -43,8 +43,7 @@ from ..const import (
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, HostNetworkNotFound
from ..host.const import AuthMethod, InterfaceType, WifiMode
from ..host.network import (
from ..host.configuration import (
AccessPoint,
Interface,
InterfaceMethod,
@@ -52,6 +51,7 @@ from ..host.network import (
VlanConfig,
WifiConfig,
)
from ..host.const import AuthMethod, InterfaceType, WifiMode
from .utils import api_process, api_validate
_SCHEMA_IP_CONFIG = vol.Schema(
@@ -121,6 +121,7 @@ def interface_struct(interface: Interface) -> dict[str, Any]:
ATTR_ENABLED: interface.enabled,
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_WIFI: wifi_struct(interface.wifi) if interface.wifi else None,
@@ -196,19 +197,19 @@ class APINetwork(CoreSysAttributes):
# Apply config
for key, config in body.items():
if key == ATTR_IPV4:
interface.ipv4 = attr.evolve(
interface.ipv4 = replace(
interface.ipv4
or IpConfig(InterfaceMethod.STATIC, [], None, [], None),
**config,
)
elif key == ATTR_IPV6:
interface.ipv6 = attr.evolve(
interface.ipv6 = replace(
interface.ipv6
or IpConfig(InterfaceMethod.STATIC, [], None, [], None),
**config,
)
elif key == ATTR_WIFI:
interface.wifi = attr.evolve(
interface.wifi = replace(
interface.wifi
or WifiConfig(
WifiMode.INFRASTRUCTURE, "", AuthMethod.OPEN, None, None
@@ -276,6 +277,8 @@ class APINetwork(CoreSysAttributes):
)
vlan_interface = Interface(
"",
"",
"",
True,
True,

View File

@@ -8,11 +8,15 @@ from aiohttp import web
import voluptuous as vol
from ..const import (
ATTR_ACTIVITY_LED,
ATTR_BOARD,
ATTR_BOOT,
ATTR_DEVICES,
ATTR_DISK_LED,
ATTR_HEARTBEAT_LED,
ATTR_ID,
ATTR_NAME,
ATTR_POWER_LED,
ATTR_SERIAL,
ATTR_SIZE,
ATTR_UPDATE_AVAILABLE,
@@ -27,21 +31,19 @@ from .const import (
ATTR_DATA_DISK,
ATTR_DEV_PATH,
ATTR_DEVICE,
ATTR_DISK_LED,
ATTR_DISKS,
ATTR_HEARTBEAT_LED,
ATTR_MODEL,
ATTR_POWER_LED,
ATTR_SYSTEM_HEALTH_LED,
ATTR_VENDOR,
)
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
# pylint: disable=no-value-for-parameter
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
SCHEMA_DISK = vol.Schema({vol.Required(ATTR_DEVICE): str})
# pylint: disable=no-value-for-parameter
SCHEMA_YELLOW_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_DISK_LED): vol.Boolean(),
@@ -49,6 +51,14 @@ SCHEMA_YELLOW_OPTIONS = vol.Schema(
vol.Optional(ATTR_POWER_LED): vol.Boolean(),
}
)
SCHEMA_GREEN_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_ACTIVITY_LED): vol.Boolean(),
vol.Optional(ATTR_POWER_LED): vol.Boolean(),
vol.Optional(ATTR_SYSTEM_HEALTH_LED): vol.Boolean(),
}
)
# pylint: enable=no-value-for-parameter
class APIOS(CoreSysAttributes):
@@ -105,6 +115,31 @@ class APIOS(CoreSysAttributes):
],
}
@api_process
async def boards_green_info(self, request: web.Request) -> dict[str, Any]:
"""Get green board settings."""
return {
ATTR_ACTIVITY_LED: self.sys_dbus.agent.board.green.activity_led,
ATTR_POWER_LED: self.sys_dbus.agent.board.green.power_led,
ATTR_SYSTEM_HEALTH_LED: self.sys_dbus.agent.board.green.user_led,
}
@api_process
async def boards_green_options(self, request: web.Request) -> None:
"""Update green board settings."""
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]
if ATTR_POWER_LED in body:
self.sys_dbus.agent.board.green.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]
self.sys_dbus.agent.board.green.save_data()
@api_process
async def boards_yellow_info(self, request: web.Request) -> dict[str, Any]:
"""Get yellow board settings."""
@@ -128,6 +163,7 @@ class APIOS(CoreSysAttributes):
if ATTR_POWER_LED in body:
self.sys_dbus.agent.board.yellow.power_led = body[ATTR_POWER_LED]
self.sys_dbus.agent.board.yellow.save_data()
self.sys_resolution.create_issue(
IssueType.REBOOT_REQUIRED,
ContextType.SYSTEM,

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-NoHhvMA3Ku8.js");else try{new Function("import('/api/hassio/app/frontend_latest/entrypoint-G81gb268sps.js')")()}catch(t){n("/api/hassio/app/frontend_es5/entrypoint-NoHhvMA3Ku8.js")}}()
!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")}}()

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 +1 @@
{"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/20230601.0/src/common/dom/stop_propagation.ts","https://raw.githubusercontent.com/home-assistant/frontend/20230601.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":""}
{"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

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,2 @@
!function(){"use strict";var n,t,e={14595:function(n,t,e){e(58556);var r,i,o=e(93217),u=e(422),a=e(62173),s=function(n,t,e){if("input"===n){if("type"===t&&"checkbox"===e||"checked"===t||"disabled"===t)return;return""}},c={renderMarkdown:function(n,t){var e,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return r||(r=Object.assign(Object.assign({},(0,a.getDefaultWhiteList)()),{},{input:["type","disabled","checked"],"ha-icon":["icon"],"ha-svg-icon":["path"],"ha-alert":["alert-type","title"]})),o.allowSvg?(i||(i=Object.assign(Object.assign({},r),{},{svg:["xmlns","height","width"],path:["transform","stroke","d"],img:["src"]})),e=i):e=r,(0,a.filterXSS)((0,u.TU)(n,t),{whiteList:e,onTagAttr:s})}};(0,o.Jj)(c)}},r={};function i(n){var t=r[n];if(void 0!==t)return t.exports;var o=r[n]={exports:{}};return e[n](o,o.exports,i),o.exports}i.m=e,i.x=function(){var n=i.O(void 0,[9191,215],(function(){return i(14595)}));return n=i.O(n)},n=[],i.O=function(t,e,r,o){if(!e){var u=1/0;for(f=0;f<n.length;f++){e=n[f][0],r=n[f][1],o=n[f][2];for(var a=!0,s=0;s<e.length;s++)(!1&o||u>=o)&&Object.keys(i.O).every((function(n){return i.O[n](e[s])}))?e.splice(s--,1):(a=!1,o<u&&(u=o));if(a){n.splice(f--,1);var c=r();void 0!==c&&(t=c)}}return t}o=o||0;for(var f=n.length;f>0&&n[f-1][2]>o;f--)n[f]=n[f-1];n[f]=[e,r,o]},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,{a:t}),t},i.d=function(n,t){for(var e in t)i.o(t,e)&&!i.o(n,e)&&Object.defineProperty(n,e,{enumerable:!0,get:t[e]})},i.f={},i.e=function(n){return Promise.all(Object.keys(i.f).reduce((function(t,e){return i.f[e](n,t),t}),[]))},i.u=function(n){return n+"-"+{215:"FPZmDYZTPdk",9191:"37260H-osZ4"}[n]+".js"},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="/api/hassio/app/frontend_es5/",function(){var n={1402:1};i.f.i=function(t,e){n[t]||importScripts(i.p+i.u(t))};var t=self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[],e=t.push.bind(t);t.push=function(t){var r=t[0],o=t[1],u=t[2];for(var a in o)i.o(o,a)&&(i.m[a]=o[a]);for(u&&u(i);r.length;)n[r.pop()]=1;e(t)}}(),t=i.x,i.x=function(){return Promise.all([i.e(9191),i.e(215)]).then(t)};i.x()}();
//# sourceMappingURL=1402-6WKUruvoXtM.js.map

View File

@@ -1 +1 @@
{"version":3,"file":"4971-bQWIUsuRYEk.js","mappings":"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","sources":["no-source/webpack/runtime/chunk loaded","no-source/webpack/runtime/startup chunk dependencies","https://raw.githubusercontent.com/home-assistant/frontend/20230601.0/src/resources/markdown_worker.ts","no-source/webpack/bootstrap","no-source/webpack/runtime/compat get default export","no-source/webpack/runtime/define property getters","no-source/webpack/runtime/ensure chunk","no-source/webpack/runtime/get javascript chunk filename","no-source/webpack/runtime/hasOwnProperty shorthand","no-source/webpack/runtime/publicPath","no-source/webpack/runtime/importScripts chunk loading","no-source/webpack/startup"],"names":["deferred","next","whiteListNormal","whiteListSvg","onTagAttr","tag","name","value","api","renderMarkdown","content","markedOptions","whiteList","hassOptions","arguments","length","undefined","Object","assign","getDefaultWhiteList","input","allowSvg","svg","path","img","filterXSS","marked","expose","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","m","x","__webpack_exports__","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","keys","every","key","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","get","f","e","chunkId","Promise","all","reduce","promises","u","obj","prop","prototype","hasOwnProperty","call","p","installedChunks","importScripts","chunkLoadingGlobal","self","parentChunkLoadingFunction","push","bind","data","moreModules","runtime","pop","then"],"sourceRoot":""}
{"version":3,"file":"1402-6WKUruvoXtM.js","mappings":"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","sources":["no-source/webpack/runtime/chunk loaded","no-source/webpack/runtime/startup chunk dependencies","https://raw.githubusercontent.com/home-assistant/frontend/20230703.0/src/resources/markdown-worker.ts","no-source/webpack/bootstrap","no-source/webpack/runtime/compat get default export","no-source/webpack/runtime/define property getters","no-source/webpack/runtime/ensure chunk","no-source/webpack/runtime/get javascript chunk filename","no-source/webpack/runtime/hasOwnProperty shorthand","no-source/webpack/runtime/publicPath","no-source/webpack/runtime/importScripts chunk loading","no-source/webpack/startup"],"names":["deferred","next","whiteListNormal","whiteListSvg","onTagAttr","tag","name","value","api","renderMarkdown","content","markedOptions","whiteList","hassOptions","arguments","length","undefined","Object","assign","getDefaultWhiteList","input","allowSvg","svg","path","img","filterXSS","marked","expose","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","m","x","__webpack_exports__","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","keys","every","key","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","get","f","e","chunkId","Promise","all","reduce","promises","u","obj","prop","prototype","hasOwnProperty","call","p","installedChunks","importScripts","chunkLoadingGlobal","self","parentChunkLoadingFunction","push","bind","data","moreModules","runtime","pop","then"],"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

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

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

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

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