From 9fb036e201814a65e2f81ec890afda042e272b1c Mon Sep 17 00:00:00 2001 From: Penghao Date: Tue, 30 Sep 2025 18:08:41 +0800 Subject: [PATCH 1/6] Enable the VolumeGroupSnapshot tests Signed-off-by: Penghao --- prow.sh | 228 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 58 deletions(-) diff --git a/prow.sh b/prow.sh index b4e34730..0106e054 100755 --- a/prow.sh +++ b/prow.sh @@ -140,8 +140,8 @@ csi_prow_kubernetes_version_suffix="$(echo "${CSI_PROW_KUBERNETES_VERSION}" | tr # for that, otherwise the latest stable release for which we then # list the officially supported images below. kind_version_default () { - case "${CSI_PROW_KUBERNETES_VERSION}" in - latest|master) + case "${CSI_PROW_KUBERNETES_VERSION},$(basename "${REPO_DIR}")" in + latest,*|master,*|*,kubernetes) echo main;; *) echo v0.25.0;; @@ -381,6 +381,9 @@ default_csi_snapshotter_version () { } configvar CSI_SNAPSHOTTER_VERSION "$(default_csi_snapshotter_version)" "external-snapshotter version tag" +# Enable installing VolumeGroupSnapshot CRDs (off by default, can be set to true in prow jobs) +configvar CSI_PROW_ENABLE_GROUP_SNAPSHOT "false" "Enable the VolumeGroupSnapshot tests" + # Some tests are known to be unusable in a KinD cluster. For example, # stopping kubelet with "ssh systemctl stop kubelet" simply # doesn't work. Such tests should be written in a way that they verify @@ -552,6 +555,14 @@ list_gates () ( # with https://kind.sigs.k8s.io/docs/user/configuration/#runtime-config list_api_groups () ( set -f; IFS=',' + + # If the volumegroupsnapshot gate is enabled, output required API groups + if ${CSI_PROW_ENABLE_GROUP_SNAPSHOT}; then + echo ' "api/ga": "true"' + echo ' "storage.k8s.io/v1alpha1": "true"' + echo ' "storage.k8s.io/v1beta1": "true"' + fi + # Ignore: Double quote to prevent globbing and word splitting. # shellcheck disable=SC2086 set -- $1 @@ -617,19 +628,29 @@ start_cluster () { if ! [ "$image" ]; then if ! ${csi_prow_kind_have_kubernetes}; then local version="${CSI_PROW_KUBERNETES_VERSION}" - if [ "$version" = "latest" ]; then - version=master + # Detect if running inside k/k repo + if [[ $(basename "${REPO_DIR}") == "kubernetes" ]]; then + echo "Using Kubernetes source from CI checkout ..." + ksrc="${REPO_DIR}" + version="$(git -C "$ksrc" rev-parse HEAD)" + else + echo "Cloning Kubernetes..." + [ "$version" = "latest" ] && version=master + ksrc="${CSI_PROW_WORK}/src/kubernetes" + git_clone https://github.com/kubernetes/kubernetes "$ksrc" "$(version_to_git "$version")" \ + || die "checking out Kubernetes $version failed" fi - git_clone https://github.com/kubernetes/kubernetes "${CSI_PROW_WORK}/src/kubernetes" "$(version_to_git "$version")" || die "checking out Kubernetes $version failed" - go_version="$(go_version_for_kubernetes "${CSI_PROW_WORK}/src/kubernetes" "$version")" || die "cannot proceed without knowing Go version for Kubernetes" + + go_version="$(go_version_for_kubernetes "$ksrc" "$version")" || die "cannot proceed without knowing Go version for Kubernetes" # Changing into the Kubernetes source code directory is a workaround for https://github.com/kubernetes-sigs/kind/issues/1910 # shellcheck disable=SC2046 - (cd "${CSI_PROW_WORK}/src/kubernetes" && run_with_go "$go_version" kind build node-image "${CSI_PROW_WORK}/src/kubernetes" --image csiprow/node:latest) || die "'kind build node-image' failed" + (cd "$ksrc" && run_with_go "$go_version" kind build node-image "$ksrc" --image csiprow/node:latest) || die "'kind build node-image' failed" csi_prow_kind_have_kubernetes=true fi image="csiprow/node:latest" fi + cat >"${CSI_PROW_WORK}/kind-config.yaml" <&2 "ERROR: VolumeGroupSnapshot CRDs not ready after 60s" + exit 1 + fi + echo "$(date +%H:%M:%S)" "waiting for VolumeGroupSnapshot CRDs, attempt #$cnt" + cnt=$((cnt + 1)) + sleep 2 + done + echo "VolumeGroupSnapshot CRDs installed and ready" + fi +} + +# Inject the CSIVolumeGroupSnapshot feature-gate for snapshot controller +# Arguments: +# $1: file path (optional) - if not provided, reads from stdin +inject_vgs_feature_gate() { + if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then + awk ' + BEGIN { inserted=0 } + { + print + if ($0 ~ /--leader-election=true/ && !inserted) { + print " - \"--feature-gates=CSIVolumeGroupSnapshot=true\"" + inserted=1 + } + } + ' + else + cat # just pass the file through unchanged + fi +} + +# Replace controller image based on the deployment mode +# Arguments: +# $1: yaml content +# $2: mode ("external-snapshotter", "canary", or "default") +# $3: new_tag (for external-snapshotter mode) +# $4: registry (for canary mode) +replace_controller_image() { + local yaml="$1" + local mode="$2" + local new_tag="${3:-}" + local registry="${4:-}" + + case "$mode" in + external-snapshotter) + # Replace with snapshot-controller:new_tag + echo "$yaml" | sed -E \ + "s|^([[:space:]]*image: )(.*snapshot-controller):[^[:space:]]*|\1snapshot-controller:${new_tag}|" + ;; + canary) + # Replace with registry/snapshot-controller:canary + echo "$yaml" | sed -E \ + "s|^([[:space:]]*image: ).*/([^/:]+):[^[:space:]]*|\1${registry}/\2:canary|" + ;; + default) + # Replace only the snapshot-controller container tag with CSI_SNAPSHOTTER_VERSION + echo "$yaml" | sed -E \ + "s|^([[:space:]]*image: .*/[^:]+):[^[:space:]]*|\1:${CSI_SNAPSHOTTER_VERSION}|" + ;; + *) + echo "Error: Unknown mode '$mode' for replace_controller_image" >&2 + echo "$yaml" + ;; + esac } # Install snapshot controller and associated RBAC, retrying until the pod is running. @@ -820,6 +917,12 @@ install_snapshot_controller() { done SNAPSHOT_CONTROLLER_YAML="${CONTROLLER_DIR}/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml" + if [[ "$SNAPSHOT_CONTROLLER_YAML" =~ ^https?:// ]]; then + yaml="$(curl -sL "$SNAPSHOT_CONTROLLER_YAML")" + else + yaml="$(cat "$SNAPSHOT_CONTROLLER_YAML")" + fi + if [[ ${REPO_DIR} == *"external-snapshotter"* ]]; then # snapshot-controller image built from the PR will get a "csiprow" tag. # Load it into the "kind" cluster so that we can deploy it. @@ -833,55 +936,32 @@ install_snapshot_controller() { # Replace image in SNAPSHOT_CONTROLLER_YAML with snapshot-controller:csiprow and deploy # NOTE: This logic is similar to the logic here: # https://github.com/kubernetes-csi/csi-driver-host-path/blob/v1.4.0/deploy/util/deploy-hostpath.sh#L155 - # Ignore: Double quote to prevent globbing and word splitting. - # shellcheck disable=SC2086 - # Ignore: Use find instead of ls to better handle non-alphanumeric filenames. - # shellcheck disable=SC2012 - for i in $(ls ${SNAPSHOT_CONTROLLER_YAML} | sort); do - echo " $i" - # Ignore: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead. - # shellcheck disable=SC2002 - # Ignore: See if you can use ${variable//search/replace} instead. - # shellcheck disable=SC2001 - modified="$(cat "$i" | while IFS= read -r line; do - nocomments="$(echo "$line" | sed -e 's/ *#.*$//')" - if echo "$nocomments" | grep -q '^[[:space:]]*image:[[:space:]]*'; then - # Split 'image: registry.k8s.io/sig-storage/snapshot-controller:v3.0.0' - # into image (snapshot-controller:v3.0.0), - # name (snapshot-controller), - # tag (v3.0.0). - image=$(echo "$nocomments" | sed -e 's;.*image:[[:space:]]*;;') - name=$(echo "$image" | sed -e 's;.*/\([^:]*\).*;\1;') - tag=$(echo "$image" | sed -e 's;.*:;;') - - # Now replace registry and/or tag - NEW_TAG="csiprow" - line="$(echo "$nocomments" | sed -e "s;$image;${name}:${NEW_TAG};")" - echo " using $line" >&2 - fi - echo "$line" - done)" - if ! echo "$modified" | kubectl apply -f -; then - echo "modified version of $i:" - echo "$modified" - exit 1 - fi - done + modified="$(replace_controller_image "$yaml" "external-snapshotter" "$NEW_TAG" | inject_vgs_feature_gate)" + diff <(echo "$yaml") <(echo "$modified") + if ! echo "$modified" | kubectl apply -f -; then + echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" + echo "$modified" + exit 1 + fi elif [ "${CSI_PROW_DRIVER_CANARY}" = "canary" ]; then echo "Deploying snapshot-controller from ${SNAPSHOT_CONTROLLER_YAML} with canary images." - yaml="$(kubectl apply --dry-run=client -o yaml -f "$SNAPSHOT_CONTROLLER_YAML")" - # Ignore: See if you can use ${variable//search/replace} instead. - # shellcheck disable=SC2001 - modified="$(echo "$yaml" | sed -e "s;image: .*/\([^/:]*\):.*;image: ${CSI_PROW_DRIVER_CANARY_REGISTRY}/\1:canary;")" + modified="$(replace_controller_image "$yaml" "canary" "" "${CSI_PROW_DRIVER_CANARY_REGISTRY}" | inject_vgs_feature_gate)" diff <(echo "$yaml") <(echo "$modified") if ! echo "$modified" | kubectl apply -f -; then - echo "modified version of $SNAPSHOT_CONTROLLER_YAML:" + echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" echo "$modified" exit 1 fi else echo "kubectl apply -f $SNAPSHOT_CONTROLLER_YAML" - kubectl apply -f "$SNAPSHOT_CONTROLLER_YAML" + # Replace snapshot-controller container tag to make it consistent with CSI_SNAPSHOTTER_VERSION + modified="$(replace_controller_image "$yaml" "default" | inject_vgs_feature_gate)" + diff <(echo "$yaml") <(echo "$modified") + if ! echo "$modified" | kubectl apply -f -; then + echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" + echo "$modified" + exit 1 + fi fi cnt=0 @@ -980,14 +1060,23 @@ install_e2e () { if sidecar_tests_enabled; then run_with_go "${CSI_PROW_GO_VERSION_BUILD}" go test -c -o "${CSI_PROW_WORK}/e2e-local.test" "${CSI_PROW_SIDECAR_E2E_IMPORT_PATH}" fi - git_checkout "${CSI_PROW_E2E_REPO}" "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" "${CSI_PROW_E2E_VERSION}" --depth=1 && + + # In kubernetes presubmit do not need clone the src + if [[ $(basename "${REPO_DIR}") == "kubernetes" ]]; then + echo "Using existing repo at ${REPO_DIR}" + E2E_SRC_DIR="${REPO_DIR}" + else + git_checkout "${CSI_PROW_E2E_REPO}" "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" "${CSI_PROW_E2E_VERSION}" --depth=1 + E2E_SRC_DIR="${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" + fi + if [ "${CSI_PROW_E2E_IMPORT_PATH}" = "k8s.io/kubernetes" ]; then patch_kubernetes "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" "${CSI_PROW_WORK}" && - go_version="${CSI_PROW_GO_VERSION_E2E:-$(go_version_for_kubernetes "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" "${CSI_PROW_E2E_VERSION}")}" && - run_with_go "$go_version" make WHAT=test/e2e/e2e.test "-C${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && - ln -s "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}/_output/bin/e2e.test" "${CSI_PROW_WORK}" && - run_with_go "$go_version" make WHAT=vendor/github.com/onsi/ginkgo/ginkgo "-C${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && - ln -s "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}/_output/bin/ginkgo" "${CSI_PROW_BIN}" + go_version="${CSI_PROW_GO_VERSION_E2E:-$(go_version_for_kubernetes "${E2E_SRC_DIR}" "${CSI_PROW_E2E_VERSION}")}" && + run_with_go "$go_version" make WHAT=test/e2e/e2e.test "-C${E2E_SRC_DIR}" && + ln -s "${E2E_SRC_DIR}/_output/bin/e2e.test" "${CSI_PROW_WORK}" && + run_with_go "$go_version" make WHAT=vendor/github.com/onsi/ginkgo/ginkgo "-C${E2E_SRC_DIR}" && + ln -s "${E2E_SRC_DIR}/_output/bin/ginkgo" "${CSI_PROW_BIN}" else run_with_go "${CSI_PROW_GO_VERSION_E2E}" go test -c -o "${CSI_PROW_WORK}/e2e.test" "${CSI_PROW_E2E_IMPORT_PATH}/test/e2e" fi @@ -1028,11 +1117,20 @@ run_e2e () ( # Rename, merge and filter JUnit files. Necessary in case that we run the E2E suite again # and to avoid the large number of "skipped" tests that we get from using # the full Kubernetes E2E testsuite while only running a few tests. + # shellcheck disable=SC2329 move_junit () { + # shellcheck disable=SC2317 + FILTER='External.Storage|CSI.mock.volume' + # shellcheck disable=SC2317 + if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then + FILTER="${FILTER}|\[Feature:volumegroupsnapshot\]" + fi + + # shellcheck disable=SC2317 if ls "${ARTIFACTS}"/junit_[0-9]*.xml 2>/dev/null >/dev/null; then mkdir -p "${ARTIFACTS}/junit/${name}" && mkdir -p "${ARTIFACTS}/junit/steps" && - run_filter_junit -t="External.Storage|CSI.mock.volume" -o "${ARTIFACTS}/junit/steps/junit_${name}.xml" "${ARTIFACTS}"/junit_[0-9]*.xml && + run_filter_junit -t="${FILTER}" -o "${ARTIFACTS}/junit/steps/junit_${name}.xml" "${ARTIFACTS}"/junit_[0-9]*.xml && mv "${ARTIFACTS}"/junit_[0-9]*.xml "${ARTIFACTS}/junit/${name}/" fi } @@ -1041,6 +1139,9 @@ run_e2e () ( if [ "${name}" == "local" ]; then cd "${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH}" && run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e-local.test" -- -report-dir "${ARTIFACTS}" -report-prefix local + elif [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ] && [ "${name}" == "parallel-features" ]; then + cd "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && + run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e.test" -- -report-dir "${ARTIFACTS}" -report-prefix vgs else cd "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e.test" -- -report-dir "${ARTIFACTS}" -storage.testdriver="${CSI_PROW_WORK}/test-driver.yaml" @@ -1248,7 +1349,10 @@ main () { images= if ${CSI_PROW_BUILD_JOB}; then # A successful build is required for testing. - run_with_go "${CSI_PROW_GO_VERSION_BUILD}" make all "GOFLAGS_VENDOR=${GOFLAGS_VENDOR}" "BUILD_PLATFORMS=${CSI_PROW_BUILD_PLATFORMS}" || die "'make all' failed" + # In kubernetes presubmit the needed test packages are already built in kind node image + if [[ $(basename "${REPO_DIR}") != "kubernetes" ]]; then + run_with_go "${CSI_PROW_GO_VERSION_BUILD}" make all "GOFLAGS_VENDOR=${GOFLAGS_VENDOR}" "BUILD_PLATFORMS=${CSI_PROW_BUILD_PLATFORMS}" || die "'make all' failed" + fi # We don't want test failures to prevent E2E testing below, because the failure # might have been minor or unavoidable, for example when experimenting with # changes in "release-tools" in a PR (that fails the "is release-tools unmodified" @@ -1264,7 +1368,9 @@ main () { fi fi # Required for E2E testing. - run_with_go "${CSI_PROW_GO_VERSION_BUILD}" make container "GOFLAGS_VENDOR=${GOFLAGS_VENDOR}" || die "'make container' failed" + if [[ $(basename "${REPO_DIR}") != "kubernetes" ]]; then + run_with_go "${CSI_PROW_GO_VERSION_BUILD}" make container "GOFLAGS_VENDOR=${GOFLAGS_VENDOR}" || die "'make container' failed" + fi fi if tests_need_kind; then @@ -1318,7 +1424,6 @@ main () { install_snapshot_crds install_snapshot_controller - # Installing the driver might be disabled. if ${CSI_PROW_DRIVER_INSTALL} "$images"; then collect_cluster_info @@ -1339,11 +1444,18 @@ main () { ret=1 fi + # Only add feature regex if groupsnapshot is not enabled + if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then + combined_focus="${CSI_PROW_E2E_FOCUS}" + else + combined_focus="$focus.*($(regex_join "${CSI_PROW_E2E_FOCUS}"))" + fi + # Run tests that are feature tagged, but non-alpha # Ignore: Double quote to prevent globbing and word splitting. # shellcheck disable=SC2086 if ! run_e2e parallel-features ${CSI_PROW_GINKGO_PARALLEL} \ - -focus="$focus.*($(regex_join "${CSI_PROW_E2E_FOCUS}"))" \ + -focus="$combined_focus" \ -skip="$(regex_join "${CSI_PROW_E2E_SERIAL}")"; then warn "E2E parallel features failed" ret=1 From 9160d31141b8af4d4834034a315643d59b2cdb73 Mon Sep 17 00:00:00 2001 From: Penghao Date: Sat, 11 Oct 2025 19:14:45 +0800 Subject: [PATCH 2/6] Fix: refine functions Signed-off-by: Penghao --- prow.sh | 142 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 50 deletions(-) diff --git a/prow.sh b/prow.sh index 0106e054..7c5c2752 100755 --- a/prow.sh +++ b/prow.sh @@ -555,14 +555,6 @@ list_gates () ( # with https://kind.sigs.k8s.io/docs/user/configuration/#runtime-config list_api_groups () ( set -f; IFS=',' - - # If the volumegroupsnapshot gate is enabled, output required API groups - if ${CSI_PROW_ENABLE_GROUP_SNAPSHOT}; then - echo ' "api/ga": "true"' - echo ' "storage.k8s.io/v1alpha1": "true"' - echo ' "storage.k8s.io/v1beta1": "true"' - fi - # Ignore: Double quote to prevent globbing and word splitting. # shellcheck disable=SC2086 set -- $1 @@ -856,20 +848,20 @@ inject_vgs_feature_gate() { fi } -# Replace controller image based on the deployment mode +# Replace the snapshot controller image based on the test mode # Arguments: # $1: yaml content -# $2: mode ("external-snapshotter", "canary", or "default") -# $3: new_tag (for external-snapshotter mode) +# $2: mode ("local-build", "canary", or "default") +# $3: new_tag (for local-build mode) # $4: registry (for canary mode) -replace_controller_image() { +replace_snapshot_controller_image() { local yaml="$1" local mode="$2" local new_tag="${3:-}" local registry="${4:-}" case "$mode" in - external-snapshotter) + local-build) # Replace with snapshot-controller:new_tag echo "$yaml" | sed -E \ "s|^([[:space:]]*image: )(.*snapshot-controller):[^[:space:]]*|\1snapshot-controller:${new_tag}|" @@ -936,7 +928,7 @@ install_snapshot_controller() { # Replace image in SNAPSHOT_CONTROLLER_YAML with snapshot-controller:csiprow and deploy # NOTE: This logic is similar to the logic here: # https://github.com/kubernetes-csi/csi-driver-host-path/blob/v1.4.0/deploy/util/deploy-hostpath.sh#L155 - modified="$(replace_controller_image "$yaml" "external-snapshotter" "$NEW_TAG" | inject_vgs_feature_gate)" + modified="$(replace_snapshot_controller_image "$yaml" "local-build" "$NEW_TAG" | inject_vgs_feature_gate)" diff <(echo "$yaml") <(echo "$modified") if ! echo "$modified" | kubectl apply -f -; then echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" @@ -945,7 +937,7 @@ install_snapshot_controller() { fi elif [ "${CSI_PROW_DRIVER_CANARY}" = "canary" ]; then echo "Deploying snapshot-controller from ${SNAPSHOT_CONTROLLER_YAML} with canary images." - modified="$(replace_controller_image "$yaml" "canary" "" "${CSI_PROW_DRIVER_CANARY_REGISTRY}" | inject_vgs_feature_gate)" + modified="$(replace_snapshot_controller_image "$yaml" "canary" "" "${CSI_PROW_DRIVER_CANARY_REGISTRY}" | inject_vgs_feature_gate)" diff <(echo "$yaml") <(echo "$modified") if ! echo "$modified" | kubectl apply -f -; then echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" @@ -955,7 +947,7 @@ install_snapshot_controller() { else echo "kubectl apply -f $SNAPSHOT_CONTROLLER_YAML" # Replace snapshot-controller container tag to make it consistent with CSI_SNAPSHOTTER_VERSION - modified="$(replace_controller_image "$yaml" "default" | inject_vgs_feature_gate)" + modified="$(replace_snapshot_controller_image "$yaml" "default" | inject_vgs_feature_gate)" diff <(echo "$yaml") <(echo "$modified") if ! echo "$modified" | kubectl apply -f -; then echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" @@ -1060,23 +1052,24 @@ install_e2e () { if sidecar_tests_enabled; then run_with_go "${CSI_PROW_GO_VERSION_BUILD}" go test -c -o "${CSI_PROW_WORK}/e2e-local.test" "${CSI_PROW_SIDECAR_E2E_IMPORT_PATH}" fi - + + local e2e_src_dir # In kubernetes presubmit do not need clone the src if [[ $(basename "${REPO_DIR}") == "kubernetes" ]]; then echo "Using existing repo at ${REPO_DIR}" - E2E_SRC_DIR="${REPO_DIR}" + e2e_src_dir="${REPO_DIR}" else git_checkout "${CSI_PROW_E2E_REPO}" "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" "${CSI_PROW_E2E_VERSION}" --depth=1 - E2E_SRC_DIR="${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" + e2e_src_dir="${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" fi if [ "${CSI_PROW_E2E_IMPORT_PATH}" = "k8s.io/kubernetes" ]; then patch_kubernetes "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" "${CSI_PROW_WORK}" && - go_version="${CSI_PROW_GO_VERSION_E2E:-$(go_version_for_kubernetes "${E2E_SRC_DIR}" "${CSI_PROW_E2E_VERSION}")}" && - run_with_go "$go_version" make WHAT=test/e2e/e2e.test "-C${E2E_SRC_DIR}" && - ln -s "${E2E_SRC_DIR}/_output/bin/e2e.test" "${CSI_PROW_WORK}" && - run_with_go "$go_version" make WHAT=vendor/github.com/onsi/ginkgo/ginkgo "-C${E2E_SRC_DIR}" && - ln -s "${E2E_SRC_DIR}/_output/bin/ginkgo" "${CSI_PROW_BIN}" + go_version="${CSI_PROW_GO_VERSION_E2E:-$(go_version_for_kubernetes "${e2e_src_dir}" "${CSI_PROW_E2E_VERSION}")}" && + run_with_go "$go_version" make WHAT=test/e2e/e2e.test "-C${e2e_src_dir}" && + ln -s "${e2e_src_dir}/_output/bin/e2e.test" "${CSI_PROW_WORK}" && + run_with_go "$go_version" make WHAT=vendor/github.com/onsi/ginkgo/ginkgo "-C${e2e_src_dir}" && + ln -s "${e2e_src_dir}/_output/bin/ginkgo" "${CSI_PROW_BIN}" else run_with_go "${CSI_PROW_GO_VERSION_E2E}" go test -c -o "${CSI_PROW_WORK}/e2e.test" "${CSI_PROW_E2E_IMPORT_PATH}/test/e2e" fi @@ -1103,7 +1096,16 @@ run_with_loggers () ( # Invokes the filter-junit.go tool. run_filter_junit () { - run_with_go "${CSI_PROW_GO_VERSION_BUILD}" go run "${RELEASE_TOOLS_ROOT}/filter-junit.go" "$@" + local go_version ksrc version + go_version="${CSI_PROW_GO_VERSION_BUILD}" + # Detect if running inside k/k repo + if [[ $(basename "${REPO_DIR}") == "kubernetes" ]]; then + echo "Using Kubernetes source from CI checkout ..." + ksrc="${REPO_DIR}" + version="$(git -C "$ksrc" rev-parse HEAD)" + go_version="$(go_version_for_kubernetes "$ksrc" "$version")" || die "cannot proceed without knowing Go version for run_filter_junit" + fi + run_with_go "${go_version}" go run "${RELEASE_TOOLS_ROOT}/filter-junit.go" "$@" } # Runs the E2E test suite in a sub-shell. @@ -1119,33 +1121,68 @@ run_e2e () ( # the full Kubernetes E2E testsuite while only running a few tests. # shellcheck disable=SC2329 move_junit () { - # shellcheck disable=SC2317 - FILTER='External.Storage|CSI.mock.volume' - # shellcheck disable=SC2317 - if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then - FILTER="${FILTER}|\[Feature:volumegroupsnapshot\]" - fi - # shellcheck disable=SC2317 if ls "${ARTIFACTS}"/junit_[0-9]*.xml 2>/dev/null >/dev/null; then mkdir -p "${ARTIFACTS}/junit/${name}" && - mkdir -p "${ARTIFACTS}/junit/steps" && - run_filter_junit -t="${FILTER}" -o "${ARTIFACTS}/junit/steps/junit_${name}.xml" "${ARTIFACTS}"/junit_[0-9]*.xml && + mkdir -p "${ARTIFACTS}/junit/steps" + + # Skip filter-junit for in-tree (VGS) runs, because k/k already produces clean JUnit + if [[ "${name}" == "vgs" ]]; then + echo "Skipping filter-junit for ${name} (in-tree tests already generate clean JUnit)" + mv "${ARTIFACTS}"/junit_[0-9]*.xml "${ARTIFACTS}/junit/${name}/" + else + # Run filtering for CSI tests to remove duplicates/skipped cases + run_filter_junit -t="External.Storage|CSI.mock.volume" \ + -o "${ARTIFACTS}/junit/steps/junit_${name}.xml" \ + "${ARTIFACTS}"/junit_[0-9]*.xml && mv "${ARTIFACTS}"/junit_[0-9]*.xml "${ARTIFACTS}/junit/${name}/" + fi fi } trap move_junit EXIT - if [ "${name}" == "local" ]; then - cd "${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH}" && - run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e-local.test" -- -report-dir "${ARTIFACTS}" -report-prefix local - elif [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ] && [ "${name}" == "parallel-features" ]; then - cd "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && - run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e.test" -- -report-dir "${ARTIFACTS}" -report-prefix vgs + + # Only set up move_junit for non-VGS tests + if [ "$name" != "vgs" ]; then + trap move_junit EXIT + fi + + # Determine ginkgo target and options + local ginkgo_target="" + local extra_args="" + local e2e_src_dir="" + local args=() + + if [[ $(basename "${REPO_DIR}") == "kubernetes" ]]; then + e2e_src_dir="${REPO_DIR}" else - cd "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && - run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e.test" -- -report-dir "${ARTIFACTS}" -storage.testdriver="${CSI_PROW_WORK}/test-driver.yaml" + e2e_src_dir="${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" fi + + case "$name" in + local) + ginkgo_target="${CSI_PROW_WORK}/e2e-local.test" + extra_args="-report-prefix=local" + cd "${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH}" || die "cd ${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH} failed" + ;; + vgs) + # VGS tests are in in-tree/core tests; do NOT pass -storage.testdriver + ginkgo_target="${CSI_PROW_WORK}/e2e.test" + cd "${e2e_src_dir}" || die "cd ${e2e_src_dir} failed" + ;; + *) + # Default: CSI external driver tests + ginkgo_target="${CSI_PROW_WORK}/e2e.test" + extra_args="-storage.testdriver=${CSI_PROW_WORK}/test-driver.yaml" + cd "${e2e_src_dir}" || die "cd ${e2e_src_dir} failed" + ;; + esac + + [ -n "$extra_args" ] && args+=("$extra_args") + run_with_loggers env \ + KUBECONFIG="$KUBECONFIG" \ + KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" \ + ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "$ginkgo_target" -- -report-dir "${ARTIFACTS}" "${args[@]}" ) # Run csi-sanity against installed CSI driver. @@ -1444,18 +1481,11 @@ main () { ret=1 fi - # Only add feature regex if groupsnapshot is not enabled - if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then - combined_focus="${CSI_PROW_E2E_FOCUS}" - else - combined_focus="$focus.*($(regex_join "${CSI_PROW_E2E_FOCUS}"))" - fi - # Run tests that are feature tagged, but non-alpha # Ignore: Double quote to prevent globbing and word splitting. # shellcheck disable=SC2086 if ! run_e2e parallel-features ${CSI_PROW_GINKGO_PARALLEL} \ - -focus="$combined_focus" \ + -focus="$focus.*($(regex_join "${CSI_PROW_E2E_FOCUS}"))" \ -skip="$(regex_join "${CSI_PROW_E2E_SERIAL}")"; then warn "E2E parallel features failed" ret=1 @@ -1479,6 +1509,18 @@ main () { ret=1 fi fi + + # Run VGS in-tree tests only if enabled + if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then + vgs_focus="\[Feature:volumegroupsnapshot\]" + if ! run_e2e vgs \ + -focus="${vgs_focus}" \ + -skip="$(regex_join "${CSI_PROW_E2E_SERIAL}" "${CSI_PROW_E2E_SKIP}")"; then + warn "E2E VGS tests failed" + ret=1 + fi + fi + fi delete_cluster_inside_prow_job non-alpha fi From 8ab66fa8fd40e8cedf9081d7edc3f7f8828f3404 Mon Sep 17 00:00:00 2001 From: Penghao Date: Thu, 16 Oct 2025 16:17:07 +0800 Subject: [PATCH 3/6] Fix: remove duplicated diff and apply Signed-off-by: Penghao --- prow.sh | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/prow.sh b/prow.sh index 7c5c2752..d95fe062 100755 --- a/prow.sh +++ b/prow.sh @@ -833,16 +833,7 @@ install_snapshot_crds() { # $1: file path (optional) - if not provided, reads from stdin inject_vgs_feature_gate() { if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then - awk ' - BEGIN { inserted=0 } - { - print - if ($0 ~ /--leader-election=true/ && !inserted) { - print " - \"--feature-gates=CSIVolumeGroupSnapshot=true\"" - inserted=1 - } - } - ' + sed -E 's|^([[:space:]]*)# end snapshot controller args|\1- "--feature-gates=CSIVolumeGroupSnapshot=true"|' else cat # just pass the file through unchanged fi @@ -929,31 +920,20 @@ install_snapshot_controller() { # NOTE: This logic is similar to the logic here: # https://github.com/kubernetes-csi/csi-driver-host-path/blob/v1.4.0/deploy/util/deploy-hostpath.sh#L155 modified="$(replace_snapshot_controller_image "$yaml" "local-build" "$NEW_TAG" | inject_vgs_feature_gate)" - diff <(echo "$yaml") <(echo "$modified") - if ! echo "$modified" | kubectl apply -f -; then - echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" - echo "$modified" - exit 1 - fi elif [ "${CSI_PROW_DRIVER_CANARY}" = "canary" ]; then echo "Deploying snapshot-controller from ${SNAPSHOT_CONTROLLER_YAML} with canary images." modified="$(replace_snapshot_controller_image "$yaml" "canary" "" "${CSI_PROW_DRIVER_CANARY_REGISTRY}" | inject_vgs_feature_gate)" - diff <(echo "$yaml") <(echo "$modified") - if ! echo "$modified" | kubectl apply -f -; then - echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" - echo "$modified" - exit 1 - fi else echo "kubectl apply -f $SNAPSHOT_CONTROLLER_YAML" # Replace snapshot-controller container tag to make it consistent with CSI_SNAPSHOTTER_VERSION modified="$(replace_snapshot_controller_image "$yaml" "default" | inject_vgs_feature_gate)" - diff <(echo "$yaml") <(echo "$modified") - if ! echo "$modified" | kubectl apply -f -; then - echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" - echo "$modified" - exit 1 - fi + fi + + diff <(echo "$yaml") <(echo "$modified") + if ! echo "$modified" | kubectl apply -f -; then + echo "modified version of ${SNAPSHOT_CONTROLLER_YAML}:" + echo "$modified" + exit 1 fi cnt=0 From 494f87981aa4f233cb0a8bf59aded1cbc3ac3368 Mon Sep 17 00:00:00 2001 From: Penghao Date: Thu, 23 Oct 2025 22:10:57 +0800 Subject: [PATCH 4/6] Fix: run vgs tests from csi external Signed-off-by: Penghao --- prow.sh | 115 ++++++++++++++++++++++++-------------------------------- 1 file changed, 50 insertions(+), 65 deletions(-) diff --git a/prow.sh b/prow.sh index d95fe062..2a5c54e6 100755 --- a/prow.sh +++ b/prow.sh @@ -780,6 +780,30 @@ install_csi_driver () { info "For container output see job artifacts." die "deploying the CSI driver with ${deploy_driver} failed" fi + + if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then + # Enable the groupSnapshot capability in test driver manifest + yq -i '.GroupSnapshotClass.FromName = true' "${CSI_PROW_WORK}/test-driver.yaml" + yq -i '.DriverInfo.Capabilities.groupSnapshot = true' "${CSI_PROW_WORK}/test-driver.yaml" + cat "${CSI_PROW_WORK}/test-driver.yaml" + + # Make sure using consistent snapshotter image with snapshot-controller + DRIVER_SNAPSHOTTER_IMAGE="registry.k8s.io/sig-storage/csi-snapshotter:${CSI_SNAPSHOTTER_VERSION}" + kubectl get sts csi-hostpathplugin -n default -o yaml \ + | yq "(.spec.template.spec.containers[] | select(.name == \"csi-snapshotter\") | .image) = \"${DRIVER_SNAPSHOTTER_IMAGE}\"" \ + | kubectl apply -f - + + # Enable the groupsnapshot feature gate for driver snapshotter + kubectl get sts csi-hostpathplugin -n default -o yaml \ + | yq '(.spec.template.spec.containers[] | select(.name == "csi-snapshotter") | .args) += ["--feature-gates=CSIVolumeGroupSnapshot=true"]' \ + | kubectl apply -f - + + # Restart the StatefulSet + kubectl rollout restart sts csi-hostpathplugin -n default + + # Wait for the rollout to complete + kubectl rollout status sts csi-hostpathplugin -n default + fi } # Installs all necessary snapshotter CRDs @@ -1101,68 +1125,22 @@ run_e2e () ( # the full Kubernetes E2E testsuite while only running a few tests. # shellcheck disable=SC2329 move_junit () { - # shellcheck disable=SC2317 if ls "${ARTIFACTS}"/junit_[0-9]*.xml 2>/dev/null >/dev/null; then mkdir -p "${ARTIFACTS}/junit/${name}" && - mkdir -p "${ARTIFACTS}/junit/steps" - - # Skip filter-junit for in-tree (VGS) runs, because k/k already produces clean JUnit - if [[ "${name}" == "vgs" ]]; then - echo "Skipping filter-junit for ${name} (in-tree tests already generate clean JUnit)" - mv "${ARTIFACTS}"/junit_[0-9]*.xml "${ARTIFACTS}/junit/${name}/" - else - # Run filtering for CSI tests to remove duplicates/skipped cases - run_filter_junit -t="External.Storage|CSI.mock.volume" \ - -o "${ARTIFACTS}/junit/steps/junit_${name}.xml" \ - "${ARTIFACTS}"/junit_[0-9]*.xml && + mkdir -p "${ARTIFACTS}/junit/steps" && + run_filter_junit -t="External.Storage|CSI.mock.volume" -o "${ARTIFACTS}/junit/steps/junit_${name}.xml" "${ARTIFACTS}"/junit_[0-9]*.xml && mv "${ARTIFACTS}"/junit_[0-9]*.xml "${ARTIFACTS}/junit/${name}/" - fi fi } trap move_junit EXIT - - # Only set up move_junit for non-VGS tests - if [ "$name" != "vgs" ]; then - trap move_junit EXIT - fi - - # Determine ginkgo target and options - local ginkgo_target="" - local extra_args="" - local e2e_src_dir="" - local args=() - - if [[ $(basename "${REPO_DIR}") == "kubernetes" ]]; then - e2e_src_dir="${REPO_DIR}" + if [ "${name}" == "local" ]; then + cd "${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH}" && + run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e-local.test" -- -report-dir "${ARTIFACTS}" -report-prefix local else - e2e_src_dir="${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" + cd "${GOPATH}/src/${CSI_PROW_E2E_IMPORT_PATH}" && + run_with_loggers env KUBECONFIG="$KUBECONFIG" KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "${CSI_PROW_WORK}/e2e.test" -- -report-dir "${ARTIFACTS}" -storage.testdriver="${CSI_PROW_WORK}/test-driver.yaml" fi - - case "$name" in - local) - ginkgo_target="${CSI_PROW_WORK}/e2e-local.test" - extra_args="-report-prefix=local" - cd "${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH}" || die "cd ${GOPATH}/src/${CSI_PROW_SIDECAR_E2E_PATH} failed" - ;; - vgs) - # VGS tests are in in-tree/core tests; do NOT pass -storage.testdriver - ginkgo_target="${CSI_PROW_WORK}/e2e.test" - cd "${e2e_src_dir}" || die "cd ${e2e_src_dir} failed" - ;; - *) - # Default: CSI external driver tests - ginkgo_target="${CSI_PROW_WORK}/e2e.test" - extra_args="-storage.testdriver=${CSI_PROW_WORK}/test-driver.yaml" - cd "${e2e_src_dir}" || die "cd ${e2e_src_dir} failed" - ;; - esac - - [ -n "$extra_args" ] && args+=("$extra_args") - run_with_loggers env \ - KUBECONFIG="$KUBECONFIG" \ - KUBE_TEST_REPO_LIST="$(if [ -e "${CSI_PROW_WORK}/e2e-repo-list" ]; then echo "${CSI_PROW_WORK}/e2e-repo-list"; fi)" \ - ginkgo --timeout="${CSI_PROW_GINKGO_TIMEOUT}" -v "$@" "$ginkgo_target" -- -report-dir "${ARTIFACTS}" "${args[@]}" ) # Run csi-sanity against installed CSI driver. @@ -1356,6 +1334,22 @@ function version_gt() { test "$(printf '%s' "$versions" | sort -V | head -n 1)" != "$greaterVersion" } +install_yq_if_missing() { + local version="${1:-v4.48.1}" + local yq_path="/usr/local/bin/yq" + if ! command -v yq &>/dev/null; then + echo "Installing yq ${version}..." + if ! curl -fsSL -o "${yq_path}" "https://github.com/mikefarah/yq/releases/download/${version}/yq_linux_amd64"; then + echo "Failed to download yq" >&2 + exit 1 + fi + chmod +x "${yq_path}" + echo "yq ${version} installed at ${yq_path}" + else + echo "yq found, skipping install" + fi +} + main () { local images ret ret=0 @@ -1363,6 +1357,9 @@ main () { # Set up work directory. ensure_paths + # Install yq + install_yq_if_missing + images= if ${CSI_PROW_BUILD_JOB}; then # A successful build is required for testing. @@ -1489,18 +1486,6 @@ main () { ret=1 fi fi - - # Run VGS in-tree tests only if enabled - if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then - vgs_focus="\[Feature:volumegroupsnapshot\]" - if ! run_e2e vgs \ - -focus="${vgs_focus}" \ - -skip="$(regex_join "${CSI_PROW_E2E_SERIAL}" "${CSI_PROW_E2E_SKIP}")"; then - warn "E2E VGS tests failed" - ret=1 - fi - fi - fi delete_cluster_inside_prow_job non-alpha fi From fa3507d430a54cde626827c7712e1831e026082e Mon Sep 17 00:00:00 2001 From: Penghao Date: Thu, 23 Oct 2025 22:45:25 +0800 Subject: [PATCH 5/6] Fix: shellcheck Signed-off-by: Penghao --- prow.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prow.sh b/prow.sh index 2a5c54e6..a6c3e766 100755 --- a/prow.sh +++ b/prow.sh @@ -1333,7 +1333,7 @@ function version_gt() { greaterVersion=${greaterVersion#"v"}; test "$(printf '%s' "$versions" | sort -V | head -n 1)" != "$greaterVersion" } - +# shellcheck disable=SC2120 install_yq_if_missing() { local version="${1:-v4.48.1}" local yq_path="/usr/local/bin/yq" @@ -1358,6 +1358,7 @@ main () { ensure_paths # Install yq + # shellcheck disable=SC2119 install_yq_if_missing images= From 3467e7a8dfc6cfa8bff06415470d43487d491041 Mon Sep 17 00:00:00 2001 From: Penghao Date: Fri, 24 Oct 2025 14:18:18 +0800 Subject: [PATCH 6/6] feat: introduce CSI_PROW_DRIVER_POSTINSTALL hook mechanism Signed-off-by: Penghao --- prow.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/prow.sh b/prow.sh index a6c3e766..3a430558 100755 --- a/prow.sh +++ b/prow.sh @@ -210,6 +210,12 @@ configvar CSI_PROW_DEPLOYMENT_SUFFIX "" "additional suffix in kubernetes-x.yy[su # a .prow.sh file and this config variable can be overridden. configvar CSI_PROW_DRIVER_INSTALL "install_csi_driver" "name of the shell function which installs the CSI driver" +# Optional post-install hook(s) that run after the CSI driver is successfully installed. +# This allows sidecars to customize the test environment (e.g., modify test-driver.yaml). +# Can be a single function name or a space-separated list of function names. +# Set to empty string to disable. +configvar CSI_PROW_DRIVER_POSTINSTALL "" "name(s) of shell function(s) which get called after CSI driver is installed" + # If CSI_PROW_DRIVER_CANARY is set (typically to "canary", but also # version tag. Usually empty. CSI_PROW_HOSTPATH_CANARY is # accepted as alternative name because some test-infra jobs @@ -781,29 +787,66 @@ install_csi_driver () { die "deploying the CSI driver with ${deploy_driver} failed" fi - if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" = "true" ]; then - # Enable the groupSnapshot capability in test driver manifest - yq -i '.GroupSnapshotClass.FromName = true' "${CSI_PROW_WORK}/test-driver.yaml" - yq -i '.DriverInfo.Capabilities.groupSnapshot = true' "${CSI_PROW_WORK}/test-driver.yaml" - cat "${CSI_PROW_WORK}/test-driver.yaml" + # Call post-install hook(s) if defined + if [ -n "${CSI_PROW_DRIVER_POSTINSTALL}" ]; then + # Iterate through space-separated list of hook functions + for hook_func in ${CSI_PROW_DRIVER_POSTINSTALL}; do + info "Running post-install hook: ${hook_func}" + # Check the function exists before calling it + if ! declare -f "${hook_func}" >/dev/null; then + die "post-install hook function '${hook_func}' is not defined" + fi + if ! "${hook_func}"; then + die "post-install hook ${hook_func} failed" + fi + done + fi +} + +# Post-install hook for enabling VolumeGroupSnapshot support. +# This function configures the test driver and CSI driver deployment +# to support VolumeGroupSnapshot functionality. +# +# This can be used as an example post-install hook by setting: +# export CSI_PROW_DRIVER_POSTINSTALL="vgs_post_install" +vgs_post_install () { + if [ "${CSI_PROW_ENABLE_GROUP_SNAPSHOT}" != "true" ]; then + warn "Skipping VGS post-install: CSI_PROW_ENABLE_GROUP_SNAPSHOT is not enabled" + return 0 + fi + + info "Configuring VolumeGroupSnapshot support..." + + # Enable the groupSnapshot capability in test driver manifest + info "Updating test-driver.yaml with VGS capabilities" + yq -i '.GroupSnapshotClass.FromName = true' "${CSI_PROW_WORK}/test-driver.yaml" + yq -i '.DriverInfo.Capabilities.groupSnapshot = true' "${CSI_PROW_WORK}/test-driver.yaml" - # Make sure using consistent snapshotter image with snapshot-controller - DRIVER_SNAPSHOTTER_IMAGE="registry.k8s.io/sig-storage/csi-snapshotter:${CSI_SNAPSHOTTER_VERSION}" - kubectl get sts csi-hostpathplugin -n default -o yaml \ + info "Test driver configuration:" + cat "${CSI_PROW_WORK}/test-driver.yaml" + + # Make sure using consistent snapshotter image with snapshot-controller + info "Updating csi-snapshotter image to ${CSI_SNAPSHOTTER_VERSION}" + DRIVER_SNAPSHOTTER_IMAGE="registry.k8s.io/sig-storage/csi-snapshotter:${CSI_SNAPSHOTTER_VERSION}" + kubectl get sts csi-hostpathplugin -n default -o yaml \ | yq "(.spec.template.spec.containers[] | select(.name == \"csi-snapshotter\") | .image) = \"${DRIVER_SNAPSHOTTER_IMAGE}\"" \ | kubectl apply -f - - # Enable the groupsnapshot feature gate for driver snapshotter - kubectl get sts csi-hostpathplugin -n default -o yaml \ + # Enable the groupsnapshot feature gate for driver snapshotter + info "Enabling CSIVolumeGroupSnapshot feature gate" + kubectl get sts csi-hostpathplugin -n default -o yaml \ | yq '(.spec.template.spec.containers[] | select(.name == "csi-snapshotter") | .args) += ["--feature-gates=CSIVolumeGroupSnapshot=true"]' \ | kubectl apply -f - - # Restart the StatefulSet - kubectl rollout restart sts csi-hostpathplugin -n default + # Restart the StatefulSet + info "Restarting StatefulSet to apply changes" + kubectl rollout restart sts csi-hostpathplugin -n default - # Wait for the rollout to complete - kubectl rollout status sts csi-hostpathplugin -n default - fi + # Wait for the rollout to complete + info "Waiting for rollout to complete..." + kubectl rollout status sts csi-hostpathplugin -n default + + info "VolumeGroupSnapshot configuration completed successfully" } # Installs all necessary snapshotter CRDs @@ -1125,6 +1168,7 @@ run_e2e () ( # the full Kubernetes E2E testsuite while only running a few tests. # shellcheck disable=SC2329 move_junit () { + # shellcheck disable=SC2317 if ls "${ARTIFACTS}"/junit_[0-9]*.xml 2>/dev/null >/dev/null; then mkdir -p "${ARTIFACTS}/junit/${name}" && mkdir -p "${ARTIFACTS}/junit/steps" && @@ -1336,7 +1380,7 @@ function version_gt() { # shellcheck disable=SC2120 install_yq_if_missing() { local version="${1:-v4.48.1}" - local yq_path="/usr/local/bin/yq" + local yq_path="${CSI_PROW_BIN}/yq" if ! command -v yq &>/dev/null; then echo "Installing yq ${version}..." if ! curl -fsSL -o "${yq_path}" "https://github.com/mikefarah/yq/releases/download/${version}/yq_linux_amd64"; then