mirror of
https://github.com/home-assistant/supervisor.git
synced 2026-04-02 08:12:47 +01:00
* Fix environment variable type errors by converting IP addresses to strings Environment variables must be strings, but IPv4Address and IPv4Network objects were being passed directly to container environment dictionaries, causing typeguard validation errors. Changes: - Convert IPv4Address objects to strings in homeassistant.py for SUPERVISOR and HASSIO environment variables - Convert IPv4Network object to string in observer.py for NETWORK_MASK environment variable - Update tests to expect string values instead of IP objects in environment dictionaries - Remove unused ip_network import from test_observer.py Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * Use explicit string conversion for extra_hosts IP addresses Use the !s format specifier in the f-string to explicitly convert IPv4Address objects to strings when building the ExtraHosts list. While f-strings implicitly convert objects to strings, using !s makes the conversion explicit and consistent with the environment variable fixes in the previous commit. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
233 lines
8.4 KiB
Python
233 lines
8.4 KiB
Python
"""Test Home Assistant container."""
|
|
|
|
from ipaddress import IPv4Address
|
|
from unittest.mock import ANY, patch
|
|
|
|
from aiodocker.containers import DockerContainer
|
|
from awesomeversion import AwesomeVersion
|
|
import pytest
|
|
|
|
from supervisor.coresys import CoreSys
|
|
from supervisor.docker.const import (
|
|
DockerMount,
|
|
MountBindOptions,
|
|
MountType,
|
|
PropagationMode,
|
|
)
|
|
from supervisor.docker.homeassistant import DockerHomeAssistant
|
|
from supervisor.docker.manager import DockerAPI
|
|
from supervisor.homeassistant.const import LANDINGPAGE
|
|
|
|
from . import DEV_MOUNT
|
|
|
|
|
|
@pytest.mark.usefixtures("tmp_supervisor_data", "path_extern")
|
|
async def test_homeassistant_start(coresys: CoreSys, container: DockerContainer):
|
|
"""Test starting homeassistant."""
|
|
coresys.homeassistant.version = AwesomeVersion("2023.8.1")
|
|
|
|
with (
|
|
patch.object(DockerAPI, "run", return_value=container.show.return_value) as run,
|
|
patch.object(
|
|
DockerHomeAssistant, "is_running", side_effect=[False, False, True]
|
|
),
|
|
patch("supervisor.homeassistant.core.asyncio.sleep"),
|
|
):
|
|
await coresys.homeassistant.core.start()
|
|
|
|
run.assert_called_once()
|
|
assert run.call_args.kwargs["name"] == "homeassistant"
|
|
assert run.call_args.kwargs["hostname"] == "homeassistant"
|
|
assert run.call_args.kwargs["privileged"] is True
|
|
assert run.call_args.kwargs["oom_score_adj"] == -300
|
|
assert run.call_args.kwargs["device_cgroup_rules"]
|
|
assert run.call_args.kwargs["extra_hosts"] == {
|
|
"supervisor": IPv4Address("172.30.32.2"),
|
|
"observer": IPv4Address("172.30.32.6"),
|
|
}
|
|
assert run.call_args.kwargs["environment"] == {
|
|
"SUPERVISOR": "172.30.32.2",
|
|
"HASSIO": "172.30.32.2",
|
|
"TZ": ANY,
|
|
"SUPERVISOR_TOKEN": ANY,
|
|
"HASSIO_TOKEN": ANY,
|
|
# no "HA_DUPLICATE_LOG_FILE"
|
|
}
|
|
assert run.call_args.kwargs["mounts"] == [
|
|
DEV_MOUNT,
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source="/run/dbus",
|
|
target="/run/dbus",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source="/run/udev",
|
|
target="/run/udev",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.config.path_extern_homeassistant.as_posix(),
|
|
target="/config",
|
|
read_only=False,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.config.path_extern_ssl.as_posix(),
|
|
target="/ssl",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.config.path_extern_share.as_posix(),
|
|
target="/share",
|
|
read_only=False,
|
|
bind_options=MountBindOptions(propagation=PropagationMode.RSLAVE),
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.config.path_extern_media.as_posix(),
|
|
target="/media",
|
|
read_only=False,
|
|
bind_options=MountBindOptions(propagation=PropagationMode.RSLAVE),
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.homeassistant.path_extern_pulse.as_posix(),
|
|
target="/etc/pulse/client.conf",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.plugins.audio.path_extern_pulse.as_posix(),
|
|
target="/run/audio",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.plugins.audio.path_extern_asound.as_posix(),
|
|
target="/etc/asound.conf",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source="/etc/machine-id",
|
|
target="/etc/machine-id",
|
|
read_only=True,
|
|
),
|
|
]
|
|
assert "volumes" not in run.call_args.kwargs
|
|
|
|
|
|
@pytest.mark.usefixtures("tmp_supervisor_data", "path_extern")
|
|
async def test_homeassistant_start_with_duplicate_log_file(
|
|
coresys: CoreSys, container: DockerContainer
|
|
):
|
|
"""Test starting homeassistant with duplicate_log_file enabled."""
|
|
coresys.homeassistant.version = AwesomeVersion("2025.12.0")
|
|
coresys.homeassistant.duplicate_log_file = True
|
|
|
|
with (
|
|
patch.object(DockerAPI, "run", return_value=container.show.return_value) as run,
|
|
patch.object(
|
|
DockerHomeAssistant, "is_running", side_effect=[False, False, True]
|
|
),
|
|
patch("supervisor.homeassistant.core.asyncio.sleep"),
|
|
):
|
|
await coresys.homeassistant.core.start()
|
|
|
|
run.assert_called_once()
|
|
env = run.call_args.kwargs["environment"]
|
|
assert "HA_DUPLICATE_LOG_FILE" in env
|
|
assert env["HA_DUPLICATE_LOG_FILE"] == "1"
|
|
|
|
|
|
@pytest.mark.usefixtures("tmp_supervisor_data", "path_extern")
|
|
async def test_landingpage_start(coresys: CoreSys, container: DockerContainer):
|
|
"""Test starting landingpage."""
|
|
coresys.homeassistant.version = LANDINGPAGE
|
|
|
|
with (
|
|
patch.object(DockerAPI, "run", return_value=container.show.return_value) as run,
|
|
patch.object(DockerHomeAssistant, "is_running", return_value=False),
|
|
):
|
|
await coresys.homeassistant.core.start()
|
|
|
|
run.assert_called_once()
|
|
assert run.call_args.kwargs["name"] == "homeassistant"
|
|
assert run.call_args.kwargs["hostname"] == "homeassistant"
|
|
assert run.call_args.kwargs["privileged"] is False
|
|
assert run.call_args.kwargs["oom_score_adj"] == -300
|
|
assert not run.call_args.kwargs["device_cgroup_rules"]
|
|
assert run.call_args.kwargs["extra_hosts"] == {
|
|
"supervisor": IPv4Address("172.30.32.2"),
|
|
"observer": IPv4Address("172.30.32.6"),
|
|
}
|
|
assert run.call_args.kwargs["environment"] == {
|
|
"SUPERVISOR": "172.30.32.2",
|
|
"HASSIO": "172.30.32.2",
|
|
"TZ": ANY,
|
|
"SUPERVISOR_TOKEN": ANY,
|
|
"HASSIO_TOKEN": ANY,
|
|
# no "HA_DUPLICATE_LOG_FILE"
|
|
}
|
|
assert run.call_args.kwargs["mounts"] == [
|
|
DEV_MOUNT,
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source="/run/dbus",
|
|
target="/run/dbus",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source="/run/udev",
|
|
target="/run/udev",
|
|
read_only=True,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source=coresys.config.path_extern_homeassistant.as_posix(),
|
|
target="/config",
|
|
read_only=False,
|
|
),
|
|
DockerMount(
|
|
type=MountType.BIND,
|
|
source="/etc/machine-id",
|
|
target="/etc/machine-id",
|
|
read_only=True,
|
|
),
|
|
]
|
|
assert "volumes" not in run.call_args.kwargs
|
|
|
|
|
|
async def test_timeout(coresys: CoreSys, container: DockerContainer):
|
|
"""Test timeout for set from S6_SERVICES_GRACETIME."""
|
|
assert coresys.homeassistant.core.instance.timeout == 260
|
|
|
|
# Env missing, remain at default
|
|
await coresys.homeassistant.core.instance.attach(AwesomeVersion("2024.3.0"))
|
|
assert coresys.homeassistant.core.instance.timeout == 260
|
|
|
|
# Set a mock value for env in attrs, see that it changes
|
|
container.show.return_value["Config"] = {
|
|
"Env": [
|
|
"SUPERVISOR=172.30.32.2",
|
|
"HASSIO=172.30.32.2",
|
|
"TZ=America/New_York",
|
|
"SUPERVISOR_TOKEN=abc123",
|
|
"HASSIO_TOKEN=abc123",
|
|
"PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
"LANG=C.UTF-8",
|
|
"S6_BEHAVIOUR_IF_STAGE2_FAILS=2",
|
|
"S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0",
|
|
"S6_CMD_WAIT_FOR_SERVICES=1",
|
|
"S6_SERVICES_READYTIME=50",
|
|
"S6_SERVICES_GRACETIME=300000",
|
|
]
|
|
}
|
|
await coresys.homeassistant.core.instance.attach(AwesomeVersion("2024.3.0"))
|
|
assert coresys.homeassistant.core.instance.timeout == 320
|