Skip to content

Commit b3ad7d8

Browse files
committed
Adding Helm Parameter CI Tests
1 parent 9370fc4 commit b3ad7d8

File tree

5 files changed

+2532
-7
lines changed

5 files changed

+2532
-7
lines changed

Makefile

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,23 @@ cluster/uninstall: bin/helm bin/aws
128128
## E2E targets
129129
# Targets to run e2e tests
130130

131+
## e2e/parameters and e2e/parameters-all are Parameter-specific e2e tests
132+
# Usage: make e2e/parameters PARAM_SET=<name> or make e2e/paramaters-all
133+
# See hack/e2e/param-sets.sh for available sets and their definitions.
134+
135+
.PHONY: e2e/parameters
136+
e2e/parameters: bin/helm bin/ginkgo
137+
./hack/e2e/param-sets.sh run $(PARAM_SET)
138+
139+
.PHONY: e2e/parameters-all
140+
e2e/parameters-all: bin/helm bin/ginkgo
141+
./hack/e2e/param-sets.sh run-all
142+
143+
# THIS WILL BE REVERSED BEFORE MERGING. Only here because these tests do not
144+
# yet have their own testgrid but reviewers need to see how JUnit output is after tests run for this PR.
131145
.PHONY: e2e/single-az
132146
e2e/single-az: bin/helm bin/ginkgo
133-
AWS_AVAILABILITY_ZONES=us-west-2a \
134-
TEST_PATH=./tests/e2e/... \
135-
GINKGO_FOCUS="\[ebs-csi-e2e\] \[single-az\]" \
136-
GINKGO_PARALLEL=5 \
137-
HELM_EXTRA_FLAGS="--set=controller.volumeModificationFeature.enabled=true,sidecars.provisioner.additionalArgs[0]='--feature-gates=VolumeAttributesClass=true',sidecars.resizer.additionalArgs[0]='--feature-gates=VolumeAttributesClass=true',node.enableMetrics=true" \
138-
./hack/e2e/run.sh
147+
./hack/e2e/param-sets.sh run-all
139148

140149
.PHONY: e2e/multi-az
141150
e2e/multi-az: bin/helm bin/ginkgo

hack/e2e/param-sets.sh

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#!/bin/bash
2+
3+
# Copyright 2025 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+
# Parameter set definitions for e2e parameter tests.
18+
# Each set defines GINKGO_FOCUS, HELM_EXTRA_FLAGS, and optionally other env vars.
19+
#
20+
# Sets in PARAM_SETS_ALL (no "special" cluster config needed):
21+
# standard - Behavioral params (tagging, metrics, logging, storage classes, etc.)
22+
# other - Volume modification, volume attach limit, and metadata labeler
23+
# debug - debugLogs=true overrides individual logLevel settings
24+
# infra - Infrastructure/deployment params (resources, security, strategy, etc.)
25+
# fips - Builds FIPS image then validates it is deployed
26+
#
27+
# Not in PARAM_SETS_ALL:
28+
# legacy-compat - Legacy CSIDriver + XFS behavior
29+
# selinux - Needs SELinux-enabled nodes
30+
31+
set -euo pipefail
32+
33+
PARAM_SETS_ALL="standard other debug infra fips"
34+
35+
param_set_standard() {
36+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:(extraCreateMetadata|k8sTagClusterId|extraVolumeTags|controllerMetrics|nodeMetrics|batching|defaultFsType|controllerLoggingFormat|nodeLoggingFormat|controllerLogLevel|nodeLogLevel|provisionerLogLevel|attacherLogLevel|snapshotterLogLevel|resizerLogLevel|nodeDriverRegistrarLogLevel|storageClasses|volumeSnapshotClasses|defaultStorageClass|snapshotterForceEnable|controllerUserAgentExtra|controllerEnablePrometheusAnnotations|nodeEnablePrometheusAnnotations|nodeKubeletPath|nodeTolerateAllTaints|controllerPodDisruptionBudget|provisionerLeaderElection|attacherLeaderElection|resizerLeaderElection|reservedVolumeAttachments|hostNetwork|nodeDisableMutation|nodeTerminationGracePeriod)\]"
37+
HELM_EXTRA_FLAGS="--set=controller.extraCreateMetadata=true,controller.k8sTagClusterId=e2e-param-test,controller.extraVolumeTags.TestKey=TestValue,controller.enableMetrics=true,node.enableMetrics=true,controller.batching=true,controller.defaultFsType=xfs,controller.loggingFormat=json,node.loggingFormat=json,controller.logLevel=4,node.logLevel=4,sidecars.provisioner.logLevel=4,sidecars.attacher.logLevel=4,sidecars.snapshotter.logLevel=4,sidecars.resizer.logLevel=4,sidecars.nodeDriverRegistrar.logLevel=4,defaultStorageClass.enabled=true,storageClasses[0].name=test-sc,storageClasses[0].parameters.type=gp3,volumeSnapshotClasses[0].name=test-vsc,volumeSnapshotClasses[0].deletionPolicy=Delete,sidecars.snapshotter.forceEnable=true,controller.userAgentExtra=e2e-test,controller.enablePrometheusAnnotations=true,node.enablePrometheusAnnotations=true,node.kubeletPath=/var/lib/kubelet,node.tolerateAllTaints=true,controller.podDisruptionBudget.enabled=true,sidecars.provisioner.leaderElection.enabled=true,sidecars.attacher.leaderElection.enabled=true,sidecars.resizer.leaderElection.enabled=true,node.reservedVolumeAttachments=2,node.hostNetwork=true,node.serviceAccount.disableMutation=true,node.terminationGracePeriodSeconds=60"
38+
}
39+
40+
# other combines volume-modification, volume-attach-limit, and metadata-labeler (no conflicting Helm values)
41+
param_set_other() {
42+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:(volumeModification|volumemodifierLogLevel|volumemodifierLeaderElection|volumeAttachLimit|metadataLabeler|metadataLabelerLogLevel)\]"
43+
HELM_EXTRA_FLAGS="--set=controller.volumeModificationFeature.enabled=true,sidecars.provisioner.additionalArgs[0]='--feature-gates=VolumeAttributesClass=true',sidecars.resizer.additionalArgs[0]='--feature-gates=VolumeAttributesClass=true',sidecars.volumemodifier.logLevel=4,sidecars.volumemodifier.leaderElection.enabled=false,node.volumeAttachLimit=25,sidecars.metadataLabeler.enabled=true,node.metadataSources='metadata-labeler',sidecars.metadataLabeler.logLevel=4"
44+
}
45+
46+
# debugLogs=true overrides individual logLevel settings, so this must be separate from standard
47+
param_set_debug() {
48+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:(debugLogs|sdkDebugLog)\]"
49+
HELM_EXTRA_FLAGS="--set=debugLogs=true,controller.sdkDebugLog=true"
50+
}
51+
52+
param_set_infra() {
53+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:(controllerReplicaCount|controllerPriorityClassName|controllerResources|controllerPodAnnotations|controllerPodLabels|controllerDeploymentAnnotations|controllerRevisionHistoryLimit|nodePriorityClassName|nodeResources|nodePodAnnotations|nodeDaemonSetAnnotations|nodeRevisionHistoryLimit|provisionerResources|attacherResources|snapshotterResources|resizerResources|nodeDriverRegistrarResources|livenessProbeResources|customLabels|controllerEnv|nodeEnv|controllerTopologySpreadConstraints|controllerSecurityContext|nodeSecurityContext|controllerContainerSecurityContext|controllerVolumes|controllerVolumeMounts|nodeVolumes|nodeVolumeMounts|controllerDnsConfig|nodeDnsConfig|controllerInitContainers|nodeInitContainers|imagePullPolicy|controllerUpdateStrategy|nodeUpdateStrategy)\]"
54+
HELM_EXTRA_FLAGS="--set=controller.replicaCount=3,controller.priorityClassName=system-cluster-critical,controller.resources.requests.cpu=100m,controller.resources.limits.memory=256Mi,controller.podAnnotations.test-annotation=test-value,controller.podLabels.test-label=test-value,controller.deploymentAnnotations.deploy-annotation=deploy-value,controller.revisionHistoryLimit=5,node.priorityClassName=system-node-critical,node.resources.requests.cpu=50m,node.resources.limits.memory=128Mi,node.podAnnotations.node-annotation=node-value,node.daemonSetAnnotations.ds-annotation=ds-value,node.revisionHistoryLimit=3,sidecars.provisioner.resources.requests.cpu=20m,sidecars.attacher.resources.requests.cpu=15m,sidecars.snapshotter.resources.requests.cpu=15m,sidecars.resizer.resources.requests.cpu=15m,sidecars.nodeDriverRegistrar.resources.requests.cpu=10m,sidecars.livenessProbe.resources.requests.cpu=5m,customLabels.custom-label=custom-value,controller.env[0].name=TEST_ENV,controller.env[0].value=test-value,node.env[0].name=NODE_ENV,node.env[0].value=node-value,controller.topologySpreadConstraints[0].maxSkew=1,controller.topologySpreadConstraints[0].topologyKey=topology.kubernetes.io/zone,controller.topologySpreadConstraints[0].whenUnsatisfiable=ScheduleAnyway,controller.securityContext.runAsNonRoot=true,controller.containerSecurityContext.readOnlyRootFilesystem=true,controller.volumes[0].name=extra-volume,controller.volumes[0].configMap.name=kube-root-ca.crt,controller.volumeMounts[0].name=extra-volume,controller.volumeMounts[0].mountPath=/extra,node.volumes[0].name=node-extra-volume,node.volumes[0].configMap.name=kube-root-ca.crt,node.volumeMounts[0].name=node-extra-volume,node.volumeMounts[0].mountPath=/node-extra,controller.dnsConfig.nameservers[0]=8.8.8.8,node.dnsConfig.nameservers[0]=8.8.4.4,controller.initContainers[0].name=init-container,controller.initContainers[0].image=busybox,controller.initContainers[0].command[0]=echo,controller.initContainers[0].command[1]=init,node.initContainers[0].name=node-init-container,node.initContainers[0].image=busybox,node.initContainers[0].command[0]=echo,node.initContainers[0].command[1]=node-init,image.pullPolicy=Always,controller.updateStrategy.type=Recreate,controller.updateStrategy.rollingUpdate=null,node.updateStrategy.type=OnDelete"
55+
}
56+
57+
param_set_legacy-compat() {
58+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:(useOldCSIDriver|legacyXFS)\]"
59+
HELM_EXTRA_FLAGS="--set=useOldCSIDriver=true,node.legacyXFS=true"
60+
}
61+
62+
param_set_selinux() {
63+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:selinux\]"
64+
HELM_EXTRA_FLAGS="--set=node.selinux=true"
65+
}
66+
67+
param_set_fips() {
68+
GINKGO_FOCUS="\[ebs-csi-e2e\] \[param:fips\]"
69+
FIPS_TEST=true
70+
HELM_EXTRA_FLAGS="--set=fips=true"
71+
FIPS_TEST=true make cluster/image
72+
}
73+
74+
# Load a parameter set by name, exporting GINKGO_FOCUS and HELM_EXTRA_FLAGS
75+
load_param_set() {
76+
local name="$1"
77+
local func="param_set_${name}"
78+
if ! declare -f "$func" > /dev/null 2>&1; then
79+
echo "Unknown parameter set: ${name}" >&2
80+
echo "Available sets: standard, other, debug, infra, legacy-compat, selinux, fips" >&2
81+
exit 1
82+
fi
83+
"$func"
84+
export GINKGO_FOCUS HELM_EXTRA_FLAGS
85+
export GINKGO_PARALLEL="${GINKGO_PARALLEL:-5}"
86+
export AWS_AVAILABILITY_ZONES="${AWS_AVAILABILITY_ZONES:-us-west-2a}"
87+
export TEST_PATH="${TEST_PATH:-./tests/e2e/...}"
88+
export JUNIT_REPORT="${REPORT_DIR:-/logs/artifacts}/junit-params-${name}.xml"
89+
# Export optional vars if set by the param set function
90+
if [[ -n "${EBS_INSTALL_SNAPSHOT+x}" ]]; then export EBS_INSTALL_SNAPSHOT; fi
91+
if [[ -n "${FIPS_TEST+x}" ]]; then export FIPS_TEST; fi
92+
}
93+
94+
# Run a single parameter set
95+
run_param_set() {
96+
load_param_set "$1"
97+
echo "### Running parameter set: $1"
98+
./hack/e2e/run.sh
99+
}
100+
101+
# Merge per-set JUnit XMLs into a single file with duplicate skipped tests removed.
102+
# Each Ginkgo run reports ALL specs (most as skipped), so the same skipped test appears
103+
# in every per-set file. This merges all results into one file, keeping non-skipped results
104+
# (passed/failed) over skipped duplicates, and emitting each skipped test only once.
105+
merge_junit_results() {
106+
local report_dir="${REPORT_DIR:-/logs/artifacts}"
107+
local output="${report_dir}/junit-params.xml"
108+
109+
python3 - "$report_dir" "$output" <<'PYEOF'
110+
import glob, sys, xml.etree.ElementTree as ET
111+
112+
report_dir, output = sys.argv[1], sys.argv[2]
113+
merged = {}
114+
time_total = 0.0
115+
116+
def priority(tc):
117+
if tc.find("failure") is not None or tc.find("error") is not None:
118+
return 2 # failed/errored
119+
if tc.find("skipped") is not None:
120+
return 0 # skipped
121+
return 1 # passed
122+
123+
for path in sorted(glob.glob(f"{report_dir}/junit-params-*.xml")):
124+
tree = ET.parse(path)
125+
time_total += float(tree.getroot().get("time", "0"))
126+
for tc in tree.iter("testcase"):
127+
name = tc.get("name", "")
128+
if name not in merged or priority(tc) > priority(merged[name]):
129+
merged[name] = tc
130+
131+
tests = list(merged.values())
132+
skipped = sum(1 for tc in tests if tc.find("skipped") is not None)
133+
failed = sum(1 for tc in tests if tc.find("failure") is not None)
134+
errored = sum(1 for tc in tests if tc.find("error") is not None)
135+
136+
root = ET.Element("testsuites", tests=str(len(tests)), disabled=str(skipped),
137+
errors=str(errored), failures=str(failed), time=str(time_total))
138+
suite = ET.SubElement(root, "testsuite", name="AWS EBS CSI Driver Parameter Tests",
139+
tests=str(len(tests)), skipped=str(skipped),
140+
errors=str(errored), failures=str(failed), time=str(time_total))
141+
for tc in tests:
142+
suite.append(tc)
143+
144+
ET.ElementTree(root).write(output, xml_declaration=True, encoding="UTF-8")
145+
PYEOF
146+
147+
# Remove per-set files only if merge succeeded, so CI only sees the merged result
148+
if [[ $? -eq 0 && -f "$output" ]]; then
149+
rm -f "${report_dir}"/junit-params-*.xml
150+
echo "Merged JUnit results into ${output}"
151+
else
152+
echo "WARNING: JUnit merge failed, keeping per-set files" >&2
153+
fi
154+
}
155+
156+
# Run all standard parameter sets sequentially
157+
run_all_param_sets() {
158+
echo "Running all parameter sets sequentially..."
159+
for set in $PARAM_SETS_ALL; do
160+
run_param_set "$set"
161+
done
162+
merge_junit_results
163+
echo "All parameter sets completed successfully!"
164+
}
165+
166+
# Allow direct invocation: ./hack/e2e/param-sets.sh run <name> or ./hack/e2e/param-sets.sh run-all
167+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
168+
case "${1:-}" in
169+
run)
170+
[[ -z "${2:-}" ]] && { echo "Usage: $0 run <param-set-name>" >&2; exit 1; }
171+
run_param_set "$2"
172+
merge_junit_results
173+
;;
174+
run-all)
175+
run_all_param_sets
176+
;;
177+
*)
178+
echo "Usage: $0 {run <param-set-name>|run-all}" >&2
179+
exit 1
180+
;;
181+
esac
182+
fi

hack/e2e/run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ else
157157
"${BIN}/ginkgo" -p -nodes="${GINKGO_PARALLEL}" \
158158
--focus="${GINKGO_FOCUS}" \
159159
--skip="${GINKGO_SKIP}" \
160-
--junit-report="${REPORT_DIR}/junit.xml" \
160+
--junit-report="${JUNIT_REPORT:-${REPORT_DIR}/junit.xml}" \
161161
"${TEST_PATH}" \
162162
-- \
163163
-kubeconfig="${KUBECONFIG}" \

hack/prow-e2e.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ test-helm-chart)
7878
TEST="helm-ct"
7979
export INSTANCE_TYPE="c5.2xlarge"
8080
;;
81+
test-e2e-parameters)
82+
TEST="parameters-all"
83+
;;
8184
*)
8285
echo "Unknown e2e test ${1}" >&2
8386
exit 1

0 commit comments

Comments
 (0)