mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-09 04:06:42 +00:00
fix(env): keep the registry allowlist on the bare bootstrap layer
909e08311f derived INFINITO_CACHE_REGISTRIES from iter_role_images. That import
walks straight out of the stdlib:
handlers/__init__ -> infinito/cache/registries -> docker.image.discovery
-> cache.yaml -> yaml
and the .env generator runs on the bare bootstrap python, before any dependency
is installed, so test_bare_bootstrap refused it.
Reaching for iter_role_images was also the wrong question. It answers 'which
images do we mirror': it drops every entry without a version: and every image
whose registry is outside _MIRRORABLE_REGISTRIES. A pull-through cache needs
the opposite set -- a registry we do not mirror is one we pay full upstream
cost for on every pull, which is the case the cache exists for. Four registries
were missing for exactly that reason, all with a version: declared and all
real: docker.gitea.com (web-app-gitea), docker.elastic.co (web-app-zammad),
docker.n8n.io (web-app-n8n) and docker-registry.kixdesk.com (web-app-kix).
The handler now reads the image: values itself with a line scan. Only a literal
plain scalar is needed, a value carrying Jinja is skipped because its registry
is unknowable before the templar runs, and split_registry_and_name from
utils.docker.image.ref still owns the parsing -- that module imports only re
and typing, which is the shape the handler README allows.
Measured against the previous derivation: the old set is contained whole, the
four above are added, nothing is dropped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
df4462741a
commit
3f0bca4d83
1 file changed
+38
-7
+38
-7
@@ -11,15 +11,23 @@ keeps it complete by construction: a role that adopts an image from a new
|
||||
registry brings that registry with it. ``BASE`` carries the registries that
|
||||
were configured before this was derived and that no role image names, so
|
||||
turning the list into a derived one cannot silently drop them.
|
||||
|
||||
The scan is a stdlib line parse rather than a YAML load. This module is
|
||||
imported by the ``.env`` generator, which runs on the bare bootstrap python
|
||||
before any dependency is installed, so it must not reach PyYAML - directly or
|
||||
through ``utils.cache.yaml``. Only the ``image:`` value is needed and it is
|
||||
always a plain scalar, so a line match is sufficient; a value carrying Jinja
|
||||
is skipped, because its registry is not knowable before the templar runs.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from utils import PROJECT_ROOT
|
||||
from utils.docker.image.discovery import iter_role_images
|
||||
from utils.docker.image.ref import DOCKER_HUB_REGISTRIES
|
||||
from utils.cache.files import read_text
|
||||
from utils.docker.image.ref import DOCKER_HUB_REGISTRIES, split_registry_and_name
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from utils.env.builder import BuildContext, EnvBuilder
|
||||
@@ -29,6 +37,26 @@ COMMENT = "Registries the pull-through proxy SSL-bumps and caches; derived from
|
||||
|
||||
BASE = frozenset({"gcr.io", "registry.k8s.io"})
|
||||
|
||||
_IMAGE_LINE = re.compile(r"^\s*image:\s*(?P<value>\S+)")
|
||||
|
||||
|
||||
def _image_values() -> set[str]:
|
||||
"""Return every literal ``image:`` value declared under ``roles/``."""
|
||||
values: set[str] = set()
|
||||
for path in sorted((PROJECT_ROOT / "roles").glob("*/meta/services.yml")):
|
||||
try:
|
||||
text = read_text(str(path))
|
||||
except (OSError, UnicodeDecodeError):
|
||||
continue
|
||||
for line in text.splitlines():
|
||||
match = _IMAGE_LINE.match(line)
|
||||
if not match:
|
||||
continue
|
||||
value = match.group("value").strip("\"'")
|
||||
if value and "{" not in value:
|
||||
values.add(value)
|
||||
return values
|
||||
|
||||
|
||||
def declared_registries() -> list[str]:
|
||||
"""Return every registry the cache must bump, sorted.
|
||||
@@ -37,11 +65,14 @@ def declared_registries() -> list[str]:
|
||||
``registry-1.docker.io`` and ``auth.docker.io``, and naming a Hub alias
|
||||
here would only duplicate that.
|
||||
"""
|
||||
found = {
|
||||
image.registry
|
||||
for image in iter_role_images(PROJECT_ROOT)
|
||||
if image.registry and image.registry not in DOCKER_HUB_REGISTRIES
|
||||
}
|
||||
found: set[str] = set()
|
||||
for value in _image_values():
|
||||
parts = split_registry_and_name(value)
|
||||
if parts is None:
|
||||
continue
|
||||
registry = parts[0]
|
||||
if registry and registry not in DOCKER_HUB_REGISTRIES:
|
||||
found.add(registry)
|
||||
return sorted(found | BASE)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user