mirror of
https://github.com/home-assistant/supervisor.git
synced 2026-01-27 09:57:25 +00:00
Compare commits
7 Commits
fix-core-c
...
2026.01.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec0f7c2b9c | ||
|
|
753021d4d5 | ||
|
|
3e3db696d3 | ||
|
|
4d708d34c8 | ||
|
|
e7a0559692 | ||
|
|
9ad1bf0f1a | ||
|
|
0f30e2cb43 |
@@ -1,4 +1,4 @@
|
||||
aiodns==3.6.1
|
||||
aiodns==4.0.0
|
||||
aiodocker==0.24.0
|
||||
aiohttp==3.13.3
|
||||
atomicwrites-homeassistant==1.4.1
|
||||
@@ -25,7 +25,7 @@ pyudev==0.24.4
|
||||
PyYAML==6.0.3
|
||||
requests==2.32.5
|
||||
securetar==2025.12.0
|
||||
sentry-sdk==2.48.0
|
||||
sentry-sdk==2.49.0
|
||||
setuptools==80.9.0
|
||||
voluptuous==0.16.0
|
||||
dbus-fast==3.1.2
|
||||
|
||||
@@ -8,9 +8,9 @@ pytest-asyncio==1.3.0
|
||||
pytest-cov==7.0.0
|
||||
pytest-timeout==2.4.0
|
||||
pytest==9.0.2
|
||||
ruff==0.14.10
|
||||
ruff==0.14.11
|
||||
time-machine==3.2.0
|
||||
types-docker==7.1.0.20260109
|
||||
types-pyyaml==6.0.12.20250915
|
||||
types-requests==2.32.4.20250913
|
||||
types-requests==2.32.4.20260107
|
||||
urllib3==2.6.3
|
||||
|
||||
@@ -226,19 +226,19 @@ class DockerHomeAssistant(DockerInterface):
|
||||
source=self.sys_config.path_extern_homeassistant.as_posix(),
|
||||
target="/config",
|
||||
read_only=False,
|
||||
).to_dict(),
|
||||
),
|
||||
DockerMount(
|
||||
type=MountType.BIND,
|
||||
source=self.sys_config.path_extern_ssl.as_posix(),
|
||||
target="/ssl",
|
||||
read_only=True,
|
||||
).to_dict(),
|
||||
),
|
||||
DockerMount(
|
||||
type=MountType.BIND,
|
||||
source=self.sys_config.path_extern_share.as_posix(),
|
||||
target="/share",
|
||||
read_only=False,
|
||||
).to_dict(),
|
||||
),
|
||||
],
|
||||
environment={ENV_TIME: self.sys_timezone},
|
||||
)
|
||||
|
||||
@@ -27,6 +27,7 @@ from docker.api.client import APIClient
|
||||
from docker.client import DockerClient
|
||||
from docker.models.containers import Container, ContainerCollection
|
||||
from docker.models.networks import Network
|
||||
from docker.types import Mount
|
||||
from docker.types.daemon import CancellableStream
|
||||
import requests
|
||||
|
||||
@@ -621,6 +622,8 @@ class DockerAPI(CoreSysAttributes):
|
||||
image: str,
|
||||
version: str = "latest",
|
||||
command: str | list[str] | None = None,
|
||||
*,
|
||||
mounts: list[DockerMount] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> CommandReturn:
|
||||
"""Create a temporary container and run command.
|
||||
@@ -632,7 +635,7 @@ class DockerAPI(CoreSysAttributes):
|
||||
|
||||
image_with_tag = f"{image}:{version}"
|
||||
|
||||
_LOGGER.info("Runing command '%s' on %s", command, image_with_tag)
|
||||
_LOGGER.info("Running command '%s' on %s", command, image_with_tag)
|
||||
container = None
|
||||
try:
|
||||
container = self.dockerpy.containers.run(
|
||||
@@ -641,6 +644,11 @@ class DockerAPI(CoreSysAttributes):
|
||||
detach=True,
|
||||
network=self.network.name,
|
||||
use_config_proxy=False,
|
||||
mounts=(
|
||||
[cast(Mount, mount.to_dict()) for mount in mounts]
|
||||
if mounts
|
||||
else None
|
||||
),
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ async def check_server(
|
||||
"""Check a DNS server and report issues."""
|
||||
ip_addr = server[6:] if server.startswith("dns://") else server
|
||||
async with DNSResolver(loop=loop, nameservers=[ip_addr]) as resolver:
|
||||
await resolver.query(DNS_CHECK_HOST, qtype)
|
||||
# following call should be changed to resolver.query() in aiodns 5.x
|
||||
await resolver.query_dns(DNS_CHECK_HOST, qtype)
|
||||
|
||||
|
||||
def setup(coresys: CoreSys) -> CheckBase:
|
||||
|
||||
@@ -10,6 +10,7 @@ import pytest
|
||||
from requests import RequestException
|
||||
|
||||
from supervisor.coresys import CoreSys
|
||||
from supervisor.docker.const import DockerMount, MountBindOptions, MountType
|
||||
from supervisor.docker.manager import CommandReturn, DockerAPI
|
||||
from supervisor.exceptions import DockerError
|
||||
|
||||
@@ -43,6 +44,7 @@ async def test_run_command_success(docker: DockerAPI):
|
||||
use_config_proxy=False,
|
||||
stdout=True,
|
||||
stderr=True,
|
||||
mounts=None,
|
||||
)
|
||||
|
||||
# Verify container cleanup
|
||||
@@ -74,6 +76,7 @@ async def test_run_command_with_defaults(docker: DockerAPI):
|
||||
detach=True,
|
||||
network=docker.network.name,
|
||||
use_config_proxy=False,
|
||||
mounts=None,
|
||||
)
|
||||
|
||||
# Verify container.logs was called with default stdout/stderr
|
||||
@@ -140,6 +143,64 @@ async def test_run_command_custom_stdout_stderr(docker: DockerAPI):
|
||||
assert result.output == b"output"
|
||||
|
||||
|
||||
async def test_run_command_with_mounts(docker: DockerAPI):
|
||||
"""Test command execution with mounts are correctly converted."""
|
||||
# Mock container and its methods
|
||||
mock_container = MagicMock()
|
||||
mock_container.wait.return_value = {"StatusCode": 0}
|
||||
mock_container.logs.return_value = b"output"
|
||||
|
||||
# Mock docker containers.run to return our mock container
|
||||
docker.dockerpy.containers.run.return_value = mock_container
|
||||
|
||||
# Create test mounts
|
||||
mounts = [
|
||||
DockerMount(
|
||||
type=MountType.BIND,
|
||||
source="/dev",
|
||||
target="/dev",
|
||||
read_only=True,
|
||||
bind_options=MountBindOptions(read_only_non_recursive=True),
|
||||
),
|
||||
DockerMount(
|
||||
type=MountType.VOLUME,
|
||||
source="my_volume",
|
||||
target="/data",
|
||||
read_only=False,
|
||||
),
|
||||
]
|
||||
|
||||
# Execute the command with mounts
|
||||
result = docker.run_command(image="alpine", command="test", mounts=mounts)
|
||||
|
||||
# Verify the result
|
||||
assert result.exit_code == 0
|
||||
|
||||
# Check that mounts were converted correctly
|
||||
docker.dockerpy.containers.run.assert_called_once_with(
|
||||
"alpine:latest",
|
||||
command="test",
|
||||
detach=True,
|
||||
network=docker.network.name,
|
||||
use_config_proxy=False,
|
||||
mounts=[
|
||||
{
|
||||
"Type": "bind",
|
||||
"Source": "/dev",
|
||||
"Target": "/dev",
|
||||
"ReadOnly": True,
|
||||
"BindOptions": {"ReadOnlyNonRecursive": True},
|
||||
},
|
||||
{
|
||||
"Type": "volume",
|
||||
"Source": "my_volume",
|
||||
"Target": "/data",
|
||||
"ReadOnly": False,
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("path_extern", "tmp_supervisor_data")
|
||||
async def test_run_container_with_cidfile(coresys: CoreSys, docker: DockerAPI):
|
||||
"""Test container creation with cidfile and bind mount."""
|
||||
|
||||
@@ -18,7 +18,7 @@ def fixture_mock_dns_query():
|
||||
"""Mock aiodns query."""
|
||||
with (
|
||||
patch(
|
||||
"supervisor.resolution.checks.dns_server.DNSResolver.query",
|
||||
"supervisor.resolution.checks.dns_server.DNSResolver.query_dns",
|
||||
new_callable=AsyncMock,
|
||||
),
|
||||
):
|
||||
|
||||
@@ -15,7 +15,7 @@ from supervisor.resolution.const import ContextType, IssueType
|
||||
async def fixture_dns_query() -> AsyncMock:
|
||||
"""Mock aiodns query."""
|
||||
with patch(
|
||||
"supervisor.resolution.checks.dns_server.DNSResolver.query",
|
||||
"supervisor.resolution.checks.dns_server.DNSResolver.query_dns",
|
||||
new_callable=AsyncMock,
|
||||
) as dns_query:
|
||||
yield dns_query
|
||||
|
||||
@@ -15,7 +15,7 @@ from supervisor.resolution.const import ContextType, IssueType
|
||||
async def fixture_dns_query() -> AsyncMock:
|
||||
"""Mock aiodns query."""
|
||||
with patch(
|
||||
"supervisor.resolution.checks.dns_server.DNSResolver.query",
|
||||
"supervisor.resolution.checks.dns_server.DNSResolver.query_dns",
|
||||
new_callable=AsyncMock,
|
||||
) as dns_query:
|
||||
yield dns_query
|
||||
|
||||
Reference in New Issue
Block a user