Skip to content

Commit 2cda5d3

Browse files
author
Per Goncalves da Silva
committed
move e2e cluster setup our of the e2e test binary and into the e2e test gha
Signed-off-by: Per Goncalves da Silva <[email protected]>
1 parent 8a07186 commit 2cda5d3

File tree

5 files changed

+161
-58
lines changed

5 files changed

+161
-58
lines changed

.github/workflows/e2e-tests.yml

+94-6
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,114 @@ on:
99
workflow_dispatch:
1010
merge_group:
1111
jobs:
12+
13+
# Build the OLM image and save it as an artifact
14+
build:
15+
runs-on: ubuntu-latest
16+
outputs:
17+
sha: ${{ steps.vars.outputs.sha }}
18+
steps:
19+
# checkout code and setup go
20+
- uses: actions/checkout@v4
21+
- uses: actions/setup-go@v5
22+
with:
23+
go-version-file: "go.mod"
24+
# build binaries and image for e2e test (includes experimental features)
25+
- name: Build controller image
26+
run: make e2e-build
27+
- name: Save image
28+
run: docker save quay.io/operator-framework/olm:local -o olm-image.tar
29+
- name: Upload Docker image as artifact
30+
uses: actions/upload-artifact@v4
31+
with:
32+
name: olm-image.tar
33+
path: olm-image.tar
34+
35+
# Run e2e tests in parallel jobs
36+
# Take olm image from the previous stage
1237
e2e:
38+
needs: build
1339
strategy:
1440
fail-fast: false
1541
matrix:
16-
parallel-id: [0, 1, 2, 3]
42+
parallel-id: [0, 1, 2, 3, flakes]
1743
runs-on: ubuntu-latest
44+
env:
45+
# absolute path to test artifacts directory
46+
ARTIFACT_DIR: ${{ github.workspace }}/artifacts
47+
E2E_TEST_CHUNK: ${{ matrix.parallel-id }}
48+
E2E_NODES: 2
49+
E2E_KUBECONFIG_ROOT: ${{ github.workspace }}/kubeconfigs
1850
steps:
51+
# checkout code and setup go
1952
- uses: actions/checkout@v4
2053
- uses: actions/setup-go@v5
2154
with:
2255
go-version-file: "go.mod"
23-
- run: mkdir -p artifacts
24-
- run: make e2e-local E2E_TEST_CHUNK=${{ matrix.parallel-id }} E2E_TEST_NUM_CHUNKS=${{ strategy.job-total }} E2E_NODES=2 ARTIFACT_DIR=./artifacts/ SKIP='\[FLAKE\]'
25-
- name: Archive Test Artifacts # test results, failed or not, are always uploaded.
56+
57+
# load the olm image
58+
- name: Load OLM Docker image
59+
uses: actions/download-artifact@v4
60+
with:
61+
name: olm-image.tar
62+
path: .
63+
- run: docker load < olm-image.tar
64+
65+
# set e2e environment variables
66+
# Set ginkgo output and parallelism
67+
- run: echo "GINKGO_E2E_OPTS=-output-dir ${ARTIFACT_DIR} -junit-report junit_e2e.xml -nodes ${E2E_NODES}" >> $GITHUB_ENV
68+
69+
# Setting -kubeconfig-root tells the e2e test suite to look for kubeconfigs
70+
# in <kubeconfig-root>/kubeconfig-<node-number>
71+
# This is used to run tests in parallel on multiple clusters as the current e2e
72+
# test suite does not support running tests in parallel on a single cluster
73+
- run: echo "E2E_OPTS=-kubeconfig-root=${E2E_KUBECONFIG_ROOT}" >> $GITHUB_ENV
74+
75+
# run e2e tests
76+
# create artifacts directory
77+
- run: mkdir -p ${ARTIFACT_DIR}
78+
79+
# deploy test clusters
80+
- name: Deploy test cluster(s)
81+
# create kubeconfig root and store the kubeconfig for each cluster within it as you create the clusters
82+
# Add kind and helm options to specify kubeconfig location
83+
# Deploy the new cluster and helm install olm for testing
84+
run: |
85+
mkdir -p ${E2E_KUBECONFIG_ROOT}
86+
for i in $(seq 1 ${E2E_NODES}); do
87+
KIND_CLUSTER_NAME="kind-olmv0-${i}" \
88+
KIND_CREATE_OPTS="--kubeconfig=${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \
89+
HELM_INSTALL_OPTS="--kubeconfig ${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \
90+
make kind-create deploy;
91+
done
92+
93+
# run non-flakes if matrix-id is not 'flakes'
94+
- name: Run e2e tests
95+
if: ${{ matrix.parallel-id != 'flakes' }}
96+
# calculate the number of chunks as the number of parallel jobs minus 1 (flakes job)
97+
# use the split tool to split the test suite into chunks and run the chunk corresponding to the matrix-id
98+
# focus on those tests and skip tests marked as FLAKE
99+
run: |
100+
E2E_TEST_NUM_CHUNKS=$(( ${{ strategy.job-total }} - 1 )) \
101+
GINKGO_E2E_OPTS="${GINKGO_E2E_OPTS} -focus '$(go run ./test/e2e/split/... -chunks $E2E_TEST_NUM_CHUNKS -print-chunk $E2E_TEST_CHUNK ./test/e2e)' -skip '\[FLAKE\]'" \
102+
make e2e;
103+
104+
# run e2e tests for flakes if matrix-id is 'flakes'
105+
- name: Run flaky e2e tests
106+
if: ${{ matrix.parallel-id == 'flakes' }}
107+
# focus on tests marked as FLAKE
108+
run: |
109+
GINKGO_E2E_OPTS="${GINKGO_E2E_OPTS} -focus '\[FLAKE\]'" make e2e
110+
111+
# archive test results
112+
- name: Archive Test Artifacts
26113
if: ${{ always() }}
27114
uses: actions/upload-artifact@v4
28115
with:
29116
name: e2e-test-output-${{ (github.event.pull_request.head.sha || github.sha) }}-${{ github.run_id }}-${{ matrix.parallel-id }}
30-
path: ${{ github.workspace }}/bin/artifacts/*
117+
path: ${{ env.ARTIFACT_DIR }}/*
31118
# TODO: create job to combine test artifacts using code in https://github.com/operator-framework/operator-lifecycle-manager/pull/1476
119+
32120
e2e-tests:
33121
if: ${{ always() }}
34122
runs-on: ubuntu-latest
@@ -40,4 +128,4 @@ jobs:
40128
if: ${{ needs.e2e.result == 'failure' }}
41129
run: |
42130
echo 'Failure: at least one e2e matrix job has failed'
43-
exit 1
131+
exit 1

Makefile

+50-41
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
##########################
22
# OLM - Build and Test #
33
##########################
4+
# Setting SHELL to bash allows bash commands to be executed by recipes.
5+
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
6+
SHELL := /usr/bin/env bash -o pipefail
7+
.SHELLFLAGS := -ec
48

59
# Undefine GOFLAGS environment variable.
610
ifdef GOFLAGS
@@ -22,6 +26,8 @@ SPECIFIC_UNIT_TEST := $(if $(TEST),-run $(TEST),)
2226
LOCAL_NAMESPACE := "olm"
2327
export GO111MODULE=on
2428
YQ_INTERNAL := go run $(MOD_FLAGS) ./vendor/github.com/mikefarah/yq/v3/
29+
HELM := go run $(MOD_FLAGS) ./vendor/helm.sh/helm/v3/cmd/helm
30+
KIND := go run $(MOD_FLAGS) ./vendor/sigs.k8s.io/kind
2531
KUBEBUILDER_ASSETS := $(or $(or $(KUBEBUILDER_ASSETS),$(dir $(shell command -v kubebuilder))),/usr/local/kubebuilder/bin)
2632
export KUBEBUILDER_ASSETS
2733
GO := GO111MODULE=on GOFLAGS="$(MOD_FLAGS)" go
@@ -33,6 +39,15 @@ ARCH := arm64
3339
else
3440
ARCH := amd64
3541
endif
42+
43+
KIND_CLUSTER_NAME ?= kind-olmv0
44+
# Not guaranteed to have patch releases available and node image tags are full versions (i.e v1.28.0 - no v1.28, v1.29, etc.)
45+
# The KIND_NODE_VERSION is set by getting the version of the k8s.io/client-go dependency from the go.mod
46+
# and sets major version to "1" and the patch version to "0". For example, a client-go version of v0.28.5
47+
# will map to a KIND_NODE_VERSION of 1.28.0
48+
KIND_NODE_VERSION := $(shell go list -m k8s.io/client-go | cut -d" " -f2 | sed 's/^v0\.\([[:digit:]]\{1,\}\)\.[[:digit:]]\{1,\}$$/1.\1.0/')
49+
KIND_CLUSTER_IMAGE := kindest/node:v$(KIND_NODE_VERSION)
50+
3651
# Phony prerequisite for targets that rely on the go build cache to determine staleness.
3752
.PHONY: build test clean vendor \
3853
coverage coverage-html e2e \
@@ -118,49 +133,43 @@ deploy-local:
118133
e2e.namespace:
119134
@printf "e2e-tests-$(shell date +%s)-$$RANDOM" > e2e.namespace
120135

121-
E2E_NODES ?= 1
122-
E2E_FLAKE_ATTEMPTS ?= 1
123-
E2E_TIMEOUT ?= 90m
124-
# Optionally run an individual chunk of e2e test specs.
125-
# Do not use this from the CLI; this is intended to be used by CI only.
126-
E2E_TEST_CHUNK ?= all
127-
E2E_TEST_NUM_CHUNKS ?= 4
128-
ifneq (all,$(E2E_TEST_CHUNK))
129-
TEST := $(shell go run ./test/e2e/split/... -chunks $(E2E_TEST_NUM_CHUNKS) -print-chunk $(E2E_TEST_CHUNK) ./test/e2e)
130-
endif
131-
E2E_OPTS ?= $(if $(E2E_SEED),-seed '$(E2E_SEED)') $(if $(SKIP), -skip '$(SKIP)') $(if $(TEST),-focus '$(TEST)') $(if $(ARTIFACT_DIR), -output-dir $(ARTIFACT_DIR) -junit-report junit_e2e.xml) -flake-attempts $(E2E_FLAKE_ATTEMPTS) -nodes $(E2E_NODES) -timeout $(E2E_TIMEOUT) -v -randomize-suites -race -trace -progress
132-
E2E_INSTALL_NS ?= operator-lifecycle-manager
133-
E2E_CATALOG_NS ?= $(E2E_INSTALL_NS)
134-
E2E_TEST_NS ?= operators
135-
136+
.PHONY: e2e
137+
GINKGO_E2E_OPTS += -timeout 90m -v -randomize-suites -race -trace --show-node-events
138+
E2E_OPTS += -namespace=operators -olmNamespace=operator-lifecycle-manager -catalogNamespace=operator-lifecycle-manager -dummyImage=bitnami/nginx:latest
136139
e2e:
137-
$(GINKGO) $(E2E_OPTS) $(or $(run), ./test/e2e) $< -- -namespace=$(E2E_TEST_NS) -olmNamespace=$(E2E_INSTALL_NS) -catalogNamespace=$(E2E_CATALOG_NS) -dummyImage=bitnami/nginx:latest $(or $(extra_args), -kubeconfig=${KUBECONFIG})
138-
139-
# See workflows/e2e-tests.yml See test/e2e/README.md for details.
140-
.PHONY: e2e-local
141-
e2e-local: BUILD_TAGS="json1 e2e experimental_metrics"
142-
e2e-local: extra_args=-kind.images=../test/e2e-local.image.tar -test-data-dir=../test/e2e/testdata -gather-artifacts-script-path=../test/e2e/collect-ci-artifacts.sh
143-
e2e-local: run=bin/e2e-local.test
144-
e2e-local: bin/e2e-local.test test/e2e-local.image.tar
145-
e2e-local: e2e
146-
147-
# this target updates the zz_chart.go file with files found in deploy/chart
148-
# this will always fire since it has been marked as phony
149-
.PHONY: test/e2e/assets/chart/zz_chart.go
150-
test/e2e/assets/chart/zz_chart.go: $(shell find deploy/chart -type f)
151-
$(BINDATA) -o $@ -pkg chart -prefix deploy/chart/ $^
152-
153-
# execute kind and helm end to end tests
154-
bin/e2e-local.test: FORCE test/e2e/assets/chart/zz_chart.go
155-
$(GO) test -c -tags kind,helm -o $@ ./test/e2e
156-
157-
# set go env and other vars, ensure that the dockerfile exists, and then build wait, cpb, and other command binaries and finally the kind image archive
158-
test/e2e-local.image.tar: export GOOS=linux
159-
test/e2e-local.image.tar: export GOARCH=amd64
160-
test/e2e-local.image.tar: build_cmd=build
161-
test/e2e-local.image.tar: e2e.Dockerfile bin/wait bin/cpb $(CMDS)
140+
$(GINKGO) $(GINKGO_E2E_OPTS) ./test/e2e -- $(E2E_OPTS)
141+
142+
.PHONY: kind-clean
143+
kind-clean:
144+
$(KIND) delete cluster --name $(KIND_CLUSTER_NAME) || true
145+
146+
.PHONY: kind-create
147+
kind-create: kind-clean
148+
$(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image $(KIND_CLUSTER_IMAGE) $(KIND_CREATE_OPTS)
149+
$(KIND) export kubeconfig --name $(KIND_CLUSTER_NAME)
150+
151+
.PHONY: deploy
152+
OLM_IMAGE := quay.io/operator-framework/olm:local
153+
deploy:
154+
$(KIND) load docker-image $(OLM_IMAGE) --name $(KIND_CLUSTER_NAME); \
155+
$(HELM) install olm deploy/chart \
156+
--set debug=true \
157+
--set olm.image.ref=$(OLM_IMAGE) \
158+
--set olm.image.pullPolicy=IfNotPresent \
159+
--set catalog.image.ref=$(OLM_IMAGE) \
160+
--set catalog.image.pullPolicy=IfNotPresent \
161+
--set package.image.ref=$(OLM_IMAGE) \
162+
--set package.image.pullPolicy=IfNotPresent \
163+
$(HELM_INSTALL_OPTS) \
164+
--wait;
165+
166+
.PHONY: e2e-build
167+
e2e-build: BUILD_TAGS="json1 e2e experimental_metrics"
168+
e2e-build: export GOOS=linux
169+
e2e-build: export GOARCH=amd64
170+
e2e-build: build_cmd=build
171+
e2e-build: e2e.Dockerfile bin/wait bin/cpb $(CMDS)
162172
docker build -t quay.io/operator-framework/olm:local -f $< bin
163-
docker save -o $@ quay.io/operator-framework/olm:local
164173

165174
vendor:
166175
go mod tidy

test/e2e/ctx/installer_none.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
//go:build !helm
2-
// +build !helm
3-
41
package ctx
52

6-
func Install(ctx *TestContext) error {
3+
func Install(_ *TestContext) error {
74
return nil
85
}

test/e2e/ctx/provisioner_kubeconfig.go

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//go:build !kind
2-
// +build !kind
3-
41
package ctx
52

63
import (

test/e2e/e2e_test.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"flag"
66
"fmt"
77
"os"
8+
"path"
9+
"strconv"
810
"testing"
911
"time"
1012

@@ -51,7 +53,7 @@ var (
5153
collectArtifactsScriptPath = flag.String(
5254
"gather-artifacts-script-path",
5355
"./collect-ci-artifacts.sh",
54-
"configures the relative/absolute path to the script resposible for collecting CI artifacts",
56+
"configures the relative/absolute path to the script responsible for collecting CI artifacts",
5557
)
5658

5759
testdataPath = flag.String(
@@ -60,12 +62,20 @@ var (
6062
"configures where to find the testdata directory",
6163
)
6264

65+
kubeconfigRootDir = flag.String(
66+
"kubeconfig-root",
67+
"",
68+
"configures the root directory for kubeconfig files when running tests in parallel. "+
69+
"Each test worker will expect their kubeconfig file to be <kubeconfig-root>/kubeconfig-<test-number>. "+
70+
"Where, <test-number> is the number of the test worker (> 0). "+
71+
"Note that this flag will override the kubeconfig flag.",
72+
)
73+
6374
testdataDir = ""
6475
testNamespace = ""
6576
operatorNamespace = ""
6677
communityOperatorsImage = ""
6778
globalCatalogNamespace = ""
68-
junitDir = "junit"
6979
)
7080

7181
func TestEndToEnd(t *testing.T) {
@@ -82,10 +92,12 @@ var deprovision func() = func() {}
8292

8393
// This function initializes a client which is used to create an operator group for a given namespace
8494
var _ = BeforeSuite(func() {
85-
if kubeConfigPath != nil && *kubeConfigPath != "" {
86-
// This flag can be deprecated in favor of the kubeconfig provisioner:
95+
if kubeconfigRootDir != nil && *kubeconfigRootDir != "" {
96+
os.Setenv("KUBECONFIG", path.Join(*kubeconfigRootDir, "kubeconfig-"+strconv.Itoa(GinkgoParallelProcess())))
97+
} else if kubeConfigPath != nil && *kubeConfigPath != "" {
8798
os.Setenv("KUBECONFIG", *kubeConfigPath)
8899
}
100+
89101
if collectArtifactsScriptPath != nil && *collectArtifactsScriptPath != "" {
90102
os.Setenv("E2E_ARTIFACT_SCRIPT", *collectArtifactsScriptPath)
91103
}

0 commit comments

Comments
 (0)