Skip to content

[OCPNODE-4505]: Automation creation of OCP-57401#31142

Open
asahay19 wants to merge 1 commit intoopenshift:mainfrom
asahay19:4505
Open

[OCPNODE-4505]: Automation creation of OCP-57401#31142
asahay19 wants to merge 1 commit intoopenshift:mainfrom
asahay19:4505

Conversation

@asahay19
Copy link
Copy Markdown
Contributor

@asahay19 asahay19 commented May 7, 2026

PR Summary

This test automates manual test case OCP-57401 by verifying end-to-end creation of both ImageDigestMirrorSet (IDMS) and ImageTagMirrorSet (ITMS) resources. It creates an IDMS and ITMS with both AllowContactingSource and NeverContactSource mirror policies, waits for MachineConfigPool rollouts, and then validates that /etc/containers/registries.conf on a worker node contains the correct digest-only and tag-only mirror entries along with blocked = true for NeverContactSource registries.

This test is already present in openshift-test-private. As part of migrating test cases , I am automating it origin.
Polarian Link: https://polarion.engineering.redhat.com/polarion/#/project/OSE/workitem?id=OCP-57401
Jira task : https://redhat.atlassian.net/browse/OCPNODE-4505

Output
Tested locally on 4.22 openshift cluster and it got passed.

./openshift-tests run-test '[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][Serial] ImageTagMirrorSet and ImageDigestMirrorSet [OTP] Create ImageDigestMirrorSet and ImageTagMirrorSet and verify registries.conf [OCP-57401]'

  Ran 1 of 1 Specs in 1274.887 seconds
  SUCCESS! -- 1 Passed | 0 Failed | 0 Pending | 0 Skipped
[
  {
    "name": "[sig-node][Suite:openshift/disruptive-longrunning][Disruptive][Serial] ImageTagMirrorSet and ImageDigestMirrorSet [OTP] Create ImageDigestMirrorSet and ImageTagMirrorSet and verify registries.conf [OCP-57401]",
    "lifecycle": "blocking",
    "duration": 1274888,
    "startTime": "2026-05-07 07:50:46.647072 UTC",
    "endTime": "2026-05-07 08:12:01.535488 UTC",
    "result": "passed",
    "output": "  STEP:

PTAL @cpmeadors @BhargaviGudi

Summary by CodeRabbit

  • Tests
    • Added a new end-to-end test suite validating ImageTagMirrorSet and ImageDigestMirrorSet behavior: ensures mirror entries and pull-from-mirror modes (digest-only, tag-only), verifies non-mirrored sources are blocked, confirms registry configuration is present on a ready worker node, and checks Machine Config Pool rollout and cleanup occur successfully.
  • Tests
    • Added test utilities to locate a ready worker node and to validate registry blocking in configuration files.

@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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Walkthrough

Adds a Ginkgo serial disruptive-longrunning e2e test that creates ImageDigestMirrorSet and ImageTagMirrorSet, waits for MCP rollouts on worker and master, reads /etc/containers/registries.conf from a ready worker, asserts mirror locations and pull-from-mirror semantics, verifies blocked NeverContactSource entries, and cleans up. Two node/helper functions added.

Changes

ImageMirrorSet E2E Test & Node Helpers

Layer / File(s) Summary
Test Suite
test/extended/node/node_e2e/node.go
New Ginkgo serial disruptive-longrunning test: creates an ImageDigestMirrorSet and an ImageTagMirrorSet, skips on MicroShift clusters, waits for MCP spec rollout completion for both worker and master, reads /etc/containers/registries.conf from a worker, asserts expected location and pull-from-mirror values, calls registry block verification, and defers deletion of mirror sets with MCP spec reversion waits.
Helper Usage (in test)
test/extended/node/node_e2e/node.go
Uses node helper functions to select the target node and to validate blocked registry entries in registries.conf.
Node Helpers
test/extended/node/node_utils.go
Adds GetFirstReadyWorkerNode(oc *exutil.CLI) string to list worker nodes and return the first with Ready condition True. Adds VerifyRegistryBlocked(registriesConf string, registrySource string) to locate a location = "<registrySource>" stanza in the provided registries.conf content and assert a corresponding blocked = true directive exists.
Imports / Wiring
test/extended/node/node_e2e/node.go
Updates imports to include configv1, imagepolicy, utilrand, and context to support new test logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

🚥 Pre-merge checks | ✅ 11 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Single Node Openshift (Sno) Test Compatibility ⚠️ Warning Test assumes worker nodes exist. GetFirstReadyWorkerNode requires 'node-role.kubernetes.io/worker' labeled nodes unavailable on SNO. Will fail with 'no worker nodes found'. Lacks SNO protection. Add SNO skip: use [Skipped:SingleReplicaTopology] label, add IsSingleNode() check with g.Skip(), or guard worker node code with exutil.IsSingleNode().
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references a Jira ticket (OCPNODE-4505) and a test case number (OCP-57401) that clearly relates to the PR objective of automating test case OCP-57401.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
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 Both test titles are stable with no dynamic values, timestamps, or identifiers that change between runs.
Test Structure And Quality ✅ Passed Test satisfies all criteria: single responsibility, proper cleanup, appropriate timeouts, meaningful assertion messages, and consistency with codebase. Review item addressed at test level.
Microshift Test Compatibility ✅ Passed Test includes MicroShift protection via BeforeEach hook with exutil.IsMicroShiftCluster() check and g.Skip(). This is an approved protective mechanism per custom check requirements.
Topology-Aware Scheduling Compatibility ✅ Passed This PR adds test code, not deployment manifests, operator code, or controllers. The custom check scope explicitly applies only to those categories.
Ote Binary Stdout Contract ✅ Passed Code runs within Ginkgo test blocks only. All logging uses framework-managed functions (e2e.Logf, framework.Logf) that are intercepted by the test framework. No process-level stdout writes detected.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Test contains no IPv4 assumptions or external connectivity requirements. All operations are cluster-internal with no actual image pulls or external registry connections.

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

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

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.

@openshift-ci openshift-ci Bot requested review from cpmeadors and mrunalp May 7, 2026 08:31
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/extended/node/node_e2e/node.go`:
- Around line 331-332: In verifyRegistryBlocked, replace the fixed "j >= i-5"
backward line-limit with a scan that continues until you hit the previous
registry boundary or start of file: starting from j := i-1 loop while j >= 0 and
!strings.Contains(lines[j], "[[registry]]") (stop before the prior
"[[registry]]") and check for strings.Contains(lines[j], "blocked = true"); do
the same for the symmetric forward scan (the other occurrence around lines
340-341) so both searches stop at the neighboring "[[registry]]" block marker
instead of a hard ±5 line window.
- Around line 182-183: The test uses fixed cluster-scoped mirror-set names
"digest-mirror" and "tag-mirror" which can collide between runs; change the code
that constructs those mirror-set resource Names to append a unique suffix (e.g.,
test run id, timestamp, or random string) so each invocation creates
uniquely-named mirror-sets, and propagate that generated name to all places that
reference "digest-mirror" and "tag-mirror" (the mirror-set creation structs and
any subsequent lookups/assertions) so tests no longer fail with AlreadyExists
from leftover artifacts.
🪄 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: 2dc75fc1-8480-42ae-b540-eab4ad3c4e55

📥 Commits

Reviewing files that changed from the base of the PR and between 65324f7 and e5944f9.

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

Comment thread test/extended/node/node_e2e/node.go Outdated
Comment thread test/extended/node/node_e2e/node.go Outdated
Comment thread test/extended/node/node_e2e/node.go Outdated
@openshift-merge-bot
Copy link
Copy Markdown
Contributor

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 openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 7, 2026
Comment thread test/extended/node/node_e2e/node.go Outdated
initialWorkerSpec := imagepolicy.GetMCPCurrentSpecConfigName(oc, "worker")
initialMasterSpec := imagepolicy.GetMCPCurrentSpecConfigName(oc, "master")

createdIDMS, err := configClient.ImageDigestMirrorSets().Create(ctx, idms, metav1.CreateOptions{})
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.

Coderabbit pointed out that this could fail with AlreadExists. Why not use Apply() rather than create? or you need to check it if exists first before create.

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.

Yeah, I addressed CodeRabbit comments. Resource names now include a random suffix via utilrand.String(5) (e.g., digest-mirror-xk4qz), so AlreadyExists collisions from leftover artifacts won't happen.
Using Apply() would work too, but it could silently overwrite a resource from a concurrent test run rather than failing explicitly, which is less safe. With unique names + Create(), we get a clean resource every time and would catch genuine conflicts.

@openshift-merge-bot openshift-merge-bot Bot added the ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review label May 8, 2026
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 8, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 8, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: asahay19
Once this PR has been reviewed and has the lgtm label, please assign haircommander 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

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: 1

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

746-764: ⚡ Quick win

GetFirstReadyWorkerNode is inconsistent with the rest of the file: no context, N+1 subprocess calls

Every other function in this file takes a context.Context and uses the Kubernetes client directly. GetFirstReadyWorkerNode instead:

  1. Takes no context — callers cannot propagate cancellation or timeouts.
  2. Issues one subprocess call to list node names, then one more per node to read its Ready condition — the existing getNodesByLabel + isNodeInReadyState helpers already cover this in a single API round-trip.

Consider implementing it with the existing helpers:

♻️ Proposed refactor
-func GetFirstReadyWorkerNode(oc *exutil.CLI) string {
-	nodeNames, err := oc.AsAdmin().WithoutNamespace().Run("get").Args(
-		"nodes", "-l", "node-role.kubernetes.io/worker",
-		"-o=jsonpath={.items[*].metadata.name}",
-	).Output()
-	o.Expect(err).NotTo(o.HaveOccurred())
-	workers := strings.Fields(nodeNames)
-	o.Expect(workers).NotTo(o.BeEmpty(), "no worker nodes found")
-
-	for _, w := range workers {
-		status, statusErr := oc.AsAdmin().WithoutNamespace().Run("get").Args(
-			"nodes", w,
-			"-o=jsonpath={.status.conditions[?(@.type=='Ready')].status}",
-		).Output()
-		if statusErr == nil && status == "True" {
-			return w
-		}
-	}
-	return ""
-}
+func GetFirstReadyWorkerNode(ctx context.Context, oc *exutil.CLI) string {
+	workers, err := getNodesByLabel(ctx, oc, "node-role.kubernetes.io/worker")
+	o.Expect(err).NotTo(o.HaveOccurred())
+	o.Expect(workers).NotTo(o.BeEmpty(), "no worker nodes found")
+
+	for _, w := range workers {
+		if isNodeInReadyState(&w) {
+			return w.Name
+		}
+	}
+	o.Expect(false).To(o.BeTrue(), "no Ready worker node found")
+	return "" // unreachable
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/extended/node/node_utils.go` around lines 746 - 764,
GetFirstReadyWorkerNode should accept a context.Context and use the existing
Kubernetes client helpers instead of spawning kubectl per-node: change the
signature of GetFirstReadyWorkerNode to take ctx context.Context, call
getNodesByLabel(ctx, oc, "node-role.kubernetes.io/worker") to get nodes, then
iterate and call isNodeInReadyState(ctx, oc, node) (or the equivalent helper
names present) to find the first Ready node and return its name; remove the
subprocess Run("get") calls and preserve the same return semantics (empty string
if none found).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/extended/node/node_utils.go`:
- Around line 755-764: GetFirstReadyWorkerNode currently returns an empty string
when no worker with Ready=True is found, causing downstream cryptic failures;
change the post-loop behavior in GetFirstReadyWorkerNode (the function that
iterates workers and calls oc.AsAdmin().WithoutNamespace().Run("get").Args(...))
to fail the test immediately with a clear message (e.g. call the test
framework's fail/assert function or t.Fatalf/Failf) indicating "no ready worker
node found" instead of returning "" so callers never receive an invalid node
name.

---

Nitpick comments:
In `@test/extended/node/node_utils.go`:
- Around line 746-764: GetFirstReadyWorkerNode should accept a context.Context
and use the existing Kubernetes client helpers instead of spawning kubectl
per-node: change the signature of GetFirstReadyWorkerNode to take ctx
context.Context, call getNodesByLabel(ctx, oc, "node-role.kubernetes.io/worker")
to get nodes, then iterate and call isNodeInReadyState(ctx, oc, node) (or the
equivalent helper names present) to find the first Ready node and return its
name; remove the subprocess Run("get") calls and preserve the same return
semantics (empty string if none found).
🪄 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: ef32c950-ef14-4009-bfa5-3caf3802f43c

📥 Commits

Reviewing files that changed from the base of the PR and between e5944f9 and 9b247db.

📒 Files selected for processing (2)
  • test/extended/node/node_e2e/node.go
  • test/extended/node/node_utils.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/extended/node/node_e2e/node.go

Comment on lines +755 to +764
for _, w := range workers {
status, statusErr := oc.AsAdmin().WithoutNamespace().Run("get").Args(
"nodes", w,
"-o=jsonpath={.status.conditions[?(@.type=='Ready')].status}",
).Output()
if statusErr == nil && status == "True" {
return w
}
}
return ""
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 | 🟡 Minor | ⚡ Quick win

GetFirstReadyWorkerNode silently returns "" when no ready worker is found

Line 753 asserts the worker list is non-empty, but if every worker node is found yet none passes the Ready=True check, the function returns "" without any assertion failure. A caller receiving "" as a node name will fail later with a cryptic "node not found" error rather than a clear test message.

🐛 Proposed fix
 	for _, w := range workers {
 		status, statusErr := oc.AsAdmin().WithoutNamespace().Run("get").Args(
 			"nodes", w,
 			"-o=jsonpath={.status.conditions[?(@.type=='Ready')].status}",
 		).Output()
 		if statusErr == nil && status == "True" {
 			return w
 		}
 	}
-	return ""
+	o.Expect(false).To(o.BeTrue(), "no Ready worker node found among %v", workers)
+	return "" // unreachable; satisfies compiler
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/extended/node/node_utils.go` around lines 755 - 764,
GetFirstReadyWorkerNode currently returns an empty string when no worker with
Ready=True is found, causing downstream cryptic failures; change the post-loop
behavior in GetFirstReadyWorkerNode (the function that iterates workers and
calls oc.AsAdmin().WithoutNamespace().Run("get").Args(...)) to fail the test
immediately with a clear message (e.g. call the test framework's fail/assert
function or t.Fatalf/Failf) indicating "no ready worker node found" instead of
returning "" so callers never receive an invalid node name.

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

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

openshift-ci Bot commented May 8, 2026

@asahay19: 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.

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

Labels

ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants