Compare commits

..

43 Commits

Author SHA1 Message Date
dependabot[bot]
c749e21d3f Bump sentry-sdk from 1.8.0 to 1.9.0 (#3759)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.8.0 to 1.9.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.8.0...1.9.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>
2022-08-03 15:44:53 +02:00
Mike Degatano
4f8f28b9f6 addons/info returns info on all addons (#3762)
* Change to legacy routing approach

* Revert launch.json changes
2022-08-03 15:44:18 +02:00
Mike Degatano
2b4f46f6b3 Watchdog shouldn't rebuild addons (#3766)
* Watchdog shouldn't rebuild addons

* pylint fix
2022-08-03 12:06:59 +02:00
dependabot[bot]
5d6e2eeaac Bump actions/setup-python from 4.1.0 to 4.2.0 (#3767)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-03 10:37:51 +02:00
Mike Degatano
a45789c906 Fix keyerror on unnamed containers (#3765) 2022-08-02 15:40:27 -04:00
Mike Degatano
d097044fa8 Update supervisor before auto-updating others (#3756) 2022-07-28 12:29:05 -04:00
dependabot[bot]
73778780ef Bump actions/stale from 5.1.0 to 5.1.1 (#3755)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-28 11:03:33 +02:00
dependabot[bot]
df05c844c0 Bump pyupgrade from 2.37.2 to 2.37.3 (#3753)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.37.2 to 2.37.3.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.37.2...v2.37.3)

---
updated-dependencies:
- dependency-name: pyupgrade
  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>
2022-07-27 17:16:05 +02:00
Mike Degatano
ebeff31bf6 Pass supervisor debug value to audio (#3752) 2022-07-27 17:15:54 +02:00
dependabot[bot]
037e42e894 Bump pyupgrade from 2.34.0 to 2.37.2 (#3751)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.34.0 to 2.37.2.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.34.0...v2.37.2)

---
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>
2022-07-25 15:12:48 +02:00
Mike Degatano
13db0e5c70 Increase max line size for ingress addons (#3747)
* Increase max line size for ingress addons

* Set max field size too
2022-07-25 15:04:27 +02:00
dependabot[bot]
dab75b597c Bump sentry-sdk from 1.7.2 to 1.8.0 (#3749)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-24 21:12:54 +02:00
dependabot[bot]
a1bab8ad08 Bump getsentry/action-release from 1.1.6 to 1.2.0 (#3748)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-21 11:48:20 +02:00
Mike Degatano
48c5dd064c Fix addons always unknown after install (#3746) 2022-07-18 15:11:55 -04:00
dependabot[bot]
fd998155c2 Bump actions/stale from 5.0.0 to 5.1.0 (#3743)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 11:11:31 +02:00
dependabot[bot]
4a3ab4ba8d Bump pylint from 2.14.4 to 2.14.5 (#3745)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 11:06:34 +02:00
dependabot[bot]
c76e7a22df Bump sentry-sdk from 1.7.1 to 1.7.2 (#3744)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 11:04:00 +02:00
Mike Degatano
d19166bb86 Docker events based watchdog and docker healthchecks (#3725)
* Docker events based watchdog

* Separate monitor from DockerAPI since it needs coresys

* Move monitor into dockerAPI

* Fix properties on coresys

* Add watchdog tests

* Added tests

* pylint issue

* Current state failures test

* Thread-safe event processing

* Use labels property
2022-07-15 09:21:59 +02:00
Stefan Agner
14bc771ba9 Fix add-on memory calculation (#3739)
Docker versions newer than 19.03 calculate memory usage sligthly
different compared to previous versions. It seems the field
"total_inactive_file" was not available in 19.03, so it can be used
as indicator.

See: https://docs.docker.com/engine/reference/commandline/stats/#description
2022-07-14 11:59:34 +02:00
dependabot[bot]
8f84eaa096 Bump sentry-sdk from 1.7.0 to 1.7.1 (#3738)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-14 10:25:09 +02:00
dependabot[bot]
2fd51c36b8 Bump actions/cache from 3.0.4 to 3.0.5 (#3734)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-13 08:40:59 +02:00
dependabot[bot]
c473d7ca62 Bump coverage from 6.4.1 to 6.4.2 (#3735)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-13 08:40:24 +02:00
dependabot[bot]
2de5b2f0fb Bump actions/setup-python from 4.0.0 to 4.1.0 (#3731)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-12 08:51:47 +02:00
dependabot[bot]
cf30810677 Bump sentry-sdk from 1.6.0 to 1.7.0 (#3732)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-12 08:43:22 +02:00
Joakim Sørensen
a8dc842f97 Bump frontend to 414db833 (#3729) 2022-07-11 16:53:59 +02:00
dependabot[bot]
38509aa3b8 Bump pre-commit from 2.19.0 to 2.20.0 (#3727)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-11 09:32:52 +02:00
Mike Degatano
9be2b3bced Bump atomicwrites (#3726) 2022-07-09 01:13:19 -04:00
dependabot[bot]
ceed1bc318 Bump debugpy from 1.6.0 to 1.6.2 (#3723)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-08 08:27:05 +02:00
Pascal Vizeli
389aab8d4a Output backup log on error (#3722)
* Output backup log on error

* Apply suggestions from code review

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

Co-authored-by: Mike Degatano <michael.degatano@gmail.com>
2022-07-07 13:20:00 -04:00
Mike Degatano
8b7aa7640c Branch names can contain periods (#3721) 2022-07-07 18:27:32 +02:00
Pascal Vizeli
a5cc3cba63 Docker info more robust (#3720) 2022-07-07 10:01:57 +02:00
dependabot[bot]
9266062709 Bump cryptography from 36.0.2 to 37.0.4 (#3714)
Bumps [cryptography](https://github.com/pyca/cryptography) from 36.0.2 to 37.0.4.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/36.0.2...37.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  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>
2022-07-06 12:12:07 -04:00
Franck Nijhof
bacedd1622 Bump black in pre-commit (#3709) 2022-07-05 11:05:09 +02:00
Franck Nijhof
7227f022b1 Upgrade pytest-asyncio to 0.18.3 and pytest-aiohttp to 1.0.4 (#3711) 2022-06-30 11:05:18 -07:00
dependabot[bot]
0ce91f2e25 Bump awesomeversion from 22.5.2 to 22.6.0 (#3706)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 10:57:39 +02:00
dependabot[bot]
fdb195cf59 Bump sentry-sdk from 1.5.12 to 1.6.0 (#3691)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 10:56:51 +02:00
Franck Nijhof
b85936774a Fix wheels build by pinning wheels action (#3710) 2022-06-30 10:07:39 +02:00
dependabot[bot]
bd106be026 Bump pylint from 2.14.3 to 2.14.4 (#3708)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 09:03:50 +02:00
dependabot[bot]
e588541fe3 Bump black from 22.3.0 to 22.6.0 (#3705)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-28 10:01:02 +02:00
Mike Degatano
d685d8539b Get version info from installed addon (#3702)
* Get version info from installed addon

* addon.slug not self.slug
2022-06-27 22:25:38 +02:00
Mike Degatano
bb3b8891bc AddonStore is_installed needs to check installed (#3701) 2022-06-27 17:46:42 +02:00
Joakim Sørensen
44e4e727cc Use checkonline instead of version for online check (#3700) 2022-06-27 16:29:16 +02:00
dependabot[bot]
acc49579f6 Bump time-machine from 2.7.0 to 2.7.1 (#3699)
Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/adamchainz/time-machine/releases)
- [Changelog](https://github.com/adamchainz/time-machine/blob/main/HISTORY.rst)
- [Commits](https://github.com/adamchainz/time-machine/compare/2.7.0...2.7.1)

---
updated-dependencies:
- dependency-name: time-machine
  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>
2022-06-27 09:42:43 +02:00
188 changed files with 2384 additions and 940 deletions

View File

@@ -91,7 +91,7 @@ jobs:
- name: Build wheels
if: needs.init.outputs.requirements == 'true'
uses: home-assistant/wheels@master
uses: home-assistant/wheels@2022.01.2
with:
tag: ${{ env.WHEELS_TAG }}
arch: ${{ matrix.arch }}
@@ -151,7 +151,7 @@ jobs:
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
if: needs.init.outputs.publish == 'true'
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}

View File

@@ -26,12 +26,12 @@ jobs:
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
with:
python-version: ${{ matrix.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -45,7 +45,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.0.4
uses: actions/cache@v3.0.5
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -66,13 +66,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -110,13 +110,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -128,7 +128,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -154,13 +154,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -186,13 +186,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -204,7 +204,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -227,13 +227,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -245,7 +245,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -271,13 +271,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -303,13 +303,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -321,7 +321,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -347,7 +347,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ matrix.python-version }}
@@ -357,7 +357,7 @@ jobs:
version: ${{ env.DEFAULT_CAS }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |
@@ -405,13 +405,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v4.0.0
uses: actions/setup-python@v4.2.0
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v3.0.4
uses: actions/cache@v3.0.5
with:
path: venv
key: |

View File

@@ -12,7 +12,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.2
- name: Sentry Release
uses: getsentry/action-release@v1.1.6
uses: getsentry/action-release@v1.2.0
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}

View File

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

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: 22.3.0
rev: 22.6.0
hooks:
- id: black
args:

2
pytest.ini Normal file
View File

@@ -0,0 +1,2 @@
[pytest]
asyncio_mode = auto

View File

@@ -1,16 +1,16 @@
aiodns==3.0.0
aiohttp==3.8.1
async_timeout==4.0.2
atomicwrites==1.4.0
atomicwrites-homeassistant==1.4.1
attrs==21.4.0
awesomeversion==22.5.2
awesomeversion==22.6.0
brotli==1.0.9
cchardet==2.1.7
ciso8601==2.2.0
colorlog==6.6.0
cpe==1.2.1
cryptography==36.0.2
debugpy==1.6.0
cryptography==37.0.4
debugpy==1.6.2
deepmerge==1.0.1
dirhash==0.2.1
docker==5.0.3
@@ -20,6 +20,6 @@ pulsectl==22.3.2
pyudev==0.23.2
ruamel.yaml==0.17.17
securetar==2022.2.0
sentry-sdk==1.5.12
sentry-sdk==1.9.0
voluptuous==0.13.1
dbus-next==0.2.3

View File

@@ -1,15 +1,15 @@
black==22.3.0
black==22.6.0
codecov==2.1.12
coverage==6.4.1
coverage==6.4.2
flake8-docstrings==1.6.0
flake8==4.0.1
pre-commit==2.19.0
pre-commit==2.20.0
pydocstyle==6.1.1
pylint==2.14.3
pytest-aiohttp==0.3.0
pytest-asyncio==0.12.0 # NB!: Versions over 0.12.0 breaks pytest-aiohttp (https://github.com/aio-libs/pytest-aiohttp/issues/16)
pylint==2.14.5
pytest-aiohttp==1.0.4
pytest-asyncio==0.18.3
pytest-cov==3.0.0
pytest-timeout==2.1.0
pytest==7.1.2
pyupgrade==2.34.0
time-machine==2.7.0
pyupgrade==2.37.3
time-machine==2.7.1

View File

@@ -167,6 +167,7 @@ class AddonManager(CoreSysAttributes):
self.data.install(store)
addon = Addon(self.coresys, slug)
await addon.load()
if not addon.path_data.is_dir():
_LOGGER.info(

View File

@@ -48,9 +48,12 @@ from ..const import (
AddonBoot,
AddonStartup,
AddonState,
BusEvent,
)
from ..coresys import CoreSys
from ..docker.addon import DockerAddon
from ..docker.const import ContainerState
from ..docker.monitor import DockerContainerStateEvent
from ..docker.stats import DockerStats
from ..exceptions import (
AddonConfigurationError,
@@ -58,7 +61,6 @@ from ..exceptions import (
AddonsNotSupportedError,
ConfigurationFileError,
DockerError,
DockerRequestError,
HostAppArmorError,
)
from ..hardware.data import Device
@@ -66,7 +68,7 @@ from ..homeassistant.const import WSEvent, WSType
from ..utils import check_port
from ..utils.apparmor import adjust_profile
from ..utils.json import read_json_file, write_json_file
from .const import AddonBackupMode
from .const import WATCHDOG_RETRY_SECONDS, AddonBackupMode
from .model import AddonModel, Data
from .options import AddonOptions
from .utils import remove_data
@@ -135,15 +137,16 @@ class Addon(AddonModel):
async def load(self) -> None:
"""Async initialize of object."""
self.sys_bus.register_event(
BusEvent.DOCKER_CONTAINER_STATE_CHANGE, self.container_state_changed
)
self.sys_bus.register_event(
BusEvent.DOCKER_CONTAINER_STATE_CHANGE, self.watchdog_container
)
with suppress(DockerError):
await self.instance.attach(version=self.version)
# Evaluate state
if await self.instance.is_running():
self.state = AddonState.STARTED
else:
self.state = AddonState.STOPPED
@property
def ip_address(self) -> IPv4Address:
"""Return IP of add-on instance."""
@@ -353,6 +356,9 @@ class Addon(AddonModel):
@property
def ingress_panel(self) -> Optional[bool]:
"""Return True if the add-on access support ingress."""
if not self.with_ingress:
return None
return self.persist[ATTR_INGRESS_PANEL]
@ingress_panel.setter
@@ -613,27 +619,17 @@ class Addon(AddonModel):
# Start Add-on
try:
await self.instance.run()
except DockerRequestError as err:
self.state = AddonState.ERROR
raise AddonsError() from err
except DockerError as err:
self.state = AddonState.ERROR
raise AddonsError() from err
else:
self.state = AddonState.STARTED
async def stop(self) -> None:
"""Stop add-on."""
try:
await self.instance.stop()
except DockerRequestError as err:
self.state = AddonState.ERROR
raise AddonsError() from err
except DockerError as err:
self.state = AddonState.ERROR
raise AddonsError() from err
else:
self.state = AddonState.STOPPED
async def restart(self) -> None:
"""Restart add-on."""
@@ -681,16 +677,18 @@ class Addon(AddonModel):
try:
command_return = await self.instance.run_inside(command)
if command_return.exit_code != 0:
_LOGGER.error(
"Pre-/Post backup command returned error code: %s",
command_return.exit_code,
_LOGGER.debug(
"Pre-/Post backup command failed with: %s", command_return.output
)
raise AddonsError(
f"Pre-/Post backup command returned error code: {command_return.exit_code}",
_LOGGER.error,
)
raise AddonsError()
except DockerError as err:
_LOGGER.error(
"Failed running pre-/post backup command %s: %s", command, err
)
raise AddonsError() from err
raise AddonsError(
f"Failed running pre-/post backup command {command}: {str(err)}",
_LOGGER.error,
) from err
async def backup(self, tar_file: tarfile.TarFile) -> None:
"""Backup state of an add-on."""
@@ -884,3 +882,58 @@ class Addon(AddonModel):
Return Coroutine.
"""
return self.instance.check_trust()
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 == ContainerState.RUNNING:
self.state = AddonState.STARTED
elif event.state == ContainerState.STOPPED:
self.state = AddonState.STOPPED
elif event.state == ContainerState.FAILED:
self.state = AddonState.ERROR
async def watchdog_container(self, event: DockerContainerStateEvent) -> None:
"""Process state changes in addon container and restart if necessary."""
if not (event.name == self.instance.name and self.watchdog):
return
if event.state == ContainerState.UNHEALTHY:
while await self.instance.current_state() == event.state:
if not self.in_progress:
_LOGGER.warning(
"Watchdog found addon %s is unhealthy, restarting...", self.name
)
try:
await self.restart()
except AddonsError as err:
_LOGGER.error("Watchdog restart of addon %s failed!", self.name)
self.sys_capture_exception(err)
else:
break
await asyncio.sleep(WATCHDOG_RETRY_SECONDS)
elif event.state == ContainerState.FAILED:
# Ensure failed container is removed before attempting reanimation
with suppress(DockerError):
await self.instance.stop(remove_container=True)
while await self.instance.current_state() == event.state:
if not self.in_progress:
_LOGGER.warning(
"Watchdog found addon %s failed, restarting...", self.name
)
try:
await self.start()
except AddonsError as err:
_LOGGER.error(
"Watchdog reanimation of addon %s failed!", self.name
)
self.sys_capture_exception(err)
else:
break
await asyncio.sleep(WATCHDOG_RETRY_SECONDS)

View File

@@ -11,3 +11,4 @@ class AddonBackupMode(str, Enum):
ATTR_BACKUP = "backup"
ATTR_CODENOTARY = "codenotary"
WATCHDOG_RETRY_SECONDS = 10

View File

@@ -1,10 +1,13 @@
"""Init file for Supervisor RESTful API."""
import logging
from pathlib import Path
from typing import Optional
from typing import Any, Optional
from aiohttp import web
from supervisor.api.utils import api_process
from supervisor.exceptions import APIAddonNotInstalled
from ..coresys import CoreSys, CoreSysAttributes
from .addons import APIAddons
from .audio import APIAudio
@@ -36,6 +39,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
MAX_CLIENT_SIZE: int = 1024**2 * 16
MAX_LINE_SIZE: int = 24570
class RestAPI(CoreSysAttributes):
@@ -51,6 +55,10 @@ class RestAPI(CoreSysAttributes):
self.security.system_validation,
self.security.token_validation,
],
handler_args={
"max_line_size": MAX_LINE_SIZE,
"max_field_size": MAX_LINE_SIZE,
},
)
# service stuff
@@ -378,7 +386,6 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/addons", api_addons.list),
web.get("/addons/{addon}/info", api_addons.info),
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
web.post("/addons/{addon}/start", api_addons.start),
web.post("/addons/{addon}/stop", api_addons.stop),
@@ -396,6 +403,20 @@ class RestAPI(CoreSysAttributes):
]
)
# Legacy routing to support requests for not installed addons
api_store = APIStore()
api_store.coresys = self.coresys
@api_process
async def addons_addon_info(request: web.Request) -> dict[str, Any]:
"""Route to store if info requested for not installed addon."""
try:
return await api_addons.info(request)
except APIAddonNotInstalled:
return await api_store.addons_addon_info(request)
self.webapp.add_routes([web.get("/addons/{addon}/info", addons_addon_info)])
def _register_ingress(self) -> None:
"""Register Ingress functions."""
api_ingress = APIIngress()

View File

@@ -96,7 +96,13 @@ from ..const import (
)
from ..coresys import CoreSysAttributes
from ..docker.stats import DockerStats
from ..exceptions import APIError, APIForbidden, PwnedError, PwnedSecret
from ..exceptions import (
APIAddonNotInstalled,
APIError,
APIForbidden,
PwnedError,
PwnedSecret,
)
from ..validate import docker_ports
from .const import ATTR_SIGNED, CONTENT_TYPE_BINARY
from .utils import api_process, api_process_raw, api_validate, json_loads
@@ -140,7 +146,7 @@ class APIAddons(CoreSysAttributes):
if not addon:
raise APIError(f"Addon {addon_slug} does not exist")
if not isinstance(addon, Addon) or not addon.is_installed:
raise APIError("Addon is not installed")
raise APIAddonNotInstalled("Addon is not installed")
return addon
@@ -177,7 +183,6 @@ class APIAddons(CoreSysAttributes):
"""Reload all add-on data from store."""
await asyncio.shield(self.sys_store.reload())
@api_process
async def info(self, request: web.Request) -> dict[str, Any]:
"""Return add-on information."""
addon: AnyAddon = self._extract_addon(request)

View File

@@ -1,14 +1,14 @@
function loadES5() {
var el = document.createElement('script');
el.src = '/api/hassio/app/frontend_es5/entrypoint.f8f83860.js';
el.src = '/api/hassio/app/frontend_es5/entrypoint.2ca69b3e.js';
document.body.appendChild(el);
}
if (/.*Version\/(?:11|12)(?:\.\d+)*.*Safari\//.test(navigator.userAgent)) {
loadES5();
} else {
try {
new Function("import('/api/hassio/app/frontend_latest/entrypoint.b6cf778b.js')")();
new Function("import('/api/hassio/app/frontend_latest/entrypoint.01671338.js')")();
} catch (err) {
loadES5();
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

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

Binary file not shown.

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

Binary file not shown.

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

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

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
{
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.f8f83860.js"
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.2ca69b3e.js"
}

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

Binary file not shown.

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

View File

@@ -68,5 +68,5 @@
ha-icon-button {
color: var(--secondary-text-color);
}
`]}},{kind:"method",key:"_handleMenuAction",value:function(e){switch(e.detail.index){case 0:this._downloadClicked();break;case 1:this._deleteClicked()}}},{kind:"method",key:"_restoreClicked",value:async function(){const e=this._backupContent.backupDetails();this._restoringBackup=!0,"full"===this._backupContent.backupType?await this._fullRestoreClicked(e):await this._partialRestoreClicked(e),this._restoringBackup=!1}},{kind:"method",key:"_partialRestoreClicked",value:async function(e){var t,i,r,o;void 0===(null===(t=this._dialogParams)||void 0===t?void 0:t.supervisor)||"running"===(null===(i=this._dialogParams)||void 0===i?void 0:i.supervisor.info.state)?await(0,d.g7)(this,{title:"Are you sure you want partially to restore this backup?",confirmText:"restore",dismissText:"cancel"})&&(null!==(r=this._dialogParams)&&void 0!==r&&r.onboarding?((0,s.B)(this,"restoring"),fetch(`/api/hassio/backups/${this._backup.slug}/restore/partial`,{method:"POST",body:JSON.stringify(e)}),this.closeDialog()):this.hass.callApi("POST",`hassio/${(0,f.I)(this.hass.config.version,2021,9)?"backups":"snapshots"}/${this._backup.slug}/restore/partial`,e).then((()=>{this.closeDialog()}),(e=>{this._error=e.body.message}))):await(0,d.Ys)(this,{title:"Could not restore backup",text:`Restoring a backup is not possible right now because the system is in ${null===(o=this._dialogParams)||void 0===o?void 0:o.supervisor.info.state} state.`})}},{kind:"method",key:"_fullRestoreClicked",value:async function(e){var t,i,r,o;void 0===(null===(t=this._dialogParams)||void 0===t?void 0:t.supervisor)||"running"===(null===(i=this._dialogParams)||void 0===i?void 0:i.supervisor.info.state)?await(0,d.g7)(this,{title:"Are you sure you want to wipe your system and restore this backup?",confirmText:"restore",dismissText:"cancel"})&&(null!==(r=this._dialogParams)&&void 0!==r&&r.onboarding?((0,s.B)(this,"restoring"),fetch(`/api/hassio/backups/${this._backup.slug}/restore/full`,{method:"POST",body:JSON.stringify(e)}),this.closeDialog()):this.hass.callApi("POST",`hassio/${(0,f.I)(this.hass.config.version,2021,9)?"backups":"snapshots"}/${this._backup.slug}/restore/full`,e).then((()=>{this.closeDialog()}),(e=>{this._error=e.body.message}))):await(0,d.Ys)(this,{title:"Could not restore backup",text:`Restoring a backup is not possible right now because the system is in ${null===(o=this._dialogParams)||void 0===o?void 0:o.supervisor.info.state} state.`})}},{kind:"method",key:"_deleteClicked",value:async function(){await(0,d.g7)(this,{title:"Are you sure you want to delete this backup?",confirmText:"delete",dismissText:"cancel"})&&this.hass.callApi((0,f.I)(this.hass.config.version,2021,9)?"DELETE":"POST","hassio/"+((0,f.I)(this.hass.config.version,2021,9)?`backups/${this._backup.slug}`:`snapshots/${this._backup.slug}/remove`)).then((()=>{this._dialogParams.onDelete&&this._dialogParams.onDelete(),this.closeDialog()}),(e=>{this._error=e.body.message}))}},{kind:"method",key:"_downloadClicked",value:async function(){let e;try{e=await(0,n.iI)(this.hass,`/api/hassio/${(0,f.I)(this.hass.config.version,2021,9)?"backups":"snapshots"}/${this._backup.slug}/download`)}catch(e){return void await(0,d.Ys)(this,{text:(0,l.js)(e)})}if(window.location.href.includes("ui.nabu.casa")){if(!await(0,d.g7)(this,{title:"Potential slow download",text:"Downloading backups over the Nabu Casa URL will take some time, it is recomended to use your local URL instead, do you want to continue?",confirmText:"continue",dismissText:"cancel"}))return}(0,h.N)(e.path,`home_assistant_backup_${(0,a.l)(this._computeName)}.tar`)}},{kind:"get",key:"_computeName",value:function(){return this._backup?this._backup.name||this._backup.slug:"Unnamed backup"}}]}}),r.oi)}))},3447:(e,t,i)=>{i.d(t,{l:()=>r});const r=(e,t="_")=>{const i="àáäâãåăæąçćčđďèéěėëêęğǵḧìíïîįłḿǹńňñòóöôœøṕŕřßşśšșťțùúüûǘůűūųẃẍÿýźžż·/_,:;",r=`aaaaaaaaacccddeeeeeeegghiiiiilmnnnnooooooprrsssssttuuuuuuuuuwxyyzzz${t}${t}${t}${t}${t}${t}`,o=new RegExp(i.split("").join("|"),"g");return e.toString().toLowerCase().replace(/\s+/g,t).replace(o,(e=>r.charAt(i.indexOf(e)))).replace(/&/g,`${t}and${t}`).replace(/[^\w-]+/g,"").replace(/-/g,t).replace(new RegExp(`(${t})\\1+`,"g"),"$1").replace(new RegExp(`^${t}+`),"").replace(new RegExp(`${t}+$`),"")}},2814:(e,t,i)=>{i.d(t,{iI:()=>r});location.protocol,location.host;const r=(e,t)=>e.callWS({type:"auth/sign_path",path:t})},5936:(e,t,i)=>{i.d(t,{N:()=>r});const r=(e,t="")=>{const i=document.createElement("a");i.target="_blank",i.href=e,i.download=t,document.body.appendChild(i),i.dispatchEvent(new MouseEvent("click")),document.body.removeChild(i)}}}]);
//# sourceMappingURL=1a587b90.js.map
`]}},{kind:"method",key:"_handleMenuAction",value:function(e){switch(e.detail.index){case 0:this._downloadClicked();break;case 1:this._deleteClicked()}}},{kind:"method",key:"_restoreClicked",value:async function(){const e=this._backupContent.backupDetails();this._restoringBackup=!0,"full"===this._backupContent.backupType?await this._fullRestoreClicked(e):await this._partialRestoreClicked(e),this._restoringBackup=!1}},{kind:"method",key:"_partialRestoreClicked",value:async function(e){var t,i,r,o;if(void 0===(null===(t=this._dialogParams)||void 0===t?void 0:t.supervisor)||"running"===(null===(i=this._dialogParams)||void 0===i?void 0:i.supervisor.info.state)){if(await(0,d.g7)(this,{title:"Are you sure you want partially to restore this backup?",confirmText:"restore",dismissText:"cancel"}))if(null!==(r=this._dialogParams)&&void 0!==r&&r.onboarding)(0,s.B)(this,"restoring"),await fetch(`/api/hassio/backups/${this._backup.slug}/restore/partial`,{method:"POST",body:JSON.stringify(e)}),this.closeDialog();else try{await this.hass.callApi("POST",`hassio/${(0,f.I)(this.hass.config.version,2021,9)?"backups":"snapshots"}/${this._backup.slug}/restore/partial`,e),this.closeDialog()}catch(e){this._error=e.body.message}}else await(0,d.Ys)(this,{title:"Could not restore backup",text:`Restoring a backup is not possible right now because the system is in ${null===(o=this._dialogParams)||void 0===o?void 0:o.supervisor.info.state} state.`})}},{kind:"method",key:"_fullRestoreClicked",value:async function(e){var t,i,r,o;void 0===(null===(t=this._dialogParams)||void 0===t?void 0:t.supervisor)||"running"===(null===(i=this._dialogParams)||void 0===i?void 0:i.supervisor.info.state)?await(0,d.g7)(this,{title:"Are you sure you want to wipe your system and restore this backup?",confirmText:"restore",dismissText:"cancel"})&&(null!==(r=this._dialogParams)&&void 0!==r&&r.onboarding?((0,s.B)(this,"restoring"),fetch(`/api/hassio/backups/${this._backup.slug}/restore/full`,{method:"POST",body:JSON.stringify(e)}),this.closeDialog()):this.hass.callApi("POST",`hassio/${(0,f.I)(this.hass.config.version,2021,9)?"backups":"snapshots"}/${this._backup.slug}/restore/full`,e).then((()=>{this.closeDialog()}),(e=>{this._error=e.body.message}))):await(0,d.Ys)(this,{title:"Could not restore backup",text:`Restoring a backup is not possible right now because the system is in ${null===(o=this._dialogParams)||void 0===o?void 0:o.supervisor.info.state} state.`})}},{kind:"method",key:"_deleteClicked",value:async function(){await(0,d.g7)(this,{title:"Are you sure you want to delete this backup?",confirmText:"delete",dismissText:"cancel"})&&this.hass.callApi((0,f.I)(this.hass.config.version,2021,9)?"DELETE":"POST","hassio/"+((0,f.I)(this.hass.config.version,2021,9)?`backups/${this._backup.slug}`:`snapshots/${this._backup.slug}/remove`)).then((()=>{this._dialogParams.onDelete&&this._dialogParams.onDelete(),this.closeDialog()}),(e=>{this._error=e.body.message}))}},{kind:"method",key:"_downloadClicked",value:async function(){let e;try{e=await(0,n.iI)(this.hass,`/api/hassio/${(0,f.I)(this.hass.config.version,2021,9)?"backups":"snapshots"}/${this._backup.slug}/download`)}catch(e){return void await(0,d.Ys)(this,{text:(0,l.js)(e)})}if(window.location.href.includes("ui.nabu.casa")){if(!await(0,d.g7)(this,{title:"Potential slow download",text:"Downloading backups over the Nabu Casa URL will take some time, it is recomended to use your local URL instead, do you want to continue?",confirmText:"continue",dismissText:"cancel"}))return}(0,h.N)(e.path,`home_assistant_backup_${(0,a.l)(this._computeName)}.tar`)}},{kind:"get",key:"_computeName",value:function(){return this._backup?this._backup.name||this._backup.slug:"Unnamed backup"}}]}}),r.oi)}))},3447:(e,t,i)=>{i.d(t,{l:()=>r});const r=(e,t="_")=>{const i="àáäâãåăæąçćčđďèéěėëêęğǵḧìíïîįłḿǹńňñòóöôœøṕŕřßşśšșťțùúüûǘůűūųẃẍÿýźžż·/_,:;",r=`aaaaaaaaacccddeeeeeeegghiiiiilmnnnnooooooprrsssssttuuuuuuuuuwxyyzzz${t}${t}${t}${t}${t}${t}`,o=new RegExp(i.split("").join("|"),"g");return e.toString().toLowerCase().replace(/\s+/g,t).replace(o,(e=>r.charAt(i.indexOf(e)))).replace(/&/g,`${t}and${t}`).replace(/[^\w-]+/g,"").replace(/-/g,t).replace(new RegExp(`(${t})\\1+`,"g"),"$1").replace(new RegExp(`^${t}+`),"").replace(new RegExp(`${t}+$`),"")}},2814:(e,t,i)=>{i.d(t,{iI:()=>r});location.protocol,location.host;const r=(e,t)=>e.callWS({type:"auth/sign_path",path:t})},5936:(e,t,i)=>{i.d(t,{N:()=>r});const r=(e,t="")=>{const i=document.createElement("a");i.target="_blank",i.href=e,i.download=t,document.body.appendChild(i),i.dispatchEvent(new MouseEvent("click")),document.body.removeChild(i)}}}]);
//# sourceMappingURL=8bc74f44.js.map

Binary file not shown.

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

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

View File

@@ -1,3 +1,3 @@
{
"entrypoint.js": "/api/hassio/app/frontend_latest/entrypoint.b6cf778b.js"
"entrypoint.js": "/api/hassio/app/frontend_latest/entrypoint.01671338.js"
}

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