Skip to content

OCPCLOUD-3215: Detect IPv6 clusters and apply correct policy#30938

Open
nrb wants to merge 1 commit intoopenshift:mainfrom
nrb:ccm-dual-stack-change
Open

OCPCLOUD-3215: Detect IPv6 clusters and apply correct policy#30938
nrb wants to merge 1 commit intoopenshift:mainfrom
nrb:ccm-dual-stack-change

Conversation

@nrb
Copy link
Copy Markdown

@nrb nrb commented Mar 26, 2026

Dual stack load balancers in Kubernetes must specify an IP family policy, or else it will be set to SingleStack. On AWS, IPv6 single stack is not supported, so update the test to reflect the required value.

Assisted-By: Claude Sonnet 4.6

@openshift-ci-robot
Copy link
Copy Markdown

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-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 26, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Mar 26, 2026

@nrb: This pull request references OCPCLOUD-3215 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:

Dual stack load balancers in Kubernetes must specify an IP family policy, or else it will be set to SingleStack. On AWS, IPv6 single stack is not supported, so update the test to reflect the required value.

Assisted-By: Claude Sonnet 4.6

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.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Fetches the cluster Infrastructure, asserts infra.Status.PlatformStatus is non-nil, detects AWS IPv6‑primary, and conditionally creates the load‑balancer Service using inline YAML with spec.ipFamilyPolicy: RequireDualStack for IPv6‑primary; otherwise uses oc create ... --tcp=80:8080. Simplifies Service cleanup.

Changes

Cohort / File(s) Summary
Load Balancer Service Creation & Cleanup
test/extended/cloud_controller_manager/ccm.go
Retrieves cluster Infrastructure and asserts infra.Status.PlatformStatus exists. Computes isIPv6Primary via infra.Status.PlatformStatus.AWS.IPFamily == configv1.DualStackIPv6Primary (guarded). For IPv6‑primary, creates Service from inline YAML setting spec.ipFamilyPolicy: RequireDualStack and port mapping; otherwise uses prior oc create service loadbalancer --tcp=80:8080 flow and checks CLI output. Deferred cleanup simplified to oc delete service <name> --ignore-not-found.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

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

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.11.4)

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 openshift-ci bot requested review from JoelSpeed and MaysaMacedo March 26, 2026 15:00
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci bot commented Mar 26, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

out, err := oc.AsAdmin().WithoutNamespace().Run("create").Args("-n", oc.Namespace(), "service", "loadbalancer", svcName, "--tcp=80:8080").Output()
o.Expect(err).NotTo(o.HaveOccurred(), "failed to create lb service")
o.Expect(out).To(o.ContainSubstring("service/" + svcName + " created"))
defer oc.WithoutNamespace().AsAdmin().Run("delete").Args("service", fmt.Sprintf("%s/%s", oc.Namespace(), svcName), "--ignore-not-found").Execute()
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This change was because oc delete service loadbalancer actually isn't a valid command; it would work before because of the --ignore-not-found and namespace teardown, but this cleans it up more quickly.

@nrb nrb force-pushed the ccm-dual-stack-change branch from 6eeb44a to a5a2a3a Compare March 26, 2026 15:13
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

🤖 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/cloud_controller_manager/ccm.go`:
- Around line 102-106: The code dereferences infra.Status.PlatformStatus without
checking for nil which can panic; update the isIPv6Primary computation to first
verify infra.Status.PlatformStatus is non-nil (and then
infra.Status.PlatformStatus.AWS is non-nil) before reading .AWS.IPFamily—e.g.
check infra.Status.PlatformStatus != nil && infra.Status.PlatformStatus.AWS !=
nil && infra.Status.PlatformStatus.AWS.IPFamily ==
configv1.DualStackIPv6Primary, using the existing
infra/AdminConfigClient/ConfigV1/Infrastructures().Get call and the
isIPv6Primary variable to locate where to apply the guard.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b91f067-e4cd-453b-85f0-db8593c8274c

📥 Commits

Reviewing files that changed from the base of the PR and between 6eeb44a and a5a2a3a.

📒 Files selected for processing (1)
  • test/extended/cloud_controller_manager/ccm.go

@openshift-ci-robot
Copy link
Copy Markdown

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

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

name: %s
spec:
type: LoadBalancer
ipFamilyPolicy: PreferDualStack
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.

Should this be RequireDualStack?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yep, you're right, that's what we'd agreed on for IPv6 primary.

We don't have that captured in our API and docs are not yet written. I guess the canonical place for us to reference would be the enhancement proposal.

@nrb nrb force-pushed the ccm-dual-stack-change branch from afa7cb5 to d7bae29 Compare March 26, 2026 18:08
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

🤖 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/cloud_controller_manager/ccm.go`:
- Line 131: The oc create invocation is passing "-n" before the resource type so
the literal "service" token is being parsed as the namespace; update the
Args(...) call in test/extended/cloud_controller_manager/ccm.go (the
oc.AsAdmin().WithoutNamespace().Run("create").Args(...) call) so the resource
type and name come before the -n flag — e.g. supply "service", "loadbalancer",
svcName, then "-n", "service", "--tcp=80:8080" — ensuring the create subcommand
receives the correct resource type and name.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f75e13de-9b50-4657-9ca6-7b18e2f10c56

📥 Commits

Reviewing files that changed from the base of the PR and between afa7cb5 and d7bae29.

📒 Files selected for processing (1)
  • test/extended/cloud_controller_manager/ccm.go

@openshift-ci-robot
Copy link
Copy Markdown

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

Dual stack load balancers in Kubernetes _must_ specify an IP family
policy, or else it will be set to `SingleStack`. On AWS, IPv6 single
stack is not supported, so update the test to reflect the new setting.

Signed-off-by: Nolan Brubaker <nolan@nbrubaker.com>
Assisted-By: Claude Sonnet 4.6
Signed-off-by: Nolan Brubaker <nolan@nbrubaker.com>
@nrb nrb force-pushed the ccm-dual-stack-change branch from d7bae29 to 3a77c41 Compare March 26, 2026 18:35
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

🤖 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/cloud_controller_manager/ccm.go`:
- Around line 111-133: The create/delete calls use WithoutNamespace() so the
commands run in the default admin namespace while later lookup uses
oc.Namespace(); update the three call sites (the deferred delete using
oc.WithoutNamespace().AsAdmin().Run("delete").Args(...).Execute(), the YAML
create using oc.AsAdmin().WithoutNamespace().Run("create").Args("-f",
"-").InputString(...).Execute(), and the loadbalancer create using
oc.AsAdmin().WithoutNamespace().Run("create").Args("service", "loadbalancer",
...).Output()) to explicitly target the test namespace by replacing
WithoutNamespace() with Namespace(oc.Namespace()) (or by adding the namespace
via Args("-n", oc.Namespace(), ...)) so creation, deletion, and lookup all use
the same namespace.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b95c9f60-dc1e-4b27-8c8c-008090770cdc

📥 Commits

Reviewing files that changed from the base of the PR and between d7bae29 and 3a77c41.

📒 Files selected for processing (1)
  • test/extended/cloud_controller_manager/ccm.go

Comment on lines +111 to +133
defer oc.WithoutNamespace().AsAdmin().Run("delete").Args("service", svcName, "--ignore-not-found").Execute()
if isIPv6Primary {

// IPv6 cannot be single stack on AWS, but kube will default an empty spec.ipFamilyPolicy to SingleStack.
svcYAML := fmt.Sprintf(`apiVersion: v1
kind: Service
metadata:
name: %s
spec:
type: LoadBalancer
ipFamilyPolicy: RequireDualStack
ports:
- port: 80
targetPort: 8080
protocol: TCP
`, svcName)
err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-f", "-").InputString(svcYAML).Execute()
o.Expect(err).NotTo(o.HaveOccurred(), "failed to create lb service")
} else {
// single stack or IPv4 primary
out, err := oc.AsAdmin().WithoutNamespace().Run("create").Args("service", "loadbalancer", svcName, "--tcp=80:8080").Output()
o.Expect(err).NotTo(o.HaveOccurred(), "failed to create lb service")
o.Expect(out).To(o.ContainSubstring("service/" + svcName + " created"))
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Mar 26, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect exutil.CLI namespace behavior (constructor, WithoutNamespace, Run).
rg -n --type=go -C4 'type CLI struct|func NewCLI\(|func \([^)]+CLI\) WithoutNamespace\(|func \([^)]+CLI\) Run\(' test/extended/util

# 2) Inspect this test's create/delete/get namespace usage together.
cat -n test/extended/cloud_controller_manager/ccm.go | sed -n '96,145p'

Repository: openshift/origin

Length of output: 7386


🏁 Script executed:

# Get the full Run() function implementation
rg -n --type=go -A 30 'func \(c \*CLI\) Run\(commands' test/extended/util/client.go | head -50

Repository: openshift/origin

Length of output: 1317


🏁 Script executed:

# Find getLoadBalancerExternalIP function
rg -n --type=go -B 2 -A 15 'func getLoadBalancerExternalIP' test/extended/cloud_controller_manager/ccm.go

Repository: openshift/origin

Length of output: 801


🏁 Script executed:

# Check how namespace flag is injected in the command construction
rg -n --type=go 'withoutNamespace' test/extended/util/client.go | head -20

Repository: openshift/origin

Length of output: 289


Add explicit namespace to create/delete operations to match lookup behavior.

Service creation and deletion at lines 111, 127, and 131 use WithoutNamespace() without specifying -n <namespace>, causing the commands to operate in an unspecified namespace (kubectl default). However, the service lookup at line 137 explicitly uses oc.Namespace(). If the admin context default namespace differs from the test namespace, the service may be created/deleted in one namespace and looked up in another, causing test failures or timeouts.

Suggested fix
 		g.By("Create a cluster scope load balancer")
 		svcName := "test-lb"
-		defer oc.WithoutNamespace().AsAdmin().Run("delete").Args("service", svcName, "--ignore-not-found").Execute()
+		ns := oc.Namespace()
+		defer oc.WithoutNamespace().AsAdmin().Run("delete").Args("service", svcName, "-n", ns, "--ignore-not-found").Execute()
 		if isIPv6Primary {
@@
-			err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-f", "-").InputString(svcYAML).Execute()
+			err = oc.AsAdmin().WithoutNamespace().Run("create").Args("-n", ns, "-f", "-").InputString(svcYAML).Execute()
 			o.Expect(err).NotTo(o.HaveOccurred(), "failed to create lb service")
 		} else {
 			// single stack or IPv4 primary
-			out, err := oc.AsAdmin().WithoutNamespace().Run("create").Args("service", "loadbalancer", svcName, "--tcp=80:8080").Output()
+			out, err := oc.AsAdmin().WithoutNamespace().Run("create").Args("-n", ns, "service", "loadbalancer", svcName, "--tcp=80:8080").Output()
 			o.Expect(err).NotTo(o.HaveOccurred(), "failed to create lb service")
 			o.Expect(out).To(o.ContainSubstring("service/" + svcName + " created"))
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/extended/cloud_controller_manager/ccm.go` around lines 111 - 133, The
create/delete calls use WithoutNamespace() so the commands run in the default
admin namespace while later lookup uses oc.Namespace(); update the three call
sites (the deferred delete using
oc.WithoutNamespace().AsAdmin().Run("delete").Args(...).Execute(), the YAML
create using oc.AsAdmin().WithoutNamespace().Run("create").Args("-f",
"-").InputString(...).Execute(), and the loadbalancer create using
oc.AsAdmin().WithoutNamespace().Run("create").Args("service", "loadbalancer",
...).Output()) to explicitly target the test namespace by replacing
WithoutNamespace() with Namespace(oc.Namespace()) (or by adding the namespace
via Args("-n", oc.Namespace(), ...)) so creation, deletion, and lookup all use
the same namespace.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this suggestion makes sense? We should pass in "-n", oc.Namespace() in order to use the correct namespace for oc command in test 🤔

The suggested patch looks reasonable...

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@tthvo Yes, the fix is warranted. Looking at the original code before this PR, it already passed -n oc.Namespace() explicitly to both the create and delete commands:

// Old code (before this PR)
defer oc.WithoutNamespace().AsAdmin().Run("delete").Args("-n", oc.Namespace(), "service", "loadbalancer", svcName, "--ignore-not-found").Execute()
out, err := oc.AsAdmin().WithoutNamespace().Run("create").Args("-n", oc.Namespace(), "service", "loadbalancer", svcName, "--tcp=80:8080").Output()

The PR inadvertently dropped that -n oc.Namespace() in the refactored code, affecting:

  1. The deferred delete call
  2. The new IPv6 YAML create call (also missing namespace: in the YAML metadata)
  3. The existing service loadbalancer create call (else branch)

The suggested patch restores the correct behavior so that creation, deletion, and the subsequent getLoadBalancerExternalIP lookup (which uses oc.Namespace()) all target the same namespace.

@openshift-ci-robot
Copy link
Copy Markdown

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 Mar 26, 2026

@nrb: The following tests 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-aws-ovn-serial-2of2 3a77c41 link true /test e2e-aws-ovn-serial-2of2
ci/prow/e2e-aws-ovn-fips 3a77c41 link true /test e2e-aws-ovn-fips
ci/prow/e2e-aws-ovn-serial-1of2 3a77c41 link true /test e2e-aws-ovn-serial-1of2
ci/prow/e2e-metal-ipi-ovn-ipv6 3a77c41 link true /test e2e-metal-ipi-ovn-ipv6
ci/prow/e2e-vsphere-ovn-upi 3a77c41 link true /test e2e-vsphere-ovn-upi

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

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