Compare commits

...

249 Commits

Author SHA1 Message Date
Joakim Sørensen
169c7ec004 Update frontend to 419e5644 (#2667) 2021-03-03 16:20:04 +01:00
Joakim Sørensen
202e94615e Update frontend to bee17fce (#2665)
* Update frontend to fe50f422

* revert unrelated change

* Update frontend to bee17fce
2021-03-03 15:15:07 +01:00
Pascal Vizeli
5fe2a815ad Fix error handling with new config handling (#2666) 2021-03-03 12:46:34 +01:00
Joakim Sørensen
a13a0b4770 Guard for missing repository file (#2664)
* Guard for missing repository file

* Update supervisor/store/data.py

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-03-03 11:33:58 +01:00
Joakim Sørensen
455bbc457b Update frontend to 9f73f0ca (#2661)
* Update frontend to 9f73f0ca

* Update frontend to 935d97ce
2021-03-02 17:12:36 +01:00
Joakim Sørensen
d50fd3b580 Add network description to translation files (#2660) 2021-03-02 15:41:00 +01:00
Pascal Vizeli
455e80b07c Merge branch 'main' of https://github.com/home-assistant/supervisor into main 2021-03-02 13:16:09 +00:00
Joakim Sørensen
291becbdf9 Update frontend to 1642c684 (#2657) 2021-03-01 17:19:48 +01:00
Pascal Vizeli
33385b46a7 Fix add-on is not installed anymore (#2656)
* Fix add-on is not installed anymore

* Fix and add tests
2021-03-01 17:19:38 +01:00
Pascal Vizeli
df17668369 Fix add-on is not installed anymore 2021-03-01 15:43:50 +00:00
Joakim Sørensen
43449c85bb Fix translation schema (#2654)
* Fix translation schema

* really fix it

* fix migration path

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-03-01 16:39:00 +01:00
Stefan Agner
9e86eda05a Adjust CPU runtime allocation to support multiple add-ons (#2655)
Adjust realtime CPU runtime allocation to support multiple
add-ons/plug-ins with the runtime flag set.

The cpu.rt_runtime_us allocation is somewhat special as it
allocates the guaranteed runtime. Hence we cannot simply allocate all
time to each add-on.

Unfortunately we cannot distribute the CPU time equally based on the
number of add-ons as we don't know the number of add-ons which will use
realtime ahead of time. Also adjusting at runtime is currenlty not
supported by the Docker Python SDK (the underlying http API does
however, so this would be a possible future improvement).

This solution distributes the total available time of 950ms to up to 5
add-ons/plug-ins in equal slices. On a quad-core system this allows up
to 760ms CPU time in the real-time scheduler per 1s (76% of one CPU)
which should be sufficient for most cases.
2021-03-01 15:29:10 +01:00
Pascal Vizeli
b288554d9c Allow dynamic lookup cgroup rules based on Host udev (#2652) 2021-03-01 14:57:44 +01:00
Joakim Sørensen
bee55d08fb Create FileConfiguration baseclass (#2651) 2021-03-01 12:26:43 +01:00
Joakim Sørensen
7a542aeb38 Add support for loading add-on translation files (#2644)
* Add support for loading add-on translation files

* Fix storing translations for installed add-ons

* Allow YAML, force schema

* Adjust schema
2021-03-01 11:44:24 +01:00
dependabot[bot]
8d42513ba8 Bump gitpython from 3.1.13 to 3.1.14 (#2647)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.13 to 3.1.14.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/master/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.13...3.1.14)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 11:33:41 +01:00
dependabot[bot]
89b7247aa2 Bump home-assistant/builder from 2021.01.1 to 2021.02.0 (#2650)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2021.01.1 to 2021.02.0.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2021.01.1...8c4b820c467894c8374aca262deac0a8aef4982d)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 10:56:10 +01:00
dependabot[bot]
29132e7f4c Bump coverage from 5.4 to 5.5 (#2648)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.4 to 5.5.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.4...coverage-5.5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 10:24:38 +01:00
dependabot[bot]
3fd9baf78e Bump pylint from 2.6.2 to 2.7.2 (#2649)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.6.2 to 2.7.2.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/master/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/pylint-2.6.2...pylint-2.7.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-01 10:17:21 +01:00
Philip Allgaier
f3aa3757ce Fixed typos in resolution notify (#2646) 2021-03-01 09:44:16 +01:00
Joakim Sørensen
3760967f59 Allow use YAML for addon and repository config (#2645)
* Allow use YAML for addon and repository config

* pylint
2021-02-28 20:00:02 +01:00
Joakim Sørensen
f7ab8e0f7f Update frontend to 478a4b25 (#2637) 2021-02-26 15:23:15 +01:00
Joakim Sørensen
0e46ea12b2 Allways store docker and repository config (#2636) 2021-02-26 13:40:47 +01:00
Joakim Sørensen
be226b2b01 Make homeassistant optional in partial snapshot (#2635) 2021-02-26 12:51:04 +01:00
dependabot[bot]
9e1239e192 Bump aiohttp from 3.7.3 to 3.7.4 (#2633)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.7.3 to 3.7.4.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.7.3...v3.7.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-26 09:43:45 +01:00
dependabot[bot]
2eba3d85b0 Bump pulsectl from 20.5.1 to 21.2.0 (#2634)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 20.5.1 to 21.2.0.
- [Release notes](https://github.com/mk-fg/python-pulse-control/releases)
- [Changelog](https://github.com/mk-fg/python-pulse-control/blob/master/CHANGES.rst)
- [Commits](https://github.com/mk-fg/python-pulse-control/commits)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-26 09:42:59 +01:00
Joakim Sørensen
9b569268ab Fix add-on updates (#2632)
* Fix add-on updates

* Add to security role
2021-02-25 23:29:39 +01:00
Pascal Vizeli
31f5033dca Add throttle to job execution (#2631)
* Add throttle to job execution

* fix unittests

* Add tests

* address comments

* add comment

* better on __init__

* New text

* Simplify logic
2021-02-25 23:29:03 +01:00
Pascal Vizeli
78d9c60be5 Log issues/suggestion with info (#2629) 2021-02-25 19:52:19 +01:00
Stefan Agner
baa86f09e5 Real-time fixes (#2630)
* Fix path of cpu.rt_runtime_us sysfs file

Fix detection of CPU bandwidth allocation (CONFIG_RT_GROUP_SCHED) option
by checking the correct file location.

* Set priority limit and memory lock limit

Set a soft limit of real-time priority 90 and hard limit of 99. The
maximum is 99, to avoid add-ons using such a high priority without
second thought set the soft limit to 90. This allows a process to higher
the limit to 99, if really required.

Also set max locked memory to 128MB. Locking memory from getting paged
out is often used for the real-time process/thread to avoid delays due
to swapping/pageing in. Ideally a real-time process should only do the
real-time job, hence not need too much memory.

* Remove check for support_cpu_realtime and set correct limit for audio plug-in
2021-02-25 18:48:08 +01:00
Pascal Vizeli
a4c4b39ba8 Fix k-anonymity handling (#2627) 2021-02-25 18:16:20 +01:00
Joakim Sørensen
752068bb56 Add /store API (#2626) 2021-02-25 16:15:51 +01:00
Pascal Vizeli
739cfbb273 Small cleanups with pwned handling (#2625) 2021-02-25 15:36:02 +01:00
Pascal Vizeli
115af4cadf Optimize resolution checks / add endpoint to trigger it manual (#2622) 2021-02-25 14:05:27 +01:00
Joakim Sørensen
ae3274e559 Add home-assistant version to API response (#2621) 2021-02-25 11:44:22 +01:00
dependabot[bot]
c61f096dbd Bump docker from 4.4.3 to 4.4.4 (#2619)
Bumps [docker](https://github.com/docker/docker-py) from 4.4.3 to 4.4.4.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.4.3...4.4.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-25 10:27:24 +01:00
dependabot[bot]
ee7b5c42fd Bump awesomeversion from 21.2.2 to 21.2.3 (#2620)
Bumps [awesomeversion](https://github.com/ludeeus/awesomeversion) from 21.2.2 to 21.2.3.
- [Release notes](https://github.com/ludeeus/awesomeversion/releases)
- [Commits](https://github.com/ludeeus/awesomeversion/compare/21.2.2...21.2.3)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-25 10:27:05 +01:00
Pascal Vizeli
85d527bfbc Add check for pwned secrets to resolution center (#2614)
* Add check for pwned secrets to resolution center

* restructure check

* add checks

* Add test

* Add test

* reload secrets before check

* simplify

* create notification

* Use own exceptions

* Check on startup

* Apply suggestions from code review

Co-authored-by: Franck Nijhof <git@frenck.dev>

* Add job decorator

* Update supervisor/resolution/notify.py

Co-authored-by: Franck Nijhof <git@frenck.dev>

* Update supervisor/utils/pwned.py

Co-authored-by: Franck Nijhof <git@frenck.dev>

Co-authored-by: Franck Nijhof <git@frenck.dev>
2021-02-25 09:37:45 +01:00
Pascal Vizeli
dd561da819 Fix landingpage on check_api_state (#2615)
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2021-02-24 21:52:18 +01:00
Joakim Sørensen
cb5932cb8b Fix issue with concurrent reads (#2610)
* Fix issue with concurrent reads

* Use lock

* acquire/release

* handle ConnectionError

* No there was not mulitple issues, it's the same code just different syle.....Which is stated on the same page as that image...
2021-02-24 18:36:21 +01:00
Pascal Vizeli
8630adc54a Add execution limit for jobs (#2612)
* Add execution limit for jobs

* Add test for execution police

* Use better test

* Apply suggestions from code review

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* Rename JobExecutionLimit

* fix typing

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2021-02-24 17:15:13 +01:00
Joakim Sørensen
90d8832cd2 Send event when add-on changes state (#2608)
* Send event when add-on changes state

* fix test
2021-02-23 15:12:30 +01:00
Pascal Vizeli
3802b97bb6 Add kernel docs about the device classes (#2607) 2021-02-22 15:10:28 +01:00
Pascal Vizeli
2de175e181 Remove not needed call_soon (#2606) 2021-02-22 14:41:44 +01:00
Joakim Sørensen
6b7d437b00 Signal frontend to refresh on SU startup (#2603)
* Signal frontend to refresh on SU startup

* Use sync variant
2021-02-22 14:31:48 +01:00
Pascal Vizeli
e2faf906de Use the cpu_rt support check also for rtprio (#2605) 2021-02-22 14:02:36 +01:00
Franck Nijhof
bb44ce5cd2 Fix small typo in log message (#2604) 2021-02-22 13:44:12 +01:00
Joakim Sørensen
15544ae589 Show add-on with bad config in log (#2601) 2021-02-22 13:43:03 +01:00
Pascal Vizeli
e421284471 Detect host support for CPU realtime + add an option for enable it (#2602) 2021-02-22 13:30:32 +01:00
Pascal Vizeli
785dc64787 Imrove the LXC detection (#2599) 2021-02-22 11:39:18 +01:00
Joakim Sørensen
7e7e3a7876 Update frontend to ef0bfb23 (#2598) 2021-02-22 11:22:47 +01:00
Pascal Vizeli
2b45c059e0 Support realtime scheduling for add-ons (#2593)
* Support realtime scheduling for add-ons

* support on audio

* address comments from @jens-maus
2021-02-22 11:22:36 +01:00
Joakim Sørensen
14ec61f9bd Update frontend to 2d3cf7d8 (#2594) 2021-02-22 09:41:52 +01:00
Joakim Sørensen
5cc72756f8 Fix some issues with the issue template (#2592) 2021-02-19 23:35:00 +01:00
Franck Nijhof
44785ef3e2 Update GitHub Issue Form template (#2591) 2021-02-19 23:18:23 +01:00
Franck Nijhof
e60d858feb Allow for static port in Watchdog add-on configuration (#2589) 2021-02-19 15:23:17 +01:00
Joakim Sørensen
b31ecfefcd Initial WS support (#2439)
* Initial WS support

* test

* Update frontend to fc7c4af2

* Fix issue with closing states

* log error

* make data optional

* limit stopping states

* Move wrappers to HomeAssistantWebSocket

* use info

* Use call_soon

* Use lookuptable for WS commands

* Fix tests
2021-02-19 11:57:31 +01:00
dependabot[bot]
c342231052 Bump docker from 4.4.2 to 4.4.3 (#2587)
Bumps [docker](https://github.com/docker/docker-py) from 4.4.2 to 4.4.3.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.4.2...4.4.3)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-19 10:09:03 +01:00
dependabot[bot]
673666837e Bump sentry-sdk from 0.20.2 to 0.20.3 (#2588) 2021-02-19 08:59:22 +01:00
dependabot[bot]
c8f74d6c0d Bump actions/stale from v3.0.16 to v3.0.17 (#2586) 2021-02-19 08:42:14 +01:00
Pascal Vizeli
7ed9de8014 Fix device check if not exists (#2585) 2021-02-18 12:39:42 +01:00
Pascal Vizeli
8650947f04 Add capabilities for puleaudio (#2583)
* Add capabilities for puleaudio

* fix import
2021-02-17 17:21:47 +01:00
Pascal Vizeli
a0ac8ced31 Fix handling with full access / blocked devices (#2581)
* Fix handling with full access / blocked devices

* address comment

* Use name

* Add validation warning

* add GPIO check too

* remove warning

* return directly

* fix tests
2021-02-17 15:48:48 +01:00
Joakim Sørensen
2145bbea81 Update frontend to 03d41741 (#2580) 2021-02-17 13:12:37 +01:00
Pascal Vizeli
480000ee7f Fix typo in suggestion (#2578) 2021-02-17 12:49:07 +01:00
dependabot[bot]
9ec2ad022e Bump cryptography from 3.4.5 to 3.4.6 (#2576)
Bumps [cryptography](https://github.com/pyca/cryptography) from 3.4.5 to 3.4.6.
- [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/3.4.5...3.4.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-17 12:01:18 +01:00
dependabot[bot]
43e40816dc Bump pylint from 2.6.0 to 2.6.2 (#2577)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.6.0 to 2.6.2.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/master/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/pylint-2.6.0...pylint-2.6.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-17 12:00:59 +01:00
Pascal Vizeli
941ea3ee68 Fix audio cgroup issue (#2575) 2021-02-16 09:34:15 +01:00
Pascal Vizeli
a6e4b5159e Discovery for vlc telnet (#2573) 2021-02-16 09:31:07 +01:00
dependabot[bot]
6f542d58d5 Bump docker from 4.4.1 to 4.4.2 (#2571)
Bumps [docker](https://github.com/docker/docker-py) from 4.4.1 to 4.4.2.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.4.1...4.4.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 08:41:01 +01:00
dependabot[bot]
b2b5fcee7d Bump sentry-sdk from 0.20.1 to 0.20.2 (#2572)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.20.1 to 0.20.2.
- [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/0.20.1...0.20.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-16 08:40:38 +01:00
Pascal Vizeli
59a82345a9 Drop full privileged from audio plugin (#2570) 2021-02-16 08:40:19 +01:00
Pascal Vizeli
b61a747876 Kernel modules add-on flag need no extra cap (#2569) 2021-02-15 20:42:03 +01:00
dependabot[bot]
72e5d800d5 Bump cryptography from 3.4.4 to 3.4.5 (#2567)
Bumps [cryptography](https://github.com/pyca/cryptography) from 3.4.4 to 3.4.5.
- [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/3.4.4...3.4.5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 10:09:54 +01:00
dependabot[bot]
c7aa6d4804 Bump sentry-sdk from 0.20.0 to 0.20.1 (#2568)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.20.0 to 0.20.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.20.0...0.20.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-15 10:08:58 +01:00
Pascal Vizeli
b31063449d Fix path for tmpfs (#2565) 2021-02-13 20:34:32 +01:00
dependabot[bot]
477672459d Bump sentry-sdk from 0.19.5 to 0.20.0 (#2563)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.19.5 to 0.20.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.19.5...0.20.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-12 15:33:20 +01:00
Pascal Vizeli
9c33897296 Add some issues and suggestion (#2557) 2021-02-11 09:06:46 +01:00
Matheson Steplock
100cfb57c5 Fix Typos in LOGGER (#2552)
Co-authored-by: Franck Nijhof <frenck@frenck.nl>
2021-02-10 21:53:37 +01:00
Pascal Vizeli
40b34071e7 Revert "Mask folder /dev/bus/usb RW (#2555)" (#2556)
This reverts commit 341833fd8f.
2021-02-10 11:35:21 +01:00
Pascal Vizeli
341833fd8f Mask folder /dev/bus/usb RW (#2555) 2021-02-10 10:37:40 +01:00
dependabot[bot]
f647fd6fea Bump cryptography from 3.4.3 to 3.4.4 (#2553)
Bumps [cryptography](https://github.com/pyca/cryptography) from 3.4.3 to 3.4.4.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/3.4.3...3.4.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-10 10:23:42 +01:00
dependabot[bot]
53642f2389 Bump gitpython from 3.1.12 to 3.1.13 (#2554)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.12 to 3.1.13.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/master/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.12...3.1.13)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-10 10:23:06 +01:00
Pascal Vizeli
b9bdd655ab Add hidraw to USB (#2549) 2021-02-09 21:09:57 +01:00
Pascal Vizeli
e9e1b5b54f Add support for hiddev on USB (#2548) 2021-02-09 19:25:16 +01:00
Franck Nijhof
be2163d635 Small tweaks to issue form (#2545) 2021-02-09 17:25:34 +01:00
Franck Nijhof
7f6dde3a5f Fix issue template forms (#2543) 2021-02-09 17:14:44 +01:00
Joakim Sørensen
334aafee23 Update frontend to c7821b9c (#2542) 2021-02-09 13:10:13 +01:00
Pascal Vizeli
1a20c18b19 Use Alpine 3.13 (#2539)
* Use Alpine 3.13

* Update builder.yml
2021-02-09 10:21:14 +01:00
dependabot[bot]
6e655b165c Bump cryptography from 3.3.1 to 3.4.3 (#2537)
* Bump cryptography from 3.3.1 to 3.4.3

Bumps [cryptography](https://github.com/pyca/cryptography) from 3.3.1 to 3.4.3.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/3.3.1...3.4.3)

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

* Update builder.yml

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2021-02-09 10:04:58 +01:00
Pascal Vizeli
d768b2fa1e Fix UI options without filter (#2536) 2021-02-08 21:37:44 +01:00
Joakim Sørensen
85bce1cfba Add core state to /info API (#2531) 2021-02-08 12:39:46 +01:00
Pascal Vizeli
a798a2466f Change Supervisor update flow with AppArmor (#2529) 2021-02-08 10:45:34 +01:00
dependabot[bot]
2a5d8a5c82 Bump actions/stale from v3.0.15 to v3.0.16 (#2527)
Bumps [actions/stale](https://github.com/actions/stale) from v3.0.15 to v3.0.16.
- [Release notes](https://github.com/actions/stale/releases)
- [Commits](https://github.com/actions/stale/compare/v3.0.15...9d6f46564a515a9ea11e7762ab3957ee58ca50da)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-08 09:40:58 +01:00
dependabot[bot]
ea62171d98 Bump pyupgrade from 2.9.0 to 2.10.0 (#2526)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.9.0 to 2.10.0.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.9.0...v2.10.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-08 09:40:46 +01:00
dependabot[bot]
196389d5ee Bump pre-commit from 2.10.0 to 2.10.1 (#2525)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.10.0 to 2.10.1.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.10.0...v2.10.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-08 09:40:33 +01:00
dependabot[bot]
1776021620 Bump actions/cache from v2 to v2.1.4 (#2528)
Bumps [actions/cache](https://github.com/actions/cache) from v2 to v2.1.4.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2...26968a09c0ea4f3e233fdddbafd1166051a095f6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-08 09:39:28 +01:00
Pascal Vizeli
c42a9124d3 Fix cleanup with changed image (#2521) 2021-02-05 16:03:57 +01:00
dependabot[bot]
a44647b4cd Bump awesomeversion from 21.2.0 to 21.2.2 (#2520)
Bumps [awesomeversion](https://github.com/ludeeus/awesomeversion) from 21.2.0 to 21.2.2.
- [Release notes](https://github.com/ludeeus/awesomeversion/releases)
- [Commits](https://github.com/ludeeus/awesomeversion/compare/21.2.0...21.2.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-05 11:31:57 +01:00
Pascal Vizeli
e0c3fd87c5 Add API endpoint for add-on for his own config (#2515)
* Add API endpoint for add-on for his own config

* allow access his config
2021-02-04 16:32:48 +01:00
Pascal Vizeli
ed8f2a85b7 Fix memory stats calc (#2518) 2021-02-04 16:06:12 +01:00
Pascal Vizeli
48f8553c75 Show the current core state on message (#2516) 2021-02-04 15:52:48 +01:00
Joakim Sørensen
af4517fd1e Update frontend to 4273b72d (#2517) 2021-02-04 15:50:07 +01:00
Joakim Sørensen
78e6a46318 Update frontend to e06642e8 (#2513) 2021-02-03 18:00:43 +01:00
Pascal Vizeli
49ca923e51 Apply old udev handling like core container (#2511) 2021-02-03 12:56:25 +01:00
Pascal Vizeli
7ad22e0399 Make add-on file schema more future approved (#2510) 2021-02-03 12:06:22 +01:00
Pascal Vizeli
bb8acc6065 Fix add-on state was not fast reflected (#2509) 2021-02-03 12:02:09 +01:00
Joakim Sørensen
c0fa4a19e9 Change verbosity for hardware.trigger API (#2508) 2021-02-02 20:56:37 +01:00
Franck Nijhof
3f1741dd18 Typo: depircated -> deprecated (#2507) 2021-02-02 20:41:56 +01:00
Stefan Agner
9ef02e4110 Add eMMC life-time estimate support (#2413)
* Add eMMC life-time estimate support

Expose life time estimate as Host Info property "ssd_life_time"

* Fix pytest

* Fix path to helper

* Allow protected access in tests

* Apply suggestions from code review

Rename SSD to disk.

Co-authored-by: Pascal Vizeli <pascal.vizeli@syshack.ch>

* Rename functions as well

* Update host.py

Co-authored-by: Pascal Vizeli <pascal.vizeli@syshack.ch>
2021-02-02 10:31:02 +01:00
Pascal Vizeli
15a6f38ebb Make sure device is ready initialize on udev (#2504)
* Make sure device is ready initialize on udev

* fix style

* let's start with 2sec

* better logic

* style

* add change events back
2021-02-02 09:53:09 +01:00
dependabot[bot]
227f2e5a21 Bump pyupgrade from 2.8.0 to 2.9.0 (#2505)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.8.0 to 2.9.0.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.8.0...v2.9.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-02 09:52:51 +01:00
Pascal Vizeli
517d6ee981 Lookup udev device in monitor thread (#2503) 2021-02-01 18:29:05 +01:00
Pascal Vizeli
184eeb7f49 Udev - move away form depricated callback / increase buffer (#2502)
* Use new callback from udev / only forward

* minimize loop

* Udev - move away form depricated callback / increase buffer

* code cleanup
2021-02-01 17:33:53 +01:00
Joakim Sørensen
a3555c74e8 Bump awesomeversion from 21.1.8 to 21.2.0 (#2501) 2021-02-01 15:45:35 +01:00
Pascal Vizeli
657bafd458 Fix handling with shm and shared /dev (#2499)
* Fix handling with shm and shared /dev

* address commends

* let's share shm
2021-02-01 14:44:02 +01:00
Joakim Sørensen
2ad5df420c Rerun label check on synchronize (#2500) 2021-02-01 14:37:56 +01:00
Joakim Sørensen
b24d489ec5 Update frontend to a9192ae2 (#2498) 2021-02-01 13:26:54 +01:00
Franck Nijhof
6bb0210f1f Fix add-on is_valid check (#2497) 2021-02-01 11:27:34 +01:00
dependabot[bot]
c1de50266a Bump pytz from 2020.5 to 2021.1 (#2496)
Bumps [pytz](https://github.com/stub42/pytz) from 2020.5 to 2021.1.
- [Release notes](https://github.com/stub42/pytz/releases)
- [Commits](https://github.com/stub42/pytz/compare/release_2020.5...release_2021.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-01 11:27:17 +01:00
dependabot[bot]
562e02bc64 Bump pyupgrade from 2.7.4 to 2.8.0 (#2494)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.7.4 to 2.8.0.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.7.4...v2.8.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-01 11:27:04 +01:00
dependabot[bot]
f71ec7913a Bump awesomeversion from 21.1.5 to 21.1.8 (#2493)
Bumps [awesomeversion](https://github.com/ludeeus/awesomeversion) from 21.1.5 to 21.1.8.
- [Release notes](https://github.com/ludeeus/awesomeversion/releases)
- [Commits](https://github.com/ludeeus/awesomeversion/compare/21.1.5...21.1.8)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-01 11:26:51 +01:00
dependabot[bot]
d98baaf660 Bump jinja2 from 2.11.2 to 2.11.3 (#2495)
Bumps [jinja2](https://github.com/pallets/jinja) from 2.11.2 to 2.11.3.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/master/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/2.11.2...2.11.3)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-02-01 11:26:30 +01:00
Pascal Vizeli
72db591576 Validate build env before using it (#2492) 2021-02-01 09:46:48 +01:00
Wouter Schoot
509a37fc04 Typofix exsist -> exist (#2491)
* Typofix exsist -> exist

* Typofix exist -> exists
2021-02-01 09:34:17 +01:00
Pascal Vizeli
17f62b6e86 Handle corrupt store branch / ignore local reset on corruption (#2490)
* Handle corrupt store branch / ignore local reset on corruption

* Update data.py

* Update data.py
2021-01-31 22:55:43 +01:00
Pascal Vizeli
b09aee7644 Filter out virtual vcs devices (#2489)
* Filter out virtual vcs devices

* fix test
2021-01-31 14:40:14 +01:00
Pascal Vizeli
babcc0de0c Cleanup supervisor/udev device action / add GPIO (#2488)
* Cleanup supervisor/udev device action / add GPIO

* Apply francks comment
2021-01-31 14:24:22 +01:00
Franck Nijhof
5cc47c9222 Re-enable old template until form is resolved (#2486) 2021-01-30 19:47:45 +01:00
Franck Nijhof
833559a3b3 Add initial GitHub Issue Form (#2485)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2021-01-30 19:35:15 +01:00
Pascal Vizeli
b8a976b344 Change handling kernel udev events (#2484)
* Change handling kernel udev events / add USB events

* finish USB

* map dev ro

* fix bind
2021-01-30 14:19:53 +01:00
Joakim Sørensen
10b14132b9 Update frontend to 86847263 (#2483) 2021-01-29 18:23:58 +01:00
Pascal Vizeli
18953f0b7c plug & play devices (#2482)
* Add support for plug&play container & full udev passtrhough

* plug & play devices

* this hack is not needed anymore

* Fix GPIO issue

* Apply suggestions from code review

Co-authored-by: Franck Nijhof <git@frenck.dev>

Co-authored-by: Franck Nijhof <git@frenck.dev>
2021-01-29 17:17:41 +01:00
Joakim Sørensen
19f5fba3aa Bump awesomeversion from 21.1.4 to 21.1.5 (#2481) 2021-01-29 14:10:06 +01:00
Pascal Vizeli
636bc3e61a Handle GPIO / VIDEO map with subystem (#2478)
* Handle GPIO / VIDEO mapping with subystem

* fix tests

* add udev support

* init udev data

* fix
2021-01-29 11:28:16 +01:00
Pascal Vizeli
521037e1a6 Fix mknod creating of the device on runtime time (#2477) 2021-01-28 17:07:33 +01:00
Pascal Vizeli
e024c3e38d Improve device selection and show device by id if available (#2476) 2021-01-28 15:43:06 +01:00
Pascal Vizeli
6a0206c1e7 Next generation hardware handling (#2429)
* Next generation hardware handling

* need daemon for some details

* fix tests

* fix wrong coresys lookup

* test initial import

* test device lookup

* validate if device exists

* Add cgroups rules manager

* mapping udev from host

* Modify validation/options handling

* lookup devices

* add support for host udev mapping

* next

* Add policy support to add-ons

* Depricate hardware trigger call

* next cleanup round

* detect USB linking

* optimize

* readd udev utils for backwards compatibility

* fix tests

* Add more tests

* fix tests

* Make device explicit

* Add filter

* work on tests

* Add migration step

* clean out auto_uart

* Fix all tests

* Expose all device information

* small  improvment

* Fix loop over right devices

* Use migration for new device format

* Update rootfs/etc/cont-init.d/udev.sh

Co-authored-by: Franck Nijhof <git@frenck.dev>

* Fix old helper

* Fix API

* add helper for by-id

* fix tests

* Fix serial helper

* Fix hardware API schema

* Hide some virtual devices from tracking

* Apply suggestions from code review

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

* Update supervisor/addons/validate.py

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

* Update supervisor/addons/validate.py

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

* fix lint

* Apply suggestions from code review

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* Apply suggestions from code review

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* fix black

* fix lint

Co-authored-by: Franck Nijhof <git@frenck.dev>
Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2021-01-28 15:26:56 +01:00
Joakim Sørensen
69a8a83528 Limit label check (#2475) 2021-01-28 12:07:42 +01:00
Joakim Sørensen
0307d700fa Add TypeError guard for docker stats (#2474) 2021-01-28 11:58:04 +01:00
Joakim Sørensen
919c383b41 Bump awesomeversion from 21.1.3 to 21.1.4 (#2473) 2021-01-28 11:41:11 +01:00
dependabot[bot]
d331af4d5a Bump pre-commit from 2.9.3 to 2.10.0 (#2472)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.9.3 to 2.10.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.9.3...v2.10.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-28 08:46:29 +01:00
Joakim Sørensen
b5467d3c23 Update frontend to 5ee0250b (#2471) 2021-01-28 08:45:33 +01:00
dependabot[bot]
3ef0040d66 Bump coverage from 5.3.1 to 5.4 (#2470)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.3.1 to 5.4.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.3.1...coverage-5.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-27 08:41:22 +01:00
Joakim Sørensen
ec4dfd2172 Add action to check PR labels (#2469)
* Check PR labels

* update

* update

* update

* only use lable events

* remove env stuff

* add back types
2021-01-26 14:21:05 +01:00
Pascal Vizeli
8f54d7c8e9 New version logic NM (#2466) 2021-01-26 10:33:35 +01:00
dependabot[bot]
b59e709dc0 Bump home-assistant/builder from 2020.11.0 to 2021.01.1 (#2468)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2020.11.0 to 2021.01.1.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2020.11.0...e33ea8af3ad98e9ed7513cad92cc88fb303b42ff)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-26 10:17:50 +01:00
dependabot[bot]
b236e6c886 Bump pytest from 6.2.1 to 6.2.2 (#2467)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.1 to 6.2.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.1...6.2.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-26 09:47:45 +01:00
Pascal Vizeli
8acbb7d6f0 Fix API info calls access (#2464) 2021-01-25 10:45:08 +01:00
dependabot[bot]
49e4bc9381 Bump actions/stale from v3.0.14 to v3.0.15 (#2463)
Bumps [actions/stale](https://github.com/actions/stale) from v3.0.14 to v3.0.15.
- [Release notes](https://github.com/actions/stale/releases)
- [Commits](https://github.com/actions/stale/compare/v3.0.14...86561461b92875de77a8b2d2e75f004c826e8f45)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-25 09:59:20 +01:00
Philip Allgaier
36106cc08d Small README tweaks (#2460) 2021-01-24 21:18:06 +01:00
Pascal Vizeli
8f1763abe2 Fix OSError with custom component check (#2458) 2021-01-24 16:46:49 +01:00
Joakim Sørensen
480eebc6cb Update alert notification (#2457) 2021-01-23 21:06:55 +01:00
Pascal Vizeli
dccfffd979 Improve fixups with Job condition checks (#2451) 2021-01-21 16:48:25 +01:00
dependabot[bot]
1a978f4762 Bump pytest-cov from 2.11.0 to 2.11.1 (#2455)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.11.0 to 2.11.1.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.11.0...v2.11.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-21 09:29:47 +01:00
Pascal Vizeli
1fbc8f4060 Add discovery support for zwave_js (#2454)
* Add discovery support for zwave_js

* New schema

* hmm

* address comments
2021-01-20 16:51:51 +01:00
Pascal Vizeli
db3fc1421c Fix: stable issue with corrupt git repository / submodule (#2452) 2021-01-19 14:21:27 +01:00
dependabot[bot]
9ecd03db0e Bump pytest-cov from 2.10.1 to 2.11.0 (#2446)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.10.1...v2.11.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-18 13:54:22 +01:00
dependabot[bot]
f111ccb1b6 Bump awesomeversion from 21.1.2 to 21.1.3 (#2445)
Bumps [awesomeversion](https://github.com/ludeeus/awesomeversion) from 21.1.2 to 21.1.3.
- [Release notes](https://github.com/ludeeus/awesomeversion/releases)
- [Commits](https://github.com/ludeeus/awesomeversion/compare/21.1.2...21.1.3)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-18 13:54:07 +01:00
Joakim Sørensen
a32341cc5d Update frontend to 08c1b864 (#2444) 2021-01-17 17:54:42 +01:00
Pascal Vizeli
f73e277230 Fix issues with awesomeversion and representation (#2443) 2021-01-17 16:39:34 +01:00
Joakim Sørensen
8d8587ca29 Update wording in notification (#2438)
* Update wording in notification

* Update notify.py
2021-01-15 21:49:52 +01:00
Joakim Sørensen
88eb9511bf Add core version check (#2436)
* Add core version check

* Fix version handling, rename and use correct paths

* simplify check

* wrap approve check
2021-01-15 21:13:42 +01:00
Pascal Vizeli
e1068997ea Fix submodule update (#2434) 2021-01-15 14:28:31 +01:00
dependabot[bot]
560e04c64a Bump colorlog from 4.6.2 to 4.7.2 (#2432)
Bumps [colorlog](https://github.com/borntyping/python-colorlog) from 4.6.2 to 4.7.2.
- [Release notes](https://github.com/borntyping/python-colorlog/releases)
- [Commits](https://github.com/borntyping/python-colorlog/compare/v4.6.2...v4.7.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-15 14:24:40 +01:00
Joakim Sørensen
621ec03971 Ignore wheels on release (#2428)
* Fix wheels on publish

* ignore wheels for publish

* test

* revert test
2021-01-12 15:45:35 +01:00
Pascal Vizeli
d14a47d3f7 Auth: Improve authorisation (#2427) 2021-01-12 14:49:53 +01:00
Pascal Vizeli
3e9de0c210 Fix submodules - check if it is needed or not (#2426) 2021-01-12 13:53:04 +01:00
Joakim Sørensen
01a6e074a5 Adjust development tasks (#2425)
* Adjust development tasks

* add development
2021-01-12 13:50:11 +01:00
Joakim Sørensen
1434077f4e Update frontend panel to edcb7e87 (#2422) 2021-01-11 15:22:10 +01:00
Fredrik Erlandsson
3922175af1 Update git to support updates of submodules (#2378)
* Update git to support updates of submodules

* Remove unnecessary-comprehension

* prefix with **
2021-01-11 15:21:09 +01:00
Franck Nijhof
ec6852a8d7 Set a default for add-on options and schema config (#2421) 2021-01-11 12:36:19 +01:00
Pascal Vizeli
b0b908b4ae Fix missing repository (#2420) 2021-01-11 12:17:53 +01:00
Franck Nijhof
5a00336ef1 Set a default for add-on startup config (#2419) 2021-01-11 12:10:23 +01:00
Stefan Agner
d53f5e21f4 Increases core container timeout to match core shutdown time (#2417)
Align the core container timeout with what the core container
uses as grace period.
2021-01-11 11:24:54 +01:00
Stefan Agner
bd173fa333 Shutdown using systemd-logind if available (#2416)
The Reboot() and PowerOff() methods of the systemd D-Bus API are not
meant to be called directly when logind is in use. Make sure to use the
logind APIs if available.

Since OS release 5.1 systemd-logind is enabled.
2021-01-11 11:21:45 +01:00
Franck Nijhof
6b32fa31b6 Set a default for add-on boot config (#2418) 2021-01-11 11:17:23 +01:00
Joakim Sørensen
d1dba89e39 Add GitHub Action to build wheels (#2186)
* Make GitHub Action to build wheels

* try new

* fix branch

* fix typo

* test arch

* waitfor

* add ref

* fix wait

* fix name

* quote

* add complete step

* Update .github/workflows/wheels.yml

Co-authored-by: Franck Nijhof <git@frenck.dev>

* fix typo

* use name

* test

* merge them

* move

* test with requirement change

* add wheels-user

* revert version change

* use master

* bump awesomeversion

* set user

Co-authored-by: Franck Nijhof <git@frenck.dev>
2021-01-08 18:57:35 +01:00
dependabot[bot]
b2f2806465 Bump gitpython from 3.1.11 to 3.1.12 (#2404)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.11 to 3.1.12.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/master/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.11...3.1.12)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-07 21:03:01 +01:00
Sergio Oller
3b70cd58a3 Allow GET method on /auth with BasicAuth (#2407)
* Allow GET on /auth with BasicAuth

* Accept GET without further validation

As suggested on https://github.com/home-assistant/supervisor/pull/2407#pullrequestreview-563712080
2021-01-07 21:02:36 +01:00
Joakim Sørensen
6769bfd824 Fix typo in reference (#2409) 2021-01-07 19:05:31 +01:00
dependabot[bot]
bff4af2534 Bump codecov/codecov-action from v1.2.0 to v1.2.1 (#2405)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.2.0 to v1.2.1.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1.2.0...e156083f13aff6830c92fc5faa23505779fbf649)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-06 14:04:37 +01:00
dependabot[bot]
aabf575ac5 Bump actions/upload-artifact from v2.2.1 to v2.2.2 (#2400)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from v2.2.1 to v2.2.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2.2.1...e448a9b857ee2131e752b06002bf0e093c65e571)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-05 09:50:24 +01:00
dependabot[bot]
4aacaf6bd6 Bump codecov/codecov-action from v1.1.1 to v1.2.0 (#2401)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.1.1 to v1.2.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1.1.1...a92c414703a4bba586f6df7fcc885c9d0bdff772)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-05 09:49:32 +01:00
dependabot[bot]
268070e89c Bump dessant/lock-threads from v2.0.1 to v2.0.3 (#2398)
Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from v2.0.1 to v2.0.3.
- [Release notes](https://github.com/dessant/lock-threads/releases)
- [Changelog](https://github.com/dessant/lock-threads/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dessant/lock-threads/compare/v2.0.1...486f7380c15596f92b724e4260e4981c68d6bde6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-04 09:37:26 +01:00
Joakim Sørensen
4fa2134cc6 Bump awesomeversion from 20.12.4 to 20.12.5 (#2394) 2021-01-02 22:13:35 +01:00
Pascal Vizeli
97c35de49a Refacture version handling with AwesomeVersion (#2392)
* Refacture version handling with AwesomeVersion

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* next

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* next

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* next

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* v20.12.3

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* next

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* next

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* fix exception

* fix schema

* cleanup plugins

* fix tests

* fix attach

* fix TypeError

* fix issue with compairing

* make lint happy

* Update supervisor/homeassistant/__init__.py

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* Update tests/test_validate.py

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* Update supervisor/docker/__init__.py

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

* Update supervisor/supervisor.py

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2020-12-31 17:09:33 +01:00
Joakim Sørensen
32fb550969 Bump docker to 4.4.1 (#2390) 2020-12-29 16:38:20 +01:00
dependabot[bot]
3457441929 Bump pytz from 2020.4 to 2020.5 (#2386)
Bumps [pytz](https://github.com/stub42/pytz) from 2020.4 to 2020.5.
- [Release notes](https://github.com/stub42/pytz/releases)
- [Commits](https://github.com/stub42/pytz/compare/release_2020.4...release_2020.5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-28 16:26:50 +01:00
dependabot[bot]
32f0fc7a46 Bump codecov/codecov-action from v1.1.0 to v1.1.1 (#2381)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.1.0 to v1.1.1.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1.1.0...1fc7722ded4708880a5aea49f2bfafb9336f0c8d)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-22 13:27:04 +01:00
dependabot[bot]
c891a8f164 Bump coverage from 5.3 to 5.3.1 (#2379)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.3 to 5.3.1.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.3...coverage-5.3.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-21 15:18:02 +01:00
dependabot[bot]
991764af94 Bump actions/setup-python from v2.2.0 to v2.2.1 (#2380)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from v2.2.0 to v2.2.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2.2.0...3105fb18c05ddd93efea5f9e0bef7a03a6e9e7df)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-21 15:17:25 +01:00
dependabot[bot]
1df447272e Bump codecov/codecov-action from v1.0.15 to v1.1.0 (#2375)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.0.15 to v1.1.0.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1.0.15...7de43a7373de21874ae196a78f8eb633fcf7f0c4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-18 21:42:42 +01:00
dependabot[bot]
f032ae757b Bump actions/setup-python from v2.1.4 to v2.2.0 (#2376)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from v2.1.4 to v2.2.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2.1.4...8c5ea631b2b2d5d8840cf4a2b183a8a0edc1e40d)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-18 21:42:10 +01:00
dependabot[bot]
e529b2859e Bump codecov from 2.1.10 to 2.1.11 (#2377)
Bumps [codecov](https://github.com/codecov/codecov-python) from 2.1.10 to 2.1.11.
- [Release notes](https://github.com/codecov/codecov-python/releases)
- [Changelog](https://github.com/codecov/codecov-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-python/compare/v2.1.10...v2.1.11)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-18 21:40:42 +01:00
Casper
d1cb2368fa fix typo (#2372) 2020-12-16 10:13:20 +01:00
dependabot[bot]
7b812184d1 Bump pytest from 6.2.0 to 6.2.1 (#2373)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.0...6.2.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-16 10:12:57 +01:00
dependabot[bot]
4f7ce1c6ee Bump cryptography from 3.2.1 to 3.3.1 (#2360)
Bumps [cryptography](https://github.com/pyca/cryptography) from 3.2.1 to 3.3.1.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/3.2.1...3.3.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 12:52:47 +01:00
dependabot[bot]
44a5ac63db Bump pytest from 6.1.2 to 6.2.0 (#2365)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.1.2 to 6.2.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.1.2...6.2.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 12:52:22 +01:00
Joakim Sørensen
0989ee88cc Pin docker-py to commit (#2371)
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-12-15 12:48:50 +01:00
dependabot[bot]
ba8b72c2c8 Bump sentry-sdk from 0.19.4 to 0.19.5 (#2362)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 0.19.4 to 0.19.5.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGES.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/0.19.4...0.19.5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 12:28:11 +01:00
dependabot[bot]
2dbb4583f4 Bump debugpy from 1.2.0 to 1.2.1 (#2370)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.2.0...v1.2.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-15 12:26:45 +01:00
Robin
81ad42e029 Fix typo in log message when completing snapshot (#2367) 2020-12-15 10:49:40 +01:00
dependabot[bot]
5d3695f8ba Bump pre-commit from 2.9.2 to 2.9.3 (#2356)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.9.2 to 2.9.3.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.9.2...v2.9.3)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-08 08:35:18 +01:00
Pascal Vizeli
c771694aa0 Show link for help user with unsupported systems (#2354)
* Show link for help user with unsupported systems

* Update .github/ISSUE_TEMPLATE/config.yml

Co-authored-by: Franck Nijhof <git@frenck.dev>

Co-authored-by: Franck Nijhof <git@frenck.dev>
2020-12-07 11:45:46 +01:00
Pascal Vizeli
1ac0fd4c10 Add note for unsupported system (#2353) 2020-12-07 11:00:27 +01:00
dependabot[bot]
631ff8caef Bump voluptuous from 0.12.0 to 0.12.1 (#2352)
Bumps [voluptuous](https://github.com/alecthomas/voluptuous) from 0.12.0 to 0.12.1.
- [Release notes](https://github.com/alecthomas/voluptuous/releases)
- [Changelog](https://github.com/alecthomas/voluptuous/blob/master/CHANGELOG.md)
- [Commits](https://github.com/alecthomas/voluptuous/compare/0.12.0...0.12.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-07 10:39:49 +01:00
Joakim Sørensen
7382182132 Add changes to release drafter (#2349)
* Add changes to release drafter

* remove duplicate

* Add more labels

* add CI

* remove enhacement
2020-12-06 13:24:09 +01:00
Joakim Sørensen
4ff9da68ef Actually use the vlan_struct (#2347) 2020-12-05 13:04:37 +01:00
Pascal Vizeli
dee2998ee3 Fix issue with mark system wrong as rollback (#2345) 2020-12-05 11:19:27 +01:00
Pascal Vizeli
1d43236211 Upgrade json config handler logging to critical (#2344) 2020-12-05 10:57:20 +01:00
Pascal Vizeli
792bc610a3 Fix NM byte switch for ipv6 nameserver (#2342)
* Fix NM byte switch for ipv6 nameserver

* remove not needed code
2020-12-04 17:55:26 +01:00
Pascal Vizeli
7a51c828c2 Fix wrong exception handler 2020-12-04 15:26:13 +00:00
Pascal Vizeli
fab6fcd5ac Check NetworkManager Version if it is supported (#2340)
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2020-12-04 12:38:12 +01:00
Joakim Sørensen
c8e00ba160 Adds vlan_struct (#2337)
* Return VLAN ID instead of wifistruct for VLAN

* Use vlan_struct

* fix typing

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-12-04 11:37:55 +01:00
Joakim Sørensen
6245b6d823 Fix KeyError in connectivity_enabled (#2336) 2020-12-03 21:40:34 +01:00
Pascal Vizeli
0c55bf20fc Fix issue on store git clone (#2331) 2020-12-03 21:06:48 +01:00
Pascal Vizeli
f8fd7b5933 Improve error handling with job condition (#2322)
* Improve error handling with job condition

* fix

* first patch

* last patch

* Address comments

* Revert strange replace
2020-12-03 12:24:32 +01:00
Pascal Vizeli
6462eea2ef Fix sentry stdlib spam (#2326) 2020-12-02 17:24:40 +01:00
Pascal Vizeli
3d79891249 Make dbus connection more robust (#2325)
* Make dbus connection more robust

* move rauc down
2020-12-02 17:22:28 +01:00
Pascal Vizeli
80763c4bbf Support OTA url over version files (#2324)
* Support OTA url over version files

* Fix new schema
2020-12-02 14:59:42 +01:00
Pascal Vizeli
59102afd45 Fix sentry with sets (#2323) 2020-12-02 12:43:38 +01:00
Pascal Vizeli
0b085354db Send list of images to sentry (#2321) 2020-12-01 14:29:37 +01:00
Pascal Vizeli
e2a473baa3 Add network reload to api (#2319) 2020-12-01 14:03:59 +01:00
Pascal Vizeli
06e10fdd3c Fix NM naming schema (#2318)
* Fix NM naming schema

* Address comments

* Add test
2020-12-01 12:11:20 +01:00
Pascal Vizeli
fb4386a7ad Use persistent MAC address instead clone / don't touch default (#2317) 2020-12-01 09:27:49 +01:00
Pascal Vizeli
2d294f6841 Make evaluation of container better (#2316) 2020-11-30 18:00:12 +01:00
Pascal Vizeli
e09a839148 Fix byte order for network DNS settings (#2315) 2020-11-30 15:22:02 +01:00
Pascal Vizeli
d9c4dae739 Send error to sentry from update 2020-11-30 10:28:05 +00:00
Pascal Vizeli
49853e92a4 Fix sentry spam (#2313) 2020-11-30 11:01:10 +01:00
Pascal Vizeli
19620d6808 Fix: cleanup repository from list (#2310)
* Fix: cleanup repository from list

* Add repr

* Avoid not exists error message
2020-11-29 14:00:29 +01:00
Pascal Vizeli
f6bf44de1c Add tests for remove function (#2309) 2020-11-29 12:34:33 +01:00
Pascal Vizeli
06fae59fc8 Remove corrupt FS on store sentry report (#2308) 2020-11-28 18:11:56 +01:00
Pascal Vizeli
5c25fcd84c Reset on invalid filesystem (#2307) 2020-11-28 15:57:00 +01:00
Pascal Vizeli
aa5297026f Handle Store suggestion (#2306)
* Handle Store suggestion

* Add fixup

* Add more fixup & list

* Enable fixups

* Add tests

* fix index

* fix break

* fix import

* Load it anyway

* Run suFix ccestion on load too

* fix error message

* fix error message

* Fix remove

* Finishing

* Add tests

* Fix error

* fix cleanup stale stuff

* Fix source

* use source as url

* add test for url

* Apply suggestions from code review

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2020-11-28 15:03:44 +01:00
Joakim Sørensen
841520b75e Strip device names (#2303) 2020-11-26 22:40:54 +01:00
Pascal Vizeli
d9e20307de Allow check to cleanup issues (#2302) 2020-11-26 22:38:33 +01:00
Pascal Vizeli
fda1b523ba Extend resolution center (#2297)
* Extend resolution center

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* move forward

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* Rename it to fixups

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* Finish p1

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* Finish p1 - add files

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>

* Finishup

* Add more tests

* Add test for suggestion

* Add more tests

* fix tests & isort

* address comments

* address comments v2

* fix isort

* Change reference handling
2020-11-26 17:16:36 +01:00
dependabot[bot]
7cccbc682c Bump pre-commit from 2.9.0 to 2.9.2 (#2300)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.9.0 to 2.9.2.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.9.0...v2.9.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-11-26 08:30:35 +01:00
Pascal Vizeli
621eb4c4c0 Don't send DBusProgramError to sentry (#2294)
* Don't send DBusProgramError to sentry

* Add message
2020-11-24 14:18:00 +01:00
Pascal Vizeli
056926242f Fix sentry resoluton messages (#2295) 2020-11-24 14:17:47 +01:00
Pascal Vizeli
84294f286f Add unhealthy if update fails on startup 2020-11-24 12:51:16 +00:00
Joakim Sørensen
b6bc6b8498 Update frontend panel to 1d367eca (#2293) 2020-11-24 11:56:35 +01:00
Pascal Vizeli
845c935b39 Add JobManager API ignore (#2290)
* Disable job condition for unhealth & unsupported systems

* Add JobManager API ignore

* Apply suggestions from code review

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* Update tests/resolution/evaluation/test_evaluate_job_conditions.py

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>

* fix names

* address comments

* Update decorator.py

* adjust security

* add reset

* Apply suggestions from code review

Co-authored-by: Joakim Sørensen <joasoe@gmail.com>

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2020-11-24 10:54:57 +01:00
dependabot[bot]
19d8de89df Bump docker from 4.3.1 to 4.4.0 (#2292)
Bumps [docker](https://github.com/docker/docker-py) from 4.3.1 to 4.4.0.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.3.1...4.4.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-11-24 08:49:22 +01:00
Joakim Sørensen
cfae20a3ec Change snapshot create conditions (#2289) 2020-11-23 22:57:41 +01:00
Joakim Sørensen
6db6ab96e6 Update frontend panel to 0ef88816 (#2291) 2020-11-23 22:57:11 +01:00
dependabot[bot]
48695c6805 Bump actions/stale from v3.0.13 to v3.0.14 (#2286)
Bumps [actions/stale](https://github.com/actions/stale) from v3.0.13 to v3.0.14.
- [Release notes](https://github.com/actions/stale/releases)
- [Commits](https://github.com/actions/stale/compare/v3.0.13...87c2b794b9b47a9bec68ae03c01aeb572ffebdb1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-11-23 09:36:20 +01:00
dependabot[bot]
d74908e3b5 Bump pre-commit from 2.8.2 to 2.9.0 (#2287)
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.8.2 to 2.9.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.8.2...v2.9.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-11-23 09:30:41 +01:00
429 changed files with 15141 additions and 8880 deletions

View File

@@ -2,6 +2,11 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.8
WORKDIR /workspaces
# Set Docker daemon config
RUN \
mkdir -p /etc/docker \
&& echo '{"storage-driver": "vfs"}' > /etc/docker/daemon.json
# Install Node/Yarn for Frontent
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \

View File

@@ -5,6 +5,7 @@
"appPort": "9123:8123",
"postCreateCommand": "pre-commit install",
"runArgs": ["-e", "GIT_EDITOR=code --wait", "--privileged"],
"containerEnv": {"NVM_DIR":"/usr/local/share/nvm"},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",

View File

@@ -1,5 +1,5 @@
---
name: Report a bug with the Supervisor
name: Report a bug with the Supervisor on a supported System
about: Report an issue related to the Home Assistant Supervisor.
labels: bug
---
@@ -11,6 +11,10 @@ labels: bug
- If you have a problem with an add-on, make an issue in it's repository.
-->
<!--
Important: You can only fill a bug repport for an supported system! If you run an unsupported installation. This report would be closed without comment.
-->
### Describe the issue
<!-- Provide as many details as possible. -->
@@ -47,3 +51,19 @@ Paste supervisor logs here
```
</details>
### System Information
<details>
<summary>System Information</summary>
<!--
- Use this command: ha info
-->
```
Paste system info here
```
</details>

106
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: Bug Report Form
about: Report an issue related to the Home Assistant Supervisor.
labels: bug
title: ""
issue_body: true
body:
- type: markdown
attributes:
value: |
This issue form is for reporting bugs with **supported** setups only!
If you have a feature or enhancement request, please use the [feature request][fr] section of our [Community Forum][fr].
[fr]: https://community.home-assistant.io/c/feature-requests
- type: textarea
validations:
required: true
attributes:
label: Describe the issue you are experiencing
description: Provide a clear and concise description of what the bug is.
- type: markdown
attributes:
value: |
## Environment
- type: input
validations:
required: true
attributes:
label: What is the used version of the Supervisor?
placeholder: supervisor-
description: >
Can be found in the Supervisor panel -> System tab. Starts with
`supervisor-....`.
- type: dropdown
validations:
required: true
attributes:
label: What type of installation are you running?
description: >
If you don't know, you can find it in: Configuration panel -> Info.
options:
- Home Assistant OS
- Home Assistant Supervised
- type: dropdown
validations:
required: true
attributes:
label: Which operating system are you running on?
options:
- Home Assistant Operating System
- Debian
- Other (e.g., Raspbian/Raspberry Pi OS/Fedora)
- type: input
validations:
required: true
attributes:
label: What is the version of your installed operating system?
placeholder: "5.11"
description: Can be found in the Supervisor panel -> System tab.
- type: input
validations:
required: true
attributes:
label: What version of Home Assistant Core is installed?
placeholder: core-
description: >
Can be found in the Supervisor panel -> System tab. Starts with
`core-....`.
- type: markdown
attributes:
value: |
# Details
- type: textarea
validations:
required: true
attributes:
label: Steps to reproduce the issue
description: |
Please tell us exactly how to reproduce your issue.
Provide clear and concise step by step instructions and add code snippets if needed.
value: |
1.
2.
3.
...
- type: textarea
validations:
required: true
attributes:
label: Anything in the Supervisor logs that might be useful for us?
description: >
The Supervisor logs can be found in the Supervisor panel -> System tab.
value: |
```txt
# Put your logs below this line
```
- type: markdown
attributes:
value: |
## Additional information
- type: markdown
attributes:
value: |
If you have any additional information for us, use the field below.
Please note, you can attach screenshots or screen recordings here.

View File

@@ -1,5 +1,9 @@
blank_issues_enabled: false
contact_links:
- name: Report a bug/issues with an unsupported Supervisor
url: https://community.home-assistant.io
about: The Community guide can help or was updated to solve your issue
- name: Report a bug for the Supervisor panel
url: https://github.com/home-assistant/frontend/issues
about: The Supervisor panel is a part of the Home Assistant frontend

View File

@@ -1,4 +1,49 @@
change-template: "- #$NUMBER $TITLE @$AUTHOR"
sort-direction: ascending
categories:
- title: ":boom: Breaking Changes"
label: "breaking-change"
- title: ":wrench: Build"
label: "build"
- title: ":boar: Chore"
label: "chore"
- title: ":sparkles: New Features"
label: "new-feature"
- title: ":zap: Performance"
label: "performance"
- title: ":recycle: Refactor"
label: "refactor"
- title: ":green_heart: CI"
label: "ci"
- title: ":bug: Bug Fixes"
label: "bugfix"
- title: ":white_check_mark: Test"
label: "test"
- title: ":arrow_up: Dependency Updates"
label: "dependencies"
include-labels:
- "breaking-change"
- "build"
- "chore"
- "performance"
- "refactor"
- "new-feature"
- "bugfix"
- "dependencies"
- "test"
- "ci"
template: |
## What's Changed
$CHANGES

View File

@@ -35,6 +35,7 @@ on:
env:
BUILD_NAME: supervisor
BUILD_TYPE: supervisor
WHEELS_TAG: 3.8-alpine3.13
jobs:
init:
@@ -45,6 +46,7 @@ jobs:
version: ${{ steps.version.outputs.version }}
channel: ${{ steps.version.outputs.channel }}
publish: ${{ steps.version.outputs.publish }}
requirements: ${{ steps.requirements.outputs.changed }}
steps:
- name: Checkout the repository
uses: actions/checkout@v2
@@ -61,6 +63,18 @@ jobs:
with:
type: ${{ env.BUILD_TYPE }}
- name: Get changed files
id: changed_files
if: steps.version.outputs.publish == 'false'
uses: jitterbit/get-changed-files@v1
- name: Check if requirements files changed
id: requirements
run: |
if [[ "${{ steps.changed_files.outputs.all }}" =~ requirements.txt ]]; then
echo "::set-output name=changed::true"
fi
build:
name: Build ${{ matrix.arch }} supervisor
needs: init
@@ -74,6 +88,19 @@ jobs:
with:
fetch-depth: 0
- name: Build wheels
if: needs.init.outputs.requirements == 'true'
uses: home-assistant/wheels@master
with:
tag: ${{ env.WHEELS_TAG }}
arch: ${{ matrix.arch }}
wheels-host: ${{ secrets.WHEELS_HOST }}
wheels-key: ${{ secrets.WHEELS_KEY }}
wheels-user: wheels
apk: "build-base;libffi-dev;openssl-dev;cargo"
skip-binary: aiohttp
requirements: "requirements.txt"
- name: Set version
if: needs.init.outputs.publish == 'true'
uses: home-assistant/actions/helpers/version@master
@@ -92,7 +119,7 @@ jobs:
run: echo "BUILD_ARGS=--test" >> $GITHUB_ENV
- name: Build supervisor
uses: home-assistant/builder@2020.11.0
uses: home-assistant/builder@2021.02.0
with:
args: |
$BUILD_ARGS \
@@ -134,7 +161,7 @@ jobs:
uses: actions/checkout@v2
- name: Build the Supervisor
uses: home-assistant/builder@2020.11.0
uses: home-assistant/builder@2021.02.0
with:
args: |
--test \

19
.github/workflows/check_pr_labels.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Check PR
on:
pull_request:
branches: ["main"]
types: [labeled, unlabeled, synchronize]
jobs:
init:
name: Check labels
runs-on: ubuntu-latest
steps:
- name: Check labels
run: |
labels=$(jq -r '.pull_request.labels[] | .name' ${{github.event_path }})
echo "$labels"
if [ "$labels" == "cla-signed" ]; then
exit 1
fi

View File

@@ -25,12 +25,12 @@ jobs:
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
with:
python-version: ${{ matrix.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
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@v2
uses: actions/cache@v2.1.4
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -68,13 +68,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -112,13 +112,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -130,7 +130,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -156,13 +156,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -188,13 +188,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -206,7 +206,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -229,13 +229,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -247,7 +247,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -273,13 +273,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -305,13 +305,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -323,7 +323,7 @@ jobs:
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
@@ -349,13 +349,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ matrix.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -390,7 +390,7 @@ jobs:
-o console_output_style=count \
tests
- name: Upload coverage artifact
uses: actions/upload-artifact@v2.2.1
uses: actions/upload-artifact@v2.2.2
with:
name: coverage-${{ matrix.python-version }}
path: .coverage
@@ -403,13 +403,13 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.4
uses: actions/setup-python@v2.2.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
uses: actions/cache@v2.1.4
with:
path: venv
key: |
@@ -428,4 +428,4 @@ jobs:
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1.0.15
uses: codecov/codecov-action@v1.2.1

View File

@@ -9,7 +9,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v2.0.1
- uses: dessant/lock-threads@v2.0.3
with:
github-token: ${{ github.token }}
issue-lock-inactive-days: "30"

View File

@@ -2,14 +2,43 @@ name: Release Drafter
on:
push:
# branches to consider in the event; optional, defaults to all
branches:
- main
jobs:
update_release_draft:
runs-on: ubuntu-latest
name: Release Drafter
steps:
- uses: release-drafter/release-drafter@v5
- name: Checkout the repository
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Find Next Version
id: version
run: |
declare -i newpost
latest=$(git describe --tags $(git rev-list --tags --max-count=1))
latestpre=$(echo "$latest" | awk '{split($0,a,"."); print a[1] "." a[2]}')
datepre=$(date --utc '+%Y.%m')
if [[ "$latestpre" == "$datepre" ]]; then
latestpost=$(echo "$latest" | awk '{split($0,a,"."); print a[3]}')
newpost=$latestpost+1
else
newpost=0
fi
echo Current version: $latest
echo New target version: $datepre.$newpost
echo "::set-output name=version::$datepre.$newpost"
- name: Run Release Drafter
uses: release-drafter/release-drafter@v5
with:
tag: ${{ steps.version.outputs.version }}
name: ${{ steps.version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

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

22
.vscode/tasks.json vendored
View File

@@ -2,9 +2,9 @@
"version": "2.0.0",
"tasks": [
{
"label": "Run Testenv",
"label": "Run Supervisor",
"type": "shell",
"command": "./scripts/test_env.sh",
"command": "./scripts/run-supervisor.sh",
"group": {
"kind": "test",
"isDefault": true
@@ -16,7 +16,21 @@
"problemMatcher": []
},
{
"label": "Run Testenv CLI",
"label": "Build Supervisor",
"type": "shell",
"command": "./scripts/build-supervisor.sh",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Run Supervisor CLI",
"type": "shell",
"command": "docker exec -ti hassio_cli /usr/bin/cli.sh",
"group": {
@@ -30,7 +44,7 @@
"problemMatcher": []
},
{
"label": "Update UI",
"label": "Update Supervisor Panel",
"type": "shell",
"command": "./scripts/update-frontend.sh",
"group": {

View File

@@ -10,26 +10,23 @@ network settings or installing and updating software.
## Installation
Installation instructions can be found at https://home-assistant.io/hassio.
Installation instructions can be found at https://home-assistant.io/getting-started.
## Development
The development of the Supervisor is not difficult but tricky.
- You can use the builder to create your Supervisor: https://github.com/home-assistant/hassio-builder
- Access a HassOS device or VM and pull your Supervisor.
- Set the developer modus with the CLI tool: `ha supervisor options --channel=dev`
- Tag it as `homeassistant/xy-hassio-supervisor:latest`
- Restart the service with `systemctl restart hassos-supervisor | journalctl -fu hassos-supervisor`
- Test your changes
For small bugfixes or improvements, make a PR. For significant changes open a RFC first, please. Thanks.
For small changes and bugfixes you can just follow this, but for significant changes open a RFC first.
Development instructions can be found [here][development].
## Release
Follow is the relase circle process:
Releases are done in 3 stages (channels) with this structure:
1. Merge master into dev / make sure version stay on dev
2. Merge dev into master
3. Bump the release on master
4. Create a GitHub Release from master with the right version tag
1. Pull requests are merged to the `main` branch.
2. A new build is pushed to the `dev` stage.
3. Releases are published.
4. A new build is pushed to the `beta` stage.
5. The [`stable.json`][stable] file is updated.
6. The build that was pushed to `beta` will now be pushed to `stable`.
[development]: https://developers.home-assistant.io/docs/supervisor/development
[stable]: https://github.com/home-assistant/version/blob/master/stable.json

View File

@@ -1,26 +0,0 @@
# https://dev.azure.com/home-assistant
trigger:
batch: true
branches:
include:
- main
pr: none
variables:
- name: versionWheels
value: "1.13.0-3.8-alpine3.12"
resources:
repositories:
- repository: azure
type: github
name: "home-assistant/ci-azure"
endpoint: "home-assistant"
jobs:
- template: templates/azp-job-wheels.yaml@azure
parameters:
builderVersion: "$(versionWheels)"
builderApk: "build-base;libffi-dev;openssl-dev"
builderPip: "Cython"
skipBinary: "aiohttp"
wheelsRequirement: "requirements.txt"

View File

@@ -1,11 +1,11 @@
{
"image": "homeassistant/{arch}-hassio-supervisor",
"build_from": {
"aarch64": "homeassistant/aarch64-base-python:3.8-alpine3.12",
"armhf": "homeassistant/armhf-base-python:3.8-alpine3.12",
"armv7": "homeassistant/armv7-base-python:3.8-alpine3.12",
"amd64": "homeassistant/amd64-base-python:3.8-alpine3.12",
"i386": "homeassistant/i386-base-python:3.8-alpine3.12"
"aarch64": "homeassistant/aarch64-base-python:3.8-alpine3.13",
"armhf": "homeassistant/armhf-base-python:3.8-alpine3.13",
"armv7": "homeassistant/armv7-base-python:3.8-alpine3.13",
"amd64": "homeassistant/amd64-base-python:3.8-alpine3.13",
"i386": "homeassistant/i386-base-python:3.8-alpine3.13"
},
"labels": {
"io.hass.type": "supervisor"

View File

@@ -1,20 +1,20 @@
aiohttp==3.7.3
aiohttp==3.7.4
async_timeout==3.0.1
atomicwrites==1.4.0
attrs==20.3.0
awesomeversion==21.2.3
brotli==1.0.9
cchardet==2.1.7
colorlog==4.6.2
colorlog==4.7.2
cpe==1.2.1
cryptography==3.2.1
debugpy==1.2.0
docker==4.3.1
gitpython==3.1.11
jinja2==2.11.2
packaging==20.4
pulsectl==20.5.1
pytz==2020.4
cryptography==3.4.6
debugpy==1.2.1
docker==4.4.4
gitpython==3.1.14
jinja2==2.11.3
pulsectl==21.2.0
pytz==2021.1
pyudev==0.22.0
ruamel.yaml==0.15.100
sentry-sdk==0.19.4
voluptuous==0.12.0
sentry-sdk==0.20.3
voluptuous==0.12.1

View File

@@ -1,14 +1,14 @@
black==20.8b1
codecov==2.1.10
coverage==5.3
codecov==2.1.11
coverage==5.5
flake8-docstrings==1.5.0
flake8==3.8.4
pre-commit==2.8.2
pre-commit==2.10.1
pydocstyle==5.1.1
pylint==2.6.0
pylint==2.7.2
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)
pytest-cov==2.10.1
pytest-cov==2.11.1
pytest-timeout==1.4.2
pytest==6.1.2
pyupgrade==2.7.4
pytest==6.2.2
pyupgrade==2.10.0

View File

@@ -2,9 +2,17 @@
# ==============================================================================
# Start udev service
# ==============================================================================
if bashio::fs.directory_exists /run/udev && ! bashio::fs.file_exists /run/.old_udev; then
bashio::log.info "Using udev information from host"
bashio::exit.ok
fi
bashio::log.info "Setup udev backend inside container"
udevd --daemon
bashio::log.info "Update udev information"
touch /run/.old_udev
if udevadm trigger; then
udevadm settle || true
else

28
scripts/build-supervisor.sh Executable file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
source "${BASH_SOURCE[0]%/*}/common.sh"
set -eE
DOCKER_TIMEOUT=30
DOCKER_PID=0
function build_supervisor() {
docker pull homeassistant/amd64-builder:dev
docker run --rm \
--privileged \
-v /run/docker.sock:/run/docker.sock \
-v "$(pwd):/data" \
homeassistant/amd64-builder:dev \
--generic latest \
--target /data \
--test \
--amd64 \
--no-cache
}
echo "Build Supervisor"
start_docker
trap "stop_docker" ERR
build_supervisor

75
scripts/test_env.sh → scripts/common.sh Executable file → Normal file
View File

@@ -1,9 +1,4 @@
#!/bin/bash
set -eE
DOCKER_TIMEOUT=30
DOCKER_PID=0
function start_docker() {
local starttime
@@ -28,7 +23,6 @@ function start_docker() {
echo "Docker was initialized"
}
function stop_docker() {
local starttime
local endtime
@@ -54,17 +48,6 @@ function stop_docker() {
fi
}
function build_supervisor() {
docker pull homeassistant/amd64-builder:dev
docker run --rm --privileged \
-v /run/docker.sock:/run/docker.sock -v "$(pwd):/data" \
homeassistant/amd64-builder:dev \
--generic dev -t /data --test --amd64 --no-cache
}
function cleanup_lastboot() {
if [[ -f /workspaces/test_supervisor/config.json ]]; then
echo "Cleaning up last boot"
@@ -73,61 +56,3 @@ function cleanup_lastboot() {
rm /tmp/config.json
fi
}
function cleanup_docker() {
echo "Cleaning up stopped containers..."
docker rm $(docker ps -a -q) || true
}
function setup_test_env() {
mkdir -p /workspaces/test_supervisor
echo "Start Supervisor"
docker run --rm --privileged \
--name hassio_supervisor \
--security-opt seccomp=unconfined \
--security-opt apparmor:unconfined \
-v /run/docker.sock:/run/docker.sock \
-v /run/dbus:/run/dbus \
-v "/workspaces/test_supervisor":/data \
-v /etc/machine-id:/etc/machine-id:ro \
-e SUPERVISOR_SHARE="/workspaces/test_supervisor" \
-e SUPERVISOR_NAME=hassio_supervisor \
-e SUPERVISOR_DEV=1 \
-e SUPERVISOR_MACHINE="qemux86-64" \
homeassistant/amd64-hassio-supervisor:latest
}
function init_dbus() {
if pgrep dbus-daemon; then
echo "Dbus is running"
return 0
fi
echo "Startup dbus"
mkdir -p /var/lib/dbus
cp -f /etc/machine-id /var/lib/dbus/machine-id
# cleanups
mkdir -p /run/dbus
rm -f /run/dbus/pid
# run
dbus-daemon --system --print-address
}
echo "Start Test-Env"
start_docker
trap "stop_docker" ERR
build_supervisor
cleanup_lastboot
cleanup_docker
init_dbus
setup_test_env
stop_docker

102
scripts/run-supervisor.sh Executable file
View File

@@ -0,0 +1,102 @@
#!/bin/bash
source "${BASH_SOURCE[0]%/*}/common.sh"
source "${BASH_SOURCE[0]%/*}/build-supervisor.sh"
set -eE
DOCKER_TIMEOUT=30
DOCKER_PID=0
function cleanup_docker() {
echo "Cleaning up stopped containers..."
docker rm $(docker ps -a -q) || true
}
function run_supervisor() {
mkdir -p /workspaces/test_supervisor
echo "Start Supervisor"
docker run --rm --privileged \
--name hassio_supervisor \
--privileged \
--security-opt seccomp=unconfined \
--security-opt apparmor:unconfined \
-v /run/docker.sock:/run/docker.sock:rw \
-v /run/dbus:/run/dbus:ro \
-v /run/udev:/run/udev:ro \
-v "/workspaces/test_supervisor":/data:rw \
-v /etc/machine-id:/etc/machine-id:ro \
-v /workspaces/supervisor:/usr/src/supervisor \
-e SUPERVISOR_SHARE="/workspaces/test_supervisor" \
-e SUPERVISOR_NAME=hassio_supervisor \
-e SUPERVISOR_DEV=1 \
-e SUPERVISOR_MACHINE="qemux86-64" \
homeassistant/amd64-hassio-supervisor:latest
}
function init_dbus() {
if pgrep dbus-daemon; then
echo "Dbus is running"
return 0
fi
echo "Startup dbus"
mkdir -p /var/lib/dbus
cp -f /etc/machine-id /var/lib/dbus/machine-id
# cleanups
mkdir -p /run/dbus
rm -f /run/dbus/pid
# run
dbus-daemon --system --print-address
}
function init_udev() {
if pgrep systemd-udevd; then
echo "udev is running"
return 0
fi
echo "Startup udev"
# cleanups
mkdir -p /run/udev
# run
/lib/systemd/systemd-udevd --daemon
sleep 3
udevadm trigger && udevadm settle
}
echo "Run Supervisor"
start_docker
trap "stop_docker" ERR
if [ "$( docker container inspect -f '{{.State.Status}}' hassio_supervisor )" == "running" ]; then
echo "Restarting Supervisor"
docker rm -f hassio_supervisor
init_dbus
init_udev
cleanup_lastboot
run_supervisor
stop_docker
else
echo "Starting Supervisor"
docker system prune -f
build_supervisor
cleanup_lastboot
cleanup_docker
init_dbus
init_udev
run_supervisor
stop_docker
fi

View File

@@ -10,6 +10,7 @@ from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
AddonConfigurationError,
AddonsError,
AddonsJobError,
AddonsNotSupportedError,
CoreDNSError,
DockerAPIError,
@@ -147,7 +148,8 @@ class AddonManager(CoreSysAttributes):
JobCondition.FREE_SPACE,
JobCondition.INTERNET_HOST,
JobCondition.HEALTHY,
]
],
on_condition=AddonsJobError,
)
async def install(self, slug: str) -> None:
"""Install an add-on."""
@@ -248,7 +250,8 @@ class AddonManager(CoreSysAttributes):
JobCondition.FREE_SPACE,
JobCondition.INTERNET_HOST,
JobCondition.HEALTHY,
]
],
on_condition=AddonsJobError,
)
async def update(self, slug: str) -> None:
"""Update add-on."""
@@ -273,17 +276,18 @@ class AddonManager(CoreSysAttributes):
# Update instance
last_state: AddonState = addon.state
old_image = addon.image
try:
await addon.instance.update(store.version, store.image)
# Cleanup
with suppress(DockerError):
await addon.instance.cleanup()
except DockerError as err:
raise AddonsError() from err
else:
self.data.update(store)
_LOGGER.info("Add-on '%s' successfully updated", slug)
_LOGGER.info("Add-on '%s' successfully updated", slug)
self.data.update(store)
# Cleanup
with suppress(DockerError):
await addon.instance.cleanup(old_image=old_image)
# Setup/Fix AppArmor profile
await addon.install_apparmor()
@@ -297,7 +301,8 @@ class AddonManager(CoreSysAttributes):
JobCondition.FREE_SPACE,
JobCondition.INTERNET_HOST,
JobCondition.HEALTHY,
]
],
on_condition=AddonsJobError,
)
async def rebuild(self, slug: str) -> None:
"""Perform a rebuild of local build add-on."""
@@ -339,7 +344,8 @@ class AddonManager(CoreSysAttributes):
JobCondition.FREE_SPACE,
JobCondition.INTERNET_HOST,
JobCondition.HEALTHY,
]
],
on_condition=AddonsJobError,
)
async def restore(self, slug: str, tar_file: tarfile.TarFile) -> None:
"""Restore state of an add-on."""

View File

@@ -10,7 +10,7 @@ import secrets
import shutil
import tarfile
from tempfile import TemporaryDirectory
from typing import Any, Awaitable, Dict, List, Optional
from typing import Any, Awaitable, Dict, List, Optional, Set
import aiohttp
import voluptuous as vol
@@ -22,6 +22,8 @@ from ..const import (
ATTR_AUDIO_OUTPUT,
ATTR_AUTO_UPDATE,
ATTR_BOOT,
ATTR_DATA,
ATTR_EVENT,
ATTR_IMAGE,
ATTR_INGRESS_ENTRY,
ATTR_INGRESS_PANEL,
@@ -32,8 +34,10 @@ from ..const import (
ATTR_PORTS,
ATTR_PROTECTED,
ATTR_SCHEMA,
ATTR_SLUG,
ATTR_STATE,
ATTR_SYSTEM,
ATTR_TYPE,
ATTR_USER,
ATTR_UUID,
ATTR_VERSION,
@@ -50,18 +54,21 @@ from ..exceptions import (
AddonConfigurationError,
AddonsError,
AddonsNotSupportedError,
ConfigurationFileError,
DockerError,
DockerRequestError,
HostAppArmorError,
JsonFileError,
)
from ..hardware.data import Device
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 ..utils.tar import atomic_contents_add, secure_path
from .model import AddonModel, Data
from .options import AddonOptions
from .utils import remove_data
from .validate import SCHEMA_ADDON_SNAPSHOT, validate_options
from .validate import SCHEMA_ADDON_SNAPSHOT
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -72,7 +79,7 @@ RE_WEBUI = re.compile(
RE_WATCHDOG = re.compile(
r"^(?:(?P<s_prefix>https?|tcp)|\[PROTO:(?P<t_proto>\w+)\])"
r":\/\/\[HOST\]:\[PORT:(?P<t_port>\d+)\](?P<s_suffix>.*)$"
r":\/\/\[HOST\]:(?:\[PORT:)?(?P<t_port>\d+)\]?(?P<s_suffix>.*)$"
)
RE_OLD_AUDIO = re.compile(r"\d+,\d+")
@@ -87,12 +94,34 @@ class Addon(AddonModel):
"""Initialize data holder."""
super().__init__(coresys, slug)
self.instance: DockerAddon = DockerAddon(coresys, self)
self.state: AddonState = AddonState.UNKNOWN
self._state: AddonState = AddonState.UNKNOWN
def __repr__(self) -> str:
"""Return internal representation."""
return f"<Addon: {self.slug}>"
@property
def state(self) -> AddonState:
"""Return state of the add-on."""
return self._state
@state.setter
def state(self, new_state: AddonState) -> None:
"""Set the add-on into new state."""
if self._state == new_state:
return
self._state = new_state
self.sys_homeassistant.websocket.send_command(
{
ATTR_TYPE: WSType.SUPERVISOR_EVENT,
ATTR_DATA: {
ATTR_EVENT: WSEvent.ADDON,
ATTR_SLUG: self.slug,
ATTR_STATE: new_state,
},
}
)
@property
def in_progress(self) -> bool:
"""Return True if a task is in progress."""
@@ -101,7 +130,7 @@ class Addon(AddonModel):
async def load(self) -> None:
"""Async initialize of object."""
with suppress(DockerError):
await self.instance.attach(tag=self.version)
await self.instance.attach(version=self.version)
# Evaluate state
if await self.instance.is_running():
@@ -394,6 +423,34 @@ class Addon(AddonModel):
"""Return path to asound config for Docker."""
return Path(self.sys_config.path_extern_tmp, f"{self.slug}_pulse")
@property
def devices(self) -> Set[Device]:
"""Extract devices from add-on options."""
raw_schema = self.data[ATTR_SCHEMA]
if isinstance(raw_schema, bool) or not raw_schema:
return set()
# Validate devices
options_validator = AddonOptions(self.coresys, raw_schema, self.name, self.slug)
with suppress(vol.Invalid):
options_validator(self.options)
return options_validator.devices
@property
def pwned(self) -> Set[str]:
"""Extract pwned data for add-on options."""
raw_schema = self.data[ATTR_SCHEMA]
if isinstance(raw_schema, bool) or not raw_schema:
return set()
# Validate devices
options_validator = AddonOptions(self.coresys, raw_schema, self.name, self.slug)
with suppress(vol.Invalid):
options_validator(self.options)
return options_validator.pwned
def save_persist(self) -> None:
"""Save data of add-on."""
self.sys_addons.data.save_data()
@@ -442,22 +499,19 @@ class Addon(AddonModel):
async def write_options(self) -> None:
"""Return True if add-on options is written to data."""
schema = self.schema
options = self.options
# Update secrets for validation
await self.sys_homeassistant.secrets.reload()
try:
options = schema(options)
options = self.schema(self.options)
write_json_file(self.path_options, options)
except vol.Invalid as ex:
_LOGGER.error(
"Add-on %s has invalid options: %s",
self.slug,
humanize_error(options, ex),
humanize_error(self.options, ex),
)
except JsonFileError:
except ConfigurationFileError:
_LOGGER.error("Add-on %s can't write options", self.slug)
else:
_LOGGER.debug("Add-on %s write options: %s", self.slug, options)
@@ -538,7 +592,9 @@ class Addon(AddonModel):
# create voluptuous
new_schema = vol.Schema(
vol.All(dict, validate_options(self.coresys, new_raw_schema))
vol.All(
dict, AddonOptions(self.coresys, new_raw_schema, self.name, self.slug)
)
)
# validate
@@ -570,7 +626,7 @@ class Addon(AddonModel):
try:
await self.instance.run()
except DockerRequestError as err:
self.state = AddonState.STOPPED
self.state = AddonState.ERROR
raise AddonsError() from err
except DockerError as err:
self.state = AddonState.ERROR
@@ -581,8 +637,9 @@ class Addon(AddonModel):
async def stop(self) -> None:
"""Stop add-on."""
try:
return await self.instance.stop()
await self.instance.stop()
except DockerRequestError as err:
self.state = AddonState.ERROR
raise AddonsError() from err
except DockerError as err:
self.state = AddonState.ERROR
@@ -653,7 +710,7 @@ class Addon(AddonModel):
# Store local configs/state
try:
write_json_file(temp_path.joinpath("addon.json"), data)
except JsonFileError as err:
except ConfigurationFileError as err:
_LOGGER.error("Can't save meta for %s", self.slug)
raise AddonsError() from err
@@ -709,7 +766,7 @@ class Addon(AddonModel):
# Read snapshot data
try:
data = read_json_file(Path(temp, "addon.json"))
except JsonFileError as err:
except ConfigurationFileError as err:
raise AddonsError() from err
# Validate

View File

@@ -4,16 +4,24 @@ from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Dict
from ..const import ATTR_ARGS, ATTR_BUILD_FROM, ATTR_SQUASH, META_ADDON
from awesomeversion import AwesomeVersion
from ..const import (
ATTR_ARGS,
ATTR_BUILD_FROM,
ATTR_SQUASH,
FILE_SUFFIX_CONFIGURATION,
META_ADDON,
)
from ..coresys import CoreSys, CoreSysAttributes
from ..utils.json import JsonConfig
from ..utils.common import FileConfiguration, find_one_filetype
from .validate import SCHEMA_BUILD_CONFIG
if TYPE_CHECKING:
from . import AnyAddon
class AddonBuild(JsonConfig, CoreSysAttributes):
class AddonBuild(FileConfiguration, CoreSysAttributes):
"""Handle build options for add-ons."""
def __init__(self, coresys: CoreSys, addon: AnyAddon) -> None:
@@ -22,7 +30,10 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
self.addon = addon
super().__init__(
Path(self.addon.path_location, "build.json"), SCHEMA_BUILD_CONFIG
find_one_filetype(
self.addon.path_location, "build", FILE_SUFFIX_CONFIGURATION
),
SCHEMA_BUILD_CONFIG,
)
def save_data(self):
@@ -46,11 +57,21 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
"""Return additional Docker build arguments."""
return self._data[ATTR_ARGS]
def get_docker_args(self, version):
@property
def is_valid(self) -> bool:
"""Return true if the build env is valid."""
return all(
[
self.addon.path_location.is_dir(),
Path(self.addon.path_location, "Dockerfile").is_file(),
]
)
def get_docker_args(self, version: AwesomeVersion):
"""Create a dict with Docker build arguments."""
args = {
"path": str(self.addon.path_location),
"tag": f"{self.addon.image}:{version}",
"tag": f"{self.addon.image}:{version!s}",
"pull": True,
"forcerm": True,
"squash": self.squash,

View File

@@ -1,6 +1,5 @@
"""Init file for Supervisor add-on data."""
from copy import deepcopy
import logging
from typing import Any, Dict
from ..const import (
@@ -13,16 +12,14 @@ from ..const import (
)
from ..coresys import CoreSys, CoreSysAttributes
from ..store.addon import AddonStore
from ..utils.json import JsonConfig
from ..utils.common import FileConfiguration
from .addon import Addon
from .validate import SCHEMA_ADDONS_FILE
_LOGGER: logging.Logger = logging.getLogger(__name__)
Config = Dict[str, Any]
class AddonsData(JsonConfig, CoreSysAttributes):
class AddonsData(FileConfiguration, CoreSysAttributes):
"""Hold data for installed Add-ons inside Supervisor."""
def __init__(self, coresys: CoreSys):

View File

@@ -3,7 +3,7 @@ from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any, Awaitable, Dict, List, Optional
from packaging import version as pkg_version
from awesomeversion import AwesomeVersion, AwesomeVersionException
import voluptuous as vol
from ..const import (
@@ -12,7 +12,6 @@ from ..const import (
ATTR_ARCH,
ATTR_AUDIO,
ATTR_AUTH_API,
ATTR_AUTO_UART,
ATTR_BOOT,
ATTR_DESCRIPTON,
ATTR_DEVICES,
@@ -46,6 +45,7 @@ from ..const import (
ATTR_PORTS,
ATTR_PORTS_DESCRIPTION,
ATTR_PRIVILEGED,
ATTR_REALTIME,
ATTR_REPOSITORY,
ATTR_SCHEMA,
ATTR_SERVICES,
@@ -56,6 +56,8 @@ from ..const import (
ATTR_STDIN,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_TRANSLATIONS,
ATTR_UART,
ATTR_UDEV,
ATTR_URL,
ATTR_USB,
@@ -71,7 +73,9 @@ from ..const import (
AddonStartup,
)
from ..coresys import CoreSys, CoreSysAttributes
from .validate import RE_SERVICE, RE_VOLUME, schema_ui_options, validate_options
from ..docker.const import Capabilities
from .options import AddonOptions, UiOptions
from .validate import RE_SERVICE, RE_VOLUME
Data = Dict[str, Any]
@@ -183,12 +187,17 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data[ATTR_REPOSITORY]
@property
def latest_version(self) -> str:
def translations(self) -> dict:
"""Return add-on translations."""
return self.data[ATTR_TRANSLATIONS]
@property
def latest_version(self) -> AwesomeVersion:
"""Return latest version of add-on."""
return self.data[ATTR_VERSION]
@property
def version(self) -> Optional[str]:
def version(self) -> AwesomeVersion:
"""Return version of add-on."""
return self.data[ATTR_VERSION]
@@ -296,14 +305,9 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data[ATTR_HOST_DBUS]
@property
def devices(self) -> List[str]:
"""Return devices of add-on."""
return self.data.get(ATTR_DEVICES, [])
@property
def tmpfs(self) -> Optional[str]:
"""Return tmpfs of add-on."""
return self.data.get(ATTR_TMPFS)
def static_devices(self) -> List[Path]:
"""Return static devices of add-on."""
return [Path(node) for node in self.data.get(ATTR_DEVICES, [])]
@property
def environment(self) -> Optional[Dict[str, str]]:
@@ -311,7 +315,7 @@ class AddonModel(CoreSysAttributes, ABC):
return self.data.get(ATTR_ENVIRONMENT)
@property
def privileged(self) -> List[str]:
def privileged(self) -> List[Capabilities]:
"""Return list of privilege."""
return self.data.get(ATTR_PRIVILEGED, [])
@@ -387,7 +391,7 @@ class AddonModel(CoreSysAttributes, ABC):
@property
def with_uart(self) -> bool:
"""Return True if we should map all UART device."""
return self.data[ATTR_AUTO_UART]
return self.data[ATTR_UART]
@property
def with_udev(self) -> bool:
@@ -399,6 +403,11 @@ class AddonModel(CoreSysAttributes, ABC):
"""Return True if the add-on access to kernel modules."""
return self.data[ATTR_KERNEL_MODULES]
@property
def with_realtime(self) -> bool:
"""Return True if the add-on need realtime schedule functions."""
return self.data[ATTR_REALTIME]
@property
def with_full_access(self) -> bool:
"""Return True if the add-on want full access to hardware."""
@@ -409,6 +418,11 @@ class AddonModel(CoreSysAttributes, ABC):
"""Return True if the add-on read access to devicetree."""
return self.data[ATTR_DEVICETREE]
@property
def with_tmpfs(self) -> Optional[str]:
"""Return if tmp is in memory of add-on."""
return self.data[ATTR_TMPFS]
@property
def access_auth_api(self) -> bool:
"""Return True if the add-on access to login/auth backend."""
@@ -522,8 +536,10 @@ class AddonModel(CoreSysAttributes, ABC):
raw_schema = self.data[ATTR_SCHEMA]
if isinstance(raw_schema, bool):
return vol.Schema(dict)
return vol.Schema(vol.All(dict, validate_options(self.coresys, raw_schema)))
raw_schema = {}
return vol.Schema(
vol.All(dict, AddonOptions(self.coresys, raw_schema, self.name, self.slug))
)
@property
def schema_ui(self) -> Optional[List[Dict[str, Any]]]:
@@ -532,7 +548,7 @@ class AddonModel(CoreSysAttributes, ABC):
if isinstance(raw_schema, bool):
return None
return schema_ui_options(raw_schema)
return UiOptions(self.coresys)(raw_schema)
def __eq__(self, other):
"""Compaired add-on objects."""
@@ -554,15 +570,10 @@ class AddonModel(CoreSysAttributes, ABC):
return False
# Home Assistant
version = config.get(ATTR_HOMEASSISTANT)
if version is None or self.sys_homeassistant.version is None:
return True
version: Optional[AwesomeVersion] = config.get(ATTR_HOMEASSISTANT)
try:
return pkg_version.parse(
self.sys_homeassistant.version
) >= pkg_version.parse(version)
except pkg_version.InvalidVersion:
return self.sys_homeassistant.version >= version
except (AwesomeVersionException, TypeError):
return True
def _image(self, config) -> str:

View File

@@ -0,0 +1,410 @@
"""Add-on Options / UI rendering."""
import hashlib
import logging
from pathlib import Path
import re
from typing import Any, Dict, List, Set, Union
import voluptuous as vol
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import HardwareNotFound
from ..hardware.const import UdevSubsystem
from ..hardware.data import Device
from ..validate import network_port
_LOGGER: logging.Logger = logging.getLogger(__name__)
_STR = "str"
_INT = "int"
_FLOAT = "float"
_BOOL = "bool"
_PASSWORD = "password"
_EMAIL = "email"
_URL = "url"
_PORT = "port"
_MATCH = "match"
_LIST = "list"
_DEVICE = "device"
RE_SCHEMA_ELEMENT = re.compile(
r"^(?:"
r"|bool"
r"|email"
r"|url"
r"|port"
r"|device(?:\((?P<filter>subsystem=[a-z]+)\))?"
r"|str(?:\((?P<s_min>\d+)?,(?P<s_max>\d+)?\))?"
r"|password(?:\((?P<p_min>\d+)?,(?P<p_max>\d+)?\))?"
r"|int(?:\((?P<i_min>\d+)?,(?P<i_max>\d+)?\))?"
r"|float(?:\((?P<f_min>[\d\.]+)?,(?P<f_max>[\d\.]+)?\))?"
r"|match\((?P<match>.*)\)"
r"|list\((?P<list>.+)\)"
r")\??$"
)
_SCHEMA_LENGTH_PARTS = (
"i_min",
"i_max",
"f_min",
"f_max",
"s_min",
"s_max",
"p_min",
"p_max",
)
class AddonOptions(CoreSysAttributes):
"""Validate Add-ons Options."""
def __init__(
self, coresys: CoreSys, raw_schema: Dict[str, Any], name: str, slug: str
):
"""Validate schema."""
self.coresys: CoreSys = coresys
self.raw_schema: Dict[str, Any] = raw_schema
self.devices: Set[Device] = set()
self.pwned: Set[str] = set()
self._name = name
self._slug = slug
def __call__(self, struct):
"""Create schema validator for add-ons options."""
options = {}
# read options
for key, value in struct.items():
# Ignore unknown options / remove from list
if key not in self.raw_schema:
_LOGGER.warning(
"Option '%s' does not exist in the schema for %s (%s)",
key,
self._name,
self._slug,
)
continue
typ = self.raw_schema[key]
try:
if isinstance(typ, list):
# nested value list
options[key] = self._nested_validate_list(typ[0], value, key)
elif isinstance(typ, dict):
# nested value dict
options[key] = self._nested_validate_dict(typ, value, key)
else:
# normal value
options[key] = self._single_validate(typ, value, key)
except (IndexError, KeyError):
raise vol.Invalid(
f"Type error for option '{key}' in {self._name} ({self._slug})"
) from None
self._check_missing_options(self.raw_schema, options, "root")
return options
# pylint: disable=no-value-for-parameter
def _single_validate(self, typ: str, value: Any, key: str):
"""Validate a single element."""
# if required argument
if value is None:
raise vol.Invalid(
f"Missing required option '{key}' in {self._name} ({self._slug})"
) from None
# Lookup secret
if str(value).startswith("!secret "):
secret: str = value.partition(" ")[2]
value = self.sys_homeassistant.secrets.get(secret)
if value is None:
raise vol.Invalid(
f"Unknown secret '{secret}' in {self._name} ({self._slug})"
) from None
# parse extend data from type
match = RE_SCHEMA_ELEMENT.match(typ)
if not match:
raise vol.Invalid(
f"Unknown type '{typ}' in {self._name} ({self._slug})"
) from None
# prepare range
range_args = {}
for group_name in _SCHEMA_LENGTH_PARTS:
group_value = match.group(group_name)
if group_value:
range_args[group_name[2:]] = float(group_value)
if typ.startswith(_STR) or typ.startswith(_PASSWORD):
if typ.startswith(_PASSWORD) and value:
self.pwned.add(hashlib.sha1(str(value).encode()).hexdigest())
return vol.All(str(value), vol.Range(**range_args))(value)
elif typ.startswith(_INT):
return vol.All(vol.Coerce(int), vol.Range(**range_args))(value)
elif typ.startswith(_FLOAT):
return vol.All(vol.Coerce(float), vol.Range(**range_args))(value)
elif typ.startswith(_BOOL):
return vol.Boolean()(value)
elif typ.startswith(_EMAIL):
return vol.Email()(value)
elif typ.startswith(_URL):
return vol.Url()(value)
elif typ.startswith(_PORT):
return network_port(value)
elif typ.startswith(_MATCH):
return vol.Match(match.group("match"))(str(value))
elif typ.startswith(_LIST):
return vol.In(match.group("list").split("|"))(str(value))
elif typ.startswith(_DEVICE):
try:
device = self.sys_hardware.get_by_path(Path(value))
except HardwareNotFound:
raise vol.Invalid(
f"Device '{value}' does not exists! in {self._name} ({self._slug})"
) from None
# Have filter
if match.group("filter"):
str_filter = match.group("filter")
device_filter = _create_device_filter(str_filter)
if device not in self.sys_hardware.filter_devices(**device_filter):
raise vol.Invalid(
f"Device '{value}' don't match the filter {str_filter}! in {self._name} ({self._slug})"
)
# Device valid
self.devices.add(device)
return str(device.path)
raise vol.Invalid(
f"Fatal error for option '{key}' with type '{typ}' in {self._name} ({self._slug})"
) from None
def _nested_validate_list(self, typ: Any, data_list: List[Any], key: str):
"""Validate nested items."""
options = []
# Make sure it is a list
if not isinstance(data_list, list):
raise vol.Invalid(
f"Invalid list for option '{key}' in {self._name} ({self._slug})"
) from None
# Process list
for element in data_list:
# Nested?
if isinstance(typ, dict):
c_options = self._nested_validate_dict(typ, element, key)
options.append(c_options)
else:
options.append(self._single_validate(typ, element, key))
return options
def _nested_validate_dict(
self, typ: Dict[Any, Any], data_dict: Dict[Any, Any], key: str
):
"""Validate nested items."""
options = {}
# Make sure it is a dict
if not isinstance(data_dict, dict):
raise vol.Invalid(
f"Invalid dict for option '{key}' in {self._name} ({self._slug})"
) from None
# Process dict
for c_key, c_value in data_dict.items():
# Ignore unknown options / remove from list
if c_key not in typ:
_LOGGER.warning(
"Unknown option '%s' for %s (%s)", c_key, self._name, self._slug
)
continue
# Nested?
if isinstance(typ[c_key], list):
options[c_key] = self._nested_validate_list(
typ[c_key][0], c_value, c_key
)
else:
options[c_key] = self._single_validate(typ[c_key], c_value, c_key)
self._check_missing_options(typ, options, key)
return options
def _check_missing_options(
self, origin: Dict[Any, Any], exists: Dict[Any, Any], root: str
) -> None:
"""Check if all options are exists."""
missing = set(origin) - set(exists)
for miss_opt in missing:
if isinstance(origin[miss_opt], str) and origin[miss_opt].endswith("?"):
continue
raise vol.Invalid(
f"Missing option '{miss_opt}' in {root} in {self._name} ({self._slug})"
) from None
class UiOptions(CoreSysAttributes):
"""Render UI Add-ons Options."""
def __init__(self, coresys: CoreSys) -> None:
"""Initialize UI option render."""
self.coresys = coresys
def __call__(self, raw_schema: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate UI schema."""
ui_schema: List[Dict[str, Any]] = []
# read options
for key, value in raw_schema.items():
if isinstance(value, list):
# nested value list
self._nested_ui_list(ui_schema, value, key)
elif isinstance(value, dict):
# nested value dict
self._nested_ui_dict(ui_schema, value, key)
else:
# normal value
self._single_ui_option(ui_schema, value, key)
return ui_schema
def _single_ui_option(
self,
ui_schema: List[Dict[str, Any]],
value: str,
key: str,
multiple: bool = False,
) -> None:
"""Validate a single element."""
ui_node: Dict[str, Union[str, bool, float, List[str]]] = {"name": key}
# If multiple
if multiple:
ui_node["multiple"] = True
# Parse extend data from type
match = RE_SCHEMA_ELEMENT.match(value)
if not match:
return
# Prepare range
for group_name in _SCHEMA_LENGTH_PARTS:
group_value = match.group(group_name)
if not group_value:
continue
if group_name[2:] == "min":
ui_node["lengthMin"] = float(group_value)
elif group_name[2:] == "max":
ui_node["lengthMax"] = float(group_value)
# If required
if value.endswith("?"):
ui_node["optional"] = True
else:
ui_node["required"] = True
# Data types
if value.startswith(_STR):
ui_node["type"] = "string"
elif value.startswith(_PASSWORD):
ui_node["type"] = "string"
ui_node["format"] = "password"
elif value.startswith(_INT):
ui_node["type"] = "integer"
elif value.startswith(_FLOAT):
ui_node["type"] = "float"
elif value.startswith(_BOOL):
ui_node["type"] = "boolean"
elif value.startswith(_EMAIL):
ui_node["type"] = "string"
ui_node["format"] = "email"
elif value.startswith(_URL):
ui_node["type"] = "string"
ui_node["format"] = "url"
elif value.startswith(_PORT):
ui_node["type"] = "integer"
elif value.startswith(_MATCH):
ui_node["type"] = "string"
elif value.startswith(_LIST):
ui_node["type"] = "select"
ui_node["options"] = match.group("list").split("|")
elif value.startswith(_DEVICE):
ui_node["type"] = "select"
# Have filter
if match.group("filter"):
device_filter = _create_device_filter(match.group("filter"))
ui_node["options"] = [
(device.by_id or device.path).as_posix()
for device in self.sys_hardware.filter_devices(**device_filter)
]
else:
ui_node["options"] = [
(device.by_id or device.path).as_posix()
for device in self.sys_hardware.devices
]
ui_schema.append(ui_node)
def _nested_ui_list(
self,
ui_schema: List[Dict[str, Any]],
option_list: List[Any],
key: str,
) -> None:
"""UI nested list items."""
try:
element = option_list[0]
except IndexError:
_LOGGER.error("Invalid schema %s", key)
return
if isinstance(element, dict):
self._nested_ui_dict(ui_schema, element, key, multiple=True)
else:
self._single_ui_option(ui_schema, element, key, multiple=True)
def _nested_ui_dict(
self,
ui_schema: List[Dict[str, Any]],
option_dict: Dict[str, Any],
key: str,
multiple: bool = False,
) -> None:
"""UI nested dict items."""
ui_node = {
"name": key,
"type": "schema",
"optional": True,
"multiple": multiple,
}
nested_schema = []
for c_key, c_value in option_dict.items():
# Nested?
if isinstance(c_value, list):
self._nested_ui_list(nested_schema, c_value, c_key)
else:
self._single_ui_option(nested_schema, c_value, c_key)
ui_node["schema"] = nested_schema
ui_schema.append(ui_node)
def _create_device_filter(str_filter: str) -> Dict[str, Any]:
"""Generate device Filter."""
raw_filter = dict(value.split("=") for value in str_filter.split(";"))
clean_filter = {}
for key, value in raw_filter.items():
if key == "subsystem":
clean_filter[key] = UdevSubsystem(value)
else:
clean_filter[key] = value
return clean_filter

View File

@@ -6,18 +6,8 @@ import logging
from pathlib import Path
from typing import TYPE_CHECKING
from ..const import (
PRIVILEGED_DAC_READ_SEARCH,
PRIVILEGED_NET_ADMIN,
PRIVILEGED_SYS_ADMIN,
PRIVILEGED_SYS_MODULE,
PRIVILEGED_SYS_PTRACE,
PRIVILEGED_SYS_RAWIO,
ROLE_ADMIN,
ROLE_MANAGER,
SECURITY_DISABLE,
SECURITY_PROFILE,
)
from ..const import ROLE_ADMIN, ROLE_MANAGER, SECURITY_DISABLE, SECURITY_PROFILE
from ..docker.const import Capabilities
if TYPE_CHECKING:
from .model import AddonModel
@@ -46,16 +36,19 @@ def rating_security(addon: AddonModel) -> int:
rating += 1
# Privileged options
if any(
privilege in addon.privileged
for privilege in (
PRIVILEGED_NET_ADMIN,
PRIVILEGED_SYS_ADMIN,
PRIVILEGED_SYS_RAWIO,
PRIVILEGED_SYS_PTRACE,
PRIVILEGED_SYS_MODULE,
PRIVILEGED_DAC_READ_SEARCH,
if (
any(
privilege in addon.privileged
for privilege in (
Capabilities.NET_ADMIN,
Capabilities.SYS_ADMIN,
Capabilities.SYS_RAWIO,
Capabilities.SYS_PTRACE,
Capabilities.SYS_MODULE,
Capabilities.DAC_READ_SEARCH,
)
)
or addon.with_kernel_modules
):
rating += -1
@@ -73,12 +66,8 @@ def rating_security(addon: AddonModel) -> int:
if addon.host_pid:
rating += -2
# Full Access
if addon.with_full_access:
rating += -2
# Docker Access
if addon.access_docker_api:
# Docker Access & full Access
if addon.access_docker_api or addon.with_full_access:
rating = 1
return max(min(6, rating), 1)

View File

@@ -2,7 +2,7 @@
import logging
import re
import secrets
from typing import Any, Dict, List, Union
from typing import Any, Dict
import uuid
import voluptuous as vol
@@ -18,10 +18,10 @@ from ..const import (
ATTR_AUDIO_INPUT,
ATTR_AUDIO_OUTPUT,
ATTR_AUTH_API,
ATTR_AUTO_UART,
ATTR_AUTO_UPDATE,
ATTR_BOOT,
ATTR_BUILD_FROM,
ATTR_CONFIGURATION,
ATTR_DESCRIPTON,
ATTR_DEVICES,
ATTR_DEVICETREE,
@@ -60,6 +60,7 @@ from ..const import (
ATTR_PORTS_DESCRIPTION,
ATTR_PRIVILEGED,
ATTR_PROTECTED,
ATTR_REALTIME,
ATTR_REPOSITORY,
ATTR_SCHEMA,
ATTR_SERVICES,
@@ -73,6 +74,8 @@ from ..const import (
ATTR_SYSTEM,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_TRANSLATIONS,
ATTR_UART,
ATTR_UDEV,
ATTR_URL,
ATTR_USB,
@@ -82,7 +85,6 @@ from ..const import (
ATTR_VIDEO,
ATTR_WATCHDOG,
ATTR_WEBUI,
PRIVILEGED_ALL,
ROLE_ALL,
ROLE_DEFAULT,
AddonBoot,
@@ -90,9 +92,10 @@ from ..const import (
AddonStartup,
AddonState,
)
from ..coresys import CoreSys
from ..discovery.validate import valid_discovery_service
from ..docker.const import Capabilities
from ..validate import (
docker_image,
docker_ports,
docker_ports_description,
network_port,
@@ -100,51 +103,14 @@ from ..validate import (
uuid_match,
version_tag,
)
from .options import RE_SCHEMA_ELEMENT
_LOGGER: logging.Logger = logging.getLogger(__name__)
RE_VOLUME = re.compile(r"^(config|ssl|addons|backup|share|media)(?::(rw|ro))?$")
RE_SERVICE = re.compile(r"^(?P<service>mqtt|mysql):(?P<rights>provide|want|need)$")
V_STR = "str"
V_INT = "int"
V_FLOAT = "float"
V_BOOL = "bool"
V_PASSWORD = "password"
V_EMAIL = "email"
V_URL = "url"
V_PORT = "port"
V_MATCH = "match"
V_LIST = "list"
RE_SCHEMA_ELEMENT = re.compile(
r"^(?:"
r"|bool"
r"|email"
r"|url"
r"|port"
r"|str(?:\((?P<s_min>\d+)?,(?P<s_max>\d+)?\))?"
r"|password(?:\((?P<p_min>\d+)?,(?P<p_max>\d+)?\))?"
r"|int(?:\((?P<i_min>\d+)?,(?P<i_max>\d+)?\))?"
r"|float(?:\((?P<f_min>[\d\.]+)?,(?P<f_max>[\d\.]+)?\))?"
r"|match\((?P<match>.*)\)"
r"|list\((?P<list>.+)\)"
r")\??$"
)
_SCHEMA_LENGTH_PARTS = (
"i_min",
"i_max",
"f_min",
"f_max",
"s_min",
"s_max",
"p_min",
"p_max",
)
RE_DOCKER_IMAGE = re.compile(r"^([a-zA-Z\-\.:\d{}]+/)*?([\-\w{}]+)/([\-\w{}]+)$")
RE_DOCKER_IMAGE_BUILD = re.compile(
r"^([a-zA-Z\-\.:\d{}]+/)*?([\-\w{}]+)/([\-\w{}]+)(:[\.\-\w{}]+)?$"
)
@@ -173,34 +139,101 @@ RE_MACHINE = re.compile(
)
def _simple_startup(value) -> str:
"""Define startup schema."""
if value == "before":
return AddonStartup.SERVICES.value
if value == "after":
return AddonStartup.APPLICATION.value
return value
def _warn_addon_config(config: Dict[str, Any]):
"""Warn about miss configs."""
name = config.get(ATTR_NAME)
if not name:
raise vol.Invalid("Invalid Add-on config!")
if config.get(ATTR_FULL_ACCESS, False) and (
config.get(ATTR_DEVICES)
or config.get(ATTR_UART)
or config.get(ATTR_USB)
or config.get(ATTR_GPIO)
):
_LOGGER.warning(
"Add-on have full device access, and selective device access in the configuration. Please report this to the maintainer of %s",
name,
)
return config
def _migrate_addon_config(protocol=False):
"""Migrate addon config."""
def _migrate(config: Dict[str, Any]):
name = config.get(ATTR_NAME)
if not name:
raise vol.Invalid("Invalid Add-on config!")
# Startup 2018-03-30
if config.get(ATTR_STARTUP) in ("before", "after"):
value = config[ATTR_STARTUP]
if protocol:
_LOGGER.warning(
"Add-on config 'startup' with '%s' is deprecated. Please report this to the maintainer of %s",
value,
name,
)
if value == "before":
config[ATTR_STARTUP] = AddonStartup.SERVICES.value
elif value == "after":
config[ATTR_STARTUP] = AddonStartup.APPLICATION.value
# UART 2021-01-20
if "auto_uart" in config:
if protocol:
_LOGGER.warning(
"Add-on config 'auto_uart' is deprecated, use 'uart'. Please report this to the maintainer of %s",
name,
)
config[ATTR_UART] = config.pop("auto_uart")
# Device 2021-01-20
if ATTR_DEVICES in config and any(":" in line for line in config[ATTR_DEVICES]):
if protocol:
_LOGGER.warning(
"Add-on config 'devices' use a deprecated format, the new format uses a list of paths only. Please report this to the maintainer of %s",
name,
)
config[ATTR_DEVICES] = [line.split(":")[0] for line in config[ATTR_DEVICES]]
# TMPFS 2021-02-01
if ATTR_TMPFS in config and not isinstance(config[ATTR_TMPFS], bool):
if protocol:
_LOGGER.warning(
"Add-on config 'tmpfs' use a deprecated format, new it's only a boolean. Please report this to the maintainer of %s",
name,
)
config[ATTR_TMPFS] = True
return config
return _migrate
# pylint: disable=no-value-for-parameter
SCHEMA_ADDON_CONFIG = vol.Schema(
_SCHEMA_ADDON_CONFIG = vol.Schema(
{
vol.Required(ATTR_NAME): vol.Coerce(str),
vol.Required(ATTR_VERSION): vol.All(version_tag, str),
vol.Required(ATTR_SLUG): vol.Coerce(str),
vol.Required(ATTR_DESCRIPTON): vol.Coerce(str),
vol.Required(ATTR_NAME): str,
vol.Required(ATTR_VERSION): version_tag,
vol.Required(ATTR_SLUG): str,
vol.Required(ATTR_DESCRIPTON): str,
vol.Required(ATTR_ARCH): [vol.In(ARCH_ALL)],
vol.Optional(ATTR_MACHINE): vol.All([vol.Match(RE_MACHINE)], vol.Unique()),
vol.Optional(ATTR_URL): vol.Url(),
vol.Required(ATTR_STARTUP): vol.All(_simple_startup, vol.Coerce(AddonStartup)),
vol.Required(ATTR_BOOT): vol.Coerce(AddonBoot),
vol.Optional(ATTR_STARTUP, default=AddonStartup.APPLICATION): vol.Coerce(
AddonStartup
),
vol.Optional(ATTR_BOOT, default=AddonBoot.AUTO): vol.Coerce(AddonBoot),
vol.Optional(ATTR_INIT, default=True): vol.Boolean(),
vol.Optional(ATTR_ADVANCED, default=False): vol.Boolean(),
vol.Optional(ATTR_STAGE, default=AddonStage.STABLE): vol.Coerce(AddonStage),
vol.Optional(ATTR_PORTS): docker_ports,
vol.Optional(ATTR_PORTS_DESCRIPTION): docker_ports_description,
vol.Optional(ATTR_WATCHDOG): vol.Match(
r"^(?:https?|\[PROTO:\w+\]|tcp):\/\/\[HOST\]:\[PORT:\d+\].*$"
r"^(?:https?|\[PROTO:\w+\]|tcp):\/\/\[HOST\]:(\[PORT:\d+\]|\d+).*$"
),
vol.Optional(ATTR_WEBUI): vol.Match(
r"^(?:https?|\[PROTO:\w+\]):\/\/\[HOST\]:\[PORT:\d+\].*$"
@@ -209,30 +242,31 @@ SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_INGRESS_PORT, default=8099): vol.Any(
network_port, vol.Equal(0)
),
vol.Optional(ATTR_INGRESS_ENTRY): vol.Coerce(str),
vol.Optional(ATTR_PANEL_ICON, default="mdi:puzzle"): vol.Coerce(str),
vol.Optional(ATTR_PANEL_TITLE): vol.Coerce(str),
vol.Optional(ATTR_INGRESS_ENTRY): str,
vol.Optional(ATTR_PANEL_ICON, default="mdi:puzzle"): str,
vol.Optional(ATTR_PANEL_TITLE): str,
vol.Optional(ATTR_PANEL_ADMIN, default=True): vol.Boolean(),
vol.Optional(ATTR_HOMEASSISTANT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_HOMEASSISTANT): vol.Maybe(version_tag),
vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_PID, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_DBUS, default=False): vol.Boolean(),
vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")],
vol.Optional(ATTR_AUTO_UART, default=False): vol.Boolean(),
vol.Optional(ATTR_DEVICES): [str],
vol.Optional(ATTR_UDEV, default=False): vol.Boolean(),
vol.Optional(ATTR_TMPFS): vol.Match(r"^size=(\d)*[kmg](,uid=\d{1,4})?(,rw)?$"),
vol.Optional(ATTR_TMPFS, default=False): vol.Boolean(),
vol.Optional(ATTR_MAP, default=list): [vol.Match(RE_VOLUME)],
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)],
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): str},
vol.Optional(ATTR_PRIVILEGED): [vol.Coerce(Capabilities)],
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
vol.Optional(ATTR_FULL_ACCESS, default=False): vol.Boolean(),
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
vol.Optional(ATTR_VIDEO, default=False): vol.Boolean(),
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
vol.Optional(ATTR_USB, default=False): vol.Boolean(),
vol.Optional(ATTR_UART, default=False): vol.Boolean(),
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
vol.Optional(ATTR_KERNEL_MODULES, default=False): vol.Boolean(),
vol.Optional(ATTR_REALTIME, default=False): vol.Boolean(),
vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(),
vol.Optional(ATTR_HASSIO_ROLE, default=ROLE_DEFAULT): vol.In(ROLE_ALL),
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),
@@ -242,32 +276,26 @@ SCHEMA_ADDON_CONFIG = vol.Schema(
vol.Optional(ATTR_AUTH_API, default=False): vol.Boolean(),
vol.Optional(ATTR_SERVICES): [vol.Match(RE_SERVICE)],
vol.Optional(ATTR_DISCOVERY): [valid_discovery_service],
vol.Optional(ATTR_SNAPSHOT_EXCLUDE): [vol.Coerce(str)],
vol.Required(ATTR_OPTIONS): dict,
vol.Required(ATTR_SCHEMA): vol.Any(
vol.Optional(ATTR_SNAPSHOT_EXCLUDE): [str],
vol.Optional(ATTR_OPTIONS, default={}): dict,
vol.Optional(ATTR_SCHEMA, default={}): vol.Any(
vol.Schema(
{
vol.Coerce(str): vol.Any(
str: vol.Any(
SCHEMA_ELEMENT,
[
vol.Any(
SCHEMA_ELEMENT,
{
vol.Coerce(str): vol.Any(
SCHEMA_ELEMENT, [SCHEMA_ELEMENT]
)
},
{str: vol.Any(SCHEMA_ELEMENT, [SCHEMA_ELEMENT])},
)
],
vol.Schema(
{vol.Coerce(str): vol.Any(SCHEMA_ELEMENT, [SCHEMA_ELEMENT])}
),
vol.Schema({str: vol.Any(SCHEMA_ELEMENT, [SCHEMA_ELEMENT])}),
)
}
),
False,
),
vol.Optional(ATTR_IMAGE): vol.Match(RE_DOCKER_IMAGE),
vol.Optional(ATTR_IMAGE): docker_image,
vol.Optional(ATTR_TIMEOUT, default=10): vol.All(
vol.Coerce(int), vol.Range(min=10, max=300)
),
@@ -275,6 +303,10 @@ SCHEMA_ADDON_CONFIG = vol.Schema(
extra=vol.REMOVE_EXTRA,
)
SCHEMA_ADDON_CONFIG = vol.All(
_migrate_addon_config(True), _warn_addon_config, _SCHEMA_ADDON_CONFIG
)
# pylint: disable=no-value-for-parameter
SCHEMA_BUILD_CONFIG = vol.Schema(
@@ -290,23 +322,38 @@ SCHEMA_BUILD_CONFIG = vol.Schema(
extra=vol.REMOVE_EXTRA,
)
SCHEMA_TRANSLATION_CONFIGURATION = vol.Schema(
{
vol.Required(ATTR_NAME): str,
vol.Optional(ATTR_DESCRIPTON): vol.Maybe(str),
},
extra=vol.REMOVE_EXTRA,
)
SCHEMA_ADDON_TRANSLATIONS = vol.Schema(
{
vol.Optional(ATTR_CONFIGURATION): {str: SCHEMA_TRANSLATION_CONFIGURATION},
vol.Optional(ATTR_NETWORK): {str: str},
},
extra=vol.REMOVE_EXTRA,
)
# pylint: disable=no-value-for-parameter
SCHEMA_ADDON_USER = vol.Schema(
{
vol.Required(ATTR_VERSION): vol.Coerce(str),
vol.Optional(ATTR_IMAGE): vol.Coerce(str),
vol.Required(ATTR_VERSION): version_tag,
vol.Optional(ATTR_IMAGE): docker_image,
vol.Optional(ATTR_UUID, default=lambda: uuid.uuid4().hex): uuid_match,
vol.Optional(ATTR_ACCESS_TOKEN): token,
vol.Optional(ATTR_INGRESS_TOKEN, default=secrets.token_urlsafe): vol.Coerce(
str
),
vol.Optional(ATTR_INGRESS_TOKEN, default=secrets.token_urlsafe): str,
vol.Optional(ATTR_OPTIONS, default=dict): dict,
vol.Optional(ATTR_AUTO_UPDATE, default=False): vol.Boolean(),
vol.Optional(ATTR_BOOT): vol.Coerce(AddonBoot),
vol.Optional(ATTR_NETWORK): docker_ports,
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_AUDIO_OUTPUT): vol.Maybe(str),
vol.Optional(ATTR_AUDIO_INPUT): vol.Maybe(str),
vol.Optional(ATTR_PROTECTED, default=True): vol.Boolean(),
vol.Optional(ATTR_INGRESS_PANEL, default=False): vol.Boolean(),
vol.Optional(ATTR_WATCHDOG, default=False): vol.Boolean(),
@@ -314,20 +361,26 @@ SCHEMA_ADDON_USER = vol.Schema(
extra=vol.REMOVE_EXTRA,
)
SCHEMA_ADDON_SYSTEM = SCHEMA_ADDON_CONFIG.extend(
{
vol.Required(ATTR_LOCATON): vol.Coerce(str),
vol.Required(ATTR_REPOSITORY): vol.Coerce(str),
}
SCHEMA_ADDON_SYSTEM = vol.All(
_migrate_addon_config(),
_SCHEMA_ADDON_CONFIG.extend(
{
vol.Required(ATTR_LOCATON): str,
vol.Required(ATTR_REPOSITORY): str,
vol.Required(ATTR_TRANSLATIONS, default=dict): {
str: SCHEMA_ADDON_TRANSLATIONS
},
}
),
)
SCHEMA_ADDONS_FILE = vol.Schema(
{
vol.Optional(ATTR_USER, default=dict): {vol.Coerce(str): SCHEMA_ADDON_USER},
vol.Optional(ATTR_SYSTEM, default=dict): {vol.Coerce(str): SCHEMA_ADDON_SYSTEM},
}
vol.Optional(ATTR_USER, default=dict): {str: SCHEMA_ADDON_USER},
vol.Optional(ATTR_SYSTEM, default=dict): {str: SCHEMA_ADDON_SYSTEM},
},
extra=vol.REMOVE_EXTRA,
)
@@ -336,263 +389,7 @@ SCHEMA_ADDON_SNAPSHOT = vol.Schema(
vol.Required(ATTR_USER): SCHEMA_ADDON_USER,
vol.Required(ATTR_SYSTEM): SCHEMA_ADDON_SYSTEM,
vol.Required(ATTR_STATE): vol.Coerce(AddonState),
vol.Required(ATTR_VERSION): vol.Coerce(str),
vol.Required(ATTR_VERSION): version_tag,
},
extra=vol.REMOVE_EXTRA,
)
def validate_options(coresys: CoreSys, raw_schema: Dict[str, Any]):
"""Validate schema."""
def validate(struct):
"""Create schema validator for add-ons options."""
options = {}
# read options
for key, value in struct.items():
# Ignore unknown options / remove from list
if key not in raw_schema:
_LOGGER.warning("Unknown options %s", key)
continue
typ = raw_schema[key]
try:
if isinstance(typ, list):
# nested value list
options[key] = _nested_validate_list(coresys, typ[0], value, key)
elif isinstance(typ, dict):
# nested value dict
options[key] = _nested_validate_dict(coresys, typ, value, key)
else:
# normal value
options[key] = _single_validate(coresys, typ, value, key)
except (IndexError, KeyError):
raise vol.Invalid(f"Type error for {key}") from None
_check_missing_options(raw_schema, options, "root")
return options
return validate
# pylint: disable=no-value-for-parameter
# pylint: disable=inconsistent-return-statements
def _single_validate(coresys: CoreSys, typ: str, value: Any, key: str):
"""Validate a single element."""
# if required argument
if value is None:
raise vol.Invalid(f"Missing required option '{key}'") from None
# Lookup secret
if str(value).startswith("!secret "):
secret: str = value.partition(" ")[2]
value = coresys.homeassistant.secrets.get(secret)
if value is None:
raise vol.Invalid(f"Unknown secret {secret}") from None
# parse extend data from type
match = RE_SCHEMA_ELEMENT.match(typ)
if not match:
raise vol.Invalid(f"Unknown type {typ}") from None
# prepare range
range_args = {}
for group_name in _SCHEMA_LENGTH_PARTS:
group_value = match.group(group_name)
if group_value:
range_args[group_name[2:]] = float(group_value)
if typ.startswith(V_STR) or typ.startswith(V_PASSWORD):
return vol.All(str(value), vol.Range(**range_args))(value)
elif typ.startswith(V_INT):
return vol.All(vol.Coerce(int), vol.Range(**range_args))(value)
elif typ.startswith(V_FLOAT):
return vol.All(vol.Coerce(float), vol.Range(**range_args))(value)
elif typ.startswith(V_BOOL):
return vol.Boolean()(value)
elif typ.startswith(V_EMAIL):
return vol.Email()(value)
elif typ.startswith(V_URL):
return vol.Url()(value)
elif typ.startswith(V_PORT):
return network_port(value)
elif typ.startswith(V_MATCH):
return vol.Match(match.group("match"))(str(value))
elif typ.startswith(V_LIST):
return vol.In(match.group("list").split("|"))(str(value))
raise vol.Invalid(f"Fatal error for {key} type {typ}") from None
def _nested_validate_list(coresys, typ, data_list, key):
"""Validate nested items."""
options = []
# Make sure it is a list
if not isinstance(data_list, list):
raise vol.Invalid(f"Invalid list for {key}") from None
# Process list
for element in data_list:
# Nested?
if isinstance(typ, dict):
c_options = _nested_validate_dict(coresys, typ, element, key)
options.append(c_options)
else:
options.append(_single_validate(coresys, typ, element, key))
return options
def _nested_validate_dict(coresys, typ, data_dict, key):
"""Validate nested items."""
options = {}
# Make sure it is a dict
if not isinstance(data_dict, dict):
raise vol.Invalid(f"Invalid dict for {key}") from None
# Process dict
for c_key, c_value in data_dict.items():
# Ignore unknown options / remove from list
if c_key not in typ:
_LOGGER.warning("Unknown options %s", c_key)
continue
# Nested?
if isinstance(typ[c_key], list):
options[c_key] = _nested_validate_list(
coresys, typ[c_key][0], c_value, c_key
)
else:
options[c_key] = _single_validate(coresys, typ[c_key], c_value, c_key)
_check_missing_options(typ, options, key)
return options
def _check_missing_options(origin, exists, root):
"""Check if all options are exists."""
missing = set(origin) - set(exists)
for miss_opt in missing:
if isinstance(origin[miss_opt], str) and origin[miss_opt].endswith("?"):
continue
raise vol.Invalid(f"Missing option {miss_opt} in {root}") from None
def schema_ui_options(raw_schema: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate UI schema."""
ui_schema: List[Dict[str, Any]] = []
# read options
for key, value in raw_schema.items():
if isinstance(value, list):
# nested value list
_nested_ui_list(ui_schema, value, key)
elif isinstance(value, dict):
# nested value dict
_nested_ui_dict(ui_schema, value, key)
else:
# normal value
_single_ui_option(ui_schema, value, key)
return ui_schema
def _single_ui_option(
ui_schema: List[Dict[str, Any]], value: str, key: str, multiple: bool = False
) -> None:
"""Validate a single element."""
ui_node: Dict[str, Union[str, bool, float, List[str]]] = {"name": key}
# If multiple
if multiple:
ui_node["multiple"] = True
# Parse extend data from type
match = RE_SCHEMA_ELEMENT.match(value)
if not match:
return
# Prepare range
for group_name in _SCHEMA_LENGTH_PARTS:
group_value = match.group(group_name)
if not group_value:
continue
if group_name[2:] == "min":
ui_node["lengthMin"] = float(group_value)
elif group_name[2:] == "max":
ui_node["lengthMax"] = float(group_value)
# If required
if value.endswith("?"):
ui_node["optional"] = True
else:
ui_node["required"] = True
# Data types
if value.startswith(V_STR):
ui_node["type"] = "string"
elif value.startswith(V_PASSWORD):
ui_node["type"] = "string"
ui_node["format"] = "password"
elif value.startswith(V_INT):
ui_node["type"] = "integer"
elif value.startswith(V_FLOAT):
ui_node["type"] = "float"
elif value.startswith(V_BOOL):
ui_node["type"] = "boolean"
elif value.startswith(V_EMAIL):
ui_node["type"] = "string"
ui_node["format"] = "email"
elif value.startswith(V_URL):
ui_node["type"] = "string"
ui_node["format"] = "url"
elif value.startswith(V_PORT):
ui_node["type"] = "integer"
elif value.startswith(V_MATCH):
ui_node["type"] = "string"
elif value.startswith(V_LIST):
ui_node["type"] = "select"
ui_node["options"] = match.group("list").split("|")
ui_schema.append(ui_node)
def _nested_ui_list(
ui_schema: List[Dict[str, Any]], option_list: List[Any], key: str
) -> None:
"""UI nested list items."""
try:
element = option_list[0]
except IndexError:
_LOGGER.error("Invalid schema %s", key)
return
if isinstance(element, dict):
_nested_ui_dict(ui_schema, element, key, multiple=True)
else:
_single_ui_option(ui_schema, element, key, multiple=True)
def _nested_ui_dict(
ui_schema: List[Dict[str, Any]],
option_dict: Dict[str, Any],
key: str,
multiple: bool = False,
) -> None:
"""UI nested dict items."""
ui_node = {"name": key, "type": "schema", "optional": True, "multiple": multiple}
nested_schema = []
for c_key, c_value in option_dict.items():
# Nested?
if isinstance(c_value, list):
_nested_ui_list(nested_schema, c_value, c_key)
else:
_single_ui_option(nested_schema, c_value, c_key)
ui_node["schema"] = nested_schema
ui_schema.append(ui_node)

View File

@@ -18,6 +18,7 @@ from .homeassistant import APIHomeAssistant
from .host import APIHost
from .info import APIInfo
from .ingress import APIIngress
from .jobs import APIJobs
from .multicast import APIMulticast
from .network import APINetwork
from .observer import APIObserver
@@ -27,6 +28,7 @@ from .resolution import APIResoulution
from .security import SecurityMiddleware
from .services import APIServices
from .snapshots import APISnapshots
from .store import APIStore
from .supervisor import APISupervisor
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -72,12 +74,14 @@ class RestAPI(CoreSysAttributes):
self._register_network()
self._register_observer()
self._register_os()
self._register_jobs()
self._register_panel()
self._register_proxy()
self._register_resolution()
self._register_services()
self._register_snapshots()
self._register_supervisor()
self._register_store()
await self.start()
@@ -110,6 +114,7 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/network/info", api_network.info),
web.post("/network/reload", api_network.reload),
web.get(
"/network/interface/{interface}/info", api_network.interface_info
),
@@ -141,6 +146,19 @@ class RestAPI(CoreSysAttributes):
]
)
def _register_jobs(self) -> None:
"""Register Jobs functions."""
api_jobs = APIJobs()
api_jobs.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/jobs/info", api_jobs.info),
web.post("/jobs/options", api_jobs.options),
web.post("/jobs/reset", api_jobs.reset),
]
)
def _register_cli(self) -> None:
"""Register HA cli functions."""
api_cli = APICli()
@@ -222,6 +240,7 @@ class RestAPI(CoreSysAttributes):
"/resolution/issue/{issue}",
api_resolution.dismiss_issue,
),
web.post("/resolution/healthcheck", api_resolution.healthcheck),
]
)
@@ -232,6 +251,7 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/auth", api_auth.auth),
web.post("/auth", api_auth.auth),
web.post("/auth/reset", api_auth.reset),
web.delete("/auth/cache", api_auth.cache),
@@ -321,16 +341,15 @@ class RestAPI(CoreSysAttributes):
web.get("/addons", api_addons.list),
web.post("/addons/reload", api_addons.reload),
web.get("/addons/{addon}/info", api_addons.info),
web.post("/addons/{addon}/install", api_addons.install),
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
web.post("/addons/{addon}/start", api_addons.start),
web.post("/addons/{addon}/stop", api_addons.stop),
web.post("/addons/{addon}/restart", api_addons.restart),
web.post("/addons/{addon}/update", api_addons.update),
web.post("/addons/{addon}/options", api_addons.options),
web.post(
"/addons/{addon}/options/validate", api_addons.options_validate
),
web.get("/addons/{addon}/options/config", api_addons.options_config),
web.post("/addons/{addon}/rebuild", api_addons.rebuild),
web.get("/addons/{addon}/logs", api_addons.logs),
web.get("/addons/{addon}/icon", api_addons.icon),
@@ -451,6 +470,46 @@ class RestAPI(CoreSysAttributes):
]
)
def _register_store(self) -> None:
"""Register store endpoints."""
api_store = APIStore()
api_store.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/store", api_store.store_info),
web.get("/store/addons", api_store.addons_list),
web.get("/store/addons/{addon}", api_store.addons_addon_info),
web.get("/store/addons/{addon}/{version}", api_store.addons_addon_info),
web.post(
"/store/addons/{addon}/install", api_store.addons_addon_install
),
web.post(
"/store/addons/{addon}/install/{version}",
api_store.addons_addon_install,
),
web.post("/store/addons/{addon}/update", api_store.addons_addon_update),
web.post(
"/store/addons/{addon}/update/{version}",
api_store.addons_addon_update,
),
web.post("/store/reload", api_store.reload),
web.get("/store/repositories", api_store.repositories_list),
web.get(
"/store/repositories/{repository}",
api_store.repositories_repository_info,
),
]
)
# Reroute from legacy
self.webapp.add_routes(
[
web.post("/addons/{addon}/install", api_store.addons_addon_install),
web.post("/addons/{addon}/update", api_store.addons_addon_update),
]
)
def _register_panel(self) -> None:
"""Register panel for Home Assistant."""
panel_dir = Path(__file__).parent.joinpath("panel")

View File

@@ -82,6 +82,8 @@ from ..const import (
ATTR_STARTUP,
ATTR_STATE,
ATTR_STDIN,
ATTR_TRANSLATIONS,
ATTR_UART,
ATTR_UDEV,
ATTR_UPDATE_AVAILABLE,
ATTR_URL,
@@ -101,7 +103,7 @@ from ..const import (
)
from ..coresys import CoreSysAttributes
from ..docker.stats import DockerStats
from ..exceptions import APIError
from ..exceptions import APIError, APIForbidden
from ..validate import docker_ports
from .utils import api_process, api_process_raw, api_validate
@@ -170,6 +172,7 @@ class APIAddons(CoreSysAttributes):
ATTR_INSTALLED: addon.is_installed,
ATTR_AVAILABLE: addon.available,
ATTR_DETACHED: addon.is_detached,
ATTR_HOMEASSISTANT: addon.homeassistant_version,
ATTR_REPOSITORY: addon.repository,
ATTR_BUILD: addon.need_build,
ATTR_URL: addon.url,
@@ -237,7 +240,7 @@ class APIAddons(CoreSysAttributes):
ATTR_PRIVILEGED: addon.privileged,
ATTR_FULL_ACCESS: addon.with_full_access,
ATTR_APPARMOR: addon.apparmor,
ATTR_DEVICES: _pretty_devices(addon),
ATTR_DEVICES: addon.static_devices,
ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo,
ATTR_CHANGELOG: addon.with_changelog,
@@ -250,6 +253,7 @@ class APIAddons(CoreSysAttributes):
ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api,
ATTR_GPIO: addon.with_gpio,
ATTR_USB: addon.with_usb,
ATTR_UART: addon.with_uart,
ATTR_KERNEL_MODULES: addon.with_kernel_modules,
ATTR_DEVICETREE: addon.with_devicetree,
ATTR_UDEV: addon.with_udev,
@@ -262,6 +266,7 @@ class APIAddons(CoreSysAttributes):
ATTR_SERVICES: _pretty_services(addon),
ATTR_DISCOVERY: addon.discovery,
ATTR_IP_ADDRESS: None,
ATTR_TRANSLATIONS: addon.translations,
ATTR_INGRESS: addon.with_ingress,
ATTR_INGRESS_ENTRY: None,
ATTR_INGRESS_URL: None,
@@ -286,6 +291,8 @@ class APIAddons(CoreSysAttributes):
ATTR_VERSION: addon.version,
ATTR_UPDATE_AVAILABLE: addon.need_update,
ATTR_WATCHDOG: addon.watchdog,
ATTR_DEVICES: addon.static_devices
+ [device.path for device in addon.devices],
}
)
@@ -339,6 +346,19 @@ class APIAddons(CoreSysAttributes):
return data
@api_process
async def options_config(self, request: web.Request) -> None:
"""Validate user options for add-on."""
slug: str = request.match_info.get("addon")
if slug != "self":
raise APIForbidden("This can be only read by the Add-on itself!")
addon = self._extract_addon_installed(request)
try:
return addon.schema(addon.options)
except vol.Invalid:
raise APIError("Invalid configuration data for the add-on") from None
@api_process
async def security(self, request: web.Request) -> None:
"""Store security options for add-on."""
@@ -369,12 +389,6 @@ class APIAddons(CoreSysAttributes):
ATTR_BLK_WRITE: stats.blk_write,
}
@api_process
def install(self, request: web.Request) -> Awaitable[None]:
"""Install add-on."""
addon = self._extract_addon(request)
return asyncio.shield(addon.install())
@api_process
def uninstall(self, request: web.Request) -> Awaitable[None]:
"""Uninstall add-on."""
@@ -393,12 +407,6 @@ class APIAddons(CoreSysAttributes):
addon = self._extract_addon_installed(request)
return asyncio.shield(addon.stop())
@api_process
def update(self, request: web.Request) -> Awaitable[None]:
"""Update add-on."""
addon: Addon = self._extract_addon_installed(request)
return asyncio.shield(addon.update())
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart add-on."""
@@ -468,14 +476,6 @@ class APIAddons(CoreSysAttributes):
await asyncio.shield(addon.write_stdin(data))
def _pretty_devices(addon: AnyAddon) -> List[str]:
"""Return a simplified device list."""
dev_list = addon.devices
if not dev_list:
return []
return [row.split(":")[0] for row in dev_list]
def _pretty_services(addon: AnyAddon) -> List[str]:
"""Return a simplified services role list."""
return [f"{name}:{access}" for name, access in addon.services_role.items()]

View File

@@ -29,6 +29,10 @@ SCHEMA_PASSWORD_RESET = vol.Schema(
}
)
REALM_HEADER: Dict[str, str] = {
WWW_AUTHENTICATE: 'Basic realm="Home Assistant Authentication"'
}
class APIAuth(CoreSysAttributes):
"""Handle RESTful API for auth functions."""
@@ -63,7 +67,9 @@ class APIAuth(CoreSysAttributes):
# BasicAuth
if AUTHORIZATION in request.headers:
return await self._process_basic(request, addon)
if not await self._process_basic(request, addon):
raise HTTPUnauthorized(headers=REALM_HEADER)
return True
# Json
if request.headers.get(CONTENT_TYPE) == CONTENT_TYPE_JSON:
@@ -75,9 +81,7 @@ class APIAuth(CoreSysAttributes):
data = await request.post()
return await self._process_dict(request, addon, data)
raise HTTPUnauthorized(
headers={WWW_AUTHENTICATE: 'Basic realm="Home Assistant Authentication"'}
)
raise HTTPUnauthorized(headers=REALM_HEADER)
@api_process
async def reset(self, request: web.Request) -> None:

View File

@@ -1,50 +1,46 @@
"""Init file for Supervisor hardware RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict, List
from typing import Any, Awaitable, Dict
from aiohttp import web
from ..const import (
ATTR_AUDIO,
ATTR_DISK,
ATTR_GPIO,
ATTR_INPUT,
ATTR_OUTPUT,
ATTR_SERIAL,
ATTR_USB,
)
from ..const import ATTR_AUDIO, ATTR_DEVICES, ATTR_INPUT, ATTR_NAME, ATTR_OUTPUT
from ..coresys import CoreSysAttributes
from ..hardware.const import (
ATTR_ATTRIBUTES,
ATTR_BY_ID,
ATTR_DEV_PATH,
ATTR_SUBSYSTEM,
ATTR_SYSFS,
)
from ..hardware.data import Device
from .utils import api_process
_LOGGER: logging.Logger = logging.getLogger(__name__)
def device_struct(device: Device) -> Dict[str, Any]:
"""Return a dict with information of a interface to be used in th API."""
return {
ATTR_NAME: device.name,
ATTR_SYSFS: device.sysfs,
ATTR_DEV_PATH: device.path,
ATTR_SUBSYSTEM: device.subsystem,
ATTR_BY_ID: device.by_id,
ATTR_ATTRIBUTES: device.attributes,
}
class APIHardware(CoreSysAttributes):
"""Handle RESTful API for hardware functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Show hardware info."""
serial: List[str] = []
# Create Serial list with device links
for device in self.sys_hardware.serial_devices:
serial.append(device.path.as_posix())
for link in device.links:
serial.append(link.as_posix())
return {
ATTR_SERIAL: serial,
ATTR_INPUT: list(self.sys_hardware.input_devices),
ATTR_DISK: [
device.path.as_posix() for device in self.sys_hardware.disk_devices
],
ATTR_GPIO: list(self.sys_hardware.gpio_devices),
ATTR_USB: [
device.path.as_posix() for device in self.sys_hardware.usb_devices
],
ATTR_AUDIO: self.sys_hardware.audio_devices,
ATTR_DEVICES: [
device_struct(device) for device in self.sys_hardware.devices
]
}
@api_process
@@ -64,6 +60,6 @@ class APIHardware(CoreSysAttributes):
}
@api_process
def trigger(self, request: web.Request) -> Awaitable[None]:
async def trigger(self, request: web.Request) -> Awaitable[None]:
"""Trigger a udev device reload."""
return asyncio.shield(self.sys_hardware.udev_trigger())
_LOGGER.debug("Ignoring DEPRECATED hardware trigger function call.")

View File

@@ -11,6 +11,7 @@ from ..const import (
ATTR_DEPLOYMENT,
ATTR_DESCRIPTON,
ATTR_DISK_FREE,
ATTR_DISK_LIFE_TIME,
ATTR_DISK_TOTAL,
ATTR_DISK_USED,
ATTR_FEATURES,
@@ -43,6 +44,7 @@ class APIHost(CoreSysAttributes):
ATTR_DISK_FREE: self.sys_host.info.free_space,
ATTR_DISK_TOTAL: self.sys_host.info.total_space,
ATTR_DISK_USED: self.sys_host.info.used_space,
ATTR_DISK_LIFE_TIME: self.sys_host.info.disk_life_time,
ATTR_FEATURES: self.sys_host.features,
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_KERNEL: self.sys_host.info.kernel,

View File

@@ -15,6 +15,7 @@ from ..const import (
ATTR_LOGGING,
ATTR_MACHINE,
ATTR_OPERATING_SYSTEM,
ATTR_STATE,
ATTR_SUPERVISOR,
ATTR_SUPPORTED,
ATTR_SUPPORTED_ARCH,
@@ -42,6 +43,7 @@ class APIInfo(CoreSysAttributes):
ATTR_FEATURES: self.sys_host.features,
ATTR_MACHINE: self.sys_machine,
ATTR_ARCH: self.sys_arch.default,
ATTR_STATE: self.sys_core.state,
ATTR_SUPPORTED_ARCH: self.sys_arch.supported,
ATTR_SUPPORTED: self.sys_core.supported,
ATTR_CHANNEL: self.sys_updater.channel,

42
supervisor/api/jobs.py Normal file
View File

@@ -0,0 +1,42 @@
"""Init file for Supervisor Jobs RESTful API."""
import logging
from typing import Any, Dict
from aiohttp import web
import voluptuous as vol
from ..coresys import CoreSysAttributes
from ..jobs.const import ATTR_IGNORE_CONDITIONS, JobCondition
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_OPTIONS = vol.Schema(
{vol.Optional(ATTR_IGNORE_CONDITIONS): [vol.Coerce(JobCondition)]}
)
class APIJobs(CoreSysAttributes):
"""Handle RESTful API for OS functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return JobManager information."""
return {
ATTR_IGNORE_CONDITIONS: self.sys_jobs.ignore_conditions,
}
@api_process
async def options(self, request: web.Request) -> None:
"""Set options for JobManager."""
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_IGNORE_CONDITIONS in body:
self.sys_jobs.ignore_conditions = body[ATTR_IGNORE_CONDITIONS]
self.sys_jobs.save_data()
@api_process
async def reset(self, request: web.Request) -> None:
"""Reset options for JobManager."""
self.sys_jobs.reset_data()

View File

@@ -1,7 +1,7 @@
"""REST API for network."""
import asyncio
from ipaddress import ip_address, ip_interface
from typing import Any, Dict
from typing import Any, Awaitable, Dict
from aiohttp import web
import attr
@@ -18,6 +18,7 @@ from ..const import (
ATTR_FREQUENCY,
ATTR_GATEWAY,
ATTR_HOST_INTERNET,
ATTR_ID,
ATTR_INTERFACE,
ATTR_INTERFACES,
ATTR_IPV4,
@@ -26,6 +27,7 @@ from ..const import (
ATTR_METHOD,
ATTR_MODE,
ATTR_NAMESERVERS,
ATTR_PARENT,
ATTR_PRIMARY,
ATTR_PSK,
ATTR_SIGNAL,
@@ -80,7 +82,7 @@ SCHEMA_UPDATE = vol.Schema(
)
def ipconfig_struct(config: IpConfig) -> dict:
def ipconfig_struct(config: IpConfig) -> Dict[str, Any]:
"""Return a dict with information about ip configuration."""
return {
ATTR_METHOD: config.method,
@@ -90,7 +92,7 @@ def ipconfig_struct(config: IpConfig) -> dict:
}
def wifi_struct(config: WifiConfig) -> dict:
def wifi_struct(config: WifiConfig) -> Dict[str, Any]:
"""Return a dict with information about wifi configuration."""
return {
ATTR_MODE: config.mode,
@@ -100,7 +102,15 @@ def wifi_struct(config: WifiConfig) -> dict:
}
def interface_struct(interface: Interface) -> dict:
def vlan_struct(config: VlanConfig) -> Dict[str, Any]:
"""Return a dict with information about VLAN configuration."""
return {
ATTR_ID: config.id,
ATTR_PARENT: config.interface,
}
def interface_struct(interface: Interface) -> Dict[str, Any]:
"""Return a dict with information of a interface to be used in th API."""
return {
ATTR_INTERFACE: interface.name,
@@ -111,11 +121,11 @@ def interface_struct(interface: Interface) -> dict:
ATTR_IPV4: ipconfig_struct(interface.ipv4) if interface.ipv4 else None,
ATTR_IPV6: ipconfig_struct(interface.ipv6) if interface.ipv6 else None,
ATTR_WIFI: wifi_struct(interface.wifi) if interface.wifi else None,
ATTR_VLAN: wifi_struct(interface.vlan) if interface.vlan else None,
ATTR_VLAN: vlan_struct(interface.vlan) if interface.vlan else None,
}
def accesspoint_struct(accesspoint: AccessPoint) -> dict:
def accesspoint_struct(accesspoint: AccessPoint) -> Dict[str, Any]:
"""Return a dict for AccessPoint."""
return {
ATTR_MODE: accesspoint.mode,
@@ -145,7 +155,7 @@ class APINetwork(CoreSysAttributes):
except HostNetworkNotFound:
pass
raise APIError(f"Interface {name} does not exsist") from None
raise APIError(f"Interface {name} does not exist") from None
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
@@ -207,6 +217,11 @@ class APINetwork(CoreSysAttributes):
await asyncio.shield(self.sys_host.network.apply_changes(interface))
@api_process
def reload(self, request: web.Request) -> Awaitable[None]:
"""Reload network data."""
return asyncio.shield(self.sys_host.network.update())
@api_process
async def scan_accesspoints(self, request: web.Request) -> Dict[str, Any]:
"""Scan and return a list of available networks."""

View File

@@ -1,9 +1,9 @@
try {
new Function("import('/api/hassio/app/frontend_latest/entrypoint.4ec3f364.js')")();
new Function("import('/api/hassio/app/frontend_latest/entrypoint.c1a28650.js')")();
} catch (err) {
var el = document.createElement('script');
el.src = '/api/hassio/app/frontend_es5/entrypoint.1799405f.js';
el.src = '/api/hassio/app/frontend_es5/entrypoint.54588d7a.js';
document.body.appendChild(el);
}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.0aeb318c1dfa0b946242.js","sources":["webpack://home-assistant-frontend/chunk.0aeb318c1dfa0b946242.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1,2 +0,0 @@
!function(){"use strict";var n,t={14971:function(n,t,e){e(58556);var r,o,i=e(91107),u=e(9902),a=e.n(u),s=e(62173),f={renderMarkdown:function(n,t){var e,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return r||(r=Object.assign({},(0,s.getDefaultWhiteList)(),{"ha-icon":["icon"],"ha-svg-icon":["path"]})),i.allowSvg?(o||(o=Object.assign({},r,{svg:["xmlns","height","width"],path:["transform","stroke","d"],img:["src"]})),e=o):e=r,(0,s.filterXSS)(a()(n,t),{whiteList:e})}};(0,i.Jj)(f)}},e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={exports:{}};return t[n].call(o.exports,o,o.exports,r),o.exports}r.m=t,r.x=function(){r(14971)},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,{a:t}),t},r.d=function(n,t){for(var e in t)r.o(t,e)&&!r.o(n,e)&&Object.defineProperty(n,e,{enumerable:!0,get:t[e]})},r.f={},r.e=function(n){return Promise.all(Object.keys(r.f).reduce((function(t,e){return r.f[e](n,t),t}),[]))},r.u=function(n){return"chunk.d93e72d29a82b1218f4a.js"},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},n=r.x,r.x=function(){return r.e(474).then(n)},r.p="/api/hassio/app/frontend_es5/",function(){var n={971:1};r.f.i=function(t,e){n[t]||importScripts(""+r.u(t))};var t=self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[],e=t.push.bind(t);t.push=function(t){var o=t[0],i=t[1],u=t[2];for(var a in i)r.o(i,a)&&(r.m[a]=i[a]);for(u&&u(r);o.length;)n[o.pop()]=1;e(t)}}(),r.x()}();
//# sourceMappingURL=chunk.0cd3dee90fe9e2ba789d.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.0cd3dee90fe9e2ba789d.js","sources":["webpack://home-assistant-frontend/chunk.0cd3dee90fe9e2ba789d.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.114930542eafd429baaa.js","sources":["webpack://home-assistant-frontend/chunk.114930542eafd429baaa.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.1274df0d4f9b61110840.js","sources":["webpack://home-assistant-frontend/chunk.1274df0d4f9b61110840.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.192eacaff3f9b89ec13e.js","sources":["webpack://home-assistant-frontend/chunk.192eacaff3f9b89ec13e.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.23709353009814f6ec3d.js","sources":["webpack://home-assistant-frontend/chunk.23709353009814f6ec3d.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.3a2a2f6b4ddd0c4883f8.js","sources":["webpack://home-assistant-frontend/chunk.3a2a2f6b4ddd0c4883f8.js"],"mappings":";AAAA","sourceRoot":""}

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.3bff0586eed52d338fd7.js","sources":["webpack://home-assistant-frontend/chunk.3bff0586eed52d338fd7.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.3daef259cd4ead95b329.js","sources":["webpack://home-assistant-frontend/chunk.3daef259cd4ead95b329.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.4c51a194fe9fc242f107.js","sources":["webpack://home-assistant-frontend/chunk.4c51a194fe9fc242f107.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.66a403e06c27cd823e0b.js","sources":["webpack://home-assistant-frontend/chunk.66a403e06c27cd823e0b.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.69339833f81fc6a02f8b.js","sources":["webpack://home-assistant-frontend/chunk.69339833f81fc6a02f8b.js"],"mappings":";AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.6f668ed3050b9fdfc6f2.js","sources":["webpack://home-assistant-frontend/chunk.6f668ed3050b9fdfc6f2.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.84c7c01d0e7eaf24fc0c.js","sources":["webpack://home-assistant-frontend/chunk.84c7c01d0e7eaf24fc0c.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.8c95d60c89a57c50576d.js","sources":["webpack://home-assistant-frontend/chunk.8c95d60c89a57c50576d.js"],"mappings":";AAAA","sourceRoot":""}

View File

@@ -0,0 +1,2 @@
(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[914],{92914:function(r,o,a){"use strict";a.r(o),a.d(o,{keymap:function(){return t.$f},EditorView:function(){return t.tk},EditorState:function(){return l.yy},Prec:function(){return l.Wl},tagExtension:function(){return l.kU},defaultKeymap:function(){return p.wQ},lineNumbers:function(){return d.Eu},searchKeymap:function(){return g.Lp},highlightSelectionMatches:function(){return g.sW},history:function(){return u.m8},historyKeymap:function(){return u.f$},langs:function(){return m},tabKeyBindings:function(){return s},theme:function(){return b},highlightStyle:function(){return v}});var e=a(49619),t=a(19753),n=a(11163),c=a(49413),i=a(8987),p=a(86876),l=a(77885),d=a(11254),g=a(72360),u=a(62118),m={jinja2:n.i.define(c.b),yaml:n.i.define(i.r)},s=[{key:"Tab",run:p.at},{key:"Shift-Tab",run:p.xi}],b=t.tk.theme({$:{color:"var(--primary-text-color)",backgroundColor:"var(--code-editor-background-color, var(--card-background-color))","& ::selection":{backgroundColor:"rgba(var(--rgb-primary-color), 0.3)"},height:"var(--code-mirror-height, auto)",maxHeight:"var(--code-mirror-max-height, unset)"},$scroller:{outline:"none"},$content:{caretColor:"var(--secondary-text-color)"},$$focused:{outline:"none"},"$$focused $cursor":{borderLeftColor:"#var(--secondary-text-color)"},"$$focused $selectionBackground, $selectionBackground":{backgroundColor:"rgba(var(--rgb-primary-color), 0.3)"},$panels:{backgroundColor:"var(--primary-background-color)",color:"var(--primary-text-color)"},"$panels.top":{borderBottom:"1px solid var(--divider-color)"},"$panels.bottom":{borderTop:"1px solid var(--divider-color)"},"$panel.search input":{margin:"4px 4px 0"},$button:{border:"1px solid var(--primary-color)",padding:"0px 16px",textTransform:"uppercase",margin:"4px",background:"none",color:"var(--primary-color)",fontFamily:"var(--mdc-typography-button-font-family, var(--mdc-typography-font-family, Roboto, sans-serif))",fontSize:"var(--mdc-typography-button-font-size, 0.875rem)",height:"36px",fontWeight:"var(--mdc-typography-button-font-weight, 500)",borderRadius:"4px",letterSpacing:"var(--mdc-typography-button-letter-spacing, 0.0892857em)"},$textfield:{padding:"4px 0px 5px",borderRadius:"0",fontSize:"16px",color:"var(--primary-text-color)",border:"0",background:"none",fontFamily:"Roboto",borderBottom:"1px solid var(--paper-input-container-color, var(--secondary-text-color))",margin:"4px 4px 0","& ::placeholder":{color:"var(--paper-input-container-color, var(--secondary-text-color))"},"&:focus":{outline:"none",borderBottom:"2px solid var(--primary-color)",paddingBottom:"4px"}},$selectionMatch:{backgroundColor:"rgba(var(--rgb-primary-color), 0.1)"},$searchMatch:{backgroundColor:"rgba(var(--rgb-accent-color), .2)",outline:"1px solid rgba(var(--rgb-accent-color), .4)"},"$searchMatch.selected":{backgroundColor:"rgba(var(--rgb-accent-color), .4)",outline:"1px solid var(--accent-color)"},$gutters:{backgroundColor:"var(--paper-dialog-background-color, var(--primary-background-color))",color:"var(--paper-dialog-color, var(--secondary-text-color))",border:"none",borderRight:"1px solid var(--paper-input-container-color, var(--secondary-text-color))",paddingRight:"1px"},"$$focused $gutters":{borderRight:"2px solid var(--paper-input-container-focus-color, var(--primary-color))",paddingRight:"0"},"$gutterElementags.lineNumber":{color:"inherit"}}),v=e.Qf.define({tag:e.pJ.keyword,color:"var(--codemirror-keyword, #6262FF)"},{tag:[e.pJ.name,e.pJ.deleted,e.pJ.character,e.pJ.propertyName,e.pJ.macroName],color:"var(--codemirror-property, #905)"},{tag:[e.pJ.function(e.pJ.variableName),e.pJ.labelName],color:"var(--codemirror-variable, #07a)"},{tag:[e.pJ.color,e.pJ.constant(e.pJ.name),e.pJ.standard(e.pJ.name)],color:"var(--codemirror-qualifier, #690)"},{tag:[e.pJ.definition(e.pJ.name),e.pJ.separator],color:"var(--codemirror-def, #8DA6CE)"},{tag:[e.pJ.typeName,e.pJ.className,e.pJ.number,e.pJ.changed,e.pJ.annotation,e.pJ.modifier,e.pJ.self,e.pJ.namespace],color:"var(--codemirror-number, #ca7841)"},{tag:[e.pJ.operator,e.pJ.operatorKeyword,e.pJ.url,e.pJ.escape,e.pJ.regexp,e.pJ.link,e.pJ.special(e.pJ.string)],color:"var(--codemirror-operator, #cda869)"},{tag:e.pJ.comment,color:"var(--codemirror-comment, #777)"},{tag:e.pJ.meta,color:"var(--codemirror-meta, var(--primary-text-color))"},{tag:e.pJ.strong,fontWeight:"bold"},{tag:e.pJ.emphasis,fontStyle:"italic"},{tag:e.pJ.link,color:"var(--primary-color)",textDecoration:"underline"},{tag:e.pJ.heading,fontWeight:"bold"},{tag:e.pJ.atom,color:"var(--codemirror-atom, #F90)"},{tag:e.pJ.bool,color:"var(--codemirror-atom, #F90)"},{tag:e.pJ.special(e.pJ.variableName),color:"var(--codemirror-variable-2, #690)"},{tag:e.pJ.processingInstruction,color:"var(--secondary-text-color)"},{tag:e.pJ.string,color:"var(--codemirror-string, #07a)"},{tag:e.pJ.inserted,color:"var(--codemirror-string2, #07a)"},{tag:e.pJ.invalid,color:"var(--error-color)"})}}]);
//# sourceMappingURL=chunk.9f79daafe7d108c4c9cc.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.9f79daafe7d108c4c9cc.js","sources":["webpack://home-assistant-frontend/chunk.9f79daafe7d108c4c9cc.js"],"mappings":"AAAA","sourceRoot":""}

View File

@@ -1,2 +0,0 @@
(self.webpackChunkhome_assistant_frontend=self.webpackChunkhome_assistant_frontend||[]).push([[528],{92914:function(n,e,r){"use strict";r.r(e),r.d(e,{codeMirror:function(){return c},codeMirrorCss:function(){return i}});var t=r(79074),s=r.n(t),o=r(49338),a=(r(22080),r(19393),r(47181));s().commands.save=function(n){(0,a.B)(n.getWrapperElement(),"editor-save")};var c=s(),i=o.Z}}]);
//# sourceMappingURL=chunk.a7915ead0233f6fee305.js.map

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.a7915ead0233f6fee305.js","sources":["webpack://home-assistant-frontend/chunk.a7915ead0233f6fee305.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"file":"chunk.ad46d3b20600ba78423d.js","sources":["webpack://home-assistant-frontend/chunk.ad46d3b20600ba78423d.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.ae740c7fbd846ae0a428.js","sources":["webpack://home-assistant-frontend/chunk.ae740c7fbd846ae0a428.js"],"mappings":"AAAA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"file":"chunk.afa043f3e39764ffdf47.js","sources":["webpack://home-assistant-frontend/chunk.afa043f3e39764ffdf47.js"],"mappings":"AAAA","sourceRoot":""}

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