From 6b95b6b20850fb7fafff24d8085d284607a7d334 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Sun, 16 Aug 2026 10:59:37 -0400 Subject: [PATCH 1/7] optional-operators-operator-sdk-non-ci-bundle-image: support mirroring bundle into the cluster's own registry Add OO_MIRROR_TO_CLUSTER_REGISTRY (opt-in, default false): when a consumer's external bundle registry can't reliably supply working credentials to operator-sdk's own containerd-based bundle-pull client, mirror OO_BUNDLE into the test cluster's own internal image registry first, mark the registry route insecure so in-cluster kubelet/CRI-O pulls succeed against its self-signed certificate, grant anonymous pull on the install namespace so operator-sdk needs no credentials to resolve the mirrored copy, and wait for the MachineConfigPool rollout that the insecure-registry trust change triggers before installing. This mutates cluster-wide config (image registry route, insecureRegistries, MCO rollout) beyond the install namespace, so it's gated behind the flag rather than applied unconditionally -- this ref is shared by other consumers (e.g. openshift-file-integrity-operator) who don't need it. Also add OO_PSA_ENFORCE_PRIVILEGED (opt-in, default false): force pod-security.kubernetes.io/enforce=privileged on an `openshift-*` install namespace, extending the treatment already unconditionally applied to non-`openshift-*` namespaces, since PSA level derived purely from granted SCCs can lag behind what operator-sdk's own registry pod needs under PodSecurity "restricted". Signed-off-by: Tiger Kaovilai --- ...erator-sdk-non-ci-bundle-image-commands.sh | 322 +++++++++++++++++- ...-operator-sdk-non-ci-bundle-image-ref.yaml | 36 ++ 2 files changed, 353 insertions(+), 5 deletions(-) diff --git a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh index 88cb5d7c467fe..b728d73d889fa 100755 --- a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh +++ b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh @@ -20,6 +20,8 @@ echo "[$(date --utc +%FT%T.%3NZ)] OO_BUNDLE: $OO_BUNDLE" echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_NAMESPACE: $OO_INSTALL_NAMESPACE" echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_MODE: $OO_INSTALL_MODE" echo "[$(date --utc +%FT%T.%3NZ)] OO_SECURITY_CONTEXT: $OO_SECURITY_CONTEXT" +echo "[$(date --utc +%FT%T.%3NZ)] OO_PSA_ENFORCE_PRIVILEGED: $OO_PSA_ENFORCE_PRIVILEGED" +echo "[$(date --utc +%FT%T.%3NZ)] OO_MIRROR_TO_CLUSTER_REGISTRY: $OO_MIRROR_TO_CLUSTER_REGISTRY" echo "[$(date --utc +%FT%T.%3NZ)] USE_HOSTED_KUBECONFIG: $USE_HOSTED_KUBECONFIG" if [[ "${USE_HOSTED_KUBECONFIG}" == "true" ]]; then @@ -53,7 +55,7 @@ EOF ) fi -if [[ "${OO_INSTALL_NAMESPACE}" =~ ^openshift- ]]; then +if [[ "${OO_INSTALL_NAMESPACE}" =~ ^openshift- ]] && [[ "${OO_PSA_ENFORCE_PRIVILEGED}" != "true" ]]; then echo "[$(date --utc +%FT%T.%3NZ)] Setting label security.openshift.io/scc.podSecurityLabelSync value to true on the namespace \"$OO_INSTALL_NAMESPACE\"" ./oc label --overwrite ns "${OO_INSTALL_NAMESPACE}" security.openshift.io/scc.podSecurityLabelSync=true else @@ -61,18 +63,328 @@ else ./oc label --overwrite ns "${OO_INSTALL_NAMESPACE}" security.openshift.io/scc.podSecurityLabelSync=false pod-security.kubernetes.io/enforce=privileged fi -INSTALL_MODE_ARG="" +OPTIONAL_ARGS=() if [[ -n ${OO_INSTALL_MODE} ]]; then - INSTALL_MODE_ARG=--install-mode="${INSTALL_MODE_ARG}" + OPTIONAL_ARGS+=("--install-mode=${OO_INSTALL_MODE}") fi + +OO_BUNDLE_EFFECTIVE="${OO_BUNDLE}" + +if [[ "${OO_MIRROR_TO_CLUSTER_REGISTRY}" == "true" ]]; then + # operator-sdk run bundle pulls OO_BUNDLE via opm's own containerd-based + # registry client, which cannot be given working credentials for some + # external registries (observed against a CI registry proxy) even when + # the same credential is independently valid via oc image mirror/oc + # image info. Side-step this: mirror OO_BUNDLE into the test cluster's + # own internal registry, grant anonymous pull there, and install from + # that copy instead -- no credentials needed for operator-sdk's own + # resolve step. + # + # Opt-in (default false): this ref is shared by non-KDM consumers (e.g. + # openshift-file-integrity-operator) who don't need their cluster's + # image-registry route exposed or an anonymous-pull grant added. Assumes + # an ephemeral, single-use test cluster; none of these mutations are + # torn down. + echo "[$(date --utc +%FT%T.%3NZ)] Extracting the test cluster's own global pull secret to read OO_BUNDLE" + # Cleanup net for every exit path (not just the happy path, which + # already removes MERGED_AUTH_FILE promptly once oc image mirror is + # done with it) -- these files hold the cluster's own global pull + # secret and the mirror-destination credential, and an early `exit 1` + # from any of the checks below would otherwise leave them in /tmp for + # the rest of the pod's lifetime. + trap 'rm -f /tmp/.dockerconfigjson /tmp/oo-merged-auth.json /tmp/oo-auth-splice.sed "${INSECURE_READ_ERR:-}"' EXIT + (umask 077; ./oc extract secret/pull-secret -n openshift-config --to=/tmp --confirm) + echo "[$(date --utc +%FT%T.%3NZ)] Diagnostic: registries in pull secret: $(grep -oE '"[a-zA-Z0-9.-]+"[[:space:]]*:[[:space:]]*\{[[:space:]]*"auth"' /tmp/.dockerconfigjson | sed -E 's/^"([^"]+)".*/\1/' | paste -sd ', ' -)" + + echo "[$(date --utc +%FT%T.%3NZ)] Enabling the test cluster's own image registry default route" + ./oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge + + DEST_HOST="" + for i in $(seq 1 30); do + DEST_HOST=$(./oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}' 2>/dev/null || true) + [[ -n "${DEST_HOST}" ]] && break + sleep 5 + done + if [[ -z "${DEST_HOST}" ]]; then + echo "[$(date --utc +%FT%T.%3NZ)] Timed out waiting for the image registry's default route" >&2 + exit 1 + fi + echo "[$(date --utc +%FT%T.%3NZ)] Test cluster's own registry route: ${DEST_HOST}" + + # The bundle-unpack Job OLM creates for the Subscription pulls the bundle + # image directly via kubelet/CRI-O, not operator-sdk's own HTTP client -- + # it has no --skip-tls-verify equivalent and does full TLS verification, + # which fails against the registry route's self-signed certificate + # ("x509: certificate signed by unknown authority"). Mark this route + # hostname as an insecure registry cluster-wide (same pattern as this + # repo's own quay-operator e2e test) so in-cluster pulls succeed. + # Read-modify-write, not replace: this ref also mounts + # openshift-custom-mirror-registry credentials for some consumers, who + # may already have their own insecureRegistries entries that a blind + # --type=merge replace on the array would discard. + # + # Known limitation: insecureRegistries disables TLS verification + # entirely for this host; image.config.openshift.io/cluster's + # spec.additionalTrustedCA would instead add the route's actual CA so + # pulls stay verified. Narrower and strictly better, but needs its own + # validation before swapping in. + echo "[$(date --utc +%FT%T.%3NZ)] Marking ${DEST_HOST} as an insecure registry cluster-wide so in-cluster pulls (e.g. OLM's bundle-unpack Job) don't fail TLS verification against the registry route's own certificate" + # Hard-fail (no `|| true`) rather than silently treating a failed read + # as an empty list: the read-modify-write below exists specifically to + # avoid discarding other consumers' entries, which a swallowed error + # here would defeat -- a genuinely empty result and a failed query + # must not be indistinguishable. stderr goes to a separate temp file, + # not merged via 2>&1: a stray warning on an otherwise-successful call + # would otherwise land inside EXISTING_INSECURE itself and get treated + # as a real hostname by the substring check and array build below. + INSECURE_READ_ERR=$(mktemp) + if ! EXISTING_INSECURE=$(./oc get image.config.openshift.io/cluster -o jsonpath='{.spec.registrySources.insecureRegistries[*]}' 2>"${INSECURE_READ_ERR}"); then + echo "[$(date --utc +%FT%T.%3NZ)] Failed to read the current insecureRegistries list; refusing to patch and risk dropping existing entries: $(cat "${INSECURE_READ_ERR}")" >&2 + rm -f "${INSECURE_READ_ERR}" + exit 1 + fi + rm -f "${INSECURE_READ_ERR}" + # Only patch (and later wait for the MCO rollout it triggers) when + # DEST_HOST is genuinely new. A no-op patch (host already present) + # produces no new rendered MachineConfig, so the deterministic MCO + # wait below would poll for a configuration.name change that never + # comes and hang until its timeout -- this only bites a cluster whose + # registrySources already lists the host (e.g. reused/pooled), not a + # fresh IPI cluster where the array starts empty. + if [[ " ${EXISTING_INSECURE} " != *" ${DEST_HOST} "* ]]; then + NEW_INSECURE="${EXISTING_INSECURE:+${EXISTING_INSECURE} }${DEST_HOST}" + # Intentional word splitting: one JSON array element per + # space-separated host in NEW_INSECURE. + # shellcheck disable=SC2086 + INSECURE_JSON=$(printf '"%s",' ${NEW_INSECURE}) + INSECURE_JSON="[${INSECURE_JSON%,}]" + # Captured immediately before the patch, not after the several + # steps (SA/token creation, mirroring) that follow -- capturing + # it later risked the MCO already starting its rollout in that + # gap, poisoning the "pre-change" baseline the wait below relies on. + MCP_BASELINE=$(./oc get mcp -o jsonpath='{range .items[*]}{.metadata.name}={.status.configuration.name}{"\n"}{end}') + if [[ -z "${MCP_BASELINE//[[:space:]]/}" ]]; then + # No MachineConfigPools means the wait loop below would iterate + # zero pools, leave ALL_DONE at its initial "true", and report + # success on the very first attempt without confirming anything. + echo "[$(date --utc +%FT%T.%3NZ)] No MachineConfigPools found; cannot confirm the insecure-registry trust rollout" >&2 + exit 1 + fi + ./oc patch image.config.openshift.io/cluster --type=merge -p "{\"spec\":{\"registrySources\":{\"insecureRegistries\":${INSECURE_JSON}}}}" + + # Deterministic MCO rollout wait: nothing else in this + # OO_MIRROR_TO_CLUSTER_REGISTRY block depends on the node-level + # trust rollout except operator-sdk run bundle itself (much further + # down), so running the wait immediately after the patch keeps the + # baseline-to-first-poll gap as small as possible. Capture each + # MCP's current rendered-config name before the patch (above), then + # poll until every pool has moved to a different config AND + # finished applying it to all its machines -- a plain + # `oc wait --for=condition=Updated` can return instantly if the MCO + # hasn't started rolling out yet (Updated can still read "True" + # from before our own patch). + echo "[$(date --utc +%FT%T.%3NZ)] Waiting for MachineConfigPools to finish rolling out the insecure-registry trust change" + for i in $(seq 1 90); do + ALL_DONE=true + DEGRADED_MCP="" + while IFS='=' read -r mcp_name old_config; do + [[ -z "${mcp_name}" ]] && continue + new_config=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.configuration.name}' 2>/dev/null || true) + updated_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.updatedMachineCount}' 2>/dev/null || true) + total_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.machineCount}' 2>/dev/null || true) + degraded_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.degradedMachineCount}' 2>/dev/null || true) + # Default empty (not just failed) lookups too -- a pool + # queried before its counts are populated returns "" with + # exit 0, which `|| echo` alone wouldn't catch, and "" == "" + # would have looked falsely "done". + updated_count="${updated_count:-0}" + total_count="${total_count:-1}" + degraded_count="${degraded_count:-0}" + if [[ "${degraded_count}" -gt 0 ]]; then + DEGRADED_MCP="${mcp_name}" + fi + if [[ "${new_config}" == "${old_config}" ]] || [[ "${updated_count}" != "${total_count}" ]]; then + ALL_DONE=false + fi + done <<< "${MCP_BASELINE}" + if [[ -n "${DEGRADED_MCP}" ]]; then + # Fail fast instead of burning the full wait budget: a + # degraded pool isn't going to un-degrade on its own within + # the remaining polls, so waiting out the rest of the 90 + # iterations only delays a failure that's already certain. + echo "[$(date --utc +%FT%T.%3NZ)] MachineConfigPool ${DEGRADED_MCP} reports degraded machines; aborting the rollout wait early" >&2 + ./oc get mcp -o wide || true + ./oc get nodes -o wide || true + exit 1 + fi + [[ "${ALL_DONE}" == "true" ]] && break + sleep 20 + done + if [[ "${ALL_DONE}" != "true" ]]; then + # Fail here, with MCO-specific diagnostics, rather than warn and + # proceed: without the trust rollout complete, the bundle-unpack + # Job's pull fails TLS verification against DEST_HOST's + # certificate anyway -- limping forward just defers to a later, + # less diagnostic failure inside operator-sdk run bundle. + echo "[$(date --utc +%FT%T.%3NZ)] MachineConfigPool rollout did not confirm completion within the wait budget" >&2 + ./oc get mcp -o wide || true + ./oc get nodes -o wide || true + exit 1 + fi + else + echo "[$(date --utc +%FT%T.%3NZ)] ${DEST_HOST} is already marked insecure -- skipping patch and MCO wait" + fi + + # oc registry login needs the ambient session to be bearer-token-based, + # but this test cluster's admin kubeconfig is client-cert based ("no + # token is currently in use for this session"). Create a dedicated + # ServiceAccount with explicit image-builder rights and a manually- + # requested token Secret instead -- works regardless of the ambient + # session's own credential type. Internal registry basic-auth accepts + # any username with a valid SA token as the password (standard + # OpenShift convention, e.g. `podman login -u unused -p $(oc whoami -t)`). + OO_ROBOT_SA="oo-bundle-pusher" + ./oc create serviceaccount "${OO_ROBOT_SA}" -n "${OO_INSTALL_NAMESPACE}" --dry-run=client -o yaml | ./oc apply -f - + ./oc policy add-role-to-user system:image-builder -z "${OO_ROBOT_SA}" -n "${OO_INSTALL_NAMESPACE}" + cat </dev/null | base64 -d || true) + [[ -n "${ROBOT_TOKEN}" ]] && break + sleep 2 + done + if [[ -z "${ROBOT_TOKEN}" ]]; then + echo "[$(date --utc +%FT%T.%3NZ)] Timed out waiting for the robot ServiceAccount token to populate" >&2 + exit 1 + fi + + # Built with printf/sed, not jq -- this ref has no guaranteed jq, and a + # runtime curl download of an unpinned-by-checksum binary from an + # archived repo isn't worth it for JSON this simple. + # /tmp/.dockerconfigjson is a compact, machine-generated Secret extract + # (oc extract, not hand-edited), so splicing a new entry right after + # the opening "auths":{ is reliable. + # + # `|` as the sed delimiter, not `/`: a structural guarantee, not an + # empirical one -- standard base64 (RFC 4648, DEST_AUTH_B64 below) uses + # only A-Za-z0-9+/=, and a Route's .spec.host (DEST_HOST) is a DNS name + # (RFC 1123: alphanumerics, hyphens, dots), so neither value spliced + # through this sed can ever contain `|`. + # + # Script file, not an inline -e expression: an inline sed command puts + # NEW_AUTH_ENTRY (which embeds the credential, base64-obscured but not + # secret) on this process's own command line, visible to any other + # process on the host via /proc//cmdline for as long as sed runs. + DEST_AUTH_B64=$(printf 'unused:%s' "${ROBOT_TOKEN}" | base64 | tr -d '\n') + unset ROBOT_TOKEN + MERGED_AUTH_FILE=/tmp/oo-merged-auth.json + SED_SCRIPT=/tmp/oo-auth-splice.sed + NEW_AUTH_ENTRY="\"${DEST_HOST}\":{\"auth\":\"${DEST_AUTH_B64}\"}," + unset DEST_AUTH_B64 + (umask 077; printf 's|"auths"[[:space:]]*:[[:space:]]*\{|"auths":{%s|\n' "${NEW_AUTH_ENTRY}" > "${SED_SCRIPT}") + (umask 077; sed -E -f "${SED_SCRIPT}" /tmp/.dockerconfigjson > "${MERGED_AUTH_FILE}") + rm -f "${SED_SCRIPT}" + if ! grep -q "\"${DEST_HOST}\":" "${MERGED_AUTH_FILE}"; then + echo "[$(date --utc +%FT%T.%3NZ)] Failed to splice mirror credentials into the auth file" >&2 + exit 1 + fi + + # Generic name (not OADP-specific): this ref is shared by non-KDM + # consumers too. Namespace-scoped and ephemeral, so no collision risk. + OO_BUNDLE_MIRROR="${DEST_HOST}/${OO_INSTALL_NAMESPACE}/oo-bundle-mirror:latest" + echo "[$(date --utc +%FT%T.%3NZ)] Mirroring ${OO_BUNDLE} to ${OO_BUNDLE_MIRROR}" + # --insecure applies to BOTH ends of this single mirror invocation -- oc + # image mirror has no per-registry insecure flag (see + # `oc image mirror --help`) -- so it also skips TLS verification for + # OO_BUNDLE's own source registry, not just DEST_HOST, which is the + # only side that actually needs it. Known limitation, not an + # oversight: splitting this into a verified pull (full TLS to the + # source) followed by an insecure push (to DEST_HOST only), e.g. via a + # local --dir stage, would close the gap, but needs its own validation + # before swapping in. + ./oc image mirror --registry-config="${MERGED_AUTH_FILE}" --filter-by-os=linux/amd64 --insecure=true "${OO_BUNDLE}=${OO_BUNDLE_MIRROR}" + rm -f "${MERGED_AUTH_FILE}" + OO_BUNDLE_EFFECTIVE="${OO_BUNDLE_MIRROR}" + + echo "[$(date --utc +%FT%T.%3NZ)] Granting anonymous pull on ${OO_INSTALL_NAMESPACE} so operator-sdk's own bundle-pull mechanism needs no credentials" + # system:unauthenticated is a GROUP, not a user -- anonymous requests + # authenticate as user system:anonymous, a member of that group. + # add-role-to-USER never matches real anonymous requests ("access + # denied" on an anonymous HEAD despite the binding existing: + # www-authenticate="Basic realm=openshift,error=\"access denied\""), + # so add-role-to-group is the correct subject kind. + ./oc policy add-role-to-group system:image-puller system:unauthenticated -n "${OO_INSTALL_NAMESPACE}" + + # Deliberately NOT revoked once operator-sdk run bundle returns: the + # CatalogSource OLM creates gets its own long-lived registry/grpc pod + # (discoverable via -l olm.catalogSource, see the diagnostics below), + # reconciled by OLM's catalog-operator for as long as the CatalogSource + # exists -- i.e. for the rest of this job, well past this step's own + # lifetime. If that pod is ever rescheduled (node pressure, eviction, + # OOM) during set-related-image or e2e, kubelet re-pulls its image + # from DEST_HOST, and revoking here first would turn that into an + # ImagePullBackOff far from this step, with no obvious link back to + # the cause. + # + # Leaving the grant standing for the rest of the job is acceptable + # only because both of these hold: this is an ephemeral, single-use + # test cluster torn down at job end, and this whole block only runs + # when OO_MIRROR_TO_CLUSTER_REGISTRY is explicitly opted into (only + # the 4 KDM configs, as of this writing). If either changes -- a + # pooled or longer-lived cluster, or this flag ever defaulting to + # true -- this reasoning needs revisiting. + SKIP_TLS_VERIFY_ARG="--skip-tls-verify" +fi + +if [[ -n "${SKIP_TLS_VERIFY_ARG:-}" ]]; then + OPTIONAL_ARGS+=("${SKIP_TLS_VERIFY_ARG}") +fi + +set +o errexit ( cd /tmp - operator-sdk run bundle "${OO_BUNDLE}" -n "${OO_INSTALL_NAMESPACE}" --verbose ${INSTALL_MODE_ARG} --timeout="${OO_INSTALL_TIMEOUT_MINUTES}m" --security-context-config="${OO_SECURITY_CONTEXT}" + # ${OPTIONAL_ARGS[@]+"${OPTIONAL_ARGS[@]}"}, not a bare + # "${OPTIONAL_ARGS[@]}": expanding a zero-element array under + # set -o nounset only stopped erroring in bash 4.4+. bash 3.2 (still + # the macOS system default, and plausible in other minimal base + # images) hard-errors ("unbound variable") on the bare form for an + # empty array; this guarded form works on both. + operator-sdk run bundle "${OO_BUNDLE_EFFECTIVE}" -n "${OO_INSTALL_NAMESPACE}" --verbose "${OPTIONAL_ARGS[@]+"${OPTIONAL_ARGS[@]}"}" --timeout="${OO_INSTALL_TIMEOUT_MINUTES}m" --security-context-config="${OO_SECURITY_CONTEXT}" ) +RUN_BUNDLE_STATUS=$? +set -o errexit + +if [[ "${RUN_BUNDLE_STATUS}" -ne 0 ]]; then + # A generic timeout here can mask a real OLM-side blocker rather than + # just slow resync/resolution -- dump the actual state so it's + # diagnosable instead of guessed at. + echo "[$(date --utc +%FT%T.%3NZ)] operator-sdk run bundle failed (exit ${RUN_BUNDLE_STATUS}) -- dumping OLM diagnostics" + ./oc get catalogsource -n "${OO_INSTALL_NAMESPACE}" -o yaml || true + ./oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o yaml || true + ./oc get installplan -n "${OO_INSTALL_NAMESPACE}" -o yaml || true + ./oc get pods -n "${OO_INSTALL_NAMESPACE}" -o wide || true + REG_POD=$(./oc get pods -n "${OO_INSTALL_NAMESPACE}" -l olm.catalogSource -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true) + if [[ -n "${REG_POD}" ]]; then + echo "[$(date --utc +%FT%T.%3NZ)] Logs for registry pod ${REG_POD}" + ./oc logs "${REG_POD}" -n "${OO_INSTALL_NAMESPACE}" --all-containers || true + fi + ./oc get events -n "${OO_INSTALL_NAMESPACE}" --sort-by=.lastTimestamp || true + ./oc get pods -n openshift-operator-lifecycle-manager -o wide || true + exit "${RUN_BUNDLE_STATUS}" +fi echo "check deployment" if [[ ! -z "${DEPLOYMENT}" ]]; then ./oc wait --timeout=10m --for condition=Available -n openshift-file-integrity deployment $DEPLOYMENT fi echo "[$(date --utc +%FT%T.%3NZ)] Script Completed Execution Successfully !" - diff --git a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml index 4505ae5234dff..996fd07ff66c0 100644 --- a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml +++ b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml @@ -39,6 +39,42 @@ ref: Specifies the security context to use for the catalog pod created by operator-sdk. Allowed: `restricted`, `legacy`. (default: `restricted`) default: "restricted" + - name: OO_PSA_ENFORCE_PRIVILEGED + documentation: |- + When true, force pod-security.kubernetes.io/enforce=privileged on + OO_INSTALL_NAMESPACE regardless of its name. By default, namespaces + prefixed `openshift-` only get security.openshift.io/scc.podSecurityLabelSync=true + (PSA level derived from whatever SCCs are granted, which can lag behind + what operator-sdk's own internal registry pod actually needs and reject + it under PodSecurity "restricted"). Namespaces not prefixed `openshift-` + already get the explicit-privileged treatment unconditionally; this + flag extends that same treatment to an `openshift-*` namespace. + default: "false" + - name: OO_MIRROR_TO_CLUSTER_REGISTRY + documentation: |- + When true, mirror OO_BUNDLE into the test cluster's own internal + image registry first (exposing its default route, marking it as an + insecure registry cluster-wide, and granting anonymous pull on + OO_INSTALL_NAMESPACE), and install from that internal copy instead + of OO_BUNDLE directly. Works around a real, still only partially + understood failure where operator-sdk's own containerd-based bundle + pull cannot be given working credentials for some external + registries (observed against a CI registry proxy) even when the + exact same credential is independently confirmed valid via + `oc image mirror`/`oc image info`. + + This is opt-in and defaults to false because it mutates + cluster-wide config (image registry route, insecureRegistries, + MachineConfigPool rollout) beyond OO_INSTALL_NAMESPACE -- only + enable it for a consumer that has actually hit the failure above. + Assumes an ephemeral, single-use test cluster; none of these + mutations are torn down. + + Sizing job/test timeouts: enabling this adds up to ~30 minutes + (the MachineConfigPool rollout wait) on top of this step's own + grace_period and OO_INSTALL_TIMEOUT_MINUTES, before OO_BUNDLE's + own install even starts. + default: "false" - name: OO_BUNDLE documentation: |- Specifies a non ci-bundle image From 43ee4b6bb79b2eae0c095577eb6e46f5f268ffae Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Sun, 16 Aug 2026 10:59:58 -0400 Subject: [PATCH 2/7] Add KDM (kubevirt-datamover-controller/plugin) e2e presubmits against oadp-operator Add e2e-test-aws presubmits for migtools/kubevirt-datamover-controller and migtools/kubevirt-datamover-plugin, on both the oadp-dev and oadp-1.6 branches (4 jobs total). Each job: - Provisions an AWS IPI cluster and installs oadp-operator from its promoted, non-CI bundle image via operator-sdk run bundle (with OO_MIRROR_TO_CLUSTER_REGISTRY and OO_PSA_ENFORCE_PRIVILEGED enabled, since openshift-adp needs both). - Overrides the datamover controller/plugin's image via Subscription.spec.config.env (RELATED_IMAGE_KUBEVIRT_DATAMOVER_ CONTROLLER/PLUGIN) so the operator runs the PR's own build rather than its released default, then waits for the Deployment to roll out the change. This is OLM's supported override mechanism: it wins over same-named CSV env vars and survives reconciliation, unlike patching the Deployment directly. --type merge replaces the whole spec.config.env array rather than merging by key; safe here because operator-sdk's freshly created Subscription has no pre-existing config.env entries to lose. - Runs `make TEST_VIRT=true test-e2e` against the resulting cluster, the same real KubeVirt VM backup/restore suite oadp-operator's own e2e already exercises. The oadp-1.6 jobs use the corresponding oadp-1.6 promoted bundle and image tags; oadp-dev tracks the operator's development bundle. Signed-off-by: Tiger Kaovilai --- ...ubevirt-datamover-controller-oadp-1.6.yaml | 95 +++++++++++++++++++ ...ubevirt-datamover-controller-oadp-dev.yaml | 95 +++++++++++++++++++ ...ls-kubevirt-datamover-plugin-oadp-1.6.yaml | 95 +++++++++++++++++++ ...ls-kubevirt-datamover-plugin-oadp-dev.yaml | 95 +++++++++++++++++++ ...mover-controller-oadp-1.6-postsubmits.yaml | 1 + ...amover-controller-oadp-1.6-presubmits.yaml | 86 +++++++++++++++++ ...mover-controller-oadp-dev-postsubmits.yaml | 1 + ...amover-controller-oadp-dev-presubmits.yaml | 86 +++++++++++++++++ ...datamover-plugin-oadp-1.6-postsubmits.yaml | 1 + ...-datamover-plugin-oadp-1.6-presubmits.yaml | 86 +++++++++++++++++ ...datamover-plugin-oadp-dev-postsubmits.yaml | 1 + ...-datamover-plugin-oadp-dev-presubmits.yaml | 86 +++++++++++++++++ 12 files changed, 728 insertions(+) diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml index 0841369a62368..6876fcd6f9433 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml @@ -1,3 +1,8 @@ +base_images: + test-oadp-operator: + name: oadp-operator-e2e-tests + namespace: konveyor + tag: oadp-1.6 build_root: image_stream_tag: name: builder @@ -13,6 +18,12 @@ promotion: to: - name: kubevirt-datamover-controller namespace: konveyor +releases: + latest: + candidate: + product: ocp + stream: nightly + version: "5.0" resources: '*': limits: @@ -20,6 +31,90 @@ resources: requests: cpu: 100m memory: 200Mi +tests: +- always_run: false + as: e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + steps: + cluster_profile: openshift-org-aws + env: + OO_BUNDLE: quay-proxy.ci.openshift.org/openshift/ci:konveyor_oadp-operator-bundle_oadp-1.6 + OO_INSTALL_MODE: OwnNamespace + OO_INSTALL_NAMESPACE: openshift-adp + OO_INSTALL_TIMEOUT_MINUTES: "25" + OO_MIRROR_TO_CLUSTER_REGISTRY: "true" + OO_PSA_ENFORCE_PRIVILEGED: "true" + post: + - chain: ipi-aws-post + pre: + - chain: ipi-aws-pre + - ref: optional-operators-operator-sdk-non-ci-bundle-image + test: + - as: set-related-image + cli: latest + commands: | + set -o errexit + set -o nounset + set -o pipefail + SUBS=$(oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o jsonpath='{.items[*].metadata.name}') + if [ -z "${SUBS}" ]; then + echo "No Subscription found in namespace ${OO_INSTALL_NAMESPACE}" >&2 + exit 1 + fi + if [ "$(echo "${SUBS}" | wc -w)" -gt 1 ]; then + echo "Multiple Subscriptions found in ${OO_INSTALL_NAMESPACE}: ${SUBS}" >&2 + exit 1 + fi + SUB="${SUBS}" + echo "Discovered Subscription: ${SUB}" + # Subscription.spec.config.env is OLM's supported override mechanism: + # it wins over same-named CSV env vars and survives reconciliation, + # unlike patching the Deployment directly (OLM reconciles that from + # the CSV and would revert it). Built with printf, not jq -- the cli + # image doesn't ship it, and the patch shape is fixed/simple enough not to need it. + # NOTE: --type merge below REPLACES the whole spec.config.env array + # rather than merging by key. Safe today only because operator-sdk's + # freshly created Subscription in this ephemeral, single-purpose + # namespace has no pre-existing config.env entries to lose; this + # would need a read-modify-write if that ever stops being true. + PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER","value":"%s"}]}}}' "${KDM_CONTROLLER_IMAGE}") + oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" + echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER=${KDM_CONTROLLER_IMAGE}" + for i in $(seq 1 60); do + CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER\")].value}" 2>/dev/null || true) + [ "${CURRENT}" = "${KDM_CONTROLLER_IMAGE}" ] && break + sleep 5 + done + if [ "${CURRENT}" != "${KDM_CONTROLLER_IMAGE}" ]; then + echo "Timed out waiting for Deployment spec to reflect the Subscription.spec.config.env override" >&2 + oc get subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/subscription-${SUB}.yaml" || true + oc get csv -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/csvs.yaml" || true + oc get deployment -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/deployments.yaml" || true + exit 1 + fi + oc rollout status deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" --timeout=180s + dependencies: + - env: KDM_CONTROLLER_IMAGE + name: kubevirt-datamover-controller-oadp-1.6 + env: + - name: OO_INSTALL_NAMESPACE + from: cli + resources: + requests: + cpu: 100m + memory: 100Mi + - as: e2e + cli: latest + commands: make TEST_VIRT=true test-e2e + credentials: + - mount_path: /var/run/oadp-credentials + name: oadp-credentials + namespace: test-credentials + from: test-oadp-operator + resources: + requests: + cpu: 1000m + memory: 512Mi zz_generated_metadata: branch: oadp-1.6 org: migtools diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml index 6cd5562fe088b..2f35f8b9f93ec 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml @@ -1,3 +1,8 @@ +base_images: + test-oadp-operator: + name: oadp-operator-e2e-tests + namespace: konveyor + tag: oadp-dev build_root: image_stream_tag: name: builder @@ -13,6 +18,12 @@ promotion: to: - namespace: konveyor tag: oadp-dev +releases: + latest: + candidate: + product: ocp + stream: nightly + version: "5.0" resources: '*': limits: @@ -20,6 +31,90 @@ resources: requests: cpu: 100m memory: 200Mi +tests: +- always_run: false + as: e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + steps: + cluster_profile: openshift-org-aws + env: + OO_BUNDLE: quay-proxy.ci.openshift.org/openshift/ci:konveyor_oadp-operator-bundle_oadp-dev + OO_INSTALL_MODE: OwnNamespace + OO_INSTALL_NAMESPACE: openshift-adp + OO_INSTALL_TIMEOUT_MINUTES: "25" + OO_MIRROR_TO_CLUSTER_REGISTRY: "true" + OO_PSA_ENFORCE_PRIVILEGED: "true" + post: + - chain: ipi-aws-post + pre: + - chain: ipi-aws-pre + - ref: optional-operators-operator-sdk-non-ci-bundle-image + test: + - as: set-related-image + cli: latest + commands: | + set -o errexit + set -o nounset + set -o pipefail + SUBS=$(oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o jsonpath='{.items[*].metadata.name}') + if [ -z "${SUBS}" ]; then + echo "No Subscription found in namespace ${OO_INSTALL_NAMESPACE}" >&2 + exit 1 + fi + if [ "$(echo "${SUBS}" | wc -w)" -gt 1 ]; then + echo "Multiple Subscriptions found in ${OO_INSTALL_NAMESPACE}: ${SUBS}" >&2 + exit 1 + fi + SUB="${SUBS}" + echo "Discovered Subscription: ${SUB}" + # Subscription.spec.config.env is OLM's supported override mechanism: + # it wins over same-named CSV env vars and survives reconciliation, + # unlike patching the Deployment directly (OLM reconciles that from + # the CSV and would revert it). Built with printf, not jq -- the cli + # image doesn't ship it, and the patch shape is fixed/simple enough not to need it. + # NOTE: --type merge below REPLACES the whole spec.config.env array + # rather than merging by key. Safe today only because operator-sdk's + # freshly created Subscription in this ephemeral, single-purpose + # namespace has no pre-existing config.env entries to lose; this + # would need a read-modify-write if that ever stops being true. + PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER","value":"%s"}]}}}' "${KDM_CONTROLLER_IMAGE}") + oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" + echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER=${KDM_CONTROLLER_IMAGE}" + for i in $(seq 1 60); do + CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER\")].value}" 2>/dev/null || true) + [ "${CURRENT}" = "${KDM_CONTROLLER_IMAGE}" ] && break + sleep 5 + done + if [ "${CURRENT}" != "${KDM_CONTROLLER_IMAGE}" ]; then + echo "Timed out waiting for Deployment spec to reflect the Subscription.spec.config.env override" >&2 + oc get subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/subscription-${SUB}.yaml" || true + oc get csv -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/csvs.yaml" || true + oc get deployment -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/deployments.yaml" || true + exit 1 + fi + oc rollout status deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" --timeout=180s + dependencies: + - env: KDM_CONTROLLER_IMAGE + name: kubevirt-datamover-controller + env: + - name: OO_INSTALL_NAMESPACE + from: cli + resources: + requests: + cpu: 100m + memory: 100Mi + - as: e2e + cli: latest + commands: make TEST_VIRT=true test-e2e + credentials: + - mount_path: /var/run/oadp-credentials + name: oadp-credentials + namespace: test-credentials + from: test-oadp-operator + resources: + requests: + cpu: 1000m + memory: 512Mi zz_generated_metadata: branch: oadp-dev org: migtools diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml index 74ebd47549d07..ff8f06083b3e7 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml @@ -1,3 +1,8 @@ +base_images: + test-oadp-operator: + name: oadp-operator-e2e-tests + namespace: konveyor + tag: oadp-1.6 build_root: image_stream_tag: name: builder @@ -13,6 +18,12 @@ promotion: to: - name: kubevirt-datamover-plugin namespace: konveyor +releases: + latest: + candidate: + product: ocp + stream: nightly + version: "5.0" resources: '*': limits: @@ -20,6 +31,90 @@ resources: requests: cpu: 100m memory: 200Mi +tests: +- always_run: false + as: e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + steps: + cluster_profile: openshift-org-aws + env: + OO_BUNDLE: quay-proxy.ci.openshift.org/openshift/ci:konveyor_oadp-operator-bundle_oadp-1.6 + OO_INSTALL_MODE: OwnNamespace + OO_INSTALL_NAMESPACE: openshift-adp + OO_INSTALL_TIMEOUT_MINUTES: "25" + OO_MIRROR_TO_CLUSTER_REGISTRY: "true" + OO_PSA_ENFORCE_PRIVILEGED: "true" + post: + - chain: ipi-aws-post + pre: + - chain: ipi-aws-pre + - ref: optional-operators-operator-sdk-non-ci-bundle-image + test: + - as: set-related-image + cli: latest + commands: | + set -o errexit + set -o nounset + set -o pipefail + SUBS=$(oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o jsonpath='{.items[*].metadata.name}') + if [ -z "${SUBS}" ]; then + echo "No Subscription found in namespace ${OO_INSTALL_NAMESPACE}" >&2 + exit 1 + fi + if [ "$(echo "${SUBS}" | wc -w)" -gt 1 ]; then + echo "Multiple Subscriptions found in ${OO_INSTALL_NAMESPACE}: ${SUBS}" >&2 + exit 1 + fi + SUB="${SUBS}" + echo "Discovered Subscription: ${SUB}" + # Subscription.spec.config.env is OLM's supported override mechanism: + # it wins over same-named CSV env vars and survives reconciliation, + # unlike patching the Deployment directly (OLM reconciles that from + # the CSV and would revert it). Built with printf, not jq -- the cli + # image doesn't ship it, and the patch shape is fixed/simple enough not to need it. + # NOTE: --type merge below REPLACES the whole spec.config.env array + # rather than merging by key. Safe today only because operator-sdk's + # freshly created Subscription in this ephemeral, single-purpose + # namespace has no pre-existing config.env entries to lose; this + # would need a read-modify-write if that ever stops being true. + PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN","value":"%s"}]}}}' "${KDM_PLUGIN_IMAGE}") + oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" + echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN=${KDM_PLUGIN_IMAGE}" + for i in $(seq 1 60); do + CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN\")].value}" 2>/dev/null || true) + [ "${CURRENT}" = "${KDM_PLUGIN_IMAGE}" ] && break + sleep 5 + done + if [ "${CURRENT}" != "${KDM_PLUGIN_IMAGE}" ]; then + echo "Timed out waiting for Deployment spec to reflect the Subscription.spec.config.env override" >&2 + oc get subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/subscription-${SUB}.yaml" || true + oc get csv -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/csvs.yaml" || true + oc get deployment -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/deployments.yaml" || true + exit 1 + fi + oc rollout status deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" --timeout=180s + dependencies: + - env: KDM_PLUGIN_IMAGE + name: kubevirt-datamover-plugin-oadp-1.6 + env: + - name: OO_INSTALL_NAMESPACE + from: cli + resources: + requests: + cpu: 100m + memory: 100Mi + - as: e2e + cli: latest + commands: make TEST_VIRT=true test-e2e + credentials: + - mount_path: /var/run/oadp-credentials + name: oadp-credentials + namespace: test-credentials + from: test-oadp-operator + resources: + requests: + cpu: 1000m + memory: 512Mi zz_generated_metadata: branch: oadp-1.6 org: migtools diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml index 3fb476682384d..5d9d07606c056 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml @@ -1,3 +1,8 @@ +base_images: + test-oadp-operator: + name: oadp-operator-e2e-tests + namespace: konveyor + tag: oadp-dev build_root: image_stream_tag: name: builder @@ -13,6 +18,12 @@ promotion: to: - namespace: konveyor tag: oadp-dev +releases: + latest: + candidate: + product: ocp + stream: nightly + version: "5.0" resources: '*': limits: @@ -20,6 +31,90 @@ resources: requests: cpu: 100m memory: 200Mi +tests: +- always_run: false + as: e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + steps: + cluster_profile: openshift-org-aws + env: + OO_BUNDLE: quay-proxy.ci.openshift.org/openshift/ci:konveyor_oadp-operator-bundle_oadp-dev + OO_INSTALL_MODE: OwnNamespace + OO_INSTALL_NAMESPACE: openshift-adp + OO_INSTALL_TIMEOUT_MINUTES: "25" + OO_MIRROR_TO_CLUSTER_REGISTRY: "true" + OO_PSA_ENFORCE_PRIVILEGED: "true" + post: + - chain: ipi-aws-post + pre: + - chain: ipi-aws-pre + - ref: optional-operators-operator-sdk-non-ci-bundle-image + test: + - as: set-related-image + cli: latest + commands: | + set -o errexit + set -o nounset + set -o pipefail + SUBS=$(oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o jsonpath='{.items[*].metadata.name}') + if [ -z "${SUBS}" ]; then + echo "No Subscription found in namespace ${OO_INSTALL_NAMESPACE}" >&2 + exit 1 + fi + if [ "$(echo "${SUBS}" | wc -w)" -gt 1 ]; then + echo "Multiple Subscriptions found in ${OO_INSTALL_NAMESPACE}: ${SUBS}" >&2 + exit 1 + fi + SUB="${SUBS}" + echo "Discovered Subscription: ${SUB}" + # Subscription.spec.config.env is OLM's supported override mechanism: + # it wins over same-named CSV env vars and survives reconciliation, + # unlike patching the Deployment directly (OLM reconciles that from + # the CSV and would revert it). Built with printf, not jq -- the cli + # image doesn't ship it, and the patch shape is fixed/simple enough not to need it. + # NOTE: --type merge below REPLACES the whole spec.config.env array + # rather than merging by key. Safe today only because operator-sdk's + # freshly created Subscription in this ephemeral, single-purpose + # namespace has no pre-existing config.env entries to lose; this + # would need a read-modify-write if that ever stops being true. + PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN","value":"%s"}]}}}' "${KDM_PLUGIN_IMAGE}") + oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" + echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN=${KDM_PLUGIN_IMAGE}" + for i in $(seq 1 60); do + CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN\")].value}" 2>/dev/null || true) + [ "${CURRENT}" = "${KDM_PLUGIN_IMAGE}" ] && break + sleep 5 + done + if [ "${CURRENT}" != "${KDM_PLUGIN_IMAGE}" ]; then + echo "Timed out waiting for Deployment spec to reflect the Subscription.spec.config.env override" >&2 + oc get subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/subscription-${SUB}.yaml" || true + oc get csv -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/csvs.yaml" || true + oc get deployment -n "${OO_INSTALL_NAMESPACE}" -o yaml > "${ARTIFACT_DIR}/deployments.yaml" || true + exit 1 + fi + oc rollout status deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" --timeout=180s + dependencies: + - env: KDM_PLUGIN_IMAGE + name: kubevirt-datamover-plugin + env: + - name: OO_INSTALL_NAMESPACE + from: cli + resources: + requests: + cpu: 100m + memory: 100Mi + - as: e2e + cli: latest + commands: make TEST_VIRT=true test-e2e + credentials: + - mount_path: /var/run/oadp-credentials + name: oadp-credentials + namespace: test-credentials + from: test-oadp-operator + resources: + requests: + cpu: 1000m + memory: 512Mi zz_generated_metadata: branch: oadp-dev org: migtools diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-postsubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-postsubmits.yaml index 6e6a435045bc0..15a55b786d20b 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-postsubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-postsubmits.yaml @@ -13,6 +13,7 @@ postsubmits: capability/arm64: arm64 ci-operator.openshift.io/is-promotion: "true" ci.openshift.io/generator: prowgen + job-release: "5.0" max_concurrency: 1 name: branch-ci-migtools-kubevirt-datamover-controller-oadp-1.6-images spec: diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-presubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-presubmits.yaml index e2a48e2137d1e..18bf370dfe348 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-presubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6-presubmits.yaml @@ -1,5 +1,90 @@ presubmits: migtools/kubevirt-datamover-controller: + - agent: kubernetes + always_run: false + branches: + - ^oadp-1\.6$ + - ^oadp-1\.6- + cluster: build11 + context: ci/prow/e2e-test-aws + decorate: true + decoration_config: + sparse_checkout_files: + - Dockerfile + labels: + ci-operator.openshift.io/cloud: aws + ci-operator.openshift.io/cloud-cluster-profile: openshift-org-aws + ci.openshift.io/generator: prowgen + job-release: "5.0" + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: pull-ci-migtools-kubevirt-datamover-controller-oadp-1.6-e2e-test-aws + rerun_command: /test e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + spec: + containers: + - args: + - --gcs-upload-secret=/secrets/gcs/service-account.json + - --image-import-pull-secret=/etc/pull-secret/.dockerconfigjson + - --lease-server-credentials-file=/etc/boskos/credentials + - --report-credentials-file=/etc/report/credentials + - --secret-dir=/secrets/ci-pull-credentials + - --target=e2e-test-aws + command: + - ci-operator + env: + - name: HTTP_SERVER_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: quay-proxy.ci.openshift.org/openshift/ci:ci_ci-operator_latest + imagePullPolicy: Always + name: "" + ports: + - containerPort: 8080 + name: http + resources: + requests: + cpu: 10m + volumeMounts: + - mountPath: /etc/boskos + name: boskos + readOnly: true + - mountPath: /secrets/ci-pull-credentials + name: ci-pull-credentials + readOnly: true + - mountPath: /secrets/gcs + name: gcs-credentials + readOnly: true + - mountPath: /secrets/manifest-tool + name: manifest-tool-local-pusher + readOnly: true + - mountPath: /etc/pull-secret + name: pull-secret + readOnly: true + - mountPath: /etc/report + name: result-aggregator + readOnly: true + serviceAccountName: ci-operator + volumes: + - name: boskos + secret: + items: + - key: credentials + path: credentials + secretName: boskos-credentials + - name: ci-pull-credentials + secret: + secretName: ci-pull-credentials + - name: manifest-tool-local-pusher + secret: + secretName: manifest-tool-local-pusher + - name: pull-secret + secret: + secretName: registry-pull-credentials + - name: result-aggregator + secret: + secretName: result-aggregator + trigger: (?m)^/test( | .* )e2e-test-aws,?($|\s.*) - agent: kubernetes always_run: true branches: @@ -14,6 +99,7 @@ presubmits: labels: capability/arm64: arm64 ci.openshift.io/generator: prowgen + job-release: "5.0" pj-rehearse.openshift.io/can-be-rehearsed: "true" name: pull-ci-migtools-kubevirt-datamover-controller-oadp-1.6-images rerun_command: /test images diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-postsubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-postsubmits.yaml index a01715b010015..5b5e4ce363dec 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-postsubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-postsubmits.yaml @@ -13,6 +13,7 @@ postsubmits: capability/arm64: arm64 ci-operator.openshift.io/is-promotion: "true" ci.openshift.io/generator: prowgen + job-release: "5.0" max_concurrency: 1 name: branch-ci-migtools-kubevirt-datamover-controller-oadp-dev-images spec: diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-presubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-presubmits.yaml index 24990c860ac38..490ced6d35ce7 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-presubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev-presubmits.yaml @@ -1,5 +1,90 @@ presubmits: migtools/kubevirt-datamover-controller: + - agent: kubernetes + always_run: false + branches: + - ^oadp-dev$ + - ^oadp-dev- + cluster: build11 + context: ci/prow/e2e-test-aws + decorate: true + decoration_config: + sparse_checkout_files: + - Dockerfile + labels: + ci-operator.openshift.io/cloud: aws + ci-operator.openshift.io/cloud-cluster-profile: openshift-org-aws + ci.openshift.io/generator: prowgen + job-release: "5.0" + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: pull-ci-migtools-kubevirt-datamover-controller-oadp-dev-e2e-test-aws + rerun_command: /test e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + spec: + containers: + - args: + - --gcs-upload-secret=/secrets/gcs/service-account.json + - --image-import-pull-secret=/etc/pull-secret/.dockerconfigjson + - --lease-server-credentials-file=/etc/boskos/credentials + - --report-credentials-file=/etc/report/credentials + - --secret-dir=/secrets/ci-pull-credentials + - --target=e2e-test-aws + command: + - ci-operator + env: + - name: HTTP_SERVER_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: quay-proxy.ci.openshift.org/openshift/ci:ci_ci-operator_latest + imagePullPolicy: Always + name: "" + ports: + - containerPort: 8080 + name: http + resources: + requests: + cpu: 10m + volumeMounts: + - mountPath: /etc/boskos + name: boskos + readOnly: true + - mountPath: /secrets/ci-pull-credentials + name: ci-pull-credentials + readOnly: true + - mountPath: /secrets/gcs + name: gcs-credentials + readOnly: true + - mountPath: /secrets/manifest-tool + name: manifest-tool-local-pusher + readOnly: true + - mountPath: /etc/pull-secret + name: pull-secret + readOnly: true + - mountPath: /etc/report + name: result-aggregator + readOnly: true + serviceAccountName: ci-operator + volumes: + - name: boskos + secret: + items: + - key: credentials + path: credentials + secretName: boskos-credentials + - name: ci-pull-credentials + secret: + secretName: ci-pull-credentials + - name: manifest-tool-local-pusher + secret: + secretName: manifest-tool-local-pusher + - name: pull-secret + secret: + secretName: registry-pull-credentials + - name: result-aggregator + secret: + secretName: result-aggregator + trigger: (?m)^/test( | .* )e2e-test-aws,?($|\s.*) - agent: kubernetes always_run: true branches: @@ -14,6 +99,7 @@ presubmits: labels: capability/arm64: arm64 ci.openshift.io/generator: prowgen + job-release: "5.0" pj-rehearse.openshift.io/can-be-rehearsed: "true" name: pull-ci-migtools-kubevirt-datamover-controller-oadp-dev-images rerun_command: /test images diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-postsubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-postsubmits.yaml index 1fde5040ef48e..4e545be58496a 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-postsubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-postsubmits.yaml @@ -13,6 +13,7 @@ postsubmits: capability/arm64: arm64 ci-operator.openshift.io/is-promotion: "true" ci.openshift.io/generator: prowgen + job-release: "5.0" max_concurrency: 1 name: branch-ci-migtools-kubevirt-datamover-plugin-oadp-1.6-images spec: diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-presubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-presubmits.yaml index e50593dde217e..7e938372c79f4 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-presubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6-presubmits.yaml @@ -1,5 +1,90 @@ presubmits: migtools/kubevirt-datamover-plugin: + - agent: kubernetes + always_run: false + branches: + - ^oadp-1\.6$ + - ^oadp-1\.6- + cluster: build06 + context: ci/prow/e2e-test-aws + decorate: true + decoration_config: + sparse_checkout_files: + - Dockerfile + labels: + ci-operator.openshift.io/cloud: aws + ci-operator.openshift.io/cloud-cluster-profile: openshift-org-aws + ci.openshift.io/generator: prowgen + job-release: "5.0" + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: pull-ci-migtools-kubevirt-datamover-plugin-oadp-1.6-e2e-test-aws + rerun_command: /test e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + spec: + containers: + - args: + - --gcs-upload-secret=/secrets/gcs/service-account.json + - --image-import-pull-secret=/etc/pull-secret/.dockerconfigjson + - --lease-server-credentials-file=/etc/boskos/credentials + - --report-credentials-file=/etc/report/credentials + - --secret-dir=/secrets/ci-pull-credentials + - --target=e2e-test-aws + command: + - ci-operator + env: + - name: HTTP_SERVER_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: quay-proxy.ci.openshift.org/openshift/ci:ci_ci-operator_latest + imagePullPolicy: Always + name: "" + ports: + - containerPort: 8080 + name: http + resources: + requests: + cpu: 10m + volumeMounts: + - mountPath: /etc/boskos + name: boskos + readOnly: true + - mountPath: /secrets/ci-pull-credentials + name: ci-pull-credentials + readOnly: true + - mountPath: /secrets/gcs + name: gcs-credentials + readOnly: true + - mountPath: /secrets/manifest-tool + name: manifest-tool-local-pusher + readOnly: true + - mountPath: /etc/pull-secret + name: pull-secret + readOnly: true + - mountPath: /etc/report + name: result-aggregator + readOnly: true + serviceAccountName: ci-operator + volumes: + - name: boskos + secret: + items: + - key: credentials + path: credentials + secretName: boskos-credentials + - name: ci-pull-credentials + secret: + secretName: ci-pull-credentials + - name: manifest-tool-local-pusher + secret: + secretName: manifest-tool-local-pusher + - name: pull-secret + secret: + secretName: registry-pull-credentials + - name: result-aggregator + secret: + secretName: result-aggregator + trigger: (?m)^/test( | .* )e2e-test-aws,?($|\s.*) - agent: kubernetes always_run: true branches: @@ -14,6 +99,7 @@ presubmits: labels: capability/arm64: arm64 ci.openshift.io/generator: prowgen + job-release: "5.0" pj-rehearse.openshift.io/can-be-rehearsed: "true" name: pull-ci-migtools-kubevirt-datamover-plugin-oadp-1.6-images rerun_command: /test images diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-postsubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-postsubmits.yaml index 80bcdb3fa8b48..3eac88bdb87c0 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-postsubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-postsubmits.yaml @@ -13,6 +13,7 @@ postsubmits: capability/arm64: arm64 ci-operator.openshift.io/is-promotion: "true" ci.openshift.io/generator: prowgen + job-release: "5.0" max_concurrency: 1 name: branch-ci-migtools-kubevirt-datamover-plugin-oadp-dev-images spec: diff --git a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-presubmits.yaml b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-presubmits.yaml index eb598fe505c7a..b211c7bd6b604 100644 --- a/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-presubmits.yaml +++ b/ci-operator/jobs/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev-presubmits.yaml @@ -1,5 +1,90 @@ presubmits: migtools/kubevirt-datamover-plugin: + - agent: kubernetes + always_run: false + branches: + - ^oadp-dev$ + - ^oadp-dev- + cluster: build06 + context: ci/prow/e2e-test-aws + decorate: true + decoration_config: + sparse_checkout_files: + - Dockerfile + labels: + ci-operator.openshift.io/cloud: aws + ci-operator.openshift.io/cloud-cluster-profile: openshift-org-aws + ci.openshift.io/generator: prowgen + job-release: "5.0" + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: pull-ci-migtools-kubevirt-datamover-plugin-oadp-dev-e2e-test-aws + rerun_command: /test e2e-test-aws + run_if_changed: (\.go|\.ya?ml|\.sh)$|^go\.(mod|sum)$|^Makefile$|^Dockerfile$|^\.dockerignore$ + spec: + containers: + - args: + - --gcs-upload-secret=/secrets/gcs/service-account.json + - --image-import-pull-secret=/etc/pull-secret/.dockerconfigjson + - --lease-server-credentials-file=/etc/boskos/credentials + - --report-credentials-file=/etc/report/credentials + - --secret-dir=/secrets/ci-pull-credentials + - --target=e2e-test-aws + command: + - ci-operator + env: + - name: HTTP_SERVER_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + image: quay-proxy.ci.openshift.org/openshift/ci:ci_ci-operator_latest + imagePullPolicy: Always + name: "" + ports: + - containerPort: 8080 + name: http + resources: + requests: + cpu: 10m + volumeMounts: + - mountPath: /etc/boskos + name: boskos + readOnly: true + - mountPath: /secrets/ci-pull-credentials + name: ci-pull-credentials + readOnly: true + - mountPath: /secrets/gcs + name: gcs-credentials + readOnly: true + - mountPath: /secrets/manifest-tool + name: manifest-tool-local-pusher + readOnly: true + - mountPath: /etc/pull-secret + name: pull-secret + readOnly: true + - mountPath: /etc/report + name: result-aggregator + readOnly: true + serviceAccountName: ci-operator + volumes: + - name: boskos + secret: + items: + - key: credentials + path: credentials + secretName: boskos-credentials + - name: ci-pull-credentials + secret: + secretName: ci-pull-credentials + - name: manifest-tool-local-pusher + secret: + secretName: manifest-tool-local-pusher + - name: pull-secret + secret: + secretName: registry-pull-credentials + - name: result-aggregator + secret: + secretName: result-aggregator + trigger: (?m)^/test( | .* )e2e-test-aws,?($|\s.*) - agent: kubernetes always_run: true branches: @@ -14,6 +99,7 @@ presubmits: labels: capability/arm64: arm64 ci.openshift.io/generator: prowgen + job-release: "5.0" pj-rehearse.openshift.io/can-be-rehearsed: "true" name: pull-ci-migtools-kubevirt-datamover-plugin-oadp-dev-images rerun_command: /test images From 3d021dd26d1dee7235ef94c122cba5f72506cc9d Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Mon, 17 Aug 2026 13:22:09 -0400 Subject: [PATCH 3/7] Fix shellcheck SC2034: rename unused retry-loop counters to _ Four "for i in \$(seq 1 N); do ... done" retry loops (DEST_HOST wait, MCO rollout wait, robot-SA token wait, and the deployment-rollout wait in set-related-image) never reference the loop variable -- it's purely a repeat count. Renamed to the conventional _ placeholder, which shellcheck doesn't flag as unused. No behavior change; verified with a real shellcheck run (both the shared step script and the extracted set-related-image script now report zero findings) and bash -n on both bash 3.2 and modern bash. Signed-off-by: Tiger Kaovilai --- .../migtools-kubevirt-datamover-controller-oadp-1.6.yaml | 2 +- .../migtools-kubevirt-datamover-controller-oadp-dev.yaml | 2 +- .../migtools-kubevirt-datamover-plugin-oadp-1.6.yaml | 2 +- .../migtools-kubevirt-datamover-plugin-oadp-dev.yaml | 2 +- ...l-operators-operator-sdk-non-ci-bundle-image-commands.sh | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml index 6876fcd6f9433..ec3e40ce71946 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml @@ -80,7 +80,7 @@ tests: PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER","value":"%s"}]}}}' "${KDM_CONTROLLER_IMAGE}") oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER=${KDM_CONTROLLER_IMAGE}" - for i in $(seq 1 60); do + for _ in $(seq 1 60); do CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER\")].value}" 2>/dev/null || true) [ "${CURRENT}" = "${KDM_CONTROLLER_IMAGE}" ] && break sleep 5 diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml index 2f35f8b9f93ec..05dc5fa28defc 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml @@ -80,7 +80,7 @@ tests: PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER","value":"%s"}]}}}' "${KDM_CONTROLLER_IMAGE}") oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER=${KDM_CONTROLLER_IMAGE}" - for i in $(seq 1 60); do + for _ in $(seq 1 60); do CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_CONTROLLER\")].value}" 2>/dev/null || true) [ "${CURRENT}" = "${KDM_CONTROLLER_IMAGE}" ] && break sleep 5 diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml index ff8f06083b3e7..da672472417f2 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml @@ -80,7 +80,7 @@ tests: PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN","value":"%s"}]}}}' "${KDM_PLUGIN_IMAGE}") oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN=${KDM_PLUGIN_IMAGE}" - for i in $(seq 1 60); do + for _ in $(seq 1 60); do CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN\")].value}" 2>/dev/null || true) [ "${CURRENT}" = "${KDM_PLUGIN_IMAGE}" ] && break sleep 5 diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml index 5d9d07606c056..911d3506b9721 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml @@ -80,7 +80,7 @@ tests: PATCH=$(printf '{"spec":{"config":{"env":[{"name":"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN","value":"%s"}]}}}' "${KDM_PLUGIN_IMAGE}") oc patch subscription "${SUB}" -n "${OO_INSTALL_NAMESPACE}" --type merge -p "${PATCH}" echo "Waiting for Deployment to observe RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN=${KDM_PLUGIN_IMAGE}" - for i in $(seq 1 60); do + for _ in $(seq 1 60); do CURRENT=$(oc get deployment/openshift-adp-controller-manager -n "${OO_INSTALL_NAMESPACE}" -o jsonpath="{.spec.template.spec.containers[?(@.name==\"manager\")].env[?(@.name==\"RELATED_IMAGE_KUBEVIRT_DATAMOVER_PLUGIN\")].value}" 2>/dev/null || true) [ "${CURRENT}" = "${KDM_PLUGIN_IMAGE}" ] && break sleep 5 diff --git a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh index b728d73d889fa..e92043ae9e3cc 100755 --- a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh +++ b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh @@ -100,7 +100,7 @@ if [[ "${OO_MIRROR_TO_CLUSTER_REGISTRY}" == "true" ]]; then ./oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge DEST_HOST="" - for i in $(seq 1 30); do + for _ in $(seq 1 30); do DEST_HOST=$(./oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}' 2>/dev/null || true) [[ -n "${DEST_HOST}" ]] && break sleep 5 @@ -184,7 +184,7 @@ if [[ "${OO_MIRROR_TO_CLUSTER_REGISTRY}" == "true" ]]; then # hasn't started rolling out yet (Updated can still read "True" # from before our own patch). echo "[$(date --utc +%FT%T.%3NZ)] Waiting for MachineConfigPools to finish rolling out the insecure-registry trust change" - for i in $(seq 1 90); do + for _ in $(seq 1 90); do ALL_DONE=true DEGRADED_MCP="" while IFS='=' read -r mcp_name old_config; do @@ -258,7 +258,7 @@ type: kubernetes.io/service-account-token EOF ROBOT_TOKEN="" - for i in $(seq 1 30); do + for _ in $(seq 1 30); do ROBOT_TOKEN=$(./oc get secret "${OO_ROBOT_SA}-token" -n "${OO_INSTALL_NAMESPACE}" -o jsonpath='{.data.token}' 2>/dev/null | base64 -d || true) [[ -n "${ROBOT_TOKEN}" ]] && break sleep 2 From c8398643bcfd62d0df7e39163e61c1f1f2e17992 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Mon, 17 Aug 2026 16:52:08 -0400 Subject: [PATCH 4/7] Switch KDM e2e to TEST_VIRT_KDM (kdm-labeled specs only) Replaces make TEST_VIRT=true (full virt suite) with TEST_VIRT_KDM=true (kdm-labeled subset) in all 4 KDM e2e-test-aws jobs. Requires openshift/oadp-operator#2350 to merge and promote first -- until then TEST_VIRT_KDM is an unset Make var and these jobs would run zero virt specs. Signed-off-by: Tiger Kaovilai --- .../migtools-kubevirt-datamover-controller-oadp-1.6.yaml | 2 +- .../migtools-kubevirt-datamover-controller-oadp-dev.yaml | 2 +- .../migtools-kubevirt-datamover-plugin-oadp-1.6.yaml | 2 +- .../migtools-kubevirt-datamover-plugin-oadp-dev.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml index ec3e40ce71946..ffcbd55d4c833 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml @@ -105,7 +105,7 @@ tests: memory: 100Mi - as: e2e cli: latest - commands: make TEST_VIRT=true test-e2e + commands: make TEST_VIRT_KDM=true test-e2e credentials: - mount_path: /var/run/oadp-credentials name: oadp-credentials diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml index 05dc5fa28defc..fa9f8340c0c0a 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml @@ -105,7 +105,7 @@ tests: memory: 100Mi - as: e2e cli: latest - commands: make TEST_VIRT=true test-e2e + commands: make TEST_VIRT_KDM=true test-e2e credentials: - mount_path: /var/run/oadp-credentials name: oadp-credentials diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml index da672472417f2..9225a7c07c23d 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml @@ -105,7 +105,7 @@ tests: memory: 100Mi - as: e2e cli: latest - commands: make TEST_VIRT=true test-e2e + commands: make TEST_VIRT_KDM=true test-e2e credentials: - mount_path: /var/run/oadp-credentials name: oadp-credentials diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml index 911d3506b9721..0a11c328998c0 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml @@ -105,7 +105,7 @@ tests: memory: 100Mi - as: e2e cli: latest - commands: make TEST_VIRT=true test-e2e + commands: make TEST_VIRT_KDM=true test-e2e credentials: - mount_path: /var/run/oadp-credentials name: oadp-credentials From 53bf1ad64256c2154a530c0339334c622a9120a9 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Mon, 17 Aug 2026 23:42:47 -0400 Subject: [PATCH 5/7] Fork operator-sdk bundle-install step into OADP-owned oadp/operator-sdk-bundle-image Reverts the KDM-specific OO_MIRROR_TO_CLUSTER_REGISTRY/OO_PSA_ENFORCE_PRIVILEGED additions to the shared optional-operators-operator-sdk-non-ci-bundle-image step back to its upstream/main state (zero diff, drops out of this PR's file list), and moves that logic into a new full copy under ci-operator/step-registry/oadp/, owned by the OADP team instead of the shared step's KubeVirt/HCO OWNERS. The 4 KDM configs now reference the new oadp-operator-sdk-bundle-image ref. Signed-off-by: Tiger Kaovilai --- ...ubevirt-datamover-controller-oadp-1.6.yaml | 2 +- ...ubevirt-datamover-controller-oadp-dev.yaml | 2 +- ...ls-kubevirt-datamover-plugin-oadp-1.6.yaml | 2 +- ...ls-kubevirt-datamover-plugin-oadp-dev.yaml | 2 +- .../oadp/operator-sdk-bundle-image/OWNERS | 15 + .../oadp/operator-sdk-bundle-image/README.md | 41 ++ ...oadp-operator-sdk-bundle-image-commands.sh | 391 ++++++++++++++++++ ...perator-sdk-bundle-image-ref.metadata.json | 21 + .../oadp-operator-sdk-bundle-image-ref.yaml | 89 ++++ ...erator-sdk-non-ci-bundle-image-commands.sh | 322 +-------------- ...-operator-sdk-non-ci-bundle-image-ref.yaml | 36 -- 11 files changed, 566 insertions(+), 357 deletions(-) create mode 100644 ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS create mode 100644 ci-operator/step-registry/oadp/operator-sdk-bundle-image/README.md create mode 100644 ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-commands.sh create mode 100644 ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json create mode 100644 ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.yaml diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml index ffcbd55d4c833..7d55d1c6e0437 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-1.6.yaml @@ -48,7 +48,7 @@ tests: - chain: ipi-aws-post pre: - chain: ipi-aws-pre - - ref: optional-operators-operator-sdk-non-ci-bundle-image + - ref: oadp-operator-sdk-bundle-image test: - as: set-related-image cli: latest diff --git a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml index fa9f8340c0c0a..ab169bbea119b 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-controller/migtools-kubevirt-datamover-controller-oadp-dev.yaml @@ -48,7 +48,7 @@ tests: - chain: ipi-aws-post pre: - chain: ipi-aws-pre - - ref: optional-operators-operator-sdk-non-ci-bundle-image + - ref: oadp-operator-sdk-bundle-image test: - as: set-related-image cli: latest diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml index 9225a7c07c23d..58056f1757757 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-1.6.yaml @@ -48,7 +48,7 @@ tests: - chain: ipi-aws-post pre: - chain: ipi-aws-pre - - ref: optional-operators-operator-sdk-non-ci-bundle-image + - ref: oadp-operator-sdk-bundle-image test: - as: set-related-image cli: latest diff --git a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml index 0a11c328998c0..e17847396e91a 100644 --- a/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml +++ b/ci-operator/config/migtools/kubevirt-datamover-plugin/migtools-kubevirt-datamover-plugin-oadp-dev.yaml @@ -48,7 +48,7 @@ tests: - chain: ipi-aws-post pre: - chain: ipi-aws-pre - - ref: optional-operators-operator-sdk-non-ci-bundle-image + - ref: oadp-operator-sdk-bundle-image test: - as: set-related-image cli: latest diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS new file mode 100644 index 0000000000000..0a1f910f099b9 --- /dev/null +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS @@ -0,0 +1,15 @@ +approvers: +- tareqalayan +- weshayutin +- akarol +- PrasadJoshi12 +- mpryc +options: {} +reviewers: +- tareqalayan +- kaovilai +- PrasadJoshi12 +- stillalearner # Sachin S +- weshayutin +- akarol +- mpryc diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/README.md b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/README.md new file mode 100644 index 0000000000000..5f1742cb19595 --- /dev/null +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/README.md @@ -0,0 +1,41 @@ +# oadp-operator-sdk-bundle-image-ref + +## Table of Contents + +- [Purpose](#purpose) +- [Process](#process) + - [Environment Variables](#environment-variables) +- [Provenance](#provenance) + +## Purpose + +Install an optional operator from a provided non ci-bundle image via `operator-sdk run bundle`, with two opt-in behaviors needed by the KDM (kubevirt-datamover-controller/-plugin) e2e jobs: mirroring the bundle into the test cluster's own internal registry, and forcing PSA `privileged` enforcement on the install namespace. + +## Process + +Creates (or reuses) `OO_INSTALL_NAMESPACE`, applies the PSA labeling appropriate for it, optionally mirrors `OO_BUNDLE` into the cluster's internal registry (see `OO_MIRROR_TO_CLUSTER_REGISTRY` below), then runs `operator-sdk run bundle` against the effective bundle pullspec. On failure, dumps CatalogSource/Subscription/InstallPlan/pod/registry-pod-log diagnostics before exiting. + +### Environment Variables + +- `USE_HOSTED_KUBECONFIG` + - When true, install the operator on the hosted cluster (default: `false`). +- `OO_INSTALL_NAMESPACE` + - The namespace into which the operator and catalog will be installed. +- `OO_INSTALL_MODE` + - The install-mode flag value of the `operator-sdk run bundle` command (default: `AllNamespaces`). +- `OO_INSTALL_TIMEOUT_MINUTES` + - How long (in minutes) to wait for the installation, before giving up (default: `10`). +- `OO_SECURITY_CONTEXT` + - Security context for the catalog pod created by operator-sdk: `restricted` or `legacy` (default: `restricted`). +- `OO_PSA_ENFORCE_PRIVILEGED` + - When true, force `pod-security.kubernetes.io/enforce=privileged` on `OO_INSTALL_NAMESPACE` regardless of its name (default: `false`). +- `OO_MIRROR_TO_CLUSTER_REGISTRY` + - When true, mirror `OO_BUNDLE` into the test cluster's own internal registry first and install from that copy instead. Works around operator-sdk's containerd-based bundle pull being unable to use credentials that work fine via `oc image mirror`/`oc image info` against some external registries. Mutates cluster-wide config (registry route, insecureRegistries, triggers an MCO rollout) and assumes an ephemeral, single-use test cluster (default: `false`). +- `OO_BUNDLE` + - Specifies a non ci-bundle image. +- `DEPLOYMENT` + - Deployment to be installed by the bundle. Optional; if empty, the check is skipped. + +## Provenance + +Forked from `optional-operators-operator-sdk-non-ci-bundle-image` (openshift/release#83049) into an OADP-owned copy so KDM-specific changes here don't require approval from that ref's OWNERS. Check that ref's git history periodically for upstream fixes worth porting into this fork manually. diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-commands.sh b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-commands.sh new file mode 100644 index 0000000000000..f6d3bd84616d6 --- /dev/null +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-commands.sh @@ -0,0 +1,391 @@ +#!/bin/bash + +# Forked from +# ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image +# (as of openshift/release#83049) into an OADP-owned copy so KDM-specific +# changes here don't need approval from that step's own OWNERS. Upstream +# fixes/improvements to the original ref may be worth porting back manually. + +set -o nounset +set -o errexit +set -o pipefail + +# For disconnected or otherwise unreachable environments, we want to +# have steps use an HTTP(S) proxy to reach the API server. This proxy +# configuration file should export HTTP_PROXY, HTTPS_PROXY, and NO_PROXY +# environment variables, as well as their lowercase equivalents (note +# that libcurl doesn't recognize the uppercase variables). +if test -f "${SHARED_DIR}/proxy-conf.sh" +then + # shellcheck disable=SC1090 + source "${SHARED_DIR}/proxy-conf.sh" +fi + +echo "[$(date --utc +%FT%T.%3NZ)] == Parameters:" +echo "[$(date --utc +%FT%T.%3NZ)] OO_BUNDLE: $OO_BUNDLE" +echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_NAMESPACE: $OO_INSTALL_NAMESPACE" +echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_MODE: $OO_INSTALL_MODE" +echo "[$(date --utc +%FT%T.%3NZ)] OO_SECURITY_CONTEXT: $OO_SECURITY_CONTEXT" +echo "[$(date --utc +%FT%T.%3NZ)] OO_PSA_ENFORCE_PRIVILEGED: $OO_PSA_ENFORCE_PRIVILEGED" +echo "[$(date --utc +%FT%T.%3NZ)] OO_MIRROR_TO_CLUSTER_REGISTRY: $OO_MIRROR_TO_CLUSTER_REGISTRY" +echo "[$(date --utc +%FT%T.%3NZ)] USE_HOSTED_KUBECONFIG: $USE_HOSTED_KUBECONFIG" + +if [[ "${USE_HOSTED_KUBECONFIG}" == "true" ]]; then + export KUBECONFIG="${SHARED_DIR}/nested_kubeconfig" +fi + +if [[ -f "${SHARED_DIR}/operator-install-namespace.txt" ]]; then + OO_INSTALL_NAMESPACE=$(cat "$SHARED_DIR"/operator-install-namespace.txt) +elif ! oc get namespace "$OO_INSTALL_NAMESPACE"; then + echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_NAMESPACE is '$OO_INSTALL_NAMESPACE' which does not exist: creating" + NS_NAMESTANZA="name: $OO_INSTALL_NAMESPACE" +else + echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_NAMESPACE is '$OO_INSTALL_NAMESPACE'" +fi + +echo "Checking/installing oc..." +if ! command -v oc &> /dev/null; then + cd /tmp && curl -L https://openshift-mirror-list.ci-systems.workers.dev/pub/openshift-v4/clients/oc/latest/linux/oc.tar.gz -o oc.tar.gz && tar xzvf oc.tar.gz +fi +echo "Installing oc done" +./oc version --client + +if [[ -n "${NS_NAMESTANZA:-}" ]]; then + OO_INSTALL_NAMESPACE=$( + ./oc create -f - -o jsonpath='{.metadata.name}' </dev/null || true) + [[ -n "${DEST_HOST}" ]] && break + sleep 5 + done + if [[ -z "${DEST_HOST}" ]]; then + echo "[$(date --utc +%FT%T.%3NZ)] Timed out waiting for the image registry's default route" >&2 + exit 1 + fi + echo "[$(date --utc +%FT%T.%3NZ)] Test cluster's own registry route: ${DEST_HOST}" + + # The bundle-unpack Job OLM creates for the Subscription pulls the bundle + # image directly via kubelet/CRI-O, not operator-sdk's own HTTP client -- + # it has no --skip-tls-verify equivalent and does full TLS verification, + # which fails against the registry route's self-signed certificate + # ("x509: certificate signed by unknown authority"). Mark this route + # hostname as an insecure registry cluster-wide (same pattern as this + # repo's own quay-operator e2e test) so in-cluster pulls succeed. + # Read-modify-write, not replace: other insecureRegistries entries may + # already be present and a blind --type=merge replace on the array + # would discard them. + # + # Known limitation: insecureRegistries disables TLS verification + # entirely for this host; image.config.openshift.io/cluster's + # spec.additionalTrustedCA would instead add the route's actual CA so + # pulls stay verified. Narrower and strictly better, but needs its own + # validation before swapping in. + echo "[$(date --utc +%FT%T.%3NZ)] Marking ${DEST_HOST} as an insecure registry cluster-wide so in-cluster pulls (e.g. OLM's bundle-unpack Job) don't fail TLS verification against the registry route's own certificate" + # Hard-fail (no `|| true`) rather than silently treating a failed read + # as an empty list: the read-modify-write below exists specifically to + # avoid discarding other consumers' entries, which a swallowed error + # here would defeat -- a genuinely empty result and a failed query + # must not be indistinguishable. stderr goes to a separate temp file, + # not merged via 2>&1: a stray warning on an otherwise-successful call + # would otherwise land inside EXISTING_INSECURE itself and get treated + # as a real hostname by the substring check and array build below. + INSECURE_READ_ERR=$(mktemp) + if ! EXISTING_INSECURE=$(./oc get image.config.openshift.io/cluster -o jsonpath='{.spec.registrySources.insecureRegistries[*]}' 2>"${INSECURE_READ_ERR}"); then + echo "[$(date --utc +%FT%T.%3NZ)] Failed to read the current insecureRegistries list; refusing to patch and risk dropping existing entries: $(cat "${INSECURE_READ_ERR}")" >&2 + rm -f "${INSECURE_READ_ERR}" + exit 1 + fi + rm -f "${INSECURE_READ_ERR}" + # Only patch (and later wait for the MCO rollout it triggers) when + # DEST_HOST is genuinely new. A no-op patch (host already present) + # produces no new rendered MachineConfig, so the deterministic MCO + # wait below would poll for a configuration.name change that never + # comes and hang until its timeout -- this only bites a cluster whose + # registrySources already lists the host (e.g. reused/pooled), not a + # fresh IPI cluster where the array starts empty. + if [[ " ${EXISTING_INSECURE} " != *" ${DEST_HOST} "* ]]; then + NEW_INSECURE="${EXISTING_INSECURE:+${EXISTING_INSECURE} }${DEST_HOST}" + # Intentional word splitting: one JSON array element per + # space-separated host in NEW_INSECURE. + # shellcheck disable=SC2086 + INSECURE_JSON=$(printf '"%s",' ${NEW_INSECURE}) + INSECURE_JSON="[${INSECURE_JSON%,}]" + # Captured immediately before the patch, not after the several + # steps (SA/token creation, mirroring) that follow -- capturing + # it later risked the MCO already starting its rollout in that + # gap, poisoning the "pre-change" baseline the wait below relies on. + MCP_BASELINE=$(./oc get mcp -o jsonpath='{range .items[*]}{.metadata.name}={.status.configuration.name}{"\n"}{end}') + if [[ -z "${MCP_BASELINE//[[:space:]]/}" ]]; then + # No MachineConfigPools means the wait loop below would iterate + # zero pools, leave ALL_DONE at its initial "true", and report + # success on the very first attempt without confirming anything. + echo "[$(date --utc +%FT%T.%3NZ)] No MachineConfigPools found; cannot confirm the insecure-registry trust rollout" >&2 + exit 1 + fi + ./oc patch image.config.openshift.io/cluster --type=merge -p "{\"spec\":{\"registrySources\":{\"insecureRegistries\":${INSECURE_JSON}}}}" + + # Deterministic MCO rollout wait: nothing else in this + # OO_MIRROR_TO_CLUSTER_REGISTRY block depends on the node-level + # trust rollout except operator-sdk run bundle itself (much further + # down), so running the wait immediately after the patch keeps the + # baseline-to-first-poll gap as small as possible. Capture each + # MCP's current rendered-config name before the patch (above), then + # poll until every pool has moved to a different config AND + # finished applying it to all its machines -- a plain + # `oc wait --for=condition=Updated` can return instantly if the MCO + # hasn't started rolling out yet (Updated can still read "True" + # from before our own patch). + echo "[$(date --utc +%FT%T.%3NZ)] Waiting for MachineConfigPools to finish rolling out the insecure-registry trust change" + for _ in $(seq 1 90); do + ALL_DONE=true + DEGRADED_MCP="" + while IFS='=' read -r mcp_name old_config; do + [[ -z "${mcp_name}" ]] && continue + new_config=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.configuration.name}' 2>/dev/null || true) + updated_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.updatedMachineCount}' 2>/dev/null || true) + total_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.machineCount}' 2>/dev/null || true) + degraded_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.degradedMachineCount}' 2>/dev/null || true) + # Default empty (not just failed) lookups too -- a pool + # queried before its counts are populated returns "" with + # exit 0, which `|| echo` alone wouldn't catch, and "" == "" + # would have looked falsely "done". + updated_count="${updated_count:-0}" + total_count="${total_count:-1}" + degraded_count="${degraded_count:-0}" + if [[ "${degraded_count}" -gt 0 ]]; then + DEGRADED_MCP="${mcp_name}" + fi + if [[ "${new_config}" == "${old_config}" ]] || [[ "${updated_count}" != "${total_count}" ]]; then + ALL_DONE=false + fi + done <<< "${MCP_BASELINE}" + if [[ -n "${DEGRADED_MCP}" ]]; then + # Fail fast instead of burning the full wait budget: a + # degraded pool isn't going to un-degrade on its own within + # the remaining polls, so waiting out the rest of the 90 + # iterations only delays a failure that's already certain. + echo "[$(date --utc +%FT%T.%3NZ)] MachineConfigPool ${DEGRADED_MCP} reports degraded machines; aborting the rollout wait early" >&2 + ./oc get mcp -o wide || true + ./oc get nodes -o wide || true + exit 1 + fi + [[ "${ALL_DONE}" == "true" ]] && break + sleep 20 + done + if [[ "${ALL_DONE}" != "true" ]]; then + # Fail here, with MCO-specific diagnostics, rather than warn and + # proceed: without the trust rollout complete, the bundle-unpack + # Job's pull fails TLS verification against DEST_HOST's + # certificate anyway -- limping forward just defers to a later, + # less diagnostic failure inside operator-sdk run bundle. + echo "[$(date --utc +%FT%T.%3NZ)] MachineConfigPool rollout did not confirm completion within the wait budget" >&2 + ./oc get mcp -o wide || true + ./oc get nodes -o wide || true + exit 1 + fi + else + echo "[$(date --utc +%FT%T.%3NZ)] ${DEST_HOST} is already marked insecure -- skipping patch and MCO wait" + fi + + # oc registry login needs the ambient session to be bearer-token-based, + # but this test cluster's admin kubeconfig is client-cert based ("no + # token is currently in use for this session"). Create a dedicated + # ServiceAccount with explicit image-builder rights and a manually- + # requested token Secret instead -- works regardless of the ambient + # session's own credential type. Internal registry basic-auth accepts + # any username with a valid SA token as the password (standard + # OpenShift convention, e.g. `podman login -u unused -p $(oc whoami -t)`). + OO_ROBOT_SA="oo-bundle-pusher" + ./oc create serviceaccount "${OO_ROBOT_SA}" -n "${OO_INSTALL_NAMESPACE}" --dry-run=client -o yaml | ./oc apply -f - + ./oc policy add-role-to-user system:image-builder -z "${OO_ROBOT_SA}" -n "${OO_INSTALL_NAMESPACE}" + cat </dev/null | base64 -d || true) + [[ -n "${ROBOT_TOKEN}" ]] && break + sleep 2 + done + if [[ -z "${ROBOT_TOKEN}" ]]; then + echo "[$(date --utc +%FT%T.%3NZ)] Timed out waiting for the robot ServiceAccount token to populate" >&2 + exit 1 + fi + + # Built with printf/sed, not jq -- this ref has no guaranteed jq, and a + # runtime curl download of an unpinned-by-checksum binary from an + # archived repo isn't worth it for JSON this simple. + # /tmp/.dockerconfigjson is a compact, machine-generated Secret extract + # (oc extract, not hand-edited), so splicing a new entry right after + # the opening "auths":{ is reliable. + # + # `|` as the sed delimiter, not `/`: a structural guarantee, not an + # empirical one -- standard base64 (RFC 4648, DEST_AUTH_B64 below) uses + # only A-Za-z0-9+/=, and a Route's .spec.host (DEST_HOST) is a DNS name + # (RFC 1123: alphanumerics, hyphens, dots), so neither value spliced + # through this sed can ever contain `|`. + # + # Script file, not an inline -e expression: an inline sed command puts + # NEW_AUTH_ENTRY (which embeds the credential, base64-obscured but not + # secret) on this process's own command line, visible to any other + # process on the host via /proc//cmdline for as long as sed runs. + DEST_AUTH_B64=$(printf 'unused:%s' "${ROBOT_TOKEN}" | base64 | tr -d '\n') + unset ROBOT_TOKEN + MERGED_AUTH_FILE=/tmp/oo-merged-auth.json + SED_SCRIPT=/tmp/oo-auth-splice.sed + NEW_AUTH_ENTRY="\"${DEST_HOST}\":{\"auth\":\"${DEST_AUTH_B64}\"}," + unset DEST_AUTH_B64 + (umask 077; printf 's|"auths"[[:space:]]*:[[:space:]]*\{|"auths":{%s|\n' "${NEW_AUTH_ENTRY}" > "${SED_SCRIPT}") + (umask 077; sed -E -f "${SED_SCRIPT}" /tmp/.dockerconfigjson > "${MERGED_AUTH_FILE}") + rm -f "${SED_SCRIPT}" + if ! grep -q "\"${DEST_HOST}\":" "${MERGED_AUTH_FILE}"; then + echo "[$(date --utc +%FT%T.%3NZ)] Failed to splice mirror credentials into the auth file" >&2 + exit 1 + fi + + OO_BUNDLE_MIRROR="${DEST_HOST}/${OO_INSTALL_NAMESPACE}/oo-bundle-mirror:latest" + echo "[$(date --utc +%FT%T.%3NZ)] Mirroring ${OO_BUNDLE} to ${OO_BUNDLE_MIRROR}" + # --insecure applies to BOTH ends of this single mirror invocation -- oc + # image mirror has no per-registry insecure flag (see + # `oc image mirror --help`) -- so it also skips TLS verification for + # OO_BUNDLE's own source registry, not just DEST_HOST, which is the + # only side that actually needs it. Known limitation, not an + # oversight: splitting this into a verified pull (full TLS to the + # source) followed by an insecure push (to DEST_HOST only), e.g. via a + # local --dir stage, would close the gap, but needs its own validation + # before swapping in. + ./oc image mirror --registry-config="${MERGED_AUTH_FILE}" --filter-by-os=linux/amd64 --insecure=true "${OO_BUNDLE}=${OO_BUNDLE_MIRROR}" + rm -f "${MERGED_AUTH_FILE}" + OO_BUNDLE_EFFECTIVE="${OO_BUNDLE_MIRROR}" + + echo "[$(date --utc +%FT%T.%3NZ)] Granting anonymous pull on ${OO_INSTALL_NAMESPACE} so operator-sdk's own bundle-pull mechanism needs no credentials" + # system:unauthenticated is a GROUP, not a user -- anonymous requests + # authenticate as user system:anonymous, a member of that group. + # add-role-to-USER never matches real anonymous requests ("access + # denied" on an anonymous HEAD despite the binding existing: + # www-authenticate="Basic realm=openshift,error=\"access denied\""), + # so add-role-to-group is the correct subject kind. + ./oc policy add-role-to-group system:image-puller system:unauthenticated -n "${OO_INSTALL_NAMESPACE}" + + # Deliberately NOT revoked once operator-sdk run bundle returns: the + # CatalogSource OLM creates gets its own long-lived registry/grpc pod + # (discoverable via -l olm.catalogSource, see the diagnostics below), + # reconciled by OLM's catalog-operator for as long as the CatalogSource + # exists -- i.e. for the rest of this job, well past this step's own + # lifetime. If that pod is ever rescheduled (node pressure, eviction, + # OOM) during set-related-image or e2e, kubelet re-pulls its image + # from DEST_HOST, and revoking here first would turn that into an + # ImagePullBackOff far from this step, with no obvious link back to + # the cause. + # + # Leaving the grant standing for the rest of the job is acceptable + # only because both of these hold: this is an ephemeral, single-use + # test cluster torn down at job end, and this whole block only runs + # when OO_MIRROR_TO_CLUSTER_REGISTRY is explicitly opted into (only + # the 4 KDM configs, as of this writing). If either changes -- a + # pooled or longer-lived cluster, or this flag ever defaulting to + # true -- this reasoning needs revisiting. + SKIP_TLS_VERIFY_ARG="--skip-tls-verify" +fi + +if [[ -n "${SKIP_TLS_VERIFY_ARG:-}" ]]; then + OPTIONAL_ARGS+=("${SKIP_TLS_VERIFY_ARG}") +fi + +set +o errexit +( + cd /tmp + # ${OPTIONAL_ARGS[@]+"${OPTIONAL_ARGS[@]}"}, not a bare + # "${OPTIONAL_ARGS[@]}": expanding a zero-element array under + # set -o nounset only stopped erroring in bash 4.4+. bash 3.2 (still + # the macOS system default, and plausible in other minimal base + # images) hard-errors ("unbound variable") on the bare form for an + # empty array; this guarded form works on both. + operator-sdk run bundle "${OO_BUNDLE_EFFECTIVE}" -n "${OO_INSTALL_NAMESPACE}" --verbose "${OPTIONAL_ARGS[@]+"${OPTIONAL_ARGS[@]}"}" --timeout="${OO_INSTALL_TIMEOUT_MINUTES}m" --security-context-config="${OO_SECURITY_CONTEXT}" +) +RUN_BUNDLE_STATUS=$? +set -o errexit + +if [[ "${RUN_BUNDLE_STATUS}" -ne 0 ]]; then + # A generic timeout here can mask a real OLM-side blocker rather than + # just slow resync/resolution -- dump the actual state so it's + # diagnosable instead of guessed at. + echo "[$(date --utc +%FT%T.%3NZ)] operator-sdk run bundle failed (exit ${RUN_BUNDLE_STATUS}) -- dumping OLM diagnostics" + ./oc get catalogsource -n "${OO_INSTALL_NAMESPACE}" -o yaml || true + ./oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o yaml || true + ./oc get installplan -n "${OO_INSTALL_NAMESPACE}" -o yaml || true + ./oc get pods -n "${OO_INSTALL_NAMESPACE}" -o wide || true + REG_POD=$(./oc get pods -n "${OO_INSTALL_NAMESPACE}" -l olm.catalogSource -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true) + if [[ -n "${REG_POD}" ]]; then + echo "[$(date --utc +%FT%T.%3NZ)] Logs for registry pod ${REG_POD}" + ./oc logs "${REG_POD}" -n "${OO_INSTALL_NAMESPACE}" --all-containers || true + fi + ./oc get events -n "${OO_INSTALL_NAMESPACE}" --sort-by=.lastTimestamp || true + ./oc get pods -n openshift-operator-lifecycle-manager -o wide || true + exit "${RUN_BUNDLE_STATUS}" +fi + +echo "check deployment" +if [[ ! -z "${DEPLOYMENT}" ]]; then + ./oc wait --timeout=10m --for condition=Available -n openshift-file-integrity deployment $DEPLOYMENT +fi +echo "[$(date --utc +%FT%T.%3NZ)] Script Completed Execution Successfully !" diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json new file mode 100644 index 0000000000000..e0bc1aacc2bd8 --- /dev/null +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json @@ -0,0 +1,21 @@ +{ + "path": "oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.yaml", + "owners": { + "approvers": [ + "tareqalayan", + "weshayutin", + "akarol", + "PrasadJoshi12", + "mpryc" + ], + "reviewers": [ + "tareqalayan", + "kaovilai", + "PrasadJoshi12", + "stillalearner", + "weshayutin", + "akarol", + "mpryc" + ] + } +} \ No newline at end of file diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.yaml b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.yaml new file mode 100644 index 0000000000000..8d686fe91a53c --- /dev/null +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.yaml @@ -0,0 +1,89 @@ +ref: + as: oadp-operator-sdk-bundle-image + from_image: + name: "4.18" + namespace: origin + tag: operator-sdk + commands: oadp-operator-sdk-bundle-image-commands.sh + grace_period: 10m + resources: + requests: + cpu: 300m + memory: 300Mi + env: + - name: USE_HOSTED_KUBECONFIG + documentation: When true, install the operator on the hosted cluster + default: "false" + - name: OO_INSTALL_NAMESPACE + documentation: The namespace into which the operator and catalog will be installed. + - name: OO_INSTALL_MODE + documentation: |- + The install-mode flag value of the operator-sdk run bundle command. The format is the install-mode name + list of + comma separated list of namespaces (for some mode type). + values can be: + + * `OwnNamespace` - indicates that the operator can be a member of an `OperatorGroup` that selects its own namespace. Must not contain list of namespaces. + * `SingleNamespace=` - indicates that the operator can be a member of an `OperatorGroup` that selects one namespace. Must contain one and only one namespace. the namespace must be different than the `OO_INSTALL_NAMESPACE`. + * `MultiNamespace=[,[,...]]` - indicates that the operator can be a member of an `OperatorGroup` that selects more than one namespace. The namespace list must not be empty. + * `AllNamespaces` - (default) indicates that the operator can be a member of an `OperatorGroup` that selects all namespaces (target namespace set is the empty string ""). Must not contain list of namespaces. + default: "AllNamespaces" + - name: OO_INSTALL_TIMEOUT_MINUTES + documentation: how long (in minutes) to wait for the installation, before giving up. + default: "10" + - name: OO_SECURITY_CONTEXT + documentation: |- + Specifies the security context to use for the catalog pod created by operator-sdk. + Allowed: `restricted`, `legacy`. (default: `restricted`) + default: "restricted" + - name: OO_PSA_ENFORCE_PRIVILEGED + documentation: |- + When true, force pod-security.kubernetes.io/enforce=privileged on + OO_INSTALL_NAMESPACE regardless of its name. By default, namespaces + prefixed `openshift-` only get security.openshift.io/scc.podSecurityLabelSync=true + (PSA level derived from whatever SCCs are granted, which can lag behind + what operator-sdk's own internal registry pod actually needs and reject + it under PodSecurity "restricted"). Namespaces not prefixed `openshift-` + already get the explicit-privileged treatment unconditionally; this + flag extends that same treatment to an `openshift-*` namespace. + default: "false" + - name: OO_MIRROR_TO_CLUSTER_REGISTRY + documentation: |- + When true, mirror OO_BUNDLE into the test cluster's own internal + image registry first (exposing its default route, marking it as an + insecure registry cluster-wide, and granting anonymous pull on + OO_INSTALL_NAMESPACE), and install from that internal copy instead + of OO_BUNDLE directly. Works around a real, still only partially + understood failure where operator-sdk's own containerd-based bundle + pull cannot be given working credentials for some external + registries (observed against a CI registry proxy) even when the + exact same credential is independently confirmed valid via + `oc image mirror`/`oc image info`. + + This is opt-in and defaults to false because it mutates + cluster-wide config (image registry route, insecureRegistries, + MachineConfigPool rollout) beyond OO_INSTALL_NAMESPACE -- only + enable it for a consumer that has actually hit the failure above. + Assumes an ephemeral, single-use test cluster; none of these + mutations are torn down. + + Sizing job/test timeouts: enabling this adds up to ~30 minutes + (the MachineConfigPool rollout wait) on top of this step's own + grace_period and OO_INSTALL_TIMEOUT_MINUTES, before OO_BUNDLE's + own install even starts. + default: "false" + - name: OO_BUNDLE + documentation: |- + Specifies a non ci-bundle image + - name: DEPLOYMENT + documentation: |- + Deployment to be installed by the bundle. + Optional. If it is empty, the check will be skipped. + default: "" + documentation: |- + OADP-owned fork of optional-operators-operator-sdk-non-ci-bundle-image + (see that ref's git history for upstream fixes worth porting back + manually), kept separate so KDM-specific changes here don't require + approval from that ref's own OWNERS. Installs an optional operator + from a provided non ci-bundle image, using operator-sdk, with two + opt-in KDM-specific behaviors (OO_MIRROR_TO_CLUSTER_REGISTRY, + OO_PSA_ENFORCE_PRIVILEGED). diff --git a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh index e92043ae9e3cc..88cb5d7c467fe 100755 --- a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh +++ b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-commands.sh @@ -20,8 +20,6 @@ echo "[$(date --utc +%FT%T.%3NZ)] OO_BUNDLE: $OO_BUNDLE" echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_NAMESPACE: $OO_INSTALL_NAMESPACE" echo "[$(date --utc +%FT%T.%3NZ)] OO_INSTALL_MODE: $OO_INSTALL_MODE" echo "[$(date --utc +%FT%T.%3NZ)] OO_SECURITY_CONTEXT: $OO_SECURITY_CONTEXT" -echo "[$(date --utc +%FT%T.%3NZ)] OO_PSA_ENFORCE_PRIVILEGED: $OO_PSA_ENFORCE_PRIVILEGED" -echo "[$(date --utc +%FT%T.%3NZ)] OO_MIRROR_TO_CLUSTER_REGISTRY: $OO_MIRROR_TO_CLUSTER_REGISTRY" echo "[$(date --utc +%FT%T.%3NZ)] USE_HOSTED_KUBECONFIG: $USE_HOSTED_KUBECONFIG" if [[ "${USE_HOSTED_KUBECONFIG}" == "true" ]]; then @@ -55,7 +53,7 @@ EOF ) fi -if [[ "${OO_INSTALL_NAMESPACE}" =~ ^openshift- ]] && [[ "${OO_PSA_ENFORCE_PRIVILEGED}" != "true" ]]; then +if [[ "${OO_INSTALL_NAMESPACE}" =~ ^openshift- ]]; then echo "[$(date --utc +%FT%T.%3NZ)] Setting label security.openshift.io/scc.podSecurityLabelSync value to true on the namespace \"$OO_INSTALL_NAMESPACE\"" ./oc label --overwrite ns "${OO_INSTALL_NAMESPACE}" security.openshift.io/scc.podSecurityLabelSync=true else @@ -63,328 +61,18 @@ else ./oc label --overwrite ns "${OO_INSTALL_NAMESPACE}" security.openshift.io/scc.podSecurityLabelSync=false pod-security.kubernetes.io/enforce=privileged fi -OPTIONAL_ARGS=() +INSTALL_MODE_ARG="" if [[ -n ${OO_INSTALL_MODE} ]]; then - OPTIONAL_ARGS+=("--install-mode=${OO_INSTALL_MODE}") + INSTALL_MODE_ARG=--install-mode="${INSTALL_MODE_ARG}" fi - -OO_BUNDLE_EFFECTIVE="${OO_BUNDLE}" - -if [[ "${OO_MIRROR_TO_CLUSTER_REGISTRY}" == "true" ]]; then - # operator-sdk run bundle pulls OO_BUNDLE via opm's own containerd-based - # registry client, which cannot be given working credentials for some - # external registries (observed against a CI registry proxy) even when - # the same credential is independently valid via oc image mirror/oc - # image info. Side-step this: mirror OO_BUNDLE into the test cluster's - # own internal registry, grant anonymous pull there, and install from - # that copy instead -- no credentials needed for operator-sdk's own - # resolve step. - # - # Opt-in (default false): this ref is shared by non-KDM consumers (e.g. - # openshift-file-integrity-operator) who don't need their cluster's - # image-registry route exposed or an anonymous-pull grant added. Assumes - # an ephemeral, single-use test cluster; none of these mutations are - # torn down. - echo "[$(date --utc +%FT%T.%3NZ)] Extracting the test cluster's own global pull secret to read OO_BUNDLE" - # Cleanup net for every exit path (not just the happy path, which - # already removes MERGED_AUTH_FILE promptly once oc image mirror is - # done with it) -- these files hold the cluster's own global pull - # secret and the mirror-destination credential, and an early `exit 1` - # from any of the checks below would otherwise leave them in /tmp for - # the rest of the pod's lifetime. - trap 'rm -f /tmp/.dockerconfigjson /tmp/oo-merged-auth.json /tmp/oo-auth-splice.sed "${INSECURE_READ_ERR:-}"' EXIT - (umask 077; ./oc extract secret/pull-secret -n openshift-config --to=/tmp --confirm) - echo "[$(date --utc +%FT%T.%3NZ)] Diagnostic: registries in pull secret: $(grep -oE '"[a-zA-Z0-9.-]+"[[:space:]]*:[[:space:]]*\{[[:space:]]*"auth"' /tmp/.dockerconfigjson | sed -E 's/^"([^"]+)".*/\1/' | paste -sd ', ' -)" - - echo "[$(date --utc +%FT%T.%3NZ)] Enabling the test cluster's own image registry default route" - ./oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge - - DEST_HOST="" - for _ in $(seq 1 30); do - DEST_HOST=$(./oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}' 2>/dev/null || true) - [[ -n "${DEST_HOST}" ]] && break - sleep 5 - done - if [[ -z "${DEST_HOST}" ]]; then - echo "[$(date --utc +%FT%T.%3NZ)] Timed out waiting for the image registry's default route" >&2 - exit 1 - fi - echo "[$(date --utc +%FT%T.%3NZ)] Test cluster's own registry route: ${DEST_HOST}" - - # The bundle-unpack Job OLM creates for the Subscription pulls the bundle - # image directly via kubelet/CRI-O, not operator-sdk's own HTTP client -- - # it has no --skip-tls-verify equivalent and does full TLS verification, - # which fails against the registry route's self-signed certificate - # ("x509: certificate signed by unknown authority"). Mark this route - # hostname as an insecure registry cluster-wide (same pattern as this - # repo's own quay-operator e2e test) so in-cluster pulls succeed. - # Read-modify-write, not replace: this ref also mounts - # openshift-custom-mirror-registry credentials for some consumers, who - # may already have their own insecureRegistries entries that a blind - # --type=merge replace on the array would discard. - # - # Known limitation: insecureRegistries disables TLS verification - # entirely for this host; image.config.openshift.io/cluster's - # spec.additionalTrustedCA would instead add the route's actual CA so - # pulls stay verified. Narrower and strictly better, but needs its own - # validation before swapping in. - echo "[$(date --utc +%FT%T.%3NZ)] Marking ${DEST_HOST} as an insecure registry cluster-wide so in-cluster pulls (e.g. OLM's bundle-unpack Job) don't fail TLS verification against the registry route's own certificate" - # Hard-fail (no `|| true`) rather than silently treating a failed read - # as an empty list: the read-modify-write below exists specifically to - # avoid discarding other consumers' entries, which a swallowed error - # here would defeat -- a genuinely empty result and a failed query - # must not be indistinguishable. stderr goes to a separate temp file, - # not merged via 2>&1: a stray warning on an otherwise-successful call - # would otherwise land inside EXISTING_INSECURE itself and get treated - # as a real hostname by the substring check and array build below. - INSECURE_READ_ERR=$(mktemp) - if ! EXISTING_INSECURE=$(./oc get image.config.openshift.io/cluster -o jsonpath='{.spec.registrySources.insecureRegistries[*]}' 2>"${INSECURE_READ_ERR}"); then - echo "[$(date --utc +%FT%T.%3NZ)] Failed to read the current insecureRegistries list; refusing to patch and risk dropping existing entries: $(cat "${INSECURE_READ_ERR}")" >&2 - rm -f "${INSECURE_READ_ERR}" - exit 1 - fi - rm -f "${INSECURE_READ_ERR}" - # Only patch (and later wait for the MCO rollout it triggers) when - # DEST_HOST is genuinely new. A no-op patch (host already present) - # produces no new rendered MachineConfig, so the deterministic MCO - # wait below would poll for a configuration.name change that never - # comes and hang until its timeout -- this only bites a cluster whose - # registrySources already lists the host (e.g. reused/pooled), not a - # fresh IPI cluster where the array starts empty. - if [[ " ${EXISTING_INSECURE} " != *" ${DEST_HOST} "* ]]; then - NEW_INSECURE="${EXISTING_INSECURE:+${EXISTING_INSECURE} }${DEST_HOST}" - # Intentional word splitting: one JSON array element per - # space-separated host in NEW_INSECURE. - # shellcheck disable=SC2086 - INSECURE_JSON=$(printf '"%s",' ${NEW_INSECURE}) - INSECURE_JSON="[${INSECURE_JSON%,}]" - # Captured immediately before the patch, not after the several - # steps (SA/token creation, mirroring) that follow -- capturing - # it later risked the MCO already starting its rollout in that - # gap, poisoning the "pre-change" baseline the wait below relies on. - MCP_BASELINE=$(./oc get mcp -o jsonpath='{range .items[*]}{.metadata.name}={.status.configuration.name}{"\n"}{end}') - if [[ -z "${MCP_BASELINE//[[:space:]]/}" ]]; then - # No MachineConfigPools means the wait loop below would iterate - # zero pools, leave ALL_DONE at its initial "true", and report - # success on the very first attempt without confirming anything. - echo "[$(date --utc +%FT%T.%3NZ)] No MachineConfigPools found; cannot confirm the insecure-registry trust rollout" >&2 - exit 1 - fi - ./oc patch image.config.openshift.io/cluster --type=merge -p "{\"spec\":{\"registrySources\":{\"insecureRegistries\":${INSECURE_JSON}}}}" - - # Deterministic MCO rollout wait: nothing else in this - # OO_MIRROR_TO_CLUSTER_REGISTRY block depends on the node-level - # trust rollout except operator-sdk run bundle itself (much further - # down), so running the wait immediately after the patch keeps the - # baseline-to-first-poll gap as small as possible. Capture each - # MCP's current rendered-config name before the patch (above), then - # poll until every pool has moved to a different config AND - # finished applying it to all its machines -- a plain - # `oc wait --for=condition=Updated` can return instantly if the MCO - # hasn't started rolling out yet (Updated can still read "True" - # from before our own patch). - echo "[$(date --utc +%FT%T.%3NZ)] Waiting for MachineConfigPools to finish rolling out the insecure-registry trust change" - for _ in $(seq 1 90); do - ALL_DONE=true - DEGRADED_MCP="" - while IFS='=' read -r mcp_name old_config; do - [[ -z "${mcp_name}" ]] && continue - new_config=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.configuration.name}' 2>/dev/null || true) - updated_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.updatedMachineCount}' 2>/dev/null || true) - total_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.machineCount}' 2>/dev/null || true) - degraded_count=$(./oc get mcp "${mcp_name}" -o jsonpath='{.status.degradedMachineCount}' 2>/dev/null || true) - # Default empty (not just failed) lookups too -- a pool - # queried before its counts are populated returns "" with - # exit 0, which `|| echo` alone wouldn't catch, and "" == "" - # would have looked falsely "done". - updated_count="${updated_count:-0}" - total_count="${total_count:-1}" - degraded_count="${degraded_count:-0}" - if [[ "${degraded_count}" -gt 0 ]]; then - DEGRADED_MCP="${mcp_name}" - fi - if [[ "${new_config}" == "${old_config}" ]] || [[ "${updated_count}" != "${total_count}" ]]; then - ALL_DONE=false - fi - done <<< "${MCP_BASELINE}" - if [[ -n "${DEGRADED_MCP}" ]]; then - # Fail fast instead of burning the full wait budget: a - # degraded pool isn't going to un-degrade on its own within - # the remaining polls, so waiting out the rest of the 90 - # iterations only delays a failure that's already certain. - echo "[$(date --utc +%FT%T.%3NZ)] MachineConfigPool ${DEGRADED_MCP} reports degraded machines; aborting the rollout wait early" >&2 - ./oc get mcp -o wide || true - ./oc get nodes -o wide || true - exit 1 - fi - [[ "${ALL_DONE}" == "true" ]] && break - sleep 20 - done - if [[ "${ALL_DONE}" != "true" ]]; then - # Fail here, with MCO-specific diagnostics, rather than warn and - # proceed: without the trust rollout complete, the bundle-unpack - # Job's pull fails TLS verification against DEST_HOST's - # certificate anyway -- limping forward just defers to a later, - # less diagnostic failure inside operator-sdk run bundle. - echo "[$(date --utc +%FT%T.%3NZ)] MachineConfigPool rollout did not confirm completion within the wait budget" >&2 - ./oc get mcp -o wide || true - ./oc get nodes -o wide || true - exit 1 - fi - else - echo "[$(date --utc +%FT%T.%3NZ)] ${DEST_HOST} is already marked insecure -- skipping patch and MCO wait" - fi - - # oc registry login needs the ambient session to be bearer-token-based, - # but this test cluster's admin kubeconfig is client-cert based ("no - # token is currently in use for this session"). Create a dedicated - # ServiceAccount with explicit image-builder rights and a manually- - # requested token Secret instead -- works regardless of the ambient - # session's own credential type. Internal registry basic-auth accepts - # any username with a valid SA token as the password (standard - # OpenShift convention, e.g. `podman login -u unused -p $(oc whoami -t)`). - OO_ROBOT_SA="oo-bundle-pusher" - ./oc create serviceaccount "${OO_ROBOT_SA}" -n "${OO_INSTALL_NAMESPACE}" --dry-run=client -o yaml | ./oc apply -f - - ./oc policy add-role-to-user system:image-builder -z "${OO_ROBOT_SA}" -n "${OO_INSTALL_NAMESPACE}" - cat </dev/null | base64 -d || true) - [[ -n "${ROBOT_TOKEN}" ]] && break - sleep 2 - done - if [[ -z "${ROBOT_TOKEN}" ]]; then - echo "[$(date --utc +%FT%T.%3NZ)] Timed out waiting for the robot ServiceAccount token to populate" >&2 - exit 1 - fi - - # Built with printf/sed, not jq -- this ref has no guaranteed jq, and a - # runtime curl download of an unpinned-by-checksum binary from an - # archived repo isn't worth it for JSON this simple. - # /tmp/.dockerconfigjson is a compact, machine-generated Secret extract - # (oc extract, not hand-edited), so splicing a new entry right after - # the opening "auths":{ is reliable. - # - # `|` as the sed delimiter, not `/`: a structural guarantee, not an - # empirical one -- standard base64 (RFC 4648, DEST_AUTH_B64 below) uses - # only A-Za-z0-9+/=, and a Route's .spec.host (DEST_HOST) is a DNS name - # (RFC 1123: alphanumerics, hyphens, dots), so neither value spliced - # through this sed can ever contain `|`. - # - # Script file, not an inline -e expression: an inline sed command puts - # NEW_AUTH_ENTRY (which embeds the credential, base64-obscured but not - # secret) on this process's own command line, visible to any other - # process on the host via /proc//cmdline for as long as sed runs. - DEST_AUTH_B64=$(printf 'unused:%s' "${ROBOT_TOKEN}" | base64 | tr -d '\n') - unset ROBOT_TOKEN - MERGED_AUTH_FILE=/tmp/oo-merged-auth.json - SED_SCRIPT=/tmp/oo-auth-splice.sed - NEW_AUTH_ENTRY="\"${DEST_HOST}\":{\"auth\":\"${DEST_AUTH_B64}\"}," - unset DEST_AUTH_B64 - (umask 077; printf 's|"auths"[[:space:]]*:[[:space:]]*\{|"auths":{%s|\n' "${NEW_AUTH_ENTRY}" > "${SED_SCRIPT}") - (umask 077; sed -E -f "${SED_SCRIPT}" /tmp/.dockerconfigjson > "${MERGED_AUTH_FILE}") - rm -f "${SED_SCRIPT}" - if ! grep -q "\"${DEST_HOST}\":" "${MERGED_AUTH_FILE}"; then - echo "[$(date --utc +%FT%T.%3NZ)] Failed to splice mirror credentials into the auth file" >&2 - exit 1 - fi - - # Generic name (not OADP-specific): this ref is shared by non-KDM - # consumers too. Namespace-scoped and ephemeral, so no collision risk. - OO_BUNDLE_MIRROR="${DEST_HOST}/${OO_INSTALL_NAMESPACE}/oo-bundle-mirror:latest" - echo "[$(date --utc +%FT%T.%3NZ)] Mirroring ${OO_BUNDLE} to ${OO_BUNDLE_MIRROR}" - # --insecure applies to BOTH ends of this single mirror invocation -- oc - # image mirror has no per-registry insecure flag (see - # `oc image mirror --help`) -- so it also skips TLS verification for - # OO_BUNDLE's own source registry, not just DEST_HOST, which is the - # only side that actually needs it. Known limitation, not an - # oversight: splitting this into a verified pull (full TLS to the - # source) followed by an insecure push (to DEST_HOST only), e.g. via a - # local --dir stage, would close the gap, but needs its own validation - # before swapping in. - ./oc image mirror --registry-config="${MERGED_AUTH_FILE}" --filter-by-os=linux/amd64 --insecure=true "${OO_BUNDLE}=${OO_BUNDLE_MIRROR}" - rm -f "${MERGED_AUTH_FILE}" - OO_BUNDLE_EFFECTIVE="${OO_BUNDLE_MIRROR}" - - echo "[$(date --utc +%FT%T.%3NZ)] Granting anonymous pull on ${OO_INSTALL_NAMESPACE} so operator-sdk's own bundle-pull mechanism needs no credentials" - # system:unauthenticated is a GROUP, not a user -- anonymous requests - # authenticate as user system:anonymous, a member of that group. - # add-role-to-USER never matches real anonymous requests ("access - # denied" on an anonymous HEAD despite the binding existing: - # www-authenticate="Basic realm=openshift,error=\"access denied\""), - # so add-role-to-group is the correct subject kind. - ./oc policy add-role-to-group system:image-puller system:unauthenticated -n "${OO_INSTALL_NAMESPACE}" - - # Deliberately NOT revoked once operator-sdk run bundle returns: the - # CatalogSource OLM creates gets its own long-lived registry/grpc pod - # (discoverable via -l olm.catalogSource, see the diagnostics below), - # reconciled by OLM's catalog-operator for as long as the CatalogSource - # exists -- i.e. for the rest of this job, well past this step's own - # lifetime. If that pod is ever rescheduled (node pressure, eviction, - # OOM) during set-related-image or e2e, kubelet re-pulls its image - # from DEST_HOST, and revoking here first would turn that into an - # ImagePullBackOff far from this step, with no obvious link back to - # the cause. - # - # Leaving the grant standing for the rest of the job is acceptable - # only because both of these hold: this is an ephemeral, single-use - # test cluster torn down at job end, and this whole block only runs - # when OO_MIRROR_TO_CLUSTER_REGISTRY is explicitly opted into (only - # the 4 KDM configs, as of this writing). If either changes -- a - # pooled or longer-lived cluster, or this flag ever defaulting to - # true -- this reasoning needs revisiting. - SKIP_TLS_VERIFY_ARG="--skip-tls-verify" -fi - -if [[ -n "${SKIP_TLS_VERIFY_ARG:-}" ]]; then - OPTIONAL_ARGS+=("${SKIP_TLS_VERIFY_ARG}") -fi - -set +o errexit ( cd /tmp - # ${OPTIONAL_ARGS[@]+"${OPTIONAL_ARGS[@]}"}, not a bare - # "${OPTIONAL_ARGS[@]}": expanding a zero-element array under - # set -o nounset only stopped erroring in bash 4.4+. bash 3.2 (still - # the macOS system default, and plausible in other minimal base - # images) hard-errors ("unbound variable") on the bare form for an - # empty array; this guarded form works on both. - operator-sdk run bundle "${OO_BUNDLE_EFFECTIVE}" -n "${OO_INSTALL_NAMESPACE}" --verbose "${OPTIONAL_ARGS[@]+"${OPTIONAL_ARGS[@]}"}" --timeout="${OO_INSTALL_TIMEOUT_MINUTES}m" --security-context-config="${OO_SECURITY_CONTEXT}" + operator-sdk run bundle "${OO_BUNDLE}" -n "${OO_INSTALL_NAMESPACE}" --verbose ${INSTALL_MODE_ARG} --timeout="${OO_INSTALL_TIMEOUT_MINUTES}m" --security-context-config="${OO_SECURITY_CONTEXT}" ) -RUN_BUNDLE_STATUS=$? -set -o errexit - -if [[ "${RUN_BUNDLE_STATUS}" -ne 0 ]]; then - # A generic timeout here can mask a real OLM-side blocker rather than - # just slow resync/resolution -- dump the actual state so it's - # diagnosable instead of guessed at. - echo "[$(date --utc +%FT%T.%3NZ)] operator-sdk run bundle failed (exit ${RUN_BUNDLE_STATUS}) -- dumping OLM diagnostics" - ./oc get catalogsource -n "${OO_INSTALL_NAMESPACE}" -o yaml || true - ./oc get subscription -n "${OO_INSTALL_NAMESPACE}" -o yaml || true - ./oc get installplan -n "${OO_INSTALL_NAMESPACE}" -o yaml || true - ./oc get pods -n "${OO_INSTALL_NAMESPACE}" -o wide || true - REG_POD=$(./oc get pods -n "${OO_INSTALL_NAMESPACE}" -l olm.catalogSource -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true) - if [[ -n "${REG_POD}" ]]; then - echo "[$(date --utc +%FT%T.%3NZ)] Logs for registry pod ${REG_POD}" - ./oc logs "${REG_POD}" -n "${OO_INSTALL_NAMESPACE}" --all-containers || true - fi - ./oc get events -n "${OO_INSTALL_NAMESPACE}" --sort-by=.lastTimestamp || true - ./oc get pods -n openshift-operator-lifecycle-manager -o wide || true - exit "${RUN_BUNDLE_STATUS}" -fi echo "check deployment" if [[ ! -z "${DEPLOYMENT}" ]]; then ./oc wait --timeout=10m --for condition=Available -n openshift-file-integrity deployment $DEPLOYMENT fi echo "[$(date --utc +%FT%T.%3NZ)] Script Completed Execution Successfully !" + diff --git a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml index 996fd07ff66c0..4505ae5234dff 100644 --- a/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml +++ b/ci-operator/step-registry/optional-operators/operator-sdk/non-ci-bundle-image/optional-operators-operator-sdk-non-ci-bundle-image-ref.yaml @@ -39,42 +39,6 @@ ref: Specifies the security context to use for the catalog pod created by operator-sdk. Allowed: `restricted`, `legacy`. (default: `restricted`) default: "restricted" - - name: OO_PSA_ENFORCE_PRIVILEGED - documentation: |- - When true, force pod-security.kubernetes.io/enforce=privileged on - OO_INSTALL_NAMESPACE regardless of its name. By default, namespaces - prefixed `openshift-` only get security.openshift.io/scc.podSecurityLabelSync=true - (PSA level derived from whatever SCCs are granted, which can lag behind - what operator-sdk's own internal registry pod actually needs and reject - it under PodSecurity "restricted"). Namespaces not prefixed `openshift-` - already get the explicit-privileged treatment unconditionally; this - flag extends that same treatment to an `openshift-*` namespace. - default: "false" - - name: OO_MIRROR_TO_CLUSTER_REGISTRY - documentation: |- - When true, mirror OO_BUNDLE into the test cluster's own internal - image registry first (exposing its default route, marking it as an - insecure registry cluster-wide, and granting anonymous pull on - OO_INSTALL_NAMESPACE), and install from that internal copy instead - of OO_BUNDLE directly. Works around a real, still only partially - understood failure where operator-sdk's own containerd-based bundle - pull cannot be given working credentials for some external - registries (observed against a CI registry proxy) even when the - exact same credential is independently confirmed valid via - `oc image mirror`/`oc image info`. - - This is opt-in and defaults to false because it mutates - cluster-wide config (image registry route, insecureRegistries, - MachineConfigPool rollout) beyond OO_INSTALL_NAMESPACE -- only - enable it for a consumer that has actually hit the failure above. - Assumes an ephemeral, single-use test cluster; none of these - mutations are torn down. - - Sizing job/test timeouts: enabling this adds up to ~30 minutes - (the MachineConfigPool rollout wait) on top of this step's own - grace_period and OO_INSTALL_TIMEOUT_MINUTES, before OO_BUNDLE's - own install even starts. - default: "false" - name: OO_BUNDLE documentation: |- Specifies a non ci-bundle image From b9d51b879616184fd36dc13d84b2cde4b01daba3 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Tue, 18 Aug 2026 00:39:02 -0400 Subject: [PATCH 6/7] Add oadp-operator repo OWNERS to step-registry/oadp/OWNERS Merges openshift/oadp-operator's own approvers/reviewers into this dir's OWNERS so oadp-operator team members can approve changes under ci-operator/step-registry/oadp/ (including the new oadp-operator-sdk-bundle-image fork) without needing a separate step-specific OWNERS override. Signed-off-by: Tiger Kaovilai --- ci-operator/step-registry/oadp/OWNERS | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ci-operator/step-registry/oadp/OWNERS b/ci-operator/step-registry/oadp/OWNERS index 2c9a1d470eaa9..0a1c58bb914c9 100644 --- a/ci-operator/step-registry/oadp/OWNERS +++ b/ci-operator/step-registry/oadp/OWNERS @@ -1,7 +1,20 @@ approvers: - cspi-qe-ocp-lp - tareqalayan +- jwmatthews +- sseago +- shawn-hurley +- dymurray +- shubham-pampattiwar +- kaovilai +- mpryc +- joeavaikath options: {} reviewers: - cspi-qe-ocp-lp -- tareqalayan \ No newline at end of file +- tareqalayan +- sseago +- shubham-pampattiwar +- kaovilai +- mpryc +- joeavaikath \ No newline at end of file From dfb2ed865e6a5a8052926d1e8c6ff8ae5a380153 Mon Sep 17 00:00:00 2001 From: Tiger Kaovilai Date: Tue, 18 Aug 2026 00:44:36 -0400 Subject: [PATCH 7/7] Fix invalid OWNERS: drop untrusted tareqalayan, vet oadp-operator names openshift org membership check confirmed tareqalayan is not an org member (404 on orgs/openshift/members), which openshift/release's own OWNERS validation flags as invalid. Drops it from step-registry/oadp/OWNERS. Also replaces the operator-sdk-bundle-image step's OWNERS (registry-metadata requires a physical OWNERS file per step dir, no directory-level inheritance) with only the oadp-operator repo OWNERS actually confirmed as openshift org members. Signed-off-by: Tiger Kaovilai --- ci-operator/step-registry/oadp/OWNERS | 2 -- .../oadp/operator-sdk-bundle-image/OWNERS | 19 +++++++-------- ...perator-sdk-bundle-image-ref.metadata.json | 23 ++++++++++--------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/ci-operator/step-registry/oadp/OWNERS b/ci-operator/step-registry/oadp/OWNERS index 0a1c58bb914c9..0d705d8ad6b9a 100644 --- a/ci-operator/step-registry/oadp/OWNERS +++ b/ci-operator/step-registry/oadp/OWNERS @@ -1,6 +1,5 @@ approvers: - cspi-qe-ocp-lp -- tareqalayan - jwmatthews - sseago - shawn-hurley @@ -12,7 +11,6 @@ approvers: options: {} reviewers: - cspi-qe-ocp-lp -- tareqalayan - sseago - shubham-pampattiwar - kaovilai diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS index 0a1f910f099b9..08bf362d96bee 100644 --- a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/OWNERS @@ -1,15 +1,16 @@ approvers: -- tareqalayan -- weshayutin -- akarol -- PrasadJoshi12 +- jwmatthews +- sseago +- shawn-hurley +- dymurray +- shubham-pampattiwar +- kaovilai - mpryc +- joeavaikath options: {} reviewers: -- tareqalayan +- sseago +- shubham-pampattiwar - kaovilai -- PrasadJoshi12 -- stillalearner # Sachin S -- weshayutin -- akarol - mpryc +- joeavaikath diff --git a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json index e0bc1aacc2bd8..17dcee4691986 100644 --- a/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json +++ b/ci-operator/step-registry/oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.metadata.json @@ -2,20 +2,21 @@ "path": "oadp/operator-sdk-bundle-image/oadp-operator-sdk-bundle-image-ref.yaml", "owners": { "approvers": [ - "tareqalayan", - "weshayutin", - "akarol", - "PrasadJoshi12", - "mpryc" + "jwmatthews", + "sseago", + "shawn-hurley", + "dymurray", + "shubham-pampattiwar", + "kaovilai", + "mpryc", + "joeavaikath" ], "reviewers": [ - "tareqalayan", + "sseago", + "shubham-pampattiwar", "kaovilai", - "PrasadJoshi12", - "stillalearner", - "weshayutin", - "akarol", - "mpryc" + "mpryc", + "joeavaikath" ] } } \ No newline at end of file