Skip to content

OCPNODE-3983: Add e2e tests for KubeletEnsureSecretPulledImages feature gate#31102

Open
Chandan9112 wants to merge 1 commit intoopenshift:release-4.22from
Chandan9112:add-kubelet-secret-pulled-images-tests
Open

OCPNODE-3983: Add e2e tests for KubeletEnsureSecretPulledImages feature gate#31102
Chandan9112 wants to merge 1 commit intoopenshift:release-4.22from
Chandan9112:add-kubelet-secret-pulled-images-tests

Conversation

@Chandan9112
Copy link
Copy Markdown
Contributor

@Chandan9112 Chandan9112 commented Apr 30, 2026

Summary

  • Automates all test scenarios from OCPNODE-3982 for the Ensure Secret Pull Images feature
  • Covers multi-tenancy isolation, credential rotation, ImagePullPolicy, credential verification policy, and registry availability scenarios
  • Uses OpenShift internal image registry and dynamic SA pull secrets

Test Cases

  1. Multi-tenancy isolation – private/public image access across namespaces
  2. Credential rotation – secret hash mismatch and secret coordinates mismatch
  3. ImagePullPolicy – IfNotPresent, Never, Always behavior
  4. Credential verification policy – NeverVerify, AlwaysVerify
  5. Registry availability – cached pull-records vs new credentials when registry is down

Prerequisites

  • Requires KubeletEnsureSecretPulledImages feature gate to be enabled
  • Cluster must have TechPreviewNoUpgrade or CustomNoUpgrade FeatureSet
  • Tests are annotated with [OCPFeatureGate:KubeletEnsureSecretPulledImages] and will be skipped automatically on clusters without the feature gate enabled

Testing Result

Tested on latest 4.22 OCP cluster

➜ oc version
Client Version: 4.21.0
Kustomize Version: v5.7.1
Server Version: 4.22.0-0.nightly-2026-04-27-194825
Kubernetes Version: v1.35.3

➜ oc get featuregate cluster -o jsonpath='{.spec}'
{"customNoUpgrade":{"enabled":["KubeletEnsureSecretPulledImages"]},"featureSet":"CustomNoUpgrade"}%                                                  

Case 1: 

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 1: Multi-tenancy isolation for private and public images"

    STEP: Verifying tenant-a can pull private image with valid secret @ 04/30/26 12:40:38.661
    STEP: Verifying tenant-b cannot pull private image without secret @ 04/30/26 12:40:41.722
    STEP: Verifying tenant-a can pull public image without secret @ 04/30/26 12:40:44.726
    STEP: Verifying tenant-b can pull same public image without secret @ 04/30/26 12:40:47.935
  • [20.647 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 20.648 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 2:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 2: Credential rotation"

 STEP: Pulling private image with secret-v1 to establish pull record on the node @ 04/30/26 12:41:17.321
    STEP: Verifying pod succeeds when secret hash matches but secret coordinates differ @ 04/30/26 12:41:20.445
    STEP: Verifying pod succeeds when secret coordinates match but secret hash differs @ 04/30/26 12:41:24.155
  I0430 12:41:24.902518 58252 kubelet_secret_pulled_images.go:359] Extracted SA credentials, user=<token>
  • [18.801 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 18.801 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 3:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 3: ImagePullPolicy scenarios"

    STEP: Verifying IfNotPresent ImagePullPolicy with valid secret pulls and caches the image @ 04/30/26 12:41:51.136
    STEP: Verifying Never ImagePullPolicy with valid secret uses cached image @ 04/30/26 12:41:54.211
    STEP: Verifying Always ImagePullPolicy with valid secret re-pulls the image @ 04/30/26 12:41:57.338
  • [16.850 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 16.851 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 4:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 4: Credential verification policy [Slow]"

STEP: Pre-caching private image on the node with a valid secret @ 04/30/26 13:24:28.309
STEP: Applying NeverVerify policy and waiting for MCO rollout @ 04/30/26 13:24:31.349
  I0430 13:24:43.248742 64108 node_utils.go:522] Waiting for MCP worker to be ready (timeout: 30m0s)...
  I0430 13:24:43.630075 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=0/3
  I0430 13:33:33.642781 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=1/3
  I0430 13:33:43.632152 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=2/3
  I0430 13:39:24.613653 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
STEP: Verifying NeverVerify policy allows pod without secret to use cached image @ 04/30/26 13:39:24.616
STEP: Switching to AlwaysVerify policy and waiting for MCO rollout @ 04/30/26 13:39:27.673
 I0430 13:45:19.473074 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=0/3
  I0430 14:00:57.687670 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
STEP: Verifying AlwaysVerify policy allows pod with valid secret @ 04/30/26 14:00:57.687
STEP: Verifying AlwaysVerify policy blocks pod without valid secret @ 04/30/26 14:05:19.669
  kubeletconfig.machineconfiguration.openshift.io "cred-verify-policy" deleted
  I0430 14:05:24.264526 64108 node_utils.go:522] Waiting for MCP worker to be ready (timeout: 30m0s)...
  I0430 14:05:24.572942 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
  • [1226.487 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 1226.489 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 5:

/openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 5: Registry availability"

STEP: Caching private image then making the registry unavailable @ 04/30/26 12:42:21.2
  deployment.apps/image-registry scaled
  Waiting for deployment "image-registry" rollout to finish: 0 of 2 updated replicas are available...
  Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
  Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
  Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
  deployment "image-registry" successfully rolled out
STEP: Verifying cached pull-record works when registry is down @ 04/30/26 12:43:14.358
STEP: Verifying new credentials fail when registry is down @ 04/30/26 12:43:17.371
  deployment.apps/image-registry scaled
  • [68.573 seconds]
  ------------------------------

  Ran 1 of 1 Specs in 68.574 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

References

Summary by CodeRabbit

  • Tests
    • Added a comprehensive disruptive node test suite that validates kubelet credential verification and image-pull behavior across scenarios: multi-tenant isolation for private/public images, secret rotation effects, ImagePullPolicy modes (IfNotPresent/Never/Always), KubeletConfig-driven verification transitions coordinated with node pool updates, and cached versus fresh pull behavior when the registry is unavailable.

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

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

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 30, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 30, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: 04a883ac-0bb8-425e-85a5-1986ffd84b3f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds a new Ginkgo node test that validates kubelet image-pull credential verification and caching across scenarios: multi-tenant isolation, secret rotation, imagePullPolicy modes, KubeletConfig verification policy changes with MCP rollout, and registry availability impacts.

Changes

Cohort / File(s) Summary
Kubelet Secret Pulled Images Test Suite
test/extended/node/kubelet_secret_pulled_images.go
New long-running Ginkgo node test (≈471 lines). Implements five ordered scenarios exercising kubelet credential verification and cached pull-record behavior: multi-tenancy, secret rotation (name vs content changes), ImagePullPolicy modes (IfNotPresent/Never/Always), KubeletConfig verification policy transitions (NeverVerify ↔ AlwaysVerify) with MachineConfigPool coordination, and registry scaling/cached-pull validation. Includes helpers for namespace and RBAC setup, dockerconfig secret creation/extraction, test pod generation, pod failure assertions, KubeletConfig application, and MCP wait logic.

Sequence Diagram(s)

sequenceDiagram
  participant Test as Test Harness
  participant APIServer as Kubernetes API
  participant Kubelet as Node Kubelet
  participant Registry as Internal Registry
  participant MCP as MachineConfigPool

  Test->>APIServer: create namespaces, imagestream tag, extract secret
  Test->>APIServer: create pods referencing secrets / imagePullPolicy
  APIServer->>Kubelet: schedule Pod spec
  Kubelet->>Registry: attempt image pull (uses secret or cached pull-record)
  Registry-->>Kubelet: respond (success / unauthorized / unavailable)
  alt KubeletConfig change
    Test->>APIServer: apply KubeletConfig (NeverVerify/AlwaysVerify)
    APIServer->>MCP: rollout config
    MCP-->>Kubelet: kubelet restarts with new policy
  end
  Kubelet-->>APIServer: report Pod status (Running / ErrImagePull / ImagePullBackOff)
  Test->>APIServer: scale registry (to zero) and validate cached vs new pulls
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 8 | ❌ 4

❌ Failed checks (4 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ⚠️ Warning Test file contains 22 assertions lacking meaningful failure context messages, violating test quality best practices for maintainability and CI diagnostics. Add meaningful failure messages to all 22 Expect assertions by providing descriptive second string arguments explaining what failed for clarity in CI logs.
Microshift Test Compatibility ⚠️ Warning Test uses MicroShift-incompatible APIs (ImageStream, KubeletConfig, MachineConfigPool) and feature gates without proper protective labels ([Skipped:MicroShift] or [apigroup:...]) on the test name. Add [Skipped:MicroShift] label to test name or [apigroup:machineconfiguration.openshift.io] tag to enable automatic MicroShift CI skipping for unavailable APIs.
Single Node Openshift (Sno) Test Compatibility ⚠️ Warning Test assumes multiple worker nodes exist by selecting a worker node, applying MachineConfigPool updates, and expecting pod rescheduling during kubelet restarts, which is incompatible with Single Node OpenShift. Add Single Node OpenShift compatibility check: use [Skipped:SingleReplicaTopology] label, exutil.IsSingleNode() check with g.Skip(), or verify infrastructure.Status.ControlPlaneTopology for single-node topology mode.
✅ Passed checks (8 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: adding e2e tests for the KubeletEnsureSecretPulledImages feature gate, which aligns with the changeset that introduces a comprehensive test suite for this feature.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed All test titles in kubelet_secret_pulled_images.go use static string literals without dynamic values, variable references, or format specifiers.
Topology-Aware Scheduling Compatibility ✅ Passed PR adds only a Ginkgo-based test file (test/extended/node/kubelet_secret_pulled_images.go) with 471 lines. Custom check applies to deployment manifests, operator code, or controllers—not test code.
Ote Binary Stdout Contract ✅ Passed The test file contains only Ginkgo v2 test blocks with no process-level stdout writes that violate the OTE Binary Stdout Contract.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Test file contains no IPv4 hardcoded addresses, no external connectivity requirements, and no IPv4-specific network assumptions. All images sourced from cluster-internal registry.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@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: 2

🧹 Nitpick comments (1)
test/extended/node/kubelet_secret_pulled_images.go (1)

409-425: ⚡ Quick win

Consider folding the MCP transition polling into the shared helper.

This local helper duplicates MCP condition polling that already exists in test/extended/node/node_utils.go:521-570. Extending the shared wait path to support “must observe Updating=True before waiting for ready” would keep rollout semantics in one place and avoid the two implementations drifting on degraded/updated handling.

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

In `@test/extended/node/kubelet_secret_pulled_images.go` around lines 409 - 425,
The function credVerifyWaitForMCPUpdating duplicates MCP polling; remove it and
extend the existing shared helper waitForMCP (in node_utils.go) to accept an
option/flag (e.g., requireObserveUpdating bool or a policy enum) that first
polls for condition Type "Updating" == True and only then proceeds with the
existing wait-for-ready semantics; update callers (including where
credVerifyWaitForMCPUpdating was used) to call waitForMCP with the new option so
all MCP transition logic remains centralized and avoids duplicated/ drifting
implementations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/extended/node/kubelet_secret_pulled_images.go`:
- Around line 27-30: Replace the Docker Hub mutable image references with
pinned, internally-hosted images: change the constant credVerifyPublicImage from
"docker.io/library/nginx:alpine" to a registry-controlled, immutable image
(preferably using a digest) served by the cluster image-registry (use
internalRegistryPrefix as the prefix and point to a specific repo@sha256:...
digest); update the seed import lines referenced around 71-74 likewise to pull
from the internal registry and pin by digest (do not use :latest or other
mutable tags) so all pulls come from the environment-controlled registry and are
immutable.
- Around line 251-257: Before scaling the image-registry down, query and store
its current replica count (e.g., via
oc.AsAdmin().WithoutNamespace().Run("get").Args("deployment/image-registry",
"-n", "openshift-image-registry", "-o", "jsonpath={.spec.replicas}") or
equivalent) and then use that stored value in the g.DeferCleanup closure instead
of the hard-coded "--replicas=2"; in the cleanup closure call
oc.AsAdmin().WithoutNamespace().Run("scale").Args("deployment/image-registry",
"-n", "openshift-image-registry", fmt.Sprintf("--replicas=%d",
originalReplicas)) and then wait for completion with
oc.AsAdmin().WithoutNamespace().Run("rollout").Args("status",
"deployment/image-registry", "-n", "openshift-image-registry",
"--timeout=2m").Execute() to ensure the registry is restored to its exact prior
size and the test waits for rollout.

---

Nitpick comments:
In `@test/extended/node/kubelet_secret_pulled_images.go`:
- Around line 409-425: The function credVerifyWaitForMCPUpdating duplicates MCP
polling; remove it and extend the existing shared helper waitForMCP (in
node_utils.go) to accept an option/flag (e.g., requireObserveUpdating bool or a
policy enum) that first polls for condition Type "Updating" == True and only
then proceeds with the existing wait-for-ready semantics; update callers
(including where credVerifyWaitForMCPUpdating was used) to call waitForMCP with
the new option so all MCP transition logic remains centralized and avoids
duplicated/ drifting implementations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 6c10e20a-d25e-473b-9257-be65b6405b54

📥 Commits

Reviewing files that changed from the base of the PR and between 231811f and f75db07.

📒 Files selected for processing (1)
  • test/extended/node/kubelet_secret_pulled_images.go

Comment on lines +27 to +30
// credVerifyPublicImage is a publicly available image used in multi-tenancy tests
credVerifyPublicImage = "docker.io/library/nginx:alpine"
// internalRegistryPrefix is the OpenShift internal registry service address
internalRegistryPrefix = "image-registry.openshift-image-registry.svc:5000"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid Docker Hub and mutable tags in this suite.

credVerifyPublicImage and the seed import both depend on anonymous pulls from Docker Hub, and busybox:latest also makes the test behavior drift as that tag moves. For a disruptive long-running e2e, that is an easy source of flakes from rate limits, outages, or image changes unrelated to this feature. Please pin immutable images and source them from a registry the test environment controls.

Also applies to: 71-74

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

In `@test/extended/node/kubelet_secret_pulled_images.go` around lines 27 - 30,
Replace the Docker Hub mutable image references with pinned, internally-hosted
images: change the constant credVerifyPublicImage from
"docker.io/library/nginx:alpine" to a registry-controlled, immutable image
(preferably using a digest) served by the cluster image-registry (use
internalRegistryPrefix as the prefix and point to a specific repo@sha256:...
digest); update the seed import lines referenced around 71-74 likewise to pull
from the internal registry and pin by digest (do not use :latest or other
mutable tags) so all pulls come from the environment-controlled registry and are
immutable.

Comment thread test/extended/node/kubelet_secret_pulled_images.go Outdated
@Chandan9112 Chandan9112 changed the title Add e2e tests for KubeletEnsureSecretPulledImages feature gate OCPNODE-3983 : Add e2e tests for KubeletEnsureSecretPulledImages feature gate Apr 30, 2026
@Chandan9112 Chandan9112 changed the title OCPNODE-3983 : Add e2e tests for KubeletEnsureSecretPulledImages feature gate OCPNODE-3983: Add e2e tests for KubeletEnsureSecretPulledImages feature gate Apr 30, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Apr 30, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Apr 30, 2026

@Chandan9112: This pull request references OCPNODE-3983 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 "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Automates all test scenarios from OCPNODE-3982 for the Ensure Secret Pull Images feature
  • Covers multi-tenancy isolation, credential rotation, ImagePullPolicy, credential verification policy, and registry availability scenarios
  • Uses OpenShift internal image registry and dynamic SA pull secrets

Test Cases

  1. Multi-tenancy isolation – private/public image access across namespaces
  2. Credential rotation – secret hash mismatch and secret coordinates mismatch
  3. ImagePullPolicy – IfNotPresent, Never, Always behavior
  4. Credential verification policy – NeverVerify, AlwaysVerify
  5. Registry availability – cached pull-records vs new credentials when registry is down

Prerequisites

  • Requires KubeletEnsureSecretPulledImages feature gate to be enabled
  • Cluster must have TechPreviewNoUpgrade or CustomNoUpgrade FeatureSet
  • Tests are annotated with [OCPFeatureGate:KubeletEnsureSecretPulledImages] and will be skipped automatically on clusters without the feature gate enabled

Testing Result

Tested on latest 4.22 OCP cluster

➜ oc version
Client Version: 4.21.0
Kustomize Version: v5.7.1
Server Version: 4.22.0-0.nightly-2026-04-27-194825
Kubernetes Version: v1.35.3

➜ oc get featuregate cluster -o jsonpath='{.spec}'
{"customNoUpgrade":{"enabled":["KubeletEnsureSecretPulledImages"]},"featureSet":"CustomNoUpgrade"}%                                                  

Case 1: 

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 1: Multi-tenancy isolation for private and public images"

   STEP: Verifying tenant-a can pull private image with valid secret @ 04/30/26 12:40:38.661
   STEP: Verifying tenant-b cannot pull private image without secret @ 04/30/26 12:40:41.722
   STEP: Verifying tenant-a can pull public image without secret @ 04/30/26 12:40:44.726
   STEP: Verifying tenant-b can pull same public image without secret @ 04/30/26 12:40:47.935
 • [20.647 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 20.648 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 2:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 2: Credential rotation"

STEP: Pulling private image with secret-v1 to establish pull record on the node @ 04/30/26 12:41:17.321
   STEP: Verifying pod succeeds when secret hash matches but secret coordinates differ @ 04/30/26 12:41:20.445
   STEP: Verifying pod succeeds when secret coordinates match but secret hash differs @ 04/30/26 12:41:24.155
 I0430 12:41:24.902518 58252 kubelet_secret_pulled_images.go:359] Extracted SA credentials, user=<token>
 • [18.801 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 18.801 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 3:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 3: ImagePullPolicy scenarios"

   STEP: Verifying IfNotPresent ImagePullPolicy with valid secret pulls and caches the image @ 04/30/26 12:41:51.136
   STEP: Verifying Never ImagePullPolicy with valid secret uses cached image @ 04/30/26 12:41:54.211
   STEP: Verifying Always ImagePullPolicy with valid secret re-pulls the image @ 04/30/26 12:41:57.338
 • [16.850 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 16.851 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 4:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 4: Credential verification policy [Slow]"

STEP: Pre-caching private image on the node with a valid secret @ 04/30/26 13:24:28.309
STEP: Applying NeverVerify policy and waiting for MCO rollout @ 04/30/26 13:24:31.349
 I0430 13:24:43.248742 64108 node_utils.go:522] Waiting for MCP worker to be ready (timeout: 30m0s)...
 I0430 13:24:43.630075 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=0/3
 I0430 13:33:33.642781 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=1/3
 I0430 13:33:43.632152 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=2/3
 I0430 13:39:24.613653 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
STEP: Verifying NeverVerify policy allows pod without secret to use cached image @ 04/30/26 13:39:24.616
STEP: Switching to AlwaysVerify policy and waiting for MCO rollout @ 04/30/26 13:39:27.673
I0430 13:45:19.473074 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=0/3
 I0430 14:00:57.687670 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
STEP: Verifying AlwaysVerify policy allows pod with valid secret @ 04/30/26 14:00:57.687
STEP: Verifying AlwaysVerify policy blocks pod without valid secret @ 04/30/26 14:05:19.669
 kubeletconfig.machineconfiguration.openshift.io "cred-verify-policy" deleted
 I0430 14:05:24.264526 64108 node_utils.go:522] Waiting for MCP worker to be ready (timeout: 30m0s)...
 I0430 14:05:24.572942 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
 • [1226.487 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 1226.489 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 5:

/openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 5: Registry availability"

STEP: Caching private image then making the registry unavailable @ 04/30/26 12:42:21.2
 deployment.apps/image-registry scaled
 Waiting for deployment "image-registry" rollout to finish: 0 of 2 updated replicas are available...
 Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
 Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
 Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
 deployment "image-registry" successfully rolled out
STEP: Verifying cached pull-record works when registry is down @ 04/30/26 12:43:14.358
STEP: Verifying new credentials fail when registry is down @ 04/30/26 12:43:17.371
 deployment.apps/image-registry scaled
 • [68.573 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 68.574 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

References

Summary by CodeRabbit

Release Notes

  • Tests
  • Added comprehensive test suite validating kubelet credential verification and image pull behavior across multiple scenarios including private/public image access patterns, secret rotation handling, image pull policy variations, KubeletConfig-driven credential policy transitions coordinated with node pool updates, and cached versus fresh credential scenarios.

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
Copy Markdown

openshift-ci-robot commented Apr 30, 2026

@Chandan9112: This pull request references OCPNODE-3983 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 either version "5.0." or "openshift-5.0.", but it targets "openshift-4.22" instead.

Details

In response to this:

Summary

  • Automates all test scenarios from OCPNODE-3982 for the Ensure Secret Pull Images feature
  • Covers multi-tenancy isolation, credential rotation, ImagePullPolicy, credential verification policy, and registry availability scenarios
  • Uses OpenShift internal image registry and dynamic SA pull secrets

Test Cases

  1. Multi-tenancy isolation – private/public image access across namespaces
  2. Credential rotation – secret hash mismatch and secret coordinates mismatch
  3. ImagePullPolicy – IfNotPresent, Never, Always behavior
  4. Credential verification policy – NeverVerify, AlwaysVerify
  5. Registry availability – cached pull-records vs new credentials when registry is down

Prerequisites

  • Requires KubeletEnsureSecretPulledImages feature gate to be enabled
  • Cluster must have TechPreviewNoUpgrade or CustomNoUpgrade FeatureSet
  • Tests are annotated with [OCPFeatureGate:KubeletEnsureSecretPulledImages] and will be skipped automatically on clusters without the feature gate enabled

Testing Result

Tested on latest 4.22 OCP cluster

➜ oc version
Client Version: 4.21.0
Kustomize Version: v5.7.1
Server Version: 4.22.0-0.nightly-2026-04-27-194825
Kubernetes Version: v1.35.3

➜ oc get featuregate cluster -o jsonpath='{.spec}'
{"customNoUpgrade":{"enabled":["KubeletEnsureSecretPulledImages"]},"featureSet":"CustomNoUpgrade"}%                                                  

Case 1: 

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 1: Multi-tenancy isolation for private and public images"

   STEP: Verifying tenant-a can pull private image with valid secret @ 04/30/26 12:40:38.661
   STEP: Verifying tenant-b cannot pull private image without secret @ 04/30/26 12:40:41.722
   STEP: Verifying tenant-a can pull public image without secret @ 04/30/26 12:40:44.726
   STEP: Verifying tenant-b can pull same public image without secret @ 04/30/26 12:40:47.935
 • [20.647 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 20.648 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 2:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 2: Credential rotation"

STEP: Pulling private image with secret-v1 to establish pull record on the node @ 04/30/26 12:41:17.321
   STEP: Verifying pod succeeds when secret hash matches but secret coordinates differ @ 04/30/26 12:41:20.445
   STEP: Verifying pod succeeds when secret coordinates match but secret hash differs @ 04/30/26 12:41:24.155
 I0430 12:41:24.902518 58252 kubelet_secret_pulled_images.go:359] Extracted SA credentials, user=<token>
 • [18.801 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 18.801 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 3:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 3: ImagePullPolicy scenarios"

   STEP: Verifying IfNotPresent ImagePullPolicy with valid secret pulls and caches the image @ 04/30/26 12:41:51.136
   STEP: Verifying Never ImagePullPolicy with valid secret uses cached image @ 04/30/26 12:41:54.211
   STEP: Verifying Always ImagePullPolicy with valid secret re-pulls the image @ 04/30/26 12:41:57.338
 • [16.850 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 16.851 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 4:

./openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 4: Credential verification policy [Slow]"

STEP: Pre-caching private image on the node with a valid secret @ 04/30/26 13:24:28.309
STEP: Applying NeverVerify policy and waiting for MCO rollout @ 04/30/26 13:24:31.349
 I0430 13:24:43.248742 64108 node_utils.go:522] Waiting for MCP worker to be ready (timeout: 30m0s)...
 I0430 13:24:43.630075 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=0/3
 I0430 13:33:33.642781 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=1/3
 I0430 13:33:43.632152 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=2/3
 I0430 13:39:24.613653 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
STEP: Verifying NeverVerify policy allows pod without secret to use cached image @ 04/30/26 13:39:24.616
STEP: Switching to AlwaysVerify policy and waiting for MCO rollout @ 04/30/26 13:39:27.673
I0430 13:45:19.473074 64108 node_utils.go:564] MachineConfigPool worker not ready yet: updating=true, ready=false, machines=0/3
 I0430 14:00:57.687670 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
STEP: Verifying AlwaysVerify policy allows pod with valid secret @ 04/30/26 14:00:57.687
STEP: Verifying AlwaysVerify policy blocks pod without valid secret @ 04/30/26 14:05:19.669
 kubeletconfig.machineconfiguration.openshift.io "cred-verify-policy" deleted
 I0430 14:05:24.264526 64108 node_utils.go:522] Waiting for MCP worker to be ready (timeout: 30m0s)...
 I0430 14:05:24.572942 64108 node_utils.go:561] MachineConfigPool worker is ready: 3/3 machines ready
 • [1226.487 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 1226.489 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

Case 5:

/openshift-tests run-test "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][OCPFeatureGate:KubeletEnsureSecretPulledImages][Serial] Case 5: Registry availability"

STEP: Caching private image then making the registry unavailable @ 04/30/26 12:42:21.2
 deployment.apps/image-registry scaled
 Waiting for deployment "image-registry" rollout to finish: 0 of 2 updated replicas are available...
 Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
 Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
 Waiting for deployment "image-registry" rollout to finish: 1 of 2 updated replicas are available...
 deployment "image-registry" successfully rolled out
STEP: Verifying cached pull-record works when registry is down @ 04/30/26 12:43:14.358
STEP: Verifying new credentials fail when registry is down @ 04/30/26 12:43:17.371
 deployment.apps/image-registry scaled
 • [68.573 seconds]
 ------------------------------

 Ran 1 of 1 Specs in 68.574 seconds
 SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped

References

Summary by CodeRabbit

  • Tests
  • Added a comprehensive disruptive node test suite that validates kubelet credential verification and image-pull behavior across scenarios: multi-tenant isolation for private/public images, secret rotation effects, ImagePullPolicy modes (IfNotPresent/Never/Always), KubeletConfig-driven verification transitions coordinated with node pool updates, and cached versus fresh pull behavior when the registry is unavailable.

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.

@Chandan9112 Chandan9112 changed the base branch from main to release-4.22 April 30, 2026 13:04
@Chandan9112 Chandan9112 changed the base branch from release-4.22 to main April 30, 2026 13:08
@Chandan9112 Chandan9112 changed the base branch from main to release-4.22 April 30, 2026 13:31
@Chandan9112 Chandan9112 force-pushed the add-kubelet-secret-pulled-images-tests branch from 179ba2d to 57ed3a2 Compare April 30, 2026 13:33
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 30, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Chandan9112
Once this PR has been reviewed and has the lgtm label, please assign cpmeadors for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@Chandan9112 Chandan9112 marked this pull request as ready for review April 30, 2026 13:38
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 30, 2026
@Chandan9112 Chandan9112 force-pushed the add-kubelet-secret-pulled-images-tests branch from 57ed3a2 to 63b9239 Compare April 30, 2026 13:48
@ngopalak-redhat
Copy link
Copy Markdown
Contributor

/payload-job periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 30, 2026

@ngopalak-redhat: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/3cb375d0-44a6-11f1-837c-4e7f0d7ef13a-0

credVerifyCreateSecret(ctx, oc, ns, "secret-v1", pullSecret)

g.By("Pulling private image with secret-v1 to establish pull record on the node")
credVerifyRunPod(ctx, oc, credVerifyPod(ns, "pod-initial-pull", privateImage, workerNode, corev1.PullIfNotPresent, "secret-v1"))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If this fails is the secret deleted?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would the secret need to be deleted?

},
}
_, err := oc.AdminKubeClient().CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
if apierrors.IsAlreadyExists(err) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the namespace exists ensure that it has the required labels

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added in latest commit. credVerifyEnsureNamespace now applies the required labels when namespace already exist.

…re gate

Automates 14 test scenarios from OCPNODE-3982 covering:
- Multi-tenancy isolation for private and public images
- Credential rotation (secret hash and coordinates)
- ImagePullPolicy (IfNotPresent, Never, Always)
- Credential verification policy (NeverVerify, AlwaysVerify)
- Registry availability (cached pull-records vs new credentials)
@Chandan9112 Chandan9112 force-pushed the add-kubelet-secret-pulled-images-tests branch from 63b9239 to 7e09a28 Compare May 4, 2026 06:05
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 4, 2026

@Chandan9112: all tests passed!

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.

@ngopalak-redhat
Copy link
Copy Markdown
Contributor

@Chandan9112 Can you add the link to the job that actually runs this test case?

@Chandan9112
Copy link
Copy Markdown
Contributor Author

@Chandan9112 Can you add the link to the job that actually runs this test case?

CI job: https://prow.ci.openshift.org/view/gs/test-platform-results/logs/openshift-origin-31102-nightly-4.22-e2e-aws-disruptive-longrunning/2049868133291790336

The tests are skipped in this job because the cluster doesn't have the KubeletEnsureSecretPulledImages feature gate enabled (requires TechPreviewNoUpgrade or CustomNoUpgrade FeatureSet).

@Chandan9112
Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 5, 2026

@Chandan9112: trigger 2 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview-1of2
  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview-2of2

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/39bdf220-484c-11f1-96b2-66597a73dafb-0

@Chandan9112
Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 5, 2026

@Chandan9112: trigger 2 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview-1of2
  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview-2of2

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/0a664830-4868-11f1-9015-6470e27966d2-0

@Chandan9112
Copy link
Copy Markdown
Contributor Author

/payload-job periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 5, 2026

@Chandan9112: trigger 2 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview-1of2
  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-disruptive-longrunning-techpreview-2of2

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/6a85c3b0-4879-11f1-9d80-723c8c0f052f-0

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

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants