Skip to content

Commit c85ced2

Browse files
alicefrjlebon
authored andcommitted
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 4321fae commit c85ced2

3 files changed

Lines changed: 70 additions & 11 deletions

File tree

Makefile

Lines changed: 19 additions & 4 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+
BINK_NODE_DISK_IMAGE ?= ghcr.io/alicefr/bink/node:v1.35-fedora-44-disk
10+
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

@@ -62,7 +64,10 @@ e2e: ## Run e2e tests (requires: make deploy-bink). V=1 for verbose. RUN=<regex>
6264
rm -rf $(ARTIFACTS)
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)) \
67+
BINK_NODE_DISK_IMAGE=$(BINK_NODE_DISK_IMAGE) \
68+
BINK_LOCAL_REGISTRY_NODE_IMAGE=$(BINK_LOCAL_REGISTRY_NODE_IMAGE) \
6569
ARTIFACTS=$(ARTIFACTS) \
70+
BINK_NODE_IMAGE_DIGEST=$$(skopeo inspect --tls-verify=false --format '{{.Digest}}' docker://localhost:5000/node:latest) \
6671
go test -timeout 10m -count=1 $(if $(V),-v) $(if $(RUN),-run $(RUN)) .
6772

6873
##@ Build
@@ -111,12 +116,22 @@ undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.
111116
# Note the :latest tag here: this makes the pull policy be Always.
112117
IMG_BINK ?= registry.cluster.local:5000/bootc-operator-e2e:latest
113118

114-
.PHONY: start-bink
115-
start-bink: ## Start a bink cluster (idempotent).
119+
.PHONY: seed-node-image
120+
seed-node-image: ## Pull the bootc node image by digest and push to the bink registry.
116121
bink registry start
117-
bink cluster list 2>&1 | grep -qw $(BINK_CLUSTER_NAME) || \
122+
podman pull $(BINK_NODE_DISK_IMAGE)
123+
bootc_img=$$(podman inspect --format '{{index .Config.Labels "bink.bootc-image"}}' $(BINK_NODE_DISK_IMAGE)) && \
124+
bootc_digest=$$(podman inspect --format '{{index .Config.Labels "bink.bootc-image-digest"}}' $(BINK_NODE_DISK_IMAGE)) && \
125+
podman pull "$$bootc_img@$$bootc_digest" && \
126+
podman tag "$$bootc_img@$$bootc_digest" localhost:5000/node:latest
127+
podman push --tls-verify=false localhost:5000/node:latest
128+
129+
.PHONY: start-bink
130+
start-bink: seed-node-image ## Start a bink cluster (idempotent).
131+
bink cluster list 2>&1 | grep -qw $(BINK_CLUSTER_NAME) || { \
132+
node_digest=$$(skopeo inspect --tls-verify=false --format '{{.Digest}}' docker://localhost:5000/node:latest) && \
118133
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))
134+
--node-image $(BINK_NODE_DISK_IMAGE) --target-imgref $(BINK_LOCAL_REGISTRY_NODE_IMAGE)@$$node_digest; }
120135
kubectl --kubeconfig $(KUBECONFIG_BINK) wait --for=condition=Ready node/controller --timeout=5m
121136

122137
.PHONY: deploy-bink

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.NodeImageDigestedPullSpec(); 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("BINK_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)