From 4b79ae369c93a078ae99ff57c438df956d460ff4 Mon Sep 17 00:00:00 2001 From: mbakalarski <64490638+mbakalarski@users.noreply.github.com> Date: Wed, 5 Aug 2026 12:41:11 +0000 Subject: [PATCH 1/2] Generate the lab topology with a plain image name, not a registry address `examples/lab/topology.yaml` is committed and fetched at a tag by netclab-xp, which reads it as documentation as much as it runs it. It named `localhost:5001/netclab/ceos:4.36.1F` -- an address that is correct only on a machine running this repository's bring-up script, and meaningless everywhere else. A reader following netclab-xp's documentation imports cEOS with `docker import` and `kind load`, which leaves it as `ceos:4.36.1F`, so the fetched topology sent them to a registry they do not have. The generator's default becomes that plain name. `--image` already existed and is unchanged, so anything wanting a registry can still ask for one. kind-up.sh is the one consumer that does. It now derives the registry address itself and rewrites a temp copy rather than the committed file -- the file is an artifact other repositories fetch, and the golden test compares it to what the generator produces. The EOS version still comes from the topology, so the model keeps deciding which image the lab runs. Also fixes a trap that the temp-copy trap would have replaced, leaving a regenerated topology behind on exit. --- examples/lab/topology.yaml | 4 ++-- function/netclab_topology.py | 12 +++++++++++- scripts/kind-up.sh | 23 ++++++++++++++++++----- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/examples/lab/topology.yaml b/examples/lab/topology.yaml index ac9bdd4..e6e34ba 100644 --- a/examples/lab/topology.yaml +++ b/examples/lab/topology.yaml @@ -6,7 +6,7 @@ topology: nodes: - name: dc1-spine1 type: ceos - image: localhost:5001/netclab/ceos:4.36.1F + image: ceos:4.36.1F memory: 2Gi cpu: 1000m interfaces: @@ -14,7 +14,7 @@ topology: network: b1 - name: dc1-leaf1a type: ceos - image: localhost:5001/netclab/ceos:4.36.1F + image: ceos:4.36.1F memory: 2Gi cpu: 1000m interfaces: diff --git a/function/netclab_topology.py b/function/netclab_topology.py index 4fc7cee..3716d08 100644 --- a/function/netclab_topology.py +++ b/function/netclab_topology.py @@ -27,7 +27,17 @@ # the readable link written alongside as a comment. MAX_IFNAME = 15 -CEOS_IMAGE = "localhost:5001/netclab/ceos:4.36.1F" +# No registry, deliberately. The generated topology is committed and fetched at +# a tag by other repositories, so it is read far more often than it is run here +# -- and a machine-local registry address in a published artifact is wrong for +# everyone but the machine that has it. `docker import` + `kind load` names the +# image exactly this way, which is what a reader following netclab-xp's +# documentation ends up with. +# +# Bring-up scripts that do serve cEOS from a registry rewrite this: it is one +# line against a temp copy, and local specifics belong in a script rather than +# in something published. See `scripts/kind-up.sh`. +CEOS_IMAGE = "ceos:4.36.1F" CEOS_MEMORY = "2Gi" CEOS_CPU = "1000m" diff --git a/scripts/kind-up.sh b/scripts/kind-up.sh index 5674f16..6213d31 100755 --- a/scripts/kind-up.sh +++ b/scripts/kind-up.sh @@ -191,15 +191,21 @@ EOF else echo ">> lab topology regenerated for ${LAB_HOSTS}" TOPO="$(mktemp -t netclab-topology.XXXXXX.yaml)" - trap 'rm -f "$TOPO"' EXIT + TOPO_REGENERATED="$TOPO" uv run avd-topology "$LAB_FABRIC" --hosts "$LAB_HOSTS" > "$TOPO" fi + # The topology names the image without a registry -- the name `docker import` + # plus `kind load` leaves, and the one a reader of netclab-xp's documentation + # ends up with. This lab serves cEOS from the local registry instead, because + # that survives teardown. The EOS version still comes from the topology: it is + # generated from the AVD model, so the model decides which image the lab runs. + CEOS_TAG="$(awk '/image:/ {print $2; exit}' "$TOPO")"; CEOS_TAG="${CEOS_TAG##*:}" + CEOS_REPO=${CEOS_REPO:-netclab/ceos} + CEOS_IMG="localhost:${REG_PORT}/${CEOS_REPO}:${CEOS_TAG}" + # cEOS cannot be pulled: it is licensed and needs an Arista login. Fail here # with the tag the topology asks for, rather than as an ImagePullBackOff later. - CEOS_IMG="$(awk '/image:/ {print $2; exit}' "$TOPO")" - CEOS_REPO="${CEOS_IMG#*/}"; CEOS_REPO="${CEOS_REPO%:*}" - CEOS_TAG="${CEOS_IMG##*:}" if ! curl -sf "http://localhost:${REG_PORT}/v2/${CEOS_REPO}/tags/list" \ | grep -q "\"${CEOS_TAG}\""; then echo "!! ${CEOS_IMG} is not in the local registry." @@ -208,9 +214,16 @@ EOF exit 1 fi + # Rewrite a copy, never the committed file: it is an artifact other + # repositories fetch at a tag, and `test_topology_golden` compares it to what + # the generator produces. + TOPO_LOCAL="$(mktemp -t netclab-topology-local.XXXXXX.yaml)" + trap 'rm -f "$TOPO_LOCAL" "${TOPO_REGENERATED:-}"' EXIT + sed "s|^\( *image: \).*|\1${CEOS_IMG}|" "$TOPO" > "$TOPO_LOCAL" + echo ">> netclab-chart ${NETCLAB_CHART}" helm upgrade --install avd netclab/netclab --version "${NETCLAB_CHART}" \ - --kube-context "$CTX" -n default -f "$TOPO" >/dev/null + --kube-context "$CTX" -n default -f "$TOPO_LOCAL" >/dev/null fi echo From 798a2f7fcea979136dc23697a4cb3562de44542c Mon Sep 17 00:00:00 2001 From: mbakalarski <64490638+mbakalarski@users.noreply.github.com> Date: Wed, 5 Aug 2026 12:46:31 +0000 Subject: [PATCH 2/2] Release v0.1.6 The topology change is consumed by netclab-xp at a tag, so it needs one. --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index afd3ad0..824f76a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "function-avd" -version = "0.1.5" +version = "0.1.6" description = "Living AVD model driven by Crossplane XRs (Fabric -> Device composite function)" readme = "README.md" authors = [ diff --git a/uv.lock b/uv.lock index dbbba70..a39fcc7 100644 --- a/uv.lock +++ b/uv.lock @@ -327,7 +327,7 @@ wheels = [ [[package]] name = "function-avd" -version = "0.1.5" +version = "0.1.6" source = { editable = "." } dependencies = [ { name = "crossplane-function-sdk-python" },