mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-12-10 00:39:22 -06:00
Disable timeout for Docker image pull operations (#6391)
* Disable timeout for Docker image pull operations The aiodocker migration introduced a regression where image pulls could timeout during slow downloads. The session-level timeout (900s total) was being applied to pull operations, but docker-py explicitly sets timeout=None for pulls, allowing them to run indefinitely. When aiodocker receives timeout=None, it converts it to ClientTimeout(total=None), which aiohttp treats as "no timeout" (returns TimerNoop instead of enforcing a timeout). This fixes TimeoutError exceptions that could occur during installation on systems with slow network connections or when pulling large images. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix pytests --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3b3db2a9bc
commit
382f0e8aef
@ -474,8 +474,10 @@ class DockerAPI(CoreSysAttributes):
|
|||||||
raises only if the get fails afterwards. Additionally it fires progress reports for the pull
|
raises only if the get fails afterwards. Additionally it fires progress reports for the pull
|
||||||
on the bus so listeners can use that to update status for users.
|
on the bus so listeners can use that to update status for users.
|
||||||
"""
|
"""
|
||||||
|
# Use timeout=None to disable timeout for pull operations, matching docker-py behavior.
|
||||||
|
# aiodocker converts None to ClientTimeout(total=None) which disables the timeout.
|
||||||
async for e in self.images.pull(
|
async for e in self.images.pull(
|
||||||
repository, tag=tag, platform=platform, auth=auth, stream=True
|
repository, tag=tag, platform=platform, auth=auth, stream=True, timeout=None
|
||||||
):
|
):
|
||||||
entry = PullLogEntry.from_pull_log_dict(job_id, e)
|
entry = PullLogEntry.from_pull_log_dict(job_id, e)
|
||||||
if entry.error:
|
if entry.error:
|
||||||
|
|||||||
@ -54,7 +54,7 @@ async def test_docker_image_platform(
|
|||||||
coresys.docker.images.inspect.return_value = {"Id": "test:1.2.3"}
|
coresys.docker.images.inspect.return_value = {"Id": "test:1.2.3"}
|
||||||
await test_docker_interface.install(AwesomeVersion("1.2.3"), "test", arch=cpu_arch)
|
await test_docker_interface.install(AwesomeVersion("1.2.3"), "test", arch=cpu_arch)
|
||||||
coresys.docker.images.pull.assert_called_once_with(
|
coresys.docker.images.pull.assert_called_once_with(
|
||||||
"test", tag="1.2.3", platform=platform, auth=None, stream=True
|
"test", tag="1.2.3", platform=platform, auth=None, stream=True, timeout=None
|
||||||
)
|
)
|
||||||
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
||||||
|
|
||||||
@ -71,7 +71,12 @@ async def test_docker_image_default_platform(
|
|||||||
):
|
):
|
||||||
await test_docker_interface.install(AwesomeVersion("1.2.3"), "test")
|
await test_docker_interface.install(AwesomeVersion("1.2.3"), "test")
|
||||||
coresys.docker.images.pull.assert_called_once_with(
|
coresys.docker.images.pull.assert_called_once_with(
|
||||||
"test", tag="1.2.3", platform="linux/386", auth=None, stream=True
|
"test",
|
||||||
|
tag="1.2.3",
|
||||||
|
platform="linux/386",
|
||||||
|
auth=None,
|
||||||
|
stream=True,
|
||||||
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
||||||
@ -111,7 +116,12 @@ async def test_private_registry_credentials_passed_to_pull(
|
|||||||
expected_auth["registry"] = registry_key
|
expected_auth["registry"] = registry_key
|
||||||
|
|
||||||
coresys.docker.images.pull.assert_called_once_with(
|
coresys.docker.images.pull.assert_called_once_with(
|
||||||
image, tag="1.2.3", platform="linux/amd64", auth=expected_auth, stream=True
|
image,
|
||||||
|
tag="1.2.3",
|
||||||
|
platform="linux/amd64",
|
||||||
|
auth=expected_auth,
|
||||||
|
stream=True,
|
||||||
|
timeout=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -360,7 +370,12 @@ async def test_install_fires_progress_events(
|
|||||||
):
|
):
|
||||||
await test_docker_interface.install(AwesomeVersion("1.2.3"), "test")
|
await test_docker_interface.install(AwesomeVersion("1.2.3"), "test")
|
||||||
coresys.docker.images.pull.assert_called_once_with(
|
coresys.docker.images.pull.assert_called_once_with(
|
||||||
"test", tag="1.2.3", platform="linux/386", auth=None, stream=True
|
"test",
|
||||||
|
tag="1.2.3",
|
||||||
|
platform="linux/386",
|
||||||
|
auth=None,
|
||||||
|
stream=True,
|
||||||
|
timeout=None,
|
||||||
)
|
)
|
||||||
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
||||||
|
|
||||||
@ -817,7 +832,12 @@ async def test_install_progress_containerd_snapshot(
|
|||||||
with patch.object(Supervisor, "arch", PropertyMock(return_value="i386")):
|
with patch.object(Supervisor, "arch", PropertyMock(return_value="i386")):
|
||||||
await test_docker_interface.mock_install()
|
await test_docker_interface.mock_install()
|
||||||
coresys.docker.images.pull.assert_called_once_with(
|
coresys.docker.images.pull.assert_called_once_with(
|
||||||
"test", tag="1.2.3", platform="linux/386", auth=None, stream=True
|
"test",
|
||||||
|
tag="1.2.3",
|
||||||
|
platform="linux/386",
|
||||||
|
auth=None,
|
||||||
|
stream=True,
|
||||||
|
timeout=None,
|
||||||
)
|
)
|
||||||
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
coresys.docker.images.inspect.assert_called_once_with("test:1.2.3")
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user