mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-12-10 00:39:22 -06:00
* Use Docker's official registry domain detection logic Replace the custom IMAGE_WITH_HOST regex with a proper implementation based on Docker's reference parser (vendor/github.com/distribution/ reference/normalize.go). Changes: - Change DOCKER_HUB from "hub.docker.com" to "docker.io" (official default) - Add DOCKER_HUB_LEGACY for backward compatibility with "hub.docker.com" - Add IMAGE_DOMAIN_REGEX and get_domain() function that properly detects: - localhost (with optional port) - Domains with "." (e.g., ghcr.io, 127.0.0.1) - Domains with ":" port (e.g., myregistry:5000) - IPv6 addresses (e.g., [::1]:5000) - Update credential handling to support both docker.io and hub.docker.com - Add comprehensive tests for domain detection 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Refactor Docker domain detection to utils module Move get_domain function to supervisor/docker/utils.py and rename it to get_domain_from_image for consistency with get_registry_for_image. Use named group in the regex for better readability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Rename domain to registry for consistency Use consistent "registry" terminology throughout the codebase: - Rename get_domain_from_image to get_registry_from_image - Rename IMAGE_DOMAIN_REGEX to IMAGE_REGISTRY_REGEX - Update named group from "domain" to "registry" - Update all related comments and variable names 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
123 lines
4.5 KiB
Python
123 lines
4.5 KiB
Python
"""Test docker login."""
|
|
|
|
import pytest
|
|
|
|
# pylint: disable=protected-access
|
|
from supervisor.coresys import CoreSys
|
|
from supervisor.docker.const import DOCKER_HUB, DOCKER_HUB_LEGACY
|
|
from supervisor.docker.interface import DockerInterface
|
|
from supervisor.docker.utils import get_registry_from_image
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("image_ref", "expected_registry"),
|
|
[
|
|
# No registry - Docker Hub images
|
|
("nginx", None),
|
|
("nginx:latest", None),
|
|
("library/nginx", None),
|
|
("library/nginx:latest", None),
|
|
("homeassistant/amd64-supervisor", None),
|
|
("homeassistant/amd64-supervisor:1.2.3", None),
|
|
# Registry with dot
|
|
("ghcr.io/homeassistant/amd64-supervisor", "ghcr.io"),
|
|
("ghcr.io/homeassistant/amd64-supervisor:latest", "ghcr.io"),
|
|
("myregistry.com/nginx", "myregistry.com"),
|
|
("registry.example.com/org/image:v1", "registry.example.com"),
|
|
("127.0.0.1/myimage", "127.0.0.1"),
|
|
# Registry with port
|
|
("myregistry:5000/myimage", "myregistry:5000"),
|
|
("localhost:5000/myimage", "localhost:5000"),
|
|
("registry.io:5000/org/app:v1", "registry.io:5000"),
|
|
# localhost special case
|
|
("localhost/myimage", "localhost"),
|
|
("localhost/myimage:tag", "localhost"),
|
|
# IPv6
|
|
("[::1]:5000/myimage", "[::1]:5000"),
|
|
("[2001:db8::1]:5000/myimage:tag", "[2001:db8::1]:5000"),
|
|
],
|
|
)
|
|
def test_get_registry_from_image(image_ref: str, expected_registry: str | None):
|
|
"""Test get_registry_from_image extracts registry from image reference.
|
|
|
|
Based on Docker's reference implementation:
|
|
vendor/github.com/distribution/reference/normalize.go
|
|
"""
|
|
assert get_registry_from_image(image_ref) == expected_registry
|
|
|
|
|
|
def test_no_credentials(coresys: CoreSys, test_docker_interface: DockerInterface):
|
|
"""Test no credentials."""
|
|
coresys.docker.config._data["registries"] = {
|
|
DOCKER_HUB: {"username": "Spongebob Squarepants", "password": "Password1!"}
|
|
}
|
|
assert not test_docker_interface._get_credentials("ghcr.io/homeassistant")
|
|
assert not test_docker_interface._get_credentials(
|
|
"ghcr.io/homeassistant/amd64-supervisor"
|
|
)
|
|
|
|
|
|
def test_no_matching_credentials(
|
|
coresys: CoreSys, test_docker_interface: DockerInterface
|
|
):
|
|
"""Test no matching credentials."""
|
|
coresys.docker.config._data["registries"] = {
|
|
DOCKER_HUB: {"username": "Spongebob Squarepants", "password": "Password1!"}
|
|
}
|
|
assert not test_docker_interface._get_credentials("ghcr.io/homeassistant")
|
|
assert not test_docker_interface._get_credentials(
|
|
"ghcr.io/homeassistant/amd64-supervisor"
|
|
)
|
|
|
|
|
|
def test_matching_credentials(coresys: CoreSys, test_docker_interface: DockerInterface):
|
|
"""Test no matching credentials."""
|
|
coresys.docker.config._data["registries"] = {
|
|
"ghcr.io": {"username": "Octocat", "password": "Password1!"},
|
|
DOCKER_HUB: {"username": "Spongebob Squarepants", "password": "Password1!"},
|
|
}
|
|
|
|
credentials = test_docker_interface._get_credentials(
|
|
"ghcr.io/homeassistant/amd64-supervisor"
|
|
)
|
|
assert credentials["registry"] == "ghcr.io"
|
|
|
|
credentials = test_docker_interface._get_credentials(
|
|
"homeassistant/amd64-supervisor"
|
|
)
|
|
assert credentials["username"] == "Spongebob Squarepants"
|
|
assert "registry" not in credentials
|
|
|
|
|
|
def test_legacy_docker_hub_credentials(
|
|
coresys: CoreSys, test_docker_interface: DockerInterface
|
|
):
|
|
"""Test legacy hub.docker.com credentials are used for Docker Hub images."""
|
|
coresys.docker.config._data["registries"] = {
|
|
DOCKER_HUB_LEGACY: {"username": "LegacyUser", "password": "Password1!"},
|
|
}
|
|
|
|
credentials = test_docker_interface._get_credentials(
|
|
"homeassistant/amd64-supervisor"
|
|
)
|
|
assert credentials["username"] == "LegacyUser"
|
|
# No registry should be included for Docker Hub
|
|
assert "registry" not in credentials
|
|
|
|
|
|
def test_docker_hub_preferred_over_legacy(
|
|
coresys: CoreSys, test_docker_interface: DockerInterface
|
|
):
|
|
"""Test docker.io is preferred over legacy hub.docker.com when both exist."""
|
|
coresys.docker.config._data["registries"] = {
|
|
DOCKER_HUB: {"username": "NewUser", "password": "Password1!"},
|
|
DOCKER_HUB_LEGACY: {"username": "LegacyUser", "password": "Password2!"},
|
|
}
|
|
|
|
credentials = test_docker_interface._get_credentials(
|
|
"homeassistant/amd64-supervisor"
|
|
)
|
|
# docker.io should be preferred
|
|
assert credentials["username"] == "NewUser"
|
|
assert "registry" not in credentials
|