Merge pull request #2141 from home-assistant/dev

Release 248
This commit is contained in:
Pascal Vizeli 2020-10-18 16:16:58 +02:00 committed by GitHub
commit ebf0fe8397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
238 changed files with 7865 additions and 7588 deletions

68
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,68 @@
<!--
You are amazing! Thanks for contributing to our project!
Please, DO NOT DELETE ANY TEXT from this template! (unless instructed).
-->
## Proposed change
<!--
Describe the big picture of your changes here to communicate to the
maintainers why we should accept this pull request. If it fixes a bug
or resolves a feature request, be sure to link to that issue in the
additional information section.
-->
## Type of change
<!--
What type of change does your PR introduce to Home Assistant?
NOTE: Please, check only 1! box!
If your PR requires multiple boxes to be checked, you'll most likely need to
split it into multiple PRs. This makes things easier and faster to code review.
-->
- [ ] Dependency upgrade
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (which adds functionality to the supervisor)
- [ ] Breaking change (fix/feature causing existing functionality to break)
- [ ] Code quality improvements to existing code or addition of tests
## Additional information
<!--
Details are important, and help maintainers processing your PR.
Please be sure to fill out additional details, if applicable.
-->
- This PR fixes or closes issue: fixes #
- This PR is related to issue:
- Link to documentation pull request:
## Checklist
<!--
Put an `x` in the boxes that apply. You can also fill these out after
creating the PR. If you're unsure about any of them, don't hesitate to ask.
We're here to help! This is simply a reminder of what we are going to look
for before merging your code.
-->
- [ ] The code change is tested and works locally.
- [ ] Local tests pass. **Your PR cannot be merged unless tests pass**
- [ ] There is no commented out code in this PR.
- [ ] I have followed the [development checklist][dev-checklist]
- [ ] The code has been formatted using Black (`black --fast supervisor tests`)
- [ ] Tests have been added to verify that the new code works.
If API endpoints of add-on configuration are added/changed:
- [ ] Documentation added/updated for [developers.home-assistant.io][docs-repository]
<!--
Thank you for contributing <3
Below, some useful links you could explore:
-->
[dev-checklist]: https://developers.home-assistant.io/docs/en/development_checklist.html
[docs-repository]: https://github.com/home-assistant/developers.home-assistant

View File

@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
with:
python-version: ${{ matrix.python-version }}
- name: Restore Python virtual environment
@ -69,7 +69,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -113,7 +113,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -157,7 +157,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -189,7 +189,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -230,7 +230,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -274,7 +274,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -306,7 +306,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}
@ -350,7 +350,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ matrix.python-version }}
@ -391,7 +391,7 @@ jobs:
-o console_output_style=count \
tests
- name: Upload coverage artifact
uses: actions/upload-artifact@v2.1.4
uses: actions/upload-artifact@v2.2.0
with:
name: coverage-${{ matrix.python-version }}
path: .coverage
@ -404,7 +404,7 @@ jobs:
- name: Check out code from GitHub
uses: actions/checkout@v2
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v2.1.2
uses: actions/setup-python@v2.1.4
id: python
with:
python-version: ${{ env.DEFAULT_PYTHON }}

View File

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

1235
API.md

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +0,0 @@
# https://dev.azure.com/home-assistant
trigger:
batch: true
branches:
include:
- master
- dev
pr:
- dev
variables:
- name: versionHadolint
value: "v1.16.3"
jobs:
- job: "Tox"
pool:
vmImage: "ubuntu-latest"
steps:
- script: |
sudo apt-get update
sudo apt-get install -y libpulse0 libudev1
displayName: "Install Host library"
- task: UsePythonVersion@0
displayName: "Use Python 3.8"
inputs:
versionSpec: "3.8"
- script: pip install tox
displayName: "Install Tox"
- script: tox
displayName: "Run Tox"
- 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"

@ -1 +1 @@
Subproject commit 9dabce1dd76e36e298bb752f7d5b834028f3cce3
Subproject commit 713e0579f8ccc73d1ea6c287d45a61372e5f39b7

View File

@ -1,20 +1,21 @@
aiohttp==3.6.2
aiohttp==3.6.3
async_timeout==3.0.1
attrs==20.2.0
brotlipy==0.7.0
cchardet==2.1.6
colorlog==4.2.1
colorlog==4.4.0
cpe==1.2.1
cryptography==3.1
debugpy==1.0.0rc2
debugpy==1.0.0
docker==4.3.1
gitpython==3.1.8
gitpython==3.1.9
jinja2==2.11.2
packaging==20.4
pulsectl==20.5.1
pytz==2020.1
pyudev==0.22.0
ruamel.yaml==0.15.100
sentry-sdk==0.17.8
sentry-sdk==0.18.0
uvloop==0.14.0
voluptuous==0.12.0
yarl==1.5.1
yarl==1.5.1

View File

@ -1,8 +1,8 @@
black==20.8b1
codecov==2.1.9
codecov==2.1.10
coverage==5.3
flake8-docstrings==1.5.0
flake8==3.8.3
flake8==3.8.4
pre-commit==2.7.1
pydocstyle==5.1.1
pylint==2.6.0
@ -10,5 +10,5 @@ pytest-aiohttp==0.3.0
pytest-asyncio==0.12.0 # NB!: Versions over 0.12.0 breaks pytest-aiohttp (https://github.com/aio-libs/pytest-aiohttp/issues/16)
pytest-cov==2.10.1
pytest-timeout==1.4.2
pytest==6.1.0
pytest==6.1.1
pyupgrade==2.7.2

View File

@ -5,7 +5,7 @@
declare failed_count=0
declare supervisor_state
bashio::log.info "Start local supervisor watchdog..."
bashio::log.info "Starting local supervisor watchdog..."
while [[ failed_count -lt 2 ]];
do
@ -31,4 +31,4 @@ do
done
basio::exit.nok "Watchdog detect issue with Supervisor - take container down!"
basio::exit.nok "Watchdog detected issue with Supervisor - taking container down!"

View File

@ -36,24 +36,24 @@ if __name__ == "__main__":
executor = ThreadPoolExecutor(thread_name_prefix="SyncWorker")
loop.set_default_executor(executor)
_LOGGER.info("Initialize Supervisor setup")
_LOGGER.info("Initializing Supervisor setup")
coresys = loop.run_until_complete(bootstrap.initialize_coresys())
loop.run_until_complete(coresys.core.connect())
bootstrap.supervisor_debugger(coresys)
bootstrap.migrate_system_env(coresys)
_LOGGER.info("Setup Supervisor")
_LOGGER.info("Setting up Supervisor")
loop.run_until_complete(coresys.core.setup())
loop.call_soon_threadsafe(loop.create_task, coresys.core.start())
loop.call_soon_threadsafe(bootstrap.reg_signal, loop, coresys)
try:
_LOGGER.info("Run Supervisor")
_LOGGER.info("Running Supervisor")
loop.run_forever()
finally:
loop.close()
_LOGGER.info("Close Supervisor")
_LOGGER.info("Closing Supervisor")
sys.exit(0)

View File

@ -93,7 +93,7 @@ class AddonManager(CoreSysAttributes):
tasks.append(addon)
# Evaluate add-ons which need to be started
_LOGGER.info("Phase '%s' start %d add-ons", stage, len(tasks))
_LOGGER.info("Phase '%s' starting %d add-ons", stage, len(tasks))
if not tasks:
return
@ -127,7 +127,7 @@ class AddonManager(CoreSysAttributes):
tasks.append(addon)
# Evaluate add-ons which need to be stopped
_LOGGER.info("Phase '%s' stop %d add-ons", stage, len(tasks))
_LOGGER.info("Phase '%s' stopping %d add-ons", stage, len(tasks))
if not tasks:
return
@ -159,7 +159,9 @@ class AddonManager(CoreSysAttributes):
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)
_LOGGER.info(
"Creating Home Assistant add-on data folder %s", addon.path_data
)
addon.path_data.mkdir()
# Setup/Fix AppArmor profile
@ -346,7 +348,7 @@ class AddonManager(CoreSysAttributes):
return
for addon in needs_repair:
_LOGGER.info("Start repair for add-on: %s", addon.slug)
_LOGGER.info("Repairing for add-on: %s", addon.slug)
await self.sys_run_in_executor(
self.sys_docker.network.stale_cleanup, addon.instance.name
)

View File

@ -463,7 +463,7 @@ class Addon(AddonModel):
if not self.path_data.is_dir():
return
_LOGGER.info("Remove add-on data folder %s", self.path_data)
_LOGGER.info("Removing add-on data folder %s", self.path_data)
await remove_data(self.path_data)
def write_pulse(self) -> None:
@ -545,7 +545,7 @@ class Addon(AddonModel):
async def start(self) -> None:
"""Set options and start add-on."""
if await self.instance.is_running():
_LOGGER.warning("%s already running!", self.slug)
_LOGGER.warning("%s is already running!", self.slug)
return
# Access Token
@ -567,7 +567,7 @@ class Addon(AddonModel):
raise AddonsError() from err
except DockerError as err:
self.state = AddonState.ERROR
raise AddonsError(err) from err
raise AddonsError() from err
else:
self.state = AddonState.STARTED
@ -676,7 +676,7 @@ class Addon(AddonModel):
)
try:
_LOGGER.info("Build snapshot for add-on %s", self.slug)
_LOGGER.info("Building 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)
@ -731,7 +731,7 @@ class Addon(AddonModel):
# Check version / restore image
version = data[ATTR_VERSION]
if not await self.instance.exists():
_LOGGER.info("Restore/Install image for addon %s", self.slug)
_LOGGER.info("Restore/Install of image for addon %s", self.slug)
image_file = Path(temp, "image.tar")
if image_file.is_file():
@ -742,7 +742,7 @@ class Addon(AddonModel):
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)
_LOGGER.info("Restore/Update of image for addon %s", self.slug)
with suppress(DockerError):
await self.instance.update(version, restore_image)
else:
@ -754,7 +754,7 @@ class Addon(AddonModel):
"""Restore data."""
shutil.copytree(Path(temp, "data"), self.path_data, symlinks=True)
_LOGGER.info("Restore data for addon %s", self.slug)
_LOGGER.info("Restoring data for addon %s", self.slug)
if self.path_data.is_dir():
await remove_data(self.path_data)
try:
@ -778,4 +778,4 @@ class Addon(AddonModel):
if data[ATTR_STATE] == AddonState.STARTED:
return await self.start()
_LOGGER.info("Finish restore for add-on %s", self.slug)
_LOGGER.info("Finished restore for add-on %s", self.slug)

View File

@ -12,6 +12,7 @@ from .auth import APIAuth
from .cli import APICli
from .discovery import APIDiscovery
from .dns import APICoreDNS
from .docker import APIDocker
from .hardware import APIHardware
from .homeassistant import APIHomeAssistant
from .host import APIHost
@ -22,6 +23,7 @@ from .network import APINetwork
from .observer import APIObserver
from .os import APIOS
from .proxy import APIProxy
from .resolution import APIResoulution
from .security import SecurityMiddleware
from .services import APIServices
from .snapshots import APISnapshots
@ -42,7 +44,10 @@ class RestAPI(CoreSysAttributes):
self.security: SecurityMiddleware = SecurityMiddleware(coresys)
self.webapp: web.Application = web.Application(
client_max_size=MAX_CLIENT_SIZE,
middlewares=[self.security.token_validation],
middlewares=[
self.security.system_validation,
self.security.token_validation,
],
)
# service stuff
@ -51,26 +56,28 @@ class RestAPI(CoreSysAttributes):
async def load(self) -> None:
"""Register REST API Calls."""
self._register_supervisor()
self._register_host()
self._register_os()
self._register_addons()
self._register_audio()
self._register_auth()
self._register_cli()
self._register_observer()
self._register_multicast()
self._register_network()
self._register_discovery()
self._register_dns()
self._register_docker()
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_host()
self._register_info()
self._register_auth()
self._register_dns()
self._register_audio()
self._register_ingress()
self._register_multicast()
self._register_network()
self._register_observer()
self._register_os()
self._register_panel()
self._register_proxy()
self._register_resolution()
self._register_services()
self._register_snapshots()
self._register_supervisor()
def _register_host(self) -> None:
"""Register hostcontrol functions."""
@ -185,6 +192,29 @@ class RestAPI(CoreSysAttributes):
self.webapp.add_routes([web.get("/info", api_info.info)])
def _register_resolution(self) -> None:
"""Register info functions."""
api_resolution = APIResoulution()
api_resolution.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/resolution/info", api_resolution.info),
web.post(
"/resolution/suggestion/{suggestion}",
api_resolution.apply_suggestion,
),
web.delete(
"/resolution/suggestion/{suggestion}",
api_resolution.dismiss_suggestion,
),
web.delete(
"/resolution/issue/{issue}",
api_resolution.dismiss_issue,
),
]
)
def _register_auth(self) -> None:
"""Register auth functions."""
api_auth = APIAuth()
@ -324,7 +354,7 @@ class RestAPI(CoreSysAttributes):
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.delete("/snapshots/{snapshot}", api_snapshots.remove),
web.post(
"/snapshots/{snapshot}/restore/full", api_snapshots.restore_full
),
@ -333,6 +363,8 @@ class RestAPI(CoreSysAttributes):
api_snapshots.restore_partial,
),
web.get("/snapshots/{snapshot}/download", api_snapshots.download),
# Old, remove at end of 2020
web.post("/snapshots/{snapshot}/remove", api_snapshots.remove),
]
)
@ -408,6 +440,20 @@ class RestAPI(CoreSysAttributes):
panel_dir = Path(__file__).parent.joinpath("panel")
self.webapp.add_routes([web.static("/app", panel_dir)])
def _register_docker(self) -> None:
"""Register docker configuration functions."""
api_docker = APIDocker()
api_docker.coresys = self.coresys
self.webapp.add_routes(
[
web.get("/docker/info", api_docker.info),
web.get("/docker/registries", api_docker.registries),
web.post("/docker/registries", api_docker.create_registry),
web.delete("/docker/registries/{hostname}", api_docker.remove_registry),
]
)
async def start(self) -> None:
"""Run RESTful API webserver."""
await self._runner.setup()
@ -420,7 +466,7 @@ class RestAPI(CoreSysAttributes):
except OSError as err:
_LOGGER.critical("Failed to create HTTP server at 0.0.0.0:80 -> %s", err)
else:
_LOGGER.info("Start API on %s", self.sys_docker.network.supervisor)
_LOGGER.info("Starting API on %s", self.sys_docker.network.supervisor)
async def stop(self) -> None:
"""Stop RESTful API webserver."""
@ -431,4 +477,4 @@ class RestAPI(CoreSysAttributes):
await self._site.stop()
await self._runner.cleanup()
_LOGGER.info("Stop API on %s", self.sys_docker.network.supervisor)
_LOGGER.info("Stopping API on %s", self.sys_docker.network.supervisor)

View File

@ -339,7 +339,7 @@ class APIAddons(CoreSysAttributes):
body: Dict[str, Any] = await api_validate(SCHEMA_SECURITY, request)
if ATTR_PROTECTED in body:
_LOGGER.warning("Protected flag changing for %s!", addon.slug)
_LOGGER.warning("Changing protected flag for %s!", addon.slug)
addon.protected = body[ATTR_PROTECTED]
addon.save_persist()

76
supervisor/api/docker.py Normal file
View File

@ -0,0 +1,76 @@
"""Init file for Supervisor Home Assistant RESTful API."""
import logging
from typing import Any, Dict
from aiohttp import web
import voluptuous as vol
from ..const import (
ATTR_HOSTNAME,
ATTR_LOGGING,
ATTR_PASSWORD,
ATTR_REGISTRIES,
ATTR_STORAGE,
ATTR_USERNAME,
ATTR_VERSION,
)
from ..coresys import CoreSysAttributes
from .utils import api_process, api_validate
_LOGGER: logging.Logger = logging.getLogger(__name__)
SCHEMA_DOCKER_REGISTRY = vol.Schema(
{
vol.Coerce(str): {
vol.Required(ATTR_USERNAME): str,
vol.Required(ATTR_PASSWORD): str,
}
}
)
class APIDocker(CoreSysAttributes):
"""Handle RESTful API for Docker configuration."""
@api_process
async def registries(self, request) -> Dict[str, Any]:
"""Return the list of registries."""
data_registries = {}
for hostname, registry in self.sys_docker.config.registries.items():
data_registries[hostname] = {
ATTR_USERNAME: registry[ATTR_USERNAME],
}
return {ATTR_REGISTRIES: data_registries}
@api_process
async def create_registry(self, request: web.Request):
"""Create a new docker registry."""
body = await api_validate(SCHEMA_DOCKER_REGISTRY, request)
for hostname, registry in body.items():
self.sys_docker.config.registries[hostname] = registry
self.sys_docker.config.save_data()
@api_process
async def remove_registry(self, request: web.Request):
"""Delete a docker registry."""
hostname = request.match_info.get(ATTR_HOSTNAME)
del self.sys_docker.config.registries[hostname]
self.sys_docker.config.save_data()
@api_process
async def info(self, request: web.Request):
"""Get docker info."""
data_registries = {}
for hostname, registry in self.sys_docker.config.registries.items():
data_registries[hostname] = {
ATTR_USERNAME: registry[ATTR_USERNAME],
}
return {
ATTR_VERSION: self.sys_docker.info.version,
ATTR_STORAGE: self.sys_docker.info.storage,
ATTR_LOGGING: self.sys_docker.info.logging,
ATTR_REGISTRIES: data_registries,
}

View File

@ -39,6 +39,7 @@ SCHEMA_UPDATE = vol.Schema(
def interface_information(interface: NetworkInterface) -> dict:
"""Return a dict with information of a interface to be used in th API."""
return {
ATTR_INTERFACE: interface.name,
ATTR_IP_ADDRESS: f"{interface.ip_address}/{interface.prefix}",
ATTR_GATEWAY: interface.gateway,
ATTR_ID: interface.id,
@ -69,8 +70,19 @@ class APINetwork(CoreSysAttributes):
async def interface_info(self, request: web.Request) -> Dict[str, Any]:
"""Return network information for a interface."""
req_interface = request.match_info.get(ATTR_INTERFACE)
for interface in self.sys_host.network.interfaces:
if req_interface == self.sys_host.network.interfaces[interface].name:
if req_interface.lower() == "default":
for interface in self.sys_host.network.interfaces:
if not self.sys_host.network.interfaces[interface].primary:
continue
return interface_information(
self.sys_host.network.interfaces[interface]
)
else:
for interface in self.sys_host.network.interfaces:
if req_interface != self.sys_host.network.interfaces[interface].name:
continue
return interface_information(
self.sys_host.network.interfaces[interface]
)

View File

@ -1,9 +1,9 @@
try {
new Function("import('/api/hassio/app/frontend_latest/entrypoint.db541070.js')")();
new Function("import('/api/hassio/app/frontend_latest/entrypoint.cbedde60.js')")();
} catch (err) {
var el = document.createElement('script');
el.src = '/api/hassio/app/frontend_es5/entrypoint.aaeeb8e2.js';
el.src = '/api/hassio/app/frontend_es5/entrypoint.96d2427f.js';
document.body.appendChild(el);
}

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,25 @@
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <http://feross.org>
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use

View File

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

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"version":3,"file":"entrypoint.aaeeb8e2.js","sources":["webpack:///entrypoint.aaeeb8e2.js"],"mappings":";AAAA","sourceRoot":""}

View File

@ -1,3 +1,3 @@
{
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.aaeeb8e2.js"
"entrypoint.js": "/api/hassio/app/frontend_es5/entrypoint.96d2427f.js"
}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.05c74bd6edc0c5c372eb.js","sources":["webpack:///chunk.05c74bd6edc0c5c372eb.js"],"mappings":"AAAA;;;AAoMA;AACA;;;AAGA;;;;;AAKA;;AAEA;AAEA;AACA;;;;;;;AAQA;;;;;AAKA;;AAEA;AAEA;AACA;;;;;;;AAQA;;;;;AAOA;;;;;;;;;;;;;;;;AAuBA;AAknBA;;AAEA;;AAEA;AACA;;AAIA;AA0IA;;;;AAIA;;AAEA;AACA;;;AAGA;;;;AAIA;AACA;;;;;;AAQA;;;;;;;;;;;;;;;;;;;;;;AA6HA;;;AAyGA;AACA;;;;;;;;AAQA;;AAGA;;;AAGA;;AAEA;AACA;;;;AAIA;;;;;;;AAQA;;;AAGA;;;;;AAvCA;;;;;;;;;;;;;;;AA8KA;;;AAkFA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;AApBA;;;;;;;;;;;AA4CA;;;AA8GA;;AAEA;;;;AARA;;;;;;;;;;;;AAiCA;;AAiCA;AACA;AACA;;;AAMA;;;;AA6IA;;;AAMA;AACA;;;AAGA;;AAEA;;AAKA;;AAEA;;AAEA;;AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EA;AAsLA;;;;AAIA;AACA;AACA;AACA;;;AAGA;;;;;;;;AAQA;AACA;AACA;;;;AAIA;AACA;;;AAGA;;;AAGA;AACA;;;;;;;AAOA;;;;;;;;;AASA;;AAEA;AACA;;;;AAIA;;AAEA;;;;AAIA;;;AAGA;;;;AAIA;AACA;AACA;;;AAGA;;;;;;AAMA;;AAEA;AACA;;;;AAIA;;;AAGA;;AAEA;;AAEA;AACA;AAIA;;;;;;AAMA;;AAEA;AACA;;AAEA;AAKA;;AAEA;;;;AAIA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;AAGA;;AAEA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;AACA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;AAKA;;AAEA;AACA;;AAEA;;;;;;AAMA;;;AAGA;;;AAGA;;AAEA;;;;;;;;AAQA;AACA;;;;;AAKA;AACA;;;;;;;;AAQA;AACA;;;;AAIA;AACA;AACA;;;;;;;;;AASA;AACA;;;;AAIA;AACA;AACA;;;;;AAKA;;;AAGA;AACA;AACA;;;;AAIA;AACA;AACA;;;;;;;;AAQA;AACA;;;;AAIA;;AAEA;AACA;;;AAGA;AACA;;;AAGA;AACA;;;;;;AAMA;AACA;;;;AAIA;AACA;;;;AAIA;;AAEA;;;;;;;;;;AAUA;AACA;AACA;;;AAGA;;;AAGA;;;;AAIA;;;AAGA;AACA;;;;AAIA;AACA;AACA;;;;;;AAMA;AACA;;;;;;;;AAQA;;;;AAIA;;;;AAIA;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAocA;;;AAoFA;AACA;AACA;;;AARA;;;;;;AA4BA;AAqGA;;AAEA;;AAEA;AACA;AACA;;;AAGA;;;AAKA;;;;;;;;;AAgBA;;;AAiGA;AACA;;;AAPA;;;;;;AA2BA;;AAmQA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;;;AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

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

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"version":3,"file":"chunk.1fce560aeae04197cd1a.js","sources":["webpack:///chunk.1fce560aeae04197cd1a.js"],"mappings":"AAAA;AA0OA;AACA;AACA;AANA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA","sourceRoot":""}

File diff suppressed because one or more lines are too long

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