mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-08-05 15:27:41 +00:00
commit
ebf0fe8397
68
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
68
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal 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
|
22
.github/workflows/ci.yaml
vendored
22
.github/workflows/ci.yaml
vendored
@ -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 }}
|
||||
|
2
.github/workflows/sentry.yaml
vendored
2
.github/workflows/sentry.yaml
vendored
@ -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 }}
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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!"
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
76
supervisor/api/docker.py
Normal 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,
|
||||
}
|
@ -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]
|
||||
)
|
||||
|
@ -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);
|
||||
}
|
||||
|
Binary file not shown.
@ -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
|
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -0,0 +1 @@
|
||||
{"version":3,"file":"chunk.58899b77fdb7b6ef0605.js","sources":["webpack://home-assistant-frontend/chunk.58899b77fdb7b6ef0605.js"],"mappings":"AAAA","sourceRoot":""}
|
@ -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
|
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -1 +0,0 @@
|
||||
{"version":3,"file":"chunk.77f2d29b4f5da94ea7d7.js","sources":["webpack:///chunk.77f2d29b4f5da94ea7d7.js"],"mappings":";AAAA","sourceRoot":""}
|
@ -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
|
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -1 +0,0 @@
|
||||
{"version":3,"file":"chunk.f2d1cbf860fa69dbf667.js","sources":["webpack:///chunk.f2d1cbf860fa69dbf667.js"],"mappings":"AAAA","sourceRoot":""}
|
3
supervisor/api/panel/frontend_es5/entrypoint.96d2427f.js
Normal file
3
supervisor/api/panel/frontend_es5/entrypoint.96d2427f.js
Normal file
File diff suppressed because one or more lines are too long
@ -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
|
BIN
supervisor/api/panel/frontend_es5/entrypoint.96d2427f.js.gz
Normal file
BIN
supervisor/api/panel/frontend_es5/entrypoint.96d2427f.js.gz
Normal file
Binary file not shown.
@ -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
Binary file not shown.
@ -1 +0,0 @@
|
||||
{"version":3,"file":"entrypoint.aaeeb8e2.js","sources":["webpack:///entrypoint.aaeeb8e2.js"],"mappings":";AAAA","sourceRoot":""}
|
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Binary file not shown.
@ -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
Loading…
x
Reference in New Issue
Block a user