Compare commits

...

1328 Commits
0.23 ... 178

Author SHA1 Message Date
Pascal Vizeli
2e53a48504 Merge pull request #1224 from home-assistant/dev
Release 178
2019-08-16 13:26:45 +02:00
Pascal Vizeli
8e4db0c3ec Stripe resolv (#1226) 2019-08-16 13:22:07 +02:00
Pascal Vizeli
4072b06faf Fix issue on isntalled add-ons (#1225) 2019-08-16 13:12:39 +02:00
Pascal Vizeli
a2cf7ece70 Change handling with host files (#1223) 2019-08-16 12:47:32 +02:00
Pascal Vizeli
734fe3afde Bump version 178 2019-08-16 00:15:05 +02:00
Pascal Vizeli
7f3bc91c1d Merge pull request #1222 from home-assistant/dev
Release 177
2019-08-16 00:13:51 +02:00
Pascal Vizeli
9c2c95757d Validate dns better (#1221) 2019-08-15 23:48:14 +02:00
Franck Nijhof
b5ed6c586a Cleanup ingress panel on add-on uninstall (#1220)
* Cleanup ingress panel on add-on uninstall

* Update __init__.py
2019-08-15 23:05:03 +02:00
Franck Nijhof
35033d1f76 Allow manager role to access DNS API (#1219) 2019-08-15 22:38:34 +02:00
Pascal Vizeli
9e41d0c5b0 Bump version 177 2019-08-15 14:51:28 +02:00
Pascal Vizeli
62e92fada9 Merge pull request #1218 from home-assistant/dev
Release 176
2019-08-15 14:50:55 +02:00
dependabot-preview[bot]
ae0a1a657f Bump gitpython from 3.0.0 to 3.0.1 (#1216)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.0.0 to 3.0.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.0.0...3.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-15 14:46:16 +02:00
Pascal Vizeli
81e511ba8e Fix spell 2019-08-15 12:42:34 +00:00
Pascal Vizeli
d89cb91c8c Revert "Call update of resolv later (#1215)" (#1217)
This reverts commit dc31b6e6fe.
2019-08-15 14:42:05 +02:00
Pascal Vizeli
dc31b6e6fe Call update of resolv later (#1215) 2019-08-15 13:57:44 +02:00
Pascal Vizeli
930a32de1a Fix latest issue (#1214)
* Fix latest issue

* Use also update now

* Fix style
2019-08-15 12:42:21 +02:00
Pascal Vizeli
e40f2ed8e3 Bump version 176 2019-08-15 11:36:47 +02:00
Pascal Vizeli
abbd3d1078 Merge pull request #1213 from home-assistant/dev
Release 175
2019-08-15 11:36:06 +02:00
Pascal Vizeli
63c9948456 Add CoreDNS to update process (#1212) 2019-08-15 11:05:08 +02:00
Pascal Vizeli
b6c81d779a Use own coredns for supervisor 2019-08-15 08:51:42 +00:00
Pascal Vizeli
2480c83169 Fix socat command (#1211) 2019-08-15 10:17:41 +02:00
Pascal Vizeli
334cc66cf6 Bump Version 175 2019-08-14 15:39:44 +02:00
Pascal Vizeli
3cf189ad94 Merge pull request #1209 from home-assistant/dev
Release 174
2019-08-14 15:38:57 +02:00
dependabot-preview[bot]
6ffb94a0f5 Bump ptvsd from 4.3.1 to 4.3.2 (#1207)
Bumps [ptvsd](https://github.com/Microsoft/ptvsd) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/Microsoft/ptvsd/releases)
- [Commits](https://github.com/Microsoft/ptvsd/compare/v4.3.1...v4.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-14 14:35:43 +02:00
Pascal Vizeli
3593826441 Fix issue with windows dev env 2019-08-14 10:37:39 +00:00
Pascal Vizeli
0a0a62f238 Addon provide his own udev support (#1206)
* Addon provide his own udev support

* upgrade logger
2019-08-14 12:29:00 +02:00
Pascal Vizeli
41ce9913d2 Stats percent (#1205)
* Fix stats and add Memory percent

* Fix tasks

* round percent
2019-08-14 10:47:11 +02:00
Pascal Vizeli
b77c42384d Add DNS to add-on (#1204) 2019-08-14 09:53:03 +02:00
Pascal Vizeli
138bb12f98 Add debug output to gdbus (#1203) 2019-08-13 21:25:04 +02:00
Pascal Vizeli
4fe2859f4e Rename scripts folder (#1202)
* Rename script folder

* Rename scripts
2019-08-13 14:39:32 +02:00
dependabot-preview[bot]
0768b2b4bc Bump ptvsd from 4.3.0 to 4.3.1 (#1200)
Bumps [ptvsd](https://github.com/Microsoft/ptvsd) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/Microsoft/ptvsd/releases)
- [Commits](https://github.com/Microsoft/ptvsd/compare/v4.3.0...v4.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-13 14:35:41 +02:00
dependabot-preview[bot]
e6f1772a93 Bump gitpython from 2.1.13 to 3.0.0 (#1199)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 2.1.13 to 3.0.0.
- [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/2.1.13...3.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-13 14:35:15 +02:00
dependabot-preview[bot]
5374b2b3b9 Bump voluptuous from 0.11.5 to 0.11.7 (#1201)
Bumps [voluptuous](https://github.com/alecthomas/voluptuous) from 0.11.5 to 0.11.7.
- [Release notes](https://github.com/alecthomas/voluptuous/releases)
- [Changelog](https://github.com/alecthomas/voluptuous/blob/master/CHANGELOG.md)
- [Commits](https://github.com/alecthomas/voluptuous/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-13 14:29:33 +02:00
Pascal Vizeli
1196788856 Add CoreDNS as DNS backend (#1195)
* Add CoreDNS / DNS configuration

* Support get version

* add version

* add coresys

* Add more logic

* move forwareder into dns

* Setup docker inside

* add docker to env

* Add more function

* more interface

* Update hosts template

* Add DNS folder

* Fix issues

* Add more logic

* Add handling for hosts

* Fix setting

* fix lint

* Fix some issues

* Fix issue

* Run with no cache

* Fix issue on validate

* Fix bug

* Allow to jump into dev mode

* Fix permission

* Fix issue

* Add dns search

* Add watchdog

* Fix set issues

* add API description

* Add API endpoint

* Add CLI support

* Fix logs + add hostname

* Add/remove DNS entry

* Fix attribute

* Fix style

* Better shutdown

* Remove ha from network mapping

* Add more options

* Fix env shutdown

* Add support for new repair function

* Start coreDNS faster after restart

* remove options

* Fix ha fix
2019-08-13 14:20:42 +02:00
Pascal Vizeli
9f3f47eb80 Bump version 174 2019-08-11 09:59:48 +02:00
Pascal Vizeli
1a90a478f2 Merge pull request #1197 from home-assistant/dev
Release 173
2019-08-11 09:39:17 +02:00
Pascal Vizeli
ee773f3b63 Fix hanging landingpage (#1196) 2019-08-11 09:05:47 +02:00
Pascal Vizeli
5ffc27f60c Bump version 173 2019-08-08 23:24:11 +02:00
Pascal Vizeli
4c13dfb43c Merge pull request #1194 from home-assistant/dev
Release 172
2019-08-08 23:21:26 +02:00
Pascal Vizeli
bc099f0d81 Fix Version detection with exists container (#1193) 2019-08-08 23:20:26 +02:00
Pascal Vizeli
b26dd0af19 Add better log output for repair (#1191) 2019-08-08 10:14:13 +02:00
Pascal Vizeli
0dee5bd763 Fix black formating args 2019-08-08 10:13:44 +02:00
Pascal Vizeli
0765387ad8 Bump version 172 2019-08-07 18:18:09 +02:00
Pascal Vizeli
a07517bd3c Merge pull request #1190 from home-assistant/dev
Release 171
2019-08-07 18:17:30 +02:00
Pascal Vizeli
e5f0d80d96 Start API server before he beform a self update (#1189) 2019-08-07 18:03:56 +02:00
Pascal Vizeli
2fc5e3b7d9 Repair / fixup docker overlayfs issues (#1170)
* Add a repair modus

* Add repair to add-ons

* repair to cli

* Add API call

* fix sync call

* Clean all images

* Fix repair

* Fix supervisor

* Add new function to core

* fix tagging

* better style

* use retag

* new retag function

* Fix lint

* Fix import export
2019-08-07 17:26:32 +02:00
Pascal Vizeli
778bc46848 Don't relay on latest with HA/Addons (#1175)
* Don't relay on latest with HA/Addons

* Fix latest on install

* Revert some options

* Fix attach

* migrate to new version handling

* Fix thread

* Fix is running

* Allow wait

* debug code

* Fix debug value

* Fix list

* Fix regex

* Some better log output

* Fix logic

* Improve cleanup handling

* Fix bug

* Cleanup old code

* Improve version handling

* Fix the way to attach
2019-08-07 09:51:27 +02:00
Pascal Vizeli
882586b246 Fix time adjustments on latest boot (#1187)
* Fix time adjustments on latest boot

* Fix spell
2019-08-06 09:24:22 +02:00
dependabot-preview[bot]
b7c07a2555 Bump pytz from 2019.1 to 2019.2 (#1184)
Bumps [pytz](https://github.com/stub42/pytz) from 2019.1 to 2019.2.
- [Release notes](https://github.com/stub42/pytz/releases)
- [Commits](https://github.com/stub42/pytz/compare/release_2019.1...release_2019.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-02 10:32:04 +02:00
dependabot-preview[bot]
814b504fa9 Bump ptvsd from 4.2.10 to 4.3.0 (#1179)
Bumps [ptvsd](https://github.com/Microsoft/ptvsd) from 4.2.10 to 4.3.0.
- [Release notes](https://github.com/Microsoft/ptvsd/releases)
- [Commits](https://github.com/Microsoft/ptvsd/compare/v4.2.10...v4.3.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-29 17:01:28 +02:00
dependabot-preview[bot]
7ae430e7a8 Bump gitpython from 2.1.12 to 2.1.13 (#1178)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 2.1.12 to 2.1.13.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/master/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/2.1.12...2.1.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-29 14:53:54 +02:00
dependabot-preview[bot]
0e7e95ba20 Bump gitpython from 2.1.11 to 2.1.12 (#1171)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 2.1.11 to 2.1.12.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/master/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/2.1.11...2.1.12)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-22 14:18:11 +02:00
Pascal Vizeli
e577d8acb2 Bump version 171 2019-07-19 11:49:00 +02:00
Pascal Vizeli
0a76ab5054 Merge pull request #1168 from home-assistant/dev
Release 170
2019-07-19 11:48:28 +02:00
Pascal Vizeli
03c5596e04 Fix machine version (#1167) 2019-07-19 11:47:55 +02:00
Pascal Vizeli
3af4e14e83 Bump version 170 2019-07-16 12:36:05 +02:00
Pascal Vizeli
7c8cf57820 Merge pull request #1164 from home-assistant/dev
Release 169
2019-07-16 12:35:10 +02:00
Pascal Vizeli
8d84a8a62e Update panel & support panel on devcontainer (#1163)
* Update panel & support panel on devcontainer

* small cleanups

* small size
2019-07-16 12:23:03 +02:00
Pascal Vizeli
08c45060bd Add support for RPi4 (#1162) 2019-07-16 10:33:56 +02:00
Pascal Vizeli
7ca8d2811b Update URL for version file (#1161) 2019-07-16 10:26:59 +02:00
Pascal Vizeli
bb6898b032 Update azure-pipelines.yml for Azure Pipelines 2019-07-12 09:57:55 +02:00
Pascal Vizeli
cd86c6814e Update azure-pipelines.yml for Azure Pipelines 2019-07-12 09:42:55 +02:00
Pascal Vizeli
b67e116650 Update azure-pipelines.yml 2019-07-12 09:41:40 +02:00
Pascal Vizeli
57ce411fb6 Update azure-pipelines.yml 2019-07-11 22:11:37 +02:00
Pascal Vizeli
85ed4d9e8d Update Dockerfile 2019-07-11 19:25:07 +02:00
dependabot-preview[bot]
ccb39da569 Bump flake8 from 3.7.7 to 3.7.8 (#1154)
Bumps [flake8](https://gitlab.com/pycqa/flake8) from 3.7.7 to 3.7.8.
- [Release notes](https://gitlab.com/pycqa/flake8/tags)
- [Commits](https://gitlab.com/pycqa/flake8/compare/3.7.7...3.7.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-09 14:05:43 +02:00
Pascal Vizeli
dd7ba64d32 Bump version 169 2019-07-08 16:03:59 +02:00
Pascal Vizeli
de3edb1654 Merge pull request #1153 from home-assistant/dev
Release 168
2019-07-08 16:02:39 +02:00
dependabot-preview[bot]
d262151727 Bump pytest from 4.6.3 to 5.0.1 (#1148)
* Bump pytest from 4.6.3 to 5.0.1

Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.6.3 to 5.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/4.6.3...5.0.1)

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

* Update tox.ini
2019-07-06 18:07:15 +02:00
Pascal Vizeli
a37c90af96 Forward Params (#1150) 2019-07-06 18:06:39 +02:00
Pascal Vizeli
0a3a752b4c Add timezone to info call (#1146) 2019-07-04 18:20:46 +02:00
Pascal Vizeli
0a34f427f8 Fix error on save special permission (#1145) 2019-07-04 17:30:42 +02:00
Pascal Vizeli
157740e374 Update devcontainer.json 2019-07-04 17:28:50 +02:00
Pascal Vizeli
b0e994f3f5 Bump version 168 2019-06-25 17:38:57 +02:00
Pascal Vizeli
f374852801 Merge pull request #1139 from home-assistant/dev
Release 167
2019-06-25 17:34:42 +02:00
Pascal Vizeli
709f034f2e New TimeZone handling (#1138)
* Remove function to get TZ from config file

* Readd old timezone handling

* Fix tests
2019-06-25 17:09:14 +02:00
Pascal Vizeli
6d6deb8c66 Cleanup udev handling (#1137)
* Cleanup udev handling

* Update hardware.py
2019-06-25 16:15:02 +02:00
Pascal Vizeli
5771b417bc sort import 2019-06-25 12:54:45 +00:00
Pascal Vizeli
51efcefdab Compile only hassio 2019-06-24 23:21:15 +00:00
Pascal Vizeli
d31ab5139d compile all 2019-06-24 23:09:08 +00:00
Pascal Vizeli
ce18183daa Allow update discovery messages (#1136)
* Allow update discovery messages

* Update __init__.py

* Update __init__.py

* Update __init__.py

* fix lint

* Fix style
2019-06-24 23:29:42 +02:00
Pascal Vizeli
b8b73cf880 remove diff wheels build 2019-06-24 19:16:26 +02:00
Pascal Vizeli
5291e6c1f3 Use multistage 2019-06-24 19:04:52 +02:00
Pascal Vizeli
626a9f06c4 Update to alpine 3.10 (#1135) 2019-06-24 18:49:43 +02:00
Pascal Vizeli
72338eb5b8 Add devcontainer support (#1134) 2019-06-24 14:48:10 +02:00
Jakub
7bd77c6e99 Append devlinks to serial dev_list (#1131)
* append devlinks to dev_list

* replace eudev-libs with eudev

* include only devlinks starting with /dev/serial/by-id

* add missing package, move udev init to entry.sh

* fix mode on entry.sh

* Update homeassistant.py

* Update homeassistant.py
2019-06-24 09:53:54 +02:00
dependabot-preview[bot]
69151b962a Bump pytest from 4.6.2 to 4.6.3 (#1125)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.6.2 to 4.6.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/4.6.2...4.6.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-21 09:50:42 +02:00
dependabot-preview[bot]
86305d4fe4 Bump docker from 4.0.1 to 4.0.2 (#1133)
Bumps [docker](https://github.com/docker/docker-py) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/4.0.1...4.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-21 09:50:28 +02:00
Pascal Vizeli
d5c3850a3f Don't break on supervisor update (#1118)
* Don't break on supervisor update

* Update core.py

* Fix lint
2019-06-06 10:57:36 +02:00
Pascal Vizeli
3e645b6175 Fix timeout on check port (#1116) 2019-06-05 17:49:05 +02:00
Pascal Vizeli
89dc78bc05 Bump version 167 2019-06-05 17:10:44 +02:00
Pascal Vizeli
164c403d05 Merge pull request #1115 from home-assistant/dev
Release 166
2019-06-05 17:10:14 +02:00
Pascal Vizeli
5e8007453f detect native arch (#1114) 2019-06-05 16:59:43 +02:00
Pascal Vizeli
0a0d97b084 Support pip progress for HA 0.94 (#1113)
* Support pip progress for HA 0.94

* fix black

* add tests

* add test for adguard

* Fix lint
2019-06-05 14:46:03 +02:00
dependabot-preview[bot]
eb604ed92d Bump pytest from 4.6.1 to 4.6.2 (#1112)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/4.6.1...4.6.2)
2019-06-04 23:47:35 +02:00
dependabot-preview[bot]
c47828dbaa Bump pytest from 4.5.0 to 4.6.1 (#1110)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.5.0 to 4.6.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/4.5.0...4.6.1)
2019-06-04 14:43:20 +02:00
Pascal Vizeli
ea437dc745 Update azure-pipelines.yml for Azure Pipelines 2019-06-02 14:12:45 +02:00
Franck Nijhof
c16a208b39 Support for AdGuard Home discovery (#1107)
* Support for AdGuard Home discovery

* 👕 Darkened the sky
2019-06-02 07:47:12 +02:00
dependabot-preview[bot]
55d803b2a0 Bump cryptography from 2.6.1 to 2.7 (#1108)
Bumps [cryptography](https://github.com/pyca/cryptography) from 2.6.1 to 2.7.
- [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.6.1...2.7)
2019-05-31 17:55:16 +02:00
Pascal Vizeli
611f6f2829 Don't follow requests itself (#1106)
* Don't follow requests itself

* Fix black lint
2019-05-31 13:53:46 +02:00
Pascal Vizeli
b94df76731 Update azure-pipelines.yml for Azure Pipelines 2019-05-31 12:42:37 +02:00
Pascal Vizeli
218619e7f0 Bump version 166 2019-05-31 12:36:06 +02:00
Pascal Vizeli
273eed901a Merge pull request #1105 from home-assistant/dev
Release 165
2019-05-31 12:35:34 +02:00
Pascal Vizeli
8ea712a937 Fix error on comparson (#1104) 2019-05-31 11:46:28 +02:00
Pascal Vizeli
658449a7a0 Update azure-pipelines.yml for Azure Pipelines 2019-05-30 17:43:30 +02:00
Pascal Vizeli
968c471591 Update azure-pipelines.yml for Azure Pipelines 2019-05-30 17:25:47 +02:00
Pascal Vizeli
b4665f3907 Add black support (#1101) 2019-05-27 12:35:06 +02:00
dependabot[bot]
496cee1ec4 Bump ptvsd from 4.2.9 to 4.2.10 (#1096)
Bumps [ptvsd](https://github.com/Microsoft/ptvsd) from 4.2.9 to 4.2.10.
- [Release notes](https://github.com/Microsoft/ptvsd/releases)
- [Commits](https://github.com/Microsoft/ptvsd/compare/v4.2.9...v4.2.10)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-22 14:29:57 +02:00
dependabot[bot]
0f8c80f3ba Bump docker from 3.7.2 to 4.0.1 (#1093)
Bumps [docker](https://github.com/docker/docker-py) from 3.7.2 to 4.0.1.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/3.7.2...4.0.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-21 12:07:01 +02:00
Pascal Vizeli
6c28f82239 Bump version 165 2019-05-18 22:39:43 +02:00
Pascal Vizeli
def32abb57 Merge pull request #1090 from home-assistant/dev
Release 164
2019-05-18 22:37:47 +02:00
Pascal Vizeli
f57a241b9e Panel search function (#1089) 2019-05-18 22:31:07 +02:00
Pascal Vizeli
11a7e8b15d Fix error with repository without repository.json (#1088) 2019-05-18 22:17:32 +02:00
Pascal Vizeli
fa4f7697b7 Update azure-pipelines.yml for Azure Pipelines 2019-05-16 09:42:55 +02:00
dependabot[bot]
6098b7de8e Bump pytest from 4.4.2 to 4.5.0 (#1083)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.4.2 to 4.5.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/4.4.2...4.5.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-13 23:03:55 +02:00
dependabot[bot]
0a382ce54d Bump ptvsd from 4.2.8 to 4.2.9 (#1081)
Bumps [ptvsd](https://github.com/Microsoft/ptvsd) from 4.2.8 to 4.2.9.
- [Release notes](https://github.com/Microsoft/ptvsd/releases)
- [Commits](https://github.com/Microsoft/ptvsd/compare/v4.2.8...v4.2.9)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-10 15:32:29 +02:00
dependabot[bot]
dd53aaa30c Bump pytest from 4.4.1 to 4.4.2 (#1080)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.4.1 to 4.4.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/4.4.1...4.4.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-05-09 14:11:58 +02:00
Pascal Vizeli
31e175a15a Bump version 164 2019-05-09 12:07:57 +02:00
Pascal Vizeli
4c80727bcc Merge pull request #1079 from home-assistant/dev
Release 163
2019-05-09 12:07:22 +02:00
Pascal Vizeli
b2c3157361 Fix device bug (#1078) 2019-05-09 11:41:37 +02:00
Pascal Vizeli
dc4f38ebd0 Update azure-pipelines.yml for Azure Pipelines 2019-05-08 23:46:08 +02:00
Pascal Vizeli
7c9437c6ee Bugfixes / increase Home Assistant timeout (#1077)
* Fix small bugs with new store

* Add more timeout to homeassistant
2019-05-08 22:37:05 +02:00
Pascal Vizeli
9ce9e10dfd WIP: Split add-on store logic (#1067)
* Split add-on store logic

* finish data model

* Cleanup models

* Cleanup imports

* split up store addons

* More cleanup

* Go to stable

* Fix layout

* Cleanup interface

* Fix restore/snapshot

* Fix algo

* Fix reload task

* Fix typing / remove indirect add-on references

* Fix version

* Fix repository data

* Fix addon repo

* Fix api check

* Fix API return

* Fix model

* Temp fix available

* Fix lint

* Fix install

* Fix partial restore

* Fix store restore

* Fix ingress port

* Fix API

* Fix style
2019-05-07 17:27:00 +02:00
carstenschroeder
4e94043bca Fix validation of image and last_version (#1073)
* Fix validation of image and last_vesrion

* use of Maybe
2019-05-05 23:25:56 +02:00
Pascal Vizeli
749d45bf13 Update Dockerfile 2019-05-03 12:18:27 +02:00
Pascal Vizeli
ce99b3e259 Update azure-pipelines.yml for Azure Pipelines 2019-05-03 12:10:21 +02:00
Pascal Vizeli
2c84daefab Debugger (#1070)
* Add debuger to supervisor

* Fix init

* Fix lint
2019-05-03 12:02:32 +02:00
Pascal Vizeli
dc1933fa88 Remove old panels < 0.70 (#1066) 2019-04-29 12:13:31 +02:00
Pascal Vizeli
6970cebf80 Force auto API password (#1065) 2019-04-29 11:43:13 +02:00
dependabot[bot]
a234006de2 Bump pytest from 4.3.0 to 4.4.1 (#1059)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 4.3.0 to 4.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/4.3.0...4.4.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-25 17:36:55 +02:00
dependabot[bot]
2484149323 Bump pytz from 2018.9 to 2019.1 (#1058)
Bumps [pytz](https://github.com/stub42/pytz) from 2018.9 to 2019.1.
- [Release notes](https://github.com/stub42/pytz/releases)
- [Commits](https://github.com/stub42/pytz/compare/release_2018.9...release_2019.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-25 17:36:26 +02:00
dependabot[bot]
778148424c Bump attrs from 18.2.0 to 19.1.0 (#1057)
Bumps [attrs](https://github.com/python-attrs/attrs) from 18.2.0 to 19.1.0.
- [Release notes](https://github.com/python-attrs/attrs/releases)
- [Changelog](https://github.com/python-attrs/attrs/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/python-attrs/attrs/compare/18.2.0...19.1.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2019-04-25 17:36:01 +02:00
Pascal Vizeli
55f4a2395e Bump version 163 2019-04-24 11:12:01 +02:00
Pascal Vizeli
5a45d47ed8 Merge pull request #1056 from home-assistant/dev
Release 162
2019-04-24 11:11:36 +02:00
Pascal Vizeli
da601d1483 Bump version 162 2019-04-24 11:05:14 +02:00
Pascal Vizeli
e98a1272e9 Panel small fixes (#1055) 2019-04-24 10:24:16 +02:00
Pascal Vizeli
90e9cf788b Update README.md 2019-04-24 10:04:35 +02:00
Pascal Vizeli
ec387c3010 Rename panel config attributes (#1054) 2019-04-24 09:48:01 +02:00
Fredrik Erlandsson
7e5a960c98 remove potential tag when pulling new image (#1053) 2019-04-24 09:46:58 +02:00
Pascal Vizeli
f1bcbf2416 Merge pull request #1051 from home-assistant/dev
Release 161
2019-04-23 14:41:55 +02:00
Pascal Vizeli
bce144e197 Panel Auto integration (#1050) 2019-04-23 14:28:13 +02:00
Pascal Vizeli
86a3735d83 Downgrade logger for audio to debug (#1049) 2019-04-23 11:29:45 +02:00
Pascal Vizeli
decf254e5f Ingress panel support (#1047)
* Ingress Panel support

* Fix lists

* Allow to set the value

* fix panels

* Update ha realtime

* Fix url

* Fix update
2019-04-23 11:18:04 +02:00
Pascal Vizeli
e10fe16f21 [skip ci] Update azure-pipelines.yml for Azure Pipelines 2019-04-16 13:49:51 +02:00
Pascal Vizeli
996891a740 Create stale.yml 2019-04-16 11:05:26 +02:00
Pascal Vizeli
7385d026ea Bump version 161 2019-04-16 00:00:08 +02:00
Pascal Vizeli
09f43d6f3c Merge pull request #1042 from home-assistant/dev
Release 160
2019-04-15 23:50:57 +02:00
Pascal Vizeli
6906e757dd Update azure-pipelines.yml for Azure Pipelines 2019-04-15 23:22:05 +02:00
Pascal Vizeli
963d242afa Fix handling with Firefox (#1041) 2019-04-15 18:09:13 +02:00
Pascal Vizeli
3ed7cbe2ed Fix: Websocket detection case sensitive (#1040) 2019-04-15 17:03:36 +02:00
Pascal Vizeli
0da924f10b [skip ci] Update azure-pipelines.yml for Azure Pipelines 2019-04-14 17:25:10 +02:00
Pascal Vizeli
76411da0a7 Update azure-pipelines.yml for Azure Pipelines 2019-04-14 01:10:41 +02:00
Pascal Vizeli
ce87a72cf0 Update .hadolint.yaml 2019-04-14 01:06:21 +02:00
Pascal Vizeli
f8c9e2f295 Create .hadolint.yaml 2019-04-14 01:03:25 +02:00
Pascal Vizeli
00af027e51 Update azure-pipelines.yml for Azure Pipelines 2019-04-14 01:01:24 +02:00
Pascal Vizeli
c91fce3281 [skip azurepipelines] Add badge 2019-04-13 13:29:04 +02:00
Pascal Vizeli
fb6df18ce9 Update azure-pipelines.yml for Azure Pipelines
Update parallel builds
2019-04-13 13:00:33 +02:00
Pascal Vizeli
31f5c6f938 Update azure-pipelines.yml for Azure Pipelines
Fix login
2019-04-13 12:50:37 +02:00
Pascal Vizeli
d3a44b2992 Update azure-pipelines.yml for Azure Pipelines 2019-04-13 12:44:47 +02:00
Pascal Vizeli
b537a03e6d [skip azurepipelines] Update azure-pipelines.yml for Azure Pipelines 2019-04-13 12:40:39 +02:00
Pascal Vizeli
46093379e4 Update azure-pipelines.yml for Azure Pipelines 2019-04-13 12:28:25 +02:00
Pascal Vizeli
1b17d90504 Update azure-pipelines.yml for Azure Pipelines 2019-04-13 00:14:33 +02:00
Pascal Vizeli
7d42dd7ac2 Update azure-pipelines.yml for Azure Pipelines (#1037)
* Update azure-pipelines.yml for Azure Pipelines

* Update azure-pipelines.yml for Azure Pipelines
2019-04-13 00:04:43 +02:00
Pascal Vizeli
f35dcfcfd3 Update azure-pipelines.yml for Azure Pipelines 2019-04-12 10:41:19 +02:00
Pascal Vizeli
c4f223c38a Update azure-pipelines.yml for Azure Pipelines 2019-04-12 10:40:24 +02:00
Pascal Vizeli
71362f2c76 Bump version 160 2019-04-12 00:57:40 +02:00
Pascal Vizeli
96beac9fd9 Merge pull request #1036 from home-assistant/dev
Release 159
2019-04-12 00:57:01 +02:00
Pascal Vizeli
608c0e5076 Allow to update logger (#1035)
* Allow to update logger

* Fix bug
2019-04-12 00:48:46 +02:00
Pascal Vizeli
16ef6d82d2 Panel sidebar (#1034) 2019-04-12 00:20:10 +02:00
Pascal Vizeli
51940222be Bump version 159 2019-04-11 11:21:53 +02:00
Pascal Vizeli
21f3c4820b Merge pull request #1033 from home-assistant/dev
Release 158
2019-04-11 11:20:18 +02:00
Pascal Vizeli
214c6f919e Support for central log level handling (#1032)
* Support for central log level handling

* Fix API
2019-04-11 11:16:00 +02:00
Pascal Vizeli
d9d438d571 Panel Dashboard update (#1031) 2019-04-11 10:47:58 +02:00
Pascal Vizeli
cf60d1f55c Bump version 158 2019-04-10 22:22:56 +02:00
Pascal Vizeli
f9aa12cbad Merge pull request #1030 from home-assistant/dev
Release 157
2019-04-10 22:22:07 +02:00
Pascal Vizeli
76266cc18b Panel Fixes2 (#1029) 2019-04-10 22:17:11 +02:00
Pascal Vizeli
50b9506ff3 Bump version 157 2019-04-10 15:37:26 +02:00
Pascal Vizeli
754cd64213 Merge pull request #1028 from home-assistant/dev
Release 156
2019-04-10 15:36:52 +02:00
Pascal Vizeli
113b62ee77 Fix protocol handling (#1027) 2019-04-10 15:31:43 +02:00
Pascal Vizeli
d9874c4c3e Panel Refresh v2 (#1026) 2019-04-10 01:49:58 +02:00
Pascal Vizeli
ca44e858c5 Update .gitmodules 2019-04-10 01:31:42 +02:00
Pascal Vizeli
c7ca4de307 Update .gitmodules 2019-04-10 00:27:25 +02:00
Pascal Vizeli
b77146a4e0 Allow to add a description for a port (#1023) 2019-04-09 22:15:23 +02:00
Pascal Vizeli
45b4800378 Bump version 156 2019-04-08 10:22:04 +02:00
Pascal Vizeli
7f9232d2b9 Merge pull request #1020 from home-assistant/dev
Release 155
2019-04-08 10:21:27 +02:00
Pascal Vizeli
d90426f745 Fix content-type response (#1017) 2019-04-07 22:13:31 +02:00
Pascal Vizeli
c2deabb672 Support dynamic ingress port (#1015)
* Support dynamic ingress port

* Allow to remeber ports

* Add tests

* Fix schema

* Cleanup handling / speed

* Fix port
2019-04-07 21:59:21 +02:00
Pascal Vizeli
ead5993f3e Bump version 155 2019-04-07 18:19:59 +02:00
Pascal Vizeli
1bcd74e8fa Merge pull request #1014 from home-assistant/dev
Release 154
2019-04-07 18:18:32 +02:00
Pascal Vizeli
118da3c275 Cleanup last_version with latest_version inside code (#1012)
* Cleanup last_version with latest_version inside code

* Fix property
2019-04-07 15:04:16 +02:00
Pascal Vizeli
d7bb9013d4 Improve add-on rebuild (#1011)
* Check version

* Use image instead next_image
2019-04-07 14:42:07 +02:00
Pascal Vizeli
812c46d82b Fix add-on build / install (#1010) 2019-04-07 13:44:17 +02:00
Pascal Vizeli
c0462b28cd Bump version 154 2019-04-07 00:22:34 +02:00
Pascal Vizeli
82b2f66920 Merge pull request #1007 from home-assistant/dev
Release 153
2019-04-07 00:21:54 +02:00
Pascal Vizeli
01da42e1b6 Add add-ons reload for manager (#1006) 2019-04-07 00:15:33 +02:00
Pascal Vizeli
d652d22547 Panel ingress fix (#1004) 2019-04-06 23:03:54 +02:00
Pascal Vizeli
baea84abe6 Panel ingress support (#999) 2019-04-06 12:03:26 +02:00
Pascal Vizeli
c2d705a42a Fix ingress_url with not installed add-ons (#998)
Fix ingress_url with not installed add-ons
2019-04-06 11:24:04 +02:00
Pascal Vizeli
f10b433e1f Fix token handling with new secrets (#996)
* Fix token handling with new secrets

* add schema also to ingress
2019-04-05 17:49:43 +02:00
Pascal Vizeli
67f562a846 Init ingress session boarder / lookup (#995)
* Init ingress session boarder / lookup

* Add session to API

* Add cokkie validate

* Do it without event bus

* Add logger

* Fix validation

* Add tests

* Update tests

* Mock json storage
2019-04-05 17:36:07 +02:00
Pascal Vizeli
1edec61133 Add Ingress support (#991)
* Add Ingress support to supervisor

* Update security

* cleanup add-on extraction

* update description

* fix header part

* fix

* Fix header check

* fix tox

* Migrate docker interface typing

* Update home assistant to new docker

* Migrate supervisor

* Fix host add-on problem

* Update hassos

* Update API

* Expose data to API

* Check on API ingress support

* Add ingress URL

* Some cleanups

* debug

* disable uvloop

* Fix issue

* test

* Fix bug

* Fix flow

* Fix interface

* Fix network

* Fix metadata

* cleanups

* Fix exception

* Migrate to token system

* Fix webui

* Fix update

* Fix relaod

* Update log messages

* Attach ingress url only if enabled

* Cleanup ingress url handling

* Ingress update

* Support check version

* Fix raise error

* Migrate default port

* Fix junks

* search error

* Fix content filter

* Add debug

* Update log

* Update flags

* Update documentation

* Cleanup debugs

* Fix lint

* change default port to 8099

* Fix lint

* fix lint
2019-04-05 12:13:44 +02:00
Stephen Beechen
c13a33bf71 Downgrade add-on API access logging to debug (#992)
resolves home-assistant/hassio#865
2019-04-05 11:42:31 +02:00
Pascal Vizeli
2ae93ae7b1 Update API data for deconz (#989)
* Update API data for deconz

* Fix tests
2019-04-01 16:58:58 +02:00
Pascal Vizeli
8451020afe Update uvloop 0.12.2 (#988) 2019-04-01 14:02:28 +02:00
Pascal Vizeli
a48e568efc Update azure-pipelines.yml for Azure Pipelines [skip ci] 2019-04-01 14:01:59 +02:00
Pascal Vizeli
dee2808cb5 Delete main.workflow 2019-04-01 13:57:42 +02:00
Pascal Vizeli
06a2ab26a2 Update azure-pipelines.yml for Azure Pipelines [skip ci] 2019-04-01 13:56:02 +02:00
Pascal Vizeli
45de0f2f39 Update azure-pipelines.yml for Azure Pipelines [skip ci] 2019-04-01 13:05:23 +02:00
Pascal Vizeli
bac5f704dc Update azure-pipelines.yml for Azure Pipelines [skip ci] 2019-04-01 13:01:37 +02:00
Pascal Vizeli
79669a5d04 Set up CI with Azure Pipelines [skip ci] 2019-04-01 12:49:59 +02:00
Pascal Vizeli
a6e712c9ea Bump version 153 2019-03-30 23:37:11 +01:00
Pascal Vizeli
069fe99699 Merge pull request #984 from home-assistant/dev
Release 152
2019-03-30 23:35:54 +01:00
Pascal Vizeli
4754f067ad Update panel for 0.91.0 (#983) 2019-03-30 23:30:46 +01:00
Pascal Vizeli
dce9818812 Bump version 152 2019-03-28 15:01:53 +01:00
Pascal Vizeli
d054b6dbb7 Merge pull request #979 from home-assistant/dev
Release 151
2019-03-28 15:01:23 +01:00
Pascal Vizeli
3093165325 Update cryptography (#981) 2019-03-28 14:37:06 +01:00
Pascal Vizeli
fd9c5bd412 Make arch required (#978) 2019-03-28 14:23:46 +01:00
Pascal Vizeli
9a8850fecd Remove unused pylint 2019-03-28 14:13:36 +01:00
Pascal Vizeli
b12175ab9a Support for deconz discovery & cleanup (#974)
* Support for deconz discovery & cleanup

* Split discovery

* Fix lint

* Fix lint / import
2019-03-28 14:11:18 +01:00
Pascal Vizeli
b52f90187b Make homeassistant container constant (#808)
* Make homeassistant container constant

* Update homeassistant.py

* Update homeassistant.py

* Update interface.py

* Update homeassistant.py

* Fix handling

* add start function

* Add typing

* Fix lint

* Add API call

* Update logs

* Fix some issue with watchdog

* Fix lint
2019-03-27 17:20:05 +01:00
Pascal Vizeli
4eb02f474d Bump version 151 2019-03-20 22:09:42 +01:00
Pascal Vizeli
dfdcddfd0b Merge pull request #968 from home-assistant/dev
Release 150
2019-03-20 22:08:17 +01:00
Pascal Vizeli
0391277bad Fix panel for 0.90.0 (#967) 2019-03-20 22:03:31 +01:00
Pascal Vizeli
73643b9bfe Bump version 150 2019-03-19 21:29:47 +01:00
Pascal Vizeli
93a52b8382 Merge pull request #965 from home-assistant/dev
Release 149
2019-03-19 21:26:38 +01:00
Pascal Vizeli
7a91bb1f6c Update panel for 0.90.0 v6 (#963) 2019-03-19 19:01:52 +01:00
Pascal Vizeli
26efa998a1 Revert dev link (#956) 2019-03-18 09:42:31 +01:00
Pascal Vizeli
fc9f3fee0a Fix 2019-03-18 09:20:48 +01:00
cadwal
ec19bd570b Include serial device node links in container device mapping to allow for persistent names in the HA serial config (#944) 2019-03-18 09:05:04 +01:00
David McNett
3335bad9e1 Correct typo: 'ignore' -> 'ignored' (#947) 2019-03-18 09:02:29 +01:00
Pascal Vizeli
71ae334e24 Update pylint (#945) 2019-03-11 14:03:28 +01:00
Pascal Vizeli
0807651fbd Bump version 149 2019-03-08 11:59:41 +01:00
Pascal Vizeli
7026d42d77 Merge pull request #942 from home-assistant/dev
Release 148
2019-03-08 11:41:58 +01:00
Pascal Vizeli
31047b9ec2 Down or upgrade exists image on restore (#941) 2019-03-08 11:36:36 +01:00
Pascal Vizeli
714791de8f Bump version 148 2019-03-07 21:12:54 +01:00
Pascal Vizeli
c544fff2b2 Merge pull request #939 from home-assistant/dev
Release 147
2019-03-07 21:12:20 +01:00
Pascal Vizeli
fc45670686 Fix bug with update (#938) 2019-03-07 21:09:43 +01:00
Pascal Vizeli
5cefa0a2ee Bump version 147 2019-03-07 16:28:39 +01:00
Pascal Vizeli
a1910d4135 Merge pull request #937 from home-assistant/dev
Release 146
2019-03-07 16:28:09 +01:00
Pascal Vizeli
f1fecdde3a Enable Armv7 for Add-ons (#936)
* Enable Armv7 for Add-ons

* Cleanups

* fix tests
2019-03-07 16:00:41 +01:00
Pascal Vizeli
9ba4ea7d18 Check json files too 2019-03-07 10:03:07 +01:00
Pascal Vizeli
58a455d639 Fix lint 2019-03-04 10:09:34 +01:00
Pascal Vizeli
3ea85f6a28 Delete .travis.yml 2019-03-04 10:04:19 +01:00
Pascal Vizeli
4e1469ada4 Replace travis 2019-03-04 10:03:54 +01:00
Curtis Gibby
5778f78f28 Fix misspelling on "environment" (#934) 2019-03-04 10:00:41 +01:00
Pascal Vizeli
227125cc0b Change json error handling (#930)
* Change json error handling

* Typing + modern way to read file

* fix lint
2019-02-26 00:19:05 +01:00
Pascal Vizeli
b36e178c45 Bump version to 146 2019-02-21 17:24:01 +01:00
Pascal Vizeli
32c9198fb2 Merge pull request #929 from home-assistant/dev
Release 145
2019-02-21 17:21:43 +01:00
Pascal Vizeli
6983dcc267 Fix image arch version on restore/update (#928) 2019-02-21 16:40:49 +01:00
Pascal Vizeli
813fcc41f0 Bump version 145 2019-02-20 17:04:41 +01:00
Pascal Vizeli
f4e9dd0f1c Merge pull request #927 from home-assistant/dev
Release 144
2019-02-20 17:04:15 +01:00
Pascal Vizeli
7f074142bf Replace pycrpytodome with cryptocraphy (#923)
* Replace pycrpytodome with cryptocraphy

* Fix typing

* fix typing

* Fix lints

* Fix build

* Add musl libc

* Fix lint

* fix lint

* Fix algo

* Add more typing fix crypto imports v2

* Fix padding
2019-02-20 10:30:22 +01:00
Pascal Vizeli
b6df37628d Merge pull request #924 from home-assistant/feat-wait-time
Increase wait time for home assistant startup
2019-02-18 16:24:21 +01:00
Pascal Vizeli
7867eded50 Increase wait time for home assistant startup 2019-02-18 09:51:21 +01:00
Pascal Vizeli
311abb8a90 Bump version 144 2019-02-02 11:48:29 +01:00
Pascal Vizeli
21303f4b05 Merge pull request #913 from home-assistant/dev
Release 143
2019-02-02 11:47:13 +01:00
Pascal Vizeli
da3270af67 Fix that need_build work like image (#912) 2019-01-31 22:08:10 +01:00
Pascal Vizeli
35aae69f23 Support armv7 and allow support of multible arch types per CPU (#892)
* Support armv7 and first abstraction

* Change layout

* Add more type hints

* Fix imports

* Update

* move forward

* add tests

* fix type

* fix lint & tests

* fix tests

* Fix unittests

* Fix create folder

* cleanup

* Fix import order

* cleanup loop parameter

* cleanup init function

* Allow changeable image name

* fix setup

* Fix load of arch

* Fix lint

* Add typing

* fix init

* fix hassos cli problem & stick on supervisor arch

* address comments

* cleanup

* Fix image selfheal

* Add comment

* update uvloop

* remove uvloop

* fix tagging

* Fix install name

* Fix validate build config

* Abstract image_name from system cache
2019-01-31 18:47:44 +01:00
Franck Nijhof
118a2e1951 Revert "Delete move.yml" (#901)
This reverts commit 07c4058a8c.
2019-01-22 12:19:38 +01:00
Pascal Vizeli
9053341581 Fix wrong UTF-8 config files (#895)
* Fix wrong UTF-8 config files

* Fix lint

* Update data.py
2019-01-18 18:57:54 +01:00
Pascal Vizeli
27532a8a00 Update aioHttp 3.5.4 (#894) 2019-01-17 21:40:52 +01:00
Pascal Vizeli
7fdfa630b5 Bump version 143 2019-01-15 12:11:56 +01:00
Pascal Vizeli
3974d5859f Merge pull request #890 from home-assistant/dev
Release 142
2019-01-15 12:10:58 +01:00
Pascal Vizeli
aa1c765c4b Add support for SYS_MODULE (#889)
* Add support for SYS_MODULE

* Update flake stuff

* Fix lint

* Fix lint

* Fix lint

* Fix lint
2019-01-15 00:56:07 +01:00
Pascal Vizeli
e78385e7ea Support to map kernel modules ro into container (#888) 2019-01-14 23:20:30 +01:00
Pascal Vizeli
9d59b56c94 Fix lint 2019-01-14 23:20:07 +01:00
Pascal Vizeli
9d72dcabfc Support to map kernel modules ro into container 2019-01-14 21:57:14 +01:00
Pascal Vizeli
a0b5d0b67e Fix error on first run because the landing page already run (#886)
* Fix error on first run because the landing page already run

* Update homeassistant.py
2019-01-14 21:25:17 +01:00
Pascal Vizeli
2b5520405f Fix log info about update on dev (#885) 2019-01-14 20:05:03 +01:00
Pascal Vizeli
ca376b3fcd Update docker-py to 3.7.0 (#882)
* Update docker-py to 3.7.0

* Update __init__.py

* Update addon.py
2019-01-14 20:04:27 +01:00
Pascal Vizeli
11e3c0c547 Update aioHttp to 3.5.2 (#881) 2019-01-13 12:22:01 +01:00
Pascal Vizeli
9da136e037 Fix API descriptions 2019-01-02 23:31:35 +01:00
Pascal Vizeli
9b3e59d876 Merge pull request #861 from casperklein/patch-1
Duplicate entry removed.
2018-12-20 16:18:29 +01:00
Casper
7a592795b5 Duplicate entry removed. 2018-12-20 13:45:04 +01:00
Pascal Vizeli
5b92137699 Bump version 142 2018-12-11 23:46:01 +01:00
Pascal Vizeli
7520cdfeb4 Merge pull request #853 from home-assistant/dev
Release 141
2018-12-11 23:45:29 +01:00
Pascal Vizeli
0ada791e3a Update Panel for Home Assistant 0.84.0 (#852) 2018-12-11 20:54:30 +01:00
Pascal Vizeli
73afced4dc Bugfix stack trace on remove (#842) 2018-11-30 00:09:33 +01:00
Pascal Vizeli
633a2e93bf Create ISSUE_TEMPLATE.md 2018-11-22 14:53:49 +01:00
Pascal Vizeli
07c4058a8c Delete move.yml 2018-11-22 14:46:58 +01:00
Alastair D'Silva
b6f3938b14 Add support for the Orange Pi Prime (#829)
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
2018-11-21 17:03:25 +01:00
Pascal Vizeli
57534fac96 Bump version 141 2018-11-20 17:39:39 +01:00
Pascal Vizeli
4a03e72983 Merge pull request #827 from home-assistant/dev
Release 140
2018-11-20 17:39:12 +01:00
Pascal Vizeli
ddb29ea9b1 Speedup build 2018-11-20 17:17:04 +01:00
Pascal Vizeli
95179c30f7 Update Panel with new security functions (#826) 2018-11-20 17:13:55 +01:00
Pascal Vizeli
f49970ce2c Update .gitmodules 2018-11-20 12:25:45 +01:00
Pascal Vizeli
790818d1aa Update README.md 2018-11-20 10:56:19 +01:00
Pascal Vizeli
62f675e613 Fix documentation 2018-11-19 22:37:46 +01:00
Pascal Vizeli
f33434fb01 Downgrade discovery duplicate logging (#824) 2018-11-19 21:05:51 +01:00
Pascal Vizeli
254d6aee32 Small code cleanups (#822)
* Small code cleanups

* Update homeassistant.py
2018-11-19 16:44:21 +01:00
Pascal Vizeli
a5ecd597ed Add tests for add-ons map (#821) 2018-11-19 16:43:24 +01:00
Pascal Vizeli
0fab3e940a Merge pull request #820 from home-assistant/master
Master
2018-11-19 14:52:45 +01:00
Pascal Vizeli
60fbebc16b Rating add-on better they implement hass auth (#819)
* Rating add-on better they implement hass auth

* Update utils.py
2018-11-19 14:51:03 +01:00
Christian
ec366d8112 Provide options for legacy add-ons (#814)
* Provide options for legacy add-ons

* Remove whitespace from blank line

* Only provide primitive data types as Docker environment variable

* Fix linting issues

* Update addon.py
2018-11-19 12:05:12 +01:00
Christian
b8818788c9 Bugfix Add-on validate correct image url (#810)
* Bugfix Add-on validate correct image path

* Add tests for different add-on image urls
2018-11-18 19:29:23 +01:00
Pascal Vizeli
e23f6f6998 Update uvloop to version 0.11.3 (#818) 2018-11-18 12:08:59 +01:00
Pascal Vizeli
05b58d76b9 Add tests for hass.io (#817)
* Add tests for hass.io

* Fix folder

* Fix test command
2018-11-18 12:08:46 +01:00
Pascal Vizeli
644d13e3fa Bugfix Add-on validate on RO (#803) 2018-11-09 23:53:41 +01:00
Pascal Vizeli
9de71472d4 Remove links they are not needed 2018-11-09 10:26:01 +01:00
Pascal Vizeli
bf28227b91 Add developer guide 2018-11-09 10:25:29 +01:00
Pascal Vizeli
4c1ee49068 Bump version 140 2018-11-05 16:20:01 +01:00
Pascal Vizeli
6e7cf5e4c9 Merge pull request #796 from home-assistant/dev
Release 139
2018-11-05 16:19:17 +01:00
Pascal Vizeli
11f8c97347 Fix discovery update (#795)
* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update discovery.py
2018-11-05 14:59:57 +01:00
Pascal Vizeli
a1461fd518 Update requirements.txt 2018-11-05 13:53:16 +01:00
Pascal Vizeli
fa5c2e37d3 Discovery default config (#793) 2018-11-05 07:45:28 +01:00
luca-simonetti
1f091b20ad fix: use a different convention to handle multiple devices on same card (#767)
* fix: use a different convention to handle multiple devices on same card

* fix: use a different convention to handle multiple devices on same card

* Update alsa.py

* Update alsa.py
2018-11-02 10:47:25 +01:00
Pascal Vizeli
d3b4a03851 Catch exception on watchdog for pretty log (#778)
* Catch exception on watchdog for pretty log

* Update tasks.py
2018-10-29 16:40:19 +01:00
Jorim Tielemans
fb12fee59b Expand add-on installation error message (#783)
* Expand error message

Since an add-on is only available for certain machine and architecture combination we should log both.

* Update addon.py
2018-10-27 15:24:56 +02:00
Pascal Vizeli
7a87d2334a flake8 update to 3.6.0 (#777)
* flake8 update to 3.6.0

* fix lint
2018-10-27 15:23:26 +02:00
Pascal Vizeli
9591e71138 Update auth.py (#771) 2018-10-24 14:02:16 +02:00
Ville Skyttä
cecad526a2 Grammar and spelling fixes (#772) 2018-10-24 14:01:28 +02:00
Pascal Vizeli
53dab4ee45 Bump version 139 2018-10-16 12:52:19 +02:00
Pascal Vizeli
8abbba46c7 Merge pull request #766 from home-assistant/dev
Release 138
2018-10-16 12:51:47 +02:00
Pascal Vizeli
0f01ac1b59 Fix syntax 2018-10-16 12:45:06 +02:00
Pascal Vizeli
aa8ab593c0 Rename login_backend to auth_api (#764)
* Update const.py

* Update validate.py

* Update addon.py

* Update auth.py

* Update addons.py

* Update API.md
2018-10-16 12:33:40 +02:00
Pascal Vizeli
84f791220e Don't clean cache on fake auth (#765)
* Don't clean cache on fake auth

* Update auth.py
2018-10-16 12:30:24 +02:00
Pascal Vizeli
cee2c5469f Bump version 138 2018-10-15 15:25:29 +02:00
Pascal Vizeli
6e75964a8b Merge pull request #761 from home-assistant/dev
Release 137
2018-10-15 15:25:05 +02:00
Pascal Vizeli
5ab5036504 Fix proxy handling with failing connection (#760)
* Fix proxy handling with failing connection

* fix lint

* Fix exception handling

* clenaup error handling

* Fix type error

* Fix event stream

* Fix stream handling

* Fix

* Fix lint

* Handle

* Update proxy.py

* fix lint
2018-10-15 13:01:52 +02:00
Pascal Vizeli
000a3c1f7e Bump to 137 2018-10-12 14:39:47 +02:00
Pascal Vizeli
8ea123eb94 Merge pull request #754 from home-assistant/dev
Release 136
2018-10-12 14:39:18 +02:00
Pascal Vizeli
571c42ef7d Create role for backup add-ons (#755)
* Create role for backup add-ons

* Update validate.py

* Update security.py
2018-10-12 12:48:12 +02:00
Pascal Vizeli
8443da0b9f Add-on SSO support with Home Assistant auth system (#752)
* Create auth.py

* Finish auth cache

* Add documentation

* Add valid schema

* Update auth.py

* Update auth.py

* Update security.py

* Create auth.py

* Update coresys.py

* Update bootstrap.py

* Update const.py

* Update validate.py

* Update const.py

* Update addon.py

* Update auth.py

* Update __init__.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update const.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update validate.py

* Update coresys.py

* Update auth.py

* Update auth.py

* more security

* Update API.md

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update auth.py

* Update homeassistant.py

* Update homeassistant.py
2018-10-12 12:21:48 +02:00
Pascal Vizeli
7dbbcf24c8 Check exists hardware for audio/gpio devices (#753)
* Update hardware.py

* Update addon.py

* Update hardware.py

* Update addon.py
2018-10-12 10:22:58 +02:00
Pascal Vizeli
468cb0c36b Rename info (#750)
* Rename version to info

* fix security
2018-10-10 16:46:34 +02:00
Pascal Vizeli
78e093df96 Bump version 136 2018-10-09 17:10:25 +02:00
Pascal Vizeli
ec4d7dab21 Merge pull request #749 from home-assistant/dev
Release 135
2018-10-09 17:08:19 +02:00
Pascal Vizeli
d00ee0adea Add hostname into version API call (#748) 2018-10-09 15:40:44 +02:00
Pascal Vizeli
55d5ee4ed4 Merge pull request #747 from mbo18/patch-1
Add missing tinker board
2018-10-09 14:00:44 +02:00
mbo18
0e51d74265 Add missing tinker board 2018-10-09 09:29:38 +02:00
Pascal Vizeli
916f3caedd Bump version 135 2018-10-08 00:21:59 +02:00
Pascal Vizeli
ff80ccce64 Merge pull request #745 from home-assistant/dev
Release 134
2018-10-08 00:20:20 +02:00
Pascal Vizeli
23f28b38e9 small code cleanups (#740)
* small code cleanups

* Update __init__.py

* Update homeassistant.py

* Update __init__.py

* Update homeassistant.py

* Update homeassistant.py

* Update __init__.py

* fix list

* Fix api call
2018-10-07 23:50:18 +02:00
Franck Nijhof
da425a0530 Adds support for privilege DAC_READ_SEARCH (#743)
* Adds support for privilege DAC_READ_SEARCH

* 🚑 Fixes security rating regarding privileges
2018-10-07 19:17:06 +02:00
Jorim Tielemans
79dca1608e Fix machine 'odroid-c2' (#744)
Odroid-cu2 does not exist AFAIK, it needs to be c2.
2018-10-07 19:16:29 +02:00
Pascal Vizeli
33b615e40d Fix manager access to /addons (#738) 2018-10-05 13:48:29 +02:00
Pascal Vizeli
c825c40c4d Bump version 134 2018-10-01 19:07:48 +02:00
Pascal Vizeli
8beb723cc2 Merge pull request #736 from home-assistant/dev
Release 133
2018-10-01 19:07:17 +02:00
Pascal Vizeli
94fd24c251 Bugfix message handling (#735) 2018-10-01 18:57:31 +02:00
Pascal Vizeli
bf75a8a439 Cleanup discovery data (#734)
* Cleanup discovery data

* Update API.md

* Update validate.py

* Update discovery.py

* Update const.py
2018-10-01 16:17:46 +02:00
Pascal Vizeli
36cdb05387 Don't allow add-on to update itself (#733) 2018-10-01 15:22:26 +02:00
Pascal Vizeli
dccc652d42 Bump version 133 2018-09-30 20:16:42 +02:00
Pascal Vizeli
74e03a9a2e Merge pull request #728 from home-assistant/dev
Release 132
2018-09-30 20:16:08 +02:00
Pascal Vizeli
2f6df3a946 Fix discovery on add-on uninstall (#731)
* Fix discovery on add-on uninstall

* Update discovery.py

* Update discovery.py
2018-09-30 18:24:10 +02:00
Pascal Vizeli
2872be6385 Update Panel (#730) 2018-09-30 17:58:26 +02:00
Pascal Vizeli
af19e95c81 Make discovery persistent (#727)
* Make discovery persistent

* fix file handling

* fix detection

* Smooth

* Fix ring import

* Fix handling

* fix schema

* fix validate

* fix discovery cleanup
2018-09-30 15:33:16 +02:00
Pascal Vizeli
e5451973bd Overwork Services/Discovery (#725)
* Update homeassistant.py

* Update validate.py

* Update exceptions.py

* Update services.py

* Update discovery.py

* fix gitignore

* Fix handling for discovery

* use object in ref

* lock down discovery API

* fix api

* Design

* Fix API

* fix lint

* fix

* Fix security layer

* add provide layer

* fix access

* change rating

* fix rights

* Fix API error handling

* raise error

* fix rights

* api

* fix handling

* fix

* debug

* debug json

* Fix validator

* fix error

* new url

* fix schema
2018-09-29 19:49:08 +02:00
Pascal Vizeli
4ef8c9d633 Change API for new UI & Add machine support (#720)
* Change API for new UI

* Update API.md

* Update validate.py

* Update addon.py

* Update API.md

* Update addons.py

* fix lint

* Update security.py

* Update version.py

* Update security.py

* Update security.py
2018-09-28 14:34:43 +02:00
Pascal Vizeli
4a9dcb540e Add support for long live token (#719)
* Add support for long live token

* Update proxy.py
2018-09-27 14:35:40 +02:00
Pascal Vizeli
61eefea358 Add version endpoint (#718)
* Add version endpoint

* Update API.md

* Update const.py

* Create version.py

* Update __init__.py

* Update security.py

* Update version.py
2018-09-26 11:39:45 +02:00
Pascal Vizeli
f2a5512bbf Fix not exists label bug (#717) 2018-09-25 13:46:48 +02:00
Pascal Vizeli
2f4e114f25 Fix wrong regex 2018-09-25 12:51:47 +02:00
Pascal Vizeli
c91bac2527 Add log to blacklist / reduce free calls (#713) 2018-09-24 17:03:21 +02:00
Pascal Vizeli
52da7605f5 Enable Security API (#710)
* Enable Security API

* Update addons.py

* Update proxy.py

* Update __init__.py

* Update security.py

* Fix lint
2018-09-24 15:11:33 +02:00
Fabian Affolter
267791833e Update docstrings, comments and log messages (#707) 2018-09-18 23:47:47 +02:00
Pascal Vizeli
67dcf1563b Bump version to 132 2018-09-18 21:20:10 +02:00
Pascal Vizeli
ccff0f5b9e Merge pull request #706 from home-assistant/dev
Release 131
2018-09-18 21:19:33 +02:00
Pascal Vizeli
9f8ad05471 Add API role system (#703)
* Add API role system

* Finish

* Simplify

* Fix lint

* Fix rights

* Fix lint

* Fix spell

* Fix log
2018-09-18 20:39:58 +02:00
Fabian Affolter
c2299ef8da Fix typos (#704) 2018-09-18 18:17:20 +02:00
Franck Nijhof
f5845564db 👕 Fixes a typo in method name (#702) 2018-09-17 23:11:53 +02:00
Franck Nijhof
17904d70d8 🚀 Adds venv to .dockerignore (#701) 2018-09-17 21:03:14 +02:00
Franck Nijhof
622e99e04c Adds host PID mode support for add-ons (#700)
*  Adds host PID mode support for add-ons.

* 🔒 Disables host PID mode when in protected mode

* 🚦 Adds more negative rating weight to host PID mode
2018-09-17 21:02:28 +02:00
Pascal Vizeli
061420f279 Make Label handling more robust (#696)
* Make Label handling more robust

* Update interface.py

* Update interface.py

* Update interface.py
2018-09-15 22:07:05 +02:00
Franck Nijhof
3d459f1b8b Adds support for SYS_PTRACE add-on privileges (#697) 2018-09-15 22:05:50 +02:00
Pascal Vizeli
5f3dd6190a Bump version 130 2018-09-10 00:02:27 +02:00
Pascal Vizeli
ac824d3af6 Merge pull request #691 from home-assistant/dev
Release 130
2018-09-10 00:00:56 +02:00
Pascal Vizeli
dd25c29544 Bugfix Proxy with new token (#690)
* Update proxy.py

* Update security.py
2018-09-09 23:47:35 +02:00
Pascal Vizeli
5cbdbffbb2 Bump version to 130 2018-09-08 00:17:05 +02:00
Pascal Vizeli
bb81f14c2c Merge pull request #688 from home-assistant/dev
Release 129
2018-09-08 00:16:17 +02:00
Pascal Vizeli
cecefd6972 Change access to API (#686)
* Update API.md

* Update API.md

* Update API.md

* Update addons.py

* Update addons.py

* Update addons.py

* Update addons.py

* Update __init__.py

* Update security.py

* Update security.py

* Update const.py

* Update validate.py

* Update __init__.py

* Update validate.py

* Update homeassistant.py

* Update homeassistant.py

* Update homeassistant.py

* Update addon.py

* Update addon.py

* Update homeassistant.py

* Fix lint

* Fix lint

* Backward combatibility

* Make token more robust

* Fix bug

* Logic error

* Fix access

* fix valid
2018-09-07 22:59:31 +02:00
Pascal Vizeli
ff7f6a0b4c Bump version 129 2018-08-29 10:16:04 +02:00
Pascal Vizeli
1dc9f35e12 Merge pull request #674 from home-assistant/dev
Release 128
2018-08-29 10:13:57 +02:00
Pascal Vizeli
051b63c7cc Fix access token property (#673)
* Fix access token property

* revert
2018-08-28 17:04:39 +02:00
Pascal Vizeli
aac4b9b24a Snapshot/Restore Home-Assistant token (#672)
* Snapshot/Restore Home-Assistant token

* Encrypt token & check api

* fix lint
2018-08-28 16:32:17 +02:00
Paulus Schoutsen
1a208a20b6 Handle access token expiration (#671) 2018-08-28 12:14:40 +02:00
Pascal Vizeli
b1e8722ead Update: pycryptodome to 3.6.6 (#670) 2018-08-28 12:04:32 +02:00
Pascal Vizeli
a66af6e903 Update aiohttp to 3.4.0 (#668)
Update: aiohttp to 3.4.0
2018-08-28 01:18:38 +02:00
Pascal Vizeli
0c345fc615 Bump version 128 2018-08-19 22:05:42 +02:00
Pascal Vizeli
087b082a6b Merge pull request #660 from home-assistant/dev
Release 127
2018-08-19 22:03:49 +02:00
Pascal Vizeli
0b85209eae Detect running record migration (#659)
* Detect running record migration

* Fix order

* Change order second one
2018-08-19 21:58:19 +02:00
Pascal Vizeli
d81bc7de46 Change rating 1-6 (#658) 2018-08-19 18:17:14 +02:00
Pascal Vizeli
e3a99b9f89 Fix /share inside whitelist (#657) 2018-08-18 15:05:18 +02:00
Pascal Vizeli
5d319b37ea Bump verison 127 2018-08-16 23:38:57 +02:00
Pascal Vizeli
9f25606986 Merge pull request #653 from home-assistant/dev
Release 126
2018-08-16 23:38:24 +02:00
Pascal Vizeli
ecd12732ee New generation of security and access (#652)
* New generation of security and access

* Update const.py

* Update validate.py

* Update addon.py

* Update validate.py

* Fix name

* Allow access

* Fix

* add logs

* change message

* add rating

* fix lint

* fix lint

* fix

* Fix
2018-08-16 22:49:08 +02:00
Pascal Vizeli
85fbde8e36 Fix Dockerfile 2018-08-16 01:42:56 +02:00
Pascal Vizeli
6e6c2c3efb Change timezone handling (#641)
* Change timezone handling

* Update dt.py

* Update homeassistant.py

* fix

* Use new timezone

* fix handling

* fix regex

* fix regex

* Rename old config

* fix lint

* simplify

* fix regex

* fix

* cleanup

* cleanup

* fix

* fix find

* mm
2018-08-16 01:40:20 +02:00
Pascal Vizeli
0d4a808449 Improve docker build cache for supervisor (#651) 2018-08-15 23:52:52 +02:00
Pascal Vizeli
087f746647 update docker API to 3.5.0 (#650) 2018-08-15 22:05:13 +02:00
Pascal Vizeli
640d66ad1a Update uvloop 0.11.2 (#648) 2018-08-15 21:38:57 +02:00
Pascal Vizeli
f5f5ed83af Bump version 126 2018-08-09 14:38:34 +02:00
Pascal Vizeli
95f01a1161 Merge pull request #640 from home-assistant/dev
Release 125
2018-08-09 14:37:56 +02:00
Pascal Vizeli
b84e7e7d94 Allow to reset token (#639)
* Allow to reset token

* Update homeassistant.py
2018-08-09 14:37:00 +02:00
Pascal Vizeli
5d7018f3f0 Bump version 125 2018-08-09 01:05:21 +02:00
Pascal Vizeli
d87a85ceb5 Merge pull request #636 from home-assistant/dev
Release 124
2018-08-09 01:03:47 +02:00
Pascal Vizeli
9ab6e80b6f Cleanup logging (#637)
* Cleanup logging

* simplify
2018-08-09 01:03:00 +02:00
Pascal Vizeli
78e91e859e Add add-on support for docker sock ro (#635)
* Add add-on support for docker sock ro

* fix
2018-08-09 00:42:33 +02:00
Pascal Vizeli
9eee8eade6 Fix gpio mapping on amd64 systems (#634) 2018-08-09 00:29:20 +02:00
Pascal Vizeli
124ce0b8b7 Update voluptuous 0.11.5 (#622) 2018-08-09 00:06:49 +02:00
Pascal Vizeli
00e7d96472 Fix new auth system (#633)
* Fix new auth system

* Update exceptions.py

* Update exceptions.py

* Update homeassistant.py

* Update homeassistant.py

* Update homeassistant.py

* Fix some API Errors

* fix lint
2018-08-09 00:05:08 +02:00
Pascal Vizeli
398815efd8 Bump version to 124 2018-08-08 19:22:12 +02:00
Pascal Vizeli
bdc2bdcf56 Merge pull request #631 from ndarilek/dev
Add SYS_RESOURCE to list of valid privileges
2018-08-07 17:06:15 +02:00
Nolan Darilek
68eafb0a7d Add SYS_RESOURCE to list of valid privileges 2018-08-07 03:21:21 +00:00
Pascal Vizeli
7ca2fd7193 Merge pull request #618 from home-assistant/dev
Release 123
2018-08-04 01:25:55 +02:00
Pascal Vizeli
ec823edd8f Cleanup docker image (#617) 2018-08-04 00:41:14 +02:00
Pascal Vizeli
858c7a1fa7 Bump version 123 2018-08-02 23:40:52 +02:00
Pascal Vizeli
6ac45a24fc Merge pull request #615 from home-assistant/dev
Release 122
2018-08-02 23:39:43 +02:00
Pascal Vizeli
9430b39042 Update uvloop version 0.11.1 (#614) 2018-08-02 23:18:40 +02:00
Pascal Vizeli
ae7466ccfe Fix UnicodeDecodeError with read json file (#613)
* Update json.py

* Update data.py
2018-08-02 21:48:50 +02:00
Simon Holzmayer
2c17fe5da8 Adapt regex validation to allow docker images from other registries (#608)
* Adapt regex validation to allow images from other registries than dockerhub

Issue #564

* Update validate.py
2018-07-30 12:34:42 +02:00
Pascal Vizeli
a0fb91af29 Use requirements.txt (#607)
* Create requirements.txt

* Update setup.py

* Update Dockerfile

* Update Dockerfile

* Update requirements.txt

* Update requirements.txt

* Update Dockerfile

* Update tox.ini
2018-07-27 16:34:47 +02:00
Pascal Vizeli
f626e31fd3 Bump version 122 2018-07-25 01:52:24 +02:00
Pascal Vizeli
0151a149fd Merge pull request #604 from home-assistant/dev
Release 121
2018-07-25 01:47:36 +02:00
Pascal Vizeli
9dea93142b Timeout shutdown (#603)
* Don't wait too long for shutdown

* Update log message

* Fix timeout

* Fast shudown
2018-07-25 01:46:54 +02:00
Pascal Vizeli
7f878bfac0 Bump version to 121 2018-07-25 01:39:33 +02:00
Pascal Vizeli
ebe9ae2341 Merge pull request #600 from home-assistant/dev
Release 120
2018-07-24 22:11:10 +02:00
Pascal Vizeli
e777bbd024 Fix bug with proxy (#599) 2018-07-24 22:00:46 +02:00
Pascal Vizeli
2116d56124 Bump version 120 2018-07-24 16:32:46 +02:00
Pascal Vizeli
0b6a82b018 Merge pull request #598 from home-assistant/dev
Release 119
2018-07-24 16:21:06 +02:00
Pascal Vizeli
b4ea28af4e Update uvloop to 0.11.0 (#597) 2018-07-24 16:16:26 +02:00
Pascal Vizeli
22f59712df Bump version 119 2018-07-23 13:01:51 +02:00
Pascal Vizeli
efe95f7bab Merge pull request #593 from home-assistant/dev
Release 118
2018-07-23 12:59:15 +02:00
Pascal Vizeli
200c68f67f Fix proxy data passthrougth (#592)
* Fix proxy data passthrougth

* Update homeassistant.py
2018-07-23 12:53:32 +02:00
Pascal Vizeli
dcefec7b99 Cleanup old stuff (#589) 2018-07-22 01:51:45 +02:00
Pascal Vizeli
5db798bcf8 Fix API for home-assistant (#588)
* Fix API for home-assistant

* Update API.md
2018-07-22 00:42:45 +02:00
Pascal Vizeli
70005296cc Bump version 118 2018-07-21 20:25:12 +02:00
Pascal Vizeli
f2bf8dea93 Merge pull request #585 from home-assistant/dev
Release 117
2018-07-21 20:21:18 +02:00
Pascal Vizeli
fee858c956 Fix exception is HomeAssistant allready running (#587) 2018-07-21 20:13:13 +02:00
Pascal Vizeli
e3ae48c8ff Remove geo ip (#586)
* Remove geo ip

* Update core.py

* Update dt.py
2018-07-21 19:45:11 +02:00
Pascal Vizeli
fa9e20385e Bugfix passwrod (#584) 2018-07-21 19:07:22 +02:00
Pascal Vizeli
f51c9704e0 Fix timeout on freegeoip (#581)
* Fix timeout on freegeoip

* Update updater.py

* Update supervisor.py

* Update dt.py

* Update hassos.py

* Update core.py

* Update hassos.py

* Update supervisor.py

* Update updater.py
2018-07-21 19:01:20 +02:00
Pascal Vizeli
57c58d81c0 Bump version 117 2018-07-21 00:06:34 +02:00
Pascal Vizeli
1ec1082068 Merge pull request #580 from home-assistant/dev
Release 116
2018-07-21 00:05:56 +02:00
Pascal Vizeli
35b7c2269c Support control of hassos-cli (#555)
* Support control of hassos-cli

* Update const.py

* Update validate.py

* Update supervisor.py

* Create hassos_cli.py

* Update hassos_cli.py

* Update hassos_cli.py

* Update hassos.py

* Update tasks.py

* Update hassos.py

* Update API.md

* Update API.md

* Update const.py

* Update hassos.py

* Update __init__.py

* Fix lint

* fix

* Fix logging

* change order

* Fix download
2018-07-20 23:45:36 +02:00
Pascal Vizeli
cc3e6ec6fd Fix stream error with aiohttp >= 3 (#579)
* Fix stream error with aiohttp >= 3

* Update proxy.py

* Update proxy.py

* Update proxy.py

* Update proxy.py

* Update proxy.py

* Update proxy.py
2018-07-20 22:28:56 +02:00
Paulus Schoutsen
4df42e054d Leverage access and refresh tokens if available (#575)
* Leverage access and refresh tokens if available

* Update homeassistant.py

* Update homeassistant.py

* Update proxy.py

* Migrate HomeAssistant to new exception layout

* Fix build for 3.7

* Cleanups

* Fix style

* fix log strings

* Fix new style

* Fix travis build

* python 3.7

* next try

* fix

* fix lint

* Fix lint p2

* Add logging

* Fix logging

* fix access

* Fix spell

* fix return

* Fix runtime

* Add to hass config
2018-07-20 16:55:48 +02:00
Pascal Vizeli
1b481e0b37 Fix small bugs (python37) (#577)
* Fix small bugs (python37)

* Update utils.py

* Update utils.py

* Update utils.py

* Update utils.py

* Update utils.py
2018-07-19 21:22:26 +02:00
Pascal Vizeli
3aa4cdf540 Fix remove data inside executor (#576) 2018-07-19 20:25:58 +02:00
Pascal Vizeli
029f277945 Reset readonly on remove data (#569)
* Reset readonly on remove data

* Update addon.py

* Update utils.py

* Fix lint

* Update utils.py

* Update utils.py

* Update utils.py

* Update utils.py

* Update addon.py
2018-07-19 12:44:16 +02:00
Pascal Vizeli
e7e0b9adda Fix-python7 compatibility (#573) 2018-07-19 01:18:43 +02:00
Pascal Vizeli
5fbff75da8 Support new base images (#571)
* Support new base images

* Update Dockerfile

* Update setup.py
2018-07-17 23:32:50 +02:00
Paulus Schoutsen
58299a0389 Add release drafter 2018-07-10 10:38:45 +02:00
Pascal Vizeli
1151d7e17b Bump version to 116 2018-07-06 13:10:16 +02:00
Pascal Vizeli
b56ed547e3 Merge pull request #559 from home-assistant/dev
Release 115
2018-07-06 13:09:32 +02:00
Pascal Vizeli
a71ebba940 Bugfix rollback if the hass instant is complete corrupt (#558) 2018-07-06 13:08:57 +02:00
Pascal Vizeli
4fcb516c75 Bump version to 115 2018-07-06 01:38:18 +02:00
Pascal Vizeli
22142d32d2 Merge remote-tracking branch 'origin/dev'
Release 114
2018-07-06 01:37:10 +02:00
Pascal Vizeli
21194f1411 Add hostname to UI (#557)
* Add hostname to UI

* Fix dbus call

* support boolean

* support types

* revert

* test

* test

* log

* fixup

* fix bug
2018-07-06 01:36:28 +02:00
Pascal Vizeli
09df046fa8 Fix problem with Repositories (#552)
* Fix problem with Repositories

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* Update git.py

* fix lint

* fix

* reset origin

* Git cleanup
2018-07-05 23:21:54 +02:00
Pascal Vizeli
63d3889d5c Fix problem with options / hostname (#554) 2018-07-05 13:01:48 +02:00
Pascal Vizeli
0ffc0559e2 Map devicetree 2018-07-04 01:12:58 +02:00
Pascal Vizeli
78118a502c Map devicetree 2018-07-04 01:12:25 +02:00
Pascal Vizeli
946cc3d618 Bump version to 114 2018-07-04 00:53:19 +02:00
Pascal Vizeli
c40a3f18e9 Merge remote-tracking branch 'origin/dev'
Release 113
2018-07-04 00:51:36 +02:00
Pascal Vizeli
f01945bf8c Update addon.py (#550) 2018-07-04 00:51:01 +02:00
Pascal Vizeli
0f72db45f9 Bump version to 113 2018-07-03 23:02:21 +02:00
Pascal Vizeli
83510341b6 Merge remote-tracking branch 'origin/dev'
Release 112
2018-07-03 22:43:05 +02:00
Pascal Vizeli
70dd6593e4 Rollback homeassistant on failover (#549)
* Rollback homeassistant on failover

* Check running system
2018-07-03 22:41:50 +02:00
Pascal Vizeli
60ba2db561 Bump version to 112 2018-07-03 20:44:06 +02:00
Pascal Vizeli
5820d16419 Fix wrong mount options for devicetree (#548) 2018-07-03 18:44:45 +02:00
Pascal Vizeli
9f9ff0d1ad Merge remote-tracking branch 'origin/dev'
Release 111
2018-07-03 00:14:28 +02:00
Pascal Vizeli
806161e3ac Use machine-id from filesystem (#546)
* Use machine-id from filesystem

* Update security.py

* Update security.py

* fix lint
2018-07-01 22:28:32 +02:00
Pascal Vizeli
44ae9c7b63 Don't try to shutdown a not running API (#543) 2018-06-30 22:06:18 +02:00
Pascal Vizeli
75d24ba534 Bump version to 111 2018-06-30 22:03:21 +02:00
Pascal Vizeli
13243cd02c Merge remote-tracking branch 'origin/dev'
Release 110
2018-06-30 02:10:48 +02:00
Pascal Vizeli
411fad8a45 Fix scroll bugs (#542) 2018-06-30 01:59:33 +02:00
Pascal Vizeli
5fe9d63c79 Add HassOS OTA support on Hass.io (#536)
* Add HassOS OTA support on Hass.io

* Update dt.py

* Update updater.py

* add rauc dbus / initial dbus signal handling

* Update gdbus.py

* Update hassos.py

* Update const.py

* Update hassos.py

* Update exceptions.py

* Update hassos.py

* Update rauc.py

* Update rauc.py

* Update rauc.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update __init__.py

* Update hassos.py

* Update hassos.py

* Update updater.py

* Update updater.py

* Update exceptions.py

* Update exceptions.py

* Update hassos.py

* Update dt.py

* fix lint

* Fix update

* fix property

* tmp disabled

* fix path

* fix rauc

* info

* More details

* cleanup signal hadnling

* fix

* Fix lint
2018-06-30 01:48:58 +02:00
Pascal Vizeli
33095f8792 Bump version to 110 2018-06-29 22:23:00 +02:00
Pascal Vizeli
0253722369 Remove update config with allready installed one (#533)
* Remove update config with allready installed one

* fix lint
2018-06-28 12:22:27 +02:00
Pascal Vizeli
495c45564a Update libuv (#529) 2018-06-26 00:21:49 +02:00
Pascal Vizeli
8517b43e85 Merge pull request #526 from home-assistant/dev
Release 109
2018-06-23 00:58:29 +02:00
Pascal Vizeli
033ea4e7dc Panel with HassOS support (#525) 2018-06-23 00:52:19 +02:00
Pascal Vizeli
a0c9e5ad26 HassOS support (#522)
* Add support for hassos

* Name command

* Update host.py

* Create hassos.py

* Update const.py

* Update host.py

* Update API.md

* Update const.py

* Update __init__.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update hassos.py

* Update const.py

* Update API.md

* Update hassos.py

* Update hassos.py

* Update API.md

* Update const.py

* Update hassos.py

* Update __init__.py

* fix lint

* Fix lint v2

* remove old function

* fix attribute error

* inittialize hassos

* Fix link

* fix error handling

* Fix handling
2018-06-22 22:54:03 +02:00
Pascal Vizeli
408d6eafcc Bump version to 109 2018-06-21 12:21:59 +02:00
Pascal Vizeli
054e357483 Add support to map devicetree into add-on (#519)
* Add support to map devicetree into add-on

* Update const.py

* Update validate.py

* Update addon.py

* Update addons.py

* Update API.md
2018-06-21 12:19:14 +02:00
Pascal Vizeli
cb520bff23 Merge pull request #518 from home-assistant/fix-device-configs
Bugfix home-assistant config with devices
2018-06-21 12:18:20 +02:00
Pascal Vizeli
024ebe0026 Update homeassistant.py 2018-06-21 12:00:13 +02:00
Pascal Vizeli
7b62e2f07b Bugfix home-assistant config with devices 2018-06-21 11:51:04 +02:00
Pascal Vizeli
7d52b3ba01 Merge pull request #517 from home-assistant/dev
Release 108
2018-06-21 11:33:09 +02:00
Pascal Vizeli
46caa23319 Update version.json 2018-06-21 11:27:19 +02:00
Pascal Vizeli
9aa5eda2c8 Some bugfix (#516)
* Some bugfix

* Update apparmor.py

* Update apparmor.py

* Update apparmor.py

* Update apparmor.py
2018-06-20 23:25:08 +02:00
Pascal Vizeli
f48182a69c Add lost panel files (#515)
* Update Panel for 0.72

* Add new panel files
2018-06-20 21:07:33 +02:00
Pascal Vizeli
788f883490 Update Panel for 0.72 (#514) 2018-06-20 20:37:26 +02:00
Pascal Vizeli
e84e82d018 Fix aiohttp handling (#512) 2018-06-20 15:32:55 +02:00
Pascal Vizeli
20e73796b8 Change aiohttp handling for server (#511) 2018-06-20 12:17:33 +02:00
Pascal Vizeli
7769d6fff1 Cleanup and fixup Apparmor implementation (#509)
* Cleanup and fixup Apparmor implementation

* Update addon.py

* Update validate.py

* Create apparmor.py

* Update exceptions.py

* Update apparmor.py

* Create apparmor.py

* Update const.py

* Update bootstrap.py

* Update const.py

* Update config.py

* Update addons.py

* Update apparmor.py

* Add support for host AppArmor

* Update apparmor.py

* Update apparmor.py

* Update apparmor.py

* Update apparmor.py

* Update apparmor.py

* Update addon.py

* Update apparmor.py

* Update addon.py

* Update addon.py

* Update addon.py

* Update addon.py

* Update const.py

* Update supervisor.py

* Update supervisor.py

* Update supervisor.py

* Add snapshot support

* some cleanup

* Cleanup v2

* Update aiohttp

* fix lint

* fix bugs

* Add info logs
2018-06-20 00:09:18 +02:00
Pascal Vizeli
561e80c2be Extend Systemd Support / Apparmor (#506)
* Update systemd.py

* Update control.py

* Update control.py

* Create service.py

* Update info.py

* Rename hassio/host/asound.tmpl to hassio/host/data/asound.tmpl

* Rename hassio/host/audiodb.json to hassio/host/data/audiodb.json

* Update alsa.py

* Update alsa.py

* Update control.py

* Fix

* Enable call

* fix

* fix args

* Fix gdbus

* parse service data

* Change handling

* Fix states

* Fix parser for tuples

* Fix parser v2

* Fix tuple handling

* Fix regex string handling

* Faster tuple finder

* fix empty detector

* wrong order

* Finish

* fix lint

* better filtering

* fix match

* Fix mode string
2018-06-17 02:07:12 +02:00
Pascal Vizeli
96f47a4c32 Bump version to 108 2018-06-16 01:20:10 +02:00
Pascal Vizeli
7482d6dd45 Update last panel version (#508) 2018-06-15 22:55:57 +02:00
Pascal Vizeli
aea31ee6dd Support host tokens (#507)
* Update coresys.py

* Update bootstrap.py

* Update security.py

* fix lint

* Update bootstrap.py
2018-06-15 22:10:51 +02:00
Pascal Vizeli
de43965ecb Merge pull request #503 from home-assistant/dev
Release 107
2018-06-09 00:01:11 +02:00
Pascal Vizeli
baa61c6aa0 Bump version to 107 2018-06-08 23:48:43 +02:00
Pascal Vizeli
cb22dafb3c Fix bug with 0.70 (#502)
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2018-06-08 23:47:59 +02:00
Pascal Vizeli
ea26784c3e Merge pull request #501 from home-assistant/dev
Release 106
2018-06-08 22:14:05 +02:00
Pascal Vizeli
72332ed40f New panel for 0.71 and 0.72 (#500)
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2018-06-08 21:52:06 +02:00
Pascal Vizeli
46f2bf16a8 Bump version to 106 2018-06-08 21:51:08 +02:00
Ville Skyttä
e2725f8033 Spelling and grammar fixes (#499) 2018-06-08 21:32:06 +02:00
Pascal Vizeli
9084ac119f Fix version conflict 2018-05-29 19:40:16 +02:00
Pascal Vizeli
41943ba61a Delete .gitattributes 2018-05-29 19:38:00 +02:00
Pascal Vizeli
33794669a1 Last version.json update 2018-05-29 19:36:01 +02:00
Pascal Vizeli
fe155a4ff0 Read version from AWS (#488)
* Read version from AWS

* Update const.py

* Update updater.py

* Update updater.py

* Update updater.py

* Update updater.py

* Update updater.py

* Update const.py

* Update updater.py
2018-05-29 19:14:09 +02:00
Pascal Vizeli
124e487ef7 Support new panel generation (#487)
* Support new panel generation

* fix lint
2018-05-29 17:53:09 +02:00
Pascal Vizeli
f361916a60 Update docker timeout to 900sec (#486) 2018-05-29 17:37:20 +02:00
Pascal Vizeli
20afa1544b Bump version to 105 2018-05-29 00:22:12 +02:00
Pascal Vizeli
c08d5af4db Fix version conflicts 2018-05-29 00:21:24 +02:00
Pascal Vizeli
dc341c8af8 Fix version conflicts 2018-05-29 00:18:08 +02:00
Pascal Vizeli
2507b52adb Update Home Assistant to 0.70.0 2018-05-28 23:59:12 +02:00
Pascal Vizeli
1302708135 Update Home Assistant to 0.70.0 2018-05-28 23:58:45 +02:00
Pascal Vizeli
1314812f92 Update Home Assistant to 0.70.0 2018-05-28 23:53:28 +02:00
Pascal Vizeli
f739e3ed11 Update Hass.io to 104 2018-05-28 23:30:48 +02:00
Pascal Vizeli
abb526fc0f Update Panel / fix icons (#483) 2018-05-28 23:29:34 +02:00
Pascal Vizeli
efb1a24b8f Expose panel update (#482)
* Update __init__.py

* Update setup.py

* Update security.py

* Update setup.py

* Update __init__.py

* Update setup.py

* Update __init__.py
2018-05-28 23:16:03 +02:00
Pascal Vizeli
bc0835963d Bump version to 104 2018-05-28 21:28:19 +02:00
Pascal Vizeli
316190dff8 Fix new panel build for 0.70.0 (#481)
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
2018-05-28 21:24:17 +02:00
Pascal Vizeli
029ead0c7c Home Assistant 0.70.0b7 2018-05-27 10:52:10 +02:00
Paulus Schoutsen
a85172f30b Update to b7 2018-05-26 22:03:24 -04:00
Pascal Vizeli
dfe2532813 0.70.0b5 2018-05-26 22:28:47 +02:00
Pascal Vizeli
cf3bb23629 Home Assistant 0.70.0b5 2018-05-26 22:28:31 +02:00
Pascal Vizeli
2132042aca Update Home Assistant to version 0.70.0b3 2018-05-25 19:27:49 +02:00
Pascal Vizeli
19e448fc54 Update Home Assistant to version 0.70.0b3 2018-05-25 19:27:33 +02:00
c727
a4e0fb8e99 Update HA beta to 0.70.0b2 2018-05-22 15:03:18 +02:00
Paulus Schoutsen
5b72e2887e Update Hass.io to 0.70.0b2 2018-05-21 21:14:41 -04:00
Pascal Vizeli
d2b6ec1b7e Update Home Assistant to version 0.70.0b1 2018-05-21 15:38:04 +02:00
Paulus Schoutsen
4b541a23c4 Update Hass.io to 0.70.0b1 2018-05-21 09:27:11 -04:00
Pascal Vizeli
99869449ae Update Home Assistant to 0.70.0b0 2018-05-19 10:21:23 +02:00
Pascal Vizeli
eab73f3895 Update Home Assistant to 0.70.0b0 2018-05-19 10:20:55 +02:00
Pascal Vizeli
9e96615ffa Update Home Assistant to version 0.69.1 2018-05-13 10:20:56 +02:00
Pascal Vizeli
350010feb5 Update Home Assistant to version 0.69.1 2018-05-13 10:20:38 +02:00
Pascal Vizeli
7395e4620b Update Home Assistant to version 0.69.1 2018-05-13 10:20:18 +02:00
Pascal Vizeli
7d91ae4513 Update Home Assistant to 0.69.0 2018-05-11 22:32:38 +02:00
Pascal Vizeli
343f759983 Update Home Assistant to 0.69.0 2018-05-11 22:32:01 +02:00
Pascal Vizeli
24ee3f8cc0 Update Home Assistant to 0.69.0 2018-05-11 22:31:41 +02:00
Pascal Vizeli
c143eadb62 Update Home-Assistant 2018-05-09 20:31:22 +02:00
Pascal Vizeli
e7df38f4d1 Merge pull request #467 from home-assistant/rc
Hass.io 103
2018-05-09 15:47:18 +02:00
Pascal Vizeli
3e42318ac8 Merge branch 'master' into rc 2018-05-09 15:18:53 +02:00
Pascal Vizeli
c6e5d2932e Update Hass.io 2018-05-09 13:15:54 +02:00
Pascal Vizeli
1aaf21a350 Update Hass.io and Home Assistant 2018-05-09 13:15:35 +02:00
Pascal Vizeli
f185eece8a Update Hass.io and Home Assistant 2018-05-09 13:15:17 +02:00
Pascal Vizeli
9d951280ef Update const.py 2018-05-09 11:07:07 +02:00
Pascal Vizeli
3f598bafc0 Bugfix panel loading (#464) 2018-05-09 11:06:19 +02:00
Franck Nijhof
cddd859f56 🔈 Improves of audio devices handling (#463) 2018-05-08 14:27:17 +02:00
Pascal Vizeli
e7adf50ec1 Update Home Assistant 0.69.0b2 2018-05-07 23:54:11 +02:00
Pascal Vizeli
ac437f809a Update Home Assistant 0.69.0b2 2018-05-07 23:53:54 +02:00
Pascal Vizeli
f13dee9b9d Update Hass.io 2018-05-06 09:53:56 +02:00
Pascal Vizeli
00855c0909 Update Home Assistant and Hass.io 2018-05-06 09:53:28 +02:00
Pascal Vizeli
1fafed5a07 Update Home Assistant and Hass.io 2018-05-06 09:52:55 +02:00
Pascal Vizeli
7adb81b350 Update const.py 2018-05-06 09:45:46 +02:00
Pascal Vizeli
4647035b00 Bugfix Websession 2018-05-06 09:44:58 +02:00
Pascal Vizeli
8ad7344e02 Update Hass.io to version 103.1 2018-05-05 23:29:58 +02:00
Pascal Vizeli
f1c46b3385 Update Hass.io to version 103.1 2018-05-05 23:29:41 +02:00
Pascal Vizeli
7f84073b12 Update Hass.io to version 103.1 2018-05-05 23:29:24 +02:00
Pascal Vizeli
e383a11bb7 Pump version to fix 2018-05-05 23:19:56 +02:00
Pascal Vizeli
cc113e2251 Update Hass.io to version 103 2018-05-05 19:05:30 +02:00
Pascal Vizeli
c5a3830c7d Merge remote-tracking branch 'origin/dev' into rc 2018-05-04 21:53:40 +02:00
Pascal Vizeli
a2abadc970 Update hass.io to version 103 2018-05-04 21:39:12 +02:00
Pascal Vizeli
db444b89d3 Update gdbus.py (#460)
* Update gdbus.py

* Update gdbus.py
2018-05-04 20:58:23 +02:00
Pascal Vizeli
77881e8a58 Update Panel (#459)
* Update Panel

* Update core.py
2018-05-04 20:04:34 +02:00
Pascal Vizeli
0b15f88da3 Bugfixes (#457)
* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py

* Update gdbus.py
2018-05-03 23:22:48 +02:00
Pascal Vizeli
7c6bf96f6f shield host functions 2018-05-03 01:00:13 +02:00
Pascal Vizeli
dc77e2d8d9 Update gdbus.py 2018-05-03 00:52:57 +02:00
Pascal Vizeli
68824fab4f fix bug 2018-05-02 23:31:23 +02:00
Pascal Vizeli
d6b3a36714 Update Dockerfile 2018-05-02 22:52:08 +02:00
Pascal Vizeli
8ab1f703c7 Update Home Assistant to version 0.68.1 2018-05-01 07:24:34 +02:00
Pascal Vizeli
95a4e292aa Update Home Assistant to version 0.68.1 2018-05-01 07:24:03 +02:00
Pascal Vizeli
3b9252558f Update Home Assistant to version 0.68.1 2018-05-01 07:23:46 +02:00
Pascal Vizeli
4a324dccc6 Pump version to 103 2018-04-30 14:49:34 +02:00
Pascal Vizeli
8fffb0f8b5 Fix version 2018-04-30 14:46:59 +02:00
Pascal Vizeli
87adfce211 Update Hass.io to version 0.102 2018-04-30 14:45:31 +02:00
Tod Schmidt
297813f6e6 fix for asound.tmpl (#454) 2018-04-30 14:09:20 +02:00
Pascal Vizeli
362315852a Pump version to 0.102 2018-04-30 14:08:18 +02:00
Tod Schmidt
d221f36cf8 fix for asound.tmpl (#454) 2018-04-30 07:39:44 +02:00
Pascal Vizeli
9e18589b6b Update info.py 2018-04-28 10:51:25 +02:00
Pascal Vizeli
c4d09210e1 Update Home-Assistant to version 0.68.0 2018-04-28 10:16:57 +02:00
Pascal Vizeli
43797c5eb5 Update Home-Assistant to version 0.68.0 2018-04-28 10:16:28 +02:00
Pascal Vizeli
fe38fe94dc Update Home-Assistant to version 0.68.0 2018-04-28 10:16:06 +02:00
Pascal Vizeli
f185291eca Update control.py 2018-04-27 22:33:41 +02:00
Pascal Vizeli
7541ae6476 Update hostname.py 2018-04-27 22:31:37 +02:00
Pascal Vizeli
d94715be2b Merge pull request #451 from home-assistant/cleanups
Cleanups & restructs
2018-04-26 21:47:06 +02:00
Pascal Vizeli
99cc5972c8 Update __init__.py 2018-04-26 21:44:06 +02:00
Pascal Vizeli
3d101a24a1 Update API.md 2018-04-26 21:42:45 +02:00
Pascal Vizeli
2ed3ddf05b fix lint 2018-04-26 21:23:43 +02:00
Pascal Vizeli
10b3658bd7 Revert last changes 2018-04-26 20:51:29 +02:00
Pascal Vizeli
9f5903089e Cleanup API 2018-04-26 19:49:12 +02:00
Pascal Vizeli
0593885ed4 revert error 2018-04-26 19:25:10 +02:00
Pascal Vizeli
3efbe11d49 Cleanup 2018-04-26 19:23:52 +02:00
Pascal Vizeli
1c2e0e5749 Update host.py 2018-04-26 11:36:51 +02:00
Pascal Vizeli
f64da6a547 Update exceptions.py 2018-04-26 11:33:43 +02:00
Pascal Vizeli
94fba7e175 Update info.py 2018-04-26 11:32:15 +02:00
Pascal Vizeli
a59245e6bb Update __init__.py 2018-04-26 11:29:12 +02:00
Pascal Vizeli
217c1acc62 Update and rename power.py to control.py 2018-04-26 11:27:02 +02:00
Pascal Vizeli
2c0a68bd8f Update and rename local.py to info.py 2018-04-26 09:44:49 +02:00
Pascal Vizeli
e37ffd6107 Merge pull request #450 from home-assistant/dbus
Initial Dbus support
2018-04-26 00:17:45 +02:00
Pascal Vizeli
3bde598fa7 fix host 2018-04-25 23:49:45 +02:00
Pascal Vizeli
53f42ff934 fix attr 2018-04-25 23:36:44 +02:00
Pascal Vizeli
9041eb9e9a Fix attributes 2018-04-25 23:24:55 +02:00
Pascal Vizeli
70ac395232 fix bugs 2018-04-25 22:47:17 +02:00
Pascal Vizeli
82f68b4a7b fix dbus 2018-04-25 22:27:57 +02:00
Pascal Vizeli
2b2f3214e9 fix selecter 2018-04-25 22:12:27 +02:00
Pascal Vizeli
1c0d63a02e fix sys 2018-04-25 21:49:28 +02:00
Pascal Vizeli
de77215630 Update Home-Assistant to version 0.68.0b1 2018-04-25 21:43:06 +02:00
Pascal Vizeli
f300b843c1 Update Home-Assistant to version 0.68.0b1 2018-04-25 21:42:35 +02:00
Pascal Vizeli
0bb81136bb Add hostname function 2018-04-24 23:38:40 +02:00
Pascal Vizeli
2a81ced817 Update gdbus.py 2018-04-24 15:52:18 +02:00
Pascal Vizeli
7363951a9a Update gdbus.py 2018-04-24 15:40:14 +02:00
Pascal Vizeli
6f770b78af add interface dbus class 2018-04-23 23:30:21 +02:00
Pascal Vizeli
10219a348f fix lint 2018-04-23 21:56:54 +02:00
Pascal Vizeli
23d1013cfa Follow the correct shutdown flow 2018-04-23 21:45:06 +02:00
Pascal Vizeli
05980d4147 some cleanup more 2018-04-23 21:22:29 +02:00
Pascal Vizeli
e5e25c895f Fix error handling 2018-04-23 21:10:48 +02:00
Pascal Vizeli
b486883ff6 Cleanups 2018-04-23 15:32:23 +02:00
Pascal Vizeli
42dd4d9557 Update coresys.py 2018-04-23 09:05:52 +02:00
Pascal Vizeli
7dff9e09a7 Update bootstrap.py 2018-04-23 09:05:08 +02:00
Pascal Vizeli
c315b026a3 Update __init__.py 2018-04-23 08:58:06 +02:00
Pascal Vizeli
a4ba4c80e8 Update __init__.py 2018-04-23 08:57:39 +02:00
Pascal Vizeli
ccd48b63a2 Create __init__.py 2018-04-23 08:51:47 +02:00
Pascal Vizeli
6d5f70ced6 Rename hassio/misc/dbus/rauc.py to hassio/dbus/rauc.py 2018-04-23 08:51:15 +02:00
Pascal Vizeli
ccffb4b786 Rename hassio/misc/rauc.py to hassio/misc/dbus/rauc.py 2018-04-23 08:50:51 +02:00
Pascal Vizeli
68dbbe212c Rename hassio/misc/networkmanager.py to hassio/dbus/networkmanager.py 2018-04-23 08:50:18 +02:00
Pascal Vizeli
5df869e08a Rename hassio/misc/systemd.py to hassio/dbus/systemd.py 2018-04-23 08:49:56 +02:00
Pascal Vizeli
63b9e023b4 add hostmanager 2018-04-22 17:59:41 +02:00
Pascal Vizeli
8f357739ec code cleanups 2018-04-22 17:44:03 +02:00
Pascal Vizeli
808fc0f8b6 Log internal exceptions on API level 2018-04-22 10:16:24 +02:00
Pascal Vizeli
1a6f6085e6 Add API support for new handling 2018-04-22 10:15:07 +02:00
Pascal Vizeli
0de3e9a233 update handling 2018-04-22 09:59:43 +02:00
Pascal Vizeli
f1237f124f small down the footprint 2018-04-22 09:35:36 +02:00
Pascal Vizeli
69142b6fb0 Add systemd dbus 2018-04-21 23:56:36 +02:00
Pascal Vizeli
28f295a1e2 Cleanup 2018-04-21 22:33:06 +02:00
Pascal Vizeli
55c2127baa Cleanup Loop handling 2018-04-21 16:30:31 +02:00
Pascal Vizeli
265c36b345 Claim exceptions 2018-04-21 15:39:08 +02:00
Pascal Vizeli
9f081fe32f Update Home-Assistant to version 0.68.0b0 2018-04-21 00:04:15 +02:00
Pascal Vizeli
e4fb6ad727 Update Home-Assistant to version 0.68.0b0 2018-04-21 00:03:52 +02:00
Pascal Vizeli
1040a1624a fix lint 2018-04-20 23:40:58 +02:00
Pascal Vizeli
a2ee2852a0 Update gdbus.py 2018-04-20 16:10:59 +02:00
Pascal Vizeli
b2e3b726d9 Update gdbus.py 2018-04-20 16:01:43 +02:00
Pascal Vizeli
0f4e557552 Update gdbus.py 2018-04-20 15:59:04 +02:00
Pascal Vizeli
2efa9f9483 Update gdbus.py 2018-04-20 15:48:36 +02:00
Pascal Vizeli
43e6ca8f4a Update gdbus.py 2018-04-20 10:56:47 +02:00
Pascal Vizeli
34d67a7bcd Update gdbus.py 2018-04-20 10:15:29 +02:00
Pascal Vizeli
5a6051f9a1 Update gdbus.py 2018-04-20 09:58:49 +02:00
Pascal Vizeli
157e48f946 Initial Dbus support 2018-04-19 23:27:20 +02:00
Pascal Vizeli
9469a258ff Update Home-Assistant to version 0.67.1 2018-04-18 12:30:15 +02:00
Pascal Vizeli
fd0aeb5341 Update Home-Assistant to version 0.67.1 2018-04-18 12:29:52 +02:00
Pascal Vizeli
4d4a4ce043 Update Home-Assistant to version 0.67.1 2018-04-18 12:29:38 +02:00
Pascal Vizeli
678f77cc05 Pump version to 0.102 2018-04-14 10:50:42 +02:00
Pascal Vizeli
6c30248389 Update Home-Assistant to version 0.67.0 2018-04-14 10:04:43 +02:00
Pascal Vizeli
fda7c1cf11 Update Home-Assistant to version 0.67.0 2018-04-14 10:04:19 +02:00
Pascal Vizeli
364e5ec0b8 Update Home-Assistant to version 0.67.0 2018-04-14 10:03:51 +02:00
Pascal Vizeli
947bf7799c Fix version conflict 2018-04-14 01:28:44 +02:00
Pascal Vizeli
e22836d706 Fix version conflict 2018-04-14 01:22:39 +02:00
Pascal Vizeli
6c8fcbfb80 Update Hass.io to version 0.101 2018-04-14 01:18:00 +02:00
Pascal Vizeli
f1fe1877fe Merge pull request #442 from home-assistant/ui-101
Update panel audio
2018-04-14 00:59:37 +02:00
Pascal Vizeli
3c0831c8eb Update pannel audio 2018-04-14 00:52:11 +02:00
Pascal Vizeli
35b3f364c9 Merge pull request #441 from home-assistant/new_audio_system
Extend Audio support
2018-04-14 00:44:37 +02:00
Pascal Vizeli
c4299b51cd Clear device on changes 2018-04-14 00:30:28 +02:00
Pascal Vizeli
31caed20fa Fix device name 2018-04-14 00:27:31 +02:00
Pascal Vizeli
41fed656c1 Use now attr 2018-04-14 00:19:29 +02:00
Pascal Vizeli
c5ee2ebc49 fix v2 2018-04-13 23:58:46 +02:00
Pascal Vizeli
743a218219 fix bug 2018-04-13 23:45:03 +02:00
Pascal Vizeli
093ef17fb7 find the error 2018-04-13 23:31:40 +02:00
Pascal Vizeli
a41912be0a fix db 2018-04-13 23:21:42 +02:00
Pascal Vizeli
5becd51b50 test 4 2018-04-13 23:11:20 +02:00
Pascal Vizeli
ef7a375396 test 2 2018-04-13 22:56:36 +02:00
Pascal Vizeli
19879e3287 test 2018-04-13 22:42:27 +02:00
Pascal Vizeli
d1c4f342fc Fix bootstrap 2018-04-13 22:16:55 +02:00
Pascal Vizeli
2f62b7046c cleanup 2018-04-13 22:04:01 +02:00
Pascal Vizeli
0cca8f522b rename audio object 2018-04-13 21:19:57 +02:00
Pascal Vizeli
39decec001 Update Home-Assistant to version 0.67.0b1 2018-04-13 06:36:42 +02:00
Pascal Vizeli
3489db2768 Update Home-Assistant to version 0.67.0b1 2018-04-13 06:36:21 +02:00
Pascal Vizeli
3382688669 Fix name 2018-04-13 00:03:03 +02:00
Pascal Vizeli
cf00ce7d78 fix lint 2018-04-12 23:50:58 +02:00
Pascal Vizeli
2c714aa003 fix 1 2018-04-12 23:11:38 +02:00
Pascal Vizeli
1e7858bf06 fix url 2018-04-12 23:00:42 +02:00
Pascal Vizeli
4e428c2e41 Fix options 2018-04-12 22:39:26 +02:00
Pascal Vizeli
b95ab3e95a Stage API 2018-04-12 22:15:08 +02:00
Pascal Vizeli
0dd7f8fbaa Fix some comments 2018-04-12 22:07:41 +02:00
Pascal Vizeli
a2789ac540 Extend Audio support 2018-04-11 23:53:30 +02:00
Pascal Vizeli
a785e10a3f Merge pull request #440 from home-assistant/addon-slug
Add slug to add-on info
2018-04-11 20:01:15 +02:00
Pascal Vizeli
10dad5a209 Update API.md 2018-04-11 18:53:01 +02:00
Pascal Vizeli
9327b24d44 Add slug to add-on info 2018-04-11 18:51:03 +02:00
Pascal Vizeli
7d02bb2fe9 Pump version to 0.101 2018-04-10 21:21:15 +02:00
Pascal Vizeli
a2d3ee0d67 Fix version conflict 2018-04-10 21:18:47 +02:00
Pascal Vizeli
d29fab69e8 Merge remote-tracking branch 'origin/dev' into rc 2018-04-09 23:46:52 +02:00
Pascal Vizeli
6205f40298 Pump version to 0.100 2018-04-09 23:45:33 +02:00
Pascal Vizeli
6b169f3f17 Fix version 2018-04-09 23:44:52 +02:00
Pascal Vizeli
0d4a5a7ffb Fix version conflict 2018-04-09 23:41:00 +02:00
Pascal Vizeli
dac90d29dd Update Hass.io to version 1.0 2018-04-09 23:39:19 +02:00
Pascal Vizeli
7e815633e7 Merge pull request #437 from home-assistant/fix_restart
Abstract restart logic
2018-04-09 23:31:55 +02:00
Pascal Vizeli
f062f31ca2 Fix logic 2018-04-09 23:10:12 +02:00
Pascal Vizeli
1374f90433 cleanup version 2018-04-09 22:52:16 +02:00
Pascal Vizeli
b692b19a4d Fix log bug 2018-04-09 22:50:21 +02:00
Pascal Vizeli
92d5b14cf5 Abstract restart logic 2018-04-09 22:13:16 +02:00
Pascal Vizeli
6a84829c16 Merge pull request #436 from home-assistant/aiohttp_update
Update aioHttp 3.1.2 & Handling
2018-04-09 21:29:21 +02:00
Pascal Vizeli
7036ecbd0a Update aioHttp 3.1.2 & Handling 2018-04-09 21:01:06 +02:00
Pascal Vizeli
19b5059972 Pump version 1.0 2018-04-09 20:23:04 +02:00
Pascal Vizeli
cebc377fa7 Merge pull request #435 from home-assistant/fix_docker_char
Bugfix, remove unsupported characters
2018-04-09 20:22:03 +02:00
Pascal Vizeli
d36c3919d7 Update docker 2018-04-09 20:01:48 +02:00
Pascal Vizeli
0684427373 Bugfix, remove unsupported characters 2018-04-08 23:30:42 +02:00
Pascal Vizeli
8ff79e85bf Merge pull request #433 from home-assistant/secure
Add support for Seccomp/AppArmor profiles
2018-04-08 23:07:33 +02:00
Pascal Vizeli
ee4b28a490 Fix's & cleanup 2018-04-08 22:27:58 +02:00
Pascal Vizeli
fddd5b8860 Fix lint 2018-04-07 00:32:54 +02:00
Pascal Vizeli
72279072ac Add support for Seccomp/AppArmor profiles 2018-04-07 00:24:23 +02:00
Pascal Vizeli
0b70448273 Update Home-Assistant 0.67.0b0 2018-04-06 23:20:02 +02:00
Pascal Vizeli
4eb24fcbc5 Update Home-Assistant 0.67.0b0 2018-04-06 23:19:31 +02:00
Pascal Vizeli
06edf59d14 Update Home-Assistant to version 0.66.1 2018-04-02 09:47:39 +02:00
Pascal Vizeli
36ca851bc2 Update Home-Assistant to version 0.66.1 2018-04-02 09:47:21 +02:00
Pascal Vizeli
a4e453bf83 Update Home-Assistant to version 0.66.1 2018-04-02 09:47:05 +02:00
Pascal Vizeli
d211eec66f Update Home-Assistant to version 0.66.1b0 2018-04-01 11:08:34 +02:00
Pascal Vizeli
db8540d4ab Update Home-Assistant to version 0.66.1b0 2018-04-01 11:07:55 +02:00
Pascal Vizeli
30e270e7c0 Update Home-Assistant to version 0.66.0 2018-03-31 09:45:53 +02:00
Pascal Vizeli
9734307551 Update Home-Assistant to version 0.66.0 2018-03-31 09:45:32 +02:00
Pascal Vizeli
c650f8d1e1 Update Home-Assistant to version 0.66.0 2018-03-31 09:45:15 +02:00
Pascal Vizeli
10005898f8 Fix tag name 2018-03-30 15:10:35 +02:00
Pascal Vizeli
716389e0c1 Fix tag format 2018-03-30 15:10:02 +02:00
Pascal Vizeli
658729feb5 Update Home-Assistant to version 0.66.0.b3 2018-03-30 10:23:10 +02:00
Pascal Vizeli
ae7808eb2a Update Home-Assistant to version 0.66.0.b3 2018-03-30 10:22:41 +02:00
Pascal Vizeli
d8e0e9e0b0 Update Home-Assistant to version 0.66.0.b2 2018-03-27 09:24:59 +02:00
Pascal Vizeli
a860a3c122 Update Home-Assistant to version 0.66.0.b2 2018-03-27 09:24:38 +02:00
Pascal Vizeli
fe60d526b9 Revert home-assistant version 2018-03-24 23:34:22 +01:00
Pascal Vizeli
769904778f Merge remote-tracking branch 'origin/rc' 2018-03-24 23:32:37 +01:00
Pascal Vizeli
a3a40c79d6 Fix merge conflicts 2018-03-24 23:31:26 +01:00
Pascal Vizeli
b44f613136 Update hass.io to version 0.99 2018-03-24 23:09:32 +01:00
Pascal Vizeli
801be9c60b Create .gitattributes 2018-03-24 23:05:58 +01:00
Pascal Vizeli
b6db6a1287 Create .gitattributes 2018-03-24 23:04:37 +01:00
Pascal Vizeli
4181174bcc Create .gitattributes 2018-03-24 23:03:15 +01:00
Pascal Vizeli
3be46e6011 Update Home-Assistant to version 0.66.0.beta0 2018-03-24 22:58:52 +01:00
Pascal Vizeli
98b93efc5c Merge pull request #423 from home-assistant/beta
Change Upstream handling
2018-03-24 22:56:04 +01:00
Pascal Vizeli
6156019c2f Merge pull request #424 from home-assistant/ui-99
Update pannel for 0.99
2018-03-24 22:50:33 +01:00
Pascal Vizeli
80d60148a9 Update pannel for 0.99 2018-03-24 22:48:45 +01:00
Pascal Vizeli
8baf59a608 fix lint 2018-03-24 22:06:56 +01:00
Pascal Vizeli
b546365aaa Fix 2018-03-24 22:05:01 +01:00
Pascal Vizeli
0a68698912 rename mode to channel 2018-03-24 22:01:13 +01:00
Pascal Vizeli
45288a2491 Change Upstream handling 2018-03-24 21:44:44 +01:00
Pascal Vizeli
f34a175e4f Update Home-Assistant to version 0.66.0.beta0 2018-03-24 10:34:53 +01:00
Pascal Vizeli
6e7e145822 Update Home-Assistant to version 0.65.6 2018-03-21 22:19:38 +01:00
Pascal Vizeli
9abebe2d5d Update Home-Assistant to version 0.65.6 2018-03-21 22:19:08 +01:00
Pascal Vizeli
b0c5884c3f Update Home-Assistant to version 0.65.5 2018-03-15 12:11:01 +01:00
Pascal Vizeli
a79e6a8eea Update Home-Assistant to version 0.65.5 2018-03-15 12:10:16 +01:00
Pascal Vizeli
c1f1aed9ca Pump version to 0.99 2018-03-14 22:25:58 +01:00
Pascal Vizeli
65b0e17b5b Merge pull request #414 from home-assistant/dev
Release 0.98
2018-03-14 22:25:14 +01:00
Pascal Vizeli
6947131b47 Update Hass.io to version 0.98 2018-03-14 22:10:13 +01:00
Pascal Vizeli
914dd53da0 Merge pull request #411 from home-assistant/fix_watchdog
Use lock on homeassistant level
2018-03-14 21:52:20 +01:00
Pascal Vizeli
58616ef686 bugfix aiohttp 2018-03-14 21:12:08 +01:00
Pascal Vizeli
563e0c1e0e fix wrong startup blocking 2018-03-14 19:08:03 +01:00
Pascal Vizeli
437070fd7a Merge pull request #412 from home-assistant/fix-geoip
Fix URL for freegeoip
2018-03-13 23:34:06 +01:00
Pascal Vizeli
baa9cf451c Fix URL for freegeoip 2018-03-13 23:28:38 +01:00
Pascal Vizeli
c2918d4519 Use lock on homeassistant level 2018-03-13 23:09:53 +01:00
Pascal Vizeli
1efdcd4691 Merge remote-tracking branch 'origin/master' into dev 2018-03-13 21:31:56 +01:00
Pascal Vizeli
2a43087ed7 Pump version to 0.98 2018-03-13 16:06:44 +01:00
Pascal Vizeli
5716324934 Merge pull request #410 from home-assistant/dev
Release 0.97
2018-03-13 16:05:31 +01:00
Pascal Vizeli
ae267e0380 Merge branch 'master' into dev 2018-03-13 14:09:13 +01:00
Pascal Vizeli
3918a2a228 Update Home-Assistant version 0.65.4 2018-03-13 14:07:21 +01:00
Pascal Vizeli
e375fc36d3 Update Hass.io to version 0.97 2018-03-13 00:09:57 +01:00
Pascal Vizeli
f5e29b4651 Update panel to last (#408) 2018-03-12 23:51:09 +01:00
Pascal Vizeli
524d875516 Update aioHttp3 (#403)
* Update aioHttp3

* fix line ending

* fix close session
2018-03-12 23:40:06 +01:00
Pascal Vizeli
60bdc00ce9 Update Home-Assistant to version 0.65.3 2018-03-12 07:13:47 +01:00
Pascal Vizeli
073166190f Update Home-Assistant to version 0.65.3 2018-03-12 07:13:27 +01:00
Pascal Vizeli
b80e4d7d70 Update Home-Assistant to version 0.65.2 2018-03-11 23:58:16 +01:00
Pascal Vizeli
cc434e27cf Update Home-Assistant to version 0.65.2 2018-03-11 23:57:57 +01:00
Pascal Vizeli
8377e04b62 Update Home-Assistant to version 0.65.1 2018-03-11 20:32:43 +01:00
Pascal Vizeli
0a47fb9c83 Update Home-Assistant to version 0.65.1 2018-03-11 20:32:25 +01:00
Pascal Vizeli
a5d3c850e9 Update Home-Assistant to version 0.65.0 2018-03-09 23:32:47 +01:00
Pascal Vizeli
d6391f62be Update Home-Assistant to version 0.65.0 2018-03-09 23:10:27 +01:00
Pascal Vizeli
c6f302e448 Update ResinOS to version 1.3 2018-03-05 22:51:44 +01:00
Pascal Vizeli
9706022c21 Update ResinOS to version 1.3 2018-03-05 22:51:08 +01:00
Pascal Vizeli
1d858f4920 Update ResinOS to version 1.2 2018-03-04 00:43:24 +01:00
Pascal Vizeli
e09ba30d46 Update ResinOS to version 1.2 2018-03-04 00:43:00 +01:00
mark9white
38ec3d14ed Allow addons that require IPC_LOCK capability (#397) 2018-03-03 23:06:42 +01:00
Pascal Vizeli
8ee9380cc7 Pump version to 0.97 2018-03-03 11:15:39 +01:00
Pascal Vizeli
6e74e4c008 Fix version conflicts 2018-03-03 11:12:59 +01:00
Pascal Vizeli
5ebc58851b Update Hass.io to version 0.96 2018-03-03 11:08:00 +01:00
Pascal Vizeli
16b09bbfc5 Allow to use branch on repositories (#395)
* Allow to use branch on repositories

* Fix argument extraction

* fix lint
2018-03-03 11:00:58 +01:00
Pascal Vizeli
d4b5fc79f4 Update Home-Assistant to version 0.64.3 2018-03-03 00:07:04 +01:00
Pascal Vizeli
e51c044ccd Update Home-Assistant to version 0.64.3 2018-03-02 23:56:48 +01:00
Pascal Vizeli
d3b1ba81f7 Update panel for encrypted backups (#394)
* Update panel for encrypted backups

* fix lint
2018-03-02 23:23:40 +01:00
Pascal Vizeli
26f55f02c0 Update Home-Assistant to version 0.64.2 2018-03-02 07:01:42 +01:00
Pascal Vizeli
8050707ff9 Update Home-Assistant to version 0.64.2 2018-03-02 06:54:32 +01:00
c727
46252030cf Improve names for built-in repos (#391) 2018-03-01 19:00:21 +01:00
Pascal Vizeli
681fa835ef Update Home-Assistant to version 0.64.1 2018-02-28 08:16:18 +01:00
Pascal Vizeli
d6560eb976 Update Home-Assistant to version 0.64.1 2018-02-28 07:48:54 +01:00
Pascal Vizeli
3770b307af Pump version to 0.96 2018-02-26 22:55:53 +01:00
Pascal Vizeli
0dacbb31be Fix version conflicts 2018-02-26 22:53:31 +01:00
Pascal Vizeli
bbdbd756a7 Update Hass.io to version 0.95 2018-02-26 22:42:29 +01:00
Pascal Vizeli
508e38e622 Fix snapshot partial API (#389) 2018-02-26 22:26:39 +01:00
Pascal Vizeli
ffe45d0d02 Bugfix if no data is given for encryption (#387)
* Bugfix if no data is given for encryption

* Update snapshot.py
2018-02-26 22:17:25 +01:00
Pascal Vizeli
9206d1acf8 Update Home-Assistant to version 0.64 2018-02-26 06:10:40 +01:00
Pascal Vizeli
da867ef8ef Update Home-Assistant to version 0.64 2018-02-26 06:03:24 +01:00
Pascal Vizeli
4826201e51 Pump version to 0.95 2018-02-25 12:57:53 +01:00
Pascal Vizeli
463c97f9e7 Update Hass.io to version 0.94 2018-02-25 12:49:39 +01:00
Pascal Vizeli
3983928c6c Bugfix snapshot dialog (#380) 2018-02-25 12:18:05 +01:00
Pascal Vizeli
15e626027f Pump version to 0.94 2018-02-24 08:50:21 +01:00
Pascal Vizeli
d46810752e Update Hass.io to version 0.93 2018-02-24 08:46:53 +01:00
Pascal Vizeli
3d10b502a0 Bugfix panel system (#379) 2018-02-24 08:38:59 +01:00
Pascal Vizeli
433c5cef3b Stop home-assistant only if they will be restored (#377) 2018-02-23 22:22:38 +01:00
Pascal Vizeli
697caf553a Pump version to 0.93 2018-02-23 11:38:04 +01:00
Pascal Vizeli
1e11359c71 Fix version conflicts 2018-02-23 11:35:43 +01:00
Pascal Vizeli
5285431825 New panel (#374) 2018-02-23 11:13:53 +01:00
Pascal Vizeli
7743a572a9 Update Hass.io to version 0.92 2018-02-23 11:01:51 +01:00
Pascal Vizeli
3b974920d3 Return snapshot slug for snapshot/import (#372)
* Update __init__.py

* Update snapshots.py

* Update API.md

* Update __init__.py

* Update __init__.py
2018-02-23 10:52:35 +01:00
Pascal Vizeli
6bc9792248 Update setup.py (#373) 2018-02-23 10:37:14 +01:00
Pascal Vizeli
da55f6fb10 Pump version to 0.92 2018-02-23 10:34:21 +01:00
Pascal Vizeli
ffa90a3407 Update Home-Assistant to version 0.63.3 2018-02-18 22:16:46 +01:00
Pascal Vizeli
0a13ea3743 Update Home-Assistant to version 0.63.3 2018-02-18 22:15:39 +01:00
Pascal Vizeli
0e2e588145 Update utils.py 2018-02-18 12:31:06 +01:00
Pascal Vizeli
b8c50fee36 Update validate.py 2018-02-18 12:30:41 +01:00
Pascal Vizeli
8cb0b7c498 Update validate.py 2018-02-18 12:23:46 +01:00
Pascal Vizeli
699fcdafba Fix pw2 (#369)
* fix rate password

* convert int
2018-02-18 12:18:11 +01:00
Pascal Vizeli
b4d5aeb5d0 Update Hass.io to version 0.91 2018-02-18 12:15:54 +01:00
Pascal Vizeli
d067dd643e Fix password hack (#368) 2018-02-18 11:51:11 +01:00
Pascal Vizeli
65a2bf2d18 Pump version to 0.91 2018-02-18 11:01:13 +01:00
Pascal Vizeli
e826e8184f Update Hass.io to version 0.90 2018-02-18 10:59:58 +01:00
Pascal Vizeli
dacbde7d77 Extend the security of snapshots (#367)
* extend security

* fix lint
2018-02-18 10:57:05 +01:00
Pascal Vizeli
5b0587b672 Pump version to 0.90 2018-02-17 17:28:19 +01:00
Pascal Vizeli
f0320c0f6d Fix version conflicts 2018-02-17 16:29:36 +01:00
Pascal Vizeli
e05c32df25 Update Hass.io to version 0.89 2018-02-17 16:28:50 +01:00
c727
9c40c32e95 Add timezone to snapshot timestamp (#360)
* Add timezone to snapshot timestamp

```
old: 2018-02-14T15:13:46.391829
new: 2018-02-14T15:13:46.391829+00:00
```

* Update __init__.py

* Move code to dt util

* Lint

* Lint 2

* Update dt.py

* Update __init__.py
2018-02-17 16:13:23 +01:00
Pascal Vizeli
ac60de0360 Update security.py (#365) 2018-02-17 16:09:10 +01:00
Pascal Vizeli
587047f9d6 Add support for encrypted snapshot files (#354)
* Add support for encrypted files

* Update tar.py

* Update tar.py

* Update tar.py

* Update addon.py

* Update API.md

* Update API.md

* Update tar.py

* cleanup snapshot

* Update API.md

* Update const.py

* Update const.py

* Update validate.py

* Update homeassistant.py

* Update homeassistant.py

* Update validate.py

* Update validate.py

* Update snapshot.py

* Update utils.py

* Update snapshot.py

* Update utils.py

* Update snapshot.py

* Update validate.py

* Update snapshot.py

* Update validate.py

* Update const.py

* fix lint

* Update snapshot.py

* Update __init__.py

* Update snapshot.py

* Update __init__.py

* Update __init__.py

* Finish snapshot object

* Fix struct

* cleanup snapshot flow

* fix some points

* Add API upload

* fix lint

* Update voluptuous

* fix docker

* Update snapshots.py

* fix versions

* fix schema

* fix schema

* fix api

* fix path

* Handle import better

* fix routing

* fix bugs

* fix bug

* cleanup gz

* fix some bugs

* fix stage

* Fix

* fix

* protect None password

* fix API

* handle exception better

* fix

* fix remove of addons

* fix bug

* clenaup code

* fix none tasks

* Encrypt Home-Assistant

* fix decrypt

* fix binary
2018-02-17 15:52:33 +01:00
Fabian Affolter
e815223047 Merge pull request #363 from home-assistant/probot
Enable probot move
2018-02-16 13:25:16 +01:00
Fabian Affolter
b6fb5ab950 Enable probot move 2018-02-16 13:18:13 +01:00
Pascal Vizeli
a0906937c4 Update Home-Assistant to version 0.63.2 2018-02-14 22:08:09 +01:00
Pascal Vizeli
07c47df369 Update Home-Assistant to version 0.63.2 2018-02-14 21:12:18 +01:00
Pascal Vizeli
85e9a949cc Update Home-Assistant to version 0.63.1 2018-02-13 06:38:45 +01:00
Pascal Vizeli
3933fb0664 Update Home-Assistant to version 0.63.1 2018-02-13 06:26:45 +01:00
Pascal Vizeli
a885fbdb41 Pump version to 0.89 2018-02-11 23:03:46 +01:00
Pascal Vizeli
210793eb34 Update Home-Assistant to version 0.63 2018-02-11 09:31:19 +01:00
Pascal Vizeli
0235c7bce0 Update Home-Assistant to version 0.63 2018-02-11 09:22:31 +01:00
Pascal Vizeli
4419c0fc6c Update Hass.io to version 0.88 2018-02-11 01:53:18 +01:00
Pascal Vizeli
2f3701693d Fix bugs with docker api 3.0.1 and fix the version (#353)
* Fix version

* fix snapshot
2018-02-11 01:42:53 +01:00
Pascal Vizeli
3bf446cbdb Improve security layer (#352)
* Improve security layer

* Update logger

* Fix access

* Validate token

* fix

* fix some bugs

* fix lint
2018-02-11 00:05:20 +01:00
Pascal Vizeli
0c67cc13a1 Pump version to 0.88 2018-02-10 00:23:37 +01:00
Pascal Vizeli
0b80d7b6f4 Update Hass.io to version 0.87 2018-02-10 00:17:13 +01:00
Pascal Vizeli
23c35d4c80 Bugfix Check Config for Home-Assistant (#350)
* add logger

* Bugfix config check
2018-02-10 00:10:30 +01:00
Pascal Vizeli
e939c29efa Pump version to 0.87 2018-02-09 10:45:15 +01:00
Pascal Vizeli
ea0655b4e5 Fix version conflict 2018-02-09 10:43:44 +01:00
Pascal Vizeli
4117ce2e86 Update Hass.io to version 0.86 2018-02-09 01:36:25 +01:00
Pascal Vizeli
dec04386bf Add support for home-assistant bootup (#349)
* Add support for home-assistant bootup

* fix bug

* fix

* fix ip bug

* bugfix
2018-02-09 01:27:45 +01:00
Pascal Vizeli
b50756785e Add support to expose internal services (#339)
* Init services discovery

* extend it

* Add mqtt provider

* Service support

* More protocol stuff

* Update validate.py

* Update validate.py

* Update API.md

* Update API.md

* update api

* add API for services

* fix lint

* add security middleware

* Add discovery layout

* update

* Finish discovery

* improve discovery

* fix

* Update API

* Update api

* fix

* Fix lint

* Update API.md

* Update __init__.py

* Update API.md

* Update interface.py

* Update mqtt.py

* Update discovery.py

* Update const.py

* Update validate.py

* Update validate.py

* Update mqtt.py

* Update mqtt.py

* Update discovery.py

* Update discovery.py

* Update discovery.py

* Update interface.py

* Update mqtt.py

* Update mqtt.py

* Update services.py

* Update discovery.py

* Update discovery.py

* Update mqtt.py

* Update discovery.py

* Update services.py

* Update discovery.py

* Update discovery.py

* Update mqtt.py

* Update discovery.py

* fix aiohttp

* test

* Update const.py

* Update addon.py

* Update homeassistant.py

* Update const.py

* Update addon.py

* Update homeassistant.py

* Update addon.py

* Update security.py

* Update const.py

* Update validate.py

* Update const.py

* Update addon.py

* Update API.md

* Update addons.py

* Update addon.py

* Update validate.py

* Update security.py

* Update security.py

* Update const.py

* Update services.py

* Update discovery.py

* Update API.md

* Update services.py

* Update API.md

* Update services.py

* Update discovery.py

* Update discovery.py

* Update mqtt.py

* Update discovery.py

* Update discovery.py

* Update __init__.py

* Update mqtt.py

* Update security.py

* fix lint

* Update core.py

* Update API.md

* Update services.py
2018-02-08 17:19:47 +01:00
Pascal Vizeli
b9538bdc67 Change timeout to 300 (#348) 2018-02-08 12:34:30 +01:00
Pascal Vizeli
a928281bbe Update Home-Assistant to version 0.62.1 2018-01-31 13:00:28 +01:00
Pascal Vizeli
4533d17e27 Update Home-Assistant to version 0.62.1 2018-01-31 12:49:52 +01:00
Pascal Vizeli
546df6d001 Pump version to 0.86 2018-01-29 23:45:01 +01:00
Pascal Vizeli
f14eef62ae Fix version conflicts 2018-01-29 23:42:58 +01:00
Pascal Vizeli
ee86770570 Fix API URL 2018-01-29 23:27:31 +01:00
Pascal Vizeli
385a4e9f6f Update hass.io to version 0.85 2018-01-29 22:45:03 +01:00
Pascal Vizeli
142cdcffca Better error handling for proxy (#334) 2018-01-29 12:36:58 +01:00
Pascal Vizeli
eb6c753514 Add support for undocument ha version inside wesocket (#333) 2018-01-29 10:17:53 +01:00
Pascal Vizeli
c3b62c80fb Update HomeAssistant to version 0.62.0 2018-01-28 12:03:01 +01:00
Pascal Vizeli
f77e176a6e Update HomeAssistant to version 0.62.0 2018-01-28 09:02:23 +01:00
Pascal Vizeli
3f99dec858 Pump version to 0.85 2018-01-26 15:21:23 +01:00
Pascal Vizeli
81b0cf55b0 Update Hass.io to version 0.84 2018-01-26 14:37:31 +01:00
Pascal Vizeli
1d5d2dc731 Update new panel system (#330) 2018-01-26 14:07:22 +01:00
Franck Nijhof
04f5ee0a80 Adds support for add-on icons (#328)
* Adds support for add-on icons

* Update addons.py
2018-01-25 00:02:15 +01:00
Pascal Vizeli
7a02777cfb New panel (#326)
* Update __init__.py

* Update __init__.py

* Update __init__.py

* Update __init__.py
2018-01-23 13:54:11 +01:00
Pascal Vizeli
7257c44d27 Pump version to 0.84 2018-01-18 23:50:13 +01:00
Pascal Vizeli
cb15602814 Merge remote-tracking branch 'origin/dev' 2018-01-18 23:39:57 +01:00
Pascal Vizeli
0f2c333484 Update Hass.io to version 0.83 2018-01-18 23:36:46 +01:00
Pascal Vizeli
6f2cf2ef85 Robust json file handling with default reset on runtime (#321)
* Update json.py

* Update validate.py

* Update validate.py

* Update snapshots.py

* Update validate.py

* Update homeassistant.py

* Update validate.py

* Update snapshot.py

* Update snapshot.py

* Update snapshot.py

* Update json.py

* Update json.py

* Update json.py

* Update validate.py

* Update snapshots.py

* Update validate.py

* Update validate.py

* improve config updates

* fix lint

* update build

* fix schema

* fix validate

* fix lint

* fix some styles

* fix

* fix snapshot

* fix errors

* Update API
2018-01-18 23:33:05 +01:00
Pascal Vizeli
70a721a47d Reset default config with None (#320)
* Update addons.py

* Update addon.py

* Update API.md
2018-01-18 10:21:16 +01:00
Pascal Vizeli
b32947af98 Update HomeAssistant to version 0.61.1 2018-01-17 12:59:20 +01:00
Pascal Vizeli
94b44ec7fe Update HomeAssistant to version 0.61.1 2018-01-17 12:27:28 +01:00
Pascal Vizeli
5c8aa71c31 Pump version to 0.83 2018-01-16 12:45:14 +01:00
pvizeli
a6c424b7c8 Fix merge conflicts 2018-01-16 12:42:58 +01:00
Pascal Vizeli
38e40c342d Update hass.io to version 0.82 2018-01-16 12:23:11 +01:00
Pascal Vizeli
26d390b66e Add GET param support (#314) 2018-01-16 12:20:04 +01:00
Pascal Vizeli
baddafa552 Update HomeAssistant to version 0.61 2018-01-15 23:03:26 +01:00
Pascal Vizeli
f443d3052b Update HomeAssistant to version 0.61 2018-01-15 22:53:18 +01:00
Franck Nijhof
8fc27ff28e ✏️ Small typo in error msg (#311) 2018-01-15 22:52:13 +01:00
Franck Nijhof
3784d759f5 📚 Fixes markdownlint & spelling issue in the README file (#312) 2018-01-15 22:51:32 +01:00
Pascal Vizeli
61037f3852 Update network.py 2018-01-11 11:16:46 +01:00
Pascal Vizeli
db8aaecdbe Remove old security layer (#306)
* Remove old security layer

* remove unneded libs

* Update diagram
2018-01-10 22:27:47 +01:00
Pascal Vizeli
15a4541595 HomeAssistant API token (#303)
* Add a uuid to home-assistant

* Add API_TOKEN to homeassistant

* Update homeassistant.py

* Update addon.py
2018-01-10 18:14:32 +01:00
Pascal Vizeli
50ae8e2335 Pump version to 0.82 2018-01-08 15:26:34 +01:00
Pascal Vizeli
279df17ba4 Update hass.io to version 0.81 2018-01-08 15:03:14 +01:00
Pascal Vizeli
f8e6362283 Improve supervisor update handling (#300)
* Improve supervisor update handling

* fix message position
2018-01-08 14:55:13 +01:00
Pascal Vizeli
0c44064926 Disable ipv6 / DNS Resolve troubles (#299)
* Disable ipv6

* Disable search domain

* Update network.py

* Update __init__.py

* add options
2018-01-08 13:57:59 +01:00
Pascal Vizeli
73c437574c Pump version to 0.81 2018-01-07 18:11:30 +01:00
Pascal Vizeli
69a2182c04 Fix version conflict 2018-01-07 18:10:03 +01:00
Pascal Vizeli
ce80e6cd32 Update hass.io to version 0.80 2018-01-07 18:04:31 +01:00
Pascal Vizeli
054def09f7 Update panel for 0.80 (#298)
* Update pannel

* fix lint
2018-01-07 17:47:15 +01:00
Pascal Vizeli
eebe90bd14 Add support for stats & code cleanup (#297)
* Add support for stats & code cleanup

* Add more stats

* Move code into own object

* Add to API

* Update API

* Add error handling

* fix lint

* fix block io
2018-01-07 15:53:54 +01:00
Pascal Vizeli
6ea280ce60 Update HomeAssistant to version 0.60.1 2018-01-07 13:45:15 +01:00
Pascal Vizeli
e992b70f92 Update HomeAssistant to version 0.60.1 2018-01-07 13:38:09 +01:00
Pascal Vizeli
0f58bb35ba Bugfix return value supervisor update (#296)
* Update supervisor.py

* Update addon.py
2018-01-06 22:35:58 +01:00
Pascal Vizeli
56abfb6adc Pump version to 0.80 2018-01-05 18:22:51 +01:00
Pascal Vizeli
8352d61f8d Div. Bugfixes for 0.79 (#294)
* Bugfix supervisor logs

* fix list

* Update addon.py

* Update snapshot.py
2018-01-05 18:07:41 +01:00
Pascal Vizeli
51d585f299 Add community add-ons to defaults (#295) 2018-01-04 23:02:53 +01:00
Pascal Vizeli
d017a52922 Update hass.io to version 0.79 2018-01-04 13:26:28 +01:00
Pascal Vizeli
78ec0d1314 Remove home-assistant devices options (#293)
* Remove home-assistant devices options

* fix version mix/max snapshot

* fix wrong path

* fix import

* fix restore

* fix

* make exists call robust

* Update addon.py

* remove old custom function

* Update homeassistant.py

* Update homeassistant.py

* Update homeassistant.py

* Update snapshot.py

* Update validate.py

* Update snapshot.py

* Update homeassistant.py

* fix lint 1

* fix lint

* fix lint

* Update snapshot.py

* Update homeassistant.py

* Update homeassistant.py

* Update homeassistant.py
2018-01-04 12:52:17 +01:00
Pascal Vizeli
c84151e9e8 fix save 2018-01-04 10:54:57 +01:00
Pascal Vizeli
e8e599cb8c Update updater.py 2018-01-04 10:51:41 +01:00
florianj1
232b9ea239 Allow additional docker privileges (#292)
In order use a DVB adapter the capabilities SYS_TIME and SYS_NICE need to be granted.
2018-01-03 14:08:22 +01:00
Pascal Vizeli
1c49351e66 Refactory code / object handling (#289)
* Refactory code / object handling

* Next step

* fix lint

* Step 2

* Cleanup API code

* cleanup addons code

* cleanup data handling

* Cleanup addons data handling

* Cleanup docker api

* clean docker api p2

* next cleanup round

* cleanup start on snapshots

* update format strings

* fix setup

* fix lint

* fix lint

* fix lint

* fix tox

* Fix wrong import of datetime module

* Fix bug with attributes

* fix extraction

* Update core

* Update logs

* Expand scheduler

* add support for time interval objects

* next updates on tasks

* Fix some things

* Cleanup code / supervisor

* fix lint

* Fix some code styles

* rename stuff

* cleanup api call reload

* fix lock replacment

* fix lint

* fix lint

* fix bug

* fix wrong config links

* fix bugs

* fix bug

* Update version on startup

* Fix some bugs

* fix bug

* Fix snapshot

* Add wait boot options

* fix lint

* fix default config

* fix snapshot

* fix snapshot

* load snapshots on startup

* add log message at the end

* Some cleanups

* fix bug

* add logger

* add logger for supervisor update

* Add more logger
2018-01-02 21:21:29 +01:00
Pascal Vizeli
34d1f4725d Pump version to 0.79 2017-12-26 12:23:34 +01:00
Pascal Vizeli
7cd81dcc95 Update Hass.io to version 0.78 2017-12-26 12:11:32 +01:00
Pascal Vizeli
1bdd3d88de Bugfix SSL settings on proxy (#288)
* Bugfix SSL settings on proxy

* fix lint
2017-12-26 12:10:24 +01:00
Pascal Vizeli
d105552fa9 Pump version to 0.78 2017-12-26 01:47:01 +01:00
Pascal Vizeli
b5af35bd6c Fix version conflicts 2017-12-26 01:43:24 +01:00
Pascal Vizeli
7d46487491 Update hass.io to version 0.77 2017-12-26 01:38:22 +01:00
Pascal Vizeli
38a599011e Add long_description from README.md (#287)
* Add readme to API

* update name
2017-12-26 01:31:24 +01:00
Pascal Vizeli
e59e2fc8d7 Update API.md 2017-12-26 00:54:39 +01:00
Pascal Vizeli
b9ce405ada Add websocket proxy support (#286)
* Add websocket proxy support

* forward

* update proxy code

* fix import

* fix import

* fix

* reorder

* fix setup

* fix code

* stage al

* fix lint

* convert it into object

* fix lint

* fix url

* fix routing

* update log output

* fix future

* add loop

* Update log messages & error handling

* fix error message

* Update logging

* improve handling

* better error handling

* Fix server read

* fix cancel reader
2017-12-26 00:51:07 +01:00
Pascal Vizeli
d7df423deb Allow event stream over api proxy (#285)
* Allow event stream over api proxy

* fix lint

* fix lint

* cleanup code

* fix bug

* fix prepare

* Fix stream bug

* fix api request
2017-12-24 15:04:16 +01:00
Pascal Vizeli
99eea99e93 Update home-assistant to 0.60 2017-12-18 14:56:20 +01:00
Pascal Vizeli
63d82ce03e better merge base image (#280)
* better merge base image

* fix lint

* fix lint

* Update build.py

* fix lint
2017-12-18 10:30:31 +01:00
Pascal Vizeli
13a2c1ecd9 Update home-assistant to 0.60 2017-12-18 10:28:25 +01:00
Franck Nijhof
627ab4ee81 💄 Re-labeling of "By our self" (#282)
Changes it to "you", this improves the displaying of the maintainer for
local add-ons.

Ref #243
2017-12-14 23:34:09 +01:00
Pascal Vizeli
54f45539be Pump version to 0.77 2017-12-13 00:18:30 +01:00
Pascal Vizeli
53297205c8 Merge remote-tracking branch 'origin/dev' 2017-12-12 23:50:52 +01:00
Pascal Vizeli
0f09fdfcce Update hass.io to 0.76 2017-12-12 23:48:57 +01:00
Pascal Vizeli
24db0fdb86 Merge remote-tracking branch 'origin/dev' 2017-12-12 23:46:37 +01:00
Pascal Vizeli
7349234638 Use uvloop & aiohttp C extension (#279)
* Update Dockerfile

* Update __main__.py

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile

* Update Dockerfile
2017-12-12 23:38:33 +01:00
Pascal Vizeli
c691f2a559 Auto mapping UART devices from host (#276)
* Add hardware to docker api

* set hardware to docker

* add loop to dns

* Use loop for dns

* Update const.py

* Update API.md

* Update validate.py

* Update addon.py

* Update addon.py

* fix lint

* style

* Update hardware.py
2017-12-12 20:01:02 +01:00
Pascal Vizeli
110cd32dc3 Update hardware.py (#275) 2017-12-12 10:41:05 +01:00
Pascal Vizeli
26d8dc0ec6 Add support for host dbus system (#274) 2017-12-12 09:10:39 +01:00
Pascal Vizeli
fd41bda828 Cleanup some API stuff (#272)
* Update API.md

* Update addons.py
2017-12-11 22:40:02 +01:00
Pascal Vizeli
1e3868bb70 Add support for changelog (#271) 2017-12-10 23:45:30 +01:00
Pascal Vizeli
ece6c644cf IPC (#267)
* Update API.md

* Update const.py

* Update addon.py

* Update validate.py

* Update addon.py

* Update addons.py

* fix lint
2017-12-10 23:29:51 +01:00
Pascal Vizeli
6a5bd5a014 Disable AppArmor/SecComp (#266)
Disable AppArmor
2017-12-10 23:10:25 +01:00
Pascal Vizeli
664334f1ad Move setup to python 3.6 2017-12-10 22:16:22 +01:00
Pascal Vizeli
e5e28747d4 Cleanup dockerfile 2017-12-10 22:13:40 +01:00
Pascal Vizeli
c7956d95ae Update Home-Assistant to 0.59.2 2017-12-06 19:30:27 +01:00
Pascal Vizeli
5ce6abdbb6 Update Home-Assistant to 0.59.2 2017-12-06 16:30:38 +01:00
Pascal Vizeli
fad0185c26 Update Home-Assistant to 0.59.1 2017-12-05 08:08:28 +01:00
Pascal Vizeli
86faf32709 Update Home-Assistant to 0.59.1 2017-12-04 18:14:53 +01:00
Pascal Vizeli
19f413796d Update Home-Assistant to version 0.59 2017-12-04 10:49:15 +01:00
Pascal Vizeli
8f94b4d63f Print error on invalid json (#263) 2017-11-30 20:23:20 +01:00
Pascal Vizeli
db263f84af Update Home-Assistant to 0.58.1 2017-11-25 09:50:45 +01:00
Pascal Vizeli
747810b729 Update Home-Assistant to 0.58.1 2017-11-25 09:50:23 +01:00
Pascal Vizeli
d6768f15a1 Pump version to 0.76 2017-11-24 22:20:54 +01:00
Pascal Vizeli
6c75957578 Fix version merge conflict 2017-11-24 22:18:13 +01:00
Pascal Vizeli
3a8307acfe Fix panel (#258) 2017-11-24 21:54:56 +01:00
Pascal Vizeli
f20c7d42ee Update home-assistant to version 0.58.1 2017-11-24 14:13:16 +01:00
Pascal Vizeli
9419fbff94 Add new pannel (#257) 2017-11-24 14:01:17 +01:00
Pascal Vizeli
3ac6c03637 Update Hass.io to 0.75 2017-11-22 16:46:14 +01:00
Pascal Vizeli
a95274f1b3 Use tini for home-assistant docker (#255) 2017-11-21 15:55:10 +01:00
Markus
9d2fb87cec typo (#254) 2017-11-20 13:48:04 +01:00
Paulus Schoutsen
ce9c3565b6 Hassio panel split (#249)
* Allow serving two types of panels

* Remove old panel

* Make backwards compatible

* Add comment
2017-11-20 13:44:04 +01:00
Pascal Vizeli
b0ec58ed1b Update Home-Assistant to 0.57.3 2017-11-13 20:47:36 +01:00
Pascal Vizeli
893a5f8dd3 Update Home-Assistant to 0.57.3 2017-11-13 18:44:12 +01:00
Pascal Vizeli
98064f6a90 Update Home-Assistant to 0.57.2 2017-11-06 11:25:25 +01:00
Pascal Vizeli
5146f89354 Update Home-Assistant to 0.57.2 2017-11-06 07:24:04 +01:00
Pascal Vizeli
fb46592d48 Pump version to 0.75 2017-11-05 00:35:04 +01:00
Pascal Vizeli
b4fb5ac681 Fix merge conflict 2017-11-05 00:32:17 +01:00
Pascal Vizeli
4b7201dc59 Update Home-Assistant to 0.57.1 2017-11-05 00:13:11 +01:00
Pascal Vizeli
3a5a4e4c27 Update hass.io to 0.74 2017-11-05 00:12:49 +01:00
Pascal Vizeli
70104a9280 Set api token for access requirements (#238)
* Set api token for access requirements

* fix uuid

* make robust

* fix names
2017-11-05 00:07:49 +01:00
Pascal Vizeli
efbc7b17a1 Use init system for add-ons (#237)
* Use init system for add-ons

* Update const.py

* Update validate.py

* Update addon.py

* Update addon.py

* remove options

* remove options p2

* remove options p3

* Update addon.py
2017-11-04 21:52:41 +01:00
Pascal Vizeli
64c5e20fc4 Update Home-Assistant to 0.57 2017-11-04 11:43:04 +01:00
Pascal Vizeli
13498afa97 Update Home-Assistant to 0.57 2017-11-04 11:33:55 +01:00
Pascal Vizeli
f6375f1bd6 Pump version to 0.74 2017-10-25 12:12:13 +02:00
pvizeli
8fd1599173 Fix merge conflict version 2017-10-25 12:09:33 +02:00
Pascal Vizeli
63302b73b0 Update hass.io to 0.73 2017-10-25 12:01:27 +02:00
Pascal Vizeli
f591f67a2a Show hardware GPIO interface (#233)
* Update hardware.py

* Update host.py

* Update API.md

* Update API.md

* fix lint
2017-10-25 11:50:00 +02:00
Pascal Vizeli
cda3184a55 Add support for legacy mode (#232)
* Add support for legacy mode

* Update const.py

* add legacy mode

* Update addon.py

* Update addon.py

* Update addon.py

* Update addon.py
2017-10-24 17:23:33 +02:00
Pascal Vizeli
afc811e975 Update Home-Assistant to 0.56.2 2017-10-24 06:59:19 +02:00
Pascal Vizeli
2e169dcb42 Update Home-Assistant to 0.56.2 2017-10-24 00:08:57 +02:00
Pascal Vizeli
34e24e184f Update Home-Assistant to 0.56.1 2017-10-23 00:26:49 +02:00
Pascal Vizeli
2e4751ed7d Update version.json 2017-10-23 00:16:38 +02:00
Pascal Vizeli
8c82c467d4 Fix aiohttp 2.3.1 (#231) 2017-10-22 14:05:45 +02:00
Pascal Vizeli
f3f6771534 Add a static entry for hassio api (#230) 2017-10-22 13:53:41 +02:00
Pascal Vizeli
0a75a4dcbc Update Home-Assistant to 0.56 2017-10-22 11:16:51 +02:00
Pascal Vizeli
1a4542fc4e Update Home-Assistant to 0.56 2017-10-22 10:34:31 +02:00
Pascal Vizeli
7e0525749e Pump version to 0.73 2017-10-17 22:49:35 +02:00
Pascal Vizeli
b33b26018d fix version conflict 2017-10-17 22:47:20 +02:00
Pascal Vizeli
66c93e7176 Minimize downtime to 1 sec (#223) 2017-10-17 22:25:29 +02:00
Pascal Vizeli
5674d32bad Update hass.io version 0.72 2017-10-17 21:54:10 +02:00
Pascal Vizeli
7a84972770 Better close/loop handling (#221)
* Better close/loop handling

* Update bootstrap.py

* Update __main__.py

* Update core.py

* Update __main__.py

* Update __main__.py

* Update supervisor.py

* Update supervisor.py

* Update const.py

* fix lint
2017-10-17 16:04:37 +02:00
Pascal Vizeli
638f0f5371 Update Home-Assistant to 0.55.2 2017-10-17 00:07:42 +02:00
Pascal Vizeli
dca1b6f1d3 Update Home-Assistant to 0.55.2 2017-10-17 00:02:17 +02:00
Pascal Vizeli
2b0ee109d6 Rollback Home-Assistant 0.55.1 2017-10-16 19:06:17 +02:00
Pascal Vizeli
e7430d87d7 Update docker image validate (#220) 2017-10-16 17:15:09 +02:00
Pascal Vizeli
9751c1de79 Update Home-Assistant to 0.55.1 2017-10-16 15:50:48 +02:00
Pascal Vizeli
c497167b64 Update Home-Assistant to 0.55.1 2017-10-16 15:50:08 +02:00
Pascal Vizeli
7fb2aca88b Pump version to 0.72 2017-10-13 22:28:15 +02:00
Pascal Vizeli
0d544845b1 Update hass.io to version 0.71 2017-10-13 22:14:11 +02:00
Pascal Vizeli
602eb472f9 Allow to set a option als optional (#218)
* Update validate.py

* Update validate.py

* Update validate.py

* Update validate.py

* Update validate.py

* fix bug

* Extend schema

* Update validate.py

* fix lint

* Update validate.py

* Update validate.py

* Fix deepmerge

* Update setup.py

* Update validate.py
2017-10-13 22:02:41 +02:00
Pascal Vizeli
f22fa46bdb Pump version to 0.71 2017-10-10 07:24:35 +02:00
Pascal Vizeli
4171a28260 Update Hass.io to 0.70 2017-10-10 07:10:01 +02:00
Pascal Vizeli
55365a631a Bugfix weburl (#217) 2017-10-10 07:08:56 +02:00
Pascal Vizeli
547415b30b Pump version to 0.70 2017-10-09 15:38:49 +02:00
pvizeli
cbf79f1fab Fix version merge conflict 2017-10-09 15:25:30 +02:00
Pascal Vizeli
31cc1dce82 Update Hass.io to version 0.69 2017-10-09 15:15:30 +02:00
Pascal Vizeli
8a11e6c845 Check if a option is missing inside nested lists (#216)
* Update validate.py

* fix lint
2017-10-09 14:08:29 +02:00
Pascal Vizeli
2df4f80aa5 More log output (#214)
* Update snapshot.py

* Update __init__.py

* Update snapshot.py

* Update snapshot.py

* fix lint
2017-10-09 13:30:15 +02:00
Pascal Vizeli
68566ee9e1 Update homeassistant.py (#215) 2017-10-09 13:21:21 +02:00
Pascal Vizeli
fe04b7ec59 Remove dedicated API calls (#212)
* Update addons.py

* Update API.md

* Update addon.py

* Update addon.py

* Update addons.py
2017-10-09 10:48:17 +02:00
Pascal Vizeli
38f96d7ddd Remove unknown options from input (#213)
* Update validate.py

* Update validate.py

* Cleanup unneeded code
2017-10-09 10:09:43 +02:00
Pascal Vizeli
2b2edd6e98 Update Home-Assistant to version 0.55 2017-10-08 09:49:06 +02:00
Pascal Vizeli
361969aca2 Update Home-Assistant to version 0.55 2017-10-08 09:43:07 +02:00
Pascal Vizeli
e61e7f41f2 Pump version to 0.69 2017-10-03 17:37:48 +02:00
Pascal Vizeli
75150fd149 Update hass.io to 0.68 2017-10-03 17:12:40 +02:00
Pascal Vizeli
bd1c8be1e1 Support new API for add-on STDIN support (#207)
* Add function to write data to add-on stdin with API

* Update API Doc

* Add to api

* Update addon.py
2017-10-03 16:44:48 +02:00
Pascal Vizeli
f167197640 New config for homeassistant_api & upgrade snapshot (#206)
* New config for homeassistant_api & upgrade snapshot

* fix lint
2017-10-03 11:47:35 +02:00
Pascal Vizeli
f084ecc007 Pump version to 0.68 2017-10-03 00:59:12 +02:00
Pascal Vizeli
65becbd0ae Update hass.io to 0.67 2017-10-03 00:41:30 +02:00
Pascal Vizeli
f38e28a4d9 Add interface and home-assistant api proxy (#205)
* Add initial for hass interface

* For better compatibility, remove extra options for cleanup old stuff

* Add new functions to api

* Add api proxy to home-assistant

* use const

* fix lint

* fix lint

* Add check_api_state function

* Add api watchdog

* Fix lint

* update output

* fix url

* Fix API call

* fix API documentation

* remove password

* fix api call to hass api only

* fix problem with config missmatch

* test

* Detect wrong ssl settings

* disable watchdog & add options

* Update API
2017-10-03 00:31:14 +02:00
Pascal Vizeli
2998cd94ff Allow dynamic handling of proto part (#203)
* Allow dynamic handling of proto part

* Fix lint

* fix bug
2017-10-01 00:03:06 +02:00
Pascal Vizeli
79e2f3e8ab Pump version to 0.67 2017-09-30 12:09:22 +02:00
Pascal Vizeli
13291f52f2 Update hass.io to 0.66 2017-09-30 12:03:37 +02:00
Pascal Vizeli
4baa80c3de Map sysfs devices/platform/soc data 2017-09-30 11:04:27 +02:00
Pascal Vizeli
be28a6b012 fix spell 2017-09-29 23:31:07 +02:00
Pascal Vizeli
d94ada6216 Pump version to 0.65 2017-09-29 22:12:52 +02:00
Pascal Vizeli
b2d7743e06 Update hass.io to 0.65 2017-09-29 21:56:15 +02:00
Pascal Vizeli
40324beb72 Add support for kernel gpio interface (#202)
* Add support for kernel gpio interface

* Update addon.py

* fix git python module change

* Update git.py
2017-09-29 21:42:33 +02:00
Pascal Vizeli
c02f6913b3 Extend label schema (#200)
* Update build.py

* Update build.py

* fix lint
2017-09-29 16:29:23 +02:00
Pascal Vizeli
d56af22d5e Dockerfiles for new build system 2017-09-27 17:17:08 +02:00
Pascal Vizeli
1795103086 Pump version to 0.65 2017-09-26 09:10:56 +02:00
pvizeli
02e1689dd1 Fix version confict 2017-09-26 08:48:31 +02:00
Pascal Vizeli
ab4d96331f Update Home-Assistant to 0.54 2017-09-23 12:03:08 +02:00
Pascal Vizeli
cb881cba28 Update Home-Assistant to 0.54 2017-09-23 12:02:49 +02:00
Pascal Vizeli
44b247f397 Update hass.io to 0.64 2017-09-19 22:06:48 +02:00
Pascal Vizeli
8bb43daf91 Remove support for custom configs / configs for other hass.io versions (#197)
* Remove support for custom configs

* not need since supervisor is autoupdate
2017-09-19 21:52:18 +02:00
Pascal Vizeli
a7e65613d6 Update validate.py (#196) 2017-09-19 20:43:44 +02:00
Pascal Vizeli
3c04c71401 Update build system to origin docker (#191)
* Update build system to origin docker

* Rename build env

* fix lint p1

* fix bug & add more log info for snapshot/restore

* fix exception

* Log build info

* revert last change

* fix regex
2017-09-19 18:06:34 +02:00
Pascal Vizeli
1353d52bd1 Reset json file to default on schema error (#193) 2017-09-19 17:51:16 +02:00
Pascal Vizeli
7701457791 Update resinos to 1.1 2017-09-18 22:05:46 +02:00
Pascal Vizeli
b7820bc6a6 Update resinos to 1.1 2017-09-18 22:05:11 +02:00
Pascal Vizeli
df66102de0 Pump version to 0.64 2017-09-17 14:42:35 +02:00
Pascal Vizeli
4b308d0de1 Fix version conflict 2017-09-17 14:40:20 +02:00
Pascal Vizeli
4448ba886b Update hass.io to version 0.63 2017-09-17 14:25:02 +02:00
Pascal Vizeli
f39006be01 Change flow and start landingpage faster (#189)
* Change flow and start landingpage faster

* run homeassistant after install

* Update homeassistant.py
2017-09-16 14:45:36 +02:00
Pascal Vizeli
e5204eef8a Update Home-Assistant to 0.53.1 2017-09-14 01:28:01 +02:00
Pascal Vizeli
1f07d47fd6 Update Home-Assistant to 0.53.1 2017-09-14 01:27:36 +02:00
Pascal Vizeli
ba352abf0b Pump version to 0.63 2017-09-12 20:13:41 +02:00
Pascal Vizeli
2bf440a744 Update hass.io to version 0.62 2017-09-12 20:10:15 +02:00
Pascal Vizeli
3b26136636 More schema options (#187)
* Extend the addon schema options

* convert range to float

* convert match to string

* fix lint

* cleanup

* fix lint

* fix options name
2017-09-12 19:38:26 +02:00
Pascal Vizeli
8249f042c0 Pump version to 0.62 2017-09-11 14:42:23 +02:00
Pascal Vizeli
84bbaeee5f Fix merge conflicts with versions 2017-09-11 14:41:12 +02:00
Pascal Vizeli
b7620b7adf Update version.json 2017-09-11 14:24:48 +02:00
Pascal Vizeli
5a80be9fd4 Allow stop/start home-assistant & flow of startup (#182)
* Allow config boot

* Read boot settings

* Use internal boot time for detect reboot

* Check if Home-Assistant need to watch

* Make datetime string and parse_datetime

* Add api calls

* fix lint p1

* Use new datetime parser for sessions and make a real default boot time

* fix lint p2

* only start docker if they is running

* convert to int (timestamp)

* add boot flag
2017-09-11 14:14:26 +02:00
Pascal Vizeli
a733886803 Pump version to 0.61 2017-09-11 10:03:15 +02:00
Pascal Vizeli
834fd29fab Update HomeAssistant to 0.53 2017-09-10 16:33:37 +02:00
Pascal Vizeli
fd1caf8aa6 Update HomeAssistant to 0.53 2017-09-10 16:33:17 +02:00
Pascal Vizeli
975c9e8061 Update Home-Assistant 0.52.1 2017-08-28 23:38:43 +02:00
Pascal Vizeli
0b3c5885ec Update Home-Assistant 0.52.1 2017-08-28 23:38:17 +02:00
Pascal Vizeli
711b63e2d0 Update Home-Assistant to version 0.52 (#173) 2017-08-26 19:42:55 +02:00
Pascal Vizeli
c7b833b5eb Update Home-Assistant 0.52 2017-08-26 13:49:11 +02:00
Pascal Vizeli
fd472b3084 Update Hass.io to 0.60 2017-08-25 16:47:06 +02:00
Pascal Vizeli
dcbb6a2160 Fix socat spawn (#172)
* Update dns.py

* Update dns.py
2017-08-25 16:41:48 +02:00
Pascal Vizeli
56fa1550d2 Pump version to 0.60 2017-08-24 22:40:19 +02:00
Pascal Vizeli
e1f97860ee Update hass.io to 0.59 2017-08-24 22:27:42 +02:00
Pascal Vizeli
6ab3fe18d9 Allow to see log also if there some process (#170) 2017-08-24 22:23:24 +02:00
Pascal Vizeli
7969f3dfd7 Remove default bridge (#168)
* Remove default bridge

* rename bridge
2017-08-24 21:49:36 +02:00
Pascal Vizeli
6f05b90e4e Pump hass.io to 0.59 2017-08-24 17:17:34 +02:00
Pascal Vizeli
3aa53d99d7 Update hass.io to 0.58 2017-08-24 17:07:26 +02:00
Pascal Vizeli
3525f5a02f Cleanup network mode & fix port mapping (#166)
* Cleanup network mode & fix port mapping

* Fix lint
2017-08-24 16:39:06 +02:00
Pascal Vizeli
04514a9f5c WIP: Network docker hassio (#159)
* Create hassio network layer / allow linking

* rename docker

* fix lint

* fix lint p2

* Set network options

* First version of network code

* Finish network layer

* Remove old api_endpoint stuff

* Add DNS forwarding

* Fix DNS recorder

* Fix lint p1

* Fix lint p2

* Fix lint p3

* Fix spell

* Fix ipam struct

* Fix ip to str

* Fix ip to str v2

* Fix spell

* Fix hass on host

* Fix host attach to network

* Cleanup network code

* Fix lint & add debug

* fix link

* Remove log

* Fix network

* fix reattach of supervisor

* set options

* Fix containers

* Fix remapping & add a test

* Fix dict bug

* Fix prop

* Test with run container

* Fix problem
2017-08-24 14:57:13 +02:00
Pascal Vizeli
1c915ef4cd Pump hass.io version to 0.58 2017-08-22 16:29:10 +02:00
pvizeli
b03a2c5c5f Merge remote-tracking branch 'origin/dev' 2017-08-22 16:16:01 +02:00
Pascal Vizeli
64988b285e Update hass.io to version 0.57 2017-08-22 16:15:17 +02:00
Pascal Vizeli
5c69dca7b3 New panel with poly2 (#163) 2017-08-22 15:44:14 +02:00
Pascal Vizeli
dfda7dc748 Better cleanup for local build add-ons (#161)
* Better cleanup for local build add-ons

* fix lint
2017-08-20 23:02:58 +02:00
Pascal Vizeli
cb7710c23f Add a error message if that is not a local build addon (#162) 2017-08-20 22:33:27 +02:00
Pascal Vizeli
f9b12a2eb2 Allow rebuild for local build addons (#158)
* Allow rebuild for local build addons

* fix lint
2017-08-19 22:44:39 +02:00
Pascal Vizeli
6a7617faad Use deepmerge for options (#157)
Add an optional extended description…
2017-08-18 15:57:13 +02:00
Pascal Vizeli
05554ccf7e Pump version to 0.57 2017-08-16 11:38:43 +02:00
pvizeli
a94e6c5303 Merge remote-tracking branch 'origin/dev' 2017-08-16 11:38:07 +02:00
Pascal Vizeli
d6fc8892db Update hass.io to 0.56 2017-08-16 11:36:50 +02:00
Pascal Vizeli
fa9b3b939e Use exit code to detect wrong configs (#156)
* Update homeassistant.py

* Update homeassistant.py

* Update util.py

* add support for yaml errors
2017-08-16 11:25:38 +02:00
Pascal Vizeli
70685c41be Update const.py 2017-08-16 02:18:33 +02:00
Pascal Vizeli
a3209c4bde Merge remote-tracking branch 'origin/dev' 2017-08-16 02:17:57 +02:00
Pascal Vizeli
f3e60f6c28 Update hass.io to 0.55 2017-08-16 02:13:54 +02:00
Pascal Vizeli
7798e7cde2 Code cleanup & add config check to API (#155)
* Code cleanup & add config check to API

* Fix comments

* fix lint p1

* Fix lint p2

* fix coro

* fix parameter

* add log output

* fix command layout

* fix Pannel

* fix lint p4

* fix regex

* convert to ascii

* fix lint p5

* add temp logging

* fix output on non-zero exit

* remove temporary log
2017-08-16 02:10:38 +02:00
Pascal Vizeli
4af92b9d25 Don't return false for addon startup on update (#153) 2017-08-15 21:30:05 +02:00
Pascal Vizeli
eab958860c Pump hassio to 0.55 2017-08-15 09:15:21 +02:00
pvizeli
09bba96940 Merge remote-tracking branch 'origin/dev' 2017-08-15 09:07:47 +02:00
Pascal Vizeli
a34806d4e2 Update hass.io to 0.54 2017-08-15 08:56:40 +02:00
Pascal Vizeli
f00b21dc28 Bugfix git clone (#152)
Add an optional extended description…
2017-08-15 08:55:55 +02:00
Pascal Vizeli
021946e181 Pump version to 0.54 2017-08-15 00:35:58 +02:00
Pascal Vizeli
6cab017042 Fix version conflict 2017-08-15 00:27:47 +02:00
Pascal Vizeli
5999b48be4 Update Hass.io 0.53 2017-08-15 00:05:55 +02:00
Pascal Vizeli
57f3178408 Change update flow to a higher level (#150) 2017-08-14 23:56:52 +02:00
Franck Nijhof
14013ac923 Recursively git clone addon repositories, allowing submodules (#148) 2017-08-14 16:15:08 +02:00
Pascal Vizeli
d08343d040 Update HomeAssistant 0.51.2 2017-08-14 13:15:45 +02:00
Pascal Vizeli
2f9f9c6165 Update HomeAssistant 0.51.2 2017-08-14 13:15:15 +02:00
Pascal Vizeli
8ab0ed5047 Update HomeAssistant 0.51.1 2017-08-13 14:59:50 +02:00
Pascal Vizeli
0119b52e11 Update HomeAssistant 0.51.1 2017-08-13 14:59:33 +02:00
Pascal Vizeli
1382a7b36e Update to HomeAssistant 0.51 2017-08-13 09:24:05 +02:00
Pascal Vizeli
2eeb8bf388 Update to HomeAssistant 0.51 2017-08-13 09:08:41 +02:00
Pascal Vizeli
5af3040223 Pump version to 0.53 2017-08-10 11:25:07 +02:00
pvizeli
47491ca55b Fix merge conflict with versions 2017-08-10 11:24:21 +02:00
Pascal Vizeli
b06ce9b6b4 Update Hass.io 0.52 2017-08-10 11:15:25 +02:00
Pascal Vizeli
38284e036d Move system into startup protection (#145)
Add an optional extended description…
2017-08-10 11:08:43 +02:00
Pascal Vizeli
27a079742d Fix hostname / add device if it use audio (#144)
Add an optional extended description…
2017-08-10 11:06:55 +02:00
Pascal Vizeli
7f33b3b5aa Pump version to 0.52 2017-08-08 21:14:37 +02:00
Pascal Vizeli
261bda82db Fix version merge conflict 2017-08-08 21:12:32 +02:00
Pascal Vizeli
c39d6357f3 fix parameter 2017-08-08 18:31:37 +02:00
Pascal Vizeli
d1b30a0e95 fix last version of HomeAssistant (#140) 2017-08-08 18:17:23 +02:00
Pascal Vizeli
6a74893a30 Bugfix docker have no version (#139) 2017-08-08 18:01:53 +02:00
Pascal Vizeli
b61d5625fe update hass.io to 0.51 2017-08-08 16:59:43 +02:00
Pascal Vizeli
8d468328f3 Expose new function to add-ons (#138)
* Expose new function to add-ons

* Rename `hassio` to `hassio_api`

* fix lint

* done
2017-08-08 16:54:42 +02:00
Pascal Vizeli
cd3b382902 Cleanup json / api code with new options (#137)
* Cleanup json / api code with new options

* fix lint
2017-08-08 10:47:39 +02:00
Pascal Vizeli
99cf44aacd Cleanup config / new updater object / New audio (#135)
* Cleanup config / new updater object / New audio

* Cleanup beta_channel

* fix lint

* fix lint p3

* Fix lint p4

* Allow set audio options

* Fix errors

* add host options
2017-08-08 00:53:54 +02:00
William Johansson
eaa489abec Allow privileged capability SYS_RAWIO (#136)
In order to allow writes to /dev/mem, which is needed e.g. to use the
GPIO ports on Raspberry Pi, the SYS_RAWIO capability needs to be
granted.

Fixes #134.
2017-08-07 21:58:57 +02:00
Pascal Vizeli
46f323791d Update to new beta version of image 2017-08-06 22:48:46 +02:00
Fabian Affolter
ec72d38220 Sync names 2017-08-04 17:00:31 +02:00
Pascal Vizeli
f5b166a7f0 Use addon slug as hostname instead docker name (#132) 2017-08-04 16:32:17 +02:00
Pascal Vizeli
8afde1e881 Return a error on update with own version (#124)
Return a error on update with own version
2017-08-02 16:59:38 +02:00
Pascal Vizeli
f751b0e6fc Update homeassistant to 0.50.2 2017-08-01 11:35:07 +02:00
Pascal Vizeli
3809f20c6a Update homeassistant to 0.50.2 2017-08-01 11:34:29 +02:00
Pascal Vizeli
68390469df Pump hass.io version to 0.51 2017-07-31 11:51:34 +02:00
pvizeli
4c122a0630 Fix version merge 2017-07-31 11:49:16 +02:00
Pascal Vizeli
d06696cd94 Update Hass.io to version 0.50 2017-07-31 11:44:02 +02:00
Pascal Vizeli
8d094d5c70 Fix wrong addon config break supervisor (#123) 2017-07-31 11:41:08 +02:00
Pascal Vizeli
068c463c98 Update Home-Assistant to version 0.50 2017-07-30 02:41:07 +02:00
Pascal Vizeli
fc95933098 Update Home-Assistant to version 0.50 2017-07-30 02:35:27 +02:00
Pascal Vizeli
630137a576 Fix wrong list (#119) 2017-07-30 00:06:43 +02:00
Pascal Vizeli
857f346b35 Pump version to 0.50 2017-07-29 00:11:06 +02:00
Pascal Vizeli
d98b4f039f Merge pull request #118 from home-assistant/dev
Release 0.49
2017-07-29 00:03:00 +02:00
Pascal Vizeli
8fee52da5e Update Hass.io to 0.49 2017-07-28 23:46:13 +02:00
Pascal Vizeli
0f9ad3658b Update panel (#117) 2017-07-28 23:45:36 +02:00
Pascal Vizeli
1155ee07e5 Hardware interface for UI (#116)
* Init hardware object

* Update API

* Update hardware list

* fix api description

* fix lint

* add hardware to API

* fix lint

* fix wrong

* fix view
2017-07-28 23:05:40 +02:00
Pascal Vizeli
fa687e982e Set hostname on homeassistant / addons (#115) 2017-07-27 22:17:48 +02:00
Fabian Affolter
4e902af937 Update name and remove/add blank lines 2017-07-26 22:34:20 +02:00
Pascal Vizeli
6455ad14a7 Pump version 0.49 2017-07-26 21:44:00 +02:00
Pascal Vizeli
4753c058a3 Merge pull request #114 from home-assistant/dev
Release 0.48
2017-07-26 21:02:44 +02:00
Pascal Vizeli
1567cbfe37 Update version.json 2017-07-26 20:56:49 +02:00
Pascal Vizeli
3ed66c802e Bugfix frontent repositories list (#113) 2017-07-26 18:49:39 +02:00
Pascal Vizeli
980baf23a8 Pump version to 0.48 2017-07-25 00:20:10 +02:00
Pascal Vizeli
d69af6a62b Fix merge version.json 2017-07-25 00:18:34 +02:00
Pascal Vizeli
863456525f fix json validate (#112) 2017-07-25 00:01:02 +02:00
Pascal Vizeli
dae49df7b1 Update Hass.io to 0.47 2017-07-24 23:42:28 +02:00
Pascal Vizeli
282fc03687 Look schema for update (#111)
* Check valid schema for update

* fix merge options

* fix style & return value

* simplify
2017-07-24 23:35:22 +02:00
Pascal Vizeli
f9f7e07c52 Update HomeAssistant 0.49.1 2017-07-24 22:43:08 +02:00
Pascal Vizeli
12a2ccf0ec Update HomeAssistant 0.49.1 2017-07-24 22:42:48 +02:00
Pascal Vizeli
a98d76618a Update tasks.py (#110) 2017-07-24 12:13:16 +02:00
Pascal Vizeli
7a59e7392b update name 2017-07-24 12:05:23 +02:00
Pascal Vizeli
446aff3fa6 Merge pull request #109 from pvizeli/allow_mount
Allow SYS_ADMIN, show devices and privileged on API
2017-07-24 11:48:35 +02:00
Pascal Vizeli
3272403141 Update frontend 2017-07-24 10:58:32 +02:00
pvizeli
d1f265da9e Update UI 2017-07-24 10:44:23 +02:00
Pascal Vizeli
4915c935dd use set for speedup 2017-07-24 10:36:47 +02:00
Pascal Vizeli
e78d935824 fix spell 2017-07-24 10:33:04 +02:00
pvizeli
934ca64a32 Allow SYS_ADMIN, show devices and privileged on API 2017-07-24 10:30:51 +02:00
Pascal Vizeli
0860e6d202 Update resinhup to v0.3 2017-07-24 00:47:39 +02:00
Pascal Vizeli
c3e1c8b58e Update resinhup to v0.3 2017-07-24 00:46:21 +02:00
Paulus Schoutsen
44e48095c7 Update license to be Apache 2.0 2017-07-23 12:11:44 -07:00
Paulus Schoutsen
a13eb7841d Remove not ready for production line 2017-07-23 11:28:43 -07:00
Pascal Vizeli
b5701c5878 Pump dev version to 0.47 2017-07-23 00:07:41 +02:00
Pascal Vizeli
803eb0f8c9 Merge pull request #108 from home-assistant/dev
Release 0.46
2017-07-22 23:47:51 +02:00
Pascal Vizeli
58c5ed7ba1 Update supervisor.py 2017-07-22 22:49:58 +02:00
Pascal Vizeli
c4d7d671d1 Update frontend 0.46 (#107) 2017-07-22 22:38:07 +02:00
Pascal Vizeli
9d88255225 API cleanup (#106)
* API cleanup

* fix lint

* fix wrong return

* fix snapshots/reload

* cleanup

* fix lint

* fix lint
2017-07-22 22:34:25 +02:00
Pascal Vizeli
bfbc366f55 Update hassio 0.46 2017-07-21 01:36:10 +02:00
Pascal Vizeli
0f30a23f3e Add support for webui (#105)
* Add support for webui

* support lists

* fix regex
2017-07-21 01:34:46 +02:00
Pascal Vizeli
7e1bb42bb7 add logo support (#104)
* fix lint

* fix lint p2

* fix api output

* fix decorator

* fix decorator p2

* fix UnboundLocalError

* revert

* fix trace bug

* fix conent type

* allow logo
2017-07-21 00:23:31 +02:00
Pascal Vizeli
251a43216e fix lint 2017-07-20 22:28:55 +02:00
Pascal Vizeli
4801b9903c fix coro 2017-07-20 22:05:58 +02:00
Pascal Vizeli
cd5a09938f Add support for logo 2017-07-20 22:04:44 +02:00
Pascal Vizeli
14bf834224 Update resinos to 1.0 2017-07-19 20:51:43 +02:00
Pascal Vizeli
8aec943a5c Update version.json 2017-07-19 20:51:18 +02:00
Pascal Vizeli
d817e75d98 Update resinos to version 0.10 2017-07-19 16:56:10 +02:00
Pascal Vizeli
fbd8abdcd5 Update version.json 2017-07-19 16:55:32 +02:00
Pascal Vizeli
ca02977505 Update OTA resinhup utility 2017-07-19 14:15:19 +02:00
Pascal Vizeli
6533b57c6d Update OTA resinhup utility 2017-07-19 14:14:48 +02:00
Pascal Vizeli
0a818282d3 Update const.py 2017-07-17 09:48:05 +02:00
Pascal Vizeli
ce2f5f9f7a Resolve merge conflict by version.json 2017-07-17 09:46:21 +02:00
Pascal Vizeli
01f767e66c New UI with ICON fix (#103)
Add an optional extended description…
2017-07-17 07:45:20 +02:00
Pascal Vizeli
106ab924e3 Update ui 45 (#102)
* Update UI

* Update panel
2017-07-17 00:53:57 +02:00
Pascal Vizeli
d031594bf9 Update HassIO 0.45 2017-07-17 00:52:36 +02:00
Pascal Vizeli
f2f146063b Pump version 2017-07-17 00:06:04 +02:00
Pascal Vizeli
5abe7a3fb9 Update HomeAssistant to 0.49 2017-07-16 12:34:29 +02:00
Pascal Vizeli
f592971b6e Update HomeAssistant to 0.49 2017-07-16 12:34:03 +02:00
Pascal Vizeli
ed2caa0d81 Merge pull request #100 from home-assistant/dev
Release 0.44
2017-07-15 01:32:20 +02:00
Pascal Vizeli
0b04c90b1f fix validate bug 2017-07-15 01:00:06 +02:00
Pascal Vizeli
2eac4b8d9b Update version.json 2017-07-14 23:51:48 +02:00
Pascal Vizeli
143a358b0c Change startup system / Allow nested dict (#99)
* Change startup system / Allow nested dict

* fix schema

* fix lint
2017-07-14 23:51:24 +02:00
Pascal Vizeli
fa049066fc Update version.json 2017-07-12 23:12:34 +02:00
Pascal Vizeli
3877dcf355 Pump version to 0.44 2017-07-12 17:25:12 +02:00
Pascal Vizeli
bfa7443ae2 Merge pull request #97 from home-assistant/dev
Release 0.43
2017-07-12 02:31:19 +02:00
Pascal Vizeli
253962df87 Update version.json 2017-07-12 02:25:18 +02:00
Pascal Vizeli
f8fbee68f4 Merge pull request #96 from pvizeli/cleanup_api_snapshot_p2
Update API / fix isoformat
2017-07-12 02:24:20 +02:00
Pascal Vizeli
3c5d4037f7 fix lint 2017-07-12 02:19:01 +02:00
Pascal Vizeli
772709dd75 Update API / fix isoformat 2017-07-12 01:38:15 +02:00
Pascal Vizeli
bcfd76d33c Merge pull request #94 from pvizeli/extend_hass
Add landingpage / cleanup homeassistant core handling
2017-07-12 00:12:12 +02:00
Pascal Vizeli
2bbe7e7dc1 cleanup after install 2017-07-12 00:09:03 +02:00
Pascal Vizeli
dbcd090244 fix flow 2017-07-11 23:45:29 +02:00
Pascal Vizeli
a0a1fd4875 fix coro 2017-07-11 23:29:38 +02:00
Pascal Vizeli
d978ec00aa fix progress v2 2017-07-11 23:08:47 +02:00
Pascal Vizeli
e40963a686 fix calling 2017-07-11 23:02:20 +02:00
Pascal Vizeli
55ec1a84fa expose running state of docker 2017-07-11 22:58:05 +02:00
Pascal Vizeli
cf154b57f3 fix lint p4 2017-07-11 22:45:09 +02:00
Pascal Vizeli
ebf4daf4cc fix lint 2017-07-11 22:38:07 +02:00
Pascal Vizeli
40e8f411ff fix lint p2 2017-07-11 22:19:22 +02:00
Pascal Vizeli
421b380043 fix lint 2017-07-11 22:11:25 +02:00
pvizeli
5ebf2068b2 Update interface, allow update every time 2017-07-11 16:57:03 +02:00
pvizeli
e5fc6846e0 fix snapshot with custom image 2017-07-11 16:52:16 +02:00
pvizeli
906c4e03fb Finish new homeassistant handling 2017-07-11 16:19:24 +02:00
pvizeli
02c8baef68 Add landingpage / cleanup homeassistant core handling 2017-07-11 12:26:58 +02:00
Pascal Vizeli
a14917e017 Pump version 0.43 2017-07-07 14:21:41 +02:00
Pascal Vizeli
7e5b2673dc Merge pull request #93 from home-assistant/dev
* Pump version to 0.42

* Update util.py (#92)

Add an optional extended description…

* Update version.json
2017-07-07 14:21:01 +02:00
Pascal Vizeli
d31895123e Update version.json 2017-07-07 14:14:55 +02:00
Pascal Vizeli
6c1456902e Update util.py (#92)
Add an optional extended description…
2017-07-07 14:12:26 +02:00
Pascal Vizeli
03bed162f4 Pump version to 0.42 2017-07-07 00:30:04 +02:00
Pascal Vizeli
f798e75e30 update hassio to 0.41 2017-07-07 00:22:30 +02:00
Pascal Vizeli
710f8570d2 Update tasks.py 2017-07-07 00:20:38 +02:00
Pascal Vizeli
4dfd11ffb4 Update const.py 2017-07-07 00:00:45 +02:00
Pascal Vizeli
4e4368debb Update setup.py 2017-07-06 23:49:42 +02:00
Pascal Vizeli
30c7ddf4ef Update version.json 2017-07-06 23:48:03 +02:00
Pascal Vizeli
7186f5a8c0 Add more addons functions. (#91)
* Add more addons functions.

* fix lint

* fix lint p2

* Allow more customable network settings

* fix lint

* change point of validate

* fix lint

* fix handling

* fix lint & validate data before write
2017-07-06 23:40:49 +02:00
Pascal Vizeli
f52d1c4509 Pump version 2017-07-06 01:52:30 +02:00
Pascal Vizeli
4dbece8e8e Merge remote-tracking branch 'origin/dev' 2017-07-06 01:42:07 +02:00
Pascal Vizeli
f731c630a6 Update version.json 2017-07-06 01:34:37 +02:00
Pascal Vizeli
0ac96c207e Convert homeassistant into a dict (snapshot) (#90)
* Convert homeassistant into a dict

* fix lint

* fix bugs

* cleanup code

* fix cleanup
2017-07-06 01:29:09 +02:00
Pascal Vizeli
e2a29b7290 Add snapshot feature (#88)
* Add API layout for snapshot

* Update api

* Add support for export/import docker images

* Move restore into addon

* Add restore to addon

* Fix lint

* fix lint

* cleanup

* init object

* fix executor

* cleanup

* Change flow of init

* Revert "Change flow of init"

This reverts commit 6b3215e44c.

* allow restore from none

* forward working

* add size

* add context for snapshot

* add init function to set meta data

* update local addon on load

* add more validate and optimaze code

* Optimaze code for restore data

* add validate layer

* Add more function to snapshot / cleanup others

* finish snapshot function

* Cleanup config / optimaze code

* Finish snapshot on core

* Some improvments first object for api

* finish

* fix lint p1

* fix lint p2

* fix lint p3

* fix async with

* fix lint p4

* fix lint p5

* fix p6

* make staticmethod

* fix schema

* fix parse system data

* fix bugs

* fix get function

* extend snapshot/restore

* add type

* fix lint

* move to gz / xz is to slow

* move to gz / xz is to slow p2

* Fix config folder

* small compresslevel for more speed

* fix lint

* fix load

* fix tar stream

* fix tar stream p2

* fix parse

* fix partial

* fix start hass

* fix rep

* fix set

* fix real

* fix generator

* Cleanup old image

* add log

* fix lint

* fix lint p2

* fix load from tar
2017-07-05 18:16:14 +02:00
Pascal Vizeli
f107a73e28 Update HomeAssistant to 0.48.1 2017-07-05 11:16:19 +02:00
Pascal Vizeli
2c68e5801f Update HomeAssistant to 0.48.1 2017-07-05 11:15:57 +02:00
Pascal Vizeli
91502a0727 Update HomeAssistant 0.48 2017-07-03 07:03:35 +02:00
Pascal Vizeli
872f1d0ae3 update homeassistant 0.48 2017-07-03 07:03:03 +02:00
Pascal Vizeli
3c4240a8a8 Update __init__.py 2017-06-29 21:10:42 +02:00
Pascal Vizeli
7a470bb3ac Pump version 0.39 2017-06-29 12:03:00 +02:00
pvizeli
766a9af54e Update version after merge 2017-06-29 12:00:39 +02:00
Pascal Vizeli
ca303a62f2 UI update for 0.38 (#87)
* Update UI

* Update frontend
2017-06-29 10:24:21 +02:00
Pascal Vizeli
90030d3a28 Add websession for reload (#86) 2017-06-29 07:57:04 +02:00
Pascal Vizeli
0ed48a7741 fix self update style on startup (#85)
* fix self update style on startup

* Check beta/dev upstream on update function
2017-06-29 07:50:42 +02:00
Pascal Vizeli
a33d765776 Update Hass.IO dev 2017-06-29 07:23:32 +02:00
Pascal Vizeli
6bb4f0e369 Update API.md 2017-06-29 00:03:23 +02:00
Pascal Vizeli
56a9f64730 Fix write options handling (#84)
* Fix write options handling

* Fix bug
2017-06-28 23:06:06 +02:00
Pascal Vizeli
d5eb66bc0d Use tmp folder / fix log bug / add executor (#83)
* Use tmp folder / fix log bug / add executor

* Update __main__.py

* Update .travis.yml

* Add autoupdate on startup.

* Fix bug

* Move selfupdate code part into start
2017-06-28 16:22:44 +02:00
Pascal Vizeli
40343089b5 Fix error handing (#82)
Add an optional extended description…
2017-06-26 09:17:09 +02:00
Pascal Vizeli
1b887e38d6 Add new data Layer for addons (#81)
* Add new data Layer for addons

* draft v2

* part 3

* Cleanups for new addon layout

* cleanup part 5

* fix lint p1

* fix lint p2

* fix api bug

* Fix lint p3

* fix lint p4

* fix lint p5

* fix lint p6

* fix update

* fix lint

* Update repo add code part 1

* new repository load code

* reorder code

* Code cleanup p1

* Don't allow change options for not installed addons

* Cleanup error handling

* Fix addon restart config bug

* minimize timeout for bad addons

* set core timeout for docker to 15

* fix lint

* fix start bug

* Add startuptype

* change names / fix update bug

* fix update bug p2

* Cleanup arch

* Ignore built-in repositories

* fix lint

* fix bug

* fix bug p4

* fix arch handling / better bugfix for boot option

* fix lint

* fix arch

* fix options

* fix close is no coro

* update api description & fix lint

* Fix error

* fix api validate config

* cleanup api

* Fix repo loader

* cleanup slugs

* fix lint
2017-06-23 00:51:28 +02:00
Pascal Vizeli
ba96f99cde Update HomeAssistant 0.47.1 2017-06-21 22:45:36 +02:00
Pascal Vizeli
b7f5cc868b HomeAssistant 0.47.1 2017-06-21 22:18:46 +02:00
Pascal Vizeli
c8343fdfb0 Update HomeAssistant 0.47.1 2017-06-21 22:16:44 +02:00
Pascal Vizeli
91e4bf1676 Update HomeAssistant 2017-06-18 00:46:54 +02:00
Pascal Vizeli
6dba8d4ef9 Update HomeAssistant 2017-06-18 00:40:13 +02:00
Pascal Vizeli
65eaed4f90 Pump version 2017-06-17 23:58:07 +02:00
Pascal Vizeli
8233083392 Merge remote-tracking branch 'origin/dev' 2017-06-17 23:55:24 +02:00
Pascal Vizeli
106378d1d0 Update version.json 2017-06-17 23:47:02 +02:00
Pascal Vizeli
01d18d5ff3 Allow custom options without validate (#80) 2017-06-17 22:47:56 +02:00
Pascal Vizeli
6d23f3bd1c Use our new base image 2017-06-14 16:55:03 +02:00
Pascal Vizeli
ef96579a29 Update HomeAssistant 0.46.1 2017-06-10 00:55:17 +02:00
Pascal Vizeli
44f0a9f21a Update HomeAssistant 0.46.1 2017-06-10 00:54:49 +02:00
Pascal Vizeli
d854307acb Remove container before delete images (#78) 2017-06-08 17:11:14 +02:00
Pascal Vizeli
334b41de71 Pump version to 0.37 2017-06-05 13:02:13 +02:00
Pascal Vizeli
1da50eab7a Fix versions 2017-06-05 12:59:44 +02:00
Pascal Vizeli
b119a42f4d Update Hass.IO 0.36 2017-06-05 12:56:14 +02:00
Pascal Vizeli
99aa438817 Allow extend cap for addons (#77)
* Allow extend cap for addons

* cleanup
2017-06-05 12:46:45 +02:00
Pascal Vizeli
99fa91f480 Add better validator for device 2017-06-05 12:45:43 +02:00
Pascal Vizeli
93969d264d Update HomeAssistant 0.46 2017-06-04 09:32:55 +02:00
Pascal Vizeli
711e199977 Update HomeAssistant 0.46 2017-06-04 09:11:46 +02:00
Pascal Vizeli
4e645332c3 Pump version to 0.36 2017-06-03 00:15:46 +02:00
Pascal Vizeli
df8afb3337 Merge pull request #76 from home-assistant/dev
Release 0.35
2017-06-03 00:01:16 +02:00
Pascal Vizeli
255a33fc08 Update Hass.IO to 0.35 2017-06-02 23:52:48 +02:00
Pascal Vizeli
d15b6f0294 Allow map special device to homeassistant docker (#75)
* Allow map special device to homeassistant docker

* fix lint

* fix '/dev/'
2017-06-02 23:39:54 +02:00
Pascal Vizeli
1aa24e40ae Update README.md 2017-06-02 10:59:55 +02:00
Pascal Vizeli
c0bde4a488 Next version 2017-06-01 00:39:39 +02:00
Pascal Vizeli
2a09b70294 Merge pull request #74 from home-assistant/dev
Release 0.34
2017-06-01 00:01:48 +02:00
Pascal Vizeli
e35b0a54c1 Pump version to 0.34 2017-05-31 23:53:22 +02:00
Pascal Vizeli
8287330c67 cleanup 2017-05-31 23:44:05 +02:00
Pascal Vizeli
6b16da93cd WIP: Refactory / Cleanup docker base (#73)
* Refactory / Cleanup docker base

* Check ID of running image

* Small bugs / lint

* Add log info

* Fix lint

* Add a real cleanup solution

* fix unused import

* Cleanup restart after updates

* Use restart callback

* rename callback

* Add info log for cleanup & fix lint

* Fix lint

* fix wrong id

* fix set addon as install
2017-05-31 23:41:04 +02:00
bestlibre
c1cd9bba45 Adding tmpfs to addon config (#72)
* Adding tmpfs to addon config

* Adding vol.Match and correcting syntax error

* Missing import and linting

* Update addon.py

* Revert "Update addon.py"

This reverts commit 82798c8f2d.

* optimaze code
2017-05-31 09:39:22 +02:00
Pascal Vizeli
e33420f26e Pump version to 0.34 2017-05-24 00:09:47 +02:00
Pascal Vizeli
abd9683e11 Fix merge conflicts 2017-05-24 00:07:49 +02:00
Pascal Vizeli
8cbeabbe21 Pump Hass.IO version 2017-05-23 23:58:20 +02:00
Pascal Vizeli
df7d988d2f Try to fetch timezone on startup (#70) 2017-05-23 23:17:20 +02:00
Pascal Vizeli
544c009b9c Fix rewrite config to addon on restart (#71) 2017-05-23 22:52:28 +02:00
Pascal Vizeli
b2e0babc60 Update HomeAssistant to 0.45.1 2017-05-23 00:04:55 +02:00
Pascal Vizeli
f7c79cbd3a Update HomeAssistant to 0.45.1 2017-05-22 23:55:47 +02:00
Pascal Vizeli
587e9618da Pump version 2017-05-22 23:22:06 +02:00
Pascal Vizeli
cb2dd3b81c Fix 2017-05-22 23:17:02 +02:00
Pascal Vizeli
8d4dd7de3f Update version.json 2017-05-22 23:07:23 +02:00
Pascal Vizeli
6927c989d0 Timezone (#69)
* Add Timezone support

* finish PR

* fix lint
2017-05-22 22:56:44 +02:00
Pascal Vizeli
97853d1691 Add support for hostname change. (#68)
* Add support for hostname change.

* Fix lint

* Fix lint p2

* Update network.py
2017-05-22 21:59:19 +02:00
Pascal Vizeli
0cdef0d118 Allow add-on to run on host network (#67)
* Allow add-on to run on host network

* cleanup name

* fix lint
2017-05-22 21:52:37 +02:00
Justin Weberg
0b17ffc243 Update readme (#66)
Update installation section for appearance and ease of understanding.
2017-05-21 17:13:36 -07:00
Pascal Vizeli
c516d46f16 Update HomeAssistant 0.45 2017-05-21 08:18:48 +02:00
Pascal Vizeli
cb8ec22b6d Update HomeAssistant 0.45 2017-05-21 08:13:51 +02:00
Pascal Vizeli
4a5fbd79c1 Update ResinOS v0.8 2017-05-20 16:38:09 +02:00
Pascal Vizeli
b636a03567 Update ResinOS v0.8 2017-05-20 16:37:32 +02:00
Pascal Vizeli
c96faf7c0a Pump version 0.32 2017-05-20 01:13:28 +02:00
Pascal Vizeli
2e1cd4076a Merge pull request #64 from home-assistant/dev
Release 0.31
2017-05-20 00:21:40 +02:00
Pascal Vizeli
9984a638ba fix lint 2017-05-20 00:19:48 +02:00
Pascal Vizeli
a492bccc03 Update Hass.IO 0.31 2017-05-20 00:16:50 +02:00
Pascal Vizeli
e7a0e0f565 update pannel 2017-05-20 00:08:11 +02:00
Pascal Vizeli
030e081d45 Update frontend (#63) 2017-05-19 23:59:25 +02:00
Pascal Vizeli
8537536368 Delete hassio-main.html.gz 2017-05-19 23:47:55 +02:00
Pascal Vizeli
f03f323aac Add files via upload 2017-05-19 23:47:34 +02:00
Pascal Vizeli
58c0c67796 Update __init__.py 2017-05-19 23:26:41 +02:00
Pascal Vizeli
f5e196a663 wrap panel into function 2017-05-19 23:24:02 +02:00
Pascal Vizeli
808df68e57 fix panel v2 2017-05-19 23:18:09 +02:00
Pascal Vizeli
fa51c2e6e9 use pathlib 2017-05-19 22:51:46 +02:00
Pascal Vizeli
ba3760e770 Revert API change 2017-05-19 22:48:17 +02:00
Pascal Vizeli
ad1a8557b8 Fix panel & new startup type (#62)
* Fix pannel

* Add new startup  type
2017-05-19 22:31:34 +02:00
Pascal Vizeli
fe91f812d9 Add hostname support for hc protocol 2017-05-19 09:56:30 +02:00
Pascal Vizeli
4cc11305c7 Pump version to 0.31 2017-05-19 09:47:25 +02:00
Pascal Vizeli
898c0330c8 Merge pull request #61 from home-assistant/dev
Release 0.30
2017-05-18 18:14:44 +02:00
Pascal Vizeli
33e5f94f1f cleanup 2017-05-18 18:10:34 +02:00
Pascal Vizeli
da4ee63890 Update version.json 2017-05-18 18:08:29 +02:00
Pascal Vizeli
d34203b133 Remove mnt mount (#60)
* Remove mnt mount

* fix lint
2017-05-18 17:45:44 +02:00
Pascal Vizeli
23addfb9a6 Pump version 2017-05-18 17:40:02 +02:00
Pascal Vizeli
81e1227a7b Merge pull request #59 from home-assistant/dev
Release 0.29
2017-05-17 23:43:09 +02:00
Pascal Vizeli
75be8666a6 Update version.json 2017-05-17 23:41:50 +02:00
Pascal Vizeli
6031a60084 Add addon share and allow to mount host mnt (#58)
* Add addon share and allow to mount host mnt

* fix comments logs
2017-05-17 17:21:54 +02:00
Pascal Vizeli
39d5785118 Allow config.json to manipulate docker env. (#57)
Allow config.json to manipulate docker env.
2017-05-17 14:45:02 +02:00
Pascal Vizeli
bddcdcadb2 Pump version 2017-05-17 14:25:57 +02:00
Pascal Vizeli
3eac6a3366 Merge pull request #56 from home-assistant/dev
Release 0.28
2017-05-16 22:31:47 +02:00
Pascal Vizeli
3c7b962cf9 update hass.io 2017-05-16 22:17:19 +02:00
Pascal Vizeli
bd756e2a9c fix dev regex 2017-05-16 22:11:42 +02:00
Pascal Vizeli
e7920bee2a Fix group regex 2017-05-16 22:03:51 +02:00
Pascal Vizeli
ebcc21370e Add policy for mappings (#55)
* Add policy for mappings

* fix travis
2017-05-16 17:15:35 +02:00
Pascal Vizeli
34c4acf199 Add device support (#54)
Add device support
2017-05-16 14:50:47 +02:00
Pascal Vizeli
47e45dfc9f Pump version 2017-05-16 11:45:20 +02:00
Pascal Vizeli
2ecea7c1b4 Merge pull request #53 from home-assistant/dev
Release 0.27
2017-05-16 00:20:29 +02:00
Pascal Vizeli
5c0eccd12f Bugfix attach container/image (#52) 2017-05-16 00:07:43 +02:00
Pascal Vizeli
f34ab9402b Fix remove (#51) 2017-05-15 23:39:34 +02:00
Pascal Vizeli
2569a82caf Update Hass.IO version 2017-05-15 23:27:18 +02:00
Pascal Vizeli
4bdd256000 Use label instead env, cleanup build (#50)
* Use label instead env, cleanup build

* Update const.py

* fix lint

* add space

* fix lint

* use dynamic type

* fix lint

* fix path

* fix label read

* fix bug
2017-05-15 23:19:35 +02:00
Pascal Vizeli
6f4f6338c5 Pump version 2017-05-15 16:35:30 +02:00
Pascal Vizeli
7cb72b55a8 Merge pull request #49 from home-assistant/dev
Release 0.26
2017-05-15 00:26:30 +02:00
Pascal Vizeli
1a9a08cbfb Update version.json 2017-05-15 00:17:59 +02:00
Pascal Vizeli
237ee0363d Update error message (#48) 2017-05-15 00:08:15 +02:00
Pascal Vizeli
86180ddc34 Allow every repository to make a local build (#47)
* Allow every repository to make a local build

* store version of build

* cleanup code

* fix lint
2017-05-14 23:32:54 +02:00
Pascal Vizeli
eed41d30ec Update const.py 2017-05-13 23:17:23 +02:00
Pascal Vizeli
0b0fd6b910 Add files via upload 2017-05-13 19:14:54 +02:00
Pascal Vizeli
1f887b47ab register panel on core 2017-05-13 17:44:16 +02:00
Pascal Vizeli
affd8057ca WIP Add panel to hass.io (#46)
* Add poliymare

* Add commit

* add static route

* fix name

* add panel
2017-05-13 17:41:46 +02:00
Pascal Vizeli
7a8ee2c46a Merge pull request #45 from home-assistant/dev
Release 0.25
2017-05-12 16:20:12 +02:00
Pascal Vizeli
35fe1f464c Update Hass.IO 0.25 2017-05-12 16:15:18 +02:00
Pascal Vizeli
0955bafebd Update data handling of addons (#44)
* Update data handling of addons

* Update addons api

* Update data.py

* Update data.py

* Add url fix bug
2017-05-12 16:14:49 +02:00
Pascal Vizeli
2e0c540c63 Pump version 2017-05-12 08:53:20 +02:00
Pascal Vizeli
6e9ef17a28 Merge pull request #43 from home-assistant/dev
Release 0.24
2017-05-12 01:47:48 +02:00
Pascal Vizeli
eb3cdbfeb9 update Hass.IO 0.24 2017-05-12 01:37:42 +02:00
Pascal Vizeli
f4cb16ad09 WIP: Add support for build docker on local repository (#42)
* Add support for build docker on local repository

* Add docker support

* finish build

* change api

* add dockerfile generator

* finish it

* fix lint

* fix path

* fix path

* fix copy

* add debug stuff

* fix docker template

* cleanups

* fix addons

* change handling

* fix lint / cleanup code

* fix lint

* tag
2017-05-12 01:37:03 +02:00
Pascal Vizeli
956af2bd62 Add security api and TOTP on supervisor (#41)
* Add security api and TOTP on supervisor

* finish security api

* fix lint

* fix lint p2

* add new api view to init

* Task session cleanup / fix hass wachdog

* fix lint

* fix api return

* fix check
2017-05-10 22:02:47 +02:00
Pascal Vizeli
b76cd5c004 Add files via upload 2017-05-10 17:01:35 +02:00
Pascal Vizeli
61d9301dcc Add files via upload 2017-05-10 11:06:34 +02:00
Pascal Vizeli
2ded05be83 Add files via upload 2017-05-10 10:39:00 +02:00
Pascal Vizeli
899d6766c5 Pump version to 0.24 2017-05-10 00:30:11 +02:00
212 changed files with 16166 additions and 2744 deletions

43
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,43 @@
FROM python:3.7
WORKDIR /workspaces
# Install Node/Yarn for Frontent
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
git \
apt-utils \
apt-transport-https \
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& 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 \
&& rm -rf /var/lib/apt/lists/*
ENV NVM_DIR /root/.nvm
# Install docker
# https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/
RUN apt-get update && apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates \
curl \
software-properties-common \
gpg-agent \
&& curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \
&& add-apt-repository "deb https://download.docker.com/linux/debian $(lsb_release -cs) stable" \
&& apt-get update && apt-get install -y --no-install-recommends \
docker-ce \
docker-ce-cli \
containerd.io \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies from requirements.txt if it exists
COPY requirements.txt requirements_tests.txt /workspaces/
RUN pip install -r requirements.txt \
&& pip3 install -r requirements_tests.txt \
&& pip install black tox
# Set the default shell to bash instead of sh
ENV SHELL /bin/bash

View File

@@ -0,0 +1,29 @@
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
"name": "Hass.io dev",
"context": "..",
"dockerFile": "Dockerfile",
"appPort": "9123:8123",
"runArgs": [
"-e",
"GIT_EDITOR='code --wait'",
"--privileged"
],
"extensions": [
"ms-python.python"
],
"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"
],
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
}

23
.dockerignore Normal file
View File

@@ -0,0 +1,23 @@
# General files
.git
.github
.devcontainer
.vscode
# Test related files
.tox
# Temporary files
**/__pycache__
.pytest_cache
# virtualenv
venv/
# HA
home-assistant-polymer/*
misc/*
script/*
# Test ENV
data/

29
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,29 @@
<!-- 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
- 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.
-->
**Home Assistant release with the issue:**
<!--
- Frontend -> Developer tools -> Info
- Or use this command: hass --version
-->
**Operating environment (HassOS/Generic):**
<!--
Please provide details about your environment.
-->
**Supervisor logs:**
<!--
- Frontend -> Hass.io -> System
- Or use this command: hassio su logs
-->
**Description of problem:**

13
.github/move.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# Configuration for move-issues - https://github.com/dessant/move-issues
# Delete the command comment. Ignored when the comment also contains other content
deleteCommand: true
# Close the source issue after moving
closeSourceIssue: true
# Lock the source issue after moving
lockSourceIssue: false
# Set custom aliases for targets
# aliases:
# r: repo
# or: owner/repo

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

@@ -0,0 +1,4 @@
template: |
## What's Changed
$CHANGES

17
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# 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
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

5
.gitignore vendored
View File

@@ -90,3 +90,8 @@ ENV/
# pylint
.pylint.d/
# VS Code
.vscode/*
!.vscode/cSpell.json
!.vscode/tasks.json

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "home-assistant-polymer"]
path = home-assistant-polymer
url = https://github.com/home-assistant/home-assistant-polymer
branch = dev

5
.hadolint.yaml Normal file
View File

@@ -0,0 +1,5 @@
ignored:
- DL3018
- DL3006
- DL3013
- SC2155

View File

@@ -1,12 +0,0 @@
sudo: false
matrix:
fast_finish: true
include:
- python: "3.5"
cache:
directories:
- $HOME/.cache/pip
install: pip install -U tox
language: python
script: tox

92
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,92 @@
{
"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": []
}
]
}

781
API.md
View File

@@ -1,10 +1,11 @@
# HassIO Server
# Hass.io
## HassIO REST API
## Hass.io RESTful API
Interface for HomeAssistant to control things from supervisor.
Interface for Home Assistant to control things from supervisor.
On error / Code 400:
On error:
```json
{
"result": "error",
@@ -12,7 +13,8 @@ On error:
}
```
On success
On success / Code 200:
```json
{
"result": "ok",
@@ -20,10 +22,14 @@ On success
}
```
### HassIO
For access to API you need set the `X-HASSIO-KEY` they will be available for Add-ons/HomeAssistant with environment `HASSIO_TOKEN`.
### Hass.io
- GET `/supervisor/ping`
This API call don't need a token.
- GET `/supervisor/info`
The addons from `addons` are only installed one.
@@ -33,17 +39,24 @@ The addons from `addons` are only installed one.
"version": "INSTALL_VERSION",
"last_version": "LAST_VERSION",
"arch": "armhf|aarch64|i386|amd64",
"beta_channel": "true|false",
"channel": "stable|beta|dev",
"timezone": "TIMEZONE",
"logging": "debug|info|warning|error|critical",
"ip_address": "ip address",
"wait_boot": "int",
"debug": "bool",
"debug_block": "bool",
"addons": [
{
"name": "xy bla",
"slug": "xy",
"description": "description",
"arch": ["armhf", "aarch64", "i386", "amd64"],
"repository": "12345678|null",
"version": "LAST_VERSION",
"installed": "INSTALL_VERSION",
"detached": "bool"
"icon": "bool",
"logo": "bool",
"state": "started|stopped",
}
],
"addons_repositories": [
@@ -52,38 +65,10 @@ The addons from `addons` are only installed one.
}
```
- GET `/supervisor/addons`
Get all available addons
```json
{
"addons": [
{
"name": "xy bla",
"slug": "xy",
"description": "description",
"arch": ["armhf", "aarch64", "i386", "amd64"],
"repository": "core|local|REP_ID",
"version": "LAST_VERSION",
"installed": "none|INSTALL_VERSION",
"detached": "bool"
}
],
"repositories": [
{
"slug": "12345678",
"name": "Repitory Name",
"source": "URL_OF_REPOSITORY",
"url": "null|WEBSITE",
"maintainer": "null|BLA BLU <fla@dld.ch>"
}
]
}
```
- POST `/supervisor/update`
Optional:
```json
{
"version": "VERSION"
@@ -91,9 +76,15 @@ Optional:
```
- POST `/supervisor/options`
```json
{
"beta_channel": "true|false",
"channel": "stable|beta|dev",
"timezone": "TIMEZONE",
"wait_boot": "int",
"debug": "bool",
"debug_block": "bool",
"logging": "debug|info|warning|error|critical",
"addons_repositories": [
"REPO_URL"
]
@@ -106,64 +97,284 @@ Reload addons/version.
- GET `/supervisor/logs`
Output the raw docker log
Output is the raw docker log.
- GET `/supervisor/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
}
```
- GET `/supervisor/repair`
Repair overlayfs issue and restore lost images
### Snapshot
- GET `/snapshots`
```json
{
"snapshots": [
{
"slug": "SLUG",
"date": "ISO",
"name": "Custom name",
"type": "full|partial",
"protected": "bool"
}
]
}
```
- POST `/snapshots/reload`
- POST `/snapshots/new/upload`
return:
```json
{
"slug": ""
}
```
- POST `/snapshots/new/full`
```json
{
"name": "Optional",
"password": "Optional"
}
```
return:
```json
{
"slug": ""
}
```
- POST `/snapshots/new/partial`
```json
{
"name": "Optional",
"addons": ["ADDON_SLUG"],
"folders": ["FOLDER_NAME"],
"password": "Optional"
}
```
return:
```json
{
"slug": ""
}
```
- POST `/snapshots/reload`
- GET `/snapshots/{slug}/info`
```json
{
"slug": "SNAPSHOT ID",
"type": "full|partial",
"name": "custom snapshot name / description",
"date": "ISO",
"size": "SIZE_IN_MB",
"protected": "bool",
"homeassistant": "version",
"addons": [
{
"slug": "ADDON_SLUG",
"name": "NAME",
"version": "INSTALLED_VERSION",
"size": "SIZE_IN_MB"
}
],
"repositories": ["URL"],
"folders": ["NAME"]
}
```
- POST `/snapshots/{slug}/remove`
- GET `/snapshots/{slug}/download`
- POST `/snapshots/{slug}/restore/full`
```json
{
"password": "Optional"
}
```
- POST `/snapshots/{slug}/restore/partial`
```json
{
"homeassistant": "bool",
"addons": ["ADDON_SLUG"],
"folders": ["FOLDER_NAME"],
"password": "Optional"
}
```
### Host
- POST `/host/reload`
- POST `/host/shutdown`
- POST `/host/reboot`
- GET `/host/info`
See HostControl info command.
```json
{
"type": "",
"version": "",
"last_version": "",
"features": ["shutdown", "reboot", "update", "network_info", "network_control"],
"hostname": "",
"os": ""
"hostname": "hostname|null",
"features": ["shutdown", "reboot", "hostname", "services", "hassos"],
"operating_system": "HassOS XY|Ubuntu 16.4|null",
"kernel": "4.15.7|null",
"chassis": "specific|null",
"deployment": "stable|beta|dev|null",
"cpe": "xy|null",
}
```
- POST `/host/update`
Optional:
```json
{
"version": "VERSION"
}
```
- POST `/host/options`
### Network
- GET `/network/info`
- POST `/network/options`
```json
{
"hostname": "",
"mode": "dhcp|fixed",
"ssid": "",
"ip": "",
"netmask": "",
"gateway": ""
}
```
### HomeAssistant
- POST `/host/reload`
#### Services
- GET `/host/services`
```json
{
"services": [
{
"name": "xy.service",
"description": "XY ...",
"state": "active|"
}
]
}
```
- POST `/host/service/{unit}/stop`
- POST `/host/service/{unit}/start`
- POST `/host/service/{unit}/reload`
### HassOS
- GET `/hassos/info`
```json
{
"version": "2.3",
"version_cli": "7",
"version_latest": "2.4",
"version_cli_latest": "8",
"board": "ova|rpi"
}
```
- POST `/hassos/update`
```json
{
"version": "optional"
}
```
- POST `/hassos/update/cli`
```json
{
"version": "optional"
}
```
- POST `/hassos/config/sync`
Load host configs from a USB stick.
### Hardware
- GET `/hardware/info`
```json
{
"serial": ["/dev/xy"],
"input": ["Input device name"],
"disk": ["/dev/sdax"],
"gpio": ["gpiochip0", "gpiochip100"],
"audio": {
"CARD_ID": {
"name": "xy",
"type": "microphone",
"devices": [
"chan_id": "channel ID",
"chan_type": "type of device"
]
}
}
}
```
- GET `/hardware/audio`
```json
{
"audio": {
"input": {
"0,0": "Mic"
},
"output": {
"1,0": "Jack",
"1,1": "HDMI"
}
}
}
```
### Home Assistant
- GET `/homeassistant/info`
```json
{
"version": "INSTALL_VERSION",
"last_version": "LAST_VERSION"
"last_version": "LAST_VERSION",
"arch": "arch",
"machine": "Image machine type",
"ip_address": "ip address",
"image": "str",
"custom": "bool -> if custom image",
"boot": "bool",
"port": 8123,
"ssl": "bool",
"watchdog": "bool",
"wait_boot": 600
}
```
- POST `/homeassistant/update`
Optional:
```json
{
"version": "VERSION"
@@ -172,33 +383,188 @@ Optional:
- GET `/homeassistant/logs`
Output the raw docker log
Output is the raw Docker log.
- POST `/homeassistant/restart`
- POST `/homeassistant/check`
- POST `/homeassistant/start`
- POST `/homeassistant/stop`
- POST `/homeassistant/rebuild`
### REST API addons
- POST `/homeassistant/options`
- GET `/addons/{addon}/info`
```json
{
"name": "xy bla",
"description": "description",
"url": "null|url of addon",
"detached": "bool",
"repository": "12345678|null",
"version": "VERSION",
"last_version": "LAST_VERSION",
"state": "started|stopped",
"boot": "auto|manual",
"options": {},
"image": "Optional|null",
"last_version": "Optional for custom image|null",
"port": "port for access hass",
"ssl": "bool",
"password": "",
"refresh_token": "",
"watchdog": "bool",
"wait_boot": 600
}
```
Image with `null` and last_version with `null` reset this options.
- POST/GET `/homeassistant/api`
Proxy to real home-assistant instance.
- GET `/homeassistant/websocket`
Proxy to real websocket instance.
- GET `/homeassistant/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
}
```
### RESTful for API addons
If an add-on will call itself, you can use `/addons/self/...`.
- GET `/addons`
Get all available addons.
```json
{
"addons": [
{
"name": "xy bla",
"slug": "xy",
"description": "description",
"repository": "core|local|REP_ID",
"version": "LAST_VERSION",
"installed": "none|INSTALL_VERSION",
"detached": "bool",
"available": "bool",
"build": "bool",
"url": "null|url",
"icon": "bool",
"logo": "bool"
}
],
"repositories": [
{
"slug": "12345678",
"name": "Repitory Name|unknown",
"source": "URL_OF_REPOSITORY",
"url": "WEBSITE|REPOSITORY",
"maintainer": "BLA BLU <fla@dld.ch>|unknown"
}
]
}
```
- POST `/addons/reload`
- GET `/addons/{addon}/info`
```json
{
"name": "xy bla",
"slug": "xdssd_xybla",
"hostname": "xdssd-xybla",
"dns": [],
"description": "description",
"long_description": "null|markdown",
"auto_update": "bool",
"url": "null|url of addon",
"detached": "bool",
"available": "bool",
"arch": ["armhf", "aarch64", "i386", "amd64"],
"machine": "[raspberrypi2, tinker]",
"homeassistant": "null|min Home Assistant version",
"repository": "12345678|null",
"version": "null|VERSION_INSTALLED",
"last_version": "LAST_VERSION",
"state": "none|started|stopped",
"boot": "auto|manual",
"build": "bool",
"options": "{}",
"network": "{}|null",
"network_description": "{}|null",
"host_network": "bool",
"host_pid": "bool",
"host_ipc": "bool",
"host_dbus": "bool",
"privileged": ["NET_ADMIN", "SYS_ADMIN"],
"apparmor": "disable|default|profile",
"devices": ["/dev/xy"],
"udev": "bool",
"auto_uart": "bool",
"icon": "bool",
"logo": "bool",
"changelog": "bool",
"hassio_api": "bool",
"hassio_role": "default|homeassistant|manager|admin",
"homeassistant_api": "bool",
"auth_api": "bool",
"full_access": "bool",
"protected": "bool",
"rating": "1-6",
"stdin": "bool",
"webui": "null|http(s)://[HOST]:port/xy/zx",
"gpio": "bool",
"kernel_modules": "bool",
"devicetree": "bool",
"docker_api": "bool",
"audio": "bool",
"audio_input": "null|0,0",
"audio_output": "null|0,0",
"services_role": "['service:access']",
"discovery": "['service']",
"ip_address": "ip address",
"ingress": "bool",
"ingress_entry": "null|/api/hassio_ingress/slug",
"ingress_url": "null|/api/hassio_ingress/slug/entry.html",
"ingress_port": "null|int",
"ingress_panel": "null|bool"
}
```
- GET `/addons/{addon}/icon`
- GET `/addons/{addon}/logo`
- GET `/addons/{addon}/changelog`
- POST `/addons/{addon}/options`
```json
{
"boot": "auto|manual",
"auto_update": "bool",
"network": {
"CONTAINER": "port|[ip, port]"
},
"options": {},
"audio_output": "null|0,0",
"audio_input": "null|0,0",
"ingress_panel": "bool"
}
```
Reset custom network/audio/options, set it `null`.
- POST `/addons/{addon}/security`
This function is not callable by itself.
```json
{
"protected": "bool",
}
```
@@ -207,63 +573,228 @@ Output the raw docker log
- POST `/addons/{addon}/stop`
- POST `/addons/{addon}/install`
Optional:
```json
{
"version": "VERSION"
}
```
- POST `/addons/{addon}/uninstall`
- POST `/addons/{addon}/update`
Optional:
- GET `/addons/{addon}/logs`
Output is the raw Docker log.
- POST `/addons/{addon}/restart`
- POST `/addons/{addon}/rebuild`
Only supported for local build addons
- POST `/addons/{addon}/stdin`
Write data to add-on stdin
- GET `/addons/{addon}/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
}
```
### ingress
- POST `/ingress/session`
Create a new Session for access to ingress service.
```json
{
"session": "token"
}
```
- GET `/ingress/panels`
Return a list of enabled panels.
```json
{
"panels": {
"addon_slug": {
"enable": "boolean",
"icon": "mdi:...",
"title": "title",
"admin": "boolean"
}
}
}
```
- VIEW `/ingress/{token}`
Ingress WebUI for this Add-on. The addon need support HASS Auth!
Need ingress session as cookie.
### discovery
- GET `/discovery`
```json
{
"discovery": [
{
"addon": "slug",
"service": "name",
"uuid": "uuid",
"config": {}
}
]
}
```
- GET `/discovery/{UUID}`
```json
{
"addon": "slug",
"service": "name",
"uuid": "uuid",
"config": {}
}
```
- POST `/discovery`
```json
{
"service": "name",
"config": {}
}
```
return:
```json
{
"uuid": "uuid"
}
```
- DEL `/discovery/{UUID}`
### Services
- GET `/services`
```json
{
"services": [
{
"slug": "name",
"available": "bool",
"providers": "list"
}
]
}
```
#### MQTT
- GET `/services/mqtt`
```json
{
"addon": "name",
"host": "xy",
"port": "8883",
"ssl": "bool",
"username": "optional",
"password": "optional",
"protocol": "3.1.1"
}
```
- POST `/services/mqtt`
```json
{
"host": "xy",
"port": "8883",
"ssl": "bool|optional",
"username": "optional",
"password": "optional",
"protocol": "3.1.1"
}
```
- DEL `/services/mqtt`
### Misc
- GET `/info`
```json
{
"supervisor": "version",
"homeassistant": "version",
"hassos": "null|version",
"hostname": "name",
"machine": "type",
"arch": "arch",
"supported_arch": ["arch1", "arch2"],
"channel": "stable|beta|dev",
"logging": "debug|info|warning|error|critical",
"timezone": "Europe/Zurich"
}
```
### DNS
- GET `/dns/info`
```json
{
"host": "ip-address",
"version": "1",
"latest_version": "2",
"servers": ["dns://8.8.8.8"]
}
```
- POST `/dns/options`
```json
{
"servers": ["dns://8.8.8.8"]
}
```
- POST `/dns/update`
```json
{
"version": "VERSION"
}
```
- GET `/addons/{addon}/logs`
- GET `/dns/logs`
Output the raw docker log
- POST `/addons/{addon}/restart`
## Host Control
Communicate over unix socket with a host daemon.
- commands
```
# info
-> {'type', 'version', 'last_version', 'features', 'hostname'}
# reboot
# shutdown
# host-update [v]
# network info
# network hostname xy
# network wlan ssd xy
# network wlan password xy
# network int ip xy
# network int netmask xy
# network int route xy
- GET `/dns/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
}
```
features:
- shutdown
- reboot
- update
- network_info
- network_control
### Auth / SSO API
Answer:
```
{}|OK|ERROR|WRONG
```
You can use the user system on homeassistant. We handle this auth system on
supervisor.
- {}: json
- OK: call was successfully
- ERROR: error on call
- WRONG: not supported
You can call post `/auth`
We support:
- Json `{ "user|name": "...", "password": "..." }`
- application/x-www-form-urlencoded `user|name=...&password=...`
- BasicAuth

38
Dockerfile Normal file
View File

@@ -0,0 +1,38 @@
ARG BUILD_FROM
FROM $BUILD_FROM
# Install base
RUN apk add --no-cache \
openssl \
libffi \
musl \
git \
socat \
glib \
libstdc++ \
eudev \
eudev-libs
ARG BUILD_ARCH
WORKDIR /usr/src
# Install requirements
COPY requirements.txt .
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 \
&& rm -f requirements.txt
# Install HassIO
COPY . hassio
RUN pip3 install --no-cache-dir -e ./hassio \
&& python3 -m compileall ./hassio/hassio
# Initialize udev daemon, handle CMD
COPY entry.sh /bin/
ENTRYPOINT ["/bin/entry.sh"]
WORKDIR /
CMD [ "python3", "-m", "hassio" ]

218
LICENSE
View File

@@ -1,29 +1,201 @@
BSD 3-Clause License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2017, Pascal Vizeli
All rights reserved.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Definitions.
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
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 "{}"
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
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Pascal Vizeli
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,26 +1,30 @@
# HassIO
### First private cloud solution for home automation.
[![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)
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.
# Hass.io
## 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.
![](misc/hassio.png?raw=true)
[HassIO-Addons](https://github.com/home-assistant/hassio-addons) | [HassIO-Build](https://github.com/home-assistant/hassio-build)
## Installation
**HassIO is under active development and is not ready yet for production use.**
Installation instructions can be found at <https://home-assistant.io/hassio>.
## Installing Hass.io
## Development
Looks to our [website](https://home-assistant.io/hassio).
The development of the supervisor is a bit tricky. Not difficult but tricky.
# HomeAssistant
- 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`
- Tag it as `homeassistant/xy-hassio-supervisor:latest`
- Restart the service like `systemctl restart hassos-supervisor | journalctl -fu hassos-supervisor`
- Test your changes
## SSL
All addons that create SSL certs follow the same file structure. If you use one, put follow lines in your `configuration.yaml`.
```yaml
http:
ssl_certificate: /ssl/fullchain.pem
ssl_key: /ssl/privkey.pem
```
Small Bugfix or improvements, make a PR. Significant change makes first an RFC.

168
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,168 @@
# https://dev.azure.com/home-assistant
trigger:
batch: true
branches:
include:
- master
- dev
tags:
include:
- '*'
exclude:
- untagged*
pr:
- dev
variables:
- name: basePythonTag
value: '3.7-alpine3.10'
- name: versionHadolint
value: 'v1.16.3'
- name: versionBuilder
value: '4.4'
- name: versionWheels
value: '1.0-3.7-alpine3.10'
- group: docker
- group: wheels
stages:
- stage: 'Test'
jobs:
- job: 'Tox'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.7'
inputs:
versionSpec: '3.7'
- script: pip install tox
displayName: 'Install Tox'
- script: tox
displayName: 'Run Tox'
- job: 'Black'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
displayName: 'Use Python $(python.version)'
inputs:
versionSpec: '3.7'
- script: pip install black
displayName: 'Install black'
- script: black --target-version py37 --check hassio tests
displayName: 'Run Black'
- job: 'JQ'
pool:
vmImage: 'ubuntu-latest'
steps:
- script: sudo apt-get install -y jq
displayName: 'Install JQ'
- bash: |
shopt -s globstar
cat **/*.json | jq '.'
displayName: 'Run JQ'
- job: 'Hadolint'
pool:
vmImage: 'ubuntu-latest'
steps:
- script: sudo docker pull hadolint/hadolint:$(versionHadolint)
displayName: 'Install Hadolint'
- script: |
sudo docker run --rm -i \
-v $(pwd)/.hadolint.yaml:/.hadolint.yaml:ro \
hadolint/hadolint:$(versionHadolint) < Dockerfile
displayName: 'Run Hadolint'
- stage: 'Wheels'
jobs:
- job: 'Wheels'
condition: eq(variables['Build.SourceBranchName'], 'dev')
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'
- stage: 'Deploy'
jobs:
- job: 'VersionValidate'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), eq(variables['Build.SourceBranchName'], 'dev'))
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.7'
inputs:
versionSpec: '3.7'
- script: |
setup_version="$(python setup.py -V)"
branch_version="$(Build.SourceBranchName)"
if [ "${branch_version}" == "dev" ]; then
exit 0
elif [ "${setup_version}" != "${branch_version}" ]; then
echo "Version of tag ${branch_version} don't match with ${setup_version}!"
exit 1
fi
displayName: 'Check version of branch/tag'
- job: 'Release'
dependsOn:
- 'VersionValidate'
pool:
vmImage: 'ubuntu-latest'
steps:
- script: sudo docker login -u $(dockerUser) -p $(dockerPassword)
displayName: 'Docker hub login'
- script: sudo docker pull homeassistant/amd64-builder:$(versionBuilder)
displayName: 'Install Builder'
- script: |
sudo docker run --rm --privileged \
-v ~/.docker:/root/.docker \
-v /run/docker.sock:/run/docker.sock:rw -v $(pwd):/data:ro \
homeassistant/amd64-builder:$(versionBuilder) \
--supervisor $(basePythonTag) --version $(Build.SourceBranchName) \
--all -t /data --docker-hub homeassistant
displayName: 'Build Release'

13
entry.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
set -e
udevd --daemon
udevadm trigger
if CMD="$(command -v "$1")"; then
shift
exec "$CMD" "$@"
else
echo "Command not found: $1"
exit 1
fi

View File

@@ -1 +1 @@
"""Init file for HassIO."""
"""Init file for Hass.io."""

View File

@@ -1,33 +1,62 @@
"""Main file for HassIO."""
"""Main file for Hass.io."""
import asyncio
from concurrent.futures import ThreadPoolExecutor
import logging
import sys
import hassio.bootstrap as bootstrap
import hassio.core as core
from hassio import bootstrap
_LOGGER = logging.getLogger(__name__)
def initialize_event_loop():
"""Attempt to use uvloop."""
try:
import uvloop
uvloop.install()
except ImportError:
pass
return asyncio.get_event_loop()
# pylint: disable=invalid-name
if __name__ == "__main__":
bootstrap.initialize_logging()
# Init async event loop
loop = initialize_event_loop()
# Check if all information are available to setup Hass.io
if not bootstrap.check_environment():
exit(1)
sys.exit(1)
loop = asyncio.get_event_loop()
hassio = core.HassIO(loop)
# init executor pool
executor = ThreadPoolExecutor(thread_name_prefix="SyncWorker")
loop.set_default_executor(executor)
_LOGGER.info("Run Hassio setup")
loop.run_until_complete(hassio.setup())
_LOGGER.info("Initialize Hass.io setup")
coresys = loop.run_until_complete(bootstrap.initialize_coresys())
loop.run_until_complete(coresys.core.connect())
_LOGGER.info("Start Hassio task")
loop.call_soon_threadsafe(loop.create_task, hassio.start())
loop.call_soon_threadsafe(bootstrap.reg_signal, loop, hassio)
bootstrap.supervisor_debugger(coresys)
bootstrap.migrate_system_env(coresys)
loop.run_forever()
loop.close()
_LOGGER.info("Setup HassIO")
loop.run_until_complete(coresys.core.setup())
_LOGGER.info("Close Hassio")
sys.exit(hassio.exit_code)
loop.call_soon_threadsafe(loop.create_task, coresys.core.start())
loop.call_soon_threadsafe(bootstrap.reg_signal, loop)
try:
_LOGGER.info("Run Hass.io")
loop.run_forever()
finally:
_LOGGER.info("Stopping Hass.io")
loop.run_until_complete(coresys.core.stop())
executor.shutdown(wait=False)
loop.close()
_LOGGER.info("Close Hass.io")
sys.exit(0)

View File

@@ -1,218 +1,319 @@
"""Init file for HassIO addons."""
"""Init file for Hass.io add-ons."""
import asyncio
from contextlib import suppress
import logging
import shutil
import tarfile
from typing import Dict, List, Optional, Union
from ..const import BOOT_AUTO, STATE_STARTED
from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
AddonsError,
AddonsNotSupportedError,
CoreDNSError,
DockerAPIError,
HomeAssistantAPIError,
HostAppArmorError,
)
from ..store.addon import AddonStore
from .addon import Addon
from .data import AddonsData
from .git import AddonsRepoHassIO, AddonsRepoCustom
from ..const import STATE_STOPPED, STATE_STARTED
from ..dock.addon import DockerAddon
_LOGGER = logging.getLogger(__name__)
AnyAddon = Union[Addon, AddonStore]
class AddonManager(AddonsData):
"""Manage addons inside HassIO."""
def __init__(self, config, loop, dock):
"""Initialize docker base wrapper."""
super().__init__(config)
class AddonManager(CoreSysAttributes):
"""Manage add-ons inside Hass.io."""
self.loop = loop
self.dock = dock
self.repositories = []
self.dockers = {}
def __init__(self, coresys: CoreSys):
"""Initialize Docker base wrapper."""
self.coresys: CoreSys = coresys
self.data: AddonsData = AddonsData(coresys)
self.local: Dict[str, Addon] = {}
self.store: Dict[str, AddonStore] = {}
async def prepare(self, arch):
"""Startup addon management."""
self.arch = arch
@property
def all(self) -> List[AnyAddon]:
"""Return a list of all add-ons."""
addons = {**self.store, **self.local}
return list(addons.values())
# init hassio repository
self.repositories.append(AddonsRepoHassIO(self.config, self.loop))
@property
def installed(self) -> List[Addon]:
"""Return a list of all installed add-ons."""
return list(self.local.values())
# init custom repositories
for url in self.config.addons_repositories:
self.repositories.append(
AddonsRepoCustom(self.config, self.loop, url))
def get(self, addon_slug: str) -> Optional[AnyAddon]:
"""Return an add-on from slug.
# load addon repository
tasks = [addon.load() for addon in self.repositories]
Prio:
1 - Local
2 - Store
"""
if addon_slug in self.local:
return self.local[addon_slug]
return self.store.get(addon_slug)
def from_token(self, token: str) -> Optional[Addon]:
"""Return an add-on from Hass.io token."""
for addon in self.installed:
if token == addon.hassio_token:
return addon
return None
async def load(self) -> None:
"""Start up add-on management."""
tasks = []
for slug in self.data.system:
addon = self.local[slug] = Addon(self.coresys, slug)
tasks.append(addon.load())
# Run initial tasks
_LOGGER.info("Found %d installed add-ons", len(tasks))
if tasks:
await asyncio.wait(tasks, loop=self.loop)
await asyncio.wait(tasks)
# read data from repositories
self.read_data_from_repositories()
self.merge_update_config()
# Sync DNS
await self.sync_dns()
# load installed addons
for addon in self.list_installed:
self.dockers[addon] = DockerAddon(
self.config, self.loop, self.dock, self, addon)
await self.dockers[addon].attach()
async def boot(self, stage: str) -> None:
"""Boot add-ons with mode auto."""
tasks = []
for addon in self.installed:
if addon.boot != BOOT_AUTO or addon.startup != stage:
continue
tasks.append(addon.start())
async def add_git_repository(self, url):
"""Add a new custom repository."""
if url in self.config.addons_repositories:
_LOGGER.warning("Repository already exists %s", url)
return False
_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)
repo = AddonsRepoCustom(self.config, self.loop, url)
async def shutdown(self, stage: str) -> None:
"""Shutdown addons."""
tasks = []
for addon in self.installed:
if await addon.state() != STATE_STARTED or addon.startup != stage:
continue
tasks.append(addon.stop())
if not await repo.load():
_LOGGER.error("Can't load from repository %s", url)
return False
_LOGGER.info("Phase '%s' stop %d add-ons", stage, len(tasks))
if tasks:
await asyncio.wait(tasks)
self.config.addons_repositories = url
self.repositories.append(repo)
return True
async def install(self, slug: str) -> None:
"""Install an add-on."""
if slug in self.local:
_LOGGER.warning("Add-on %s is already installed", slug)
return
store = self.store.get(slug)
def drop_git_repository(self, url):
"""Remove a custom repository."""
for repo in self.repositories:
if repo.url == url:
self.repositories.remove(repo)
self.config.drop_addon_repository(url)
repo.remove()
return True
if not store:
_LOGGER.error("Add-on %s not exists", slug)
raise AddonsError()
return False
if not store.available:
_LOGGER.error("Add-on %s not supported on that platform", slug)
raise AddonsNotSupportedError()
async def reload(self):
"""Update addons from repo and reload list."""
tasks = [addon.pull() for addon in self.repositories]
if not tasks:
self.data.install(store)
addon = Addon(self.coresys, slug)
if not addon.path_data.is_dir():
_LOGGER.info("Create Home Assistant add-on data folder %s", addon.path_data)
addon.path_data.mkdir()
# Setup/Fix AppArmor profile
await addon.install_apparmor()
try:
await addon.instance.install(store.version, store.image)
except DockerAPIError:
self.data.uninstall(addon)
raise AddonsError() from None
else:
self.local[slug] = addon
_LOGGER.info("Add-on '%s' successfully installed", slug)
async def uninstall(self, slug: str) -> None:
"""Remove an add-on."""
if slug not in self.local:
_LOGGER.warning("Add-on %s is not installed", slug)
return
addon = self.local.get(slug)
try:
await addon.instance.remove()
except DockerAPIError:
raise AddonsError() from None
await addon.remove_data()
# Cleanup audio settings
if addon.path_asound.exists():
with suppress(OSError):
addon.path_asound.unlink()
# Cleanup AppArmor profile
with suppress(HostAppArmorError):
await addon.uninstall_apparmor()
# Cleanup Ingress panel from sidebar
if addon.ingress_panel:
addon.ingress_panel = False
with suppress(HomeAssistantAPIError):
await self.sys_ingress.update_hass_panel(addon)
# Cleanup internal data
addon.remove_discovery()
self.data.uninstall(addon)
self.local.pop(slug)
_LOGGER.info("Add-on '%s' successfully removed", slug)
async def update(self, slug: str) -> None:
"""Update add-on."""
if slug not in self.local:
_LOGGER.error("Add-on %s is not installed", slug)
raise AddonsError()
addon = self.local.get(slug)
if addon.is_detached:
_LOGGER.error("Add-on %s is not available inside store", slug)
raise AddonsError()
store = self.store.get(slug)
if addon.version == store.version:
_LOGGER.warning("No update available for add-on %s", slug)
return
await asyncio.wait(tasks, loop=self.loop)
# Check if available, Maybe something have changed
if not store.available:
_LOGGER.error("Add-on %s not supported on that platform", slug)
raise AddonsNotSupportedError()
# read data from repositories
self.read_data_from_repositories()
self.merge_update_config()
# Update instance
last_state = await addon.state()
try:
await addon.instance.update(store.version, store.image)
# remove stalled addons
for addon in self.list_detached:
_LOGGER.warning("Dedicated addon '%s' found!", addon)
# Cleanup
with suppress(DockerAPIError):
await addon.instance.cleanup()
except DockerAPIError:
raise AddonsError() from None
else:
self.data.update(store)
_LOGGER.info("Add-on '%s' successfully updated", slug)
async def auto_boot(self, start_type):
"""Boot addons with mode auto."""
boot_list = self.list_startup(start_type)
tasks = [self.start(addon) for addon in boot_list]
# Setup/Fix AppArmor profile
await addon.install_apparmor()
_LOGGER.info("Startup %s run %d addons", start_type, len(tasks))
if tasks:
await asyncio.wait(tasks, loop=self.loop)
# restore state
if last_state == STATE_STARTED:
await addon.start()
async def install(self, addon, version=None):
"""Install a addon."""
if not self.exists_addon(addon):
_LOGGER.error("Addon %s not exists for install", addon)
return False
async def rebuild(self, slug: str) -> None:
"""Perform a rebuild of local build add-on."""
if slug not in self.local:
_LOGGER.error("Add-on %s is not installed", slug)
raise AddonsError()
addon = self.local.get(slug)
if self.arch not in self.get_arch(addon):
_LOGGER.error("Addon %s not supported on %s", addon, self.arch)
return False
if addon.is_detached:
_LOGGER.error("Add-on %s is not available inside store", slug)
raise AddonsError()
store = self.store.get(slug)
if self.is_installed(addon):
_LOGGER.error("Addon %s is already installed", addon)
return False
# Check if a rebuild is possible now
if addon.version != store.version:
_LOGGER.error("Version changed, use Update instead Rebuild")
raise AddonsError()
if not addon.need_build:
_LOGGER.error("Can't rebuild a image based add-on")
raise AddonsNotSupportedError()
if not self.path_data(addon).is_dir():
_LOGGER.info("Create Home-Assistant addon data folder %s",
self.path_data(addon))
self.path_data(addon).mkdir()
# remove docker container but not addon config
last_state = await addon.state()
try:
await addon.instance.remove()
await addon.instance.install(addon.version)
except DockerAPIError:
raise AddonsError() from None
else:
self.data.update(store)
_LOGGER.info("Add-on '%s' successfully rebuilded", slug)
addon_docker = DockerAddon(
self.config, self.loop, self.dock, self, addon)
# restore state
if last_state == STATE_STARTED:
await addon.start()
version = version or self.get_last_version(addon)
if not await addon_docker.install(version):
return False
async def restore(self, slug: str, tar_file: tarfile.TarFile) -> None:
"""Restore state of an add-on."""
if slug not in self.local:
_LOGGER.debug("Add-on %s is not local available for restore")
addon = Addon(self.coresys, slug)
else:
_LOGGER.debug("Add-on %s is local available for restore")
addon = self.local[slug]
self.dockers[addon] = addon_docker
self.set_addon_install(addon, version)
return True
await addon.restore(tar_file)
async def uninstall(self, addon):
"""Remove a addon."""
if not self.is_installed(addon):
_LOGGER.error("Addon %s is already uninstalled", addon)
return False
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
return False
if not await self.dockers[addon].remove():
return False
if self.path_data(addon).is_dir():
_LOGGER.info("Remove Home-Assistant addon data folder %s",
self.path_data(addon))
shutil.rmtree(str(self.path_data(addon)))
self.dockers.pop(addon)
self.set_addon_uninstall(addon)
return True
async def state(self, addon):
"""Return running state of addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
# Check if new
if slug in self.local:
return
if await self.dockers[addon].is_running():
return STATE_STARTED
return STATE_STOPPED
_LOGGER.info("Detect new Add-on after restore %s", slug)
self.local[slug] = addon
async def start(self, addon):
"""Set options and start addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
return False
async def repair(self) -> None:
"""Repair local add-ons."""
needs_repair: List[Addon] = []
if not self.write_addon_options(addon):
_LOGGER.error("Can't write options for addon %s", addon)
return False
# Evaluate Add-ons to repair
for addon in self.installed:
if await addon.instance.exists():
continue
needs_repair.append(addon)
return await self.dockers[addon].run()
_LOGGER.info("Found %d add-ons to repair", len(needs_repair))
if not needs_repair:
return
async def stop(self, addon):
"""Stop addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
return False
for addon in needs_repair:
_LOGGER.info("Start repair for add-on: %s", addon.slug)
return await self.dockers[addon].stop()
with suppress(DockerAPIError, KeyError):
# Need pull a image again
if not addon.need_build:
await addon.instance.install(addon.version, addon.image)
continue
async def update(self, addon, version=None):
"""Update addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
return False
# Need local lookup
elif addon.need_build and not addon.is_detached:
store = self.store[addon.slug]
# If this add-on is available for rebuild
if addon.version == store.version:
await addon.instance.install(addon.version, addon.image)
continue
version = version or self.get_last_version(addon)
is_running = self.dockers[addon].is_running()
_LOGGER.error("Can't repair %s", addon.slug)
with suppress(AddonsError):
await self.uninstall(addon.slug)
# update
if await self.dockers[addon].update(version):
self.set_addon_update(addon, version)
if is_running:
await self.start(addon)
return True
return False
async def sync_dns(self) -> None:
"""Sync add-ons DNS names."""
# Update hosts
for addon in self.installed:
if not await addon.instance.is_running():
continue
self.sys_dns.add_host(
ipv4=addon.ip_address, names=[addon.hostname], write=False
)
async def restart(self, addon):
"""Restart addon."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
return False
return await self.dockers[addon].restart()
async def logs(self, addon):
"""Return addons log output."""
if addon not in self.dockers:
_LOGGER.error("No docker found for addon %s", addon)
return False
return await self.dockers[addon].logs()
# Write hosts files
with suppress(CoreDNSError):
self.sys_dns.write_hosts()

661
hassio/addons/addon.py Normal file
View File

@@ -0,0 +1,661 @@
"""Init file for Hass.io add-ons."""
from contextlib import suppress
from copy import deepcopy
from ipaddress import IPv4Address
import logging
from pathlib import Path, PurePath
import re
import secrets
import shutil
import tarfile
from tempfile import TemporaryDirectory
from typing import Any, Awaitable, Dict, List, Optional
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..const import (
ATTR_ACCESS_TOKEN,
ATTR_AUDIO_INPUT,
ATTR_AUDIO_OUTPUT,
ATTR_AUTO_UPDATE,
ATTR_BOOT,
ATTR_IMAGE,
ATTR_INGRESS_ENTRY,
ATTR_INGRESS_PANEL,
ATTR_INGRESS_PORT,
ATTR_INGRESS_TOKEN,
ATTR_NETWORK,
ATTR_OPTIONS,
ATTR_PORTS,
ATTR_PROTECTED,
ATTR_SCHEMA,
ATTR_STATE,
ATTR_SYSTEM,
ATTR_USER,
ATTR_UUID,
ATTR_VERSION,
DNS_SUFFIX,
STATE_STARTED,
STATE_STOPPED,
)
from ..coresys import CoreSys
from ..docker.addon import DockerAddon
from ..docker.stats import DockerStats
from ..exceptions import (
AddonsError,
AddonsNotSupportedError,
DockerAPIError,
HostAppArmorError,
JsonFileError,
)
from ..utils.apparmor import adjust_profile
from ..utils.json import read_json_file, write_json_file
from .model import AddonModel, Data
from .utils import remove_data
from .validate import SCHEMA_ADDON_SNAPSHOT, validate_options
_LOGGER = logging.getLogger(__name__)
RE_WEBUI = re.compile(
r"^(?:(?P<s_prefix>https?)|\[PROTO:(?P<t_proto>\w+)\])"
r":\/\/\[HOST\]:\[PORT:(?P<t_port>\d+)\](?P<s_suffix>.*)$"
)
class Addon(AddonModel):
"""Hold data for add-on inside Hass.io."""
def __init__(self, coresys: CoreSys, slug: str):
"""Initialize data holder."""
self.coresys: CoreSys = coresys
self.instance: DockerAddon = DockerAddon(coresys, self)
self.slug: str = slug
async def load(self) -> None:
"""Async initialize of object."""
with suppress(DockerAPIError):
await self.instance.attach(tag=self.version)
@property
def ip_address(self) -> IPv4Address:
"""Return IP of Add-on instance."""
return self.instance.ip_address
@property
def data(self) -> Data:
"""Return add-on data/config."""
return self.sys_addons.data.system[self.slug]
@property
def data_store(self) -> Data:
"""Return add-on data from store."""
return self.sys_store.data.addons.get(self.slug, self.data)
@property
def persist(self) -> Data:
"""Return add-on data/config."""
return self.sys_addons.data.user[self.slug]
@property
def is_installed(self) -> bool:
"""Return True if an add-on is installed."""
return True
@property
def is_detached(self) -> bool:
"""Return True if add-on is detached."""
return self.slug not in self.sys_store.data.addons
@property
def available(self) -> bool:
"""Return True if this add-on is available on this platform."""
return self._available(self.data_store)
@property
def version(self) -> Optional[str]:
"""Return installed version."""
return self.persist[ATTR_VERSION]
@property
def dns(self) -> List[str]:
"""Return list of DNS name for that add-on."""
return [f"{self.hostname}.{DNS_SUFFIX}"]
@property
def options(self) -> Dict[str, Any]:
"""Return options with local changes."""
return {**self.data[ATTR_OPTIONS], **self.persist[ATTR_OPTIONS]}
@options.setter
def options(self, value: Optional[Dict[str, Any]]):
"""Store user add-on options."""
if value is None:
self.persist[ATTR_OPTIONS] = {}
else:
self.persist[ATTR_OPTIONS] = deepcopy(value)
@property
def boot(self) -> bool:
"""Return boot config with prio local settings."""
return self.persist.get(ATTR_BOOT, super().boot)
@boot.setter
def boot(self, value: bool):
"""Store user boot options."""
self.persist[ATTR_BOOT] = value
@property
def auto_update(self) -> bool:
"""Return if auto update is enable."""
return self.persist.get(ATTR_AUTO_UPDATE, super().auto_update)
@auto_update.setter
def auto_update(self, value: bool):
"""Set auto update."""
self.persist[ATTR_AUTO_UPDATE] = value
@property
def uuid(self) -> str:
"""Return an API token for this add-on."""
return self.persist[ATTR_UUID]
@property
def hassio_token(self) -> Optional[str]:
"""Return access token for Hass.io API."""
return self.persist.get(ATTR_ACCESS_TOKEN)
@property
def ingress_token(self) -> Optional[str]:
"""Return access token for Hass.io API."""
return self.persist.get(ATTR_INGRESS_TOKEN)
@property
def ingress_entry(self) -> Optional[str]:
"""Return ingress external URL."""
if self.with_ingress:
return f"/api/hassio_ingress/{self.ingress_token}"
return None
@property
def latest_version(self) -> str:
"""Return version of add-on."""
return self.data_store[ATTR_VERSION]
@property
def protected(self) -> bool:
"""Return if add-on is in protected mode."""
return self.persist[ATTR_PROTECTED]
@protected.setter
def protected(self, value: bool):
"""Set add-on in protected mode."""
self.persist[ATTR_PROTECTED] = value
@property
def ports(self) -> Optional[Dict[str, Optional[int]]]:
"""Return ports of add-on."""
return self.persist.get(ATTR_NETWORK, super().ports)
@ports.setter
def ports(self, value: Optional[Dict[str, Optional[int]]]):
"""Set custom ports of add-on."""
if value is None:
self.persist.pop(ATTR_NETWORK, None)
return
# Secure map ports to value
new_ports = {}
for container_port, host_port in value.items():
if container_port in self.data.get(ATTR_PORTS, {}):
new_ports[container_port] = host_port
self.persist[ATTR_NETWORK] = new_ports
@property
def ingress_url(self) -> Optional[str]:
"""Return URL to ingress url."""
if not self.with_ingress:
return None
url = f"/api/hassio_ingress/{self.ingress_token}/"
if ATTR_INGRESS_ENTRY in self.data:
return f"{url}{self.data[ATTR_INGRESS_ENTRY]}"
return url
@property
def webui(self) -> Optional[str]:
"""Return URL to webui or None."""
url = super().webui
if not url:
return None
webui = RE_WEBUI.match(url)
# extract arguments
t_port = webui.group("t_port")
t_proto = webui.group("t_proto")
s_prefix = webui.group("s_prefix") or ""
s_suffix = webui.group("s_suffix") or ""
# search host port for this docker port
if self.ports is None:
port = t_port
else:
port = self.ports.get(f"{t_port}/tcp", t_port)
# for interface config or port lists
if isinstance(port, (tuple, list)):
port = port[-1]
# lookup the correct protocol from config
if t_proto:
proto = "https" if self.options[t_proto] else "http"
else:
proto = s_prefix
return f"{proto}://[HOST]:{port}{s_suffix}"
@property
def ingress_port(self) -> Optional[int]:
"""Return Ingress port."""
if not self.with_ingress:
return None
port = self.data[ATTR_INGRESS_PORT]
if port == 0:
return self.sys_ingress.get_dynamic_port(self.slug)
return port
@property
def ingress_panel(self) -> Optional[bool]:
"""Return True if the add-on access support ingress."""
return self.persist[ATTR_INGRESS_PANEL]
@ingress_panel.setter
def ingress_panel(self, value: bool):
"""Return True if the add-on access support ingress."""
self.persist[ATTR_INGRESS_PANEL] = value
@property
def audio_output(self) -> Optional[str]:
"""Return ALSA config for output or None."""
if not self.with_audio:
return None
return self.persist.get(ATTR_AUDIO_OUTPUT, self.sys_host.alsa.default.output)
@audio_output.setter
def audio_output(self, value: Optional[str]):
"""Set/reset audio output settings."""
if value is None:
self.persist.pop(ATTR_AUDIO_OUTPUT, None)
else:
self.persist[ATTR_AUDIO_OUTPUT] = value
@property
def audio_input(self) -> Optional[str]:
"""Return ALSA config for input or None."""
if not self.with_audio:
return None
return self.persist.get(ATTR_AUDIO_INPUT, self.sys_host.alsa.default.input)
@audio_input.setter
def audio_input(self, value: Optional[str]):
"""Set/reset audio input settings."""
if value is None:
self.persist.pop(ATTR_AUDIO_INPUT, None)
else:
self.persist[ATTR_AUDIO_INPUT] = value
@property
def image(self):
"""Return image name of add-on."""
return self.persist.get(ATTR_IMAGE)
@property
def need_build(self):
"""Return True if this add-on need a local build."""
return ATTR_IMAGE not in self.data
@property
def path_data(self):
"""Return add-on data path inside Supervisor."""
return Path(self.sys_config.path_addons_data, self.slug)
@property
def path_extern_data(self):
"""Return add-on data path external for Docker."""
return PurePath(self.sys_config.path_extern_addons_data, self.slug)
@property
def path_options(self):
"""Return path to add-on options."""
return Path(self.path_data, "options.json")
@property
def path_asound(self):
"""Return path to asound config."""
return Path(self.sys_config.path_tmp, f"{self.slug}_asound")
@property
def path_extern_asound(self):
"""Return path to asound config for Docker."""
return Path(self.sys_config.path_extern_tmp, f"{self.slug}_asound")
def save_persist(self):
"""Save data of add-on."""
self.sys_addons.data.save_data()
def write_options(self):
"""Return True if add-on options is written to data."""
schema = self.schema
options = self.options
try:
schema(options)
write_json_file(self.path_options, options)
except vol.Invalid as ex:
_LOGGER.error(
"Add-on %s have wrong options: %s",
self.slug,
humanize_error(options, ex),
)
except JsonFileError:
_LOGGER.error("Add-on %s can't write options", self.slug)
else:
_LOGGER.debug("Add-on %s write options: %s", self.slug, options)
return
raise AddonsError()
def remove_discovery(self):
"""Remove all discovery message from add-on."""
for message in self.sys_discovery.list_messages:
if message.addon != self.slug:
continue
self.sys_discovery.remove(message)
async def remove_data(self):
"""Remove add-on data."""
if not self.path_data.is_dir():
return
_LOGGER.info("Remove add-on data folder %s", self.path_data)
await remove_data(self.path_data)
def write_asound(self):
"""Write asound config to file and return True on success."""
asound_config = self.sys_host.alsa.asound(
alsa_input=self.audio_input, alsa_output=self.audio_output
)
try:
with self.path_asound.open("w") as config_file:
config_file.write(asound_config)
except OSError as err:
_LOGGER.error("Add-on %s can't write asound: %s", self.slug, err)
raise AddonsError()
_LOGGER.debug("Add-on %s write asound: %s", self.slug, self.path_asound)
async def install_apparmor(self) -> None:
"""Install or Update AppArmor profile for Add-on."""
exists_local = self.sys_host.apparmor.exists(self.slug)
exists_addon = self.path_apparmor.exists()
# Nothing to do
if not exists_local and not exists_addon:
return
# Need removed
if exists_local and not exists_addon:
await self.sys_host.apparmor.remove_profile(self.slug)
return
# Need install/update
with TemporaryDirectory(dir=self.sys_config.path_tmp) as tmp_folder:
profile_file = Path(tmp_folder, "apparmor.txt")
adjust_profile(self.slug, self.path_apparmor, profile_file)
await self.sys_host.apparmor.load_profile(self.slug, profile_file)
async def uninstall_apparmor(self) -> None:
"""Remove AppArmor profile for Add-on."""
if not self.sys_host.apparmor.exists(self.slug):
return
await self.sys_host.apparmor.remove_profile(self.slug)
def test_update_schema(self) -> bool:
"""Check if the existing configuration is valid after update."""
# load next schema
new_raw_schema = self.data_store[ATTR_SCHEMA]
default_options = self.data_store[ATTR_OPTIONS]
# if disabled
if isinstance(new_raw_schema, bool):
return True
# merge options
options = {**self.persist[ATTR_OPTIONS], **default_options}
# create voluptuous
new_schema = vol.Schema(vol.All(dict, validate_options(new_raw_schema)))
# validate
try:
new_schema(options)
except vol.Invalid:
_LOGGER.warning("Add-on %s new schema is not compatible", self.slug)
return False
return True
async def state(self) -> str:
"""Return running state of add-on."""
if await self.instance.is_running():
return STATE_STARTED
return STATE_STOPPED
async def start(self) -> None:
"""Set options and start add-on."""
if await self.instance.is_running():
_LOGGER.warning("%s already running!", self.slug)
return
# Access Token
self.persist[ATTR_ACCESS_TOKEN] = secrets.token_hex(56)
self.save_persist()
# Options
self.write_options()
# Sound
if self.with_audio:
self.write_asound()
try:
await self.instance.run()
except DockerAPIError:
raise AddonsError() from None
async def stop(self) -> None:
"""Stop add-on."""
try:
return await self.instance.stop()
except DockerAPIError:
raise AddonsError() from None
async def restart(self) -> None:
"""Restart add-on."""
with suppress(AddonsError):
await self.stop()
await self.start()
def logs(self) -> Awaitable[bytes]:
"""Return add-ons log output.
Return a coroutine.
"""
return self.instance.logs()
async def stats(self) -> DockerStats:
"""Return stats of container."""
try:
return await self.instance.stats()
except DockerAPIError:
raise AddonsError() from None
async def write_stdin(self, data):
"""Write data to add-on stdin.
Return a coroutine.
"""
if not self.with_stdin:
_LOGGER.error("Add-on don't support write to stdin!")
raise AddonsNotSupportedError()
try:
return await self.instance.write_stdin(data)
except DockerAPIError:
raise AddonsError() from None
async def snapshot(self, tar_file: tarfile.TarFile) -> None:
"""Snapshot state of an add-on."""
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp:
# store local image
if self.need_build:
try:
await self.instance.export_image(Path(temp, "image.tar"))
except DockerAPIError:
raise AddonsError() from None
data = {
ATTR_USER: self.persist,
ATTR_SYSTEM: self.data,
ATTR_VERSION: self.version,
ATTR_STATE: await self.state(),
}
# Store local configs/state
try:
write_json_file(Path(temp, "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")
try:
self.sys_host.apparmor.backup_profile(self.slug, profile)
except HostAppArmorError:
_LOGGER.error("Can't backup AppArmor profile")
raise AddonsError() from None
# write into tarfile
def _write_tarfile():
"""Write tar inside loop."""
with tar_file as snapshot:
snapshot.add(temp, arcname=".")
snapshot.add(self.path_data, arcname="data")
try:
_LOGGER.info("Build snapshot for add-on %s", self.slug)
await self.sys_run_in_executor(_write_tarfile)
except (tarfile.TarError, OSError) as err:
_LOGGER.error("Can't write tarfile %s: %s", tar_file, err)
raise AddonsError() from None
_LOGGER.info("Finish snapshot for addon %s", self.slug)
async def restore(self, tar_file: tarfile.TarFile) -> None:
"""Restore state of an add-on."""
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp:
# extract snapshot
def _extract_tarfile():
"""Extract tar snapshot."""
with tar_file as snapshot:
snapshot.extractall(path=Path(temp))
try:
await self.sys_run_in_executor(_extract_tarfile)
except tarfile.TarError as err:
_LOGGER.error("Can't read tarfile %s: %s", tar_file, err)
raise AddonsError() from None
# Read snapshot data
try:
data = read_json_file(Path(temp, "addon.json"))
except JsonFileError:
raise AddonsError() from None
# Validate
try:
data = SCHEMA_ADDON_SNAPSHOT(data)
except vol.Invalid as err:
_LOGGER.error(
"Can't validate %s, snapshot data: %s",
self.slug,
humanize_error(data, err),
)
raise AddonsError() from None
# If available
if not self._available(data[ATTR_SYSTEM]):
_LOGGER.error("Add-on %s is not available for this Platform", self.slug)
raise AddonsNotSupportedError()
# Restore local add-on informations
_LOGGER.info("Restore config for addon %s", self.slug)
restore_image = self._image(data[ATTR_SYSTEM])
self.sys_addons.data.restore(
self.slug, data[ATTR_USER], data[ATTR_SYSTEM], restore_image
)
# Check version / restore image
version = data[ATTR_VERSION]
if not await self.instance.exists():
_LOGGER.info("Restore/Install image for addon %s", self.slug)
image_file = Path(temp, "image.tar")
if image_file.is_file():
with suppress(DockerAPIError):
await self.instance.import_image(image_file)
else:
with suppress(DockerAPIError):
await self.instance.install(version, restore_image)
await self.instance.cleanup()
elif self.instance.version != version or self.legacy:
_LOGGER.info("Restore/Update image for addon %s", self.slug)
with suppress(DockerAPIError):
await self.instance.update(version, restore_image)
else:
with suppress(DockerAPIError):
await self.instance.stop()
# Restore data
def _restore_data():
"""Restore data."""
shutil.copytree(str(Path(temp, "data")), str(self.path_data))
_LOGGER.info("Restore data for addon %s", self.slug)
if self.path_data.is_dir():
await remove_data(self.path_data)
try:
await self.sys_run_in_executor(_restore_data)
except shutil.Error as err:
_LOGGER.error("Can't restore origin data: %s", err)
raise AddonsError() from None
# Restore AppArmor
profile_file = Path(temp, "apparmor.txt")
if profile_file.exists():
try:
await self.sys_host.apparmor.load_profile(self.slug, profile_file)
except HostAppArmorError:
_LOGGER.error("Can't restore AppArmor profile")
raise AddonsError() from None
# Run add-on
if data[ATTR_STATE] == STATE_STARTED:
return await self.start()
_LOGGER.info("Finish restore for add-on %s", self.slug)

79
hassio/addons/build.py Normal file
View File

@@ -0,0 +1,79 @@
"""Hass.io add-on build environment."""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Dict
from ..const import ATTR_ARGS, ATTR_BUILD_FROM, ATTR_SQUASH, META_ADDON
from ..coresys import CoreSys, CoreSysAttributes
from ..utils.json import JsonConfig
from .validate import SCHEMA_BUILD_CONFIG
if TYPE_CHECKING:
from . import AnyAddon
class AddonBuild(JsonConfig, CoreSysAttributes):
"""Handle build options for add-ons."""
def __init__(self, coresys: CoreSys, addon: AnyAddon) -> None:
"""Initialize Hass.io add-on builder."""
self.coresys: CoreSys = coresys
self.addon = addon
super().__init__(
Path(self.addon.path_location, "build.json"), SCHEMA_BUILD_CONFIG
)
def save_data(self):
"""Ignore save function."""
raise RuntimeError()
@property
def base_image(self) -> str:
"""Base images for this add-on."""
return self._data[ATTR_BUILD_FROM].get(
self.sys_arch.default, f"homeassistant/{self.sys_arch.default}-base:latest"
)
@property
def squash(self) -> bool:
"""Return True or False if squash is active."""
return self._data[ATTR_SQUASH]
@property
def additional_args(self) -> Dict[str, str]:
"""Return additional Docker build arguments."""
return self._data[ATTR_ARGS]
def get_docker_args(self, version):
"""Create a dict with Docker build arguments."""
args = {
"path": str(self.addon.path_location),
"tag": f"{self.addon.image}:{version}",
"pull": True,
"forcerm": True,
"squash": self.squash,
"labels": {
"io.hass.version": version,
"io.hass.arch": self.sys_arch.default,
"io.hass.type": META_ADDON,
"io.hass.name": self._fix_label("name"),
"io.hass.description": self._fix_label("description"),
},
"buildargs": {
"BUILD_FROM": self.base_image,
"BUILD_VERSION": version,
"BUILD_ARCH": self.sys_arch.default,
**self.additional_args,
},
}
if self.addon.url:
args["labels"]["io.hass.url"] = self.addon.url
return args
def _fix_label(self, label_name: str) -> str:
"""Remove characters they are not supported."""
label = getattr(self.addon, label_name, "")
return label.replace("'", "")

View File

@@ -1,14 +0,0 @@
{
"local": {
"slug": "local",
"name": "Local Add-Ons",
"url": "https://home-assistant.io/hassio",
"maintainer": "By our self"
},
"core": {
"slug": "core",
"name": "Built-in Add-Ons",
"url": "https://home-assistant.io/addons",
"maintainer": "Home Assistant authors"
}
}

View File

@@ -1,361 +1,73 @@
"""Init file for HassIO addons."""
import copy
"""Init file for Hass.io add-on data."""
from copy import deepcopy
import logging
import json
from pathlib import Path, PurePath
from typing import Any, Dict
import voluptuous as vol
from voluptuous.humanize import humanize_error
from .util import extract_hash_from_path
from .validate import (
validate_options, SCHEMA_ADDON_CONFIG, SCHEMA_REPOSITORY_CONFIG)
from ..const import (
FILE_HASSIO_ADDONS, ATTR_NAME, ATTR_VERSION, ATTR_SLUG, ATTR_DESCRIPTON,
ATTR_STARTUP, ATTR_BOOT, ATTR_MAP, ATTR_OPTIONS, ATTR_PORTS, BOOT_AUTO,
DOCKER_REPO, ATTR_SCHEMA, ATTR_IMAGE, MAP_CONFIG, MAP_SSL, MAP_ADDONS,
MAP_BACKUP, ATTR_REPOSITORY, ATTR_URL, ATTR_ARCH)
from ..config import Config
from ..tools import read_json_file, write_json_file
ATTR_IMAGE,
ATTR_OPTIONS,
ATTR_SYSTEM,
ATTR_USER,
ATTR_VERSION,
FILE_HASSIO_ADDONS,
)
from ..coresys import CoreSys, CoreSysAttributes
from ..utils.json import JsonConfig
from ..store.addon import AddonStore
from .addon import Addon
from .validate import SCHEMA_ADDONS_FILE
_LOGGER = logging.getLogger(__name__)
SYSTEM = 'system'
USER = 'user'
REPOSITORY_CORE = 'core'
REPOSITORY_LOCAL = 'local'
Config = Dict[str, Any]
class AddonsData(Config):
"""Hold data for addons inside HassIO."""
class AddonsData(JsonConfig, CoreSysAttributes):
"""Hold data for installed Add-ons inside Hass.io."""
def __init__(self, config):
def __init__(self, coresys: CoreSys):
"""Initialize data holder."""
super().__init__(FILE_HASSIO_ADDONS)
self.config = config
self._system_data = self._data.get(SYSTEM, {})
self._user_data = self._data.get(USER, {})
self._addons_cache = {}
self._repositories_data = {}
self.arch = None
def save(self):
"""Store data to config file."""
self._data = {
USER: self._user_data,
SYSTEM: self._system_data,
}
super().save()
def read_data_from_repositories(self):
"""Read data from addons repository."""
self._addons_cache = {}
self._repositories_data = {}
# read core repository
self._read_addons_folder(
self.config.path_addons_core, REPOSITORY_CORE)
# read local repository
self._read_addons_folder(
self.config.path_addons_local, REPOSITORY_LOCAL)
# add built-in repositories information
self._set_builtin_repositories()
# read custom git repositories
for repository_element in self.config.path_addons_git.iterdir():
if repository_element.is_dir():
self._read_git_repository(repository_element)
def _read_git_repository(self, path):
"""Process a custom repository folder."""
slug = extract_hash_from_path(path)
repository_info = {ATTR_SLUG: slug}
# exists repository json
repository_file = Path(path, "repository.json")
try:
repository_info.update(SCHEMA_REPOSITORY_CONFIG(
read_json_file(repository_file)
))
except OSError:
_LOGGER.warning("Can't read repository information from %s",
repository_file)
return
except vol.Invalid:
_LOGGER.warning("Repository parse error %s", repository_file)
return
# process data
self._repositories_data[slug] = repository_info
self._read_addons_folder(path, slug)
def _read_addons_folder(self, path, repository):
"""Read data from addons folder."""
for addon in path.glob("**/config.json"):
try:
addon_config = read_json_file(addon)
# validate
addon_config = SCHEMA_ADDON_CONFIG(addon_config)
# Generate slug
addon_slug = "{}_{}".format(
repository, addon_config[ATTR_SLUG])
# store
addon_config[ATTR_REPOSITORY] = repository
self._addons_cache[addon_slug] = addon_config
except OSError:
_LOGGER.warning("Can't read %s", addon)
except vol.Invalid as ex:
_LOGGER.warning("Can't read %s -> %s", addon,
humanize_error(addon_config, ex))
def _set_builtin_repositories(self):
"""Add local built-in repository into dataset."""
try:
builtin_file = Path(__file__).parent.joinpath('built-in.json')
builtin_data = read_json_file(builtin_file)
except (OSError, json.JSONDecodeError) as err:
_LOGGER.warning("Can't read built-in.json -> %s", err)
return
# if core addons are available
for data in self._addons_cache.values():
if data[ATTR_REPOSITORY] == REPOSITORY_CORE:
self._repositories_data[REPOSITORY_CORE] = \
builtin_data[REPOSITORY_CORE]
break
# if local addons are available
for data in self._addons_cache.values():
if data[ATTR_REPOSITORY] == REPOSITORY_LOCAL:
self._repositories_data[REPOSITORY_LOCAL] = \
builtin_data[REPOSITORY_LOCAL]
break
def merge_update_config(self):
"""Update local config if they have update.
It need to be the same version as the local version is.
"""
have_change = False
for addon, data in self._system_data.items():
# detached
if addon not in self._addons_cache:
continue
cache = self._addons_cache[addon]
if data[ATTR_VERSION] == cache[ATTR_VERSION]:
if data != cache:
self._system_data[addon] = copy.deepcopy(cache)
have_change = True
if have_change:
self.save()
super().__init__(FILE_HASSIO_ADDONS, SCHEMA_ADDONS_FILE)
self.coresys: CoreSys = coresys
@property
def list_installed(self):
"""Return a list of installed addons."""
return set(self._system_data.keys())
def user(self):
"""Return local add-on user data."""
return self._data[ATTR_USER]
@property
def data_all(self):
"""Return a dict of all addons."""
return {
**self._system_data,
**self._addons_cache
}
def system(self):
"""Return local add-on data."""
return self._data[ATTR_SYSTEM]
@property
def data_installed(self):
"""Return a dict of installed addons."""
return self._system_data.copy()
def list_startup(self, start_type):
"""Get list of installed addon with need start by type."""
addon_list = set()
for addon in self._system_data.keys():
if self.get_boot(addon) != BOOT_AUTO:
continue
try:
if self._system_data[addon][ATTR_STARTUP] == start_type:
addon_list.add(addon)
except KeyError:
_LOGGER.warning("Orphaned addon detect %s", addon)
continue
return addon_list
@property
def list_detached(self):
"""Return local addons they not support from repo."""
addon_list = set()
for addon in self._system_data.keys():
if addon not in self._addons_cache:
addon_list.add(addon)
return addon_list
@property
def list_repositories(self):
"""Return list of addon repositories."""
return list(self._repositories_data.values())
def exists_addon(self, addon):
"""Return True if a addon exists."""
return addon in self._addons_cache or addon in self._system_data
def is_installed(self, addon):
"""Return True if a addon is installed."""
return addon in self._system_data
def version_installed(self, addon):
"""Return installed version."""
return self._user_data.get(addon, {}).get(ATTR_VERSION)
def set_addon_install(self, addon, version):
def install(self, addon: AddonStore) -> None:
"""Set addon as installed."""
self._system_data[addon] = copy.deepcopy(self._addons_cache[addon])
self._user_data[addon] = {
self.system[addon.slug] = deepcopy(addon.data)
self.user[addon.slug] = {
ATTR_OPTIONS: {},
ATTR_VERSION: version,
ATTR_VERSION: addon.version,
ATTR_IMAGE: addon.image,
}
self.save()
self.save_data()
def set_addon_uninstall(self, addon):
"""Set addon as uninstalled."""
self._system_data.pop(addon, None)
self._user_data.pop(addon, None)
self.save()
def uninstall(self, addon: Addon) -> None:
"""Set add-on as uninstalled."""
self.system.pop(addon.slug, None)
self.user.pop(addon.slug, None)
self.save_data()
def set_addon_update(self, addon, version):
"""Update version of addon."""
self._system_data[addon] = copy.deepcopy(self._addons_cache[addon])
self._user_data[addon][ATTR_VERSION] = version
self.save()
def update(self, addon: AddonStore) -> None:
"""Update version of add-on."""
self.system[addon.slug] = deepcopy(addon.data)
self.user[addon.slug].update(
{ATTR_VERSION: addon.version, ATTR_IMAGE: addon.image}
)
self.save_data()
def set_options(self, addon, options):
"""Store user addon options."""
self._user_data[addon][ATTR_OPTIONS] = copy.deepcopy(options)
self.save()
def restore(self, slug: str, user: Config, system: Config, image: str) -> None:
"""Restore data to add-on."""
self.user[slug] = deepcopy(user)
self.system[slug] = deepcopy(system)
def set_boot(self, addon, boot):
"""Store user boot options."""
self._user_data[addon][ATTR_BOOT] = boot
self.save()
def get_options(self, addon):
"""Return options with local changes."""
return {
**self._system_data[addon][ATTR_OPTIONS],
**self._user_data[addon][ATTR_OPTIONS],
}
def get_boot(self, addon):
"""Return boot config with prio local settings."""
if ATTR_BOOT in self._user_data[addon]:
return self._user_data[addon][ATTR_BOOT]
return self._system_data[addon][ATTR_BOOT]
def get_name(self, addon):
"""Return name of addon."""
return self._system_data[addon][ATTR_NAME]
def get_description(self, addon):
"""Return description of addon."""
return self._system_data[addon][ATTR_DESCRIPTON]
def get_repository(self, addon):
"""Return repository of addon."""
return self._system_data[addon][ATTR_REPOSITORY]
def get_last_version(self, addon):
"""Return version of addon."""
if addon not in self._addons_cache:
return self.version_installed(addon)
return self._addons_cache[addon][ATTR_VERSION]
def get_ports(self, addon):
"""Return ports of addon."""
return self._system_data[addon].get(ATTR_PORTS)
def get_url(self, addon):
"""Return url of addon."""
return self._system_data[addon].get(ATTR_URL)
def get_arch(self, addon):
"""Return list of supported arch."""
if addon not in self._addons_cache:
return self._system_data[addon][ATTR_ARCH]
return self._addons_cache[addon][ATTR_ARCH]
def get_image(self, addon):
"""Return image name of addon."""
addon_data = self._system_data.get(
addon, self._addons_cache.get(addon))
if ATTR_IMAGE not in addon_data:
return "{}/{}-addon-{}".format(
DOCKER_REPO, self.arch, addon_data[ATTR_SLUG])
return addon_data[ATTR_IMAGE].format(arch=self.arch)
def map_config(self, addon):
"""Return True if config map is needed."""
return MAP_CONFIG in self._system_data[addon][ATTR_MAP]
def map_ssl(self, addon):
"""Return True if ssl map is needed."""
return MAP_SSL in self._system_data[addon][ATTR_MAP]
def map_addons(self, addon):
"""Return True if addons map is needed."""
return MAP_ADDONS in self._system_data[addon][ATTR_MAP]
def map_backup(self, addon):
"""Return True if backup map is needed."""
return MAP_BACKUP in self._system_data[addon][ATTR_MAP]
def path_data(self, addon):
"""Return addon data path inside supervisor."""
return Path(self.config.path_addons_data, addon)
def path_extern_data(self, addon):
"""Return addon data path external for docker."""
return str(PurePath(self.config.path_extern_addons_data, addon))
def path_addon_options(self, addon):
"""Return path to addons options."""
return Path(self.path_data(addon), "options.json")
def write_addon_options(self, addon):
"""Return True if addon options is written to data."""
schema = self.get_schema(addon)
options = self.get_options(addon)
try:
schema(options)
return write_json_file(self.path_addon_options(addon), options)
except vol.Invalid as ex:
_LOGGER.error("Addon %s have wrong options -> %s", addon,
humanize_error(options, ex))
return False
def get_schema(self, addon):
"""Create a schema for addon options."""
raw_schema = self._system_data[addon][ATTR_SCHEMA]
schema = vol.Schema(vol.All(dict, validate_options(raw_schema)))
return schema
self.user[slug][ATTR_IMAGE] = image
self.save_data()

View File

@@ -1,107 +0,0 @@
"""Init file for HassIO addons git."""
import asyncio
import logging
from pathlib import Path
import shutil
import git
from .util import get_hash_from_repository
from ..const import URL_HASSIO_ADDONS
_LOGGER = logging.getLogger(__name__)
class AddonsRepo(object):
"""Manage addons git repo."""
def __init__(self, config, loop, path, url):
"""Initialize git base wrapper."""
self.config = config
self.loop = loop
self.repo = None
self.path = path
self.url = url
self._lock = asyncio.Lock(loop=loop)
async def load(self):
"""Init git addon repo."""
if not self.path.is_dir():
return await self.clone()
async with self._lock:
try:
_LOGGER.info("Load addon %s repository", self.path)
self.repo = await self.loop.run_in_executor(
None, git.Repo, str(self.path))
except (git.InvalidGitRepositoryError, git.NoSuchPathError,
git.GitCommandError) as err:
_LOGGER.error("Can't load %s repo: %s.", self.path, err)
return False
return True
async def clone(self):
"""Clone git addon repo."""
async with self._lock:
try:
_LOGGER.info("Clone addon %s repository", self.url)
self.repo = await self.loop.run_in_executor(
None, git.Repo.clone_from, self.url, str(self.path))
except (git.InvalidGitRepositoryError, git.NoSuchPathError,
git.GitCommandError) as err:
_LOGGER.error("Can't clone %s repo: %s.", self.url, err)
return False
return True
async def pull(self):
"""Pull git addon repo."""
if self._lock.locked():
_LOGGER.warning("It is already a task in progress.")
return False
async with self._lock:
try:
_LOGGER.info("Pull addon %s repository", self.url)
await self.loop.run_in_executor(
None, self.repo.remotes.origin.pull)
except (git.InvalidGitRepositoryError, git.NoSuchPathError,
git.exc.GitCommandError) as err:
_LOGGER.error("Can't pull %s repo: %s.", self.url, err)
return False
return True
class AddonsRepoHassIO(AddonsRepo):
"""HassIO addons repository."""
def __init__(self, config, loop):
"""Initialize git hassio addon repository."""
super().__init__(
config, loop, config.path_addons_core, URL_HASSIO_ADDONS)
class AddonsRepoCustom(AddonsRepo):
"""Custom addons repository."""
def __init__(self, config, loop, url):
"""Initialize git hassio addon repository."""
path = Path(config.path_addons_git, get_hash_from_repository(url))
super().__init__(config, loop, path, url)
def remove(self):
"""Remove a custom addon."""
if self.path.is_dir():
_LOGGER.info("Remove custom addon repository %s", self.url)
def log_err(funct, path, _):
"""Log error."""
_LOGGER.warning("Can't remove %s", path)
shutil.rmtree(str(self.path), onerror=log_err)

514
hassio/addons/model.py Normal file
View File

@@ -0,0 +1,514 @@
"""Init file for Hass.io add-ons."""
from distutils.version import StrictVersion
from pathlib import Path
from typing import Any, Awaitable, Dict, List, Optional
import voluptuous as vol
from ..const import (
ATTR_APPARMOR,
ATTR_ARCH,
ATTR_AUDIO,
ATTR_AUTH_API,
ATTR_AUTO_UART,
ATTR_BOOT,
ATTR_DESCRIPTON,
ATTR_DEVICES,
ATTR_DEVICETREE,
ATTR_DISCOVERY,
ATTR_DOCKER_API,
ATTR_ENVIRONMENT,
ATTR_FULL_ACCESS,
ATTR_GPIO,
ATTR_HASSIO_API,
ATTR_HASSIO_ROLE,
ATTR_HOMEASSISTANT,
ATTR_HOMEASSISTANT_API,
ATTR_HOST_DBUS,
ATTR_HOST_IPC,
ATTR_HOST_NETWORK,
ATTR_HOST_PID,
ATTR_IMAGE,
ATTR_INGRESS,
ATTR_KERNEL_MODULES,
ATTR_LEGACY,
ATTR_LOCATON,
ATTR_MACHINE,
ATTR_MAP,
ATTR_NAME,
ATTR_OPTIONS,
ATTR_PANEL_ADMIN,
ATTR_PANEL_ICON,
ATTR_PANEL_TITLE,
ATTR_PORTS,
ATTR_PORTS_DESCRIPTION,
ATTR_PRIVILEGED,
ATTR_REPOSITORY,
ATTR_SCHEMA,
ATTR_SERVICES,
ATTR_SLUG,
ATTR_STARTUP,
ATTR_STDIN,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_UDEV,
ATTR_URL,
ATTR_VERSION,
ATTR_WEBUI,
SECURITY_DEFAULT,
SECURITY_DISABLE,
SECURITY_PROFILE,
)
from ..coresys import CoreSysAttributes
from .validate import RE_SERVICE, RE_VOLUME, validate_options
Data = Dict[str, Any]
class AddonModel(CoreSysAttributes):
"""Add-on Data layout."""
slug: str = None
@property
def data(self) -> Data:
"""Return Add-on config/data."""
raise NotImplementedError()
@property
def is_installed(self) -> bool:
"""Return True if an add-on is installed."""
raise NotImplementedError()
@property
def is_detached(self) -> bool:
"""Return True if add-on is detached."""
raise NotImplementedError()
@property
def available(self) -> bool:
"""Return True if this add-on is available on this platform."""
return self._available(self.data)
@property
def options(self) -> Dict[str, Any]:
"""Return options with local changes."""
return self.data[ATTR_OPTIONS]
@property
def boot(self) -> bool:
"""Return boot config with prio local settings."""
return self.data[ATTR_BOOT]
@property
def auto_update(self) -> Optional[bool]:
"""Return if auto update is enable."""
return None
@property
def name(self) -> str:
"""Return name of add-on."""
return self.data[ATTR_NAME]
@property
def hostname(self) -> str:
"""Return slug/id of add-on."""
return self.slug.replace("_", "-")
@property
def dns(self) -> List[str]:
"""Return list of DNS name for that add-on."""
return []
@property
def timeout(self) -> int:
"""Return timeout of addon for docker stop."""
return self.data[ATTR_TIMEOUT]
@property
def uuid(self) -> Optional[str]:
"""Return an API token for this add-on."""
return None
@property
def hassio_token(self) -> Optional[str]:
"""Return access token for Hass.io API."""
return None
@property
def ingress_token(self) -> Optional[str]:
"""Return access token for Hass.io API."""
return None
@property
def ingress_entry(self) -> Optional[str]:
"""Return ingress external URL."""
return None
@property
def description(self) -> str:
"""Return description of add-on."""
return self.data[ATTR_DESCRIPTON]
@property
def long_description(self) -> Optional[str]:
"""Return README.md as long_description."""
readme = Path(self.path_location, "README.md")
# If readme not exists
if not readme.exists():
return None
# Return data
with readme.open("r") as readme_file:
return readme_file.read()
@property
def repository(self) -> str:
"""Return repository of add-on."""
return self.data[ATTR_REPOSITORY]
@property
def latest_version(self) -> str:
"""Return latest version of add-on."""
return self.data[ATTR_VERSION]
@property
def version(self) -> str:
"""Return version of add-on."""
return self.data[ATTR_VERSION]
@property
def protected(self) -> bool:
"""Return if add-on is in protected mode."""
return True
@property
def startup(self) -> Optional[str]:
"""Return startup type of add-on."""
return self.data.get(ATTR_STARTUP)
@property
def services_role(self) -> Dict[str, str]:
"""Return dict of services with rights."""
services_list = self.data.get(ATTR_SERVICES, [])
services = {}
for data in services_list:
service = RE_SERVICE.match(data)
services[service.group("service")] = service.group("rights")
return services
@property
def discovery(self) -> List[str]:
"""Return list of discoverable components/platforms."""
return self.data.get(ATTR_DISCOVERY, [])
@property
def ports_description(self) -> Optional[Dict[str, str]]:
"""Return descriptions of ports."""
return self.data.get(ATTR_PORTS_DESCRIPTION)
@property
def ports(self) -> Optional[Dict[str, Optional[int]]]:
"""Return ports of add-on."""
return self.data.get(ATTR_PORTS)
@property
def ingress_url(self) -> Optional[str]:
"""Return URL to ingress url."""
return None
@property
def webui(self) -> Optional[str]:
"""Return URL to webui or None."""
return self.data.get(ATTR_WEBUI)
@property
def ingress_port(self) -> Optional[int]:
"""Return Ingress port."""
return None
@property
def panel_icon(self) -> str:
"""Return panel icon for Ingress frame."""
return self.data[ATTR_PANEL_ICON]
@property
def panel_title(self) -> str:
"""Return panel icon for Ingress frame."""
return self.data.get(ATTR_PANEL_TITLE, self.name)
@property
def panel_admin(self) -> str:
"""Return panel icon for Ingress frame."""
return self.data[ATTR_PANEL_ADMIN]
@property
def host_network(self) -> bool:
"""Return True if add-on run on host network."""
return self.data[ATTR_HOST_NETWORK]
@property
def host_pid(self) -> bool:
"""Return True if add-on run on host PID namespace."""
return self.data[ATTR_HOST_PID]
@property
def host_ipc(self) -> bool:
"""Return True if add-on run on host IPC namespace."""
return self.data[ATTR_HOST_IPC]
@property
def host_dbus(self) -> bool:
"""Return True if add-on run on host D-BUS."""
return self.data[ATTR_HOST_DBUS]
@property
def devices(self) -> Optional[List[str]]:
"""Return devices of add-on."""
return self.data.get(ATTR_DEVICES, [])
@property
def auto_uart(self) -> bool:
"""Return True if we should map all UART device."""
return self.data[ATTR_AUTO_UART]
@property
def tmpfs(self) -> Optional[str]:
"""Return tmpfs of add-on."""
return self.data.get(ATTR_TMPFS)
@property
def environment(self) -> Optional[Dict[str, str]]:
"""Return environment of add-on."""
return self.data.get(ATTR_ENVIRONMENT)
@property
def privileged(self) -> List[str]:
"""Return list of privilege."""
return self.data.get(ATTR_PRIVILEGED, [])
@property
def apparmor(self) -> str:
"""Return True if AppArmor is enabled."""
if not self.data.get(ATTR_APPARMOR):
return SECURITY_DISABLE
elif self.sys_host.apparmor.exists(self.slug):
return SECURITY_PROFILE
return SECURITY_DEFAULT
@property
def legacy(self) -> bool:
"""Return if the add-on don't support Home Assistant labels."""
return self.data[ATTR_LEGACY]
@property
def access_docker_api(self) -> bool:
"""Return if the add-on need read-only Docker API access."""
return self.data[ATTR_DOCKER_API]
@property
def access_hassio_api(self) -> bool:
"""Return True if the add-on access to Hass.io REASTful API."""
return self.data[ATTR_HASSIO_API]
@property
def access_homeassistant_api(self) -> bool:
"""Return True if the add-on access to Home Assistant API proxy."""
return self.data[ATTR_HOMEASSISTANT_API]
@property
def hassio_role(self) -> str:
"""Return Hass.io role for API."""
return self.data[ATTR_HASSIO_ROLE]
@property
def with_stdin(self) -> bool:
"""Return True if the add-on access use stdin input."""
return self.data[ATTR_STDIN]
@property
def with_ingress(self) -> bool:
"""Return True if the add-on access support ingress."""
return self.data[ATTR_INGRESS]
@property
def ingress_panel(self) -> Optional[bool]:
"""Return True if the add-on access support ingress."""
return None
@property
def with_gpio(self) -> bool:
"""Return True if the add-on access to GPIO interface."""
return self.data[ATTR_GPIO]
@property
def with_udev(self) -> bool:
"""Return True if the add-on have his own udev."""
return self.data[ATTR_UDEV]
@property
def with_kernel_modules(self) -> bool:
"""Return True if the add-on access to kernel modules."""
return self.data[ATTR_KERNEL_MODULES]
@property
def with_full_access(self) -> bool:
"""Return True if the add-on want full access to hardware."""
return self.data[ATTR_FULL_ACCESS]
@property
def with_devicetree(self) -> bool:
"""Return True if the add-on read access to devicetree."""
return self.data[ATTR_DEVICETREE]
@property
def access_auth_api(self) -> bool:
"""Return True if the add-on access to login/auth backend."""
return self.data[ATTR_AUTH_API]
@property
def with_audio(self) -> bool:
"""Return True if the add-on access to audio."""
return self.data[ATTR_AUDIO]
@property
def homeassistant_version(self) -> Optional[str]:
"""Return min Home Assistant version they needed by Add-on."""
return self.data.get(ATTR_HOMEASSISTANT)
@property
def url(self) -> Optional[str]:
"""Return URL of add-on."""
return self.data.get(ATTR_URL)
@property
def with_icon(self) -> bool:
"""Return True if an icon exists."""
return self.path_icon.exists()
@property
def with_logo(self) -> bool:
"""Return True if a logo exists."""
return self.path_logo.exists()
@property
def with_changelog(self) -> bool:
"""Return True if a changelog exists."""
return self.path_changelog.exists()
@property
def supported_arch(self) -> List[str]:
"""Return list of supported arch."""
return self.data[ATTR_ARCH]
@property
def supported_machine(self) -> List[str]:
"""Return list of supported machine."""
return self.data.get(ATTR_MACHINE, [])
@property
def image(self) -> str:
"""Generate image name from data."""
return self._image(self.data)
@property
def need_build(self) -> bool:
"""Return True if this add-on need a local build."""
return ATTR_IMAGE not in self.data
@property
def map_volumes(self) -> Dict[str, str]:
"""Return a dict of {volume: policy} from add-on."""
volumes = {}
for volume in self.data[ATTR_MAP]:
result = RE_VOLUME.match(volume)
volumes[result.group(1)] = result.group(2) or "ro"
return volumes
@property
def path_location(self) -> Path:
"""Return path to this add-on."""
return Path(self.data[ATTR_LOCATON])
@property
def path_icon(self) -> Path:
"""Return path to add-on icon."""
return Path(self.path_location, "icon.png")
@property
def path_logo(self) -> Path:
"""Return path to add-on logo."""
return Path(self.path_location, "logo.png")
@property
def path_changelog(self) -> Path:
"""Return path to add-on changelog."""
return Path(self.path_location, "CHANGELOG.md")
@property
def path_apparmor(self) -> Path:
"""Return path to custom AppArmor profile."""
return Path(self.path_location, "apparmor.txt")
@property
def schema(self) -> vol.Schema:
"""Create a schema for add-on options."""
raw_schema = self.data[ATTR_SCHEMA]
if isinstance(raw_schema, bool):
return vol.Schema(dict)
return vol.Schema(vol.All(dict, validate_options(raw_schema)))
def __eq__(self, other):
"""Compaired add-on objects."""
if not isinstance(other, AddonModel):
return False
return self.slug == other.slug
def _available(self, config) -> bool:
"""Return True if this add-on is available on this platform."""
# Architecture
if not self.sys_arch.is_supported(config[ATTR_ARCH]):
return False
# Machine / Hardware
machine = config.get(ATTR_MACHINE)
if machine and self.sys_machine not in machine:
return False
# Home Assistant
version = config.get(ATTR_HOMEASSISTANT) or self.sys_homeassistant.version
if StrictVersion(self.sys_homeassistant.version) < StrictVersion(version):
return False
return True
def _image(self, config) -> str:
"""Generate image name from data."""
# Repository with Dockerhub images
if ATTR_IMAGE in config:
arch = self.sys_arch.match(config[ATTR_ARCH])
return config[ATTR_IMAGE].format(arch=arch)
# local build
return f"{config[ATTR_REPOSITORY]}/{self.sys_arch.default}-addon-{config[ATTR_SLUG]}"
def install(self) -> Awaitable[None]:
"""Install this add-on."""
return self.sys_addons.install(self.slug)
def uninstall(self) -> Awaitable[None]:
"""Uninstall this add-on."""
return self.sys_addons.uninstall(self.slug)
def update(self) -> Awaitable[None]:
"""Update this add-on."""
return self.sys_addons.update(self.slug)
def rebuild(self) -> Awaitable[None]:
"""Rebuild this add-on."""
return self.sys_addons.rebuild(self.slug)

View File

@@ -1,26 +0,0 @@
"""Util addons functions."""
import hashlib
import re
RE_SLUGIFY = re.compile(r'[^a-z0-9_]+')
RE_SHA1 = re.compile(r"[a-f0-9]{8}")
def get_hash_from_repository(name):
"""Generate a hash from repository."""
key = name.lower().encode()
return hashlib.sha1(key).hexdigest()[:8]
def extract_hash_from_path(path):
"""Extract repo id from path."""
repo_dir = path.parts[-1]
if not RE_SHA1.match(repo_dir):
return get_hash_from_repository(repo_dir)
return repo_dir
def create_hash_index_list(name_list):
"""Create a dict with hash from repositories list."""
return {get_hash_from_repository(repo): repo for repo in name_list}

99
hassio/addons/utils.py Normal file
View File

@@ -0,0 +1,99 @@
"""Util add-ons functions."""
from __future__ import annotations
import asyncio
import logging
from pathlib import Path
from typing import TYPE_CHECKING
from ..const import (
PRIVILEGED_DAC_READ_SEARCH,
PRIVILEGED_NET_ADMIN,
PRIVILEGED_SYS_ADMIN,
PRIVILEGED_SYS_MODULE,
PRIVILEGED_SYS_PTRACE,
PRIVILEGED_SYS_RAWIO,
ROLE_ADMIN,
ROLE_MANAGER,
SECURITY_DISABLE,
SECURITY_PROFILE,
)
if TYPE_CHECKING:
from .model import AddonModel
_LOGGER = logging.getLogger(__name__)
def rating_security(addon: AddonModel) -> int:
"""Return 1-6 for security rating.
1 = not secure
6 = high secure
"""
rating = 5
# AppArmor
if addon.apparmor == SECURITY_DISABLE:
rating += -1
elif addon.apparmor == SECURITY_PROFILE:
rating += 1
# Home Assistant Login
if addon.access_auth_api:
rating += 1
# Privileged options
if any(
privilege in addon.privileged
for privilege in (
PRIVILEGED_NET_ADMIN,
PRIVILEGED_SYS_ADMIN,
PRIVILEGED_SYS_RAWIO,
PRIVILEGED_SYS_PTRACE,
PRIVILEGED_SYS_MODULE,
PRIVILEGED_DAC_READ_SEARCH,
)
):
rating += -1
# API Hass.io role
if addon.hassio_role == ROLE_MANAGER:
rating += -1
elif addon.hassio_role == ROLE_ADMIN:
rating += -2
# Not secure Networking
if addon.host_network:
rating += -1
# Insecure PID namespace
if addon.host_pid:
rating += -2
# Full Access
if addon.with_full_access:
rating += -2
# Docker Access
if addon.access_docker_api:
rating = 1
return max(min(6, rating), 1)
async def remove_data(folder: Path) -> None:
"""Remove folder and reset privileged."""
try:
proc = await asyncio.create_subprocess_exec(
"rm", "-rf", str(folder), stdout=asyncio.subprocess.DEVNULL
)
_, error_msg = await proc.communicate()
except OSError as err:
error_msg = str(err)
else:
if proc.returncode == 0:
return
_LOGGER.error("Can't remove Add-on Data: %s", error_msg)

View File

@@ -1,132 +1,421 @@
"""Validate addons options schema."""
"""Validate add-ons options schema."""
import logging
import re
import secrets
import uuid
import voluptuous as vol
from ..const import (
ATTR_NAME, ATTR_VERSION, ATTR_SLUG, ATTR_DESCRIPTON, ATTR_STARTUP,
ATTR_BOOT, ATTR_MAP, ATTR_OPTIONS, ATTR_PORTS, STARTUP_ONCE, STARTUP_AFTER,
STARTUP_BEFORE, BOOT_AUTO, BOOT_MANUAL, ATTR_SCHEMA, ATTR_IMAGE, MAP_SSL,
MAP_CONFIG, MAP_ADDONS, MAP_BACKUP, ATTR_URL, ATTR_MAINTAINER, ATTR_ARCH,
ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64, ARCH_I386)
ARCH_ALL,
ATTR_ACCESS_TOKEN,
ATTR_APPARMOR,
ATTR_ARCH,
ATTR_ARGS,
ATTR_AUDIO,
ATTR_AUDIO_INPUT,
ATTR_AUDIO_OUTPUT,
ATTR_AUTH_API,
ATTR_AUTO_UART,
ATTR_AUTO_UPDATE,
ATTR_BOOT,
ATTR_BUILD_FROM,
ATTR_DESCRIPTON,
ATTR_DEVICES,
ATTR_DEVICETREE,
ATTR_DISCOVERY,
ATTR_DOCKER_API,
ATTR_ENVIRONMENT,
ATTR_FULL_ACCESS,
ATTR_GPIO,
ATTR_HASSIO_API,
ATTR_HASSIO_ROLE,
ATTR_HOMEASSISTANT,
ATTR_HOMEASSISTANT_API,
ATTR_HOST_DBUS,
ATTR_HOST_IPC,
ATTR_HOST_NETWORK,
ATTR_HOST_PID,
ATTR_IMAGE,
ATTR_INGRESS,
ATTR_INGRESS_ENTRY,
ATTR_INGRESS_PANEL,
ATTR_INGRESS_PORT,
ATTR_INGRESS_TOKEN,
ATTR_KERNEL_MODULES,
ATTR_LEGACY,
ATTR_LOCATON,
ATTR_MACHINE,
ATTR_MAP,
ATTR_NAME,
ATTR_NETWORK,
ATTR_OPTIONS,
ATTR_PANEL_ADMIN,
ATTR_PANEL_ICON,
ATTR_PANEL_TITLE,
ATTR_PORTS,
ATTR_PORTS_DESCRIPTION,
ATTR_PRIVILEGED,
ATTR_PROTECTED,
ATTR_REPOSITORY,
ATTR_SCHEMA,
ATTR_SERVICES,
ATTR_SLUG,
ATTR_SQUASH,
ATTR_STARTUP,
ATTR_STATE,
ATTR_STDIN,
ATTR_SYSTEM,
ATTR_TIMEOUT,
ATTR_TMPFS,
ATTR_UDEV,
ATTR_URL,
ATTR_USER,
ATTR_UUID,
ATTR_VERSION,
ATTR_WEBUI,
BOOT_AUTO,
BOOT_MANUAL,
PRIVILEGED_ALL,
ROLE_ALL,
ROLE_DEFAULT,
STARTUP_ALL,
STARTUP_APPLICATION,
STARTUP_SERVICES,
STATE_STARTED,
STATE_STOPPED,
)
from ..discovery.validate import valid_discovery_service
from ..validate import (
ALSA_DEVICE,
DOCKER_PORTS,
DOCKER_PORTS_DESCRIPTION,
NETWORK_PORT,
TOKEN,
UUID_MATCH,
)
V_STR = 'str'
V_INT = 'int'
V_FLOAT = 'float'
V_BOOL = 'bool'
V_EMAIL = 'email'
V_URL = 'url'
_LOGGER = logging.getLogger(__name__)
ADDON_ELEMENT = vol.In([V_STR, V_INT, V_FLOAT, V_BOOL, V_EMAIL, V_URL])
ARCH_ALL = [
ARCH_ARMHF, ARCH_AARCH64, ARCH_AMD64, ARCH_I386
RE_VOLUME = re.compile(r"^(config|ssl|addons|backup|share)(?::(rw|ro))?$")
RE_SERVICE = re.compile(r"^(?P<service>mqtt):(?P<rights>provide|want|need)$")
V_STR = "str"
V_INT = "int"
V_FLOAT = "float"
V_BOOL = "bool"
V_EMAIL = "email"
V_URL = "url"
V_PORT = "port"
V_MATCH = "match"
RE_SCHEMA_ELEMENT = re.compile(
r"^(?:"
r"|str|bool|email|url|port"
r"|int(?:\((?P<i_min>\d+)?,(?P<i_max>\d+)?\))?"
r"|float(?:\((?P<f_min>[\d\.]+)?,(?P<f_max>[\d\.]+)?\))?"
r"|match\((?P<match>.*)\)"
r")\??$"
)
RE_DOCKER_IMAGE = re.compile(r"^([a-zA-Z\-\.:\d{}]+/)*?([\-\w{}]+)/([\-\w{}]+)$")
RE_DOCKER_IMAGE_BUILD = re.compile(
r"^([a-zA-Z\-\.:\d{}]+/)*?([\-\w{}]+)/([\-\w{}]+)(:[\.\-\w{}]+)?$"
)
SCHEMA_ELEMENT = vol.Match(RE_SCHEMA_ELEMENT)
MACHINE_ALL = [
"intel-nuc",
"odroid-c2",
"odroid-xu",
"orangepi-prime",
"qemux86",
"qemux86-64",
"qemuarm",
"qemuarm-64",
"raspberrypi",
"raspberrypi2",
"raspberrypi3",
"raspberrypi3-64",
"raspberrypi4",
"raspberrypi4-64",
"tinker",
]
def _simple_startup(value):
"""Simple startup schema."""
if value == "before":
return STARTUP_SERVICES
if value == "after":
return STARTUP_APPLICATION
return value
# pylint: disable=no-value-for-parameter
SCHEMA_ADDON_CONFIG = vol.Schema({
vol.Required(ATTR_NAME): vol.Coerce(str),
vol.Required(ATTR_VERSION): vol.Coerce(str),
vol.Required(ATTR_SLUG): vol.Coerce(str),
vol.Required(ATTR_DESCRIPTON): vol.Coerce(str),
vol.Optional(ATTR_URL): vol.Url(),
vol.Optional(ATTR_ARCH, default=ARCH_ALL): [vol.In(ARCH_ALL)],
vol.Required(ATTR_STARTUP):
vol.In([STARTUP_BEFORE, STARTUP_AFTER, STARTUP_ONCE]),
vol.Required(ATTR_BOOT):
vol.In([BOOT_AUTO, BOOT_MANUAL]),
vol.Optional(ATTR_PORTS): dict,
vol.Optional(ATTR_MAP, default=[]): [
vol.In([MAP_CONFIG, MAP_SSL, MAP_ADDONS, MAP_BACKUP])
],
vol.Required(ATTR_OPTIONS): dict,
vol.Required(ATTR_SCHEMA): {
vol.Coerce(str): vol.Any(ADDON_ELEMENT, [
vol.Any(ADDON_ELEMENT, {vol.Coerce(str): ADDON_ELEMENT})
])
SCHEMA_ADDON_CONFIG = vol.Schema(
{
vol.Required(ATTR_NAME): vol.Coerce(str),
vol.Required(ATTR_VERSION): vol.Coerce(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_URL): vol.Url(),
vol.Required(ATTR_STARTUP): vol.All(_simple_startup, vol.In(STARTUP_ALL)),
vol.Required(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]),
vol.Optional(ATTR_PORTS): DOCKER_PORTS,
vol.Optional(ATTR_PORTS_DESCRIPTION): DOCKER_PORTS_DESCRIPTION,
vol.Optional(ATTR_WEBUI): vol.Match(
r"^(?:https?|\[PROTO:\w+\]):\/\/\[HOST\]:\[PORT:\d+\].*$"
),
vol.Optional(ATTR_INGRESS, default=False): vol.Boolean(),
vol.Optional(ATTR_INGRESS_PORT, default=8099): vol.Any(
NETWORK_PORT, vol.Equal(0)
),
vol.Optional(ATTR_INGRESS_ENTRY): vol.Coerce(str),
vol.Optional(ATTR_PANEL_ICON, default="mdi:puzzle"): vol.Coerce(str),
vol.Optional(ATTR_PANEL_TITLE): vol.Coerce(str),
vol.Optional(ATTR_PANEL_ADMIN, default=True): vol.Boolean(),
vol.Optional(ATTR_HOMEASSISTANT): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_HOST_NETWORK, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_PID, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(),
vol.Optional(ATTR_HOST_DBUS, default=False): vol.Boolean(),
vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")],
vol.Optional(ATTR_AUTO_UART, default=False): vol.Boolean(),
vol.Optional(ATTR_UDEV, default=False): vol.Boolean(),
vol.Optional(ATTR_TMPFS): vol.Match(r"^size=(\d)*[kmg](,uid=\d{1,4})?(,rw)?$"),
vol.Optional(ATTR_MAP, default=list): [vol.Match(RE_VOLUME)],
vol.Optional(ATTR_ENVIRONMENT): {vol.Match(r"\w*"): vol.Coerce(str)},
vol.Optional(ATTR_PRIVILEGED): [vol.In(PRIVILEGED_ALL)],
vol.Optional(ATTR_APPARMOR, default=True): vol.Boolean(),
vol.Optional(ATTR_FULL_ACCESS, default=False): vol.Boolean(),
vol.Optional(ATTR_AUDIO, default=False): vol.Boolean(),
vol.Optional(ATTR_GPIO, default=False): vol.Boolean(),
vol.Optional(ATTR_DEVICETREE, default=False): vol.Boolean(),
vol.Optional(ATTR_KERNEL_MODULES, default=False): vol.Boolean(),
vol.Optional(ATTR_HASSIO_API, default=False): vol.Boolean(),
vol.Optional(ATTR_HASSIO_ROLE, default=ROLE_DEFAULT): vol.In(ROLE_ALL),
vol.Optional(ATTR_HOMEASSISTANT_API, default=False): vol.Boolean(),
vol.Optional(ATTR_STDIN, default=False): vol.Boolean(),
vol.Optional(ATTR_LEGACY, default=False): vol.Boolean(),
vol.Optional(ATTR_DOCKER_API, default=False): vol.Boolean(),
vol.Optional(ATTR_AUTH_API, default=False): vol.Boolean(),
vol.Optional(ATTR_SERVICES): [vol.Match(RE_SERVICE)],
vol.Optional(ATTR_DISCOVERY): [valid_discovery_service],
vol.Required(ATTR_OPTIONS): dict,
vol.Required(ATTR_SCHEMA): vol.Any(
vol.Schema(
{
vol.Coerce(str): vol.Any(
SCHEMA_ELEMENT,
[
vol.Any(
SCHEMA_ELEMENT,
{
vol.Coerce(str): vol.Any(
SCHEMA_ELEMENT, [SCHEMA_ELEMENT]
)
},
)
],
vol.Schema(
{vol.Coerce(str): vol.Any(SCHEMA_ELEMENT, [SCHEMA_ELEMENT])}
),
)
}
),
False,
),
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.Optional(ATTR_IMAGE): vol.Match(r"\w*/\w*"),
}, extra=vol.ALLOW_EXTRA)
extra=vol.REMOVE_EXTRA,
)
# pylint: disable=no-value-for-parameter
SCHEMA_REPOSITORY_CONFIG = vol.Schema({
vol.Required(ATTR_NAME): vol.Coerce(str),
vol.Optional(ATTR_URL): vol.Url(),
vol.Optional(ATTR_MAINTAINER): vol.Coerce(str),
}, extra=vol.ALLOW_EXTRA)
SCHEMA_BUILD_CONFIG = vol.Schema(
{
vol.Optional(ATTR_BUILD_FROM, default=dict): vol.Schema(
{vol.In(ARCH_ALL): vol.Match(RE_DOCKER_IMAGE_BUILD)}
),
vol.Optional(ATTR_SQUASH, default=False): vol.Boolean(),
vol.Optional(ATTR_ARGS, default=dict): vol.Schema(
{vol.Coerce(str): vol.Coerce(str)}
),
},
extra=vol.REMOVE_EXTRA,
)
# pylint: disable=no-value-for-parameter
SCHEMA_ADDON_USER = vol.Schema(
{
vol.Required(ATTR_VERSION): vol.Coerce(str),
vol.Optional(ATTR_IMAGE): vol.Coerce(str),
vol.Optional(ATTR_UUID, default=lambda: uuid.uuid4().hex): UUID_MATCH,
vol.Optional(ATTR_ACCESS_TOKEN): TOKEN,
vol.Optional(ATTR_INGRESS_TOKEN, default=secrets.token_urlsafe): vol.Coerce(
str
),
vol.Optional(ATTR_OPTIONS, default=dict): dict,
vol.Optional(ATTR_AUTO_UPDATE, default=False): vol.Boolean(),
vol.Optional(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]),
vol.Optional(ATTR_NETWORK): DOCKER_PORTS,
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_DEVICE,
vol.Optional(ATTR_AUDIO_INPUT): ALSA_DEVICE,
vol.Optional(ATTR_PROTECTED, default=True): vol.Boolean(),
vol.Optional(ATTR_INGRESS_PANEL, default=False): vol.Boolean(),
},
extra=vol.REMOVE_EXTRA,
)
SCHEMA_ADDON_SYSTEM = SCHEMA_ADDON_CONFIG.extend(
{
vol.Required(ATTR_LOCATON): vol.Coerce(str),
vol.Required(ATTR_REPOSITORY): vol.Coerce(str),
}
)
SCHEMA_ADDONS_FILE = vol.Schema(
{
vol.Optional(ATTR_USER, default=dict): {vol.Coerce(str): SCHEMA_ADDON_USER},
vol.Optional(ATTR_SYSTEM, default=dict): {vol.Coerce(str): SCHEMA_ADDON_SYSTEM},
}
)
SCHEMA_ADDON_SNAPSHOT = vol.Schema(
{
vol.Required(ATTR_USER): SCHEMA_ADDON_USER,
vol.Required(ATTR_SYSTEM): SCHEMA_ADDON_SYSTEM,
vol.Required(ATTR_STATE): vol.In([STATE_STARTED, STATE_STOPPED]),
vol.Required(ATTR_VERSION): vol.Coerce(str),
},
extra=vol.REMOVE_EXTRA,
)
def validate_options(raw_schema):
"""Validate schema."""
def validate(struct):
"""Create schema validator for addons options."""
"""Create schema validator for add-ons options."""
options = {}
# read options
for key, value in struct.items():
# Ignore unknown options / remove from list
if key not in raw_schema:
raise vol.Invalid("Unknown options {}.".format(key))
_LOGGER.warning("Unknown options %s", key)
continue
typ = raw_schema[key]
try:
if isinstance(typ, list):
# nested value
options[key] = _nested_validate(typ[0], value)
# nested value list
options[key] = _nested_validate_list(typ[0], value, key)
elif isinstance(typ, dict):
# nested value dict
options[key] = _nested_validate_dict(typ, value, key)
else:
# normal value
options[key] = _single_validate(typ, value)
options[key] = _single_validate(typ, value, key)
except (IndexError, KeyError):
raise vol.Invalid(
"Type error for {}.".format(key)) from None
raise vol.Invalid(f"Type error for {key}") from None
_check_missing_options(raw_schema, options, "root")
return options
return validate
# pylint: disable=no-value-for-parameter
def _single_validate(typ, value):
# pylint: disable=inconsistent-return-statements
def _single_validate(typ, value, key):
"""Validate a single element."""
try:
# if required argument
if value is None:
raise vol.Invalid("A required argument is not set!")
# if required argument
if value is None:
raise vol.Invalid(f"Missing required option '{key}'")
if typ == V_STR:
return str(value)
elif typ == V_INT:
return int(value)
elif typ == V_FLOAT:
return float(value)
elif typ == V_BOOL:
return vol.Boolean()(value)
elif typ == V_EMAIL:
return vol.Email()(value)
elif typ == V_URL:
return vol.Url()(value)
# parse extend data from type
match = RE_SCHEMA_ELEMENT.match(typ)
raise vol.Invalid("Fatal error for {}.".format(value))
except ValueError:
raise vol.Invalid(
"Type {} error for {}.".format(typ, value)) from None
# prepare range
range_args = {}
for group_name in ("i_min", "i_max", "f_min", "f_max"):
group_value = match.group(group_name)
if group_value:
range_args[group_name[2:]] = float(group_value)
if typ.startswith(V_STR):
return str(value)
elif typ.startswith(V_INT):
return vol.All(vol.Coerce(int), vol.Range(**range_args))(value)
elif typ.startswith(V_FLOAT):
return vol.All(vol.Coerce(float), vol.Range(**range_args))(value)
elif typ.startswith(V_BOOL):
return vol.Boolean()(value)
elif typ.startswith(V_EMAIL):
return vol.Email()(value)
elif typ.startswith(V_URL):
return vol.Url()(value)
elif typ.startswith(V_PORT):
return NETWORK_PORT(value)
elif typ.startswith(V_MATCH):
return vol.Match(match.group("match"))(str(value))
raise vol.Invalid(f"Fatal error for {key} type {typ}")
def _nested_validate(typ, data_list):
def _nested_validate_list(typ, data_list, key):
"""Validate nested items."""
options = []
for element in data_list:
# dict list
# Nested?
if isinstance(typ, dict):
c_options = {}
for c_key, c_value in element.items():
if c_key not in typ:
raise vol.Invalid(
"Unknown nested options {}.".format(c_key))
c_options[c_key] = _single_validate(typ[c_key], c_value)
c_options = _nested_validate_dict(typ, element, key)
options.append(c_options)
# normal list
else:
options.append(_single_validate(typ, element))
options.append(_single_validate(typ, element, key))
return options
def _nested_validate_dict(typ, data_dict, key):
"""Validate nested items."""
options = {}
for c_key, c_value in data_dict.items():
# Ignore unknown options / remove from list
if c_key not in typ:
_LOGGER.warning("Unknown options %s", c_key)
continue
# Nested?
if isinstance(typ[c_key], list):
options[c_key] = _nested_validate_list(typ[c_key][0], c_value, c_key)
else:
options[c_key] = _single_validate(typ[c_key], c_value, c_key)
_check_missing_options(typ, options, key)
return options
def _check_missing_options(origin, exists, root):
"""Check if all options are exists."""
missing = set(origin) - set(exists)
for miss_opt in missing:
if isinstance(origin[miss_opt], str) and origin[miss_opt].endswith("?"):
continue
raise vol.Invalid(f"Missing option {miss_opt} in {root}")

View File

@@ -1,109 +1,312 @@
"""Init file for HassIO rest api."""
"""Init file for Hass.io RESTful API."""
import logging
from pathlib import Path
from typing import Optional
from aiohttp import web
from ..coresys import CoreSys, CoreSysAttributes
from .addons import APIAddons
from .auth import APIAuth
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 .network import APINetwork
from .info import APIInfo
from .ingress import APIIngress
from .proxy import APIProxy
from .security import SecurityMiddleware
from .services import APIServices
from .snapshots import APISnapshots
from .supervisor import APISupervisor
_LOGGER = logging.getLogger(__name__)
class RestAPI(object):
"""Handle rest api for hassio."""
class RestAPI(CoreSysAttributes):
"""Handle RESTful API for Hass.io."""
def __init__(self, config, loop):
"""Initialize docker base wrapper."""
self.config = config
self.loop = loop
self.webapp = web.Application(loop=self.loop)
def __init__(self, coresys: CoreSys):
"""Initialize Docker base wrapper."""
self.coresys: CoreSys = coresys
self.security: SecurityMiddleware = SecurityMiddleware(coresys)
self.webapp: web.Application = web.Application(
middlewares=[self.security.token_validation]
)
# service stuff
self._handler = None
self.server = None
self._runner: web.AppRunner = web.AppRunner(self.webapp)
self._site: Optional[web.TCPSite] = None
def register_host(self, host_control):
"""Register hostcontrol function."""
api_host = APIHost(self.config, self.loop, host_control)
async def load(self) -> None:
"""Register REST API Calls."""
self._register_supervisor()
self._register_host()
self._register_hassos()
self._register_hardware()
self._register_homeassistant()
self._register_proxy()
self._register_panel()
self._register_addons()
self._register_ingress()
self._register_snapshots()
self._register_discovery()
self._register_services()
self._register_info()
self._register_auth()
self._register_dns()
self.webapp.router.add_get('/host/info', api_host.info)
self.webapp.router.add_post('/host/reboot', api_host.reboot)
self.webapp.router.add_post('/host/shutdown', api_host.shutdown)
self.webapp.router.add_post('/host/update', api_host.update)
def _register_host(self) -> None:
"""Register hostcontrol functions."""
api_host = APIHost()
api_host.coresys = self.coresys
def register_network(self, host_control):
"""Register network function."""
api_net = APINetwork(self.config, self.loop, host_control)
self.webapp.add_routes(
[
web.get("/host/info", api_host.info),
web.post("/host/reboot", api_host.reboot),
web.post("/host/shutdown", api_host.shutdown),
web.post("/host/reload", api_host.reload),
web.post("/host/options", api_host.options),
web.get("/host/services", api_host.services),
web.post("/host/services/{service}/stop", api_host.service_stop),
web.post("/host/services/{service}/start", api_host.service_start),
web.post("/host/services/{service}/restart", api_host.service_restart),
web.post("/host/services/{service}/reload", api_host.service_reload),
]
)
self.webapp.router.add_get('/network/info', api_net.info)
self.webapp.router.add_post('/network/options', api_net.options)
def _register_hassos(self) -> None:
"""Register HassOS functions."""
api_hassos = APIHassOS()
api_hassos.coresys = self.coresys
def register_supervisor(self, supervisor, addons, host_control):
"""Register supervisor function."""
api_supervisor = APISupervisor(
self.config, self.loop, supervisor, addons, host_control)
self.webapp.add_routes(
[
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),
]
)
self.webapp.router.add_get('/supervisor/ping', api_supervisor.ping)
self.webapp.router.add_get('/supervisor/info', api_supervisor.info)
self.webapp.router.add_get(
'/supervisor/addons', api_supervisor.available_addons)
self.webapp.router.add_post(
'/supervisor/update', api_supervisor.update)
self.webapp.router.add_post(
'/supervisor/reload', api_supervisor.reload)
self.webapp.router.add_post(
'/supervisor/options', api_supervisor.options)
self.webapp.router.add_get('/supervisor/logs', api_supervisor.logs)
def _register_hardware(self) -> None:
"""Register hardware functions."""
api_hardware = APIHardware()
api_hardware.coresys = self.coresys
def register_homeassistant(self, dock_homeassistant):
"""Register homeassistant function."""
api_hass = APIHomeAssistant(self.config, self.loop, dock_homeassistant)
self.webapp.add_routes(
[
web.get("/hardware/info", api_hardware.info),
web.get("/hardware/audio", api_hardware.audio),
]
)
self.webapp.router.add_get('/homeassistant/info', api_hass.info)
self.webapp.router.add_post('/homeassistant/update', api_hass.update)
self.webapp.router.add_post('/homeassistant/restart', api_hass.restart)
self.webapp.router.add_get('/homeassistant/logs', api_hass.logs)
def _register_info(self) -> None:
"""Register info functions."""
api_info = APIInfo()
api_info.coresys = self.coresys
def register_addons(self, addons):
"""Register homeassistant function."""
api_addons = APIAddons(self.config, self.loop, addons)
self.webapp.add_routes([web.get("/info", api_info.info)])
self.webapp.router.add_get('/addons/{addon}/info', api_addons.info)
self.webapp.router.add_post(
'/addons/{addon}/install', api_addons.install)
self.webapp.router.add_post(
'/addons/{addon}/uninstall', api_addons.uninstall)
self.webapp.router.add_post('/addons/{addon}/start', api_addons.start)
self.webapp.router.add_post('/addons/{addon}/stop', api_addons.stop)
self.webapp.router.add_post(
'/addons/{addon}/restart', api_addons.restart)
self.webapp.router.add_post(
'/addons/{addon}/update', api_addons.update)
self.webapp.router.add_post(
'/addons/{addon}/options', api_addons.options)
self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs)
def _register_auth(self) -> None:
"""Register auth functions."""
api_auth = APIAuth()
api_auth.coresys = self.coresys
async def start(self):
"""Run rest api webserver."""
self._handler = self.webapp.make_handler(loop=self.loop)
self.webapp.add_routes([web.post("/auth", api_auth.auth)])
def _register_supervisor(self) -> None:
"""Register Supervisor functions."""
api_supervisor = APISupervisor()
api_supervisor.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/supervisor/ping", api_supervisor.ping),
web.get("/supervisor/info", api_supervisor.info),
web.get("/supervisor/stats", api_supervisor.stats),
web.get("/supervisor/logs", api_supervisor.logs),
web.post("/supervisor/update", api_supervisor.update),
web.post("/supervisor/reload", api_supervisor.reload),
web.post("/supervisor/options", api_supervisor.options),
web.post("/supervisor/repair", api_supervisor.repair),
]
)
def _register_homeassistant(self) -> None:
"""Register Home Assistant functions."""
api_hass = APIHomeAssistant()
api_hass.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/homeassistant/info", api_hass.info),
web.get("/homeassistant/logs", api_hass.logs),
web.get("/homeassistant/stats", api_hass.stats),
web.post("/homeassistant/options", api_hass.options),
web.post("/homeassistant/update", api_hass.update),
web.post("/homeassistant/restart", api_hass.restart),
web.post("/homeassistant/stop", api_hass.stop),
web.post("/homeassistant/start", api_hass.start),
web.post("/homeassistant/check", api_hass.check),
web.post("/homeassistant/rebuild", api_hass.rebuild),
]
)
def _register_proxy(self) -> None:
"""Register Home Assistant API Proxy."""
api_proxy = APIProxy()
api_proxy.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/homeassistant/api/websocket", api_proxy.websocket),
web.get("/homeassistant/websocket", api_proxy.websocket),
web.get("/homeassistant/api/stream", api_proxy.stream),
web.post("/homeassistant/api/{path:.+}", api_proxy.api),
web.get("/homeassistant/api/{path:.+}", api_proxy.api),
web.get("/homeassistant/api/", api_proxy.api),
]
)
def _register_addons(self) -> None:
"""Register Add-on functions."""
api_addons = APIAddons()
api_addons.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/addons", api_addons.list),
web.post("/addons/reload", api_addons.reload),
web.get("/addons/{addon}/info", api_addons.info),
web.post("/addons/{addon}/install", api_addons.install),
web.post("/addons/{addon}/uninstall", api_addons.uninstall),
web.post("/addons/{addon}/start", api_addons.start),
web.post("/addons/{addon}/stop", api_addons.stop),
web.post("/addons/{addon}/restart", api_addons.restart),
web.post("/addons/{addon}/update", api_addons.update),
web.post("/addons/{addon}/options", api_addons.options),
web.post("/addons/{addon}/rebuild", api_addons.rebuild),
web.get("/addons/{addon}/logs", api_addons.logs),
web.get("/addons/{addon}/icon", api_addons.icon),
web.get("/addons/{addon}/logo", api_addons.logo),
web.get("/addons/{addon}/changelog", api_addons.changelog),
web.post("/addons/{addon}/stdin", api_addons.stdin),
web.post("/addons/{addon}/security", api_addons.security),
web.get("/addons/{addon}/stats", api_addons.stats),
]
)
def _register_ingress(self) -> None:
"""Register Ingress functions."""
api_ingress = APIIngress()
api_ingress.coresys = self.coresys
self.webapp.add_routes(
[
web.post("/ingress/session", api_ingress.create_session),
web.get("/ingress/panels", api_ingress.panels),
web.view("/ingress/{token}/{path:.*}", api_ingress.handler),
]
)
def _register_snapshots(self) -> None:
"""Register snapshots functions."""
api_snapshots = APISnapshots()
api_snapshots.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/snapshots", api_snapshots.list),
web.post("/snapshots/reload", api_snapshots.reload),
web.post("/snapshots/new/full", api_snapshots.snapshot_full),
web.post("/snapshots/new/partial", api_snapshots.snapshot_partial),
web.post("/snapshots/new/upload", api_snapshots.upload),
web.get("/snapshots/{snapshot}/info", api_snapshots.info),
web.post("/snapshots/{snapshot}/remove", api_snapshots.remove),
web.post(
"/snapshots/{snapshot}/restore/full", api_snapshots.restore_full
),
web.post(
"/snapshots/{snapshot}/restore/partial",
api_snapshots.restore_partial,
),
web.get("/snapshots/{snapshot}/download", api_snapshots.download),
]
)
def _register_services(self) -> None:
"""Register services functions."""
api_services = APIServices()
api_services.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/services", api_services.list),
web.get("/services/{service}", api_services.get_service),
web.post("/services/{service}", api_services.set_service),
web.delete("/services/{service}", api_services.del_service),
]
)
def _register_discovery(self) -> None:
"""Register discovery functions."""
api_discovery = APIDiscovery()
api_discovery.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/discovery", api_discovery.list),
web.get("/discovery/{uuid}", api_discovery.get_discovery),
web.delete("/discovery/{uuid}", api_discovery.del_discovery),
web.post("/discovery", api_discovery.set_discovery),
]
)
def _register_dns(self) -> None:
"""Register DNS functions."""
api_dns = APICoreDNS()
api_dns.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/dns/info", api_dns.info),
web.get("/dns/stats", api_dns.stats),
web.get("/dns/logs", api_dns.logs),
web.post("/dns/update", api_dns.update),
web.post("/dns/options", api_dns.options),
]
)
def _register_panel(self) -> None:
"""Register panel for Home Assistant."""
panel_dir = Path(__file__).parent.joinpath("panel")
self.webapp.add_routes([web.static("/app", panel_dir)])
async def start(self) -> None:
"""Run RESTful API webserver."""
await self._runner.setup()
self._site = web.TCPSite(
self._runner, host="0.0.0.0", port=80, shutdown_timeout=5
)
try:
self.server = await self.loop.create_server(
self._handler, "0.0.0.0", "80")
await self._site.start()
except OSError as err:
_LOGGER.fatal(
"Failed to create HTTP server at 0.0.0.0:80 -> %s", err)
_LOGGER.fatal("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)
async def stop(self):
"""Stop rest api webserver."""
if self.server:
self.server.close()
await self.server.wait_closed()
await self.webapp.shutdown()
async def stop(self) -> None:
"""Stop RESTful API webserver."""
if not self._site:
return
if self._handler:
await self._handler.finish_connections(60)
await self.webapp.cleanup()
# Shutdown running API
await self._site.stop()
await self._runner.cleanup()
_LOGGER.info("Stop API on %s", self.sys_docker.network.supervisor)

View File

@@ -1,161 +1,438 @@
"""Init file for HassIO homeassistant rest api."""
"""Init file for Hass.io Home Assistant RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict, List
from aiohttp import web
import voluptuous as vol
from voluptuous.humanize import humanize_error
from .util import api_process, api_process_raw, api_validate
from ..addons import AnyAddon
from ..docker.stats import DockerStats
from ..addons.utils import rating_security
from ..const import (
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_STATE, ATTR_BOOT, ATTR_OPTIONS,
ATTR_URL, ATTR_DESCRIPTON, ATTR_DETACHED, ATTR_NAME, ATTR_REPOSITORY,
STATE_STOPPED, STATE_STARTED, BOOT_AUTO, BOOT_MANUAL)
ATTR_ADDONS,
ATTR_APPARMOR,
ATTR_ARCH,
ATTR_AUDIO,
ATTR_AUDIO_INPUT,
ATTR_AUDIO_OUTPUT,
ATTR_AUTH_API,
ATTR_AUTO_UPDATE,
ATTR_AVAILABLE,
ATTR_BLK_READ,
ATTR_BLK_WRITE,
ATTR_BOOT,
ATTR_BUILD,
ATTR_CHANGELOG,
ATTR_CPU_PERCENT,
ATTR_DESCRIPTON,
ATTR_DETACHED,
ATTR_DEVICES,
ATTR_DEVICETREE,
ATTR_DISCOVERY,
ATTR_DNS,
ATTR_DOCKER_API,
ATTR_FULL_ACCESS,
ATTR_GPIO,
ATTR_HASSIO_API,
ATTR_HASSIO_ROLE,
ATTR_HOMEASSISTANT,
ATTR_HOMEASSISTANT_API,
ATTR_HOST_DBUS,
ATTR_HOST_IPC,
ATTR_HOST_NETWORK,
ATTR_HOST_PID,
ATTR_HOSTNAME,
ATTR_ICON,
ATTR_INGRESS,
ATTR_INGRESS_ENTRY,
ATTR_INGRESS_PANEL,
ATTR_INGRESS_PORT,
ATTR_INGRESS_URL,
ATTR_INSTALLED,
ATTR_IP_ADDRESS,
ATTR_KERNEL_MODULES,
ATTR_LAST_VERSION,
ATTR_LOGO,
ATTR_LONG_DESCRIPTION,
ATTR_MACHINE,
ATTR_MAINTAINER,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_PERCENT,
ATTR_MEMORY_USAGE,
ATTR_NAME,
ATTR_NETWORK,
ATTR_NETWORK_DESCRIPTION,
ATTR_NETWORK_RX,
ATTR_NETWORK_TX,
ATTR_OPTIONS,
ATTR_PRIVILEGED,
ATTR_PROTECTED,
ATTR_RATING,
ATTR_REPOSITORIES,
ATTR_REPOSITORY,
ATTR_SERVICES,
ATTR_SLUG,
ATTR_SOURCE,
ATTR_STATE,
ATTR_STDIN,
ATTR_UDEV,
ATTR_URL,
ATTR_VERSION,
ATTR_WEBUI,
BOOT_AUTO,
BOOT_MANUAL,
CONTENT_TYPE_BINARY,
CONTENT_TYPE_PNG,
CONTENT_TYPE_TEXT,
REQUEST_FROM,
STATE_NONE,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import ALSA_DEVICE, DOCKER_PORTS
from .utils import api_process, api_process_raw, api_validate
_LOGGER = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({
vol.Optional(ATTR_VERSION): vol.Coerce(str),
})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
SCHEMA_OPTIONS = vol.Schema({
vol.Optional(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL])
})
# pylint: disable=no-value-for-parameter
SCHEMA_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_BOOT): vol.In([BOOT_AUTO, BOOT_MANUAL]),
vol.Optional(ATTR_NETWORK): vol.Any(None, DOCKER_PORTS),
vol.Optional(ATTR_AUTO_UPDATE): vol.Boolean(),
vol.Optional(ATTR_AUDIO_OUTPUT): ALSA_DEVICE,
vol.Optional(ATTR_AUDIO_INPUT): ALSA_DEVICE,
vol.Optional(ATTR_INGRESS_PANEL): vol.Boolean(),
}
)
# pylint: disable=no-value-for-parameter
SCHEMA_SECURITY = vol.Schema({vol.Optional(ATTR_PROTECTED): vol.Boolean()})
class APIAddons(object):
"""Handle rest api for addons functions."""
class APIAddons(CoreSysAttributes):
"""Handle RESTful API for add-on functions."""
def __init__(self, config, loop, addons):
"""Initialize homeassistant rest api part."""
self.config = config
self.loop = loop
self.addons = addons
def _extract_addon(
self, request: web.Request, check_installed: bool = True
) -> AnyAddon:
"""Return addon, throw an exception it it doesn't exist."""
addon_slug: str = request.match_info.get("addon")
def _extract_addon(self, request, check_installed=True):
"""Return addon and if not exists trow a exception."""
addon = request.match_info.get('addon')
# Lookup itself
if addon_slug == "self":
return request.get(REQUEST_FROM)
# check data
if not self.addons.exists_addon(addon):
raise RuntimeError("Addon not exists")
if check_installed and not self.addons.is_installed(addon):
raise RuntimeError("Addon is not installed")
addon = self.sys_addons.get(addon_slug)
if not addon:
raise APIError("Addon does not exist")
if check_installed and not addon.is_installed:
raise APIError("Addon is not installed")
return addon
@api_process
async def info(self, request):
"""Return addon information."""
addon = self._extract_addon(request)
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_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,
}
)
return {ATTR_ADDONS: data_addons, ATTR_REPOSITORIES: data_repositories}
@api_process
async def reload(self, request: web.Request) -> None:
"""Reload all add-on data from store."""
await asyncio.shield(self.sys_store.reload())
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return add-on information."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
data = {
ATTR_NAME: addon.name,
ATTR_SLUG: addon.slug,
ATTR_HOSTNAME: addon.hostname,
ATTR_DNS: addon.dns,
ATTR_DESCRIPTON: addon.description,
ATTR_LONG_DESCRIPTION: addon.long_description,
ATTR_AUTO_UPDATE: None,
ATTR_REPOSITORY: addon.repository,
ATTR_VERSION: None,
ATTR_LAST_VERSION: addon.latest_version,
ATTR_PROTECTED: addon.protected,
ATTR_RATING: rating_security(addon),
ATTR_BOOT: addon.boot,
ATTR_OPTIONS: addon.options,
ATTR_ARCH: addon.supported_arch,
ATTR_MACHINE: addon.supported_machine,
ATTR_HOMEASSISTANT: addon.homeassistant_version,
ATTR_URL: addon.url,
ATTR_STATE: STATE_NONE,
ATTR_DETACHED: addon.is_detached,
ATTR_AVAILABLE: addon.available,
ATTR_BUILD: addon.need_build,
ATTR_NETWORK: addon.ports,
ATTR_NETWORK_DESCRIPTION: addon.ports_description,
ATTR_HOST_NETWORK: addon.host_network,
ATTR_HOST_PID: addon.host_pid,
ATTR_HOST_IPC: addon.host_ipc,
ATTR_HOST_DBUS: addon.host_dbus,
ATTR_PRIVILEGED: addon.privileged,
ATTR_FULL_ACCESS: addon.with_full_access,
ATTR_APPARMOR: addon.apparmor,
ATTR_DEVICES: _pretty_devices(addon),
ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo,
ATTR_CHANGELOG: addon.with_changelog,
ATTR_STDIN: addon.with_stdin,
ATTR_WEBUI: None,
ATTR_HASSIO_API: addon.access_hassio_api,
ATTR_HASSIO_ROLE: addon.hassio_role,
ATTR_AUTH_API: addon.access_auth_api,
ATTR_HOMEASSISTANT_API: addon.access_homeassistant_api,
ATTR_GPIO: addon.with_gpio,
ATTR_KERNEL_MODULES: addon.with_kernel_modules,
ATTR_DEVICETREE: addon.with_devicetree,
ATTR_UDEV: addon.with_udev,
ATTR_DOCKER_API: addon.access_docker_api,
ATTR_AUDIO: addon.with_audio,
ATTR_AUDIO_INPUT: None,
ATTR_AUDIO_OUTPUT: None,
ATTR_SERVICES: _pretty_services(addon),
ATTR_DISCOVERY: addon.discovery,
ATTR_IP_ADDRESS: None,
ATTR_INGRESS: addon.with_ingress,
ATTR_INGRESS_ENTRY: None,
ATTR_INGRESS_URL: None,
ATTR_INGRESS_PORT: None,
ATTR_INGRESS_PANEL: None,
}
if addon.is_installed:
data.update(
{
ATTR_STATE: await addon.state(),
ATTR_WEBUI: addon.webui,
ATTR_INGRESS_ENTRY: addon.ingress_entry,
ATTR_INGRESS_URL: addon.ingress_url,
ATTR_INGRESS_PORT: addon.ingress_port,
ATTR_INGRESS_PANEL: addon.ingress_panel,
ATTR_AUDIO_INPUT: addon.audio_input,
ATTR_AUDIO_OUTPUT: addon.audio_output,
ATTR_AUTO_UPDATE: addon.auto_update,
ATTR_IP_ADDRESS: str(addon.ip_address),
ATTR_VERSION: addon.version,
}
)
return data
@api_process
async def options(self, request: web.Request) -> None:
"""Store user options for add-on."""
addon: AnyAddon = self._extract_addon(request)
addon_schema = SCHEMA_OPTIONS.extend(
{vol.Optional(ATTR_OPTIONS): vol.Any(None, addon.schema)}
)
body: Dict[str, Any] = await api_validate(addon_schema, request)
if ATTR_OPTIONS in body:
addon.options = body[ATTR_OPTIONS]
if ATTR_BOOT in body:
addon.boot = body[ATTR_BOOT]
if ATTR_AUTO_UPDATE in body:
addon.auto_update = body[ATTR_AUTO_UPDATE]
if ATTR_NETWORK in body:
addon.ports = body[ATTR_NETWORK]
if ATTR_AUDIO_INPUT in body:
addon.audio_input = body[ATTR_AUDIO_INPUT]
if ATTR_AUDIO_OUTPUT in body:
addon.audio_output = body[ATTR_AUDIO_OUTPUT]
if ATTR_INGRESS_PANEL in body:
addon.ingress_panel = body[ATTR_INGRESS_PANEL]
await self.sys_ingress.update_hass_panel(addon)
addon.save_persist()
@api_process
async def security(self, request: web.Request) -> None:
"""Store security options for add-on."""
addon: AnyAddon = self._extract_addon(request)
body: Dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
if ATTR_PROTECTED in body:
_LOGGER.warning("Protected flag changing for %s!", addon.slug)
addon.protected = body[ATTR_PROTECTED]
addon.save_persist()
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
addon: AnyAddon = self._extract_addon(request)
stats: DockerStats = await addon.stats()
return {
ATTR_NAME: self.addons.get_name(addon),
ATTR_DESCRIPTON: self.addons.get_description(addon),
ATTR_VERSION: self.addons.version_installed(addon),
ATTR_REPOSITORY: self.addons.get_repository(addon),
ATTR_LAST_VERSION: self.addons.get_last_version(addon),
ATTR_STATE: await self.addons.state(addon),
ATTR_BOOT: self.addons.get_boot(addon),
ATTR_OPTIONS: self.addons.get_options(addon),
ATTR_URL: self.addons.get_url(addon),
ATTR_DETACHED: addon in self.addons.list_detached,
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 options(self, request):
"""Store user options for addon."""
addon = self._extract_addon(request)
options_schema = self.addons.get_schema(addon)
addon_schema = SCHEMA_OPTIONS.extend({
vol.Optional(ATTR_OPTIONS): options_schema,
})
body = await api_validate(addon_schema, request)
if ATTR_OPTIONS in body:
self.addons.set_options(addon, body[ATTR_OPTIONS])
if ATTR_BOOT in body:
self.addons.set_boot(addon, body[ATTR_BOOT])
return True
def install(self, request: web.Request) -> Awaitable[None]:
"""Install add-on."""
addon: AnyAddon = self._extract_addon(request, check_installed=False)
return asyncio.shield(addon.install())
@api_process
async def install(self, request):
"""Install addon."""
body = await api_validate(SCHEMA_VERSION, request)
addon = self._extract_addon(request, check_installed=False)
version = body.get(
ATTR_VERSION, self.addons.get_last_version(addon))
# check if arch supported
if self.addons.arch not in self.addons.get_arch(addon):
raise RuntimeError(
"Addon is not supported on {}".format(self.addons.arch))
return await asyncio.shield(
self.addons.install(addon, version), loop=self.loop)
def uninstall(self, request: web.Request) -> Awaitable[None]:
"""Uninstall add-on."""
addon: AnyAddon = self._extract_addon(request)
return asyncio.shield(addon.uninstall())
@api_process
async def uninstall(self, request):
"""Uninstall addon."""
addon = self._extract_addon(request)
def start(self, request: web.Request) -> Awaitable[None]:
"""Start add-on."""
addon: AnyAddon = self._extract_addon(request)
return await asyncio.shield(
self.addons.uninstall(addon), loop=self.loop)
@api_process
async def start(self, request):
"""Start addon."""
addon = self._extract_addon(request)
if await self.addons.state(addon) == STATE_STARTED:
raise RuntimeError("Addon is already running")
# validate options
# check options
options = addon.options
try:
schema = self.addons.get_schema(addon)
options = self.addons.get_options(addon)
schema(options)
addon.schema(options)
except vol.Invalid as ex:
raise RuntimeError(humanize_error(options, ex)) from None
raise APIError(humanize_error(options, ex)) from None
return await asyncio.shield(
self.addons.start(addon), loop=self.loop)
return asyncio.shield(addon.start())
@api_process
async def stop(self, request):
"""Stop addon."""
addon = self._extract_addon(request)
if await self.addons.state(addon) == STATE_STOPPED:
raise RuntimeError("Addon is already stoped")
return await asyncio.shield(
self.addons.stop(addon), loop=self.loop)
def stop(self, request: web.Request) -> Awaitable[None]:
"""Stop add-on."""
addon: AnyAddon = self._extract_addon(request)
return asyncio.shield(addon.stop())
@api_process
async def update(self, request):
"""Update addon."""
body = await api_validate(SCHEMA_VERSION, request)
addon = self._extract_addon(request)
version = body.get(
ATTR_VERSION, self.addons.get_last_version(addon))
def update(self, request: web.Request) -> Awaitable[None]:
"""Update add-on."""
addon: AnyAddon = self._extract_addon(request)
if version == self.addons.version_installed(addon):
raise RuntimeError("Version is already in use")
if addon.latest_version == addon.version:
raise APIError("No update available!")
return await asyncio.shield(
self.addons.update(addon, version), loop=self.loop)
return asyncio.shield(addon.update())
@api_process
async def restart(self, request):
"""Restart addon."""
addon = self._extract_addon(request)
return await asyncio.shield(self.addons.restart(addon), loop=self.loop)
def restart(self, request: web.Request) -> Awaitable[None]:
"""Restart add-on."""
addon: AnyAddon = self._extract_addon(request)
return asyncio.shield(addon.restart())
@api_process_raw
def logs(self, request):
"""Return logs from addon."""
addon = self._extract_addon(request)
return self.addons.logs(addon)
@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")
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)
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)
if not addon.with_icon:
raise APIError("No icon found!")
with addon.path_icon.open("rb") as png:
return png.read()
@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)
if not addon.with_logo:
raise APIError("No logo found!")
with addon.path_logo.open("rb") as png:
return png.read()
@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)
if not addon.with_changelog:
raise APIError("No changelog found!")
with addon.path_changelog.open("r") as changelog:
return changelog.read()
@api_process
async def stdin(self, request: web.Request) -> None:
"""Write to stdin of add-on."""
addon: AnyAddon = self._extract_addon(request)
if not addon.with_stdin:
raise APIError("STDIN not supported by add-on")
data = await request.read()
await asyncio.shield(addon.write_stdin(data))
def _pretty_devices(addon: AnyAddon) -> List[str]:
"""Return a simplified device list."""
dev_list = addon.devices
if not dev_list:
return None
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

61
hassio/api/auth.py Normal file
View File

@@ -0,0 +1,61 @@
"""Init file for Hass.io auth/SSO RESTful API."""
import logging
from aiohttp import BasicAuth
from aiohttp.web_exceptions import HTTPUnauthorized
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION, WWW_AUTHENTICATE
from .utils import api_process
from ..const import REQUEST_FROM, CONTENT_TYPE_JSON, CONTENT_TYPE_URL
from ..coresys import CoreSysAttributes
from ..exceptions import APIForbidden
_LOGGER = logging.getLogger(__name__)
class APIAuth(CoreSysAttributes):
"""Handle RESTful API for auth functions."""
def _process_basic(self, request, addon):
"""Process login request with basic auth.
Return a coroutine.
"""
auth = BasicAuth.decode(request.headers[AUTHORIZATION])
return self.sys_auth.check_login(addon, auth.login, auth.password)
def _process_dict(self, request, addon, data):
"""Process login with dict data.
Return a coroutine.
"""
username = data.get("username") or data.get("user")
password = data.get("password")
return self.sys_auth.check_login(addon, username, password)
@api_process
async def auth(self, request):
"""Process login request."""
addon = request[REQUEST_FROM]
if not addon.access_auth_api:
raise APIForbidden("Can't use Home Assistant auth!")
# BasicAuth
if AUTHORIZATION in request.headers:
return await self._process_basic(request, addon)
# Json
if request.headers.get(CONTENT_TYPE) == CONTENT_TYPE_JSON:
data = await request.json()
return await self._process_dict(request, addon, data)
# URL encoded
if request.headers.get(CONTENT_TYPE) == CONTENT_TYPE_URL:
data = await request.post()
return await self._process_dict(request, addon, data)
raise HTTPUnauthorized(
headers={WWW_AUTHENTICATE: 'Basic realm="Hass.io Authentication"'}
)

100
hassio/api/discovery.py Normal file
View File

@@ -0,0 +1,100 @@
"""Init file for Hass.io 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,
REQUEST_FROM,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, APIForbidden
from ..discovery.validate import valid_discovery_service
SCHEMA_DISCOVERY = vol.Schema(
{
vol.Required(ATTR_SERVICE): valid_discovery_service,
vol.Optional(ATTR_CONFIG): vol.Maybe(dict),
}
)
class APIDiscovery(CoreSysAttributes):
"""Handle RESTful API for discovery functions."""
def _extract_message(self, request):
"""Extract discovery message from URL."""
message = self.sys_discovery.get(request.match_info.get("uuid"))
if not message:
raise APIError("Discovery message not found")
return message
def _check_permission_ha(self, request):
"""Check permission for API call / Home Assistant."""
if request[REQUEST_FROM] != self.sys_homeassistant:
raise APIForbidden("Only HomeAssistant can use this API!")
@api_process
async def list(self, request):
"""Show register services."""
self._check_permission_ha(request)
discovery = []
for message in self.sys_discovery.list_messages:
discovery.append(
{
ATTR_ADDON: message.addon,
ATTR_SERVICE: message.service,
ATTR_UUID: message.uuid,
ATTR_CONFIG: message.config,
}
)
return {ATTR_DISCOVERY: discovery}
@api_process
async def set_discovery(self, request):
"""Write data into a discovery pipeline."""
body = await api_validate(SCHEMA_DISCOVERY, request)
addon = request[REQUEST_FROM]
# Access?
if body[ATTR_SERVICE] not in addon.discovery:
raise APIForbidden(f"Can't use discovery!")
# Process discovery message
message = self.sys_discovery.send(addon, **body)
return {ATTR_UUID: message.uuid}
@api_process
async def get_discovery(self, request):
"""Read data into a discovery message."""
message = self._extract_message(request)
# HomeAssistant?
self._check_permission_ha(request)
return {
ATTR_ADDON: message.addon,
ATTR_SERVICE: message.service,
ATTR_UUID: message.uuid,
ATTR_CONFIG: message.config,
}
@api_process
async def del_discovery(self, request):
"""Delete data into a discovery message."""
message = self._extract_message(request)
addon = request[REQUEST_FROM]
# Permission
if message.addon != addon.slug:
raise APIForbidden(f"Can't remove discovery message")
self.sys_discovery.remove(message)
return True

89
hassio/api/dns.py Normal file
View File

@@ -0,0 +1,89 @@
"""Init file for Hass.io DNS 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_HOST,
ATTR_LATEST_VERSION,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_USAGE,
ATTR_MEMORY_PERCENT,
ATTR_NETWORK_RX,
ATTR_NETWORK_TX,
ATTR_SERVERS,
ATTR_VERSION,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import DNS_SERVER_LIST
from .utils import api_process, api_process_raw, api_validate
_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)})
class APICoreDNS(CoreSysAttributes):
"""Handle RESTful API for DNS functions."""
@api_process
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_HOST: str(self.sys_docker.network.dns),
ATTR_SERVERS: self.sys_dns.servers,
}
@api_process
async def options(self, request: web.Request) -> None:
"""Set DNS options."""
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_SERVERS in body:
self.sys_dns.servers = body[ATTR_SERVERS]
self.sys_dns.save_data()
@api_process
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
stats = await self.sys_dns.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 DNS plugin."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.sys_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))
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return DNS Docker logs."""
return self.sys_dns.logs()

42
hassio/api/hardware.py Normal file
View File

@@ -0,0 +1,42 @@
"""Init file for Hass.io hardware RESTful API."""
import logging
from .utils import api_process
from ..const import (
ATTR_SERIAL,
ATTR_DISK,
ATTR_GPIO,
ATTR_AUDIO,
ATTR_INPUT,
ATTR_OUTPUT,
)
from ..coresys import CoreSysAttributes
_LOGGER = logging.getLogger(__name__)
class APIHardware(CoreSysAttributes):
"""Handle RESTful API for hardware functions."""
@api_process
async def info(self, request):
"""Show hardware info."""
return {
ATTR_SERIAL: list(
self.sys_hardware.serial_devices | self.sys_hardware.serial_by_id
),
ATTR_INPUT: list(self.sys_hardware.input_devices),
ATTR_DISK: list(self.sys_hardware.disk_devices),
ATTR_GPIO: list(self.sys_hardware.gpio_devices),
ATTR_AUDIO: self.sys_hardware.audio_devices,
}
@api_process
async def audio(self, request):
"""Show ALSA audio devices."""
return {
ATTR_AUDIO: {
ATTR_INPUT: self.sys_host.alsa.input_devices,
ATTR_OUTPUT: self.sys_host.alsa.output_devices,
}
}

57
hassio/api/hassos.py Normal file
View File

@@ -0,0 +1,57 @@
"""Init file for Hass.io HassOS RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
import voluptuous as vol
from aiohttp import web
from ..const import (
ATTR_BOARD,
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.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,
}
@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,66 +1,170 @@
"""Init file for HassIO homeassistant rest api."""
"""Init file for Hass.io Home Assistant RESTful API."""
import asyncio
import logging
from typing import Coroutine, Dict, Any
import voluptuous as vol
from aiohttp import web
from .util import api_process, api_process_raw, api_validate
from ..const import ATTR_VERSION, ATTR_LAST_VERSION
from ..const import (
ATTR_ARCH,
ATTR_BLK_READ,
ATTR_BLK_WRITE,
ATTR_BOOT,
ATTR_CPU_PERCENT,
ATTR_CUSTOM,
ATTR_IMAGE,
ATTR_LAST_VERSION,
ATTR_MACHINE,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_USAGE,
ATTR_MEMORY_PERCENT,
ATTR_NETWORK_RX,
ATTR_NETWORK_TX,
ATTR_PASSWORD,
ATTR_PORT,
ATTR_REFRESH_TOKEN,
ATTR_SSL,
ATTR_VERSION,
ATTR_WAIT_BOOT,
ATTR_WATCHDOG,
ATTR_IP_ADDRESS,
CONTENT_TYPE_BINARY,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..validate import DOCKER_IMAGE, NETWORK_PORT
from .utils import api_process, api_process_raw, api_validate
_LOGGER = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({
vol.Optional(ATTR_VERSION): vol.Coerce(str),
})
# pylint: disable=no-value-for-parameter
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_PORT): NETWORK_PORT,
vol.Optional(ATTR_PASSWORD): vol.Maybe(vol.Coerce(str)),
vol.Optional(ATTR_SSL): vol.Boolean(),
vol.Optional(ATTR_WATCHDOG): vol.Boolean(),
vol.Optional(ATTR_WAIT_BOOT): vol.All(vol.Coerce(int), vol.Range(min=60)),
vol.Optional(ATTR_REFRESH_TOKEN): vol.Maybe(vol.Coerce(str)),
}
)
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
class APIHomeAssistant(object):
"""Handle rest api for homeassistant functions."""
def __init__(self, config, loop, homeassistant):
"""Initialize homeassistant rest api part."""
self.config = config
self.loop = loop
self.homeassistant = homeassistant
class APIHomeAssistant(CoreSysAttributes):
"""Handle RESTful API for Home Assistant functions."""
@api_process
async def info(self, request):
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return host information."""
info = {
ATTR_VERSION: self.homeassistant.version,
ATTR_LAST_VERSION: self.config.last_homeassistant,
return {
ATTR_VERSION: self.sys_homeassistant.version,
ATTR_LAST_VERSION: 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,
ATTR_WATCHDOG: self.sys_homeassistant.watchdog,
ATTR_WAIT_BOOT: self.sys_homeassistant.wait_boot,
}
return info
@api_process
async def options(self, request: web.Request) -> None:
"""Set Home Assistant options."""
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_IMAGE in body and ATTR_LAST_VERSION 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]
if ATTR_PORT in body:
self.sys_homeassistant.api_port = body[ATTR_PORT]
if ATTR_PASSWORD in body:
self.sys_homeassistant.api_password = body[ATTR_PASSWORD]
self.sys_homeassistant.refresh_token = None
if ATTR_SSL in body:
self.sys_homeassistant.api_ssl = body[ATTR_SSL]
if ATTR_WATCHDOG in body:
self.sys_homeassistant.watchdog = body[ATTR_WATCHDOG]
if ATTR_WAIT_BOOT in body:
self.sys_homeassistant.wait_boot = body[ATTR_WAIT_BOOT]
if ATTR_REFRESH_TOKEN in body:
self.sys_homeassistant.refresh_token = body[ATTR_REFRESH_TOKEN]
self.sys_homeassistant.api_password = None
self.sys_homeassistant.save_data()
@api_process
async def update(self, request):
"""Update homeassistant."""
async def stats(self, request: web.Request) -> Dict[Any, str]:
"""Return resource information."""
stats = await self.sys_homeassistant.stats()
if not stats:
raise APIError("No stats available")
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 Home Assistant."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.config.last_homeassistant)
version = body.get(ATTR_VERSION, self.sys_homeassistant.latest_version)
if self.homeassistant.in_progress:
raise RuntimeError("Other task is in progress")
if version == self.homeassistant.version:
raise RuntimeError("Version is already in use")
return await asyncio.shield(
self.homeassistant.update(version), loop=self.loop)
await asyncio.shield(self.sys_homeassistant.update(version))
@api_process
async def restart(self, request):
"""Restart homeassistant."""
if self.homeassistant.in_progress:
raise RuntimeError("Other task is in progress")
def stop(self, request: web.Request) -> Coroutine:
"""Stop Home Assistant."""
return asyncio.shield(self.sys_homeassistant.stop())
return await asyncio.shield(
self.homeassistant.restart(), loop=self.loop)
@api_process
def start(self, request: web.Request) -> Coroutine:
"""Start Home Assistant."""
return asyncio.shield(self.sys_homeassistant.start())
@api_process_raw
def logs(self, request):
"""Return homeassistant docker logs.
@api_process
def restart(self, request: web.Request) -> Coroutine:
"""Restart Home Assistant."""
return asyncio.shield(self.sys_homeassistant.restart())
Return a coroutine.
"""
return self.homeassistant.logs()
@api_process
def rebuild(self, request: web.Request) -> Coroutine:
"""Rebuild Home Assistant."""
return asyncio.shield(self.sys_homeassistant.rebuild())
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Coroutine:
"""Return Home Assistant Docker logs."""
return self.sys_homeassistant.logs()
@api_process
async def check(self, request: web.Request) -> None:
"""Check configuration of Home Assistant."""
result = await self.sys_homeassistant.check_config()
if not result.valid:
raise APIError(result.log)

View File

@@ -1,60 +1,109 @@
"""Init file for HassIO host rest api."""
"""Init file for Hass.io host RESTful API."""
import asyncio
import logging
import voluptuous as vol
from .util import api_process_hostcontrol, api_process, api_validate
from .utils import api_process, api_validate
from ..const import (
ATTR_VERSION, ATTR_LAST_VERSION, ATTR_TYPE, ATTR_HOSTNAME, ATTR_FEATURES,
ATTR_OS)
ATTR_HOSTNAME,
ATTR_FEATURES,
ATTR_KERNEL,
ATTR_OPERATING_SYSTEM,
ATTR_CHASSIS,
ATTR_DEPLOYMENT,
ATTR_STATE,
ATTR_NAME,
ATTR_DESCRIPTON,
ATTR_SERVICES,
ATTR_CPE,
)
from ..coresys import CoreSysAttributes
_LOGGER = logging.getLogger(__name__)
SCHEMA_VERSION = vol.Schema({
vol.Optional(ATTR_VERSION): vol.Coerce(str),
})
SERVICE = "service"
SCHEMA_OPTIONS = vol.Schema({vol.Optional(ATTR_HOSTNAME): vol.Coerce(str)})
class APIHost(object):
"""Handle rest api for host functions."""
def __init__(self, config, loop, host_control):
"""Initialize host rest api part."""
self.config = config
self.loop = loop
self.host_control = host_control
class APIHost(CoreSysAttributes):
"""Handle RESTful API for host functions."""
@api_process
async def info(self, request):
"""Return host information."""
return {
ATTR_TYPE: self.host_control.type,
ATTR_VERSION: self.host_control.version,
ATTR_LAST_VERSION: self.host_control.last_version,
ATTR_FEATURES: self.host_control.features,
ATTR_HOSTNAME: self.host_control.hostname,
ATTR_OS: self.host_control.os_info,
ATTR_CHASSIS: self.sys_host.info.chassis,
ATTR_CPE: self.sys_host.info.cpe,
ATTR_FEATURES: self.sys_host.supperted_features,
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_OPERATING_SYSTEM: self.sys_host.info.operating_system,
ATTR_DEPLOYMENT: self.sys_host.info.deployment,
ATTR_KERNEL: self.sys_host.info.kernel,
}
@api_process_hostcontrol
@api_process
async def options(self, request):
"""Edit host settings."""
body = await api_validate(SCHEMA_OPTIONS, request)
# hostname
if ATTR_HOSTNAME in body:
await asyncio.shield(
self.sys_host.control.set_hostname(body[ATTR_HOSTNAME])
)
@api_process
def reboot(self, request):
"""Reboot host."""
return self.host_control.reboot()
return asyncio.shield(self.sys_host.control.reboot())
@api_process_hostcontrol
@api_process
def shutdown(self, request):
"""Poweroff host."""
return self.host_control.shutdown()
return asyncio.shield(self.sys_host.control.shutdown())
@api_process_hostcontrol
async def update(self, request):
"""Update host OS."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.host_control.last_version)
@api_process
def reload(self, request):
"""Reload host data."""
return asyncio.shield(self.sys_host.reload())
if version == self.host_control.version:
raise RuntimeError("Version is already in use")
@api_process
async def services(self, request):
"""Return list of available services."""
services = []
for unit in self.sys_host.services:
services.append(
{
ATTR_NAME: unit.name,
ATTR_DESCRIPTON: unit.description,
ATTR_STATE: unit.state,
}
)
return await asyncio.shield(
self.host_control.update(version=version), loop=self.loop)
return {ATTR_SERVICES: services}
@api_process
def service_start(self, request):
"""Start a service."""
unit = request.match_info.get(SERVICE)
return asyncio.shield(self.sys_host.services.start(unit))
@api_process
def service_stop(self, request):
"""Stop a service."""
unit = request.match_info.get(SERVICE)
return asyncio.shield(self.sys_host.services.stop(unit))
@api_process
def service_reload(self, request):
"""Reload a service."""
unit = request.match_info.get(SERVICE)
return asyncio.shield(self.sys_host.services.reload(unit))
@api_process
def service_restart(self, request):
"""Restart a service."""
unit = request.match_info.get(SERVICE)
return asyncio.shield(self.sys_host.services.restart(unit))

42
hassio/api/info.py Normal file
View File

@@ -0,0 +1,42 @@
"""Init file for Hass.io info RESTful API."""
import logging
from typing import Any, Dict
from aiohttp import web
from ..const import (
ATTR_ARCH,
ATTR_CHANNEL,
ATTR_HASSOS,
ATTR_HOMEASSISTANT,
ATTR_HOSTNAME,
ATTR_LOGGING,
ATTR_MACHINE,
ATTR_SUPERVISOR,
ATTR_SUPPORTED_ARCH,
ATTR_TIMEZONE,
)
from ..coresys import CoreSysAttributes
from .utils import api_process
_LOGGER = logging.getLogger(__name__)
class APIInfo(CoreSysAttributes):
"""Handle RESTful API for info functions."""
@api_process
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Show system info."""
return {
ATTR_SUPERVISOR: self.sys_supervisor.version,
ATTR_HOMEASSISTANT: self.sys_homeassistant.version,
ATTR_HASSOS: self.sys_hassos.version,
ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_MACHINE: self.sys_machine,
ATTR_ARCH: self.sys_arch.default,
ATTR_SUPPORTED_ARCH: self.sys_arch.supported,
ATTR_CHANNEL: self.sys_updater.channel,
ATTR_LOGGING: self.sys_config.logging,
ATTR_TIMEZONE: self.sys_timezone,
}

263
hassio/api/ingress.py Normal file
View File

@@ -0,0 +1,263 @@
"""Hass.io Add-on ingress service."""
import asyncio
from ipaddress import ip_address
import logging
from typing import Any, Dict, Union
import aiohttp
from aiohttp import hdrs, web
from aiohttp.web_exceptions import (
HTTPBadGateway,
HTTPServiceUnavailable,
HTTPUnauthorized,
)
from multidict import CIMultiDict, istr
from ..addons.addon import Addon
from ..const import (
ATTR_ADMIN,
ATTR_ICON,
ATTR_SESSION,
ATTR_TITLE,
ATTR_PANELS,
ATTR_ENABLE,
COOKIE_INGRESS,
HEADER_TOKEN,
REQUEST_FROM,
)
from ..coresys import CoreSysAttributes
from .utils import api_process
_LOGGER = logging.getLogger(__name__)
class APIIngress(CoreSysAttributes):
"""Ingress view to handle add-on webui routing."""
def _extract_addon(self, request: web.Request) -> Addon:
"""Return addon, throw an exception it it doesn't exist."""
token = request.match_info.get("token")
# Find correct add-on
addon = self.sys_ingress.get(token)
if not addon:
_LOGGER.warning("Ingress for %s not available", token)
raise HTTPServiceUnavailable()
return addon
def _check_ha_access(self, request: web.Request) -> None:
if request[REQUEST_FROM] != self.sys_homeassistant:
_LOGGER.warning("Ingress is only available behind Home Assistant")
raise HTTPUnauthorized()
def _create_url(self, addon: Addon, path: str) -> str:
"""Create URL to container."""
return f"http://{addon.ip_address}:{addon.ingress_port}/{path}"
@api_process
async def panels(self, request: web.Request) -> Dict[str, Any]:
"""Create a list of panel data."""
addons = {}
for addon in self.sys_ingress.addons:
addons[addon.slug] = {
ATTR_TITLE: addon.panel_title,
ATTR_ICON: addon.panel_icon,
ATTR_ADMIN: addon.panel_admin,
ATTR_ENABLE: addon.ingress_panel,
}
return {ATTR_PANELS: addons}
@api_process
async def create_session(self, request: web.Request) -> Dict[str, Any]:
"""Create a new session."""
self._check_ha_access(request)
session = self.sys_ingress.create_session()
return {ATTR_SESSION: session}
async def handler(
self, request: web.Request
) -> Union[web.Response, web.StreamResponse, web.WebSocketResponse]:
"""Route data to Hass.io ingress service."""
self._check_ha_access(request)
# Check Ingress Session
session = request.cookies.get(COOKIE_INGRESS)
if not self.sys_ingress.validate_session(session):
_LOGGER.warning("No valid ingress session %s", session)
raise HTTPUnauthorized()
# Process requests
addon = self._extract_addon(request)
path = request.match_info.get("path")
try:
# Websocket
if _is_websocket(request):
return await self._handle_websocket(request, addon, path)
# Request
return await self._handle_request(request, addon, path)
except aiohttp.ClientError as err:
_LOGGER.error("Ingress error: %s", err)
raise HTTPBadGateway() from None
async def _handle_websocket(
self, request: web.Request, addon: Addon, path: str
) -> web.WebSocketResponse:
"""Ingress route for websocket."""
if hdrs.SEC_WEBSOCKET_PROTOCOL in request.headers:
req_protocols = [
str(proto.strip())
for proto in request.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(",")
]
else:
req_protocols = ()
ws_server = web.WebSocketResponse(
protocols=req_protocols, autoclose=False, autoping=False
)
await ws_server.prepare(request)
# Preparing
url = self._create_url(addon, path)
source_header = _init_header(request, addon)
# Support GET query
if request.query_string:
url = "{}?{}".format(url, request.query_string)
# Start proxy
async with self.sys_websession.ws_connect(
url,
headers=source_header,
protocols=req_protocols,
autoclose=False,
autoping=False,
) as ws_client:
# Proxy requests
await asyncio.wait(
[
_websocket_forward(ws_server, ws_client),
_websocket_forward(ws_client, ws_server),
],
return_when=asyncio.FIRST_COMPLETED,
)
return ws_server
async def _handle_request(
self, request: web.Request, addon: Addon, path: str
) -> Union[web.Response, web.StreamResponse]:
"""Ingress route for request."""
url = self._create_url(addon, path)
data = await request.read()
source_header = _init_header(request, addon)
async with self.sys_websession.request(
request.method,
url,
headers=source_header,
params=request.query,
allow_redirects=False,
data=data,
) as result:
headers = _response_header(result)
# Simple request
if (
hdrs.CONTENT_LENGTH in result.headers
and int(result.headers.get(hdrs.CONTENT_LENGTH, 0)) < 4_194_000
):
# Return Response
body = await result.read()
return web.Response(
headers=headers,
status=result.status,
content_type=result.content_type,
body=body,
)
# Stream response
response = web.StreamResponse(status=result.status, headers=headers)
response.content_type = result.content_type
try:
await response.prepare(request)
async for data in result.content.iter_chunked(4096):
await response.write(data)
except (aiohttp.ClientError, aiohttp.ClientPayloadError) as err:
_LOGGER.error("Stream error with %s: %s", url, err)
return response
def _init_header(
request: web.Request, addon: str
) -> Union[CIMultiDict, Dict[str, str]]:
"""Create initial header."""
headers = {}
# filter flags
for name, value in request.headers.items():
if name in (hdrs.CONTENT_LENGTH, hdrs.CONTENT_ENCODING, istr(HEADER_TOKEN)):
continue
headers[name] = value
# Update X-Forwarded-For
forward_for = request.headers.get(hdrs.X_FORWARDED_FOR)
connected_ip = ip_address(request.transport.get_extra_info("peername")[0])
headers[hdrs.X_FORWARDED_FOR] = f"{forward_for}, {connected_ip!s}"
return headers
def _response_header(response: aiohttp.ClientResponse) -> Dict[str, str]:
"""Create response header."""
headers = {}
for name, value in response.headers.items():
if name in (
hdrs.TRANSFER_ENCODING,
hdrs.CONTENT_LENGTH,
hdrs.CONTENT_TYPE,
hdrs.CONTENT_ENCODING,
):
continue
headers[name] = value
return headers
def _is_websocket(request: web.Request) -> bool:
"""Return True if request is a websocket."""
headers = request.headers
if (
"upgrade" in headers.get(hdrs.CONNECTION, "").lower()
and headers.get(hdrs.UPGRADE, "").lower() == "websocket"
):
return True
return False
async def _websocket_forward(ws_from, ws_to):
"""Handle websocket message directly."""
try:
async for msg in ws_from:
if msg.type == aiohttp.WSMsgType.TEXT:
await ws_to.send_str(msg.data)
elif msg.type == aiohttp.WSMsgType.BINARY:
await ws_to.send_bytes(msg.data)
elif msg.type == aiohttp.WSMsgType.PING:
await ws_to.ping()
elif msg.type == aiohttp.WSMsgType.PONG:
await ws_to.pong()
elif ws_to.closed:
await ws_to.close(code=ws_to.close_code, message=msg.extra)
except RuntimeError:
_LOGGER.warning("Ingress Websocket runtime error")

View File

@@ -1,26 +0,0 @@
"""Init file for HassIO network rest api."""
import logging
from .util import api_process_hostcontrol
_LOGGER = logging.getLogger(__name__)
class APINetwork(object):
"""Handle rest api for network functions."""
def __init__(self, config, loop, host_control):
"""Initialize network rest api part."""
self.config = config
self.loop = loop
self.host_control = host_control
@api_process_hostcontrol
def info(self, request):
"""Show network settings."""
pass
@api_process_hostcontrol
def options(self, request):
"""Edit network settings."""
pass

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
/**
@license
Copyright (c) 2017 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
*/
/**
@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
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./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","catch","Error","createHassioSession","sent","_slicedToArray","ingress","t0","console","error","alert","message","history","back","stop","css","_templateObject3","LitElement"],"mappings":"4gSAmBCA,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,GAAWY,MAAM,WAC/C,MAAM,IAAIC,MAAM,iCAElBC,YAAoBrC,KAAKkC,MAAMC,MAAM,WACnC,MAAM,IAAIC,MAAM,2CAPxB,UAAAZ,EAAAI,EAAAU,KAAAb,EAAAc,EAAAf,EAAA,IAEWX,EAFXY,EAAA,IAWee,QAXf,CAAAZ,EAAAE,KAAA,cAYY,IAAIM,MAAM,wCAZtB,OAeIpC,KAAKC,OAASY,EAflBe,EAAAE,KAAA,iBAAAF,EAAAC,KAAA,GAAAD,EAAAa,GAAAb,EAAA,SAkBIc,QAAQC,MAARf,EAAAa,IACAG,MAAMhB,EAAAa,GAAII,SAAW,mCACrBC,QAAQC,OApBZ,yBAAAnB,EAAAoB,SAAA1B,EAAAtB,KAAA,yRAwBA,WACE,OAAOiD,YAAPC,UA7D4BC","file":"chunk.5dd33a3a20657ed46a19.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 {\n createHassioSession,\n HassioAddonDetails,\n fetchHassioAddonInfo,\n} from \"../../../src/data/hassio\";\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 | void {\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

View File

@@ -0,0 +1,189 @@
/**
* @license
* Copyright (c) 2017 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
*/
/**
@license
Copyright (c) 2019 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
*/
/**
@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
*/
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/**
* @license
* Copyright 2016 Google Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @license
* Copyright 2018 Google Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
@license
Copyright (c) 2016 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
*/
/**
@license
Copyright (c) 2017 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
*/
/**
* @license
* Copyright (c) 2018 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
*/
/**
@license
Copyright (c) 2014 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
*/
/**
@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
*/
/**
@license
Copyright (c) 2016 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
*/
/*!
* Fuse.js v3.4.4 - Lightweight fuzzy-search (http://fusejs.io)
*
* Copyright (c) 2012-2017 Kirollos Risk (http://kiro.me)
* All Rights Reserved. Apache Software License 2.0
*
* http://www.apache.org/licenses/LICENSE-2.0
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
/**
@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
*/
/**
@license
Copyright (c) 2017 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
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{101:function(n,r,t){"use strict";t.r(r),t.d(r,"marked",function(){return a}),t.d(r,"filterXSS",function(){return c});var e=t(124),i=t.n(e),o=t(126),u=t.n(o),a=i.a,c=u.a}}]);
//# sourceMappingURL=chunk.7f8cce5798f837214ef8.js.map

Binary file not shown.

View File

@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///../src/resources/load_markdown.js"],"names":["__webpack_require__","r","__webpack_exports__","d","marked","filterXSS","marked__WEBPACK_IMPORTED_MODULE_0__","marked__WEBPACK_IMPORTED_MODULE_0___default","n","xss__WEBPACK_IMPORTED_MODULE_1__","xss__WEBPACK_IMPORTED_MODULE_1___default","marked_","filterXSS_"],"mappings":"0FAAAA,EAAAC,EAAAC,GAAAF,EAAAG,EAAAD,EAAA,2BAAAE,IAAAJ,EAAAG,EAAAD,EAAA,8BAAAG,IAAA,IAAAC,EAAAN,EAAA,KAAAO,EAAAP,EAAAQ,EAAAF,GAAAG,EAAAT,EAAA,KAAAU,EAAAV,EAAAQ,EAAAC,GAGaL,EAASO,IACTN,EAAYO","file":"chunk.7f8cce5798f837214ef8.js","sourcesContent":["import marked_ from \"marked\";\nimport filterXSS_ from \"xss\";\n\nexport const marked = marked_;\nexport const filterXSS = filterXSS_;\n"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,31 @@
/**
@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
*/
/**
@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
*/
/**
@license
Copyright (c) 2016 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
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
/**
@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
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
/**
@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
*/

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
!function(e){function n(n){for(var t,o,a=n[0],i=n[1],f=0,c=[];f<a.length;f++)o=a[f],r[o]&&c.push(r[o][0]),r[o]=0;for(t in i)Object.prototype.hasOwnProperty.call(i,t)&&(e[t]=i[t]);for(u&&u(n);c.length;)c.shift()()}var t={},r={4:0};function o(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}o.e=function(e){var n=[],t=r[e];if(0!==t)if(t)n.push(t[2]);else{var a=new Promise(function(n,o){t=r[e]=[n,o]});n.push(t[2]=a);var i,f=document.createElement("script");f.charset="utf-8",f.timeout=120,o.nc&&f.setAttribute("nonce",o.nc),f.src=function(e){return o.p+"chunk."+{0:"7f411ffa9df152cb8f05",1:"598ae99dfd641ab3a30c",2:"af7784dbf07df8e24819",3:"b15efbd4fb2c8cac0ad4",5:"87d3a6d0178fb26762cf",6:"6f4702eafe52425373ed",7:"5dd33a3a20657ed46a19",8:"7c785f796f428abae18d",9:"7f8cce5798f837214ef8",10:"04bcaa18b59728e10be9",11:"9d7374dae6137783dda4",12:"6685a7f98b13655ab808",13:"f1156b978f6f3143a651"}[e]+".js"}(e),i=function(n){f.onerror=f.onload=null,clearTimeout(u);var t=r[e];if(0!==t){if(t){var o=n&&("load"===n.type?"missing":n.type),a=n&&n.target&&n.target.src,i=new Error("Loading chunk "+e+" failed.\n("+o+": "+a+")");i.type=o,i.request=a,t[1](i)}r[e]=void 0}};var u=setTimeout(function(){i({type:"timeout",target:f})},12e4);f.onerror=f.onload=i,document.head.appendChild(f)}return Promise.all(n)},o.m=e,o.c=t,o.d=function(e,n,t){o.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,n){if(1&n&&(e=o(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(o.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)o.d(t,r,function(n){return e[n]}.bind(null,r));return t},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="/api/hassio/app/",o.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],i=a.push.bind(a);a.push=n,a=a.slice();for(var f=0;f<a.length;f++)n(a[f]);var u=i;o(o.s=0)}([function(e,n,t){window.loadES5Adapter().then(function(){Promise.all([t.e(1),t.e(6)]).then(t.bind(null,2)),Promise.all([t.e(1),t.e(12),t.e(8)]).then(t.bind(null,1))});var r=document.createElement("style");r.innerHTML="\nbody {\n font-family: Roboto, sans-serif;\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n font-weight: 400;\n margin: 0;\n padding: 0;\n height: 100vh;\n}\n",document.head.appendChild(r)}]);
//# sourceMappingURL=entrypoint.js.map

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,38 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Hass.io</title>
<meta name='viewport' content='width=device-width, user-scalable=no'>
<style>
body {
height: 100vh;
margin: 0;
padding: 0;
}
</style>
<script src='/frontend_es5/custom-elements-es5-adapter.js'></script>
</head>
<body>
<hassio-app></hassio-app>
<script>
function addScript(src) {
var e = document.createElement('script');
e.src = src;
document.write(e.outerHTML);
}
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
addScript('/static/webcomponents-lite.js');
}
</script>
<!--
Disabled while we make Home Assistant able to serve the right files.
<script src="./app.js"></script>
-->
<link rel='import' href='./hassio-app.html'>
</body>
</html>

Binary file not shown.

253
hassio/api/proxy.py Normal file
View File

@@ -0,0 +1,253 @@
"""Utils for Home Assistant Proxy."""
import asyncio
from contextlib import asynccontextmanager
import logging
import aiohttp
from aiohttp import web
from aiohttp.web_exceptions import HTTPBadGateway, HTTPUnauthorized
from aiohttp.client_exceptions import ClientConnectorError
from aiohttp.hdrs import CONTENT_TYPE, AUTHORIZATION
import async_timeout
from ..const import HEADER_HA_ACCESS
from ..coresys import CoreSysAttributes
from ..exceptions import HomeAssistantAuthError, HomeAssistantAPIError, APIError
_LOGGER = logging.getLogger(__name__)
class APIProxy(CoreSysAttributes):
"""API Proxy for Home Assistant."""
def _check_access(self, request: web.Request):
"""Check the Hass.io token."""
if AUTHORIZATION in request.headers:
bearer = request.headers[AUTHORIZATION]
hassio_token = bearer.split(" ")[-1]
else:
hassio_token = request.headers.get(HEADER_HA_ACCESS)
addon = self.sys_addons.from_token(hassio_token)
if not addon:
_LOGGER.warning("Unknown Home Assistant API access!")
elif not addon.access_homeassistant_api:
_LOGGER.warning("Not permitted API access: %s", addon.slug)
else:
_LOGGER.debug("%s access from %s", request.path, addon.slug)
return
raise HTTPUnauthorized()
@asynccontextmanager
async def _api_client(self, request: web.Request, path: str, timeout: int = 300):
"""Return a client request with proxy origin for Home Assistant."""
try:
# read data
with async_timeout.timeout(30):
data = await request.read()
if data:
content_type = request.content_type
else:
content_type = None
async with self.sys_homeassistant.make_request(
request.method.lower(),
f"api/{path}",
content_type=content_type,
data=data,
timeout=timeout,
params=request.query,
) as resp:
yield resp
return
except HomeAssistantAuthError:
_LOGGER.error("Authenticate error on API for request %s", path)
except HomeAssistantAPIError:
_LOGGER.error("Error on API for request %s", path)
except aiohttp.ClientError as err:
_LOGGER.error("Client error on API %s request %s", path, err)
except asyncio.TimeoutError:
_LOGGER.error("Client timeout error on API request %s", path)
raise HTTPBadGateway()
async def stream(self, request: web.Request):
"""Proxy HomeAssistant EventStream Requests."""
self._check_access(request)
_LOGGER.info("Home Assistant EventStream start")
async with self._api_client(request, "stream", timeout=None) as client:
response = web.StreamResponse()
response.content_type = request.headers.get(CONTENT_TYPE)
try:
await response.prepare(request)
async for data in client.content:
await response.write(data)
except (aiohttp.ClientError, aiohttp.ClientPayloadError):
pass
_LOGGER.info("Home Assistant EventStream close")
return response
async def api(self, request: web.Request):
"""Proxy Home Assistant API Requests."""
self._check_access(request)
# Normal request
path = request.match_info.get("path", "")
async with self._api_client(request, path) as client:
data = await client.read()
return web.Response(
body=data, status=client.status, content_type=client.content_type
)
async def _websocket_client(self):
"""Initialize a WebSocket API connection."""
url = f"{self.sys_homeassistant.api_url}/api/websocket"
try:
client = await self.sys_websession_ssl.ws_connect(
url, heartbeat=30, verify_ssl=False
)
# Handle authentication
data = await client.receive_json()
if data.get("type") == "auth_ok":
return client
if data.get("type") != "auth_required":
# Invalid protocol
_LOGGER.error("Got unexpected response from HA WebSocket: %s", data)
raise APIError()
if self.sys_homeassistant.refresh_token:
await self.sys_homeassistant.ensure_access_token()
await client.send_json(
{
"type": "auth",
"access_token": self.sys_homeassistant.access_token,
}
)
else:
await client.send_json(
{
"type": "auth",
"api_password": self.sys_homeassistant.api_password,
}
)
data = await client.receive_json()
if data.get("type") == "auth_ok":
return client
# Renew the Token is invalid
if (
data.get("type") == "invalid_auth"
and self.sys_homeassistant.refresh_token
):
self.sys_homeassistant.access_token = None
return await self._websocket_client()
raise HomeAssistantAuthError()
except (RuntimeError, ValueError, ClientConnectorError) as err:
_LOGGER.error("Client error on WebSocket API %s.", err)
except HomeAssistantAuthError:
_LOGGER.error("Failed authentication to Home Assistant WebSocket")
raise APIError()
async def websocket(self, request: web.Request):
"""Initialize a WebSocket API connection."""
_LOGGER.info("Home Assistant WebSocket API request initialize")
# init server
server = web.WebSocketResponse(heartbeat=30)
await server.prepare(request)
# handle authentication
try:
await server.send_json(
{"type": "auth_required", "ha_version": self.sys_homeassistant.version}
)
# Check API access
response = await server.receive_json()
hassio_token = response.get("api_password") or response.get("access_token")
addon = self.sys_addons.from_token(hassio_token)
if not addon or not addon.access_homeassistant_api:
_LOGGER.warning("Unauthorized WebSocket access!")
await server.send_json(
{"type": "auth_invalid", "message": "Invalid access"}
)
return server
_LOGGER.info("WebSocket access from %s", addon.slug)
await server.send_json(
{"type": "auth_ok", "ha_version": self.sys_homeassistant.version}
)
except (RuntimeError, ValueError) as err:
_LOGGER.error("Can't initialize handshake: %s", err)
return server
# init connection to hass
try:
client = await self._websocket_client()
except APIError:
return server
_LOGGER.info("Home Assistant WebSocket API request running")
try:
client_read = None
server_read = None
while not server.closed and not client.closed:
if not client_read:
client_read = self.sys_create_task(client.receive_str())
if not server_read:
server_read = self.sys_create_task(server.receive_str())
# wait until data need to be processed
await asyncio.wait(
[client_read, server_read], return_when=asyncio.FIRST_COMPLETED
)
# server
if server_read.done() and not client.closed:
server_read.exception()
await client.send_str(server_read.result())
server_read = None
# client
if client_read.done() and not server.closed:
client_read.exception()
await server.send_str(client_read.result())
client_read = None
except asyncio.CancelledError:
pass
except (RuntimeError, ConnectionError, TypeError) as err:
_LOGGER.info("Home Assistant WebSocket API error: %s", err)
finally:
if client_read:
client_read.cancel()
if server_read:
server_read.cancel()
# close connections
if not client.closed:
await client.close()
if not server.closed:
await server.close()
_LOGGER.info("Home Assistant WebSocket API connection is closed")
return server

148
hassio/api/security.py Normal file
View File

@@ -0,0 +1,148 @@
"""Handle security part of this API."""
import logging
import re
from aiohttp.web import middleware
from aiohttp.web_exceptions import HTTPUnauthorized, HTTPForbidden
from ..const import (
HEADER_TOKEN,
REQUEST_FROM,
ROLE_ADMIN,
ROLE_DEFAULT,
ROLE_HOMEASSISTANT,
ROLE_MANAGER,
ROLE_BACKUP,
)
from ..coresys import CoreSysAttributes
_LOGGER = logging.getLogger(__name__)
# fmt: off
# Block Anytime
BLACKLIST = re.compile(
r"^(?:"
r"|/homeassistant/api/hassio/.*"
r")$"
)
# Free to call or have own security concepts
NO_SECURITY_CHECK = re.compile(
r"^(?:"
r"|/homeassistant/api/.*"
r"|/homeassistant/websocket"
r"|/supervisor/ping"
r")$"
)
# Can called by every add-on
ADDONS_API_BYPASS = re.compile(
r"^(?:"
r"|/addons/self/(?!security|update)[^/]+"
r"|/info"
r"|/services.*"
r"|/discovery.*"
r"|/auth"
r")$"
)
# Policy role add-on API access
ADDONS_ROLE_ACCESS = {
ROLE_DEFAULT: re.compile(
r"^(?:"
r"|/[^/]+/info"
r"|/addons"
r")$"
),
ROLE_HOMEASSISTANT: re.compile(
r"^(?:"
r"|/homeassistant/.+"
r")$"
),
ROLE_BACKUP: re.compile(
r"^(?:"
r"|/snapshots.*"
r")$"
),
ROLE_MANAGER: re.compile(
r"^(?:"
r"|/dns/.*"
r"|/homeassistant/.+"
r"|/host/.+"
r"|/hardware/.+"
r"|/hassos/.+"
r"|/supervisor/.+"
r"|/addons(?:/[^/]+/(?!security).+|/reload)?"
r"|/snapshots.*"
r")$"
),
ROLE_ADMIN: re.compile(
r".*"
),
}
# fmt: off
class SecurityMiddleware(CoreSysAttributes):
"""Security middleware functions."""
def __init__(self, coresys):
"""Initialize security middleware."""
self.coresys = coresys
@middleware
async def token_validation(self, request, handler):
"""Check security access of this layer."""
request_from = None
hassio_token = request.headers.get(HEADER_TOKEN)
# Blacklist
if BLACKLIST.match(request.path):
_LOGGER.warning("%s is blacklisted!", request.path)
raise HTTPForbidden()
# Ignore security check
if NO_SECURITY_CHECK.match(request.path):
_LOGGER.debug("Passthrough %s", request.path)
return await handler(request)
# Not token
if not hassio_token:
_LOGGER.warning("No API token provided for %s", request.path)
raise HTTPUnauthorized()
# Home-Assistant
if hassio_token == self.sys_homeassistant.hassio_token:
_LOGGER.debug("%s access from Home Assistant", request.path)
request_from = self.sys_homeassistant
# Host
if hassio_token == self.sys_machine_id:
_LOGGER.debug("%s access from Host", request.path)
request_from = self.sys_host
# Add-on
addon = None
if hassio_token and not request_from:
addon = self.sys_addons.from_token(hassio_token)
# Check Add-on API access
if addon and ADDONS_API_BYPASS.match(request.path):
_LOGGER.debug("Passthrough %s from %s", request.path, addon.slug)
request_from = addon
elif addon and addon.access_hassio_api:
# Check Role
if ADDONS_ROLE_ACCESS[addon.hassio_role].match(request.path):
_LOGGER.info("%s access from %s", request.path, addon.slug)
request_from = addon
else:
_LOGGER.warning("%s no role for %s", request.path, addon.slug)
if request_from:
request[REQUEST_FROM] = request_from
return await handler(request)
_LOGGER.error("Invalid token for access %s", request.path)
raise HTTPForbidden()

82
hassio/api/services.py Normal file
View File

@@ -0,0 +1,82 @@
"""Init file for Hass.io network RESTful API."""
from .utils import api_process, api_validate
from ..const import (
ATTR_AVAILABLE,
ATTR_PROVIDERS,
ATTR_SLUG,
ATTR_SERVICES,
REQUEST_FROM,
PROVIDE_SERVICE,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError, APIForbidden
class APIServices(CoreSysAttributes):
"""Handle RESTful API for services functions."""
def _extract_service(self, request):
"""Return service, throw an exception if it doesn't exist."""
service = self.sys_services.get(request.match_info.get("service"))
if not service:
raise APIError("Service does not exist")
return service
@api_process
async def list(self, request):
"""Show register services."""
services = []
for service in self.sys_services.list_services:
services.append(
{
ATTR_SLUG: service.slug,
ATTR_AVAILABLE: service.enabled,
ATTR_PROVIDERS: service.providers,
}
)
return {ATTR_SERVICES: services}
@api_process
async def set_service(self, request):
"""Write data into a service."""
service = self._extract_service(request)
body = await api_validate(service.schema, request)
addon = request[REQUEST_FROM]
_check_access(request, service.slug)
service.set_service_data(addon, body)
@api_process
async def get_service(self, request):
"""Read data into a service."""
service = self._extract_service(request)
# Access
_check_access(request, service.slug)
if not service.enabled:
raise APIError("Service not enabled")
return service.get_service_data()
@api_process
async def del_service(self, request):
"""Delete data into a service."""
service = self._extract_service(request)
addon = request[REQUEST_FROM]
# Access
_check_access(request, service.slug, True)
service.del_service_data(addon)
def _check_access(request, service, provide=False):
"""Raise error if the rights are wrong."""
addon = request[REQUEST_FROM]
if not addon.services_role.get(service):
raise APIForbidden(f"No access to {service} service!")
if provide and addon.services_role.get(service) != PROVIDE_SERVICE:
raise APIForbidden(f"No access to write {service} service!")

204
hassio/api/snapshots.py Normal file
View File

@@ -0,0 +1,204 @@
"""Init file for Hass.io snapshot RESTful API."""
import asyncio
import logging
from pathlib import Path
from tempfile import TemporaryDirectory
from aiohttp import web
import voluptuous as vol
from .utils import api_process, api_validate
from ..snapshots.validate import ALL_FOLDERS
from ..const import (
ATTR_NAME,
ATTR_SLUG,
ATTR_DATE,
ATTR_ADDONS,
ATTR_REPOSITORIES,
ATTR_HOMEASSISTANT,
ATTR_VERSION,
ATTR_SIZE,
ATTR_FOLDERS,
ATTR_TYPE,
ATTR_SNAPSHOTS,
ATTR_PASSWORD,
ATTR_PROTECTED,
CONTENT_TYPE_TAR,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
_LOGGER = logging.getLogger(__name__)
# pylint: disable=no-value-for-parameter
SCHEMA_RESTORE_PARTIAL = vol.Schema(
{
vol.Optional(ATTR_PASSWORD): vol.Any(None, vol.Coerce(str)),
vol.Optional(ATTR_HOMEASSISTANT): vol.Boolean(),
vol.Optional(ATTR_ADDONS): vol.All([vol.Coerce(str)], vol.Unique()),
vol.Optional(ATTR_FOLDERS): vol.All([vol.In(ALL_FOLDERS)], vol.Unique()),
}
)
SCHEMA_RESTORE_FULL = vol.Schema(
{vol.Optional(ATTR_PASSWORD): vol.Any(None, vol.Coerce(str))}
)
SCHEMA_SNAPSHOT_FULL = vol.Schema(
{
vol.Optional(ATTR_NAME): vol.Coerce(str),
vol.Optional(ATTR_PASSWORD): vol.Any(None, vol.Coerce(str)),
}
)
SCHEMA_SNAPSHOT_PARTIAL = SCHEMA_SNAPSHOT_FULL.extend(
{
vol.Optional(ATTR_ADDONS): vol.All([vol.Coerce(str)], vol.Unique()),
vol.Optional(ATTR_FOLDERS): vol.All([vol.In(ALL_FOLDERS)], vol.Unique()),
}
)
class APISnapshots(CoreSysAttributes):
"""Handle RESTful API for snapshot functions."""
def _extract_snapshot(self, request):
"""Return snapshot, throw an exception if it doesn't exist."""
snapshot = self.sys_snapshots.get(request.match_info.get("snapshot"))
if not snapshot:
raise APIError("Snapshot does not exist")
return snapshot
@api_process
async def list(self, request):
"""Return snapshot list."""
data_snapshots = []
for snapshot in self.sys_snapshots.list_snapshots:
data_snapshots.append(
{
ATTR_SLUG: snapshot.slug,
ATTR_NAME: snapshot.name,
ATTR_DATE: snapshot.date,
ATTR_TYPE: snapshot.sys_type,
ATTR_PROTECTED: snapshot.protected,
}
)
return {ATTR_SNAPSHOTS: data_snapshots}
@api_process
async def reload(self, request):
"""Reload snapshot list."""
await asyncio.shield(self.sys_snapshots.reload())
return True
@api_process
async def info(self, request):
"""Return snapshot info."""
snapshot = self._extract_snapshot(request)
data_addons = []
for addon_data in snapshot.addons:
data_addons.append(
{
ATTR_SLUG: addon_data[ATTR_SLUG],
ATTR_NAME: addon_data[ATTR_NAME],
ATTR_VERSION: addon_data[ATTR_VERSION],
ATTR_SIZE: addon_data[ATTR_SIZE],
}
)
return {
ATTR_SLUG: snapshot.slug,
ATTR_TYPE: snapshot.sys_type,
ATTR_NAME: snapshot.name,
ATTR_DATE: snapshot.date,
ATTR_SIZE: snapshot.size,
ATTR_PROTECTED: snapshot.protected,
ATTR_HOMEASSISTANT: snapshot.homeassistant_version,
ATTR_ADDONS: data_addons,
ATTR_REPOSITORIES: snapshot.repositories,
ATTR_FOLDERS: snapshot.folders,
}
@api_process
async def snapshot_full(self, request):
"""Full-Snapshot a snapshot."""
body = await api_validate(SCHEMA_SNAPSHOT_FULL, request)
snapshot = await asyncio.shield(self.sys_snapshots.do_snapshot_full(**body))
if snapshot:
return {ATTR_SLUG: snapshot.slug}
return False
@api_process
async def snapshot_partial(self, request):
"""Partial-Snapshot a snapshot."""
body = await api_validate(SCHEMA_SNAPSHOT_PARTIAL, request)
snapshot = await asyncio.shield(self.sys_snapshots.do_snapshot_partial(**body))
if snapshot:
return {ATTR_SLUG: snapshot.slug}
return False
@api_process
async def restore_full(self, request):
"""Full-Restore a snapshot."""
snapshot = self._extract_snapshot(request)
body = await api_validate(SCHEMA_RESTORE_FULL, request)
return await asyncio.shield(
self.sys_snapshots.do_restore_full(snapshot, **body)
)
@api_process
async def restore_partial(self, request):
"""Partial-Restore a snapshot."""
snapshot = self._extract_snapshot(request)
body = await api_validate(SCHEMA_RESTORE_PARTIAL, request)
return await asyncio.shield(
self.sys_snapshots.do_restore_partial(snapshot, **body)
)
@api_process
async def remove(self, request):
"""Remove a snapshot."""
snapshot = self._extract_snapshot(request)
return self.sys_snapshots.remove(snapshot)
async def download(self, request):
"""Download a snapshot file."""
snapshot = self._extract_snapshot(request)
_LOGGER.info("Download snapshot %s", snapshot.slug)
response = web.FileResponse(snapshot.tarfile)
response.content_type = CONTENT_TYPE_TAR
return response
@api_process
async def upload(self, request):
"""Upload a snapshot file."""
with TemporaryDirectory(dir=str(self.sys_config.path_tmp)) as temp_dir:
tar_file = Path(temp_dir, f"snapshot.tar")
try:
with tar_file.open("wb") as snapshot:
async for data in request.content.iter_any():
snapshot.write(data)
except OSError as err:
_LOGGER.error("Can't write new snapshot file: %s", err)
return False
except asyncio.CancelledError:
return False
snapshot = await asyncio.shield(
self.sys_snapshots.import_snapshot(tar_file)
)
if snapshot:
return {ATTR_SLUG: snapshot.slug}
return False

View File

@@ -1,168 +1,174 @@
"""Init file for HassIO supervisor rest api."""
"""Init file for Hass.io Supervisor RESTful API."""
import asyncio
import logging
from typing import Any, Awaitable, Dict
from aiohttp import web
import voluptuous as vol
from .util import api_process, api_process_raw, api_validate
from ..addons.util import create_hash_index_list
from ..const import (
ATTR_ADDONS, ATTR_VERSION, ATTR_LAST_VERSION, ATTR_BETA_CHANNEL,
HASSIO_VERSION, ATTR_ADDONS_REPOSITORIES, ATTR_REPOSITORIES,
ATTR_REPOSITORY, ATTR_DESCRIPTON, ATTR_NAME, ATTR_SLUG, ATTR_INSTALLED,
ATTR_DETACHED, ATTR_SOURCE, ATTR_MAINTAINER, ATTR_URL, ATTR_ARCH)
ATTR_ADDONS,
ATTR_ADDONS_REPOSITORIES,
ATTR_ARCH,
ATTR_BLK_READ,
ATTR_BLK_WRITE,
ATTR_CHANNEL,
ATTR_CPU_PERCENT,
ATTR_DEBUG,
ATTR_DEBUG_BLOCK,
ATTR_DESCRIPTON,
ATTR_ICON,
ATTR_INSTALLED,
ATTR_IP_ADDRESS,
ATTR_LAST_VERSION,
ATTR_LOGGING,
ATTR_LOGO,
ATTR_MEMORY_LIMIT,
ATTR_MEMORY_USAGE,
ATTR_MEMORY_PERCENT,
ATTR_NAME,
ATTR_NETWORK_RX,
ATTR_NETWORK_TX,
ATTR_REPOSITORY,
ATTR_SLUG,
ATTR_STATE,
ATTR_TIMEZONE,
ATTR_VERSION,
ATTR_WAIT_BOOT,
CONTENT_TYPE_BINARY,
HASSIO_VERSION,
)
from ..coresys import CoreSysAttributes
from ..exceptions import APIError
from ..utils.validate import validate_timezone
from ..validate import CHANNELS, LOG_LEVEL, REPOSITORIES, WAIT_BOOT
from .utils import api_process, api_process_raw, api_validate
_LOGGER = logging.getLogger(__name__)
SCHEMA_OPTIONS = vol.Schema({
# pylint: disable=no-value-for-parameter
vol.Optional(ATTR_BETA_CHANNEL): vol.Boolean(),
vol.Optional(ATTR_ADDONS_REPOSITORIES): [vol.Url()],
})
# pylint: disable=no-value-for-parameter
SCHEMA_OPTIONS = vol.Schema(
{
vol.Optional(ATTR_CHANNEL): CHANNELS,
vol.Optional(ATTR_ADDONS_REPOSITORIES): REPOSITORIES,
vol.Optional(ATTR_TIMEZONE): validate_timezone,
vol.Optional(ATTR_WAIT_BOOT): WAIT_BOOT,
vol.Optional(ATTR_LOGGING): LOG_LEVEL,
vol.Optional(ATTR_DEBUG): vol.Boolean(),
vol.Optional(ATTR_DEBUG_BLOCK): vol.Boolean(),
}
)
SCHEMA_VERSION = vol.Schema({
vol.Optional(ATTR_VERSION): vol.Coerce(str),
})
SCHEMA_VERSION = vol.Schema({vol.Optional(ATTR_VERSION): vol.Coerce(str)})
class APISupervisor(object):
"""Handle rest api for supervisor functions."""
def __init__(self, config, loop, supervisor, addons, host_control):
"""Initialize supervisor rest api part."""
self.config = config
self.loop = loop
self.supervisor = supervisor
self.addons = addons
self.host_control = host_control
def _addons_list(self, only_installed=False):
"""Return a list of addons."""
detached = self.addons.list_detached
if only_installed:
addons = self.addons.data_installed
else:
addons = self.addons.data_all
data = []
for addon, values in addons.items():
i_version = self.addons.version_installed(addon)
data.append({
ATTR_NAME: values[ATTR_NAME],
ATTR_SLUG: addon,
ATTR_DESCRIPTON: values[ATTR_DESCRIPTON],
ATTR_VERSION: values[ATTR_VERSION],
ATTR_INSTALLED: i_version,
ATTR_ARCH: values[ATTR_ARCH],
ATTR_DETACHED: addon in detached,
ATTR_REPOSITORY: values[ATTR_REPOSITORY],
})
return data
def _repositories_list(self):
"""Return a list of addons repositories."""
data = []
list_id = create_hash_index_list(self.config.addons_repositories)
for repository in self.addons.list_repositories:
data.append({
ATTR_SLUG: repository[ATTR_SLUG],
ATTR_NAME: repository[ATTR_NAME],
ATTR_SOURCE: list_id.get(repository[ATTR_SLUG]),
ATTR_URL: repository.get(ATTR_URL),
ATTR_MAINTAINER: repository.get(ATTR_MAINTAINER),
})
return data
class APISupervisor(CoreSysAttributes):
"""Handle RESTful API for Supervisor functions."""
@api_process
async def ping(self, request):
"""Return ok for signal that the api is ready."""
"""Return ok for signal that the API is ready."""
return True
@api_process
async def info(self, request):
async def info(self, request: web.Request) -> Dict[str, Any]:
"""Return host information."""
list_addons = []
for addon in self.sys_addons.installed:
list_addons.append(
{
ATTR_NAME: addon.name,
ATTR_SLUG: addon.slug,
ATTR_DESCRIPTON: addon.description,
ATTR_STATE: await addon.state(),
ATTR_VERSION: addon.latest_version,
ATTR_INSTALLED: addon.version,
ATTR_REPOSITORY: addon.repository,
ATTR_ICON: addon.with_icon,
ATTR_LOGO: addon.with_logo,
}
)
return {
ATTR_VERSION: HASSIO_VERSION,
ATTR_LAST_VERSION: self.config.last_hassio,
ATTR_BETA_CHANNEL: self.config.upstream_beta,
ATTR_ARCH: self.addons.arch,
ATTR_ADDONS: self._addons_list(only_installed=True),
ATTR_ADDONS_REPOSITORIES: self.config.addons_repositories,
ATTR_LAST_VERSION: self.sys_updater.version_hassio,
ATTR_CHANNEL: self.sys_updater.channel,
ATTR_ARCH: self.sys_supervisor.arch,
ATTR_IP_ADDRESS: str(self.sys_supervisor.ip_address),
ATTR_WAIT_BOOT: self.sys_config.wait_boot,
ATTR_TIMEZONE: self.sys_config.timezone,
ATTR_LOGGING: self.sys_config.logging,
ATTR_ADDONS: list_addons,
ATTR_ADDONS_REPOSITORIES: self.sys_config.addons_repositories,
}
@api_process
async def available_addons(self, request):
"""Return information for all available addons."""
return {
ATTR_ADDONS: self._addons_list(),
ATTR_REPOSITORIES: self._repositories_list(),
}
@api_process
async def options(self, request):
"""Set supervisor options."""
async def options(self, request: web.Request) -> None:
"""Set Supervisor options."""
body = await api_validate(SCHEMA_OPTIONS, request)
if ATTR_BETA_CHANNEL in body:
self.config.upstream_beta = body[ATTR_BETA_CHANNEL]
if ATTR_CHANNEL in body:
self.sys_updater.channel = body[ATTR_CHANNEL]
if ATTR_TIMEZONE in body:
self.sys_config.timezone = body[ATTR_TIMEZONE]
if ATTR_WAIT_BOOT in body:
self.sys_config.wait_boot = body[ATTR_WAIT_BOOT]
if ATTR_DEBUG in body:
self.sys_config.debug = body[ATTR_DEBUG]
if ATTR_DEBUG_BLOCK in body:
self.sys_config.debug_block = body[ATTR_DEBUG_BLOCK]
if ATTR_LOGGING in body:
self.sys_config.logging = body[ATTR_LOGGING]
if ATTR_ADDONS_REPOSITORIES in body:
new = set(body[ATTR_ADDONS_REPOSITORIES])
old = set(self.config.addons_repositories)
await asyncio.shield(self.sys_store.update_repositories(new))
# add new repositories
tasks = [self.addons.add_git_repository(url) for url in
set(new - old)]
if tasks:
await asyncio.shield(
asyncio.wait(tasks, loop=self.loop), loop=self.loop)
# remove old repositories
for url in set(old - new):
self.addons.drop_git_repository(url)
# read repository
self.addons.read_data_from_repositories()
return True
self.sys_updater.save_data()
self.sys_config.save_data()
@api_process
async def update(self, request):
"""Update supervisor OS."""
async def stats(self, request: web.Request) -> Dict[str, Any]:
"""Return resource information."""
stats = await self.sys_supervisor.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 Supervisor OS."""
body = await api_validate(SCHEMA_VERSION, request)
version = body.get(ATTR_VERSION, self.config.last_hassio)
version = body.get(ATTR_VERSION, self.sys_updater.version_hassio)
if version == self.supervisor.version:
raise RuntimeError("Version is already in use")
return await asyncio.shield(
self.supervisor.update(version), loop=self.loop)
if version == self.sys_supervisor.version:
raise APIError("Version {} is already in use".format(version))
await asyncio.shield(self.sys_supervisor.update(version))
@api_process
async def reload(self, request):
"""Reload addons, config ect."""
tasks = [
self.addons.reload(), self.config.fetch_update_infos(),
self.host_control.load()
]
results, _ = await asyncio.shield(
asyncio.wait(tasks, loop=self.loop), loop=self.loop)
def reload(self, request: web.Request) -> Awaitable[None]:
"""Reload add-ons, configuration, etc."""
return asyncio.shield(self.sys_updater.reload())
for result in results:
if result.exception() is not None:
raise RuntimeError("Some reload task fails!")
@api_process
def repair(self, request: web.Request) -> Awaitable[None]:
"""Try to repair the local setup / overlayfs."""
return asyncio.shield(self.sys_core.repair())
return True
@api_process_raw
def logs(self, request):
"""Return supervisor docker logs.
Return a coroutine.
"""
return self.supervisor.logs()
@api_process_raw(CONTENT_TYPE_BINARY)
def logs(self, request: web.Request) -> Awaitable[bytes]:
"""Return supervisor Docker logs."""
return self.sys_supervisor.logs()

View File

@@ -1,103 +0,0 @@
"""Init file for HassIO util for rest api."""
import json
import logging
from aiohttp import web
from aiohttp.web_exceptions import HTTPServiceUnavailable
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..const import (
JSON_RESULT, JSON_DATA, JSON_MESSAGE, RESULT_OK, RESULT_ERROR)
_LOGGER = logging.getLogger(__name__)
def json_loads(data):
"""Extract json from string with support for '' and None."""
try:
return json.loads(data)
except json.JSONDecodeError:
return {}
def api_process(method):
"""Wrap function with true/false calls to rest api."""
async def wrap_api(api, *args, **kwargs):
"""Return api information."""
try:
answer = await method(api, *args, **kwargs)
except RuntimeError as err:
return api_return_error(message=str(err))
if isinstance(answer, dict):
return api_return_ok(data=answer)
elif answer:
return api_return_ok()
return api_return_error()
return wrap_api
def api_process_hostcontrol(method):
"""Wrap HostControl calls to rest api."""
async def wrap_hostcontrol(api, *args, **kwargs):
"""Return host information."""
if not api.host_control.active:
raise HTTPServiceUnavailable()
try:
answer = await method(api, *args, **kwargs)
except RuntimeError as err:
return api_return_error(message=str(err))
if isinstance(answer, dict):
return api_return_ok(data=answer)
elif answer is None:
return api_return_error("Function is not supported")
elif answer:
return api_return_ok()
return api_return_error()
return wrap_hostcontrol
def api_process_raw(method):
"""Wrap function with raw output to rest api."""
async def wrap_api(api, *args, **kwargs):
"""Return api information."""
try:
message = await method(api, *args, **kwargs)
except RuntimeError as err:
message = str(err).encode()
return web.Response(body=message)
return wrap_api
def api_return_error(message=None):
"""Return a API error message."""
return web.json_response({
JSON_RESULT: RESULT_ERROR,
JSON_MESSAGE: message,
}, status=400)
def api_return_ok(data=None):
"""Return a API ok answer."""
return web.json_response({
JSON_RESULT: RESULT_OK,
JSON_DATA: data or {},
})
async def api_validate(schema, request):
"""Validate request data with schema."""
data = await request.json(loads=json_loads)
try:
data = schema(data)
except vol.Invalid as ex:
raise RuntimeError(humanize_error(data, ex)) from None
return data

100
hassio/api/utils.py Normal file
View File

@@ -0,0 +1,100 @@
"""Init file for Hass.io util for RESTful API."""
import json
import logging
from aiohttp import web
import voluptuous as vol
from voluptuous.humanize import humanize_error
from ..const import (
JSON_RESULT,
JSON_DATA,
JSON_MESSAGE,
RESULT_OK,
RESULT_ERROR,
CONTENT_TYPE_BINARY,
)
from ..exceptions import HassioError, APIError, APIForbidden
_LOGGER = logging.getLogger(__name__)
def json_loads(data):
"""Extract json from string with support for '' and None."""
if not data:
return {}
try:
return json.loads(data)
except json.JSONDecodeError:
raise APIError("Invalid json")
def api_process(method):
"""Wrap function with true/false calls to rest api."""
async def wrap_api(api, *args, **kwargs):
"""Return API information."""
try:
answer = await method(api, *args, **kwargs)
except (APIError, APIForbidden) as err:
return api_return_error(message=str(err))
except HassioError:
return api_return_error(message="Unknown Error, see logs")
if isinstance(answer, dict):
return api_return_ok(data=answer)
if isinstance(answer, web.Response):
return answer
elif isinstance(answer, bool) and not answer:
return api_return_error()
return api_return_ok()
return wrap_api
def api_process_raw(content):
"""Wrap content_type into function."""
def wrap_method(method):
"""Wrap function with raw output to rest api."""
async def wrap_api(api, *args, **kwargs):
"""Return api information."""
try:
msg_data = await method(api, *args, **kwargs)
msg_type = content
except (APIError, APIForbidden) as err:
msg_data = str(err).encode()
msg_type = CONTENT_TYPE_BINARY
except HassioError:
msg_data = b""
msg_type = CONTENT_TYPE_BINARY
return web.Response(body=msg_data, content_type=msg_type)
return wrap_api
return wrap_method
def api_return_error(message=None):
"""Return an API error message."""
return web.json_response(
{JSON_RESULT: RESULT_ERROR, JSON_MESSAGE: message}, status=400
)
def api_return_ok(data=None):
"""Return an API ok answer."""
return web.json_response({JSON_RESULT: RESULT_OK, JSON_DATA: data or {}})
async def api_validate(schema, request):
"""Validate request data with schema."""
data = await request.json(loads=json_loads)
try:
data = schema(data)
except vol.Invalid as ex:
raise APIError(humanize_error(data, ex)) from None
return data

91
hassio/arch.py Normal file
View File

@@ -0,0 +1,91 @@
"""Handle Arch for underlay maschine/platforms."""
import logging
from pathlib import Path
import platform
from typing import List
from .coresys import CoreSys, CoreSysAttributes
from .exceptions import HassioArchNotFound, JsonFileError
from .utils.json import read_json_file
_LOGGER = logging.getLogger(__name__)
ARCH_JSON: Path = Path(__file__).parent.joinpath("data/arch.json")
MAP_CPU = {
"armv7": "armv7",
"armv6": "armhf",
"armv8": "aarch64",
"aarch64": "aarch64",
"i686": "i386",
"x86_64": "amd64",
}
class CpuArch(CoreSysAttributes):
"""Manage available architectures."""
def __init__(self, coresys: CoreSys) -> None:
"""Initialize CPU Architecture handler."""
self.coresys = coresys
self._supported_arch: List[str] = []
self._default_arch: str
@property
def default(self) -> str:
"""Return system default arch."""
return self._default_arch
@property
def supervisor(self) -> str:
"""Return supervisor arch."""
return self.sys_supervisor.arch
@property
def supported(self) -> List[str]:
"""Return support arch by CPU/Machine."""
return self._supported_arch
async def load(self) -> None:
"""Load data and initialize default arch."""
try:
arch_data = read_json_file(ARCH_JSON)
except JsonFileError:
_LOGGER.warning("Can't read arch json")
return
native_support = self.detect_cpu()
# Evaluate current CPU/Platform
if not self.sys_machine or self.sys_machine not in arch_data:
_LOGGER.warning("Can't detect underlay machine type!")
self._default_arch = native_support
self._supported_arch.append(self.default)
return
# Use configs from arch.json
self._supported_arch.extend(arch_data[self.sys_machine])
self._default_arch = self.supported[0]
# Make sure native support is in supported list
if native_support not in self._supported_arch:
self._supported_arch.append(native_support)
def is_supported(self, arch_list: List[str]) -> bool:
"""Return True if there is a supported arch by this platform."""
return not set(self.supported).isdisjoint(set(arch_list))
def match(self, arch_list: List[str]) -> str:
"""Return best match for this CPU/Platform."""
for self_arch in self.supported:
if self_arch in arch_list:
return self_arch
raise HassioArchNotFound()
def detect_cpu(self) -> str:
"""Return the arch type of local CPU."""
cpu = platform.machine()
for check, value in MAP_CPU.items():
if cpu.startswith(check):
return value
return self.sys_supervisor.arch

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