Skip to content

TRT-2295: admit and extract non-payload OTE binaries#30863

Open
smg247 wants to merge 3 commits intoopenshift:mainfrom
smg247:non-payload-ote
Open

TRT-2295: admit and extract non-payload OTE binaries#30863
smg247 wants to merge 3 commits intoopenshift:mainfrom
smg247:non-payload-ote

Conversation

@smg247
Copy link
Member

@smg247 smg247 commented Mar 11, 2026

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Dev Testing workflow:

# Get a cluster
# (In cluster-bot Slack channel)
mce create 4.21.3 8h aws

# Save kubeconfig and set up environment
export KUBECONFIG="/path/to/ote-testing.kubeconfig" # kubeconfig for mce cluster
export EXTENSIONS_PAYLOAD_OVERRIDE="registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-26-092444"
export EXTENSION_BINARY_OVERRIDE_INCLUDE_TAGS="tests"
export TEST_PROVIDER='{"type":"aws"}'
# Registry auth file contains pullsecrets for registry.redhat.io and registry.ci.openshift.org
export REGISTRY_AUTH_FILE="${HOME}/.docker/config.json"

# Build and push your extension image
cd /path/to/cluster-api-actuator-pkg
git fetch origin pull/423/head:pr-423
git checkout pr-423
# Edit Dockerfile.ci to set GOARCH=arm64
podman build -f Dockerfile.ci -t quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest .
podman push quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest

# Run in container
podman run --platform linux/arm64 \
  --authfile=$HOME/.docker/config.json \
  -it --rm \
  -v $(pwd):/workspace \
  -w /workspace \
  registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.24-openshift-4.22 \
  /bin/bash

# Inside container:
# Install oc
cd /tmp
wget https://mirror.openshift.com/pub/openshift-v4/arm64/clients/ocp-dev-preview/latest/openshift-client-linux-arm64-rhel9.tar.gz
tar xvf openshift-client-linux*.tar.gz
mv oc kubectl /usr/bin

# Build openshift-tests
cd /path/to/origin
make

# Install the CRD using the new command
./openshift-tests extension-admission install-crd

# Create admission policy using the new command
./openshift-tests extension-admission create cluster-api-extensions \
  --permit=test-extensions/*

# Create the ImageStream
# This is the yaml for an NS and ImageStream containing the proper annotations
oc apply -f cluster-api-actuator-pkg-extension.yaml

# Build and test
./openshift-tests run openshift/conformance/parallel --monitor event-collector --junit-dir=/tmp/junit --dry-run
./openshift-tests run capi/e2e --monitor event-collector --junit-dir=/tmp/junit

Summary by CodeRabbit

Release Notes

  • New Features
    • Added extension admission management to OpenShift tests with a new CLI command for installing and creating extension resources.
    • Enabled discovery of extensions with admission control based on permitted image stream patterns.
    • Extensions failing admission checks now appear as reportable items in test results for improved visibility.

…mmand to install the TestExtension CRD and apply the matching CR
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 11, 2026
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 11, 2026

@smg247: This pull request references TRT-2295 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot
Copy link

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: automatic mode

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Walkthrough

This PR introduces extension admission support to OpenShift tests. It adds a new TestExtensionAdmission CRD (testextension.redhat.io/v1), a CLI command for managing extension admissions with CRD installation and resource creation, discovery logic for non-payload binary admissions, and infrastructure to classify and report unpermitted extensions as test failures.

Changes

Cohort / File(s) Summary
API Group Definition
pkg/apis/testextension/v1/doc.go, pkg/apis/testextension/v1/register.go, pkg/apis/testextension/v1/types.go
Establishes testextension.redhat.io/v1 API group with CRD type definitions, schema registration, and metadata annotations for code generation.
Extension Admission Command
cmd/openshift-tests/openshift-tests.go, pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go, pkg/cmd/openshift-tests/extension-admission/testextensionadmission-crd.yaml
Adds new CLI subcommand for extension admission management with install-crd and create subcommands; includes embedded CRD manifest and oc apply integration for resource deployment.
Non-Payload Admission Discovery
pkg/test/extensions/non_payload_binary_admission.go
Implements discovery and validation of TestExtensionAdmission resources, permit pattern matching, and classification logic for determining permitted vs. unpermitted extensions.
Binary Extraction Infrastructure
pkg/test/extensions/binary.go, pkg/test/extensions/provider.go
Extends extraction pipeline to discover non-payload extensions, classify them against admission permits, extract permitted binaries from arbitrary images, and return unpermitted extensions list.
Test Runner Integration
pkg/test/ginkgo/cmd_runsuite.go
Updates test suite execution to capture unpermitted extensions and synthesize test cases reporting them as failures in junit output.
Callers Updated
pkg/cmd/openshift-tests/images/images_command.go, pkg/cmd/openshift-tests/list/extensions.go, pkg/testsuites/standard_suites.go
Adapts call sites of ExtractAllTestBinaries to handle new return value containing unpermitted extensions list.

Sequence Diagram(s)

sequenceDiagram
    participant Runner as Test Runner
    participant Discovery as Non-Payload Discovery
    participant Admission as TestExtensionAdmission API
    participant Classification as Extension Classifier
    participant Extraction as Binary Extractor
    participant Reporter as Test Reporter

    Runner->>Discovery: DiscoverNonPayloadBinaryAdmission()
    Discovery->>Admission: List TestExtensionAdmission resources
    Admission-->>Discovery: Return permit patterns
    Discovery-->>Runner: Return []PermitPattern

    Runner->>Discovery: discoverNonPayloadExtensions()
    Discovery->>Discovery: List ImageStreamTags across namespaces
    Discovery->>Classification: MatchesAnyPermit(namespace, imagestream, patterns)
    Classification-->>Discovery: permitted=true/false
    Discovery-->>Runner: Return permitted + unpermitted extensions

    par Parallel Processing
        Runner->>Extraction: Extract permitted extensions
        Extraction-->>Runner: Return TestBinaries
    and
        Runner->>Reporter: createUnpermittedExtensionTests(unpermitted[])
        Reporter-->>Runner: Return JUnit test cases
    end

    Runner->>Reporter: Append unpermitted test cases to results
    Reporter-->>Runner: Complete test suite with failure reporting
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'TRT-2295: admit and extract non-payload OTE binaries' directly and clearly summarizes the main changes: adding admission control via the TestExtensionAdmission CRD and extracting non-payload OpenShift test extension binaries.
Stable And Deterministic Test Names ✅ Passed The test names introduced are stable and deterministic. Static test names like '[openshift-tests] extension binary not permitted' do not contain dynamic information, following Ginkgo test naming best practices.
Test Structure And Quality ✅ Passed PR does not add any Ginkgo test code; no *_test.go files or test definitions are introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan for PR comments
  • Generate coding plan

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.5.0)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 11, 2026

@smg247: This pull request references TRT-2295 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Summary by CodeRabbit

Release Notes

  • New Features

  • Added extension-admission command with install-crd and create subcommands to manage extension permissions

  • Integrated automatic discovery and validation of non-payload extensions during test execution

  • Test results now include failed test cases for unpermitted extensions

  • Refactor

  • Extracted common binary extraction logic into reusable helper methods

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 11, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (4)
pkg/test/extensions/non-payload-binary-admission.go (1)

119-126: Replace custom isNotFound() with Kubernetes error helpers.

This fallback decides whether to suppress API errors and continue in deny-all mode. Raw substring checks are fragile; message variations or unrelated errors containing "not found" will be misclassified. Use the standard Kubernetes helpers (apierrors.IsNotFound() or kapierrs.IsNotFound()) already established throughout the codebase for discovery and dynamic-client errors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/test/extensions/non-payload-binary-admission.go` around lines 119 - 126,
The isNotFound(err error) helper currently does fragile substring checks;
replace its body to use the Kubernetes standard error helper (e.g.,
apierrors.IsNotFound or kapierrs.IsNotFound) to determine NotFound errors and
remove the manual strings.Contains checks; update imports to include the
appropriate k8s.io/apimachinery/pkg/api/errors (or the project's kapierrs alias)
and ensure all callers of isNotFound(func) continue to work with the same
signature (isNotFound) so discovery/dynamic-client errors are detected reliably.
pkg/test/ginkgo/cmd_runsuite.go (1)

180-209: LGTM - Flake pattern for visibility without blocking.

The approach of creating both a pass and fail case for the same test name is an intentional "flake" pattern that makes unpermitted extensions visible in test results without causing the overall job to fail. This aligns with the comment on line 181 and is appropriate for rolling out this feature.

One minor formatting nit on line 196:

Cleaner string formatting
-		msg := "extension binary not permitted by TestExtensionAdmission:\n"
 		for _, u := range unpermitted {
-			msg = fmt.Sprintf("%s\n  - %s/%s:%s (%s)\n", msg, u.Namespace, u.ImageStream, u.Tag, u.Component)
+			msg += fmt.Sprintf("  - %s/%s:%s (%s)\n", u.Namespace, u.ImageStream, u.Tag, u.Component)

Or use strings.Builder for better performance with multiple appends.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/test/ginkgo/cmd_runsuite.go` around lines 180 - 209, The string building
in createUnpermittedExtensionTests currently concatenates with fmt.Sprintf
repeatedly (msg variable) which is less efficient and slightly messy; replace
that with a strings.Builder (or use fmt.Fprintf to the builder) to construct the
multi-line message inside the loop that iterates over unpermitted (for _, u :=
range unpermitted) and then set FailureOutput.Output to builder.String(), and
keep the existing logrus.Warnf calls unchanged.
pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go (1)

165-171: File handle closed twice.

The file is closed via defer tmpFile.Close() at line 166, and then explicitly closed at line 171. While calling Close() twice on an *os.File is safe (subsequent calls return an error that's ignored here), the deferred os.Remove(tmpFile.Name()) at line 165 will execute before the deferred Close() at line 166 due to LIFO ordering. This means the file is removed while still open (on some OSes this is fine, on Windows it may fail).

Consider removing the deferred Close() since you're explicitly closing before exec:

Suggested fix
 	tmpFile, err := os.CreateTemp("", "testextensionadmission-*.yaml")
 	if err != nil {
 		return fmt.Errorf("failed to create temp file: %w", err)
 	}
 	defer os.Remove(tmpFile.Name())
-	defer tmpFile.Close()

 	if _, err := tmpFile.Write(yamlBytes); err != nil {
+		tmpFile.Close()
 		return fmt.Errorf("failed to write YAML to temp file: %w", err)
 	}
-	tmpFile.Close()
+	if err := tmpFile.Close(); err != nil {
+		return fmt.Errorf("failed to close temp file: %w", err)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go`
around lines 165 - 171, The temp file is being closed twice (defer
tmpFile.Close() and an explicit tmpFile.Close()), and defer
os.Remove(tmpFile.Name()) will run before the deferred Close due to LIFO
ordering which can cause remove-before-close issues on some OSes; remove the
deferred tmpFile.Close() and keep the explicit tmpFile.Close() after writing
(around the tmpFile.Write(yamlBytes) error handling) so the file is closed
deterministically before or after os.Remove as intended; look for symbols
tmpFile, tmpFile.Write, tmpFile.Close, os.Remove, and yamlBytes to update the
defers accordingly.
pkg/test/extensions/binary.go (1)

1040-1045: Consider adding a label selector to reduce API response size.

Listing all ImageStreamTags across all namespaces could return a large result set. If non-payload extensions are expected to have a specific label (e.g., openshift-tests-extension=true), adding a LabelSelector to the ListOptions would reduce the API response size and improve performance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/test/extensions/binary.go` around lines 1040 - 1045, The ImageStreamTags
list call currently queries all namespaces via
imageClient.ImageV1().ImageStreamTags("").List(ctx, metav1.ListOptions{}), which
can be large; update the ListOptions to include a LabelSelector (e.g.,
"openshift-tests-extension=true") so the API returns only extension
ImageStreamTags—modify the call that constructs metav1.ListOptions passed to
ImageStreamTags("").List to set LabelSelector accordingly and ensure the label
key matches the expected non-payload extension label.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/apis/testextension/v1/types.go`:
- Around line 7-18: Add the corresponding list runtime object for the CRD by
declaring a TestExtensionAdmissionList type that implements runtime.Object and
contains metav1.TypeMeta, metav1.ListMeta and an Items []TestExtensionAdmission
slice; keep the existing +genclient on TestExtensionAdmission and add the
appropriate deepcopy-gen/k8s tags (e.g.,
+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object) on the list
type so the generated client/list/watch surfaces match the CRD's listKind.

In `@pkg/cmd/openshift-tests/extension-admission/testextensionadmission-crd.yaml`:
- Around line 29-36: Add the missing MinItems constraint and tighten the items
pattern so the CRD matches the matcher contract in
pkg/apis/testextension/v1/types.go: for the "permit" array add "minItems: 1" and
change the item's "pattern" so a segment is either a single literal "*" or a
whole name (no embedded asterisks) — i.e. enforce each side of the "/" to be
either "*" or a [A-Za-z0-9\-_]+ token; update the CRD "permit" definition to
reflect this and keep the description in sync with the matcher behavior.

In `@pkg/test/extensions/binary.go`:
- Line 1036: The function parameter name in discoverNonPayloadExtensions is
misspelled as permitPatters; rename it to permitPatterns in the function
signature and update every usage inside discoverNonPayloadExtensions (and any
local variables) to use permitPatterns, and also update any callers or
references in this file that pass or refer to permitPatters (including the
symbol used around the code block near where permitPatters is referenced) so the
identifier is consistent.

In `@pkg/test/extensions/provider.go`:
- Around line 217-228: The override environment-variable key generation for
binaryPathOverride is not sanitizing ':' characters (e.g.,
namespace/imagestream:tag), so exports with that override won't work in shells;
update the sanitizer used by binaryPathOverride (the code path invoked by the
call at binaryPathOverride(imageTag, binaryPath)) to replace ':' with a safe
character (e.g., '_') when constructing the env-var name, then return the
override so TestBinary receives a usable path; ensure the same sanitized form is
used wherever the file builds or reads the override env var.
- Around line 109-113: The fast-path returns a cached file without revalidating
its architecture; update the cache-check block in provider.go to call
checkCompatibleArchitecture(finalBinPath) before returning: if
checkCompatibleArchitecture(finalBinPath) reports compatible, log and return
finalBinPath, 0, nil as before; if it reports incompatible or an error, remove
the stale finalBinPath (os.Remove) and continue with normal download/creation
flow (do not return the invalid path). Reference finalBinPath, imageTag and the
helper checkCompatibleArchitecture when making this change.
- Around line 230-237: The non-payload cache directory is keyed only by imageTag
(safeNameForDir(imageTag)), which allows tag retargeting to reuse stale
binaries; change the key to use the image's immutable identity from imageRef
(e.g., its digest/ID) when building nonPayloadDir so the cache is tied to the
exact image, not the mutable tag; update the call site where nonPayloadDir is
constructed (provider.binPath, safeNameForDir(imageTag)) to derive a stable name
from imageRef (and fall back to tag only if no digest is available) and ensure
any logging or error messages still reference the new nonPayloadDir; keep
provider.extractBinary usage unchanged.

---

Nitpick comments:
In `@pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go`:
- Around line 165-171: The temp file is being closed twice (defer
tmpFile.Close() and an explicit tmpFile.Close()), and defer
os.Remove(tmpFile.Name()) will run before the deferred Close due to LIFO
ordering which can cause remove-before-close issues on some OSes; remove the
deferred tmpFile.Close() and keep the explicit tmpFile.Close() after writing
(around the tmpFile.Write(yamlBytes) error handling) so the file is closed
deterministically before or after os.Remove as intended; look for symbols
tmpFile, tmpFile.Write, tmpFile.Close, os.Remove, and yamlBytes to update the
defers accordingly.

In `@pkg/test/extensions/binary.go`:
- Around line 1040-1045: The ImageStreamTags list call currently queries all
namespaces via imageClient.ImageV1().ImageStreamTags("").List(ctx,
metav1.ListOptions{}), which can be large; update the ListOptions to include a
LabelSelector (e.g., "openshift-tests-extension=true") so the API returns only
extension ImageStreamTags—modify the call that constructs metav1.ListOptions
passed to ImageStreamTags("").List to set LabelSelector accordingly and ensure
the label key matches the expected non-payload extension label.

In `@pkg/test/extensions/non-payload-binary-admission.go`:
- Around line 119-126: The isNotFound(err error) helper currently does fragile
substring checks; replace its body to use the Kubernetes standard error helper
(e.g., apierrors.IsNotFound or kapierrs.IsNotFound) to determine NotFound errors
and remove the manual strings.Contains checks; update imports to include the
appropriate k8s.io/apimachinery/pkg/api/errors (or the project's kapierrs alias)
and ensure all callers of isNotFound(func) continue to work with the same
signature (isNotFound) so discovery/dynamic-client errors are detected reliably.

In `@pkg/test/ginkgo/cmd_runsuite.go`:
- Around line 180-209: The string building in createUnpermittedExtensionTests
currently concatenates with fmt.Sprintf repeatedly (msg variable) which is less
efficient and slightly messy; replace that with a strings.Builder (or use
fmt.Fprintf to the builder) to construct the multi-line message inside the loop
that iterates over unpermitted (for _, u := range unpermitted) and then set
FailureOutput.Output to builder.String(), and keep the existing logrus.Warnf
calls unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9fa7a282-b3f1-4e14-9581-abc5f491e3c7

📥 Commits

Reviewing files that changed from the base of the PR and between 02b4172 and c53a075.

📒 Files selected for processing (13)
  • cmd/openshift-tests/openshift-tests.go
  • pkg/apis/testextension/v1/doc.go
  • pkg/apis/testextension/v1/register.go
  • pkg/apis/testextension/v1/types.go
  • pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go
  • pkg/cmd/openshift-tests/extension-admission/testextensionadmission-crd.yaml
  • pkg/cmd/openshift-tests/images/images_command.go
  • pkg/cmd/openshift-tests/list/extensions.go
  • pkg/test/extensions/binary.go
  • pkg/test/extensions/non-payload-binary-admission.go
  • pkg/test/extensions/provider.go
  • pkg/test/ginkgo/cmd_runsuite.go
  • pkg/testsuites/standard_suites.go

@openshift-ci-robot
Copy link

Scheduling required tests:
/test e2e-aws-csi
/test e2e-aws-ovn-fips
/test e2e-aws-ovn-microshift
/test e2e-aws-ovn-microshift-serial
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-gcp-csi
/test e2e-gcp-ovn
/test e2e-gcp-ovn-upgrade
/test e2e-metal-ipi-ovn-ipv6
/test e2e-vsphere-ovn
/test e2e-vsphere-ovn-upi

@pacevedom
Copy link
Contributor

/test e2e-aws-ovn-microshift

@openshift-trt
Copy link

openshift-trt bot commented Mar 12, 2026

Risk analysis has seen new tests most likely introduced by this PR.
Please ensure that new tests meet guidelines for naming and stability.

New tests seen in this PR at sha: c53a075

  • "[openshift-tests] extension binary not permitted" [Total: 13, Pass: 13, Fail: 0, Flake: 0]

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@smg247: This pull request references TRT-2295 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Dev Testing workflow:

# Get a cluster
# (In cluster-bot Slack channel)
mce create 4.21.3 8h aws

# Save kubeconfig and set up environment
export KUBECONFIG="/path/to/ote-testing.kubeconfig" # kubeconfig for mce cluster
export EXTENSIONS_PAYLOAD_OVERRIDE="registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-26-092444"
export EXTENSION_BINARY_OVERRIDE_INCLUDE_TAGS="tests"
export TEST_PROVIDER='{"type":"aws"}'
# Registry auth file contains pullsecrets for registry.redhat.io and registry.ci.openshift.org
export REGISTRY_AUTH_FILE="${HOME}/.docker/config.json"

# Build and push your extension image
cd /path/to/cluster-api-actuator-pkg
git fetch origin pull/423/head:pr-423
git checkout pr-423
# Edit Dockerfile.ci to set GOARCH=arm64
podman build -f Dockerfile.ci -t quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest .
podman push quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest

# Run in container
podman run --platform linux/arm64 \
 --authfile=$HOME/.docker/config.json \
 -it --rm \
 -v $(pwd):/workspace \
 -w /workspace \
 registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.24-openshift-4.22 \
 /bin/bash

# Inside container:
# Install oc
cd /tmp
wget https://mirror.openshift.com/pub/openshift-v4/arm64/clients/ocp-dev-preview/latest/openshift-client-linux-arm64-rhel9.tar.gz
tar xvf openshift-client-linux*.tar.gz
mv oc kubectl /usr/bin

# Build openshift-tests
cd /path/to/origin
make

# Install the CRD using the new command
./openshift-tests extension-admission install-crd

# Create admission policy using the new command
./openshift-tests extension-admission create cluster-api-extensions \
 --permit=test-extensions/*

# Create the ImageStream
oc apply -f cluster-api-actuator-pkg-extension.yaml

# Build and test
./openshift-tests run openshift/conformance/parallel --monitor event-collector --junit-dir=/tmp/junit --dry-run
./openshift-tests run capi/e2e --monitor event-collector --junit-dir=/tmp/junit

Summary by CodeRabbit

Release Notes

  • New Features

  • Added extension-admission command with install-crd and create subcommands to manage extension permissions

  • Integrated automatic discovery and validation of non-payload extensions during test execution

  • Test results now include failed test cases for unpermitted extensions

  • Refactor

  • Extracted common binary extraction logic into reusable helper methods

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@smg247: This pull request references TRT-2295 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Dev Testing workflow:

# Get a cluster
# (In cluster-bot Slack channel)
mce create 4.21.3 8h aws

# Save kubeconfig and set up environment
export KUBECONFIG="/path/to/ote-testing.kubeconfig" # kubeconfig for mce cluster
export EXTENSIONS_PAYLOAD_OVERRIDE="registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-26-092444"
export EXTENSION_BINARY_OVERRIDE_INCLUDE_TAGS="tests"
export TEST_PROVIDER='{"type":"aws"}'
# Registry auth file contains pullsecrets for registry.redhat.io and registry.ci.openshift.org
export REGISTRY_AUTH_FILE="${HOME}/.docker/config.json"

# Build and push your extension image
cd /path/to/cluster-api-actuator-pkg
git fetch origin pull/423/head:pr-423
git checkout pr-423
# Edit Dockerfile.ci to set GOARCH=arm64
podman build -f Dockerfile.ci -t quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest .
podman push quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest

# Run in container
podman run --platform linux/arm64 \
 --authfile=$HOME/.docker/config.json \
 -it --rm \
 -v $(pwd):/workspace \
 -w /workspace \
 registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.24-openshift-4.22 \
 /bin/bash

# Inside container:
# Install oc
cd /tmp
wget https://mirror.openshift.com/pub/openshift-v4/arm64/clients/ocp-dev-preview/latest/openshift-client-linux-arm64-rhel9.tar.gz
tar xvf openshift-client-linux*.tar.gz
mv oc kubectl /usr/bin

# Build openshift-tests
cd /path/to/origin
make

# Install the CRD using the new command
./openshift-tests extension-admission install-crd

# Create admission policy using the new command
./openshift-tests extension-admission create cluster-api-extensions \
 --permit=test-extensions/*

# Create the ImageStream
# This is the yaml for an NS and ImageStream containing the proper annotations
oc apply -f cluster-api-actuator-pkg-extension.yaml

# Build and test
./openshift-tests run openshift/conformance/parallel --monitor event-collector --junit-dir=/tmp/junit --dry-run
./openshift-tests run capi/e2e --monitor event-collector --junit-dir=/tmp/junit

Summary by CodeRabbit

Release Notes

  • New Features

  • Added extension-admission command with install-crd and create subcommands to manage extension permissions

  • Integrated automatic discovery and validation of non-payload extensions during test execution

  • Test results now include failed test cases for unpermitted extensions

  • Refactor

  • Extracted common binary extraction logic into reusable helper methods

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@smg247: This pull request references TRT-2295 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Dev Testing workflow:

# Get a cluster
# (In cluster-bot Slack channel)
mce create 4.21.3 8h aws

# Save kubeconfig and set up environment
export KUBECONFIG="/path/to/ote-testing.kubeconfig" # kubeconfig for mce cluster
export EXTENSIONS_PAYLOAD_OVERRIDE="registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-26-092444"
export EXTENSION_BINARY_OVERRIDE_INCLUDE_TAGS="tests"
export TEST_PROVIDER='{"type":"aws"}'
# Registry auth file contains pullsecrets for registry.redhat.io and registry.ci.openshift.org
export REGISTRY_AUTH_FILE="${HOME}/.docker/config.json"

# Build and push your extension image
cd /path/to/cluster-api-actuator-pkg
git fetch origin pull/423/head:pr-423
git checkout pr-423
# Edit Dockerfile.ci to set GOARCH=arm64
podman build -f Dockerfile.ci -t quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest .
podman push quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest

# Run in container
podman run --platform linux/arm64 \
 --authfile=$HOME/.docker/config.json \
 -it --rm \
 -v $(pwd):/workspace \
 -w /workspace \
 registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.24-openshift-4.22 \
 /bin/bash

# Inside container:
# Install oc
cd /tmp
wget https://mirror.openshift.com/pub/openshift-v4/arm64/clients/ocp-dev-preview/latest/openshift-client-linux-arm64-rhel9.tar.gz
tar xvf openshift-client-linux*.tar.gz
mv oc kubectl /usr/bin

# Build openshift-tests
cd /path/to/origin
make

# Install the CRD using the new command
./openshift-tests extension-admission install-crd

# Create admission policy using the new command
./openshift-tests extension-admission create cluster-api-extensions \
 --permit=test-extensions/*

# Create the ImageStream
# This is the yaml for an NS and ImageStream containing the proper annotations
oc apply -f cluster-api-actuator-pkg-extension.yaml

# Build and test
./openshift-tests run openshift/conformance/parallel --monitor event-collector --junit-dir=/tmp/junit --dry-run
./openshift-tests run capi/e2e --monitor event-collector --junit-dir=/tmp/junit

Summary by CodeRabbit

  • New Features

  • Added an extension-admission CLI with install-crd and create actions to manage extension permissions.

  • Introduced a cluster CRD and API types for TestExtensionAdmission to declare permitted extensions.

  • Automatic discovery of non-payload extensions during test runs; unpermitted extensions are reported as failing test cases.

  • Refactor

  • Consolidated and improved binary extraction logic to support extracting from arbitrary images and non-payload sources.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pkg/test/extensions/provider.go (1)

152-155: Typo in error message: "compatability" → "compatibility".

Suggested fix
 	// Verify the binary is compatible with our architecture
 	if err := checkCompatibleArchitecture(extractedBinary); err != nil {
-		return "", 0, errors.WithMessage(err, "error checking binary architecture compatability")
+		return "", 0, errors.WithMessage(err, "error checking binary architecture compatibility")
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/test/extensions/provider.go` around lines 152 - 155, The error message
passed to errors.WithMessage in the checkCompatibleArchitecture call contains a
typo ("compatability"); update the message string to "error checking binary
architecture compatibility" where errors.WithMessage(err, "error checking binary
architecture compatability") is used (refer to the checkCompatibleArchitecture
invocation and extractedBinary variable) so the log reports the correct
spelling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/test/extensions/provider.go`:
- Around line 152-155: The error message passed to errors.WithMessage in the
checkCompatibleArchitecture call contains a typo ("compatability"); update the
message string to "error checking binary architecture compatibility" where
errors.WithMessage(err, "error checking binary architecture compatability") is
used (refer to the checkCompatibleArchitecture invocation and extractedBinary
variable) so the log reports the correct spelling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 40b2afe2-203f-4bdb-a2a6-a05cb6216383

📥 Commits

Reviewing files that changed from the base of the PR and between c53a075 and 0d16699.

📒 Files selected for processing (7)
  • pkg/apis/testextension/v1/types.go
  • pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go
  • pkg/cmd/openshift-tests/extension-admission/testextensionadmission-crd.yaml
  • pkg/test/extensions/binary.go
  • pkg/test/extensions/non-payload-binary-admission.go
  • pkg/test/extensions/provider.go
  • pkg/test/ginkgo/cmd_runsuite.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go

@openshift-ci-robot
Copy link

Scheduling required tests:
/test e2e-aws-csi
/test e2e-aws-ovn-fips
/test e2e-aws-ovn-microshift
/test e2e-aws-ovn-microshift-serial
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-gcp-csi
/test e2e-gcp-ovn
/test e2e-gcp-ovn-upgrade
/test e2e-metal-ipi-ovn-ipv6
/test e2e-vsphere-ovn
/test e2e-vsphere-ovn-upi

@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 12, 2026

@smg247: This pull request references TRT-2295 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Implements the logic detailed in the enhancement to allow for discovery and extraction of out-of-payload OTE binaries.

Also adds a new subcommand to install the TestExtension CRD and apply the matching CR

Dev Testing workflow:

# Get a cluster
# (In cluster-bot Slack channel)
mce create 4.21.3 8h aws

# Save kubeconfig and set up environment
export KUBECONFIG="/path/to/ote-testing.kubeconfig" # kubeconfig for mce cluster
export EXTENSIONS_PAYLOAD_OVERRIDE="registry.ci.openshift.org/ocp/release:4.22.0-0.nightly-2026-02-26-092444"
export EXTENSION_BINARY_OVERRIDE_INCLUDE_TAGS="tests"
export TEST_PROVIDER='{"type":"aws"}'
# Registry auth file contains pullsecrets for registry.redhat.io and registry.ci.openshift.org
export REGISTRY_AUTH_FILE="${HOME}/.docker/config.json"

# Build and push your extension image
cd /path/to/cluster-api-actuator-pkg
git fetch origin pull/423/head:pr-423
git checkout pr-423
# Edit Dockerfile.ci to set GOARCH=arm64
podman build -f Dockerfile.ci -t quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest .
podman push quay.io/YOUR_USERNAME/cluster-api-actuator-pkg:latest

# Run in container
podman run --platform linux/arm64 \
 --authfile=$HOME/.docker/config.json \
 -it --rm \
 -v $(pwd):/workspace \
 -w /workspace \
 registry.ci.openshift.org/ocp/builder:rhel-9-golang-1.24-openshift-4.22 \
 /bin/bash

# Inside container:
# Install oc
cd /tmp
wget https://mirror.openshift.com/pub/openshift-v4/arm64/clients/ocp-dev-preview/latest/openshift-client-linux-arm64-rhel9.tar.gz
tar xvf openshift-client-linux*.tar.gz
mv oc kubectl /usr/bin

# Build openshift-tests
cd /path/to/origin
make

# Install the CRD using the new command
./openshift-tests extension-admission install-crd

# Create admission policy using the new command
./openshift-tests extension-admission create cluster-api-extensions \
 --permit=test-extensions/*

# Create the ImageStream
# This is the yaml for an NS and ImageStream containing the proper annotations
oc apply -f cluster-api-actuator-pkg-extension.yaml

# Build and test
./openshift-tests run openshift/conformance/parallel --monitor event-collector --junit-dir=/tmp/junit --dry-run
./openshift-tests run capi/e2e --monitor event-collector --junit-dir=/tmp/junit

Summary by CodeRabbit

Release Notes

  • New Features
  • Added extension admission management to OpenShift tests with a new CLI command for installing and creating extension resources.
  • Enabled discovery of extensions with admission control based on permitted image stream patterns.
  • Extensions failing admission checks now appear as reportable items in test results for improved visibility.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@stbenjam
Copy link
Member

Looks great to me!

/lgtm

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go (1)

192-196: Consider checking the error from tmpFile.Close().

For writes, Close() can fail if there's an issue flushing buffered data to disk. While unlikely for small YAML files, it's good practice to check.

♻️ Proposed fix
 	if _, err := tmpFile.Write(yamlBytes); err != nil {
 		tmpFile.Close()
 		return fmt.Errorf("failed to write YAML to temp file: %w", err)
 	}
-	tmpFile.Close()
+	if err := tmpFile.Close(); err != nil {
+		return fmt.Errorf("failed to close temp file: %w", err)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go`
around lines 192 - 196, The code writes YAML bytes to tmpFile using
tmpFile.Write(yamlBytes) but currently ignores errors from tmpFile.Close();
update the function to check and handle Close() errors: after the Write error
path ensure the tmpFile is closed and its Close() error is checked, and on the
normal path replace the un-checked tmpFile.Close() with capturing its error
(e.g., err = tmpFile.Close()) and return a wrapped fmt.Errorf if non-nil;
reference symbols: tmpFile, Write, Close, yamlBytes.
pkg/test/extensions/non_payload_binary_admission.go (1)

120-122: Consider removing the unnecessary wrapper function.

isNotFound simply delegates to apierrors.IsNotFound. Using apierrors.IsNotFound directly would be clearer and remove the indirection.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/test/extensions/non_payload_binary_admission.go` around lines 120 - 122,
The isNotFound wrapper function simply forwards to apierrors.IsNotFound and
should be removed to eliminate indirection; delete the isNotFound function
definition and update all call sites to call apierrors.IsNotFound(err) directly
(search for isNotFound usages in the file and replace them), ensuring imports
remain correct and no references to isNotFound remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go`:
- Around line 192-196: The code writes YAML bytes to tmpFile using
tmpFile.Write(yamlBytes) but currently ignores errors from tmpFile.Close();
update the function to check and handle Close() errors: after the Write error
path ensure the tmpFile is closed and its Close() error is checked, and on the
normal path replace the un-checked tmpFile.Close() with capturing its error
(e.g., err = tmpFile.Close()) and return a wrapped fmt.Errorf if non-nil;
reference symbols: tmpFile, Write, Close, yamlBytes.

In `@pkg/test/extensions/non_payload_binary_admission.go`:
- Around line 120-122: The isNotFound wrapper function simply forwards to
apierrors.IsNotFound and should be removed to eliminate indirection; delete the
isNotFound function definition and update all call sites to call
apierrors.IsNotFound(err) directly (search for isNotFound usages in the file and
replace them), ensuring imports remain correct and no references to isNotFound
remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dbe04d8a-6074-40b4-a821-ca99680ff849

📥 Commits

Reviewing files that changed from the base of the PR and between 0d16699 and d1e2115.

📒 Files selected for processing (2)
  • pkg/cmd/openshift-tests/extension-admission/extension_admission_command.go
  • pkg/test/extensions/non_payload_binary_admission.go

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 12, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: smg247, stbenjam

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Mar 12, 2026
@openshift-ci-robot
Copy link

Scheduling required tests:
/test e2e-aws-csi
/test e2e-aws-ovn-fips
/test e2e-aws-ovn-microshift
/test e2e-aws-ovn-microshift-serial
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-gcp-csi
/test e2e-gcp-ovn
/test e2e-gcp-ovn-upgrade
/test e2e-metal-ipi-ovn-ipv6
/test e2e-vsphere-ovn
/test e2e-vsphere-ovn-upi

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 12, 2026

@smg247: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-csi 0d16699 link true /test e2e-gcp-csi

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants