Skip to content

Commit 94fd74e

Browse files
committed
e2e: seed bink registry with real node image
Seed the bink registry with the bootc image from the node disk image so e2e tests can reference real images. Add --target-imgref support to make nodes track the registry image. Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5dbf3e5 commit 94fd74e

3 files changed

Lines changed: 69 additions & 13 deletions

File tree

Makefile

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ CONTAINER_TOOL ?= podman
66
BINK_CLUSTER_NAME ?= e2e
77
KUBECONFIG_BINK ?= ./kubeconfig-$(BINK_CLUSTER_NAME)
88
ARTIFACTS ?= $(abspath _output/logs)
9+
export BINK_NODE_DISK_IMAGE ?= ghcr.io/alicefr/bink/node:v1.35-fedora-44-disk
10+
export BINK_LOCAL_REGISTRY_NODE_IMAGE ?= registry.cluster.local:5000/node
911
# YEAR defines the year value used for substituting the YEAR placeholder in the boilerplate header.
1012
YEAR ?= $(shell date +%Y)
1113

@@ -63,6 +65,7 @@ e2e: ## Run e2e tests (requires: make deploy-bink). V=1 for verbose. RUN=<regex>
6365
cd test/e2e && KUBECONFIG=$(abspath $(KUBECONFIG_BINK)) BINK_CLUSTER_NAME=$(BINK_CLUSTER_NAME) \
6466
$(if $(BINK_NODE_IMAGE),BINK_NODE_IMAGE=$(BINK_NODE_IMAGE)) \
6567
ARTIFACTS=$(ARTIFACTS) \
68+
NODE_IMAGE_DIGEST=$$(podman inspect --format '{{index .Config.Labels "bink.bootc-image-digest"}}' $(BINK_NODE_DISK_IMAGE)) \
6669
go test -timeout 10m -count=1 $(if $(V),-v) $(if $(RUN),-run $(RUN)) .
6770

6871
##@ Build
@@ -111,19 +114,28 @@ undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.
111114
# Note the :latest tag here: this makes the pull policy be Always.
112115
IMG_BINK ?= registry.cluster.local:5000/bootc-operator-e2e:latest
113116

114-
.PHONY: start-bink
115-
start-bink: ## Start a bink cluster (idempotent).
117+
.PHONY: seed-node-image
118+
seed-node-image: ## Pull the bootc node image by digest and push to the bink registry.
116119
bink registry start
117-
bink cluster list 2>&1 | grep -qw $(BINK_CLUSTER_NAME) || \
120+
podman pull $(BINK_NODE_DISK_IMAGE)
121+
bootc_img=$$(podman inspect --format '{{index .Config.Labels "bink.bootc-image"}}' $(BINK_NODE_DISK_IMAGE)) && \
122+
bootc_digest=$$(podman inspect --format '{{index .Config.Labels "bink.bootc-image-digest"}}' $(BINK_NODE_DISK_IMAGE)) && \
123+
podman pull "$$bootc_img@$$bootc_digest" && \
124+
podman tag "$$bootc_img@$$bootc_digest" localhost:5000/node:latest
125+
podman push --tls-verify=false localhost:5000/node:latest
126+
127+
.PHONY: start-bink
128+
start-bink: seed-node-image ## Start a bink cluster (idempotent).
129+
bink cluster list 2>&1 | grep -qw $(BINK_CLUSTER_NAME) || { \
130+
bootc_digest=$$(podman inspect --format '{{index .Config.Labels "bink.bootc-image-digest"}}' $(BINK_NODE_DISK_IMAGE)) && \
118131
bink cluster start --cluster-name $(BINK_CLUSTER_NAME) --node-name controller --api-port 0 --expose $(KUBECONFIG_BINK) \
119-
$(if $(BINK_NODE_IMAGE),--node-image $(BINK_NODE_IMAGE))
132+
--node-image $(BINK_NODE_DISK_IMAGE) \
133+
--target-imgref $(BINK_LOCAL_REGISTRY_NODE_IMAGE)@$$bootc_digest; }
120134
kubectl --kubeconfig $(KUBECONFIG_BINK) wait --for=condition=Ready node/controller --timeout=5m
121135

122136
.PHONY: deploy-bink
123137
deploy-bink: start-bink kustomize ## Deploy to a bink cluster (requires: buildimg).
124138
podman push --tls-verify=false $(IMG) localhost:5000/bootc-operator-e2e:latest
125-
# On re-deploy, restart the rollout to force a re-pull of the :latest tag.
126-
# On fresh deploy, skip the restart -- the pod is already pulling the correct image.
127139
@existed=$$(kubectl --kubeconfig $(KUBECONFIG_BINK) -n bootc-operator get deploy bootc-operator-controller-manager -o name 2>/dev/null || true) && \
128140
$(MAKE) deploy KUBECONFIG=$(abspath $(KUBECONFIG_BINK)) IMG=$(IMG_BINK) && \
129141
if [ -n "$$existed" ]; then \

test/e2e/bootcnode_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ func TestControllerMembership(t *testing.T) {
3535

3636
ctx := context.Background()
3737

38-
// Create a pool selecting this test's nodes.
38+
// Use real registry image when seeded; fall back to fake ref for
39+
// local dev runs without deploy-bink.
3940
imageRef := testutil.ImageDigestRefA
41+
if ref := env.NodeImageDigestRef(); ref != "" {
42+
imageRef = ref
43+
}
4044
pool := env.NewPool("workers", imageRef)
4145
g.Expect(env.Client.Create(ctx, pool)).To(Succeed())
4246

test/e2e/e2eutil/env.go

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ type Env struct {
5252

5353
// nodes tracks node names added via AddNode for cleanup.
5454
nodes []string
55+
56+
// nodeImageDigest is the manifest digest of the bootc image seeded
57+
// into the bink registry (e.g. "sha256:abc123..."). Empty when not seeded.
58+
nodeImageDigest string
59+
60+
// nodeImageRegistry is the in-cluster registry path for the seeded node image
61+
// (e.g. "registry.cluster.local:5000/node"). Empty when not seeded.
62+
nodeImageRegistry string
5563
}
5664

5765
// New connects to an existing bink cluster and returns an Env ready
@@ -70,12 +78,17 @@ func New(t *testing.T) *Env {
7078
t.Fatal("BINK_CLUSTER_NAME must be set")
7179
}
7280

81+
nodeImageDigest := os.Getenv("NODE_IMAGE_DIGEST")
82+
nodeImageRegistry := os.Getenv("BINK_LOCAL_REGISTRY_NODE_IMAGE")
83+
7384
k8sClient := buildClient(t, kubeconfigPath)
7485

7586
env := &Env{
76-
Client: k8sClient,
77-
clusterName: clusterName,
78-
testID: sanitizeTestName(t.Name()),
87+
Client: k8sClient,
88+
clusterName: clusterName,
89+
testID: sanitizeTestName(t.Name()),
90+
nodeImageDigest: nodeImageDigest,
91+
nodeImageRegistry: nodeImageRegistry,
7992
}
8093

8194
t.Cleanup(func() {
@@ -89,8 +102,9 @@ func New(t *testing.T) *Env {
89102
type NodeOption func(*nodeConfig)
90103

91104
type nodeConfig struct {
92-
memory int
93-
labels map[string]string
105+
memory int
106+
labels map[string]string
107+
targetImgRef string
94108
}
95109

96110
// WithMemory sets the VM memory in MB for the node.
@@ -111,6 +125,15 @@ func WithLabel(key, value string) NodeOption {
111125
}
112126
}
113127

128+
// WithTargetImgRef sets the target image reference for the node,
129+
// passed as --target-imgref to bink node add. Overrides the automatic
130+
// default that AddNode applies when registry metadata is available.
131+
func WithTargetImgRef(ref string) NodeOption {
132+
return func(c *nodeConfig) {
133+
c.targetImgRef = ref
134+
}
135+
}
136+
114137
// AddNode provisions a worker node via bink, waits for it to be Ready,
115138
// and returns the node name. The node is labeled with LabelE2ETest
116139
// (and any extra labels from WithLabel).
@@ -122,6 +145,13 @@ func (e *Env) AddNode(t *testing.T, opts ...NodeOption) string {
122145
o(cfg)
123146
}
124147

148+
if cfg.targetImgRef == "" {
149+
if e.nodeImageRegistry == "" {
150+
t.Fatal("BINK_LOCAL_REGISTRY_NODE_IMAGE must be set (or use WithTargetImgRef)")
151+
}
152+
cfg.targetImgRef = e.nodeImageRegistry + ":latest"
153+
}
154+
125155
nodeName := e.generateNodeName(t)
126156

127157
// Provision the node with labels applied at join time.
@@ -133,9 +163,10 @@ func (e *Env) AddNode(t *testing.T, opts ...NodeOption) string {
133163
if cfg.memory > 0 {
134164
args = append(args, "--memory", fmt.Sprintf("%d", cfg.memory))
135165
}
136-
if img := os.Getenv("BINK_NODE_IMAGE"); img != "" {
166+
if img := os.Getenv("BINK_NODE_DISK_IMAGE"); img != "" {
137167
args = append(args, "--node-image", img)
138168
}
169+
args = append(args, "--target-imgref", cfg.targetImgRef)
139170
t.Logf("Adding node %q...", nodeName)
140171
if err := runBink(t, args...); err != nil {
141172
t.Fatalf("adding node %q: %v", nodeName, err)
@@ -169,6 +200,15 @@ func (e *Env) TestLabels() map[string]string {
169200
return map[string]string{LabelE2ETest: e.testID}
170201
}
171202

203+
// NodeImageDigestedPullSpec returns the digest-qualified reference for the
204+
// seeded node image (e.g. "registry.cluster.local:5000/node@sha256:abc123").
205+
func (e *Env) NodeImageDigestedPullSpec() string {
206+
if e.nodeImageRegistry == "" || e.nodeImageDigest == "" {
207+
return ""
208+
}
209+
return e.nodeImageRegistry + "@" + e.nodeImageDigest
210+
}
211+
172212
// cleanup gathers diagnostic logs, then deletes test-scoped resources
173213
// and bink nodes.
174214
func (e *Env) cleanup(t *testing.T) {

0 commit comments

Comments
 (0)