Skip to content

CORS-4466: Correctly calculate subnet CIDR length#10542

Open
bear-redhat wants to merge 1 commit intoopenshift:mainfrom
bear-redhat:issue/CORS-4466
Open

CORS-4466: Correctly calculate subnet CIDR length#10542
bear-redhat wants to merge 1 commit intoopenshift:mainfrom
bear-redhat:issue/CORS-4466

Conversation

@bear-redhat
Copy link
Copy Markdown
Contributor

@bear-redhat bear-redhat commented May 8, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Fixed subnet and CIDR computation logic for public-only configurations with external publishing
    • Improved validation handling for edge CIDR availability in public-only deployments
    • Corrected edge subnet CIDR block generation behavior for public-only networks
  • Tests

    • Added test coverage for public-only subnet configurations across multiple availability zones

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 8, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented May 8, 2026

@bear-redhat: This pull request references CORS-4466 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 bug to target the "5.0.0" version, but no target version was set.

Details

In response to this:

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 May 8, 2026

Walkthrough

This PR modifies AWS subnet allocation logic in setSubnetsManagedVPC to support "public-only subnets" mode. When enabled via environment variable, the function adjusts CIDR reservation and skips private subnet creation, with conditional edge subnet CIDR doubling and validation relaxation. A comprehensive test validates the new behavior.

Changes

Public-Only AWS Subnet Mode

Layer / File(s) Summary
Core Logic
pkg/asset/manifests/aws/zones.go
Derives isPublicOnly flag once and gates subnet/CIDR derivation on it. Adjusts public CIDR reservation under external publishing, skips private AZ subnets, disables edge CIDR doubling, and relaxes private edge CIDR validation when public-only mode is active.
Test Validation
pkg/asset/manifests/aws/zones_test.go
New Test_setSubnetsManagedVPC_publicOnly test validates public-only behavior for /22 VPC with three AZs and with an additional edge zone, asserting correct public subnet CIDR sizes and zone coverage.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 11 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately describes the main change: correcting subnet CIDR length calculation in the setSubnetsManagedVPC function, which is the primary focus of the code modifications.
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 Uses standard Go testing, not Ginkgo. Check targets Ginkgo patterns (It(), Describe(), etc.) which are absent. Test names are static with no dynamic values.
Test Structure And Quality ✅ Passed The check is for Ginkgo test code, but this PR adds standard Go unit tests without Ginkgo framework. The check is not applicable to this codebase pattern.
Microshift Test Compatibility ✅ Passed The PR adds a unit test, not a Ginkgo e2e test. The custom check applies only to Ginkgo e2e tests. Test uses standard Go testing.T, no g.It/g.Describe patterns.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR contains only standard Go unit tests, not Ginkgo e2e tests. Custom check applies only to Ginkgo tests (It(), Describe(), Context(), When()), which are absent here.
Topology-Aware Scheduling Compatibility ✅ Passed PR modifies only AWS VPC/subnet infrastructure code (CAPA network specs). No pod scheduling constraints, affinity rules, nodeSelectors, or workload scheduling logic present.
Ote Binary Stdout Contract ✅ Passed This PR modifies library code in pkg/asset/manifests/aws/ (OpenShift installer manifest generation), not an OTE test binary. The check is not applicable to non-OTE binaries.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No Ginkgo e2e tests added. Test_setSubnetsManagedVPC_publicOnly is a standard Go unit test. Custom check applies only to Ginkgo e2e tests, so not applicable here.

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

✨ 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.12.1)

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


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 mtulio and tthvo May 8, 2026 18:44
@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:
Once this PR has been reviewed and has the lgtm label, please assign tthvo 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/asset/manifests/aws/zones.go (1)

359-364: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Edge-CIDR validation does not account for isPublicOnly and will spuriously fail with multiple edge zones.

When isPublicOnly && isPublishingExternal, only len(allEdgeZones) edge CIDRs are needed (one public per edge zone), and numEdgeSubnets is computed as len(allEdgeZones) + 1 (no doubling). However, the check on Line 362 still requires len(edgeCIDRs) >= len(allEdgeZones) * 2, mirroring the non‑public‑only path. With ≥2 edge zones this becomes reachable:

  • 3 edge zones, public‑only: numEdgeSubnets = 4SplitIntoSubnetsIPv4 returns 4 → check 4 < 3*2 = 6 is true → returns "unable to define CIDR blocks to all edge zones for public subnets", even though there are sufficient CIDRs for the public subnets actually being created.

The existing test only exercises a single edge zone (numEdgeSubnets = 2, check 2 < 2 is false), so this path is not covered.

🛠️ Proposed fix: parameterize the expected count by isPublicOnly
-	if isPublishingExternal && (len(edgeCIDRs) < (len(allEdgeZones) * 2)) {
-		return fmt.Errorf("unable to define CIDR blocks to all edge zones for public subnets")
+	if isPublishingExternal {
+		expectedPublicEdgeCIDRs := len(allEdgeZones)
+		if !isPublicOnly {
+			expectedPublicEdgeCIDRs += len(allEdgeZones)
+		}
+		if len(edgeCIDRs) < expectedPublicEdgeCIDRs {
+			return fmt.Errorf("unable to define CIDR blocks to all edge zones for public subnets")
+		}
 	}
🤖 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 `@pkg/asset/manifests/aws/zones.go` around lines 359 - 364, The public-subnet
check incorrectly assumes two CIDRs per edge zone regardless of isPublicOnly;
update the second validation to compute the required edge CIDR count based on
isPublicOnly (e.g. required := len(allEdgeZones) if isPublicOnly &&
isPublishingExternal else len(allEdgeZones)*2) and replace the hardcoded
(len(allEdgeZones) * 2) comparison with this computed required value so the
check on edgeCIDRs uses the correct expected count; adjust references in the
same block that use isPublishingExternal, edgeCIDRs, and allEdgeZones (and any
related numEdgeSubnets/SplitIntoSubnetsIPv4 logic) to be consistent.
🧹 Nitpick comments (3)
pkg/asset/manifests/aws/zones.go (1)

285-306: 💤 Low value

Consider consolidating the publicCIDRs / edgeCIDR derivation to reduce branching.

The new if isPublicOnly && isPublishingExternal { ... } else { ... } block, combined with numSubnets already accounting for whether public reservation is needed, makes the index arithmetic harder to follow. A single offset-based computation can express both cases without duplicating the edge-CIDR slot logic, and avoids the dead publicCIDR computation in the isPublicOnly && !isPublishingExternal corner case.

For example:

azCount := len(allAvailabilityZones)
if isPublishingExternal {
    if isPublicOnly {
        publicCIDRs = privateCIDRs[:azCount]
    } else {
        publicCIDR := privateCIDRs[azCount].String()
        publicCIDRs, err = utilscidr.SplitIntoSubnetsIPv4(publicCIDR, azCount)
        if err != nil {
            return fmt.Errorf("unable to generate CIDR blocks for all public subnets: %w", err)
        }
    }
}
if len(allEdgeZones) > 0 {
    edgeIdx := azCount
    if isPublishingExternal && !isPublicOnly {
        edgeIdx++
    }
    edgeCIDR = privateCIDRs[edgeIdx].String()
}

Not blocking — purely a readability suggestion.

🤖 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 `@pkg/asset/manifests/aws/zones.go` around lines 285 - 306, Consolidate the
branching that computes publicCIDRs and edgeCIDR by using an azCount :=
len(allAvailabilityZones) and a single offset-based index for the edge slot
instead of separate if/else blocks; when isPublishingExternal is true, set
publicCIDRs to privateCIDRs[:azCount] if isPublicOnly, otherwise call
utilscidr.SplitIntoSubnetsIPv4(privateCIDRs[azCount].String(), azCount) and
handle its error, and compute edgeIdx := azCount (increment edgeIdx by 1 if
isPublishingExternal && !isPublicOnly) to set edgeCIDR =
privateCIDRs[edgeIdx].String() only if len(allEdgeZones) > 0, removing the dead
publicCIDR computation path and duplicated logic.
pkg/asset/manifests/aws/zones_test.go (2)

754-781: 💤 Low value

Test scaffolding largely duplicates Test_setSubnetsManagedVPC — consider a shared helper.

The post-setSubnetsManagedVPC plumbing here (nil checks on tt.args.in/Cluster, empty-subnet handling, tSortCapaSubnetsByID, and the final cmp.Equal comparison) is identical to the existing test runner in Test_setSubnetsManagedVPC (Lines 588-612). Extracting an assertManagedVPCNetworkSpec(t, in, want, wantErr) helper would deduplicate ~20 lines and ensure both tests stay in sync if the validation logic evolves. Optional cleanup — not blocking.

🤖 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 `@pkg/asset/manifests/aws/zones_test.go` around lines 754 - 781, Extract the
duplicated post-call assertions in Test_setSubnetsManagedVPC and the other test
into a single helper, e.g. assertManagedVPCNetworkSpec(t, in, want, wantErr),
that calls setSubnetsManagedVPC(in) (or accepts pre-called results), performs
the nil checks on tt.args.in and tt.args.in.Cluster, handles the empty-subnet
early-return and wantErr logic, runs tSortCapaSubnetsByID on
Cluster.Spec.NetworkSpec.Subnets, and does the final cmp.Equal comparison
against want; then replace the duplicated block in both tests with a single call
to assertManagedVPCNetworkSpec(t, tt.args.in, tt.want, tt.wantErr) to keep
behavior identical to the existing checks around setSubnetsManagedVPC,
tSortCapaSubnetsByID, and cmp.Diff.

681-752: ⚡ Quick win

Add a public-only test case with multiple edge zones.

Both new cases use at most one edge zone, so numEdgeSubnets ends at 2 and the validation len(edgeCIDRs) < len(allEdgeZones)*2 happens to pass (2 < 2 is false). With ≥2 edge zones in public-only mode the validation in setSubnetsManagedVPC (Line 362 in zones.go) is reachable and would currently return an error even though enough public-edge CIDRs are available. A test like “public-only /22 with 3 AZs and 2 edge zones” would catch that path and pin down the expected /26 CIDR allocations for public edge subnets.

🤖 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 `@pkg/asset/manifests/aws/zones_test.go` around lines 681 - 752, Add a new
table test case in zones_test.go mirroring the "public-only /22 with 3 AZs and
edge zone" case but with two edge zones to exercise the validation in
setSubnetsManagedVPC: update the test's networkInput.InstallConfig Compute
platform to include an AWS MachinePool with Zones: []string{"edge-a","edge-b"},
add "edge-b" to ZonesInRegion, and extend the expected want.Subnets to include
both "infra-id-subnet-public-edge-a" and "infra-id-subnet-public-edge-b" with
the expected /26 CIDR allocations; this will trigger the
numEdgeSubnets/edgeCIDRs vs allEdgeZones path in setSubnetsManagedVPC and pin
the correct public-edge CIDR sizes.
🤖 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.

Outside diff comments:
In `@pkg/asset/manifests/aws/zones.go`:
- Around line 359-364: The public-subnet check incorrectly assumes two CIDRs per
edge zone regardless of isPublicOnly; update the second validation to compute
the required edge CIDR count based on isPublicOnly (e.g. required :=
len(allEdgeZones) if isPublicOnly && isPublishingExternal else
len(allEdgeZones)*2) and replace the hardcoded (len(allEdgeZones) * 2)
comparison with this computed required value so the check on edgeCIDRs uses the
correct expected count; adjust references in the same block that use
isPublishingExternal, edgeCIDRs, and allEdgeZones (and any related
numEdgeSubnets/SplitIntoSubnetsIPv4 logic) to be consistent.

---

Nitpick comments:
In `@pkg/asset/manifests/aws/zones_test.go`:
- Around line 754-781: Extract the duplicated post-call assertions in
Test_setSubnetsManagedVPC and the other test into a single helper, e.g.
assertManagedVPCNetworkSpec(t, in, want, wantErr), that calls
setSubnetsManagedVPC(in) (or accepts pre-called results), performs the nil
checks on tt.args.in and tt.args.in.Cluster, handles the empty-subnet
early-return and wantErr logic, runs tSortCapaSubnetsByID on
Cluster.Spec.NetworkSpec.Subnets, and does the final cmp.Equal comparison
against want; then replace the duplicated block in both tests with a single call
to assertManagedVPCNetworkSpec(t, tt.args.in, tt.want, tt.wantErr) to keep
behavior identical to the existing checks around setSubnetsManagedVPC,
tSortCapaSubnetsByID, and cmp.Diff.
- Around line 681-752: Add a new table test case in zones_test.go mirroring the
"public-only /22 with 3 AZs and edge zone" case but with two edge zones to
exercise the validation in setSubnetsManagedVPC: update the test's
networkInput.InstallConfig Compute platform to include an AWS MachinePool with
Zones: []string{"edge-a","edge-b"}, add "edge-b" to ZonesInRegion, and extend
the expected want.Subnets to include both "infra-id-subnet-public-edge-a" and
"infra-id-subnet-public-edge-b" with the expected /26 CIDR allocations; this
will trigger the numEdgeSubnets/edgeCIDRs vs allEdgeZones path in
setSubnetsManagedVPC and pin the correct public-edge CIDR sizes.

In `@pkg/asset/manifests/aws/zones.go`:
- Around line 285-306: Consolidate the branching that computes publicCIDRs and
edgeCIDR by using an azCount := len(allAvailabilityZones) and a single
offset-based index for the edge slot instead of separate if/else blocks; when
isPublishingExternal is true, set publicCIDRs to privateCIDRs[:azCount] if
isPublicOnly, otherwise call
utilscidr.SplitIntoSubnetsIPv4(privateCIDRs[azCount].String(), azCount) and
handle its error, and compute edgeIdx := azCount (increment edgeIdx by 1 if
isPublishingExternal && !isPublicOnly) to set edgeCIDR =
privateCIDRs[edgeIdx].String() only if len(allEdgeZones) > 0, removing the dead
publicCIDR computation path and duplicated logic.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: 54ff18dc-5a34-42f1-ac7b-3c499df70dd4

📥 Commits

Reviewing files that changed from the base of the PR and between c782a19 and 1927a1c.

📒 Files selected for processing (2)
  • pkg/asset/manifests/aws/zones.go
  • pkg/asset/manifests/aws/zones_test.go

@tthvo
Copy link
Copy Markdown
Member

tthvo commented May 8, 2026

/test e2e-aws-ovn-public-subnets

@patrickdillon
Copy link
Copy Markdown
Contributor

/approve

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 8, 2026

@bear-redhat: 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-heterogeneous 1927a1c link false /test e2e-aws-ovn-heterogeneous
ci/prow/e2e-aws-ovn-edge-zones 1927a1c link false /test e2e-aws-ovn-edge-zones

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