Skip to content

Commit 89cc3e9

Browse files
committed
feat(disaggregatedset): Add hack/e2e-test.sh for Prow CI compatibility
Add a dedicated e2e test script that mirrors the LWS pattern for running e2e tests in Prow CI. The script handles the full e2e lifecycle: - Kind cluster creation/deletion with cleanup trap - Docker image building and loading to Kind - LWS controller installation from release manifests - DisaggregatedSet operator deployment via kustomize - Running ginkgo tests with junit output - Log collection on cleanup for debugging Update Makefile to call the hack script with all required environment variables (KIND, KUBECTL, KUSTOMIZE, GINKGO, etc.) and add ginkgo tool. Update e2e tests to skip redundant operations when run via hack script (detected via LWS_INSTALL_SKIP=true), allowing tests to work both standalone and in Prow CI.
1 parent 08611ad commit 89cc3e9

File tree

5 files changed

+183
-65
lines changed

5 files changed

+183
-65
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ test-integration: manifests fmt vet envtest ginkgo ## Run integration tests.
176176
.PHONY: test-e2e
177177
test-e2e: kustomize manifests fmt vet envtest ginkgo kind-image-build
178178
E2E_KIND_VERSION=$(E2E_KIND_VERSION) KIND_CLUSTER_NAME=$(KIND_CLUSTER_NAME) KIND=$(KIND) KUBECTL=$(KUBECTL) KUSTOMIZE=$(KUSTOMIZE) GINKGO=$(GINKGO) USE_EXISTING_CLUSTER=$(USE_EXISTING_CLUSTER) IMAGE_TAG=$(IMG) ARTIFACTS=$(ARTIFACTS) ./hack/e2e-test.sh
179-
$(MAKE) -C disaggregatedset test-e2e KIND=$(KIND)
179+
$(MAKE) -C disaggregatedset test-e2e KIND=$(KIND) KUBECTL=$(KUBECTL) E2E_KIND_VERSION=$(E2E_KIND_VERSION) ARTIFACTS=$(ARTIFACTS)
180180

181181
.PHONY: test-e2e-cert-manager
182182
test-e2e-cert-manager: kustomize manifests fmt vet envtest ginkgo kind-image-build

disaggregatedset/Makefile

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,32 +65,24 @@ test: manifests generate fmt vet setup-envtest ## Run tests.
6565
KUBEBUILDER_ASSETS="$(shell "$(ENVTEST)" use $(ENVTEST_K8S_VERSION) --bin-dir "$(LOCALBIN)" -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
6666

6767
# E2E tests using Kind cluster with LWS controller.
68-
# The test suite handles LWS installation automatically.
69-
# Skip LWS installation with: LWS_INSTALL_SKIP=true
70-
KIND_CLUSTER ?= disaggregatedset-test-e2e
68+
KIND_CLUSTER_NAME ?= disaggregatedset-test-e2e
69+
E2E_KIND_VERSION ?= kindest/node:v1.32.2
7170
E2E_IMG ?= controller:e2e
72-
73-
.PHONY: setup-test-e2e
74-
setup-test-e2e: ## Set up a Kind cluster for e2e tests if it does not exist
75-
@if [ ! -x "$(KIND)" ] && ! command -v $(KIND) >/dev/null 2>&1; then \
76-
echo "Kind is not installed at '$(KIND)'. Please install Kind or pass KIND=/path/to/kind."; \
77-
exit 1; \
78-
fi
79-
@case "$$($(KIND) get clusters)" in \
80-
*"$(KIND_CLUSTER)"*) \
81-
echo "Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation." ;; \
82-
*) \
83-
echo "Creating Kind cluster '$(KIND_CLUSTER)'..."; \
84-
$(KIND) create cluster --name $(KIND_CLUSTER) ;; \
85-
esac
71+
USE_EXISTING_CLUSTER ?= false
72+
ARTIFACTS ?= $(LOCALBIN)
73+
LWS_VERSION ?= v0.8.0
8674

8775
.PHONY: test-e2e
88-
test-e2e: setup-test-e2e manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind.
89-
IMG=$(E2E_IMG) KIND=$(KIND) KIND_CLUSTER=$(KIND_CLUSTER) go test -tags=e2e ./test/e2e/ -v -ginkgo.v -timeout 15m
76+
test-e2e: manifests generate kustomize ginkgo ## Run e2e tests using Kind cluster.
77+
E2E_KIND_VERSION=$(E2E_KIND_VERSION) KIND_CLUSTER_NAME=$(KIND_CLUSTER_NAME) KIND=$(KIND) \
78+
KUBECTL=$(KUBECTL) KUSTOMIZE=$(KUSTOMIZE) GINKGO=$(GINKGO) \
79+
USE_EXISTING_CLUSTER=$(USE_EXISTING_CLUSTER) IMAGE_TAG=$(E2E_IMG) \
80+
ARTIFACTS=$(ARTIFACTS) LWS_VERSION=$(LWS_VERSION) \
81+
./hack/e2e-test.sh
9082

9183
.PHONY: cleanup-test-e2e
9284
cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests
93-
@$(KIND) delete cluster --name $(KIND_CLUSTER)
85+
@$(KIND) delete cluster --name $(KIND_CLUSTER_NAME)
9486

9587
##@ Kind Development Helpers
9688

@@ -230,11 +222,13 @@ CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
230222
ENVTEST ?= $(LOCALBIN)/setup-envtest
231223
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
232224
HELMIFY ?= $(LOCALBIN)/helmify
225+
GINKGO ?= $(LOCALBIN)/ginkgo
233226

234227
## Tool Versions
235228
KUSTOMIZE_VERSION ?= v5.7.1
236229
CONTROLLER_TOOLS_VERSION ?= v0.19.0
237230
HELMIFY_VERSION ?= v0.4.18
231+
GINKGO_VERSION ?= v2.27.5
238232

239233
#ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script (i.e. release-0.20)
240234
ENVTEST_VERSION ?= $(shell v='$(call gomodver,sigs.k8s.io/controller-runtime)'; \
@@ -280,6 +274,11 @@ helmify: $(HELMIFY) ## Download helmify locally if necessary.
280274
$(HELMIFY): $(LOCALBIN)
281275
test -s "$(LOCALBIN)/helmify" || GOBIN="$(LOCALBIN)" go install github.com/arttor/helmify/cmd/helmify@$(HELMIFY_VERSION)
282276

277+
.PHONY: ginkgo
278+
ginkgo: $(GINKGO) ## Download ginkgo locally if necessary.
279+
$(GINKGO): $(LOCALBIN)
280+
test -s "$(LOCALBIN)/ginkgo" || GOBIN="$(LOCALBIN)" go install github.com/onsi/ginkgo/v2/ginkgo@$(GINKGO_VERSION)
281+
283282
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
284283
# $1 - target path with name of binary
285284
# $2 - package url which can be installed

disaggregatedset/hack/e2e-test.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2024 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -o errexit
18+
set -o nounset
19+
set -o pipefail
20+
21+
export CWD=$(pwd)
22+
23+
# LWS version to install
24+
LWS_VERSION=${LWS_VERSION:-"v0.8.0"}
25+
26+
function cleanup {
27+
if [ "$USE_EXISTING_CLUSTER" == 'false' ]
28+
then
29+
if [ ! -d "$ARTIFACTS" ]; then
30+
mkdir -p "$ARTIFACTS"
31+
fi
32+
# Export disaggregatedset controller logs
33+
$KUBECTL logs -n disaggregatedset-system deployment/disaggregatedset-controller-manager > "$ARTIFACTS"/disaggregatedset-controller-manager.log || true
34+
$KUBECTL describe pods -n disaggregatedset-system > "$ARTIFACTS"/disaggregatedset-system-pods.log || true
35+
# Export LWS controller logs
36+
$KUBECTL logs -n lws-system deployment/lws-controller-manager > "$ARTIFACTS"/lws-controller-manager.log || true
37+
$KUBECTL describe pods -n lws-system > "$ARTIFACTS"/lws-system-pods.log || true
38+
# Export kind logs and delete cluster
39+
$KIND export logs "$ARTIFACTS" || true
40+
$KIND delete cluster --name $KIND_CLUSTER_NAME
41+
fi
42+
(cd $CWD/config/manager && $KUSTOMIZE edit set image controller=controller:latest)
43+
}
44+
45+
function startup {
46+
if [ "$USE_EXISTING_CLUSTER" == 'false' ]
47+
then
48+
if [ ! -d "$ARTIFACTS" ]; then
49+
mkdir -p "$ARTIFACTS"
50+
fi
51+
$KIND create cluster --name $KIND_CLUSTER_NAME --image $E2E_KIND_VERSION --wait 1m
52+
$KUBECTL get nodes > "$ARTIFACTS"/kind-nodes.log || true
53+
$KUBECTL describe pods -n kube-system > "$ARTIFACTS"/kube-system-pods.log || true
54+
fi
55+
}
56+
57+
function docker_build {
58+
echo "Building disaggregatedset operator image..."
59+
docker build -t "$IMAGE_TAG" .
60+
}
61+
62+
function kind_load {
63+
echo "Loading operator image to Kind..."
64+
$KIND load docker-image "$IMAGE_TAG" --name "$KIND_CLUSTER_NAME"
65+
}
66+
67+
function install_lws {
68+
echo "Installing LWS ${LWS_VERSION}..."
69+
$KUBECTL apply --server-side -f "https://github.com/kubernetes-sigs/lws/releases/download/${LWS_VERSION}/manifests.yaml"
70+
echo "Waiting for LWS controller to be ready..."
71+
$KUBECTL -n lws-system wait --for=condition=available --timeout=5m deployment/lws-controller-manager
72+
}
73+
74+
function deploy_operator {
75+
echo "Deploying disaggregatedset operator..."
76+
pushd "$CWD/config/manager"
77+
$KUSTOMIZE edit set image controller="$IMAGE_TAG"
78+
popd
79+
$KUSTOMIZE build "$CWD/config/default" | $KUBECTL apply --server-side -f -
80+
echo "Waiting for disaggregatedset operator to be ready..."
81+
$KUBECTL -n disaggregatedset-system wait --for=condition=available --timeout=2m deployment/disaggregatedset-controller-manager
82+
}
83+
84+
function run_tests {
85+
echo "Running e2e tests..."
86+
# Set LWS_INSTALL_SKIP since we already installed LWS
87+
# Set KIND_CLUSTER for the test code (it expects KIND_CLUSTER, not KIND_CLUSTER_NAME)
88+
# Use --tags=e2e to include files with //go:build e2e constraint
89+
LWS_INSTALL_SKIP=true KIND_CLUSTER="$KIND_CLUSTER_NAME" $GINKGO --tags=e2e --junit-report=junit.xml --output-dir="$ARTIFACTS" -v "$CWD/test/e2e/..."
90+
}
91+
92+
trap cleanup EXIT
93+
startup
94+
docker_build
95+
kind_load
96+
install_lws
97+
deploy_operator
98+
run_tests

disaggregatedset/test/e2e/e2e_suite_test.go

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,19 @@ var _ = BeforeSuite(func() {
7979
_, err = utils.Run(cmd)
8080
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to switch kubectl context to Kind cluster")
8181

82-
By("building the operator image")
83-
cmd = exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage))
84-
_, err = utils.Run(cmd)
85-
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the operator image")
82+
// When run via hack/e2e-test.sh, the image is already built and loaded
83+
// and the operator is already deployed. Skip these steps.
84+
if !skipLWSInstall {
85+
By("building the operator image")
86+
cmd = exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectImage))
87+
_, err = utils.Run(cmd)
88+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to build the operator image")
8689

87-
By("loading the operator image to Kind")
88-
err = utils.LoadImageToKindClusterWithName(projectImage)
89-
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the operator image into Kind")
90+
By("loading the operator image to Kind")
91+
err = utils.LoadImageToKindClusterWithName(projectImage)
92+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to load the operator image into Kind")
9093

91-
// Install LWS if not skipped and not already installed
92-
if !skipLWSInstall {
94+
// Install LWS if not already installed
9395
By("checking if LWS is already installed")
9496
isLWSAlreadyInstalled = utils.IsLWSInstalled()
9597
if !isLWSAlreadyInstalled {
@@ -98,24 +100,38 @@ var _ = BeforeSuite(func() {
98100
} else {
99101
_, _ = fmt.Fprintf(GinkgoWriter, "LWS is already installed, skipping installation\n")
100102
}
103+
104+
By("installing DisaggDeployment CRDs")
105+
cmd = exec.Command("make", "install")
106+
_, err = utils.Run(cmd)
107+
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to install CRDs")
108+
} else {
109+
_, _ = fmt.Fprintf(GinkgoWriter, "LWS_INSTALL_SKIP=true: skipping image build, load, and CRD install\n")
101110
}
102111

103112
By("waiting for LWS to be ready")
104113
Expect(utils.WaitForLWSReady()).To(Succeed(), "LWS is not ready")
105-
106-
By("installing DisaggDeployment CRDs")
107-
cmd = exec.Command("make", "install")
108-
_, err = utils.Run(cmd)
109-
ExpectWithOffset(1, err).NotTo(HaveOccurred(), "Failed to install CRDs")
110114
})
111115

112116
var _ = AfterSuite(func() {
117+
// When run via hack/e2e-test.sh (LWS_INSTALL_SKIP=true), cleanup is handled by the script
118+
if skipLWSInstall {
119+
_, _ = fmt.Fprintf(GinkgoWriter, "LWS_INSTALL_SKIP=true: skipping cleanup (handled by hack/e2e-test.sh)\n")
120+
// Just restore context
121+
if originalKubeContext != "" {
122+
By("restoring original kubectl context")
123+
cmd := exec.Command("kubectl", "config", "use-context", originalKubeContext)
124+
_, _ = utils.Run(cmd)
125+
}
126+
return
127+
}
128+
113129
By("uninstalling CRDs")
114130
cmd := exec.Command("make", "uninstall")
115131
_, _ = utils.Run(cmd)
116132

117133
// Only uninstall LWS if we installed it
118-
if !skipLWSInstall && !isLWSAlreadyInstalled {
134+
if !isLWSAlreadyInstalled {
119135
_, _ = fmt.Fprintf(GinkgoWriter, "Uninstalling LWS controller...\n")
120136
utils.UninstallLWS()
121137
}

0 commit comments

Comments
 (0)