Compare commits

..

78 Commits

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

* Clean up task for cloud backup and remove by location

* Args to kwargs on backup methods

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

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

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

* Test cases and small fixes identified

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

The exception is still printed to the logs but with all the extra noise
caused by this error. Removing the argument makes the stack trace more
comprehensible and the fallback actually works as desired.
2024-10-16 09:04:24 +02:00
3208 changed files with 5930 additions and 502143 deletions

View File

@@ -53,7 +53,7 @@ jobs:
requirements: ${{ steps.requirements.outputs.changed }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
@@ -92,7 +92,7 @@ jobs:
arch: ${{ fromJson(needs.init.outputs.architectures) }}
steps:
- name: Checkout the repository
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
@@ -106,7 +106,7 @@ jobs:
- name: Build wheels
if: needs.init.outputs.requirements == 'true'
uses: home-assistant/wheels@2024.07.1
uses: home-assistant/wheels@2024.11.0
with:
abi: cp312
tag: musllinux_1_2
@@ -125,7 +125,7 @@ jobs:
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
if: needs.init.outputs.publish == 'true'
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@@ -178,7 +178,7 @@ jobs:
steps:
- name: Checkout the repository
if: needs.init.outputs.publish == 'true'
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Initialize git
if: needs.init.outputs.publish == 'true'
@@ -203,7 +203,7 @@ jobs:
timeout-minutes: 60
steps:
- name: Checkout the repository
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Build the Supervisor
if: needs.init.outputs.publish != 'true'

View File

@@ -25,15 +25,15 @@ jobs:
name: Prepare Python dependencies
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python
id: python
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -47,7 +47,7 @@ jobs:
pip install -r requirements.txt -r requirements_tests.txt
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
lookup-only: true
@@ -67,15 +67,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -87,7 +87,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
@@ -110,15 +110,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -130,7 +130,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
@@ -153,7 +153,7 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Register hadolint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
@@ -168,15 +168,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -188,7 +188,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
@@ -212,15 +212,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -232,7 +232,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: |
@@ -256,15 +256,15 @@ jobs:
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -288,9 +288,9 @@ jobs:
name: Run tests Python ${{ needs.prepare.outputs.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
@@ -300,7 +300,7 @@ jobs:
cosign-release: "v2.4.0"
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -347,15 +347,15 @@ jobs:
needs: ["pytest", "prepare"]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
- name: Set up Python ${{ needs.prepare.outputs.python-version }}
uses: actions/setup-python@v5.2.0
uses: actions/setup-python@v5.3.0
id: python
with:
python-version: ${{ needs.prepare.outputs.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.1.1
uses: actions/cache@v4.2.0
with:
path: venv
key: |
@@ -374,4 +374,4 @@ jobs:
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4.6.0
uses: codecov/codecov-action@v5.1.1

View File

@@ -11,7 +11,7 @@ jobs:
name: Release Drafter
steps:
- name: Checkout the repository
uses: actions/checkout@v4.2.1
uses: actions/checkout@v4.2.2
with:
fetch-depth: 0

View File

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

View File

@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools~=68.0.0", "wheel~=0.40.0"]
requires = ["setuptools~=75.6.0", "wheel~=0.45.0"]
build-backend = "setuptools.build_meta"
[project]

View File

@@ -1,29 +1,29 @@
aiodns==3.2.0
aiohttp==3.10.10
aiohttp==3.11.10
atomicwrites-homeassistant==1.4.1
attrs==24.2.0
awesomeversion==24.6.0
brotli==1.1.0
ciso8601==2.3.1
colorlog==6.8.2
ciso8601==2.3.2
colorlog==6.9.0
cpe==1.3.1
cryptography==43.0.1
debugpy==1.8.7
cryptography==44.0.0
debugpy==1.8.9
deepmerge==2.0
dirhash==0.5.0
docker==7.1.0
faust-cchardet==2.1.19
gitpython==3.1.43
jinja2==3.1.4
orjson==3.10.7
pulsectl==24.8.0
orjson==3.10.12
pulsectl==24.11.0
pyudev==0.24.3
PyYAML==6.0.2
requests==2.32.3
securetar==2024.2.1
sentry-sdk==2.16.0
setuptools==75.1.0
securetar==2024.11.0
sentry-sdk==2.19.2
setuptools==75.6.0
voluptuous==0.15.2
dbus-fast==2.24.3
dbus-fast==2.24.4
typing_extensions==4.12.2
zlib-fast==0.2.0

View File

@@ -1,12 +1,12 @@
coverage==7.6.3
coverage==7.6.9
pre-commit==4.0.1
pylint==3.3.1
pylint==3.3.2
pytest-aiohttp==1.0.5
pytest-asyncio==0.23.6
pytest-cov==5.0.0
pytest-cov==6.0.0
pytest-timeout==2.3.1
pytest==8.3.3
ruff==0.6.9
pytest==8.3.4
ruff==0.8.2
time-machine==2.16.0
typing_extensions==4.12.2
urllib3==2.2.3

View File

@@ -12,7 +12,6 @@ nvm install
script/bootstrap
# Download translations
start_docker
./script/translations_download
# build frontend
@@ -25,6 +24,4 @@ cp -rf build/* ../../supervisor/api/panel/
# Reset frontend git
cd ..
git reset --hard HEAD
stop_docker
git reset --hard HEAD

View File

@@ -81,7 +81,8 @@ from ..hardware.data import Device
from ..homeassistant.const import WSEvent, WSType
from ..jobs.const import JobExecutionLimit
from ..jobs.decorator import Job
from ..resolution.const import UnhealthyReason
from ..resolution.const import ContextType, IssueType, UnhealthyReason
from ..resolution.data import Issue
from ..store.addon import AddonStore
from ..utils import check_port
from ..utils.apparmor import adjust_profile
@@ -144,11 +145,27 @@ class Addon(AddonModel):
self._listeners: list[EventListener] = []
self._startup_event = asyncio.Event()
self._startup_task: asyncio.Task | None = None
self._boot_failed_issue = Issue(
IssueType.BOOT_FAIL, ContextType.ADDON, reference=self.slug
)
self._device_access_missing_issue = Issue(
IssueType.DEVICE_ACCESS_MISSING, ContextType.ADDON, reference=self.slug
)
def __repr__(self) -> str:
"""Return internal representation."""
return f"<Addon: {self.slug}>"
@property
def boot_failed_issue(self) -> Issue:
"""Get issue used if start on boot failed."""
return self._boot_failed_issue
@property
def device_access_missing_issue(self) -> Issue:
"""Get issue used if device access is missing and can't be automatically added."""
return self._device_access_missing_issue
@property
def state(self) -> AddonState:
"""Return state of the add-on."""
@@ -166,6 +183,20 @@ class Addon(AddonModel):
if new_state == AddonState.STARTED or old_state == AddonState.STARTUP:
self._startup_event.set()
# Dismiss boot failed issue if present and we started
if (
new_state == AddonState.STARTED
and self.boot_failed_issue in self.sys_resolution.issues
):
self.sys_resolution.dismiss_issue(self.boot_failed_issue)
# Dismiss device access missing issue if present and we stopped
if (
new_state == AddonState.STOPPED
and self.device_access_missing_issue in self.sys_resolution.issues
):
self.sys_resolution.dismiss_issue(self.device_access_missing_issue)
self.sys_homeassistant.websocket.send_message(
{
ATTR_TYPE: WSType.SUPERVISOR_EVENT,
@@ -322,6 +353,13 @@ class Addon(AddonModel):
"""Store user boot options."""
self.persist[ATTR_BOOT] = value
# Dismiss boot failed issue if present and boot at start disabled
if (
value == AddonBoot.MANUAL
and self._boot_failed_issue in self.sys_resolution.issues
):
self.sys_resolution.dismiss_issue(self._boot_failed_issue)
@property
def auto_update(self) -> bool:
"""Return if auto update is enable."""

View File

@@ -7,24 +7,22 @@ import logging
import tarfile
from typing import Union
from attr import evolve
from ..const import AddonBoot, AddonStartup, AddonState
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
AddonConfigurationError,
AddonsError,
AddonsJobError,
AddonsNotSupportedError,
CoreDNSError,
DockerAPIError,
DockerError,
DockerNotFound,
HassioError,
HomeAssistantAPIError,
)
from ..jobs.decorator import Job, JobCondition
from ..resolution.const import ContextType, IssueType, SuggestionType
from ..store.addon import AddonStore
from ..utils import check_exception_chain
from ..utils.sentry import capture_exception
from .addon import Addon
from .const import ADDON_UPDATE_CONDITIONS
@@ -118,15 +116,14 @@ class AddonManager(CoreSysAttributes):
try:
if start_task := await addon.start():
wait_boot.append(start_task)
except AddonsError as err:
# Check if there is an system/user issue
if check_exception_chain(
err, (DockerAPIError, DockerNotFound, AddonConfigurationError)
):
addon.boot = AddonBoot.MANUAL
addon.save_persist()
except HassioError:
pass # These are already handled
self.sys_resolution.add_issue(
evolve(addon.boot_failed_issue),
suggestions=[
SuggestionType.EXECUTE_START,
SuggestionType.DISABLE_BOOT,
],
)
else:
continue
@@ -135,6 +132,19 @@ class AddonManager(CoreSysAttributes):
# Ignore exceptions from waiting for addon startup, addon errors handled elsewhere
await asyncio.gather(*wait_boot, return_exceptions=True)
# After waiting for startup, create an issue for boot addons that are error or unknown state
# Ignore stopped as single shot addons can be run at boot and this is successful exit
# Timeout waiting for startup is not a failure, addon is probably just slow
for addon in tasks:
if addon.state in {AddonState.ERROR, AddonState.UNKNOWN}:
self.sys_resolution.add_issue(
evolve(addon.boot_failed_issue),
suggestions=[
SuggestionType.EXECUTE_START,
SuggestionType.DISABLE_BOOT,
],
)
async def shutdown(self, stage: AddonStartup) -> None:
"""Shutdown addons."""
tasks: list[Addon] = []

View File

@@ -47,7 +47,7 @@ from ..const import (
ATTR_JOURNALD,
ATTR_KERNEL_MODULES,
ATTR_LEGACY,
ATTR_LOCATON,
ATTR_LOCATION,
ATTR_MACHINE,
ATTR_MAP,
ATTR_NAME,
@@ -581,7 +581,7 @@ class AddonModel(JobGroup, ABC):
@property
def path_location(self) -> Path:
"""Return path to this add-on."""
return Path(self.data[ATTR_LOCATON])
return Path(self.data[ATTR_LOCATION])
@property
def path_icon(self) -> Path:

View File

@@ -55,7 +55,7 @@ from ..const import (
ATTR_KERNEL_MODULES,
ATTR_LABELS,
ATTR_LEGACY,
ATTR_LOCATON,
ATTR_LOCATION,
ATTR_MACHINE,
ATTR_MAP,
ATTR_NAME,
@@ -483,7 +483,7 @@ SCHEMA_ADDON_SYSTEM = vol.All(
_migrate_addon_config(),
_SCHEMA_ADDON_CONFIG.extend(
{
vol.Required(ATTR_LOCATON): str,
vol.Required(ATTR_LOCATION): str,
vol.Required(ATTR_REPOSITORY): str,
vol.Required(ATTR_TRANSLATIONS, default=dict): {
str: SCHEMA_ADDON_TRANSLATIONS

View File

@@ -413,6 +413,7 @@ class RestAPI(CoreSysAttributes):
# No need to capture HostNotSupportedError to Sentry, the cause
# is known and reported to the user using the resolution center.
capture_exception(err)
kwargs.pop("follow", None) # Follow is not supported for Docker logs
return await api_supervisor.logs(*args, **kwargs)
self.webapp.add_routes(

View File

@@ -1,5 +1,7 @@
"""Backups RESTful API."""
from __future__ import annotations
import asyncio
from collections.abc import Callable
import errno
@@ -14,6 +16,7 @@ from aiohttp.hdrs import CONTENT_DISPOSITION
import voluptuous as vol
from ..backups.backup import Backup
from ..backups.const import LOCATION_CLOUD_BACKUP, LOCATION_TYPE
from ..backups.validate import ALL_FOLDERS, FOLDER_HOMEASSISTANT, days_until_stale
from ..const import (
ATTR_ADDONS,
@@ -22,10 +25,12 @@ from ..const import (
ATTR_CONTENT,
ATTR_DATE,
ATTR_DAYS_UNTIL_STALE,
ATTR_EXTRA,
ATTR_FOLDERS,
ATTR_HOMEASSISTANT,
ATTR_HOMEASSISTANT_EXCLUDE_DATABASE,
ATTR_LOCATON,
ATTR_JOB_ID,
ATTR_LOCATION,
ATTR_NAME,
ATTR_PASSWORD,
ATTR_PROTECTED,
@@ -36,25 +41,41 @@ from ..const import (
ATTR_TIMEOUT,
ATTR_TYPE,
ATTR_VERSION,
REQUEST_FROM,
BusEvent,
CoreState,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..exceptions import APIError, APIForbidden, APINotFound
from ..jobs import JobSchedulerOptions
from ..mounts.const import MountUsage
from ..resolution.const import UnhealthyReason
from .const import ATTR_BACKGROUND, ATTR_JOB_ID, CONTENT_TYPE_TAR
from .const import (
ATTR_ADDITIONAL_LOCATIONS,
ATTR_BACKGROUND,
ATTR_LOCATIONS,
ATTR_SIZE_BYTES,
CONTENT_TYPE_TAR,
)
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
RE_SLUGIFY_NAME = re.compile(r"[^A-Za-z0-9]+")
RE_BACKUP_FILENAME = re.compile(r"^[^\\\/]+\.tar$")
# Backwards compatible
# Remove: 2022.08
_ALL_FOLDERS = ALL_FOLDERS + [FOLDER_HOMEASSISTANT]
def _ensure_list(item: Any) -> list:
"""Ensure value is a list."""
if not isinstance(item, list):
return [item]
return item
# pylint: disable=no-value-for-parameter
SCHEMA_RESTORE_FULL = vol.Schema(
{
@@ -76,9 +97,12 @@ SCHEMA_BACKUP_FULL = vol.Schema(
vol.Optional(ATTR_NAME): str,
vol.Optional(ATTR_PASSWORD): vol.Maybe(str),
vol.Optional(ATTR_COMPRESSED): vol.Maybe(vol.Boolean()),
vol.Optional(ATTR_LOCATON): vol.Maybe(str),
vol.Optional(ATTR_LOCATION): vol.All(
_ensure_list, [vol.Maybe(str)], vol.Unique()
),
vol.Optional(ATTR_HOMEASSISTANT_EXCLUDE_DATABASE): vol.Boolean(),
vol.Optional(ATTR_BACKGROUND, default=False): vol.Boolean(),
vol.Optional(ATTR_EXTRA): dict,
}
)
@@ -102,6 +126,14 @@ SCHEMA_FREEZE = vol.Schema(
}
)
SCHEMA_REMOVE = vol.Schema(
{
vol.Optional(ATTR_LOCATION): vol.All(
_ensure_list, [vol.Maybe(str)], vol.Unique()
),
}
)
class APIBackups(CoreSysAttributes):
"""Handle RESTful API for backups functions."""
@@ -110,7 +142,7 @@ class APIBackups(CoreSysAttributes):
"""Return backup, throw an exception if it doesn't exist."""
backup = self.sys_backups.get(request.match_info.get("slug"))
if not backup:
raise APIError("Backup does not exist")
raise APINotFound("Backup does not exist")
return backup
def _list_backups(self):
@@ -122,7 +154,9 @@ class APIBackups(CoreSysAttributes):
ATTR_DATE: backup.date,
ATTR_TYPE: backup.sys_type,
ATTR_SIZE: backup.size,
ATTR_LOCATON: backup.location,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_LOCATION: backup.location,
ATTR_LOCATIONS: backup.locations,
ATTR_PROTECTED: backup.protected,
ATTR_COMPRESSED: backup.compressed,
ATTR_CONTENT: {
@@ -132,6 +166,7 @@ class APIBackups(CoreSysAttributes):
},
}
for backup in self.sys_backups.list_backups
if backup.location != LOCATION_CLOUD_BACKUP
]
@api_process
@@ -191,30 +226,52 @@ class APIBackups(CoreSysAttributes):
ATTR_NAME: backup.name,
ATTR_DATE: backup.date,
ATTR_SIZE: backup.size,
ATTR_SIZE_BYTES: backup.size_bytes,
ATTR_COMPRESSED: backup.compressed,
ATTR_PROTECTED: backup.protected,
ATTR_SUPERVISOR_VERSION: backup.supervisor_version,
ATTR_HOMEASSISTANT: backup.homeassistant_version,
ATTR_LOCATON: backup.location,
ATTR_LOCATION: backup.location,
ATTR_LOCATIONS: backup.locations,
ATTR_ADDONS: data_addons,
ATTR_REPOSITORIES: backup.repositories,
ATTR_FOLDERS: backup.folders,
ATTR_HOMEASSISTANT_EXCLUDE_DATABASE: backup.homeassistant_exclude_database,
ATTR_EXTRA: backup.extra,
}
def _location_to_mount(self, body: dict[str, Any]) -> dict[str, Any]:
"""Change location field to mount if necessary."""
if not body.get(ATTR_LOCATON):
return body
def _location_to_mount(self, location: str | None) -> LOCATION_TYPE:
"""Convert a single location to a mount if possible."""
if not location or location == LOCATION_CLOUD_BACKUP:
return location
body[ATTR_LOCATON] = self.sys_mounts.get(body[ATTR_LOCATON])
if body[ATTR_LOCATON].usage != MountUsage.BACKUP:
mount = self.sys_mounts.get(location)
if mount.usage != MountUsage.BACKUP:
raise APIError(
f"Mount {body[ATTR_LOCATON].name} is not used for backups, cannot backup to there"
f"Mount {mount.name} is not used for backups, cannot backup to there"
)
return mount
def _location_field_to_mount(self, body: dict[str, Any]) -> dict[str, Any]:
"""Change location field to mount if necessary."""
body[ATTR_LOCATION] = self._location_to_mount(body.get(ATTR_LOCATION))
return body
def _validate_cloud_backup_location(
self, request: web.Request, location: list[str | None] | str | None
) -> None:
"""Cloud backup location is only available to Home Assistant."""
if not isinstance(location, list):
location = [location]
if (
LOCATION_CLOUD_BACKUP in location
and request.get(REQUEST_FROM) != self.sys_homeassistant
):
raise APIForbidden(
f"Location {LOCATION_CLOUD_BACKUP} is only available for Home Assistant"
)
async def _background_backup_task(
self, backup_method: Callable, *args, **kwargs
) -> tuple[asyncio.Task, str]:
@@ -246,12 +303,25 @@ class APIBackups(CoreSysAttributes):
self.sys_bus.remove_listener(listener)
@api_process
async def backup_full(self, request):
async def backup_full(self, request: web.Request):
"""Create full backup."""
body = await api_validate(SCHEMA_BACKUP_FULL, request)
locations: list[LOCATION_TYPE] | None = None
if ATTR_LOCATION in body:
location_names: list[str | None] = body.pop(ATTR_LOCATION)
self._validate_cloud_backup_location(request, location_names)
locations = [
self._location_to_mount(location) for location in location_names
]
body[ATTR_LOCATION] = locations.pop(0)
if locations:
body[ATTR_ADDITIONAL_LOCATIONS] = locations
background = body.pop(ATTR_BACKGROUND)
backup_task, job_id = await self._background_backup_task(
self.sys_backups.do_backup_full, **self._location_to_mount(body)
self.sys_backups.do_backup_full, **body
)
if background and not backup_task.done():
@@ -266,12 +336,25 @@ class APIBackups(CoreSysAttributes):
)
@api_process
async def backup_partial(self, request):
async def backup_partial(self, request: web.Request):
"""Create a partial backup."""
body = await api_validate(SCHEMA_BACKUP_PARTIAL, request)
locations: list[LOCATION_TYPE] | None = None
if ATTR_LOCATION in body:
location_names: list[str | None] = body.pop(ATTR_LOCATION)
self._validate_cloud_backup_location(request, location_names)
locations = [
self._location_to_mount(location) for location in location_names
]
body[ATTR_LOCATION] = locations.pop(0)
if locations:
body[ATTR_ADDITIONAL_LOCATIONS] = locations
background = body.pop(ATTR_BACKGROUND)
backup_task, job_id = await self._background_backup_task(
self.sys_backups.do_backup_partial, **self._location_to_mount(body)
self.sys_backups.do_backup_partial, **body
)
if background and not backup_task.done():
@@ -286,9 +369,10 @@ class APIBackups(CoreSysAttributes):
)
@api_process
async def restore_full(self, request):
async def restore_full(self, request: web.Request):
"""Full restore of a backup."""
backup = self._extract_slug(request)
self._validate_cloud_backup_location(request, backup.location)
body = await api_validate(SCHEMA_RESTORE_FULL, request)
background = body.pop(ATTR_BACKGROUND)
restore_task, job_id = await self._background_backup_task(
@@ -303,9 +387,10 @@ class APIBackups(CoreSysAttributes):
)
@api_process
async def restore_partial(self, request):
async def restore_partial(self, request: web.Request):
"""Partial restore a backup."""
backup = self._extract_slug(request)
self._validate_cloud_backup_location(request, backup.location)
body = await api_validate(SCHEMA_RESTORE_PARTIAL, request)
background = body.pop(ATTR_BACKGROUND)
restore_task, job_id = await self._background_backup_task(
@@ -320,28 +405,43 @@ class APIBackups(CoreSysAttributes):
)
@api_process
async def freeze(self, request):
async def freeze(self, request: web.Request):
"""Initiate manual freeze for external backup."""
body = await api_validate(SCHEMA_FREEZE, request)
await asyncio.shield(self.sys_backups.freeze_all(**body))
@api_process
async def thaw(self, request):
async def thaw(self, request: web.Request):
"""Begin thaw after manual freeze."""
await self.sys_backups.thaw_all()
@api_process
async def remove(self, request):
async def remove(self, request: web.Request):
"""Remove a backup."""
backup = self._extract_slug(request)
return self.sys_backups.remove(backup)
body = await api_validate(SCHEMA_REMOVE, request)
locations: list[LOCATION_TYPE] | None = None
async def download(self, request):
if ATTR_LOCATION in body:
self._validate_cloud_backup_location(request, body[ATTR_LOCATION])
locations = [self._location_to_mount(name) for name in body[ATTR_LOCATION]]
else:
self._validate_cloud_backup_location(request, backup.location)
return self.sys_backups.remove(backup, locations=locations)
@api_process
async def download(self, request: web.Request):
"""Download a backup file."""
backup = self._extract_slug(request)
# Query will give us '' for /backups, convert value to None
location = request.query.get(ATTR_LOCATION, backup.location) or None
self._validate_cloud_backup_location(request, location)
if location not in backup.all_locations:
raise APIError(f"Backup {backup.slug} is not in location {location}")
_LOGGER.info("Downloading backup %s", backup.slug)
response = web.FileResponse(backup.tarfile)
response = web.FileResponse(backup.all_locations[location])
response.content_type = CONTENT_TYPE_TAR
response.headers[CONTENT_DISPOSITION] = (
f"attachment; filename={RE_SLUGIFY_NAME.sub('_', backup.name)}.tar"
@@ -349,9 +449,25 @@ class APIBackups(CoreSysAttributes):
return response
@api_process
async def upload(self, request):
async def upload(self, request: web.Request):
"""Upload a backup file."""
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp_dir:
location: LOCATION_TYPE = None
locations: list[LOCATION_TYPE] | None = None
tmp_path = self.sys_config.path_tmp
if ATTR_LOCATION in request.query:
location_names: list[str] = request.query.getall(ATTR_LOCATION)
self._validate_cloud_backup_location(request, location_names)
# Convert empty string to None if necessary
locations = [
self._location_to_mount(location) if location else None
for location in location_names
]
location = locations.pop(0)
if location and location != LOCATION_CLOUD_BACKUP:
tmp_path = location.local_where
with TemporaryDirectory(dir=tmp_path.as_posix()) as temp_dir:
tar_file = Path(temp_dir, "backup.tar")
reader = await request.multipart()
contents = await reader.next()
@@ -364,7 +480,10 @@ class APIBackups(CoreSysAttributes):
backup.write(chunk)
except OSError as err:
if err.errno == errno.EBADMSG:
if err.errno == errno.EBADMSG and location in {
LOCATION_CLOUD_BACKUP,
None,
}:
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
_LOGGER.error("Can't write new backup file: %s", err)
return False
@@ -372,7 +491,11 @@ class APIBackups(CoreSysAttributes):
except asyncio.CancelledError:
return False
backup = await asyncio.shield(self.sys_backups.import_backup(tar_file))
backup = await asyncio.shield(
self.sys_backups.import_backup(
tar_file, location=location, additional_locations=locations
)
)
if backup:
return {ATTR_SLUG: backup.slug}

View File

@@ -12,6 +12,7 @@ CONTENT_TYPE_X_LOG = "text/x-log"
COOKIE_INGRESS = "ingress_session"
ATTR_ADDITIONAL_LOCATIONS = "additional_locations"
ATTR_AGENT_VERSION = "agent_version"
ATTR_APPARMOR_VERSION = "apparmor_version"
ATTR_ATTRIBUTES = "attributes"
@@ -42,11 +43,11 @@ ATTR_GROUP_IDS = "group_ids"
ATTR_IDENTIFIERS = "identifiers"
ATTR_IS_ACTIVE = "is_active"
ATTR_IS_OWNER = "is_owner"
ATTR_JOB_ID = "job_id"
ATTR_JOBS = "jobs"
ATTR_LLMNR = "llmnr"
ATTR_LLMNR_HOSTNAME = "llmnr_hostname"
ATTR_LOCAL_ONLY = "local_only"
ATTR_LOCATIONS = "locations"
ATTR_MDNS = "mdns"
ATTR_MODEL = "model"
ATTR_MOUNTS = "mounts"
@@ -58,6 +59,7 @@ ATTR_REVISION = "revision"
ATTR_SAFE_MODE = "safe_mode"
ATTR_SEAT = "seat"
ATTR_SIGNED = "signed"
ATTR_SIZE_BYTES = "size_bytes"
ATTR_STARTUP_TIME = "startup_time"
ATTR_STATUS = "status"
ATTR_SUBSYSTEM = "subsystem"
@@ -68,6 +70,7 @@ ATTR_UPDATE_TYPE = "update_type"
ATTR_USAGE = "usage"
ATTR_USE_NTP = "use_ntp"
ATTR_USERS = "users"
ATTR_USER_PATH = "user_path"
ATTR_VENDOR = "vendor"
ATTR_VIRTUALIZATION = "virtualization"

View File

@@ -4,7 +4,7 @@ import asyncio
from contextlib import suppress
import logging
from aiohttp import web
from aiohttp import ClientConnectionResetError, web
from aiohttp.hdrs import ACCEPT, RANGE
import voluptuous as vol
from voluptuous.error import CoerceInvalid
@@ -260,7 +260,10 @@ class APIHost(CoreSysAttributes):
response.headers["X-First-Cursor"] = cursor
await response.prepare(request)
headers_returned = True
await response.write(line.encode("utf-8") + b"\n")
# When client closes the connection while reading busy logs, we
# sometimes get this exception. It should be safe to ignore it.
with suppress(ClientConnectionResetError):
await response.write(line.encode("utf-8") + b"\n")
except ConnectionResetError as ex:
raise APIError(
"Connection reset when trying to fetch data from systemd-journald."

View File

@@ -11,7 +11,7 @@ from ..exceptions import APIError
from ..mounts.const import ATTR_DEFAULT_BACKUP_MOUNT, MountUsage
from ..mounts.mount import Mount
from ..mounts.validate import SCHEMA_MOUNT_CONFIG
from .const import ATTR_MOUNTS
from .const import ATTR_MOUNTS, ATTR_USER_PATH
from .utils import api_process, api_validate
SCHEMA_OPTIONS = vol.Schema(
@@ -32,7 +32,13 @@ class APIMounts(CoreSysAttributes):
if self.sys_mounts.default_backup_mount
else None,
ATTR_MOUNTS: [
mount.to_dict() | {ATTR_STATE: mount.state}
mount.to_dict()
| {
ATTR_STATE: mount.state,
ATTR_USER_PATH: mount.container_where.as_posix()
if mount.container_where
else None,
}
for mount in self.sys_mounts.mounts
],
}

View File

@@ -1 +1 @@
!function(){function n(n){var t=document.createElement("script");t.src=n,document.body.appendChild(t)}if(/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent))n("/api/hassio/app/frontend_es5/entrypoint-5yRSddAJzJ4.js");else try{new Function("import('/api/hassio/app/frontend_latest/entrypoint-qzB1D0O4L9U.js')")()}catch(t){n("/api/hassio/app/frontend_es5/entrypoint-5yRSddAJzJ4.js")}}()
!function(){function d(d){var e=document.createElement("script");e.src=d,document.body.appendChild(e)}if(/Edge?\/(12\d|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(1{2}[5-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(109|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(17\.([2-9]|\d{2,})|(1[89]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(10[4-9]|1[1-9]\d|[2-9]\d{2}|\d{4,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]([6-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](12\d|1[3-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(12\d|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(12\d|1[3-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/(2[4-9]|[3-9]\d|\d{3,})\.\d+|Home As{2}istant\/[\d.]+ \(.+; macOS (1[2-9]|[2-9]\d|\d{3,})\.\d+(\.\d+)?\)/.test(navigator.userAgent))try{new Function("import('/api/hassio/app/frontend_latest/entrypoint.eaJ87jjaoYA.js')")()}catch(e){d("/api/hassio/app/frontend_es5/entrypoint.t1yF5Ic8wyI.js")}else d("/api/hassio/app/frontend_es5/entrypoint.t1yF5Ic8wyI.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,2 +0,0 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[1047],{32594:function(e,t,r){r.d(t,{U:function(){return n}});var n=function(e){return e.stopPropagation()}},75054:function(e,t,r){r.r(t),r.d(t,{HaTimeDuration:function(){return f}});var n,a=r(88962),i=r(33368),o=r(71650),d=r(82390),u=r(69205),l=r(70906),s=r(91808),c=r(68144),v=r(79932),f=(r(47289),(0,s.Z)([(0,v.Mo)("ha-selector-duration")],(function(e,t){var r=function(t){(0,u.Z)(n,t);var r=(0,l.Z)(n);function n(){var t;(0,o.Z)(this,n);for(var a=arguments.length,i=new Array(a),u=0;u<a;u++)i[u]=arguments[u];return t=r.call.apply(r,[this].concat(i)),e((0,d.Z)(t)),t}return(0,i.Z)(n)}(t);return{F:r,d:[{kind:"field",decorators:[(0,v.Cb)({attribute:!1})],key:"hass",value:void 0},{kind:"field",decorators:[(0,v.Cb)({attribute:!1})],key:"selector",value:void 0},{kind:"field",decorators:[(0,v.Cb)({attribute:!1})],key:"value",value:void 0},{kind:"field",decorators:[(0,v.Cb)()],key:"label",value:void 0},{kind:"field",decorators:[(0,v.Cb)()],key:"helper",value:void 0},{kind:"field",decorators:[(0,v.Cb)({type:Boolean})],key:"disabled",value:function(){return!1}},{kind:"field",decorators:[(0,v.Cb)({type:Boolean})],key:"required",value:function(){return!0}},{kind:"method",key:"render",value:function(){var e;return(0,c.dy)(n||(n=(0,a.Z)([' <ha-duration-input .label="','" .helper="','" .data="','" .disabled="','" .required="','" ?enableDay="','"></ha-duration-input> '])),this.label,this.helper,this.value,this.disabled,this.required,null===(e=this.selector.duration)||void 0===e?void 0:e.enable_day)}}]}}),c.oi))}}]);
//# sourceMappingURL=1047-g7fFLS9eP4I.js.map

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[110],{46875:function(e,n,t){t.d(n,{a:function(){return c}});t(82386);var r=t(9883),a=t(213);function c(e,n){var t=(0,a.m)(e.entity_id),c=void 0!==n?n:null==e?void 0:e.state;if(["button","event","input_button","scene"].includes(t))return c!==r.Hh;if((0,r.g0)(c))return!1;if(c===r.KF&&"alert"!==t)return!1;switch(t){case"alarm_control_panel":return"disarmed"!==c;case"alert":return"idle"!==c;case"cover":case"valve":return"closed"!==c;case"device_tracker":case"person":return"not_home"!==c;case"lawn_mower":return["mowing","error"].includes(c);case"lock":return"locked"!==c;case"media_player":return"standby"!==c;case"vacuum":return!["idle","docked","paused"].includes(c);case"plant":return"problem"===c;case"group":return["on","home","open","locked","problem"].includes(c);case"timer":return"active"===c;case"camera":return"streaming"===c}return!0}},94526:function(e,n,t){t.d(n,{Hg:function(){return r},e0:function(){return a}});t(33994),t(22858),t(88871),t(81027),t(82386),t(97741),t(50693),t(72735),t(26098),t(39790),t(66457),t(55228),t(36604),t(16891),"".concat(location.protocol,"//").concat(location.host);var r=function(e){return e.map((function(e){if("string"!==e.type)return e;switch(e.name){case"username":return Object.assign(Object.assign({},e),{},{autocomplete:"username"});case"password":return Object.assign(Object.assign({},e),{},{autocomplete:"current-password"});case"code":return Object.assign(Object.assign({},e),{},{autocomplete:"one-time-code"});default:return e}}))},a=function(e,n){return e.callWS({type:"auth/sign_path",path:n})}},9883:function(e,n,t){t.d(n,{HV:function(){return c},Hh:function(){return a},KF:function(){return u},ON:function(){return o},g0:function(){return l},s7:function(){return s}});var r=t(99890),a="unavailable",c="unknown",o="on",u="off",s=[a,c],i=[a,c,u],l=(0,r.g)(s);(0,r.g)(i)},54630:function(e,n,t){var r=t(72148);e.exports=/Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(r)},36686:function(e,n,t){var r=t(13113),a=t(93187),c=t(53138),o=t(90924),u=t(22669),s=r(o),i=r("".slice),l=Math.ceil,d=function(e){return function(n,t,r){var o,d,f=c(u(n)),p=a(t),m=f.length,g=void 0===r?" ":c(r);return p<=m||""===g?f:((d=s(g,l((o=p-m)/g.length))).length>o&&(d=i(d,0,o)),e?f+d:d+f)}};e.exports={start:d(!1),end:d(!0)}},79977:function(e,n,t){var r=t(41765),a=t(36686).start;r({target:"String",proto:!0,forced:t(54630)},{padStart:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}})}}]);
//# sourceMappingURL=110.N3mhm3V6b1k.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"110.N3mhm3V6b1k.js","mappings":"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","sources":["https://raw.githubusercontent.com/home-assistant/frontend/20241106.0/src/common/entity/state_active.ts","https://raw.githubusercontent.com/home-assistant/frontend/20241106.0/src/data/auth.ts","https://raw.githubusercontent.com/home-assistant/frontend/20241106.0/src/data/entity.ts","/unknown/node_modules/core-js/internals/string-pad-webkit-bug.js","/unknown/node_modules/core-js/internals/string-pad.js","/unknown/node_modules/core-js/modules/es.string.pad-start.js"],"names":["stateActive","stateObj","state","domain","computeDomain","entity_id","compareState","undefined","includes","UNAVAILABLE","isUnavailableState","OFF","concat","location","protocol","host","autocompleteLoginFields","schema","map","field","type","name","Object","assign","autocomplete","getSignedPath","hass","path","callWS","UNKNOWN","ON","UNAVAILABLE_STATES","OFF_STATES","arrayLiteralIncludes","userAgent","module","exports","test","uncurryThis","toLength","toString","$repeat","requireObjectCoercible","repeat","stringSlice","slice","ceil","Math","createMethod","IS_END","$this","maxLength","fillString","fillLen","stringFiller","S","intMaxLength","stringLength","length","fillStr","start","end","$","$padStart","target","proto","forced","padStart","this","arguments"],"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

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,5 @@
/**
* @license
* Copyright 2024 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

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 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[1306],{21306:function(e,t,r){r.r(t),r.d(t,{HaFormGrid:function(){return v}});var a,i,o,n=r(64599),d=r(33994),u=r(22858),s=r(35806),c=r(71008),l=r(62193),h=r(2816),m=r(27927),f=r(35890),p=(r(81027),r(97741),r(16891),r(36185),r(50289)),k=r(29818),v=(0,m.A)([(0,k.EM)("ha-form-grid")],(function(e,t){var r,m=function(t){function r(){var t;(0,c.A)(this,r);for(var a=arguments.length,i=new Array(a),o=0;o<a;o++)i[o]=arguments[o];return t=(0,l.A)(this,r,[].concat(i)),e(t),t}return(0,h.A)(r,t),(0,s.A)(r)}(t);return{F:m,d:[{kind:"field",decorators:[(0,k.MZ)({attribute:!1})],key:"hass",value:void 0},{kind:"field",decorators:[(0,k.MZ)({attribute:!1})],key:"data",value:void 0},{kind:"field",decorators:[(0,k.MZ)({attribute:!1})],key:"schema",value:void 0},{kind:"field",decorators:[(0,k.MZ)({type:Boolean})],key:"disabled",value:function(){return!1}},{kind:"field",decorators:[(0,k.MZ)({attribute:!1})],key:"computeLabel",value:void 0},{kind:"field",decorators:[(0,k.MZ)({attribute:!1})],key:"computeHelper",value:void 0},{kind:"field",decorators:[(0,k.MZ)({attribute:!1})],key:"localizeValue",value:void 0},{kind:"method",key:"focus",value:(r=(0,u.A)((0,d.A)().mark((function e(){var t;return(0,d.A)().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.updateComplete;case 2:null===(t=this.renderRoot.querySelector("ha-form"))||void 0===t||t.focus();case 3:case"end":return e.stop()}}),e,this)}))),function(){return r.apply(this,arguments)})},{kind:"method",key:"updated",value:function(e){(0,f.A)(m,"updated",this,3)([e]),e.has("schema")&&(this.schema.column_min_width?this.style.setProperty("--form-grid-min-width",this.schema.column_min_width):this.style.setProperty("--form-grid-min-width",""))}},{kind:"method",key:"render",value:function(){var e=this;return(0,p.qy)(a||(a=(0,n.A)([" "," "])),this.schema.schema.map((function(t){return(0,p.qy)(i||(i=(0,n.A)([' <ha-form .hass="','" .data="','" .schema="','" .disabled="','" .computeLabel="','" .computeHelper="','" .localizeValue="','"></ha-form> '])),e.hass,e.data,[t],e.disabled,e.computeLabel,e.computeHelper,e.localizeValue)})))}},{kind:"get",static:!0,key:"styles",value:function(){return(0,p.AH)(o||(o=(0,n.A)([":host{display:grid!important;grid-template-columns:repeat(var(--form-grid-column-count,auto-fit),minmax(var(--form-grid-min-width,200px),1fr));grid-column-gap:8px;grid-row-gap:24px}:host>ha-form{display:block}"])))}}]}}),p.WF)}}]);
//# sourceMappingURL=1306.EM6Ds30Fu3A.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"1306.EM6Ds30Fu3A.js","mappings":"iWAaaA,GAAUC,EAAAA,EAAAA,GAAA,EADtBC,EAAAA,EAAAA,IAAc,kBAAe,SAAAC,EAAAC,GAAA,IAmBGC,EAlBpBL,EAAU,SAAAM,GAAA,SAAAN,IAAA,IAAAO,GAAAC,EAAAA,EAAAA,GAAA,KAAAR,GAAA,QAAAS,EAAAC,UAAAC,OAAAC,EAAA,IAAAC,MAAAJ,GAAAK,EAAA,EAAAA,EAAAL,EAAAK,IAAAF,EAAAE,GAAAJ,UAAAI,GAAA,OAAAP,GAAAQ,EAAAA,EAAAA,GAAA,KAAAf,EAAA,GAAAgB,OAAAJ,IAAAT,EAAAI,GAAAA,CAAA,QAAAU,EAAAA,EAAAA,GAAAjB,EAAAM,IAAAY,EAAAA,EAAAA,GAAAlB,EAAA,EAAAI,GAAA,OAAAe,EAAVnB,EAAUoB,EAAA,EAAAC,KAAA,QAAAC,WAAA,EACpBC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,OAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,OAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,SAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAE9BC,EAAAA,EAAAA,IAAS,CAAEI,KAAMC,WAAUH,IAAA,WAAAC,MAAA,kBAAmB,CAAK,IAAAL,KAAA,QAAAC,WAAA,EAEnDC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,eAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAK9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,gBAAAC,WAAA,IAAAL,KAAA,QAAAC,WAAA,EAI9BC,EAAAA,EAAAA,IAAS,CAAEC,WAAW,KAAQC,IAAA,gBAAAC,WAAA,IAAAL,KAAA,SAAAI,IAAA,QAAAC,OAAArB,GAAAwB,EAAAA,EAAAA,IAAAC,EAAAA,EAAAA,KAAAC,MAI/B,SAAAC,IAAA,IAAAC,EAAA,OAAAH,EAAAA,EAAAA,KAAAI,MAAA,SAAAC,GAAA,cAAAA,EAAAC,KAAAD,EAAAE,MAAA,cAAAF,EAAAE,KAAA,EACQC,KAAKC,eAAc,OACe,QAAxCN,EAAAK,KAAKE,WAAWC,cAAc,kBAAU,IAAAR,GAAxCA,EAA0CS,QAAQ,wBAAAP,EAAAQ,OAAA,GAAAX,EAAA,UACnD,WAHiB,OAAA3B,EAAAuC,MAAC,KAADlC,UAAA,KAAAW,KAAA,SAAAI,IAAA,UAAAC,MAKlB,SAAkBmB,IAChBC,EAAAA,EAAAA,GA5BS9C,EAAU,iBA4BnB8C,CA5BmB,CA4BLD,IACVA,EAAaE,IAAI,YACfT,KAAKU,OAAOC,iBACdX,KAAKY,MAAMC,YACT,wBACAb,KAAKU,OAAOC,kBAGdX,KAAKY,MAAMC,YAAY,wBAAyB,IAGtD,GAAC,CAAA9B,KAAA,SAAAI,IAAA,SAAAC,MAED,WAAmC,IAAA0B,EAAA,KACjC,OAAOC,EAAAA,EAAAA,IAAIC,IAAAA,GAAAC,EAAAA,EAAAA,GAAA,YACPjB,KAAKU,OAAOA,OAAOQ,KACnB,SAACC,GAAI,OAAKJ,EAAAA,EAAAA,IAAIK,IAAAA,GAAAH,EAAAA,EAAAA,GAAA,gJAEFH,EAAKO,KACLP,EAAKQ,KACH,CAACH,GACCL,EAAKS,SACDT,EAAKU,aACJV,EAAKW,cACLX,EAAKY,cAAa,IAK7C,GAAC,CAAA3C,KAAA,MAAA4C,QAAA,EAAAxC,IAAA,SAAAC,MAED,WACE,OAAOwC,EAAAA,EAAAA,IAAGC,IAAAA,GAAAZ,EAAAA,EAAAA,GAAA,wNAcZ,IAAC,GA1E6Ba,EAAAA,G","sources":["https://raw.githubusercontent.com/home-assistant/frontend/20241106.0/src/components/ha-form/ha-form-grid.ts"],"names":["HaFormGrid","_decorate","customElement","_initialize","_LitElement","_focus","_LitElement2","_this","_classCallCheck","_len","arguments","length","args","Array","_key","_callSuper","concat","_inherits","_createClass","F","d","kind","decorators","property","attribute","key","value","type","Boolean","_asyncToGenerator","_regeneratorRuntime","mark","_callee","_this$renderRoot$quer","wrap","_context","prev","next","this","updateComplete","renderRoot","querySelector","focus","stop","apply","changedProps","_superPropGet","has","schema","column_min_width","style","setProperty","_this2","html","_templateObject","_taggedTemplateLiteral","map","item","_templateObject2","hass","data","disabled","computeLabel","computeHelper","localizeValue","static","css","_templateObject3","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

View File

@@ -0,0 +1,5 @@
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
!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 +0,0 @@
{"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

View File

@@ -1 +0,0 @@
"use strict";(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[1639],{71639:function(s){s.exports=[]}}]);

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

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