Compare commits

...

232 Commits
207 ... 231

Author SHA1 Message Date
Pascal Vizeli
e127f23a08 Bump version 231 2020-08-11 09:07:29 +00:00
Pascal Vizeli
2f3a868e42 Merge pull request #1888 from home-assistant/dev
Release 231
2020-08-11 10:56:01 +02:00
Pascal Vizeli
a51b80f456 Tag installation type & more infos (#1887)
* Tag installation type & more infos

* fix black

* Make sure dbus is available for reports

* HassOS warning -> info

* Fix installation type name

* fix correct ADR

* change name

* make message more friendly
2020-08-11 10:52:33 +02:00
Greg Rapp
f27a426879 Allow all addons to access /host/info endpoint (#1885) 2020-08-10 23:45:05 +02:00
Pascal Vizeli
19ca485c28 Allow Core access to dbus for bluetooth (#1883) 2020-08-10 15:18:32 +02:00
Pascal Vizeli
7deed55c2d Make plugin more robust (#1881) 2020-08-10 13:23:50 +02:00
Joakim Sørensen
4c5c6f072c Updates panel to dec1f99 (#1880) 2020-08-10 10:52:41 +02:00
Pascal Vizeli
f174e08ad6 Merge pull request #1879 from home-assistant/dev
Release 230
2020-08-07 22:25:21 +02:00
Pascal Vizeli
2658f95347 Fix sentry logging (#1878)
* Fix sentry logging

* fix level
2020-08-07 22:16:07 +02:00
Pascal Vizeli
311c981d1a Small cleanup to be more robust (#1876) 2020-08-07 21:43:03 +02:00
Pascal Vizeli
d6d3bf0583 Make udev more robust (#1875) 2020-08-07 14:03:55 +02:00
Joakim Sørensen
a1a601a4d3 Update panel to c17ebfd (#1874) 2020-08-07 08:18:41 +02:00
Pascal Vizeli
14776eae76 Fix issues with dev version (#1873) 2020-08-05 18:19:57 +02:00
Pascal Vizeli
bef4034ab8 Replace debuger with debugpy (#1872) 2020-08-05 15:24:53 +02:00
Pascal Vizeli
ad988f2a24 Add diagnostics support (#1870)
* Add diagnostics support

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

* add aditional data

* Fix handling

* Better states

* Fix opt

* Update supervisor/bootstrap.py

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

* Only events on supported systems

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2020-08-05 14:54:03 +02:00
dependabot[bot]
6599ae0ee0 Bump actions/upload-artifact from v2.1.2 to v2.1.3 (#1871)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from v2.1.2 to v2.1.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2.1.2...268d7547644ab8a9d0c1163299e59a1f5d93f39b)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-08-05 11:33:29 +02:00
Martin Hjelmare
4f1ed690cd Add free disk space log on docker install error (#1868)
* Add free disk space info

* Log available space on docker image install error

* Add unit to log message

* Add 404 check and better log message

* Set default path to supervisor data path

* Clean up attribute access

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

* Move free space helper to hardware

* Add hardware test

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-08-03 15:00:07 +02:00
Joakim Sørensen
4ffaee6013 Make a copy of the logfile before rollback (#1867)
* Make a copy of the logfile before rollback

* Review changes and add log about the log file
2020-08-03 14:28:54 +02:00
Joakim Sørensen
e1ce19547e Use "stale" instead of "wontfix" (#1864) 2020-08-03 11:01:36 +02:00
dependabot[bot]
039040b972 Bump actions/upload-artifact from v2.1.1 to v2.1.2 (#1863)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from v2.1.1 to v2.1.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2.1.1...c8879bf5aef7bef66f9b82b197f34c4eeeb1731b)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-08-03 10:08:28 +02:00
dependabot[bot]
7a1af3d346 Bump pytest from 6.0.0 to 6.0.1 (#1862)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.0.0 to 6.0.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.0.0...6.0.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-31 08:14:12 +02:00
dependabot[bot]
1e98774b62 Bump pytest from 5.4.3 to 6.0.0 (#1861)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.3 to 6.0.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/5.4.3...6.0.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-29 20:46:02 +02:00
Pascal Vizeli
4b4d6c6866 Update LICENSE 2020-07-29 14:45:37 +02:00
dependabot[bot]
65ff83d359 Bump actions/upload-artifact from 2.1.0 to v2.1.1 (#1860)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2.1.0 to v2.1.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/2.1.0...5f948bc1f0a251f88bb4c9b1c3dfa6cbd1327dc5)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-28 10:04:50 +02:00
Pascal Vizeli
e509c804ae Add missing debug information (#1859) 2020-07-27 15:37:26 +02:00
Pascal Vizeli
992827e225 use lowlevel file handling, avoid additional buffers (#1858)
* Small tarfile improvments

* use lowlevel file handling, avoid additional buffers

* Fix lowlevel closing

* fix cbc

* Fix name
2020-07-27 15:21:54 +02:00
dependabot[bot]
083e97add8 Bump coverage from 5.2 to 5.2.1 (#1857)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.2 to 5.2.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.2...coverage-5.2.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-27 12:55:38 +02:00
dependabot[bot]
05378d18c0 Bump pyupgrade from 2.7.1 to 2.7.2 (#1856)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.7.1 to 2.7.2.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.7.1...v2.7.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-27 12:55:28 +02:00
dependabot[bot]
3dd465acc9 Bump colorlog from 4.1.0 to 4.2.1 (#1854)
Bumps [colorlog](https://github.com/borntyping/python-colorlog) from 4.1.0 to 4.2.1.
- [Release notes](https://github.com/borntyping/python-colorlog/releases)
- [Commits](https://github.com/borntyping/python-colorlog/compare/v4.1.0...v4.2.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-24 13:21:02 +02:00
Pascal Vizeli
8f6e36f781 Fix rollback timeout on new versions with early stage UI (#1852)
* Fix rollback timeout on new versions with early stage UI

* order code

* Add debug

* order code

* Update supervisor/homeassistant.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Update supervisor/homeassistant.py

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

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
2020-07-23 21:47:49 +02:00
dependabot[bot]
85fe56db57 Bump codecov/codecov-action from v1.0.11 to v1.0.12 (#1851)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.0.11 to v1.0.12.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Commits](https://github.com/codecov/codecov-action/compare/v1.0.11...07127fde53bc3ccd346d47ab2f14c390161ad108)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-23 13:17:59 +02:00
dependabot[bot]
8e07429e47 Bump actions/setup-python from v2 to v2.1.1 (#1848)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from v2 to v2.1.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...0c28554988f6ccf1a4e2818e703679796e41a214)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-21 11:37:50 +02:00
dependabot[bot]
ced6d702b9 Bump cryptography from 2.9.2 to 3.0 (#1847)
Bumps [cryptography](https://github.com/pyca/cryptography) from 2.9.2 to 3.0.
- [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/2.9.2...3.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-21 11:37:25 +02:00
dependabot[bot]
25d7de4dfa Bump codecov/codecov-action from v1.0.10 to v1.0.11 (#1844)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.0.10 to v1.0.11.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Commits](https://github.com/codecov/codecov-action/compare/v1.0.10...6d208f5b527841fb050f92f778e86cb808dacdcb)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-20 11:48:28 +02:00
dependabot[bot]
82754c0dfe Bump pyupgrade from 2.7.0 to 2.7.1 (#1840)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.7.0...v2.7.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-17 13:43:53 +02:00
dependabot[bot]
e604b022ee Bump aiohttp from 3.6.1 to 3.6.2 (#1831)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.6.1 to 3.6.2.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.6.1...v3.6.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-16 15:51:49 +02:00
Pascal Vizeli
6b29022822 Update azure-pipelines-wheels.yml 2020-07-16 15:51:14 +02:00
dependabot[bot]
2e671cc5ee Bump codecov from 2.1.7 to 2.1.8 (#1838)
Bumps [codecov](https://github.com/codecov/codecov-python) from 2.1.7 to 2.1.8.
- [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.7...2.1.8)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-16 09:12:04 +02:00
dependabot[bot]
f25692b98c Bump pytest-timeout from 1.4.1 to 1.4.2 (#1839)
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.4.1...1.4.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-16 09:11:51 +02:00
Franck Nijhof
c4a011b261 Don't reuse venv cache when Python version changes (#1837) 2020-07-15 15:03:53 +02:00
Pascal Vizeli
a935bac20b Bump version to 230 2020-07-15 15:03:01 +02:00
Pascal Vizeli
0a3a98cb42 Merge pull request #1836 from home-assistant/dev
Release 229
2020-07-15 15:02:18 +02:00
Pascal Vizeli
adb39ca93f Support to exclude machine (#1835)
* Support to exclude machine

* add tests
2020-07-15 14:53:44 +02:00
Pascal Vizeli
5fdc340e58 Streamline version (#1834)
* More streamline version handling

* Strict it up

* update tests
2020-07-15 13:05:11 +02:00
Pascal Vizeli
bb64dca6e6 Fix symlink snapshot (#1833)
* Fix symbolic link issue with snapshot

* Add tests

* fix symlink

* add encrypted test

* Modify x
2020-07-14 15:39:03 +02:00
dependabot[bot]
685788bcdf Bump gitpython from 3.1.3 to 3.1.7 (#1830)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.3 to 3.1.7.
- [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.3...3.1.7)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-14 15:12:04 +02:00
dependabot[bot]
e949aa35f3 Bump actions/upload-artifact from v1 to 2.1.0 (#1829)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from v1 to 2.1.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v1...ebad382c0953e8c6b4039e8d30dfd19ee7b2a862)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-14 13:58:21 +02:00
dependabot[bot]
fc80bf0df4 Bump codecov/codecov-action from v1 to v1.0.10 (#1828)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1 to v1.0.10.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Commits](https://github.com/codecov/codecov-action/compare/v1...f3570723ef743f6942b6a480461ed0cd6c0f9baa)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-14 13:55:26 +02:00
dependabot-preview[bot]
bd9740e866 Create Dependabot config file (#1826)
* Create Dependabot config file

* ✏️ Tweak

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2020-07-14 12:02:44 +02:00
Pascal Vizeli
3a260a8fd9 Fix terminal 2020-07-14 10:00:27 +00:00
Paulus Schoutsen
c87e6a5a42 Drop last references 3.7 (#1825) 2020-07-14 02:48:57 +02:00
Pascal Vizeli
8bc3319523 Update release-drafter.yml 2020-07-13 22:27:57 +02:00
Pascal Vizeli
bdfcf1a2df Migrate to python 3.8 (#1824)
* Migrate to python 3.8

* Fix tests on Py38

* cleanup tests

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2020-07-13 22:26:41 +02:00
dependabot-preview[bot]
7f4284f2af Bump pyupgrade from 2.6.2 to 2.7.0 (#1822)
Bumps [pyupgrade](https://github.com/asottile/pyupgrade) from 2.6.2 to 2.7.0.
- [Release notes](https://github.com/asottile/pyupgrade/releases)
- [Commits](https://github.com/asottile/pyupgrade/compare/v2.6.2...v2.7.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-07-13 17:04:13 +02:00
dependabot-preview[bot]
fd69120aa6 Bump coverage from 5.1 to 5.2 (#1820)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.1 to 5.2.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.1...coverage-5.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-07-08 13:39:38 +02:00
dependabot-preview[bot]
5df60b17e8 Bump codecov from 2.1.0 to 2.1.7 (#1817)
Bumps [codecov](https://github.com/codecov/codecov-python) from 2.1.0 to 2.1.7.
- [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/commits/v2.1.7)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-07-07 11:32:50 +02:00
Joakim Sørensen
cb835b5ae6 Update frontend to a674ce3 (#1816) 2020-07-05 21:27:39 +02:00
Franck Nijhof
9eab92513a Add QA/CI to Supervisor (#1814) 2020-07-05 20:20:29 +02:00
dependabot-preview[bot]
29e8f50ab8 Bump docker from 4.2.1 to 4.2.2 (#1809)
Bumps [docker](https://github.com/docker/docker-py) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.2.1...4.2.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-07-03 11:52:08 +02:00
Sean Mooney
aa0496b236 Update Issue Template (#1812)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2020-07-02 15:09:50 -07:00
Joakim Sørensen
06e9cec21a Update frontend panel to 750e7b (#1811)
* Update frontend to 750e7b1

* Remove files

* Fix cleanup in frontend update script
2020-07-02 19:35:43 +02:00
Pascal Vizeli
0fe27088df add pylance 2020-07-01 09:29:58 +00:00
Pascal Vizeli
54d226116d Bump version to 229 2020-06-28 11:29:18 +02:00
Pascal Vizeli
4b37e30680 Merge pull request #1804 from home-assistant/dev
Release 228
2020-06-28 11:28:10 +02:00
Pascal Vizeli
7c5f710deb Slowdown snapshots to make it faster on slow IO (#1803)
* Slowdown snapshots to make it faster on slow IO

* Fix error handling

* fix lint
2020-06-28 10:58:13 +02:00
Paulus Schoutsen
5a3ebaf683 Remove old panel files (#1802) 2020-06-28 10:48:04 +02:00
Pascal Vizeli
233da0e48f defcontainer update 2020-06-27 20:52:59 +00:00
Maximilian Bösing
96380d8d28 When calling atomic_contents_add recursively, pass the Path object instead of the posix path (#1801)
Fixes #1800

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>
2020-06-27 22:44:34 +02:00
Pascal Vizeli
c84a0edf20 Update panel for new style (#1799)
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-06-27 11:56:26 +02:00
Maximilian Bösing
a3cf445c93 Bugfix: No such file or directory: '/data/homeassistant/home-assistant_v2.db-shm' (#1795)
* Do not use `tar_file.add` to recursively add backup folder

As the folders might contain files which are being removed temporarily (e.g. shared memory file of sqlite database), relying on `tar_file.add` becomes problematic as it crashes the whole backup process if a file does not exist anymore.
This becomes annoying, if the file which causes the error should be excluded by the filter.

To workaround this issue, we manually iterating over the files/directories and apply filters before passing the file or directory to the `tar_file.add` method. As per [documentation](https://docs.python.org/3/library/pathlib.html#pure-paths), pure path does not access the file system.

Fixes #779

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Remove unused import

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Applied code review suggestions

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Applied codestyle

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Remove `pathlib` util and move `is_excluded_by_filter` into `tar` utils

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Rename method

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Rename `origin_dir` to `origin_path` and apply `Path` typehint

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Codestyle

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Add comment why we add the directory even if we are iterating over all its items

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Use `atomic_contents_add` from tar utils to archive addon data

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Remove unused function `exclude_filter`

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Remove unsecure default list value

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Some more codestyle

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Lowercase method name `Path.joinpath`

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Fix codestyle and use proper variable

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Add test for `_is_excluded_by_filter`

Signed-off-by: Maximilian Bösing <2189546+boesing@users.noreply.github.com>

* Update addon.py

Co-authored-by: Pascal Vizeli <pascal.vizeli@syshack.ch>
2020-06-26 11:36:49 +02:00
dependabot-preview[bot]
3f31979f66 Bump pytest-timeout from 1.4.0 to 1.4.1 (#1798)
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.4.0...1.4.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-19 15:12:46 +02:00
Franck Nijhof
44416edfd2 Collection of minor changes (#1793)
* Collection of minor changes

* Process smaller comments

* Fix HA version handling

* More type hints

* Review comment from Martin

* Add protection against TypeError in version parsing
2020-06-18 11:41:13 +02:00
Pascal Vizeli
351c45da75 Add the current supervisor version as default (#1791)
* Add the current supervisor version as default

* Fix lint

* Improve new version handling
2020-06-15 14:47:27 +02:00
dependabot-preview[bot]
e27c5dad15 Bump pytest-timeout from 1.3.4 to 1.4.0 (#1792)
Bumps [pytest-timeout](https://github.com/pytest-dev/pytest-timeout) from 1.3.4 to 1.4.0.
- [Release notes](https://github.com/pytest-dev/pytest-timeout/releases)
- [Commits](https://github.com/pytest-dev/pytest-timeout/compare/1.3.4...1.4.0)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-15 14:43:02 +02:00
dependabot-preview[bot]
dc510f22ac Bump flake8 from 3.8.2 to 3.8.3 (#1787)
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.8.2 to 3.8.3.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.8.2...3.8.3)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-09 14:48:44 +02:00
dependabot-preview[bot]
1b78011f8b Bump pylint from 2.5.2 to 2.5.3 (#1785)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.5.2 to 2.5.3.
- [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.5.2...pylint-2.5.3)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-08 13:28:34 +02:00
Pascal Vizeli
a908828bf4 Bump version to 228 2020-06-04 14:05:43 +02:00
Pascal Vizeli
55b7eb62f6 Merge pull request #1778 from home-assistant/dev
Release 227
2020-06-04 14:05:16 +02:00
Paulus Schoutsen
10e8fcf3b9 Remove complete frontend dir on rebuild and update frontend (#1777) 2020-06-04 08:58:12 +02:00
dependabot-preview[bot]
f1b0c05447 Bump pytest from 5.4.2 to 5.4.3 (#1776)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.2 to 5.4.3.
- [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/5.4.2...5.4.3)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-03 13:31:24 +02:00
dependabot-preview[bot]
de22bd688e Bump docker from 4.2.0 to 4.2.1 (#1775)
Bumps [docker](https://github.com/docker/docker-py) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.2.0...4.2.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-03 13:31:10 +02:00
Franck Nijhof
9fe35b4fb5 Improve type hinting for add-ons (#1769)
* Improve type hinting for add-ons

* Split installed vs AnyAddons extraction
2020-06-03 09:28:02 +02:00
Franck Nijhof
f13d08d37a Fix additional parameter on exception (#1774) 2020-06-02 22:57:47 +02:00
Pascal Vizeli
a0ecb46584 Bump version to 227 2020-06-02 15:36:20 +02:00
Pascal Vizeli
0c57df0c8e Merge pull request #1773 from home-assistant/dev
Release 226
2020-06-02 15:35:11 +02:00
Pascal Vizeli
9c902c5c69 Expose all services/discovery with possible add-ons (#1772) 2020-06-02 15:17:24 +02:00
Pascal Vizeli
af412c3105 Handle new API / Frontend early boot (#1770)
* Handle new API / Frontend early boot

* Adjust part 2

* fix hanging landingpage

* Fix catch error

* Fix watchdog
2020-06-02 14:53:57 +02:00
Franck Nijhof
ec43448163 Make addon model abstract (#1768) 2020-06-02 12:08:03 +02:00
Franck Nijhof
9f7e0ecd55 Docs string and exception message improvements (#1767) 2020-06-02 11:26:33 +02:00
Pascal Vizeli
e50515a17c Slowdown docker stop/start to avoid issue on slow IO (#1763)
* Slowdown docker stop/start to avoid issue on slow IO

* Fix lint

* Address comments

* Fix restore logic & Style

* Fix type

* Slow plugins
2020-06-02 11:26:10 +02:00
dependabot-preview[bot]
7c345db6fe Bump gitpython from 3.1.2 to 3.1.3 (#1764)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.2 to 3.1.3.
- [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.2...3.1.3)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-06-01 15:05:40 +02:00
Michal
51c2268c1e Fix typo in discovery log message (#1761)
typo
2020-05-30 13:37:08 +02:00
Pascal Vizeli
51feca05a5 Bump version to 226 2020-05-28 14:38:31 +02:00
Pascal Vizeli
3889504292 Merge pull request #1758 from home-assistant/dev
Release 255
2020-05-28 14:37:30 +02:00
Pascal Vizeli
7bd6ff374a Fix watchdog & scheduler (#1757)
* Fix watchdog & scheduler

* Update supervisor/misc/scheduler.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Fix callback

* hmm

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2020-05-28 14:25:36 +02:00
Sergey Morozik
44fa34203a Ingress skip incorrect session (#1755)
* ingress skip invalid timestamps

* ingress skip invalid timestamp: comment

* Use lazy string instead of f-string

* skip incorrect timestamp in validate_session
2020-05-28 09:30:15 +02:00
Pascal Vizeli
ff351c7f6d HA landing page retry 30sec (#1756) 2020-05-28 09:27:48 +02:00
Pascal Vizeli
960b00d85a Detect lxc (#1754)
* Detect LXC on health check

* fix lint

* Update supervisor/core.py

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

* fix black

Co-authored-by: Franck Nijhof <git@frenck.dev>
2020-05-26 14:12:19 +02:00
dependabot-preview[bot]
18e3eacd7f Bump flake8 from 3.8.1 to 3.8.2 (#1753)
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.8.1 to 3.8.2.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.8.1...3.8.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 13:22:13 +02:00
dependabot-preview[bot]
f4a1da33c4 Bump pulsectl from 20.5.0 to 20.5.1 (#1752)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 20.5.0 to 20.5.1.
- [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-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-25 13:21:59 +02:00
Franck Nijhof
49de5be44e Collection of type hinting fixes (#1747) 2020-05-23 13:19:53 +02:00
Pascal Vizeli
383657e8ce Bump version 225 2020-05-22 17:25:14 +02:00
Pascal Vizeli
3af970ead6 Merge pull request #1746 from home-assistant/dev
Release 224
2020-05-22 17:23:40 +02:00
Franck Nijhof
6caec79958 Complete typehinting in CoreSys (#1745)
* Complete typehinting in CoreSys

* Improve Addon model abstraction, solving Pylint warning
2020-05-22 17:05:40 +02:00
Franck Nijhof
33bbd92d9b Fix S6 supervisor not listening in finish script (#1741) 2020-05-22 16:42:35 +02:00
Pascal Vizeli
9dba78fbcd Improve version handling (#1744)
* version handling helper

* Improve version handling

* Fix bug
2020-05-22 14:21:47 +02:00
Franck Nijhof
630d85ec78 Use f-strings where possible (#1740) 2020-05-22 13:41:14 +02:00
Franck Nijhof
f0d46e8671 Improve flake8 configuration and pydocstyle fixes (#1742) 2020-05-22 13:38:57 +02:00
Franck Nijhof
db0593f0b2 Fix YAML & JSON styling (#1743) 2020-05-22 13:38:05 +02:00
Franck Nijhof
1d83c0c77a Update isort configuration and sorts imports in codebase (#1739)
* Add known first party to isort configuration

* Run isort on supervisor and tests folder
2020-05-21 13:30:54 +02:00
Pascal Vizeli
5e5fd3a79b Bump version 224 2020-05-21 12:09:15 +02:00
Pascal Vizeli
c61995aab8 Merge pull request #1738 from home-assistant/dev
Release 223
2020-05-21 12:08:36 +02:00
Franck Nijhof
37c393f857 Add mypy cache files to .gitignore (#1737) 2020-05-21 12:07:20 +02:00
Pascal Vizeli
8e043a01c1 Add Docker info & check (#1736)
* Add Docker info & check

* Add checks

* Fix logging

* fix lint
2020-05-21 12:06:27 +02:00
Franck Nijhof
c7b6b2ddb3 Cleanup and speedup pylint (#1735) 2020-05-21 12:01:43 +02:00
Franck Nijhof
522f68bf68 Remove passing in deprecated loop arguments (#1733) 2020-05-21 12:01:21 +02:00
Franck Nijhof
7d4866234f Replace Logger.fatal by Logger.critical (#1734) 2020-05-21 12:00:52 +02:00
Pascal Vizeli
7aa5bcfc7c Update panel for markdown fixes (#1732)
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-05-20 17:51:24 +02:00
dependabot-preview[bot]
04b59f0896 Bump pulsectl from 20.4.3 to 20.5.0 (#1731)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 20.4.3 to 20.5.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-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-20 14:42:23 +02:00
Pascal Vizeli
796f9a203e Rename zwave_mqtt to ozw (#1729) 2020-05-19 16:54:50 +02:00
dependabot-preview[bot]
22c8cda0d7 Bump packaging from 20.3 to 20.4 (#1728)
Bumps [packaging](https://github.com/pypa/packaging) from 20.3 to 20.4.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/20.3...20.4)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-19 16:33:31 +02:00
Klaudiusz Staniek
1cf534ccc5 Fix config version setter (#1716)
Co-authored-by: Klaudiusz Staniek <klstanie@cisco.com>
2020-05-18 11:23:45 +02:00
dependabot-preview[bot]
6d8c821148 Bump flake8 from 3.7.9 to 3.8.1 (#1722)
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.7.9 to 3.8.1.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.7.9...3.8.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-18 10:58:43 +02:00
Martin Hjelmare
264e9665b0 Lint tests during tox (#1721) 2020-05-18 10:06:07 +02:00
Martin Hjelmare
53fa8e48c0 Delint tests (#1720)
* Delint tarfile test

* Delint tests
2020-05-11 20:41:09 +02:00
Martin Hjelmare
e406aa4144 Fix vscode tasks supervisor dir (#1719) 2020-05-11 18:22:01 +02:00
dependabot-preview[bot]
4953ba5077 Bump pytest from 5.4.1 to 5.4.2 (#1717) 2020-05-11 14:02:31 +02:00
Pascal Vizeli
0a97ac0578 Bump version 223 2020-05-08 16:25:34 +02:00
Pascal Vizeli
56af4752f4 Merge pull request #1712 from home-assistant/dev
Release 222
2020-05-08 16:24:18 +02:00
Pascal Vizeli
81413d08ed Prevent boot loop (#1711)
* Prevent boot loop

* sort
2020-05-08 16:13:36 +02:00
Bram Kragten
2bc2a476d9 Bump forntend (#1710) 2020-05-08 13:58:20 +02:00
Pascal Vizeli
4d070a65c6 Bump version 222 2020-05-07 19:16:27 +02:00
Pascal Vizeli
6185fbaf26 Merge pull request #1704 from home-assistant/dev
Fix panel
2020-05-07 19:15:59 +02:00
Pascal Vizeli
698a126b93 Fix panel
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-05-07 17:14:52 +00:00
Pascal Vizeli
acf921f55d Merge pull request #1703 from home-assistant/dev
Release 221
2020-05-07 19:02:31 +02:00
Bram Kragten
f5a78c88f8 Bump supervisor panel (#1702) 2020-05-07 17:41:10 +02:00
dependabot-preview[bot]
206ece1575 Bump pylint from 2.5.0 to 2.5.2 (#1700)
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.5.0 to 2.5.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.5.0...pylint-2.5.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-07 17:04:08 +02:00
dependabot-preview[bot]
a8028dbe10 Bump gitpython from 3.1.1 to 3.1.2 (#1697)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.1 to 3.1.2.
- [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.1...3.1.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-07 17:04:00 +02:00
Pascal Vizeli
c605af6ccc Add discovery support for new ozw integration (#1701) 2020-05-07 08:32:10 +02:00
Pascal Vizeli
b7b8e6c40e Bump version 221 2020-05-01 18:11:58 +02:00
Pascal Vizeli
3fcb1de419 Merge pull request #1692 from home-assistant/dev
Release 220
2020-05-01 18:07:35 +02:00
Pascal Vizeli
12034fe5fc Update panel with new tabs (#1691)
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-05-01 17:51:35 +02:00
dependabot-preview[bot]
56959d781a Bump pylint from 2.4.4 to 2.5.0 (#1684)
* Bump pylint from 2.4.4 to 2.5.0

Bumps [pylint](https://github.com/PyCQA/pylint) from 2.4.4 to 2.5.0.
- [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.4.4...pylint-2.5.0)

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

* fix lint

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-05-01 15:34:12 +02:00
Pascal Vizeli
9a2f025646 Add support for homematic (#1690) 2020-05-01 15:23:56 +02:00
Pascal Vizeli
12cc163058 New addon panel (#1689)
* Update add-on pages

* update panel
2020-05-01 14:23:54 +02:00
dependabot-preview[bot]
74971d9753 Bump pytz from 2019.3 to 2020.1 (#1686)
Bumps [pytz](https://github.com/stub42/pytz) from 2019.3 to 2020.1.
- [Release notes](https://github.com/stub42/pytz/releases)
- [Commits](https://github.com/stub42/pytz/compare/release_2019.3...release_2020.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-29 12:15:31 +02:00
Franck Nijhof
a9157e3a9f Fix possible Ingress port collisions (#1682)
* Fix possible Ingress port collisions

* Cleanup dynamic port assignment on uninstall

* Check port against gateway address

* gateway address is already of type IPv4Address

* Update supervisor/ingress.py

Co-Authored-By: Pascal Vizeli <pvizeli@syshack.ch>

Co-authored-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-04-26 11:21:56 +02:00
dependabot-preview[bot]
b96697b708 Bump cryptography from 2.9.1 to 2.9.2 (#1676)
Bumps [cryptography](https://github.com/pyca/cryptography) from 2.9.1 to 2.9.2.
- [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/2.9.1...2.9.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-23 18:44:32 +02:00
dependabot-preview[bot]
81e6896391 Bump cryptography from 2.9 to 2.9.1 (#1673)
Bumps [cryptography](https://github.com/pyca/cryptography) from 2.9 to 2.9.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/2.9...2.9.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-22 14:23:00 +02:00
dependabot-preview[bot]
2dcaa3608d Bump pulsectl from 20.2.4 to 20.4.3 (#1674)
Bumps [pulsectl](https://github.com/mk-fg/python-pulse-control) from 20.2.4 to 20.4.3.
- [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-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-22 13:14:54 +02:00
Pascal Vizeli
e21671ec5e Bump version to 220 2020-04-22 11:32:13 +02:00
Pascal Vizeli
7841f14163 Merge pull request #1671 from home-assistant/dev
Release 219
2020-04-22 11:31:50 +02:00
Pascal Vizeli
cc9f594ab4 Better initial image load handling (#1672) 2020-04-22 11:26:53 +02:00
Pascal Vizeli
ebfaaeaa6b Improve the flow with fallback if there is a network issue (#1670) 2020-04-22 11:06:59 +02:00
Pascal Vizeli
ffa91e150d Fix handling with reset/default on json (#1669)
* Fix handling with reset/default on json

* black
2020-04-22 11:06:49 +02:00
Pascal Vizeli
06fa9f9a9e Bump version to 219 2020-04-21 20:15:15 +02:00
Pascal Vizeli
9f203c42ec Merge pull request #1668 from home-assistant/dev
Release 218
2020-04-21 20:14:44 +02:00
Pascal Vizeli
5d0d34a4af Fix version detection 2020-04-21 15:32:20 +00:00
Pascal Vizeli
c2cfc0d3d4 Allow moving registry for supervisor (#1667)
* Allow moving registry for supervisor

* fix

* Filter number
2020-04-21 16:59:28 +02:00
Pascal Vizeli
0f4810d41f Add debug 2020-04-21 13:09:52 +00:00
Pascal Vizeli
175848f2a8 Fix update order (#1666) 2020-04-21 14:41:44 +02:00
Fabian Affolter
472bd66f4d Update README (#1662) 2020-04-14 13:38:00 +02:00
dependabot-preview[bot]
168ea32d2c Bump jinja2 from 2.11.1 to 2.11.2 (#1663)
Bumps [jinja2](https://github.com/pallets/jinja) from 2.11.1 to 2.11.2.
- [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.1...2.11.2)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-14 13:37:49 +02:00
Fabian Affolter
e82d6b1ea4 Minor re-work (#1661)
* Minor re-work

* Fix typo
2020-04-14 10:27:10 +02:00
dependabot-preview[bot]
6c60ca088c Bump gitpython from 3.1.0 to 3.1.1 (#1659)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.0 to 3.1.1.
- [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.0...3.1.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-14 10:25:59 +02:00
Fabian Affolter
83e8f935fd Remove duoble DNS section (#1660) 2020-04-14 10:25:38 +02:00
Pascal Vizeli
71867302a4 Bump version to 218 2020-04-12 12:00:53 +02:00
Pascal Vizeli
8bcc402c5f Merge pull request #1656 from home-assistant/dev
Release 217
2020-04-12 12:00:16 +02:00
Pascal Vizeli
72b7d2a123 Fix restore on older snapshots (#1655) 2020-04-12 11:56:37 +02:00
Aidan Timson
20c1183450 Remove Azure CI badge (#1648)
* Fix azure ci badge

* Remove Azure CI badge
2020-04-11 14:07:19 +02:00
Pascal Vizeli
0bbfbd2544 Readd audio api 2020-04-11 13:35:26 +02:00
Pascal Vizeli
350bd9c32f Bump version to 217 2020-04-11 11:16:31 +02:00
Pascal Vizeli
dcca8b0a9a Merge pull request #1652 from home-assistant/dev
Release 216
2020-04-11 11:15:57 +02:00
Pascal Vizeli
f77b479e45 Add timeout for clean shutdown (#1650)
* Fix overlay

* Update Dockerfile
2020-04-10 23:31:24 +02:00
Pascal Vizeli
216565affb Give a bit more time to update apparmor (#1647) 2020-04-10 01:15:47 +02:00
Pascal Vizeli
6f235c2a11 force dns plugin v9 2020-04-09 16:45:10 +02:00
Pascal Vizeli
27a770bd1d force dns plugin v7 2020-04-08 23:39:18 +02:00
Pascal Vizeli
ef15b67571 Bump version to 216 2020-04-08 14:44:10 +02:00
Pascal Vizeli
6aad966c52 Merge pull request #1644 from home-assistant/dev
Release 215
2020-04-08 14:43:37 +02:00
Pascal Vizeli
9811f11859 Force plugin: cli v25 - dns v6 2020-04-08 12:34:42 +00:00
Pascal Vizeli
13148ec7fb Filter add-ons in the store based on advanced mode (#1643)
* Filter add-ons in the store based on advanced mode

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

* Filter add-ons in the store based on advanced mode p2

Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2020-04-08 14:29:43 +02:00
Pascal Vizeli
b2d7464790 Fix multicast API for logs (#1642) 2020-04-08 14:08:09 +02:00
Joakim Sørensen
ce84e185ad Restore repositories with partial snapshot (#1641)
* Restore repositories with partial snapshot

* Run black
2020-04-08 13:44:03 +02:00
Franck Nijhof
c3f5ee43b6 Add missing multicast/logs endpoint to API docs (#1640) 2020-04-08 12:11:59 +02:00
Pascal Vizeli
e2dc1a4471 Support plugin requirements & mdns (#1638)
* Support plugin requirements & mdns

* better error handling

* Use debug from LogLevel

* fix lint

* fix logger

* fix test env

* Use new style

* fix typo
2020-04-07 12:08:29 +02:00
Pascal Vizeli
e787e59b49 Cleanup network (#1637)
* Cleanup network forward

* Add permission
2020-04-06 14:00:52 +02:00
Pascal Vizeli
f0ed2eba2b Multicast support on Hass.io Network (#1634)
* Add multicast layer to docker

* support network forward

* add pluginmanager

* finish multicast plugin

* fix lint

* Add shutdown for plugins

* Add API

* Add watchdog

* Fix black

* Fix path
2020-04-05 23:26:22 +02:00
Pascal Vizeli
2364e1e652 Remove old authentication (#1635) 2020-04-05 19:16:12 +02:00
Pascal Vizeli
cc56944d75 relicense project 2020-04-05 16:23:52 +02:00
Pascal Vizeli
69cea9fc96 Plugin cleanup (#1632)
* Plugin cleanup

* Fix setup
2020-04-05 01:20:49 +02:00
Pascal Vizeli
fcebc9d1ed Use updater for image data (#1628)
* Use updater for image data

* Fix message

* Fix handling

* Update code

* fix lint

* fix names

* Fix log

* Fix error log

* make it better
2020-04-05 00:47:05 +02:00
Pascal Vizeli
9350e4f961 Store image on local config (#1627)
* Store image on local config

* Fix api validate

* Fix install handling
2020-04-03 17:12:18 +02:00
Pascal Vizeli
387e0ad03e Adjust dbus support for pulse (#1626) 2020-04-03 14:27:30 +02:00
dependabot-preview[bot]
61fec8b290 Bump cryptography from 2.8 to 2.9 (#1625)
Bumps [cryptography](https://github.com/pyca/cryptography) from 2.8 to 2.9.
- [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/2.8...2.9)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-03 13:44:03 +02:00
Pascal Vizeli
1228baebf4 Cleanup host groups (#1623) 2020-04-02 18:00:17 +02:00
Pascal Vizeli
a30063e85c Bump version to 215 2020-03-30 12:38:37 +02:00
Pascal Vizeli
524cebac4d Merge pull request #1617 from home-assistant/dev
Release 214
2020-03-30 12:37:45 +02:00
Pascal Vizeli
c94114a566 Update panel (#1616) 2020-03-30 12:34:21 +02:00
Pascal Vizeli
b6ec7a9e64 Bump version to 214 2020-03-29 14:35:55 +02:00
Pascal Vizeli
69be7a6d22 Merge pull request #1611 from home-assistant/dev
Release 213
2020-03-29 14:35:10 +02:00
Pascal Vizeli
58155c35f9 Supervisor use own dns layer (#1610)
* Supervisor use own dns layer

* Add logs
2020-03-29 13:45:46 +02:00
Pascal Vizeli
7b2377291f Fix error handling on tasks (#1608) 2020-03-28 17:05:42 +01:00
Pascal Vizeli
657ee84e39 Bump version to 213 2020-03-28 16:10:22 +01:00
Pascal Vizeli
2e4b545265 Merge pull request #1607 from home-assistant/dev
Release 212
2020-03-28 16:09:49 +01:00
Pascal Vizeli
2de1d35dd1 Get host dmesg as host logs (#1606)
* Get host dmesg as host logs

* fix lint
2020-03-28 15:56:57 +01:00
Pascal Vizeli
2b082b362d Fix cli update (#1605)
* Fix cli update

* fix logging

* Fix
2020-03-28 15:21:32 +01:00
Pascal Vizeli
dfdd0d6b4b Bump version to 212 2020-03-27 22:27:52 +01:00
Pascal Vizeli
a00e81c03f Merge pull request #1604 from home-assistant/dev
Release 211
2020-03-27 22:26:56 +01:00
Pascal Vizeli
776e6bb418 Rename API last/latest (#1603)
* Rename API last/latest

* Update panel

* Fix for HA

* ha need this
2020-03-27 22:07:54 +01:00
Pascal Vizeli
b31fca656e Bump version to 211 2020-03-27 17:48:02 +01:00
Pascal Vizeli
fa783a0d2c Merge pull request #1602 from home-assistant/dev
Release 210
2020-03-27 17:46:51 +01:00
Pascal Vizeli
96c0fbaf10 Cli rebrand (#1601)
* Rebrand CLI

* forward

* Fix startup command

* add cli api

* Add token handling

* Fix security check

* fix repair

* fix lint

* Update for new cli

* Add watchdog

* rename

* use s6
2020-03-27 17:37:48 +01:00
Pascal Vizeli
24f7801ddc Fix wrong function for set profiles (#1600) 2020-03-27 12:32:14 +01:00
Pascal Vizeli
8e83e007e9 DNS loop protection (#1599)
* DNS loop protection

* Update supervisor/dns.py

Co-Authored-By: Franck Nijhof <git@frenck.dev>

* cleanup not needed code

* Fix

Co-authored-by: Franck Nijhof <git@frenck.dev>
2020-03-27 11:54:32 +01:00
Pascal Vizeli
d0db466e67 Use DoT as fallback (#1597)
* Use DoT as fallback / add cache

* Stage

* merge

* fix lint

* Fallback server

* use fallback

* add nxdomain

* Address comments
2020-03-27 00:38:54 +01:00
Franck Nijhof
3010bd4eb6 Remove Home Panel Discovery (#1594)
* Remove Home Panel Discovery

* Remove related tests
2020-03-23 10:32:56 +01:00
Phill (pssc)
069bed8815 Rasie limit on container shutdown for addons usecase tmpfs based mariadb for recorder taking over 2 mins for dump (#1595) 2020-03-23 09:15:35 +01:00
Pascal Vizeli
d2088ae5f8 Update azure-pipelines-wheels.yml for Azure Pipelines 2020-03-21 09:13:13 +01:00
dependabot-preview[bot]
0ca5a241bb Bump cchardet from 2.1.5 to 2.1.6 (#1593)
Bumps [cchardet](https://github.com/PyYoshi/cChardet) from 2.1.5 to 2.1.6.
- [Release notes](https://github.com/PyYoshi/cChardet/releases)
- [Changelog](https://github.com/PyYoshi/cChardet/blob/master/CHANGES.rst)
- [Commits](https://github.com/PyYoshi/cChardet/compare/2.1.5...2.1.6)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-03-18 15:21:12 +01:00
dependabot-preview[bot]
dff32a8e84 Bump pytest from 5.3.5 to 5.4.1 (#1591)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.3.5 to 5.4.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/5.3.5...5.4.1)

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

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-03-16 14:36:11 +01:00
Pascal Vizeli
4a20344652 Log config check (#1583)
* Add more log for config check to debug

* Convert to ascii

* fix comment
2020-03-12 15:16:40 +01:00
Pascal Vizeli
98b969ef06 Bump version to 210 2020-03-06 12:43:11 +01:00
Pascal Vizeli
c8cb8aecf7 Merge pull request #1574 from home-assistant/dev
Release 209
2020-03-06 12:41:56 +01:00
Pascal Vizeli
73e8875018 Fix Issue with pulse folder (#1573)
* Fix Issue with pulse folder

* Fix config check
2020-03-06 12:32:29 +01:00
Pascal Vizeli
02aed9c084 Enforce Pulse client (#1572) 2020-03-05 15:54:23 +01:00
Pascal Vizeli
89148f8fff Bump packaging from 20.1 to 20.3 (#1570)
Bumps [packaging](https://github.com/pypa/packaging) from 20.1 to 20.3.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/20.1...20.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-05 13:44:10 +01:00
Pascal Vizeli
6bde527f5c Bump version to 209 2020-03-04 19:09:20 +01:00
Pascal Vizeli
d62aabc01b Merge pull request #1567 from home-assistant/dev
Release 208
2020-03-04 19:08:12 +01:00
Pascal Vizeli
82299a3799 Fix udev error without privileged (#1566)
* Fix udev error without privileged

* Fix udev

* Remove context

* Update supervisor/hwmon.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

* Update supervisor/hwmon.py

Co-Authored-By: Paulus Schoutsen <balloob@gmail.com>

Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
2020-03-04 18:55:07 +01:00
Pascal Vizeli
c02f30dd7e Enforce env check (#1565) 2020-03-04 18:15:10 +01:00
Pascal Vizeli
e91983adb4 Watchdog check in_progress for audio/dns (#1555) 2020-03-03 15:06:09 +01:00
Pascal Vizeli
ff88359429 Bump version to 208 2020-03-02 11:32:01 +01:00
345 changed files with 9835 additions and 2167 deletions

View File

@@ -1,4 +1,4 @@
FROM python:3.7
FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.8
WORKDIR /workspaces
@@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& apt-get update && apt-get install -y --no-install-recommends \
nodejs \
yarn \
&& curl -o - https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash \
&& curl -o - https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash \
&& rm -rf /var/lib/apt/lists/*
ENV NVM_DIR /root/.nvm
@@ -46,6 +46,3 @@ COPY requirements.txt requirements_tests.txt ./
RUN pip3 install -r requirements.txt -r requirements_tests.txt \
&& pip3 install tox \
&& rm -f requirements.txt requirements_tests.txt
# Set the default shell to bash instead of sh
ENV SHELL /bin/bash

View File

@@ -1,24 +1,32 @@
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
"name": "Supervisor dev",
"context": "..",
"dockerFile": "Dockerfile",
"appPort": "9123:8123",
"postCreateCommand": "pre-commit install",
"runArgs": ["-e", "GIT_EDITOR=code --wait", "--privileged"],
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"visualstudioexptteam.vscodeintellicode",
"esbenp.prettier-vscode"
],
"settings": {
"python.pythonPath": "/usr/local/bin/python",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--target-version", "py37"],
"terminal.integrated.shell.linux": "/bin/bash",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"python.pythonPath": "/usr/local/bin/python3",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--target-version", "py38"],
"python.formatting.blackPath": "/usr/local/bin/black",
"python.linting.banditPath": "/usr/local/bin/bandit",
"python.linting.flake8Path": "/usr/local/bin/flake8",
"python.linting.mypyPath": "/usr/local/bin/mypy",
"python.linting.pylintPath": "/usr/local/bin/pylint",
"python.linting.pydocstylePath": "/usr/local/bin/pydocstyle"
}
}

View File

@@ -1,15 +1,15 @@
<!-- READ THIS FIRST:
- If you need additional help with this template please refer to https://www.home-assistant.io/help/reporting_issues/
- Make sure you are running the latest version of Home Assistant before reporting an issue: https://github.com/home-assistant/home-assistant/releases
- Do not report issues for components here, plaese refer to https://github.com/home-assistant/home-assistant/issues
- Make sure you are running the latest version of Home Assistant before reporting an issue: https://github.com/home-assistant/core/releases
- Do not report issues for integrations here, please refer to https://github.com/home-assistant/core/issues
- This is for bugs only. Feature and enhancement requests should go in our community forum: https://community.home-assistant.io/c/feature-requests
- Provide as many details as possible. Paste logs, configuration sample and code into the backticks. Do not delete any text from this template!
- If you have a problem with a Add-on, make a issue on there repository.
- If you have a problem with an add-on, make an issue in its repository.
-->
**Home Assistant release with the issue:**
<!--
- Frontend -> Developer tools -> Info
- Frontend -> Configuration -> Info
- Or use this command: hass --version
-->
@@ -20,10 +20,9 @@ Please provide details about your environment.
**Supervisor logs:**
<!--
- Frontend -> Hass.io -> System
- Or use this command: hassio su logs
- Frontend -> Supervisor -> System
- Or use this command: ha supervisor logs
-->
**Description of problem:**

14
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: daily
time: "06:00"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
time: "06:00"
open-pull-requests-limit: 10

2
.github/lock.yml vendored
View File

@@ -24,4 +24,4 @@ only: pulls
# Optionally, specify configuration settings just for `issues` or `pulls`
issues:
daysUntilLock: 30
daysUntilLock: 30

2
.github/stale.yml vendored
View File

@@ -7,7 +7,7 @@ exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had

432
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,432 @@
name: CI
# yamllint disable-line rule:truthy
on:
push:
branches:
- dev
- master
pull_request: ~
env:
DEFAULT_PYTHON: 3.8
PRE_COMMIT_HOME: ~/.cache/pre-commit
jobs:
# Separate job to pre-populate the base dependency cache
# This prevent upcoming jobs to do the same individually
prepare:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]
name: Prepare Python ${{ matrix.python-version }} dependencies
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v2.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
restore-keys: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
pip install -U pip setuptools
pip install -r requirements.txt -r requirements_tests.txt
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
${{ runner.os }}-pre-commit-
- name: Install pre-commit dependencies
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
. venv/bin/activate
pre-commit install-hooks
lint-black:
name: Check black
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run black
run: |
. venv/bin/activate
black --target-version py38 --check supervisor tests setup.py
lint-dockerfile:
name: Check Dockerfile
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Register hadolint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
- name: Check Dockerfile
uses: docker://hadolint/hadolint:v1.18.0
with:
args: hadolint Dockerfile
lint-executable-shebangs:
name: Check executables
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register check executables problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/check-executables-have-shebangs.json"
- name: Run executables check
run: |
. venv/bin/activate
pre-commit run --hook-stage manual check-executables-have-shebangs --all-files
lint-flake8:
name: Check flake8
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register flake8 problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/flake8.json"
- name: Run flake8
run: |
. venv/bin/activate
flake8 supervisor tests
lint-isort:
name: Check isort
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run isort
run: |
. venv/bin/activate
pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure
lint-json:
name: Check JSON
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register check-json problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/check-json.json"
- name: Run check-json
run: |
. venv/bin/activate
pre-commit run --hook-stage manual check-json --all-files
lint-pylint:
name: Check pylint
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Register pylint problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/pylint.json"
- name: Run pylint
run: |
. venv/bin/activate
pylint supervisor tests
lint-pyupgrade:
name: Check pyupgrade
runs-on: ubuntu-latest
needs: prepare
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Restore pre-commit environment from cache
id: cache-precommit
uses: actions/cache@v2
with:
path: ${{ env.PRE_COMMIT_HOME }}
key: |
${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Fail job if cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Run pyupgrade
run: |
. venv/bin/activate
pre-commit run --hook-stage manual pyupgrade --all-files --show-diff-on-failure
pytest:
runs-on: ubuntu-latest
needs: prepare
strategy:
matrix:
python-version: [3.8]
name: Run tests Python ${{ matrix.python-version }}
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ matrix.python-version }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Install additional system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends libpulse0 libudev1
- name: Register Python problem matcher
run: |
echo "::add-matcher::.github/workflows/matchers/python.json"
- name: Install Pytest Annotation plugin
run: |
. venv/bin/activate
# Ideally this should be part of our dependencies
# However this plugin is fairly new and doesn't run correctly
# on a non-GitHub environment.
pip install pytest-github-actions-annotate-failures
- name: Run pytest
run: |
. venv/bin/activate
pytest \
-qq \
--timeout=10 \
--durations=10 \
--cov supervisor \
-o console_output_style=count \
tests
- name: Upload coverage artifact
uses: actions/upload-artifact@v2.1.3
with:
name: coverage-${{ matrix.python-version }}
path: .coverage
coverage:
name: Process test coverage
runs-on: ubuntu-latest
needs: pytest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.1
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v2
with:
path: venv
key: |
${{ runner.os }}-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_tests.txt') }}
- name: Fail job if Python cache restore failed
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
echo "Failed to restore Python virtual environment from cache"
exit 1
- name: Download all coverage artifacts
uses: actions/download-artifact@v2
- name: Combine coverage results
run: |
. venv/bin/activate
coverage combine coverage*/.coverage*
coverage report
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1.0.12

View File

@@ -0,0 +1,14 @@
{
"problemMatcher": [
{
"owner": "check-executables-have-shebangs",
"pattern": [
{
"regexp": "^(.+):\\s(.+)$",
"file": 1,
"message": 2
}
]
}
]
}

View File

@@ -0,0 +1,16 @@
{
"problemMatcher": [
{
"owner": "check-json",
"pattern": [
{
"regexp": "^(.+):\\s(.+\\sline\\s(\\d+)\\scolumn\\s(\\d+).+)$",
"file": 1,
"message": 2,
"line": 3,
"column": 4
}
]
}
]
}

30
.github/workflows/matchers/flake8.json vendored Normal file
View File

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

View File

@@ -0,0 +1,16 @@
{
"problemMatcher": [
{
"owner": "hadolint",
"pattern": [
{
"regexp": "^(.+):(\\d+)\\s+((DL\\d{4}).+)$",
"file": 1,
"line": 2,
"message": 3,
"code": 4
}
]
}
]
}

32
.github/workflows/matchers/pylint.json vendored Normal file
View File

@@ -0,0 +1,32 @@
{
"problemMatcher": [
{
"owner": "pylint-error",
"severity": "error",
"pattern": [
{
"regexp": "^(.+):(\\d+):(\\d+):\\s(([EF]\\d{4}):\\s.+)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
},
{
"owner": "pylint-warning",
"severity": "warning",
"pattern": [
{
"regexp": "^(.+):(\\d+):(\\d+):\\s(([CRW]\\d{4}):\\s.+)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
}
]
}

18
.github/workflows/matchers/python.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"problemMatcher": [
{
"owner": "python",
"pattern": [
{
"regexp": "^\\s*File\\s\\\"(.*)\\\",\\sline\\s(\\d+),\\sin\\s(.*)$",
"file": 1,
"line": 2
},
{
"regexp": "^\\s*raise\\s(.*)\\(\\'(.*)\\'\\)$",
"message": 2
}
]
}
]
}

15
.github/workflows/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Release Drafter
on:
push:
# branches to consider in the event; optional, defaults to all
branches:
- dev
jobs:
update_release_draft:
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5
.gitignore vendored
View File

@@ -95,3 +95,8 @@ ENV/
.vscode/*
!.vscode/cSpell.json
!.vscode/tasks.json
!.vscode/launch.json
# mypy
/.mypy_cache/*
/.dmypy.json

32
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,32 @@
repos:
- repo: https://github.com/psf/black
rev: 19.10b0
hooks:
- id: black
args:
- --safe
- --quiet
files: ^((supervisor|tests)/.+)?[^/]+\.py$
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.3
hooks:
- id: flake8
additional_dependencies:
- flake8-docstrings==1.5.0
- pydocstyle==5.0.2
files: ^(supervisor|script|tests)/.+\.py$
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.1.0
hooks:
- id: check-executables-have-shebangs
stages: [manual]
- id: check-json
- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.21
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v2.6.2
hooks:
- id: pyupgrade
args: [--py37-plus]

18
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Supervisor remote debug",
"type": "python",
"request": "attach",
"port": 33333,
"host": "172.30.32.2",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/usr/src/supervisor"
}
]
}
]
}

180
.vscode/tasks.json vendored
View File

@@ -1,92 +1,90 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Run Testenv",
"type": "shell",
"command": "./scripts/test_env.sh",
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Run Testenv CLI",
"type": "shell",
"command": "docker run --rm -ti -v /etc/machine-id:/etc/machine-id --network=hassio --add-host hassio:172.30.32.2 homeassistant/amd64-hassio-cli:dev",
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Update UI",
"type": "shell",
"command": "./scripts/update-frontend.sh",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Pytest",
"type": "shell",
"command": "pytest --timeout=10 tests",
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Flake8",
"type": "shell",
"command": "flake8 hassio tests",
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Pylint",
"type": "shell",
"command": "pylint hassio",
"dependsOn": [
"Install all Requirements"
],
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
]
}
"version": "2.0.0",
"tasks": [
{
"label": "Run Testenv",
"type": "shell",
"command": "./scripts/test_env.sh",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Run Testenv CLI",
"type": "shell",
"command": "docker exec -ti hassio_cli /usr/bin/cli.sh",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Update UI",
"type": "shell",
"command": "./scripts/update-frontend.sh",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Pytest",
"type": "shell",
"command": "pytest --timeout=10 tests",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Flake8",
"type": "shell",
"command": "flake8 supervisor tests",
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Pylint",
"type": "shell",
"command": "pylint supervisor",
"dependsOn": ["Install all Requirements"],
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
]
}

171
API.md
View File

@@ -2,7 +2,8 @@
## Supervisor RESTful API
Interface for Home Assistant to control things from supervisor.
The RESTful API for Home Assistant allows you to control things around
around the Supervisor and other components.
On error / Code 400:
@@ -22,8 +23,10 @@ On success / Code 200:
}
```
For access to API you need use a authorization header with a `Bearer` token.
They are available for Add-ons and the Home Assistant using the `SUPERVISOR_TOKEN` environment variable.
To access the API you need use an authorization header with a `Bearer` token.
The token is available for add-ons and Home Assistant using the
`SUPERVISOR_TOKEN` environment variable.
### Supervisor
@@ -33,12 +36,12 @@ This API call don't need a token.
- GET `/supervisor/info`
The addons from `addons` are only installed one.
Shows the installed add-ons from `addons`.
```json
{
"version": "INSTALL_VERSION",
"last_version": "LAST_VERSION",
"version_latest": "version_latest",
"arch": "armhf|aarch64|i386|amd64",
"channel": "stable|beta|dev",
"timezone": "TIMEZONE",
@@ -47,6 +50,7 @@ The addons from `addons` are only installed one.
"wait_boot": "int",
"debug": "bool",
"debug_block": "bool",
"diagnostics": "None|bool",
"addons": [
{
"name": "xy bla",
@@ -90,11 +94,11 @@ Optional:
- POST `/supervisor/reload`
Reload addons/version.
Reload the add-ons/version.
- GET `/supervisor/logs`
Output is the raw docker log.
Output is the raw Docker log.
- GET `/supervisor/stats`
@@ -113,7 +117,7 @@ Output is the raw docker log.
- GET `/supervisor/repair`
Repair overlayfs issue and restore lost images
Repair overlayfs issue and restore lost images.
### Snapshot
@@ -134,7 +138,6 @@ Repair overlayfs issue and restore lost images
```
- POST `/snapshots/reload`
- POST `/snapshots/new/upload`
return:
@@ -208,9 +211,7 @@ return:
```
- POST `/snapshots/{slug}/remove`
- GET `/snapshots/{slug}/download`
- POST `/snapshots/{slug}/restore/full`
```json
@@ -233,11 +234,8 @@ return:
### Host
- POST `/host/reload`
- POST `/host/shutdown`
- POST `/host/reboot`
- GET `/host/info`
```json
@@ -252,6 +250,10 @@ return:
}
```
- GET `/host/logs`
Return the host log messages (dmesg).
- POST `/host/options`
```json
@@ -291,9 +293,7 @@ return:
```json
{
"version": "2.3",
"version_cli": "7",
"version_latest": "2.4",
"version_cli_latest": "8",
"board": "ova|rpi",
"boot": "rauc boot slot"
}
@@ -307,17 +307,9 @@ return:
}
```
- POST `/os/update/cli`
```json
{
"version": "optional"
}
```
- POST `/os/config/sync`
Load host configs from a USB stick.
Load host configurations from an USB stick.
### Hardware
@@ -360,7 +352,7 @@ Load host configs from a USB stick.
- POST `/hardware/trigger`
Trigger an udev reload
Trigger an UDEV reload.
### Home Assistant
@@ -369,12 +361,11 @@ Trigger an udev reload
```json
{
"version": "INSTALL_VERSION",
"last_version": "LAST_VERSION",
"version_latest": "version_latest",
"arch": "arch",
"machine": "Image machine type",
"ip_address": "ip address",
"image": "str",
"custom": "bool -> if custom image",
"boot": "bool",
"port": 8123,
"ssl": "bool",
@@ -410,7 +401,7 @@ Output is the raw Docker log.
```json
{
"image": "Optional|null",
"last_version": "Optional for custom image|null",
"version_latest": "Optional for custom image|null",
"port": "port for access core",
"ssl": "bool",
"refresh_token": "",
@@ -421,7 +412,7 @@ Output is the raw Docker log.
}
```
Image with `null` and last_version with `null` reset this options.
Image with `null` and `version_latest` with `null` reset this options.
- POST/GET `/core/api`
@@ -464,7 +455,7 @@ Get all available add-ons.
"advanced": "bool",
"stage": "stable|experimental|deprecated",
"repository": "core|local|REP_ID",
"version": "LAST_VERSION",
"version": "version_latest",
"installed": "none|INSTALL_VERSION",
"detached": "bool",
"available": "bool",
@@ -508,7 +499,7 @@ Get all available add-ons.
"homeassistant": "null|min Home Assistant Core version",
"repository": "12345678|null",
"version": "null|VERSION_INSTALLED",
"last_version": "LAST_VERSION",
"version_latest": "version_latest",
"state": "none|started|stopped",
"boot": "auto|manual",
"build": "bool",
@@ -558,13 +549,9 @@ Get all available add-ons.
```
- GET `/addons/{addon}/icon`
- GET `/addons/{addon}/logo`
- GET `/addons/{addon}/changelog`
- GET `/addons/{addon}/documentation`
- POST `/addons/{addon}/options`
```json
@@ -581,7 +568,7 @@ Get all available add-ons.
}
```
Reset custom network/audio/options, set it `null`.
Reset custom network, audio and options, set it to `null`.
- POST `/addons/{addon}/security`
@@ -594,28 +581,22 @@ This function is not callable by itself.
```
- POST `/addons/{addon}/start`
- POST `/addons/{addon}/stop`
- POST `/addons/{addon}/install`
- POST `/addons/{addon}/uninstall`
- POST `/addons/{addon}/update`
- GET `/addons/{addon}/logs`
Output is the raw Docker log.
- POST `/addons/{addon}/restart`
- POST `/addons/{addon}/rebuild`
Only supported for local build addons
Only supported for local build add-ons.
- POST `/addons/{addon}/stdin`
Write data to add-on stdin
Write data to add-on stdin.
- GET `/addons/{addon}/stats`
@@ -636,7 +617,7 @@ Write data to add-on stdin
- POST `/ingress/session`
Create a new Session for access to ingress service.
Create a new session for access to the ingress service.
```json
{
@@ -663,8 +644,8 @@ Return a list of enabled panels.
- VIEW `/ingress/{token}`
Ingress WebUI for this Add-on. The addon need support HASS Auth!
Need ingress session as cookie.
Ingress WebUI for this add-on. The add-on need support for the Home Assistant
authentication system. Needs an ingress session as cookie.
### discovery
@@ -679,7 +660,10 @@ Need ingress session as cookie.
"uuid": "uuid",
"config": {}
}
]
],
"services": {
"ozw": ["core_zwave"]
}
}
```
@@ -796,6 +780,7 @@ return:
"supervisor": "version",
"homeassistant": "version",
"hassos": "null|version",
"docker": "version",
"hostname": "name",
"machine": "type",
"arch": "arch",
@@ -814,7 +799,7 @@ return:
{
"host": "ip-address",
"version": "1",
"latest_version": "2",
"version_latest": "2",
"servers": ["dns://8.8.8.8"],
"locals": ["dns://xy"]
}
@@ -857,6 +842,78 @@ return:
}
```
### CLI
- GET `/cli/info`
```json
{
"version": "1",
"version_latest": "2"
}
```
- POST `/cli/update`
```json
{
"version": "VERSION"
}
```
- GET `/cli/stats`
```json
{
"cpu_percent": 0.0,
"memory_usage": 283123,
"memory_limit": 329392,
"memory_percent": 1.4,
"network_tx": 0,
"network_rx": 0,
"blk_read": 0,
"blk_write": 0
}
```
### Multicast
- GET `/multicast/info`
```json
{
"version": "1",
"version_latest": "2"
}
```
- POST `/multicast/update`
```json
{
"version": "VERSION"
}
```
- POST `/multicast/restart`
- GET `/multicast/logs`
- GET `/multicast/stats`
```json
{
"cpu_percent": 0.0,
"memory_usage": 283123,
"memory_limit": 329392,
"memory_percent": 1.4,
"network_tx": 0,
"network_rx": 0,
"blk_read": 0,
"blk_write": 0
}
```
### Audio
- GET `/audio/info`
@@ -1048,18 +1105,18 @@ return:
}
```
### Auth / SSO API
### Authentication/SSO API
You can use the user system on homeassistant. We handle this auth system on
supervisor.
You can use the user system from Home Assistant. The auth system can be handled
with the Supervisor.
You can call post `/auth`
`/auth` is accepting POST calls.
We support:
- Json `{ "user|name": "...", "password": "..." }`
- application/x-www-form-urlencoded `user|name=...&password=...`
- BasicAuth
- JSON: `{ "user|name": "...", "password": "..." }`
- `application/x-www-form-urlencoded`: `user|name=...&password=...`
- Basic Authentication
* POST `/auth/reset`

View File

@@ -1,24 +1,29 @@
ARG BUILD_FROM
FROM $BUILD_FROM
ENV \
S6_SERVICES_GRACETIME=10000
# Install base
RUN apk add --no-cache \
eudev \
eudev-libs \
git \
glib \
libffi \
libpulse \
musl \
openssl \
socat
RUN \
apk add --no-cache \
eudev \
eudev-libs \
git \
glib \
libffi \
libpulse \
musl \
openssl \
socat
ARG BUILD_ARCH
WORKDIR /usr/src
# Install requirements
COPY requirements.txt .
RUN export MAKEFLAGS="-j$(nproc)" \
RUN \
export MAKEFLAGS="-j$(nproc)" \
&& pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links \
"https://wheels.home-assistant.io/alpine-$(cut -d '.' -f 1-2 < /etc/alpine-release)/${BUILD_ARCH}/" \
-r ./requirements.txt \
@@ -26,7 +31,8 @@ RUN export MAKEFLAGS="-j$(nproc)" \
# Install Home Assistant Supervisor
COPY . supervisor
RUN pip3 install --no-cache-dir -e ./supervisor \
RUN \
pip3 install --no-cache-dir -e ./supervisor \
&& python3 -m compileall ./supervisor/supervisor

View File

@@ -178,7 +178,7 @@
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Pascal Vizeli
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@@ -1,28 +1,26 @@
[![Build Status](https://dev.azure.com/home-assistant/Hass.io/_apis/build/status/hassio?branchName=dev)](https://dev.azure.com/home-assistant/Hass.io/_build/latest?definitionId=2&branchName=dev)
# Home Assistant Supervisor
## First private cloud solution for home automation
Hass.io is a Docker-based system for managing your Home Assistant installation
and related applications. The system is controlled via Home Assistant which
communicates with the Supervisor. The Supervisor provides an API to manage the
installation. This includes changing network settings or installing
and updating software.
Home Assistant (former Hass.io) is a container-based system for managing your
Home Assistant Core installation and related applications. The system is
controlled via Home Assistant which communicates with the Supervisor. The
Supervisor provides an API to manage the installation. This includes changing
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/hassio.
## Development
The development of the supervisor is a bit tricky. Not difficult but tricky.
The development of the Supervisor is not difficult but tricky.
- You can use the builder to build your supervisor: https://github.com/home-assistant/hassio-builder
- Go into a HassOS device or VM and pull your supervisor.
- Set the developer modus with cli `hassio supervisor options --channel=dev`
- 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 like `systemctl restart hassos-supervisor | journalctl -fu hassos-supervisor`
- Restart the service with `systemctl restart hassos-supervisor | journalctl -fu hassos-supervisor`
- Test your changes
Small Bugfix or improvements, make a PR. Significant change makes first an RFC.
For small bugfixes or improvements, make a PR. For significant changes open a RFC first, please. Thanks.

View File

@@ -22,9 +22,9 @@ jobs:
sudo apt-get install -y libpulse0 libudev1
displayName: "Install Host library"
- task: UsePythonVersion@0
displayName: "Use Python 3.7"
displayName: "Use Python 3.8"
inputs:
versionSpec: "3.7"
versionSpec: "3.8"
- script: pip install tox
displayName: "Install Tox"
- script: tox

View File

@@ -20,9 +20,9 @@ jobs:
vmImage: "ubuntu-latest"
steps:
- task: UsePythonVersion@0
displayName: "Use Python 3.7"
displayName: "Use Python 3.8"
inputs:
versionSpec: "3.7"
versionSpec: "3.8"
- script: |
setup_version="$(python setup.py -V)"
branch_version="$(Build.SourceBranchName)"

View File

@@ -8,53 +8,20 @@ trigger:
pr: none
variables:
- name: versionWheels
value: "1.6-3.7-alpine3.11"
- group: wheels
value: '1.13.0-3.8-alpine3.12'
resources:
repositories:
- repository: azure
type: github
name: 'home-assistant/ci-azure'
endpoint: 'home-assistant'
jobs:
- job: "Wheels"
timeoutInMinutes: 360
pool:
vmImage: "ubuntu-latest"
strategy:
maxParallel: 5
matrix:
amd64:
buildArch: "amd64"
i386:
buildArch: "i386"
armhf:
buildArch: "armhf"
armv7:
buildArch: "armv7"
aarch64:
buildArch: "aarch64"
steps:
- script: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
qemu-user-static \
binfmt-support \
curl
sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
sudo update-binfmts --enable qemu-arm
sudo update-binfmts --enable qemu-aarch64
displayName: "Initial cross build"
- script: |
mkdir -p .ssh
echo -e "-----BEGIN RSA PRIVATE KEY-----\n$(wheelsSSH)\n-----END RSA PRIVATE KEY-----" >> .ssh/id_rsa
ssh-keyscan -H $(wheelsHost) >> .ssh/known_hosts
chmod 600 .ssh/*
displayName: "Install ssh key"
- script: sudo docker pull homeassistant/$(buildArch)-wheels:$(versionWheels)
displayName: "Install wheels builder"
- script: |
sudo docker run --rm -v $(pwd):/data:ro -v $(pwd)/.ssh:/root/.ssh:rw \
homeassistant/$(buildArch)-wheels:$(versionWheels) \
--apk "build-base;libffi-dev;openssl-dev" \
--index $(wheelsIndex) \
--requirement requirements.txt \
--upload rsync \
--remote wheels@$(wheelsHost):/opt/wheels
displayName: "Run wheels build"
- 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.7-alpine3.11",
"armhf": "homeassistant/armhf-base-python:3.7-alpine3.11",
"armv7": "homeassistant/armv7-base-python:3.7-alpine3.11",
"amd64": "homeassistant/amd64-base-python:3.7-alpine3.11",
"i386": "homeassistant/i386-base-python:3.7-alpine3.11"
"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"
},
"labels": {
"io.hass.type": "supervisor"

9
codecov.yaml Normal file
View File

@@ -0,0 +1,9 @@
codecov:
branch: dev
coverage:
status:
project:
default:
target: 40
threshold: 0.09
comment: false

View File

@@ -1,27 +1,30 @@
[MASTER]
reports=no
jobs=2
good-names=id,i,j,k,ex,Run,_,fp,T
# Reasons disabled:
# format - handled by black
# locally-disabled - it spams too much
# duplicate-code - unavoidable
# cyclic-import - doesn't test if both import on load
# abstract-class-little-used - prevents from setting right foundation
# abstract-class-not-used - is flaky, should not show up but does
# unused-argument - generic callbacks and setup methods create a lot of warnings
# global-statement - used for the on-demand requirement installation
# redefined-variable-type - this is Python, we're duck typing!
# too-many-* - are not enforced for the sake of readability
# too-few-* - same as too-many-*
# abstract-method - with intro of async there are always methods missing
disable=
format,
abstract-class-little-used,
abstract-class-not-used,
abstract-method,
cyclic-import,
duplicate-code,
global-statement,
locally-disabled,
no-else-return,
no-self-use,
not-context-manager,
redefined-variable-type,
too-few-public-methods,
@@ -34,14 +37,6 @@ disable=
too-many-return-statements,
too-many-statements,
unused-argument,
line-too-long,
bad-continuation,
too-few-public-methods,
no-self-use,
not-async-context-manager,
too-many-locals,
too-many-branches,
no-else-return
[EXCEPTIONS]
overgeneral-exceptions=Exception

View File

@@ -1,18 +1,19 @@
aiohttp==3.6.1
aiohttp==3.6.2
async_timeout==3.0.1
attrs==19.3.0
cchardet==2.1.5
colorlog==4.1.0
cchardet==2.1.6
colorlog==4.2.1
cpe==1.2.1
cryptography==2.8
docker==4.2.0
gitpython==3.1.0
jinja2==2.11.1
packaging==20.1
ptvsd==4.3.2
pulsectl==20.2.4
pytz==2019.3
cryptography==3.0
debugpy==1.0.0b12
docker==4.2.2
gitpython==3.1.7
jinja2==2.11.2
packaging==20.4
pulsectl==20.5.1
pytz==2020.1
pyudev==0.22.0
ruamel.yaml==0.15.100
sentry-sdk==0.16.3
uvloop==0.14.0
voluptuous==0.11.7

View File

@@ -1,6 +1,13 @@
flake8==3.7.9
pylint==2.4.4
pytest==5.3.5
pytest-timeout==1.3.4
pytest-aiohttp==0.3.0
black==19.10b0
codecov==2.1.8
coverage==5.2.1
flake8-docstrings==1.5.0
flake8==3.8.3
pre-commit==2.6.0
pydocstyle==5.0.2
pylint==2.5.3
pytest-aiohttp==0.3.0
pytest-cov==2.10.0
pytest-timeout==1.4.2
pytest==6.0.1
pyupgrade==2.7.2

View File

@@ -4,6 +4,9 @@
# ==============================================================================
udevd --daemon
bashio::log.info "Update udev informations"
udevadm trigger
udevadm settle
bashio::log.info "Update udev information"
if udevadm trigger; then
udevadm settle || true
else
bashio::log.warning "Triggering of udev rules fails!"
fi

View File

@@ -2,4 +2,4 @@
# ==============================================================================
# Take down the S6 supervision tree when Supervisor fails
# ==============================================================================
s6-svscanctl -t /var/run/s6/services
redirfd -w 2 /dev/null s6-svscanctl -t /var/run/s6/services

View File

@@ -2,4 +2,6 @@
# ==============================================================================
# Start Service service
# ==============================================================================
export LD_PRELOAD="/usr/local/lib/libjemalloc.so.2"
exec python3 -m supervisor

View File

@@ -81,11 +81,6 @@ function cleanup_docker() {
}
function install_cli() {
docker pull homeassistant/amd64-hassio-cli:dev
}
function setup_test_env() {
mkdir -p /workspaces/test_supervisor
@@ -101,7 +96,7 @@ function setup_test_env() {
-e SUPERVISOR_SHARE="/workspaces/test_supervisor" \
-e SUPERVISOR_NAME=hassio_supervisor \
-e SUPERVISOR_DEV=1 \
-e HOMEASSISTANT_REPOSITORY="homeassistant/qemux86-64-homeassistant" \
-e SUPERVISOR_MACHINE="qemux86-64" \
homeassistant/amd64-hassio-supervisor:latest
}
@@ -131,7 +126,6 @@ start_docker
trap "stop_docker" ERR
build_supervisor
install_cli
cleanup_lastboot
cleanup_docker
init_dbus

View File

@@ -14,5 +14,5 @@ cd hassio
./script/build_hassio
# Copy frontend
rm -f ../../supervisor/hassio/api/panel/chunk.*
cp -rf build/* ../../supervisor/api/panel/
rm -rf ../../supervisor/api/panel/*
cp -rf build/* ../../supervisor/api/panel/

View File

@@ -11,7 +11,20 @@ default_section = THIRDPARTY
forced_separate = tests
combine_as_imports = true
use_parentheses = true
known_first_party = supervisor,tests
[flake8]
exclude = .venv,.git,.tox,docs,venv,bin,lib,deps,build
doctests = True
max-line-length = 88
ignore = E501, W503
# E501: line too long
# W503: Line break occurred before a binary operator
# E203: Whitespace before ':'
# D202 No blank lines allowed after function docstring
# W504 line break after binary operator
ignore =
E501,
W503,
E203,
D202,
W504

View File

@@ -25,7 +25,7 @@ setup(
"Topic :: Scientific/Engineering :: Atmospheric Science",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
],
keywords=["docker", "home-assistant", "api"],
zip_safe=False,
@@ -37,6 +37,7 @@ setup(
"supervisor.api",
"supervisor.misc",
"supervisor.utils",
"supervisor.plugins",
"supervisor.snapshots",
],
include_package_data=True,

View File

@@ -30,8 +30,7 @@ if __name__ == "__main__":
loop = initialize_event_loop()
# Check if all information are available to setup Supervisor
if not bootstrap.check_environment():
sys.exit(1)
bootstrap.check_environment()
# init executor pool
executor = ThreadPoolExecutor(thread_name_prefix="SyncWorker")

View File

@@ -5,7 +5,7 @@ import logging
import tarfile
from typing import Dict, List, Optional, Union
from ..const import BOOT_AUTO, STATE_STARTED
from ..const import BOOT_AUTO, STATE_STARTED, AddonStartup
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
AddonsError,
@@ -37,7 +37,7 @@ class AddonManager(CoreSysAttributes):
@property
def all(self) -> List[AnyAddon]:
"""Return a list of all add-ons."""
addons = {**self.store, **self.local}
addons: Dict[str, AnyAddon] = {**self.store, **self.local}
return list(addons.values())
@property
@@ -59,7 +59,7 @@ class AddonManager(CoreSysAttributes):
def from_token(self, token: str) -> Optional[Addon]:
"""Return an add-on from Supervisor token."""
for addon in self.installed:
if token == addon.hassio_token:
if token == addon.supervisor_token:
return addon
return None
@@ -78,30 +78,49 @@ class AddonManager(CoreSysAttributes):
# Sync DNS
await self.sync_dns()
async def boot(self, stage: str) -> None:
async def boot(self, stage: AddonStartup) -> None:
"""Boot add-ons with mode auto."""
tasks = []
tasks: List[Addon] = []
for addon in self.installed:
if addon.boot != BOOT_AUTO or addon.startup != stage:
continue
tasks.append(addon.start())
tasks.append(addon)
# Evaluate add-ons which need to be started
_LOGGER.info("Phase '%s' start %d add-ons", stage, len(tasks))
if tasks:
await asyncio.wait(tasks)
await asyncio.sleep(self.sys_config.wait_boot)
if not tasks:
return
async def shutdown(self, stage: str) -> None:
# Start Add-ons sequential
# avoid issue on slow IO
for addon in tasks:
try:
await addon.start()
except Exception as err: # pylint: disable=broad-except
_LOGGER.warning("Can't start Add-on %s: %s", addon.slug, err)
await asyncio.sleep(self.sys_config.wait_boot)
async def shutdown(self, stage: AddonStartup) -> None:
"""Shutdown addons."""
tasks = []
tasks: List[Addon] = []
for addon in self.installed:
if await addon.state() != STATE_STARTED or addon.startup != stage:
continue
tasks.append(addon.stop())
tasks.append(addon)
# Evaluate add-ons which need to be stopped
_LOGGER.info("Phase '%s' stop %d add-ons", stage, len(tasks))
if tasks:
await asyncio.wait(tasks)
if not tasks:
return
# Stop Add-ons sequential
# avoid issue on slow IO
for addon in tasks:
try:
await addon.stop()
except Exception as err: # pylint: disable=broad-except
_LOGGER.warning("Can't stop Add-on %s: %s", addon.slug, err)
async def install(self, slug: str) -> None:
"""Install an add-on."""
@@ -142,7 +161,7 @@ class AddonManager(CoreSysAttributes):
if slug not in self.local:
_LOGGER.warning("Add-on %s is not installed", slug)
return
addon = self.local.get(slug)
addon = self.local[slug]
try:
await addon.instance.remove()
@@ -166,6 +185,9 @@ class AddonManager(CoreSysAttributes):
with suppress(HomeAssistantAPIError):
await self.sys_ingress.update_hass_panel(addon)
# Cleanup Ingress dynamic port assignment
self.sys_ingress.del_dynamic_port(slug)
# Cleanup discovery data
for message in self.sys_discovery.list_messages:
if message.addon != addon.slug:
@@ -188,12 +210,12 @@ class AddonManager(CoreSysAttributes):
if slug not in self.local:
_LOGGER.error("Add-on %s is not installed", slug)
raise AddonsError()
addon = self.local.get(slug)
addon = self.local[slug]
if addon.is_detached:
_LOGGER.error("Add-on %s is not available inside store", slug)
raise AddonsError()
store = self.store.get(slug)
store = self.store[slug]
if addon.version == store.version:
_LOGGER.warning("No update available for add-on %s", slug)
@@ -230,12 +252,12 @@ class AddonManager(CoreSysAttributes):
if slug not in self.local:
_LOGGER.error("Add-on %s is not installed", slug)
raise AddonsError()
addon = self.local.get(slug)
addon = self.local[slug]
if addon.is_detached:
_LOGGER.error("Add-on %s is not available inside store", slug)
raise AddonsError()
store = self.store.get(slug)
store = self.store[slug]
# Check if a rebuild is possible now
if addon.version != store.version:
@@ -325,10 +347,10 @@ class AddonManager(CoreSysAttributes):
for addon in self.installed:
if not await addon.instance.is_running():
continue
self.sys_dns.add_host(
self.sys_plugins.dns.add_host(
ipv4=addon.ip_address, names=[addon.hostname], write=False
)
# Write hosts files
with suppress(CoreDNSError):
self.sys_dns.write_hosts()
self.sys_plugins.dns.write_hosts()

View File

@@ -51,7 +51,7 @@ from ..exceptions import (
)
from ..utils.apparmor import adjust_profile
from ..utils.json import read_json_file, write_json_file
from ..utils.tar import exclude_filter, secure_path
from ..utils.tar import atomic_contents_add, secure_path
from .model import AddonModel, Data
from .utils import remove_data
from .validate import SCHEMA_ADDON_SNAPSHOT, validate_options
@@ -71,9 +71,8 @@ class Addon(AddonModel):
def __init__(self, coresys: CoreSys, slug: str):
"""Initialize data holder."""
self.coresys: CoreSys = coresys
super().__init__(coresys, slug)
self.instance: DockerAddon = DockerAddon(coresys, self)
self.slug: str = slug
async def load(self) -> None:
"""Async initialize of object."""
@@ -82,7 +81,7 @@ class Addon(AddonModel):
@property
def ip_address(self) -> IPv4Address:
"""Return IP of Add-on instance."""
"""Return IP of add-on instance."""
return self.instance.ip_address
@property
@@ -131,12 +130,9 @@ class Addon(AddonModel):
return {**self.data[ATTR_OPTIONS], **self.persist[ATTR_OPTIONS]}
@options.setter
def options(self, value: Optional[Dict[str, Any]]):
def options(self, value: Optional[Dict[str, Any]]) -> None:
"""Store user add-on options."""
if value is None:
self.persist[ATTR_OPTIONS] = {}
else:
self.persist[ATTR_OPTIONS] = deepcopy(value)
self.persist[ATTR_OPTIONS] = {} if value is None else deepcopy(value)
@property
def boot(self) -> bool:
@@ -144,7 +140,7 @@ class Addon(AddonModel):
return self.persist.get(ATTR_BOOT, super().boot)
@boot.setter
def boot(self, value: bool):
def boot(self, value: bool) -> None:
"""Store user boot options."""
self.persist[ATTR_BOOT] = value
@@ -154,7 +150,7 @@ class Addon(AddonModel):
return self.persist.get(ATTR_AUTO_UPDATE, super().auto_update)
@auto_update.setter
def auto_update(self, value: bool):
def auto_update(self, value: bool) -> None:
"""Set auto update."""
self.persist[ATTR_AUTO_UPDATE] = value
@@ -164,7 +160,7 @@ class Addon(AddonModel):
return self.persist[ATTR_UUID]
@property
def hassio_token(self) -> Optional[str]:
def supervisor_token(self) -> Optional[str]:
"""Return access token for Supervisor API."""
return self.persist.get(ATTR_ACCESS_TOKEN)
@@ -191,7 +187,7 @@ class Addon(AddonModel):
return self.persist[ATTR_PROTECTED]
@protected.setter
def protected(self, value: bool):
def protected(self, value: bool) -> None:
"""Set add-on in protected mode."""
self.persist[ATTR_PROTECTED] = value
@@ -201,7 +197,7 @@ class Addon(AddonModel):
return self.persist.get(ATTR_NETWORK, super().ports)
@ports.setter
def ports(self, value: Optional[Dict[str, Optional[int]]]):
def ports(self, value: Optional[Dict[str, Optional[int]]]) -> None:
"""Set custom ports of add-on."""
if value is None:
self.persist.pop(ATTR_NETWORK, None)
@@ -233,6 +229,8 @@ class Addon(AddonModel):
if not url:
return None
webui = RE_WEBUI.match(url)
if not webui:
return None
# extract arguments
t_port = webui.group("t_port")
@@ -275,7 +273,7 @@ class Addon(AddonModel):
return self.persist[ATTR_INGRESS_PANEL]
@ingress_panel.setter
def ingress_panel(self, value: bool):
def ingress_panel(self, value: bool) -> None:
"""Return True if the add-on access support ingress."""
self.persist[ATTR_INGRESS_PANEL] = value
@@ -311,50 +309,50 @@ class Addon(AddonModel):
return input_data
@audio_input.setter
def audio_input(self, value: Optional[str]):
def audio_input(self, value: Optional[str]) -> None:
"""Set audio input settings."""
self.persist[ATTR_AUDIO_INPUT] = value
@property
def image(self):
def image(self) -> Optional[str]:
"""Return image name of add-on."""
return self.persist.get(ATTR_IMAGE)
@property
def need_build(self):
def need_build(self) -> bool:
"""Return True if this add-on need a local build."""
return ATTR_IMAGE not in self.data
@property
def path_data(self):
def path_data(self) -> Path:
"""Return add-on data path inside Supervisor."""
return Path(self.sys_config.path_addons_data, self.slug)
@property
def path_extern_data(self):
def path_extern_data(self) -> PurePath:
"""Return add-on data path external for Docker."""
return PurePath(self.sys_config.path_extern_addons_data, self.slug)
@property
def path_options(self):
def path_options(self) -> Path:
"""Return path to add-on options."""
return Path(self.path_data, "options.json")
@property
def path_pulse(self):
def path_pulse(self) -> Path:
"""Return path to asound config."""
return Path(self.sys_config.path_tmp, f"{self.slug}_pulse")
@property
def path_extern_pulse(self):
def path_extern_pulse(self) -> Path:
"""Return path to asound config for Docker."""
return Path(self.sys_config.path_extern_tmp, f"{self.slug}_pulse")
def save_persist(self):
def save_persist(self) -> None:
"""Save data of add-on."""
self.sys_addons.data.save_data()
async def write_options(self):
async def write_options(self) -> None:
"""Return True if add-on options is written to data."""
schema = self.schema
options = self.options
@@ -367,7 +365,7 @@ class Addon(AddonModel):
write_json_file(self.path_options, options)
except vol.Invalid as ex:
_LOGGER.error(
"Add-on %s have wrong options: %s",
"Add-on %s has invalid options: %s",
self.slug,
humanize_error(options, ex),
)
@@ -379,7 +377,7 @@ class Addon(AddonModel):
raise AddonsError()
async def remove_data(self):
async def remove_data(self) -> None:
"""Remove add-on data."""
if not self.path_data.is_dir():
return
@@ -387,12 +385,17 @@ class Addon(AddonModel):
_LOGGER.info("Remove add-on data folder %s", self.path_data)
await remove_data(self.path_data)
def write_pulse(self):
def write_pulse(self) -> None:
"""Write asound config to file and return True on success."""
pulse_config = self.sys_audio.pulse_client(
pulse_config = self.sys_plugins.audio.pulse_client(
input_profile=self.audio_input, output_profile=self.audio_output
)
# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
# Write pulse config
try:
with self.path_pulse.open("w") as config_file:
config_file.write(pulse_config)
@@ -400,11 +403,10 @@ class Addon(AddonModel):
_LOGGER.error(
"Add-on %s can't write pulse/client.config: %s", self.slug, err
)
raise AddonsError()
_LOGGER.debug(
"Add-on %s write pulse/client.config: %s", self.slug, self.path_pulse
)
else:
_LOGGER.debug(
"Add-on %s write pulse/client.config: %s", self.slug, self.path_pulse
)
async def install_apparmor(self) -> None:
"""Install or Update AppArmor profile for Add-on."""
@@ -515,13 +517,13 @@ class Addon(AddonModel):
except DockerAPIError:
raise AddonsError() from None
async def write_stdin(self, data):
async def write_stdin(self, data) -> None:
"""Write data to add-on stdin.
Return a coroutine.
"""
if not self.with_stdin:
_LOGGER.error("Add-on don't support write to stdin!")
_LOGGER.error("Add-on %s does not support writing to stdin!", self.slug)
raise AddonsNotSupportedError()
try:
@@ -532,10 +534,12 @@ class Addon(AddonModel):
async def snapshot(self, tar_file: tarfile.TarFile) -> None:
"""Snapshot state of an add-on."""
with TemporaryDirectory(dir=self.sys_config.path_tmp) as temp:
temp_path = Path(temp)
# store local image
if self.need_build:
try:
await self.instance.export_image(Path(temp, "image.tar"))
await self.instance.export_image(temp_path.joinpath("image.tar"))
except DockerAPIError:
raise AddonsError() from None
@@ -548,14 +552,14 @@ class Addon(AddonModel):
# Store local configs/state
try:
write_json_file(Path(temp, "addon.json"), data)
write_json_file(temp_path.joinpath("addon.json"), data)
except JsonFileError:
_LOGGER.error("Can't save meta for %s", self.slug)
raise AddonsError() from None
# Store AppArmor Profile
if self.sys_host.apparmor.exists(self.slug):
profile = Path(temp, "apparmor.txt")
profile = temp_path.joinpath("apparmor.txt")
try:
self.sys_host.apparmor.backup_profile(self.slug, profile)
except HostAppArmorError:
@@ -567,13 +571,15 @@ class Addon(AddonModel):
"""Write tar inside loop."""
with tar_file as snapshot:
# Snapshot system
snapshot.add(temp, arcname=".")
# Snapshot data
snapshot.add(
atomic_contents_add(
snapshot,
self.path_data,
excludes=self.snapshot_exclude,
arcname="data",
filter=exclude_filter(self.snapshot_exclude),
)
try:
@@ -619,10 +625,10 @@ class Addon(AddonModel):
# If available
if not self._available(data[ATTR_SYSTEM]):
_LOGGER.error("Add-on %s is not available for this Platform", self.slug)
_LOGGER.error("Add-on %s is not available for this platform", self.slug)
raise AddonsNotSupportedError()
# Restore local add-on informations
# Restore local add-on information
_LOGGER.info("Restore config for addon %s", self.slug)
restore_image = self._image(data[ATTR_SYSTEM])
self.sys_addons.data.restore(
@@ -653,7 +659,7 @@ class Addon(AddonModel):
# Restore data
def _restore_data():
"""Restore data."""
shutil.copytree(Path(temp, "data"), self.path_data)
shutil.copytree(Path(temp, "data"), self.path_data, symlinks=True)
_LOGGER.info("Restore data for addon %s", self.slug)
if self.path_data.is_dir():
@@ -670,7 +676,9 @@ class Addon(AddonModel):
try:
await self.sys_host.apparmor.load_profile(self.slug, profile_file)
except HostAppArmorError:
_LOGGER.error("Can't restore AppArmor profile")
_LOGGER.error(
"Can't restore AppArmor profile for add-on %s", self.slug
)
raise AddonsError() from None
# Run add-on

View File

@@ -1,5 +1,6 @@
"""Supervisor add-on build environment."""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Dict
@@ -30,7 +31,7 @@ class AddonBuild(JsonConfig, CoreSysAttributes):
@property
def base_image(self) -> str:
"""Base images for this add-on."""
"""Return base image for this add-on."""
return self._data[ATTR_BUILD_FROM].get(
self.sys_arch.default, f"homeassistant/{self.sys_arch.default}-base:latest"
)

View File

@@ -12,8 +12,8 @@ from ..const import (
FILE_HASSIO_ADDONS,
)
from ..coresys import CoreSys, CoreSysAttributes
from ..utils.json import JsonConfig
from ..store.addon import AddonStore
from ..utils.json import JsonConfig
from .addon import Addon
from .validate import SCHEMA_ADDONS_FILE

View File

@@ -1,4 +1,5 @@
"""Init file for Supervisor add-ons."""
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any, Awaitable, Dict, List, Optional
@@ -64,32 +65,36 @@ from ..const import (
SECURITY_DISABLE,
SECURITY_PROFILE,
AddonStages,
AddonStartup,
)
from ..coresys import CoreSysAttributes
from ..coresys import CoreSys, CoreSysAttributes
from .validate import RE_SERVICE, RE_VOLUME, schema_ui_options, validate_options
Data = Dict[str, Any]
class AddonModel(CoreSysAttributes):
class AddonModel(CoreSysAttributes, ABC):
"""Add-on Data layout."""
slug: str = None
def __init__(self, coresys: CoreSys, slug: str):
"""Initialize data holder."""
self.coresys: CoreSys = coresys
self.slug: str = slug
@property
@abstractmethod
def data(self) -> Data:
"""Return Add-on config/data."""
raise NotImplementedError()
"""Return add-on config/data."""
@property
@abstractmethod
def is_installed(self) -> bool:
"""Return True if an add-on is installed."""
raise NotImplementedError()
@property
@abstractmethod
def is_detached(self) -> bool:
"""Return True if add-on is detached."""
raise NotImplementedError()
@property
def available(self) -> bool:
@@ -137,7 +142,7 @@ class AddonModel(CoreSysAttributes):
return None
@property
def hassio_token(self) -> Optional[str]:
def supervisor_token(self) -> Optional[str]:
"""Return access token for Supervisor API."""
return None
@@ -180,7 +185,7 @@ class AddonModel(CoreSysAttributes):
return self.data[ATTR_VERSION]
@property
def version(self) -> str:
def version(self) -> Optional[str]:
"""Return version of add-on."""
return self.data[ATTR_VERSION]
@@ -190,9 +195,9 @@ class AddonModel(CoreSysAttributes):
return True
@property
def startup(self) -> Optional[str]:
def startup(self) -> AddonStartup:
"""Return startup type of add-on."""
return self.data.get(ATTR_STARTUP)
return self.data[ATTR_STARTUP]
@property
def advanced(self) -> bool:
@@ -212,7 +217,8 @@ class AddonModel(CoreSysAttributes):
services = {}
for data in services_list:
service = RE_SERVICE.match(data)
services[service.group("service")] = service.group("rights")
if service:
services[service.group("service")] = service.group("rights")
return services
@@ -282,7 +288,7 @@ class AddonModel(CoreSysAttributes):
return self.data[ATTR_HOST_DBUS]
@property
def devices(self) -> Optional[List[str]]:
def devices(self) -> List[str]:
"""Return devices of add-on."""
return self.data.get(ATTR_DEVICES, [])
@@ -446,7 +452,7 @@ class AddonModel(CoreSysAttributes):
return self.data.get(ATTR_MACHINE, [])
@property
def image(self) -> str:
def image(self) -> Optional[str]:
"""Generate image name from data."""
return self._image(self.data)
@@ -461,6 +467,8 @@ class AddonModel(CoreSysAttributes):
volumes = {}
for volume in self.data[ATTR_MAP]:
result = RE_VOLUME.match(volume)
if not result:
continue
volumes[result.group(1)] = result.group(2) or "ro"
return volumes
@@ -527,17 +535,22 @@ class AddonModel(CoreSysAttributes):
# Machine / Hardware
machine = config.get(ATTR_MACHINE)
if machine and self.sys_machine not in machine:
if machine and f"!{self.sys_machine}" in machine:
return False
elif machine and self.sys_machine not in machine:
return False
# Home Assistant
version = config.get(ATTR_HOMEASSISTANT) or self.sys_homeassistant.version
if pkg_version.parse(self.sys_homeassistant.version) < pkg_version.parse(
version
):
return False
version = config.get(ATTR_HOMEASSISTANT)
if version is None or self.sys_homeassistant.version is None:
return True
return True
try:
return pkg_version.parse(
self.sys_homeassistant.version
) >= pkg_version.parse(version)
except pkg_version.InvalidVersion:
return True
def _image(self, config) -> str:
"""Generate image name from data."""

View File

@@ -2,7 +2,7 @@
import logging
import re
import secrets
from typing import Any, Dict, List
from typing import Any, Dict, List, Union
import uuid
import voluptuous as vol
@@ -85,12 +85,10 @@ from ..const import (
PRIVILEGED_ALL,
ROLE_ALL,
ROLE_DEFAULT,
STARTUP_ALL,
STARTUP_APPLICATION,
STARTUP_SERVICES,
STATE_STARTED,
STATE_STOPPED,
AddonStages,
AddonStartup,
)
from ..coresys import CoreSys
from ..discovery.validate import valid_discovery_service
@@ -100,6 +98,7 @@ from ..validate import (
network_port,
token,
uuid_match,
version_tag,
)
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -121,7 +120,10 @@ V_LIST = "list"
RE_SCHEMA_ELEMENT = re.compile(
r"^(?:"
r"|bool|email|url|port"
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+)?\))?"
@@ -149,32 +151,33 @@ RE_DOCKER_IMAGE_BUILD = re.compile(
SCHEMA_ELEMENT = vol.Match(RE_SCHEMA_ELEMENT)
MACHINE_ALL = [
"intel-nuc",
"odroid-c2",
"odroid-n2",
"odroid-xu",
"qemuarm-64",
"qemuarm",
"qemux86-64",
"qemux86",
"raspberrypi",
"raspberrypi2",
"raspberrypi3-64",
"raspberrypi3",
"raspberrypi4-64",
"raspberrypi4",
"tinker",
]
RE_MACHINE = re.compile(
r"^!?(?:"
r"|intel-nuc"
r"|odroid-c2"
r"|odroid-n2"
r"|odroid-xu"
r"|qemuarm-64"
r"|qemuarm"
r"|qemux86-64"
r"|qemux86"
r"|raspberrypi"
r"|raspberrypi2"
r"|raspberrypi3-64"
r"|raspberrypi3"
r"|raspberrypi4-64"
r"|raspberrypi4"
r"|tinker"
r")$"
)
def _simple_startup(value):
"""Simple startup schema."""
def _simple_startup(value) -> str:
"""Define startup schema."""
if value == "before":
return STARTUP_SERVICES
return AddonStartup.SERVICES.value
if value == "after":
return STARTUP_APPLICATION
return AddonStartup.APPLICATION.value
return value
@@ -182,13 +185,13 @@ def _simple_startup(value):
SCHEMA_ADDON_CONFIG = vol.Schema(
{
vol.Required(ATTR_NAME): vol.Coerce(str),
vol.Required(ATTR_VERSION): 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_ARCH): [vol.In(ARCH_ALL)],
vol.Optional(ATTR_MACHINE): [vol.In(MACHINE_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.In(STARTUP_ALL)),
vol.Required(ATTR_STARTUP): vol.All(_simple_startup, vol.Coerce(AddonStartup)),
vol.Required(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]),
vol.Optional(ATTR_INIT, default=True): vol.Boolean(),
vol.Optional(ATTR_ADVANCED, default=False): vol.Boolean(),
@@ -261,7 +264,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema(
),
vol.Optional(ATTR_IMAGE): vol.Match(RE_DOCKER_IMAGE),
vol.Optional(ATTR_TIMEOUT, default=10): vol.All(
vol.Coerce(int), vol.Range(min=10, max=120)
vol.Coerce(int), vol.Range(min=10, max=300)
),
},
extra=vol.REMOVE_EXTRA,
@@ -385,6 +388,9 @@ def _single_validate(coresys: CoreSys, typ: str, value: Any, key: str):
# parse extend data from type
match = RE_SCHEMA_ELEMENT.match(typ)
if not match:
raise vol.Invalid(f"Unknown type {typ}")
# prepare range
range_args = {}
for group_name in _SCHEMA_LENGTH_PARTS:
@@ -462,7 +468,7 @@ def _check_missing_options(origin, exists, root):
def schema_ui_options(raw_schema: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate UI schema."""
ui_schema = []
ui_schema: List[Dict[str, Any]] = []
# read options
for key, value in raw_schema.items():
@@ -483,7 +489,7 @@ def _single_ui_option(
ui_schema: List[Dict[str, Any]], value: str, key: str, multiple: bool = False
) -> None:
"""Validate a single element."""
ui_node = {"name": key}
ui_node: Dict[str, Union[str, bool, float, List[str]]] = {"name": key}
# If multiple
if multiple:
@@ -491,6 +497,8 @@ def _single_ui_option(
# Parse extend data from type
match = RE_SCHEMA_ELEMENT.match(value)
if not match:
return
# Prepare range
for group_name in _SCHEMA_LENGTH_PARTS:

View File

@@ -7,21 +7,23 @@ from aiohttp import web
from ..coresys import CoreSys, CoreSysAttributes
from .addons import APIAddons
from .audio import APIAudio
from .auth import APIAuth
from .cli import APICli
from .discovery import APIDiscovery
from .dns import APICoreDNS
from .hardware import APIHardware
from .hassos import APIHassOS
from .homeassistant import APIHomeAssistant
from .host import APIHost
from .info import APIInfo
from .ingress import APIIngress
from .multicast import APIMulticast
from .os import APIOS
from .proxy import APIProxy
from .security import SecurityMiddleware
from .services import APIServices
from .snapshots import APISnapshots
from .supervisor import APISupervisor
from .audio import APIAudio
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -49,7 +51,9 @@ class RestAPI(CoreSysAttributes):
"""Register REST API Calls."""
self._register_supervisor()
self._register_host()
self._register_hassos()
self._register_os()
self._register_cli()
self._register_multicast()
self._register_hardware()
self._register_homeassistant()
self._register_proxy()
@@ -72,6 +76,7 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes(
[
web.get("/host/info", api_host.info),
web.get("/host/logs", api_host.logs),
web.post("/host/reboot", api_host.reboot),
web.post("/host/shutdown", api_host.shutdown),
web.post("/host/reload", api_host.reload),
@@ -84,22 +89,44 @@ class RestAPI(CoreSysAttributes):
]
)
def _register_hassos(self) -> None:
"""Register HassOS functions."""
api_hassos = APIHassOS()
api_hassos.coresys = self.coresys
def _register_os(self) -> None:
"""Register OS functions."""
api_os = APIOS()
api_os.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/os/info", api_hassos.info),
web.post("/os/update", api_hassos.update),
web.post("/os/update/cli", api_hassos.update_cli),
web.post("/os/config/sync", api_hassos.config_sync),
# Remove with old Supervisor fallback
web.get("/hassos/info", api_hassos.info),
web.post("/hassos/update", api_hassos.update),
web.post("/hassos/update/cli", api_hassos.update_cli),
web.post("/hassos/config/sync", api_hassos.config_sync),
web.get("/os/info", api_os.info),
web.post("/os/update", api_os.update),
web.post("/os/config/sync", api_os.config_sync),
]
)
def _register_cli(self) -> None:
"""Register HA cli functions."""
api_cli = APICli()
api_cli.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/cli/info", api_cli.info),
web.get("/cli/stats", api_cli.stats),
web.post("/cli/update", api_cli.update),
]
)
def _register_multicast(self) -> None:
"""Register Multicast functions."""
api_multicast = APIMulticast()
api_multicast.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/multicast/info", api_multicast.info),
web.get("/multicast/stats", api_multicast.stats),
web.get("/multicast/logs", api_multicast.logs),
web.post("/multicast/update", api_multicast.update),
web.post("/multicast/restart", api_multicast.restart),
]
)
@@ -353,7 +380,7 @@ class RestAPI(CoreSysAttributes):
try:
await self._site.start()
except OSError as err:
_LOGGER.fatal("Failed to create HTTP server at 0.0.0.0:80 -> %s", err)
_LOGGER.critical("Failed to create HTTP server at 0.0.0.0:80 -> %s", err)
else:
_LOGGER.info("Start API on %s", self.sys_docker.network.supervisor)

View File

@@ -54,7 +54,6 @@ from ..const import (
ATTR_INSTALLED,
ATTR_IP_ADDRESS,
ATTR_KERNEL_MODULES,
ATTR_LAST_VERSION,
ATTR_LOGO,
ATTR_LONG_DESCRIPTION,
ATTR_MACHINE,
@@ -83,6 +82,7 @@ from ..const import (
ATTR_UDEV,
ATTR_URL,
ATTR_VERSION,
ATTR_VERSION_LATEST,
ATTR_VIDEO,
ATTR_WEBUI,
BOOT_AUTO,
@@ -122,9 +122,7 @@ SCHEMA_SECURITY = vol.Schema({vol.Optional(ATTR_PROTECTED): vol.Boolean()})
class APIAddons(CoreSysAttributes):
"""Handle RESTful API for add-on functions."""
def _extract_addon(
self, request: web.Request, check_installed: bool = True
) -> AnyAddon:
def _extract_addon(self, request: web.Request) -> AnyAddon:
"""Return addon, throw an exception it it doesn't exist."""
addon_slug: str = request.match_info.get("addon")
@@ -137,49 +135,49 @@ class APIAddons(CoreSysAttributes):
addon = self.sys_addons.get(addon_slug)
if not addon:
raise APIError("Addon does not exist")
raise APIError(f"Addon {addon_slug} does not exist")
if check_installed and not addon.is_installed:
return addon
def _extract_addon_installed(self, request: web.Request) -> Addon:
addon = self._extract_addon(request)
if not isinstance(addon, Addon) or not addon.is_installed:
raise APIError("Addon is not installed")
return addon
@api_process
async def list(self, request: web.Request) -> Dict[str, Any]:
"""Return all add-ons or repositories."""
data_addons = []
for addon in self.sys_addons.all:
data_addons.append(
{
ATTR_NAME: addon.name,
ATTR_SLUG: addon.slug,
ATTR_DESCRIPTON: addon.description,
ATTR_ADVANCED: addon.advanced,
ATTR_STAGE: addon.stage,
ATTR_VERSION: addon.latest_version,
ATTR_INSTALLED: addon.version if addon.is_installed else None,
ATTR_AVAILABLE: addon.available,
ATTR_DETACHED: addon.is_detached,
ATTR_REPOSITORY: addon.repository,
ATTR_BUILD: addon.need_build,
ATTR_URL: addon.url,
ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo,
}
)
data_repositories = []
for repository in self.sys_store.all:
data_repositories.append(
{
ATTR_SLUG: repository.slug,
ATTR_NAME: repository.name,
ATTR_SOURCE: repository.source,
ATTR_URL: repository.url,
ATTR_MAINTAINER: repository.maintainer,
}
)
data_addons = [
{
ATTR_NAME: addon.name,
ATTR_SLUG: addon.slug,
ATTR_DESCRIPTON: addon.description,
ATTR_ADVANCED: addon.advanced,
ATTR_STAGE: addon.stage,
ATTR_VERSION: addon.latest_version,
ATTR_INSTALLED: addon.version if addon.is_installed else None,
ATTR_AVAILABLE: addon.available,
ATTR_DETACHED: addon.is_detached,
ATTR_REPOSITORY: addon.repository,
ATTR_BUILD: addon.need_build,
ATTR_URL: addon.url,
ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo,
}
for addon in self.sys_addons.all
]
data_repositories = [
{
ATTR_SLUG: repository.slug,
ATTR_NAME: repository.name,
ATTR_SOURCE: repository.source,
ATTR_URL: repository.url,
ATTR_MAINTAINER: repository.maintainer,
}
for repository in self.sys_store.all
]
return {ATTR_ADDONS: data_addons, ATTR_REPOSITORIES: data_repositories}
@api_process
@@ -190,7 +188,7 @@ class APIAddons(CoreSysAttributes):
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return add-on information."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
addon: AnyAddon = self._extract_addon(request)
data = {
ATTR_NAME: addon.name,
@@ -204,7 +202,7 @@ class APIAddons(CoreSysAttributes):
ATTR_AUTO_UPDATE: None,
ATTR_REPOSITORY: addon.repository,
ATTR_VERSION: None,
ATTR_LAST_VERSION: addon.latest_version,
ATTR_VERSION_LATEST: addon.latest_version,
ATTR_PROTECTED: addon.protected,
ATTR_RATING: rating_security(addon),
ATTR_BOOT: addon.boot,
@@ -257,7 +255,7 @@ class APIAddons(CoreSysAttributes):
ATTR_INGRESS_PANEL: None,
}
if addon.is_installed:
if isinstance(addon, Addon) and addon.is_installed:
data.update(
{
ATTR_STATE: await addon.state(),
@@ -279,7 +277,7 @@ class APIAddons(CoreSysAttributes):
@api_process
async def options(self, request: web.Request) -> None:
"""Store user options for add-on."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
# Update secrets for validation
await self.sys_secrets.reload()
@@ -312,7 +310,7 @@ class APIAddons(CoreSysAttributes):
@api_process
async def security(self, request: web.Request) -> None:
"""Store security options for add-on."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
body: Dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
if ATTR_PROTECTED in body:
@@ -324,7 +322,8 @@ class APIAddons(CoreSysAttributes):
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
stats: DockerStats = await addon.stats()
return {
@@ -341,64 +340,57 @@ class APIAddons(CoreSysAttributes):
@api_process
def install(self, request: web.Request) -> Awaitable[None]:
"""Install add-on."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
addon = self._extract_addon(request)
return asyncio.shield(addon.install())
@api_process
def uninstall(self, request: web.Request) -> Awaitable[None]:
"""Uninstall add-on."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
return asyncio.shield(addon.uninstall())
@api_process
def start(self, request: web.Request) -> Awaitable[None]:
"""Start add-on."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
return asyncio.shield(addon.start())
@api_process
def stop(self, request: web.Request) -> Awaitable[None]:
"""Stop add-on."""
addon: AnyAddon = self._extract_addon(request)
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: AnyAddon = self._extract_addon(request)
if addon.latest_version == addon.version:
raise APIError("No update available!")
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."""
addon: AnyAddon = self._extract_addon(request)
addon: Addon = self._extract_addon_installed(request)
return asyncio.shield(addon.restart())
@api_process
def rebuild(self, request: web.Request) -> Awaitable[None]:
"""Rebuild local build add-on."""
addon: AnyAddon = self._extract_addon(request)
if not addon.need_build:
raise APIError("Only local build addons are supported")
addon = self._extract_addon_installed(request)
return asyncio.shield(addon.rebuild())
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return logs from add-on."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
return addon.logs()
@api_process_raw(CONTENT_TYPE_PNG)
async def icon(self, request: web.Request) -> bytes:
"""Return icon from add-on."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
addon = self._extract_addon(request)
if not addon.with_icon:
raise APIError("No icon found!")
raise APIError(f"No icon found for add-on {addon.slug}!")
with addon.path_icon.open("rb") as png:
return png.read()
@@ -406,9 +398,9 @@ class APIAddons(CoreSysAttributes):
@api_process_raw(CONTENT_TYPE_PNG)
async def logo(self, request: web.Request) -> bytes:
"""Return logo from add-on."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
addon = self._extract_addon(request)
if not addon.with_logo:
raise APIError("No logo found!")
raise APIError(f"No logo found for add-on {addon.slug}!")
with addon.path_logo.open("rb") as png:
return png.read()
@@ -416,9 +408,9 @@ class APIAddons(CoreSysAttributes):
@api_process_raw(CONTENT_TYPE_TEXT)
async def changelog(self, request: web.Request) -> str:
"""Return changelog from add-on."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
addon = self._extract_addon(request)
if not addon.with_changelog:
raise APIError("No changelog found!")
raise APIError(f"No changelog found for add-on {addon.slug}!")
with addon.path_changelog.open("r") as changelog:
return changelog.read()
@@ -426,9 +418,9 @@ class APIAddons(CoreSysAttributes):
@api_process_raw(CONTENT_TYPE_TEXT)
async def documentation(self, request: web.Request) -> str:
"""Return documentation from add-on."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
addon = self._extract_addon(request)
if not addon.with_documentation:
raise APIError("No documentation found!")
raise APIError(f"No documentation found for add-on {addon.slug}!")
with addon.path_documentation.open("r") as documentation:
return documentation.read()
@@ -436,9 +428,9 @@ class APIAddons(CoreSysAttributes):
@api_process
async def stdin(self, request: web.Request) -> None:
"""Write to stdin of add-on."""
addon: AnyAddon = self._extract_addon(request)
addon = self._extract_addon_installed(request)
if not addon.with_stdin:
raise APIError("STDIN not supported by add-on")
raise APIError(f"STDIN not supported the {addon.slug} add-on")
data = await request.read()
await asyncio.shield(addon.write_stdin(data))
@@ -448,13 +440,10 @@ def _pretty_devices(addon: AnyAddon) -> List[str]:
"""Return a simplified device list."""
dev_list = addon.devices
if not dev_list:
return None
return []
return [row.split(":")[0] for row in dev_list]
def _pretty_services(addon: AnyAddon) -> List[str]:
"""Return a simplified services role list."""
services = []
for name, access in addon.services_role.items():
services.append(f"{name}:{access}")
return services
return [f"{name}:{access}" for name, access in addon.services_role.items()]

View File

@@ -18,7 +18,6 @@ from ..const import (
ATTR_HOST,
ATTR_INDEX,
ATTR_INPUT,
ATTR_LATEST_VERSION,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
ATTR_MEMORY_USAGE,
@@ -27,17 +26,19 @@ from ..const import (
ATTR_NETWORK_TX,
ATTR_OUTPUT,
ATTR_VERSION,
ATTR_VERSION_LATEST,
ATTR_VOLUME,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..host.sound import StreamType
from ..validate import version_tag
from .utils import api_process, api_process_raw, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
SCHEMA_VOLUME = vol.Schema(
{
@@ -68,8 +69,8 @@ class APIAudio(CoreSysAttributes):
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return Audio information."""
return {
ATTR_VERSION: self.sys_audio.version,
ATTR_LATEST_VERSION: self.sys_audio.latest_version,
ATTR_VERSION: self.sys_plugins.audio.version,
ATTR_VERSION_LATEST: self.sys_plugins.audio.latest_version,
ATTR_HOST: str(self.sys_docker.network.audio),
ATTR_AUDIO: {
ATTR_CARD: [attr.asdict(card) for card in self.sys_host.sound.cards],
@@ -88,7 +89,7 @@ class APIAudio(CoreSysAttributes):
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
stats = await self.sys_audio.stats()
stats = await self.sys_plugins.audio.stats()
return {
ATTR_CPU_PERCENT: stats.cpu_percent,
@@ -105,21 +106,21 @@ class APIAudio(CoreSysAttributes):
async def update(self, request: web.Request) -> None:
"""Update Audio plugin."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_audio.latest_version)
version = body.get(ATTR_VERSION, self.sys_plugins.audio.latest_version)
if version == self.sys_audio.version:
raise APIError("Version {} is already in use".format(version))
await asyncio.shield(self.sys_audio.update(version))
if version == self.sys_plugins.audio.version:
raise APIError(f"Version {version} is already in use")
await asyncio.shield(self.sys_plugins.audio.update(version))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return Audio Docker logs."""
return self.sys_audio.logs()
return self.sys_plugins.audio.logs()
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart Audio plugin."""
return asyncio.shield(self.sys_audio.restart())
return asyncio.shield(self.sys_plugins.audio.restart())
@api_process
def reload(self, request: web.Request) -> Awaitable[None]:
@@ -166,5 +167,5 @@ class APIAudio(CoreSysAttributes):
body = await api_validate(SCHEMA_PROFILE, request)
await asyncio.shield(
self.sys_host.sound.set_profile(body[ATTR_CARD], body[ATTR_NAME])
self.sys_host.sound.ativate_profile(body[ATTR_CARD], body[ATTR_NAME])
)

63
supervisor/api/cli.py Normal file
View File

@@ -0,0 +1,63 @@
"""Init file for Supervisor HA cli RESTful API."""
import asyncio
import logging
from typing import Any, Dict
from aiohttp import web
import voluptuous as vol
from ..const import (
ATTR_BLK_READ,
ATTR_BLK_WRITE,
ATTR_CPU_PERCENT,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
ATTR_MEMORY_USAGE,
ATTR_NETWORK_RX,
ATTR_NETWORK_TX,
ATTR_VERSION,
ATTR_VERSION_LATEST,
)
from ..coresys import CoreSysAttributes
from ..validate import version_tag
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
class APICli(CoreSysAttributes):
"""Handle RESTful API for HA Cli functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return HA cli information."""
return {
ATTR_VERSION: self.sys_plugins.cli.version,
ATTR_VERSION_LATEST: self.sys_plugins.cli.latest_version,
}
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.cli.stats()
return {
ATTR_CPU_PERCENT: stats.cpu_percent,
ATTR_MEMORY_USAGE: stats.memory_usage,
ATTR_MEMORY_LIMIT: stats.memory_limit,
ATTR_MEMORY_PERCENT: stats.memory_percent,
ATTR_NETWORK_RX: stats.network_rx,
ATTR_NETWORK_TX: stats.network_tx,
ATTR_BLK_READ: stats.blk_read,
ATTR_BLK_WRITE: stats.blk_write,
}
@api_process
async def update(self, request: web.Request) -> None:
"""Update HA CLI."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_plugins.cli.latest_version)
await asyncio.shield(self.sys_plugins.cli.update(version))

View File

@@ -1,19 +1,19 @@
"""Init file for Supervisor network RESTful API."""
import voluptuous as vol
from .utils import api_process, api_validate
from ..const import (
ATTR_ADDON,
ATTR_UUID,
ATTR_CONFIG,
ATTR_DISCOVERY,
ATTR_SERVICE,
ATTR_SERVICES,
ATTR_UUID,
REQUEST_FROM,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, APIForbidden
from ..discovery.validate import valid_discovery_service
from ..exceptions import APIError, APIForbidden
from .utils import api_process, api_validate
SCHEMA_DISCOVERY = vol.Schema(
{
@@ -43,6 +43,7 @@ class APIDiscovery(CoreSysAttributes):
"""Show register services."""
self._check_permission_ha(request)
# Get available discovery
discovery = []
for message in self.sys_discovery.list_messages:
discovery.append(
@@ -54,7 +55,13 @@ class APIDiscovery(CoreSysAttributes):
}
)
return {ATTR_DISCOVERY: discovery}
# Get available services/add-ons
services = {}
for addon in self.sys_addons.all:
for name in addon.discovery:
services.setdefault(name, []).append(addon.slug)
return {ATTR_DISCOVERY: discovery, ATTR_SERVICES: services}
@api_process
async def set_discovery(self, request):
@@ -64,7 +71,7 @@ class APIDiscovery(CoreSysAttributes):
# Access?
if body[ATTR_SERVICE] not in addon.discovery:
raise APIForbidden(f"Can't use discovery!")
raise APIForbidden("Can't use discovery!")
# Process discovery message
message = self.sys_discovery.send(addon, **body)
@@ -94,7 +101,7 @@ class APIDiscovery(CoreSysAttributes):
# Permission
if message.addon != addon.slug:
raise APIForbidden(f"Can't remove discovery message")
raise APIForbidden("Can't remove discovery message")
self.sys_discovery.remove(message)
return True

View File

@@ -11,7 +11,6 @@ from ..const import (
ATTR_BLK_WRITE,
ATTR_CPU_PERCENT,
ATTR_HOST,
ATTR_LATEST_VERSION,
ATTR_LOCALS,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
@@ -20,11 +19,12 @@ from ..const import (
ATTR_NETWORK_TX,
ATTR_SERVERS,
ATTR_VERSION,
ATTR_VERSION_LATEST,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import dns_server_list
from ..validate import dns_server_list, version_tag
from .utils import api_process, api_process_raw, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -32,7 +32,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
# pylint: disable=no-value-for-parameter
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_SERVERS): dns_server_list})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
class APICoreDNS(CoreSysAttributes):
@@ -42,10 +42,10 @@ class APICoreDNS(CoreSysAttributes):
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return DNS information."""
return {
ATTR_VERSION: self.sys_dns.version,
ATTR_LATEST_VERSION: self.sys_dns.latest_version,
ATTR_VERSION: self.sys_plugins.dns.version,
ATTR_VERSION_LATEST: self.sys_plugins.dns.latest_version,
ATTR_HOST: str(self.sys_docker.network.dns),
ATTR_SERVERS: self.sys_dns.servers,
ATTR_SERVERS: self.sys_plugins.dns.servers,
ATTR_LOCALS: self.sys_host.network.dns_servers,
}
@@ -55,15 +55,15 @@ class APICoreDNS(CoreSysAttributes):
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_SERVERS in body:
self.sys_dns.servers = body[ATTR_SERVERS]
self.sys_create_task(self.sys_dns.restart())
self.sys_plugins.dns.servers = body[ATTR_SERVERS]
self.sys_create_task(self.sys_plugins.dns.restart())
self.sys_dns.save_data()
self.sys_plugins.dns.save_data()
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
stats = await self.sys_dns.stats()
stats = await self.sys_plugins.dns.stats()
return {
ATTR_CPU_PERCENT: stats.cpu_percent,
@@ -80,23 +80,23 @@ class APICoreDNS(CoreSysAttributes):
async def update(self, request: web.Request) -> None:
"""Update DNS plugin."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_dns.latest_version)
version = body.get(ATTR_VERSION, self.sys_plugins.dns.latest_version)
if version == self.sys_dns.version:
raise APIError("Version {} is already in use".format(version))
await asyncio.shield(self.sys_dns.update(version))
if version == self.sys_plugins.dns.version:
raise APIError(f"Version {version} is already in use")
await asyncio.shield(self.sys_plugins.dns.update(version))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return DNS Docker logs."""
return self.sys_dns.logs()
return self.sys_plugins.dns.logs()
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart CoreDNS plugin."""
return asyncio.shield(self.sys_dns.restart())
return asyncio.shield(self.sys_plugins.dns.restart())
@api_process
def reset(self, request: web.Request) -> Awaitable[None]:
"""Reset CoreDNS plugin."""
return asyncio.shield(self.sys_dns.reset())
return asyncio.shield(self.sys_plugins.dns.reset())

View File

@@ -1,20 +1,20 @@
"""Init file for Supervisor hardware RESTful API."""
import asyncio
import logging
from typing import Any, Dict
from typing import Any, Awaitable, Dict
from aiohttp import web
from .utils import api_process
from ..const import (
ATTR_SERIAL,
ATTR_AUDIO,
ATTR_DISK,
ATTR_GPIO,
ATTR_AUDIO,
ATTR_INPUT,
ATTR_OUTPUT,
ATTR_SERIAL,
)
from ..coresys import CoreSysAttributes
from .utils import api_process
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -52,6 +52,6 @@ class APIHardware(CoreSysAttributes):
}
@api_process
def trigger(self, request: web.Request) -> None:
def trigger(self, request: web.Request) -> Awaitable[None]:
"""Trigger a udev device reload."""
return asyncio.shield(self.sys_hardware.udev_trigger())

View File

@@ -1,59 +0,0 @@
"""Init file for Supervisor HassOS RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from aiohttp import web
import voluptuous as vol
from ..const import (
ATTR_BOARD,
ATTR_BOOT,
ATTR_VERSION,
ATTR_VERSION_CLI,
ATTR_VERSION_CLI_LATEST,
ATTR_VERSION_LATEST,
)
from ..coresys import CoreSysAttributes
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
class APIHassOS(CoreSysAttributes):
"""Handle RESTful API for HassOS functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return HassOS information."""
return {
ATTR_VERSION: self.sys_hassos.version,
ATTR_VERSION_CLI: self.sys_hassos.version_cli,
ATTR_VERSION_LATEST: self.sys_hassos.version_latest,
ATTR_VERSION_CLI_LATEST: self.sys_hassos.version_cli_latest,
ATTR_BOARD: self.sys_hassos.board,
ATTR_BOOT: self.sys_dbus.rauc.boot_slot,
}
@api_process
async def update(self, request: web.Request) -> None:
"""Update HassOS."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_hassos.version_latest)
await asyncio.shield(self.sys_hassos.update(version))
@api_process
async def update_cli(self, request: web.Request) -> None:
"""Update HassOS CLI."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_hassos.version_cli_latest)
await asyncio.shield(self.sys_hassos.update_cli(version))
@api_process
def config_sync(self, request: web.Request) -> Awaitable[None]:
"""Trigger config reload on HassOS."""
return asyncio.shield(self.sys_hassos.config_sync())

View File

@@ -1,7 +1,7 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import asyncio
import logging
from typing import Any, Coroutine, Dict
from typing import Any, Awaitable, Dict
from aiohttp import web
import voluptuous as vol
@@ -14,10 +14,8 @@ from ..const import (
ATTR_BLK_WRITE,
ATTR_BOOT,
ATTR_CPU_PERCENT,
ATTR_CUSTOM,
ATTR_IMAGE,
ATTR_IP_ADDRESS,
ATTR_LAST_VERSION,
ATTR_MACHINE,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
@@ -28,13 +26,14 @@ from ..const import (
ATTR_REFRESH_TOKEN,
ATTR_SSL,
ATTR_VERSION,
ATTR_VERSION_LATEST,
ATTR_WAIT_BOOT,
ATTR_WATCHDOG,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import docker_image, network_port
from ..validate import docker_image, network_port, version_tag
from .utils import api_process, api_process_raw, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -43,8 +42,7 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_BOOT): vol.Boolean(),
vol.Inclusive(ATTR_IMAGE, "custom_hass"): vol.Maybe(docker_image),
vol.Inclusive(ATTR_LAST_VERSION, "custom_hass"): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_IMAGE): docker_image,
vol.Optional(ATTR_PORT): network_port,
vol.Optional(ATTR_SSL): vol.Boolean(),
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
@@ -55,7 +53,7 @@ SCHEMA_OPTIONS = vol.Schema(
}
)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
class APIHomeAssistant(CoreSysAttributes):
@@ -66,12 +64,11 @@ class APIHomeAssistant(CoreSysAttributes):
"""Return host information."""
return {
ATTR_VERSION: self.sys_homeassistant.version,
ATTR_LAST_VERSION: self.sys_homeassistant.latest_version,
ATTR_VERSION_LATEST: self.sys_homeassistant.latest_version,
ATTR_MACHINE: self.sys_homeassistant.machine,
ATTR_IP_ADDRESS: str(self.sys_homeassistant.ip_address),
ATTR_ARCH: self.sys_homeassistant.arch,
ATTR_IMAGE: self.sys_homeassistant.image,
ATTR_CUSTOM: self.sys_homeassistant.is_custom_image,
ATTR_BOOT: self.sys_homeassistant.boot,
ATTR_PORT: self.sys_homeassistant.api_port,
ATTR_SSL: self.sys_homeassistant.api_ssl,
@@ -79,6 +76,8 @@ class APIHomeAssistant(CoreSysAttributes):
ATTR_WAIT_BOOT: self.sys_homeassistant.wait_boot,
ATTR_AUDIO_INPUT: self.sys_homeassistant.audio_input,
ATTR_AUDIO_OUTPUT: self.sys_homeassistant.audio_output,
# Remove end of Q3 2020
"last_version": self.sys_homeassistant.latest_version,
}
@api_process
@@ -86,9 +85,8 @@ class APIHomeAssistant(CoreSysAttributes):
"""Set Home Assistant options."""
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_IMAGE in body and ATTR_LAST_VERSION in body:
if ATTR_IMAGE in body:
self.sys_homeassistant.image = body[ATTR_IMAGE]
self.sys_homeassistant.latest_version = body[ATTR_LAST_VERSION]
if ATTR_BOOT in body:
self.sys_homeassistant.boot = body[ATTR_BOOT]
@@ -143,27 +141,27 @@ class APIHomeAssistant(CoreSysAttributes):
await asyncio.shield(self.sys_homeassistant.update(version))
@api_process
def stop(self, request: web.Request) -> Coroutine:
def stop(self, request: web.Request) -> Awaitable[None]:
"""Stop Home Assistant."""
return asyncio.shield(self.sys_homeassistant.stop())
@api_process
def start(self, request: web.Request) -> Coroutine:
def start(self, request: web.Request) -> Awaitable[None]:
"""Start Home Assistant."""
return asyncio.shield(self.sys_homeassistant.start())
@api_process
def restart(self, request: web.Request) -> Coroutine:
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart Home Assistant."""
return asyncio.shield(self.sys_homeassistant.restart())
@api_process
def rebuild(self, request: web.Request) -> Coroutine:
def rebuild(self, request: web.Request) -> Awaitable[None]:
"""Rebuild Home Assistant."""
return asyncio.shield(self.sys_homeassistant.rebuild())
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Coroutine:
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return Home Assistant Docker logs."""
return self.sys_homeassistant.logs()

View File

@@ -1,24 +1,27 @@
"""Init file for Supervisor host RESTful API."""
import asyncio
import logging
from typing import Awaitable
from aiohttp import web
import voluptuous as vol
from .utils import api_process, api_validate
from ..const import (
ATTR_HOSTNAME,
ATTR_FEATURES,
ATTR_KERNEL,
ATTR_OPERATING_SYSTEM,
ATTR_CHASSIS,
ATTR_DEPLOYMENT,
ATTR_STATE,
ATTR_NAME,
ATTR_DESCRIPTON,
ATTR_SERVICES,
ATTR_CPE,
ATTR_DEPLOYMENT,
ATTR_DESCRIPTON,
ATTR_FEATURES,
ATTR_HOSTNAME,
ATTR_KERNEL,
ATTR_NAME,
ATTR_OPERATING_SYSTEM,
ATTR_SERVICES,
ATTR_STATE,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from .utils import api_process, api_process_raw, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
@@ -107,3 +110,8 @@ class APIHost(CoreSysAttributes):
"""Restart a service."""
unit = request.match_info.get(SERVICE)
return asyncio.shield(self.sys_host.services.restart(unit))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return host kernel logs."""
return self.sys_host.info.get_dmesg()

View File

@@ -7,6 +7,7 @@ from aiohttp import web
from ..const import (
ATTR_ARCH,
ATTR_CHANNEL,
ATTR_DOCKER,
ATTR_HASSOS,
ATTR_HOMEASSISTANT,
ATTR_HOSTNAME,
@@ -32,6 +33,7 @@ class APIInfo(CoreSysAttributes):
ATTR_SUPERVISOR: self.sys_supervisor.version,
ATTR_HOMEASSISTANT: self.sys_homeassistant.version,
ATTR_HASSOS: self.sys_hassos.version,
ATTR_DOCKER: self.sys_docker.info.version,
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_MACHINE: self.sys_machine,
ATTR_ARCH: self.sys_arch.default,

View File

@@ -16,11 +16,11 @@ from multidict import CIMultiDict, istr
from ..addons.addon import Addon
from ..const import (
ATTR_ADMIN,
ATTR_ENABLE,
ATTR_ICON,
ATTR_PANELS,
ATTR_SESSION,
ATTR_TITLE,
ATTR_PANELS,
ATTR_ENABLE,
COOKIE_INGRESS,
HEADER_TOKEN,
HEADER_TOKEN_OLD,
@@ -129,7 +129,7 @@ class APIIngress(CoreSysAttributes):
# Support GET query
if request.query_string:
url = "{}?{}".format(url, request.query_string)
url = f"{url}?{request.query_string}"
# Start proxy
async with self.sys_websession.ws_connect(

View File

@@ -0,0 +1,77 @@
"""Init file for Supervisor Multicast RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from aiohttp import web
import voluptuous as vol
from ..const import (
ATTR_BLK_READ,
ATTR_BLK_WRITE,
ATTR_CPU_PERCENT,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
ATTR_MEMORY_USAGE,
ATTR_NETWORK_RX,
ATTR_NETWORK_TX,
ATTR_VERSION,
ATTR_VERSION_LATEST,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import version_tag
from .utils import api_process, api_process_raw, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
class APIMulticast(CoreSysAttributes):
"""Handle RESTful API for Multicast functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return Multicast information."""
return {
ATTR_VERSION: self.sys_plugins.multicast.version,
ATTR_VERSION_LATEST: self.sys_plugins.multicast.latest_version,
}
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
stats = await self.sys_plugins.multicast.stats()
return {
ATTR_CPU_PERCENT: stats.cpu_percent,
ATTR_MEMORY_USAGE: stats.memory_usage,
ATTR_MEMORY_LIMIT: stats.memory_limit,
ATTR_MEMORY_PERCENT: stats.memory_percent,
ATTR_NETWORK_RX: stats.network_rx,
ATTR_NETWORK_TX: stats.network_tx,
ATTR_BLK_READ: stats.blk_read,
ATTR_BLK_WRITE: stats.blk_write,
}
@api_process
async def update(self, request: web.Request) -> None:
"""Update Multicast plugin."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_plugins.multicast.latest_version)
if version == self.sys_plugins.multicast.version:
raise APIError(f"Version {version} is already in use")
await asyncio.shield(self.sys_plugins.multicast.update(version))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return Multicast Docker logs."""
return self.sys_plugins.multicast.logs()
@api_process
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart Multicast plugin."""
return asyncio.shield(self.sys_plugins.multicast.restart())

43
supervisor/api/os.py Normal file
View File

@@ -0,0 +1,43 @@
"""Init file for Supervisor HassOS RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from aiohttp import web
import voluptuous as vol
from ..const import ATTR_BOARD, ATTR_BOOT, ATTR_VERSION, ATTR_VERSION_LATEST
from ..coresys import CoreSysAttributes
from ..validate import version_tag
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): version_tag})
class APIOS(CoreSysAttributes):
"""Handle RESTful API for OS functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return OS information."""
return {
ATTR_VERSION: self.sys_hassos.version,
ATTR_VERSION_LATEST: self.sys_hassos.latest_version,
ATTR_BOARD: self.sys_hassos.board,
ATTR_BOOT: self.sys_dbus.rauc.boot_slot,
}
@api_process
async def update(self, request: web.Request) -> None:
"""Update OS."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_hassos.latest_version)
await asyncio.shield(self.sys_hassos.update(version))
@api_process
def config_sync(self, request: web.Request) -> Awaitable[None]:
"""Trigger config reload on OS."""
return asyncio.shield(self.sys_hassos.config_sync())

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
(self.webpackJsonp=self.webpackJsonp||[]).push([[2],{177:function(e,r,n){"use strict";n.r(r),n.d(r,"codeMirror",function(){return c}),n.d(r,"codeMirrorCss",function(){return i});var a=n(54),o=n.n(a),s=n(170),t=(n(171),n(172),n(11));o.a.commands.save=function(e){Object(t.a)(e.getWrapperElement(),"editor-save")};var c=o.a,i=s.a}}]);
//# sourceMappingURL=chunk.26756b56961f7bf94974.js.map

View File

@@ -1 +0,0 @@
{"version":3,"sources":["webpack:///./src/resources/codemirror.ts"],"names":["__webpack_require__","r","__webpack_exports__","d","codeMirror","codeMirrorCss","codemirror__WEBPACK_IMPORTED_MODULE_0__","codemirror__WEBPACK_IMPORTED_MODULE_0___default","n","codemirror_lib_codemirror_css__WEBPACK_IMPORTED_MODULE_1__","_common_dom_fire_event__WEBPACK_IMPORTED_MODULE_4__","_CodeMirror","commands","save","cm","fireEvent","getWrapperElement","_codeMirrorCss"],"mappings":"sFAAAA,EAAAC,EAAAC,GAAAF,EAAAG,EAAAD,EAAA,+BAAAE,IAAAJ,EAAAG,EAAAD,EAAA,kCAAAG,IAAA,IAAAC,EAAAN,EAAA,IAAAO,EAAAP,EAAAQ,EAAAF,GAAAG,EAAAT,EAAA,KAAAU,GAAAV,EAAA,KAAAA,EAAA,KAAAA,EAAA,KAQAW,IAAYC,SAASC,KAAO,SAACC,GAC3BC,YAAUD,EAAGE,oBAAqB,gBAE7B,IAAMZ,EAAkBO,IAClBN,EAAqBY","file":"chunk.26756b56961f7bf94974.js","sourcesContent":["// @ts-ignore\nimport _CodeMirror, { Editor } from \"codemirror\";\n// @ts-ignore\nimport _codeMirrorCss from \"codemirror/lib/codemirror.css\";\nimport \"codemirror/mode/yaml/yaml\";\nimport \"codemirror/mode/jinja2/jinja2\";\nimport { fireEvent } from \"../common/dom/fire_event\";\n\n_CodeMirror.commands.save = (cm: Editor) => {\n fireEvent(cm.getWrapperElement(), \"editor-save\");\n};\nexport const codeMirror: any = _CodeMirror;\nexport const codeMirrorCss: any = _codeMirrorCss;\n"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"version":3,"sources":["webpack:///./hassio/src/ingress-view/hassio-ingress-view.ts"],"names":["customElement","HassioIngressView","property","this","_addon","html","_templateObject2","name","ingress_url","_templateObject","changedProps","_get","_getPrototypeOf","prototype","call","has","addon","route","path","substr","oldRoute","get","oldAddon","undefined","_fetchData","_callee","addonSlug","_ref","_ref2","regeneratorRuntime","wrap","_context","prev","next","Promise","all","fetchHassioAddonInfo","hass","Error","createHassioSession","sent","_slicedToArray","ingress","t0","console","error","alert","message","history","back","stop","css","_templateObject3","LitElement"],"mappings":"snSAmBCA,YAAc,0CACTC,smBACHC,kEACAA,mEACAA,4EAED,WACE,OAAKC,KAAKC,OAMHC,YAAPC,IAC0BH,KAAKC,OAAOG,KACpBJ,KAAKC,OAAOI,aAPrBH,YAAPI,0CAYJ,SAAkBC,GAGhB,GAFAC,EAAAC,EApBEX,EAoBFY,WAAA,eAAAV,MAAAW,KAAAX,KAAmBO,GAEdA,EAAaK,IAAI,SAAtB,CAIA,IAAMC,EAAQb,KAAKc,MAAMC,KAAKC,OAAO,GAE/BC,EAAWV,EAAaW,IAAI,SAC5BC,EAAWF,EAAWA,EAASF,KAAKC,OAAO,QAAKI,EAElDP,GAASA,IAAUM,GACrBnB,KAAKqB,WAAWR,0FAIpB,SAAAS,EAAyBC,GAAzB,IAAAC,EAAAC,EAAAZ,EAAA,OAAAa,mBAAAC,KAAA,SAAAC,GAAA,cAAAA,EAAAC,KAAAD,EAAAE,MAAA,cAAAF,EAAAC,KAAA,EAAAD,EAAAE,KAAA,EAE0BC,QAAQC,IAAI,CAChCC,YAAqBjC,KAAKkC,KAAMX,GAAhC,MAAiD,WAC/C,MAAM,IAAIY,MAAM,iCAElBC,YAAoBpC,KAAKkC,MAAzB,MAAqC,WACnC,MAAM,IAAIC,MAAM,2CAPxB,UAAAX,EAAAI,EAAAS,KAAAZ,EAAAa,EAAAd,EAAA,IAEWX,EAFXY,EAAA,IAWec,QAXf,CAAAX,EAAAE,KAAA,cAYY,IAAIK,MAAM,wCAZtB,OAeInC,KAAKC,OAASY,EAflBe,EAAAE,KAAA,iBAAAF,EAAAC,KAAA,GAAAD,EAAAY,GAAAZ,EAAA,SAkBIa,QAAQC,MAARd,EAAAY,IACAG,MAAMf,EAAAY,GAAII,SAAW,mCACrBC,QAAQC,OApBZ,yBAAAlB,EAAAmB,SAAAzB,EAAAtB,KAAA,yRAwBA,WACE,OAAOgD,YAAPC,UA7D4BC","file":"chunk.35929da61d769e57c884.js","sourcesContent":["import {\n LitElement,\n customElement,\n property,\n TemplateResult,\n html,\n PropertyValues,\n CSSResult,\n css,\n} from \"lit-element\";\nimport { HomeAssistant, Route } from \"../../../src/types\";\nimport { createHassioSession } from \"../../../src/data/hassio/supervisor\";\nimport {\n HassioAddonDetails,\n fetchHassioAddonInfo,\n} from \"../../../src/data/hassio/addon\";\nimport \"../../../src/layouts/hass-loading-screen\";\nimport \"../../../src/layouts/hass-subpage\";\n\n@customElement(\"hassio-ingress-view\")\nclass HassioIngressView extends LitElement {\n @property() public hass!: HomeAssistant;\n @property() public route!: Route;\n @property() private _addon?: HassioAddonDetails;\n\n protected render(): TemplateResult {\n if (!this._addon) {\n return html`\n <hass-loading-screen></hass-loading-screen>\n `;\n }\n\n return html`\n <hass-subpage .header=${this._addon.name} hassio>\n <iframe src=${this._addon.ingress_url}></iframe>\n </hass-subpage>\n `;\n }\n\n protected updated(changedProps: PropertyValues) {\n super.firstUpdated(changedProps);\n\n if (!changedProps.has(\"route\")) {\n return;\n }\n\n const addon = this.route.path.substr(1);\n\n const oldRoute = changedProps.get(\"route\") as this[\"route\"] | undefined;\n const oldAddon = oldRoute ? oldRoute.path.substr(1) : undefined;\n\n if (addon && addon !== oldAddon) {\n this._fetchData(addon);\n }\n }\n\n private async _fetchData(addonSlug: string) {\n try {\n const [addon] = await Promise.all([\n fetchHassioAddonInfo(this.hass, addonSlug).catch(() => {\n throw new Error(\"Failed to fetch add-on info\");\n }),\n createHassioSession(this.hass).catch(() => {\n throw new Error(\"Failed to create an ingress session\");\n }),\n ]);\n\n if (!addon.ingress) {\n throw new Error(\"This add-on does not support ingress\");\n }\n\n this._addon = addon;\n } catch (err) {\n // tslint:disable-next-line\n console.error(err);\n alert(err.message || \"Unknown error starting ingress.\");\n history.back();\n }\n }\n\n static get styles(): CSSResult {\n return css`\n iframe {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n }\n paper-icon-button {\n color: var(--text-primary-color);\n }\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"hassio-ingress-view\": HassioIngressView;\n }\n}\n"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +0,0 @@
/**
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at
http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
part of the polymer project is also subject to an additional IP rights grant
found at http://polymer.github.io/PATENTS.txt
*/

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