Skip to content

system-tests: update egress-service.go to support IPv6 single stack#1342

Open
laurayang842 wants to merge 4 commits intorh-ecosystem-edge:mainfrom
laurayang842:egresservice
Open

system-tests: update egress-service.go to support IPv6 single stack#1342
laurayang842 wants to merge 4 commits intorh-ecosystem-edge:mainfrom
laurayang842:egresservice

Conversation

@laurayang842
Copy link
Copy Markdown
Contributor

@laurayang842 laurayang842 commented Apr 21, 2026

Summary by CodeRabbit

  • Tests
    • Improved service connectivity tests to support IPv4-only, IPv6-only, and dual-stack scenarios based on actual configuration rather than hardcoded assumptions.
    • Added validation to ensure at least one IP version is configured before running tests.
    • Consolidated and simplified connectivity checks to conditionally verify only the relevant IP versions for configured targets.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 21, 2026

Warning

Rate limit exceeded

@laurayang842 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 25 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 9 minutes and 25 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0d0c89c7-707b-42e9-b5e3-a3812fc89763

📥 Commits

Reviewing files that changed from the base of the PR and between 1f6f645 and 666355f.

📒 Files selected for processing (1)
  • tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go
📝 Walkthrough

Walkthrough

Apply dynamic Service IP family policy based on configured remote IPv4/IPv6 targets and refactor egress-service connectivity checks into a shared helper that conditionally performs IPv4 and/or IPv6 curl+source-IP verifications, with assertions that at least one remote target IP is set.

Changes

Cohort / File(s) Summary
IPv Family Policy and ETP Connectivity Verification
tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go
Added applyIPFamilyPolicy to set Service ipFamilies/ipFamilyPolicy based on presence of IPv4/IPv6 remote targets; replaced unconditional dual-stack setting. Consolidated duplicated curl+verifySourceIP logic into verifyEgressServiceConnectivity, which asserts at least one remote IP and conditionally runs IPv4/IPv6 checks with appropriate URL formatting and Ginkgo step labels.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 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: adding IPv6 single-stack support to the egress-service.go system test file.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% 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.

✏️ 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.

@laurayang842 laurayang842 marked this pull request as ready for review April 21, 2026 02:42
@yprokule
Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 21, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go (2)

385-413: IPFamilyPolicy selection logic is correct.

The guard plus switch is sound: the Expect(hasIPv4 || hasIPv6) precondition makes the default branch unambiguously the "IPv4-only" case, so the three branches fully and correctly cover the tri-state (v4-only / v6-only / dual). Combined with SingleStack, downstream loops at lines 516‑541 that still branch on myIP.Is4() will only see Ingress entries of the configured family, so the empty remoteTargetIP / remoteTargetIPv6 cannot accidentally leak into the curl command.

Note: this same switch block is duplicated verbatim at lines 701‑729 in VerifyEgressServiceWithLocalETPWrapper. Consider extracting a small helper, e.g.:

♻️ Suggested helper to dedupe the ipFamilyPolicy setup (applies to both wrappers)
// applyIPFamilyPolicy configures svcBuilder's IP families based on which remote targets are set.
// Callers must ensure at least one of v4 or v6 is non-empty.
func applyIPFamilyPolicy(svcBuilder *service.Builder, remoteTargetIP, remoteTargetIPv6 string) *service.Builder {
    hasIPv4 := remoteTargetIP != ""
    hasIPv6 := remoteTargetIPv6 != ""

    switch {
    case hasIPv4 && hasIPv6:
        By("Setting ipFamilyPolicy to 'RequireDualStack'")
        return svcBuilder.WithIPFamily(
            []corev1.IPFamily{corev1.IPv4Protocol, corev1.IPv6Protocol},
            corev1.IPFamilyPolicyRequireDualStack)
    case hasIPv6:
        By("Setting ipFamilyPolicy to 'SingleStack' (IPv6)")
        return svcBuilder.WithIPFamily(
            []corev1.IPFamily{corev1.IPv6Protocol},
            corev1.IPFamilyPolicySingleStack)
    default:
        By("Setting ipFamilyPolicy to 'SingleStack' (IPv4)")
        return svcBuilder.WithIPFamily(
            []corev1.IPFamily{corev1.IPv4Protocol},
            corev1.IPFamilyPolicySingleStack)
    }
}

Then at both call sites (lines 385‑413 and 701‑729):

-	hasIPv4 := remoteTargetIP != ""
-	hasIPv6 := remoteTargetIPv6 != ""
-
-	Expect(hasIPv4 || hasIPv6).To(BeTrue(),
+	Expect(remoteTargetIP != "" || remoteTargetIPv6 != "").To(BeTrue(),
 		"At least one remote target IP (IPv4 or IPv6) must be configured")
-
-	switch {
-	case hasIPv4 && hasIPv6:
-		...
-	}
+	svcBuilder = applyIPFamilyPolicy(svcBuilder, remoteTargetIP, remoteTargetIPv6)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go` around
lines 385 - 413, The ipFamilyPolicy switch using hasIPv4/hasIPv6 is correct but
duplicated; extract the logic into a helper (e.g., applyIPFamilyPolicy) that
takes svcBuilder, remoteTargetIP and remoteTargetIPv6 and returns the updated
svcBuilder, reusing the same branches (dual → WithIPFamily([...IPv4, IPv6...],
IPFamilyPolicyRequireDualStack; IPv6-only → WithIPFamily([IPv6],
IPFamilyPolicySingleStack); default/IPv4-only → WithIPFamily([IPv4],
IPFamilyPolicySingleStack)). Replace the two verbatim blocks (the current block
using svcBuilder.WithIPFamily at lines around the first occurrence and the
duplicate in VerifyEgressServiceWithLocalETPWrapper) with calls to this helper
to remove duplication and keep behavior identical.

1001-1115: Deduplicate the four VerifyEgressServiceConnectivity* functions.

All four functions (VerifyEgressServiceConnectivityETPCluster, …ETPClusterSourceIPByNetwork, …ETPLocal, …ETPLocalSourceIPByNetwork) now share an identical shape: precondition assertion → conditional IPv4 curl + verifySourceIP(..., false, …) → conditional IPv6 curl + verifySourceIP(..., true, …). The only variation is the service name, labels, and the By() message prefix. This is a good opportunity to collapse the boilerplate into a single helper to reduce future drift (the IPv6-only support was added in four places and any future tweak — e.g., timeout, URL shape, additional assertion — will need to be mirrored four times).

♻️ Suggested helper to remove the 4-way duplication
// verifyEgressServiceConnectivity runs source-IP verification for the IPv4 and/or IPv6 remote
// targets configured in RDSCoreConfig, using the provided service identifiers and a By() label prefix.
func verifyEgressServiceConnectivity(svcName, svcNS, svcLabels, byPrefix string) {
    Expect(RDSCoreConfig.EgressServiceRemoteIP != "" || RDSCoreConfig.EgressServiceRemoteIPv6 != "").
        To(BeTrue(), "Neither EgressServiceRemoteIP nor EgressServiceRemoteIPv6 is configured")

    if RDSCoreConfig.EgressServiceRemoteIP != "" {
        By(fmt.Sprintf("Verifying %s connectivity (IPv4)", byPrefix))

        cmdToRun := []string{"/bin/bash", "-c",
            fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
                RDSCoreConfig.EgressServiceRemoteIP, RDSCoreConfig.EgressServiceRemotePort)}

        verifySourceIP(svcName, svcNS, svcLabels, cmdToRun, false,
            RDSCoreConfig.EgressServiceNetworkExpectedIPs)
    }

    if RDSCoreConfig.EgressServiceRemoteIPv6 != "" {
        By(fmt.Sprintf("Verifying %s connectivity (IPv6)", byPrefix))

        cmdToRun := []string{"/bin/bash", "-c",
            fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
                RDSCoreConfig.EgressServiceRemoteIPv6, RDSCoreConfig.EgressServiceRemotePort)}

        verifySourceIP(svcName, svcNS, svcLabels, cmdToRun, true,
            RDSCoreConfig.EgressServiceNetworkExpectedIPs)
    }
}

Call sites collapse to a single line each:

 func VerifyEgressServiceConnectivityETPCluster() {
-    Expect(...).To(BeTrue(), "...")
-    if RDSCoreConfig.EgressServiceRemoteIP != "" { ... }
-    if RDSCoreConfig.EgressServiceRemoteIPv6 != "" { ... }
+    verifyEgressServiceConnectivity(egressSVC1Name, RDSCoreConfig.EgressServiceNS, egressSVC1Labels,
+        "EgressService ETP=Cluster")
 }
 // ... similar for the other three, switching service name/labels and prefix.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go` around
lines 1001 - 1115, The four functions VerifyEgressServiceConnectivityETPCluster,
VerifyEgressServiceConnectivityETPClusterSourceIPByNetwork,
VerifyEgressServiceConnectivityETPLocal, and
VerifyEgressServiceConnectivityETPLocalSourceIPByNetwork are duplicated; extract
their common logic into a single helper (e.g., verifyEgressServiceConnectivity)
that accepts svcName, svcNS, svcLabels and a byPrefix string, moves the shared
Expect(...) check and the IPv4/IPv6 curl + verifySourceIP(...) blocks into it,
and update each original function to call that helper with the appropriate
egressSVC*Name, RDSCoreConfig.EgressServiceNS, egressSVC*Labels and message
prefix (e.g., "EgressService ETP=Cluster") to remove boilerplate and keep
behavior identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go`:
- Around line 385-413: The ipFamilyPolicy switch using hasIPv4/hasIPv6 is
correct but duplicated; extract the logic into a helper (e.g.,
applyIPFamilyPolicy) that takes svcBuilder, remoteTargetIP and remoteTargetIPv6
and returns the updated svcBuilder, reusing the same branches (dual →
WithIPFamily([...IPv4, IPv6...], IPFamilyPolicyRequireDualStack; IPv6-only →
WithIPFamily([IPv6], IPFamilyPolicySingleStack); default/IPv4-only →
WithIPFamily([IPv4], IPFamilyPolicySingleStack)). Replace the two verbatim
blocks (the current block using svcBuilder.WithIPFamily at lines around the
first occurrence and the duplicate in VerifyEgressServiceWithLocalETPWrapper)
with calls to this helper to remove duplication and keep behavior identical.
- Around line 1001-1115: The four functions
VerifyEgressServiceConnectivityETPCluster,
VerifyEgressServiceConnectivityETPClusterSourceIPByNetwork,
VerifyEgressServiceConnectivityETPLocal, and
VerifyEgressServiceConnectivityETPLocalSourceIPByNetwork are duplicated; extract
their common logic into a single helper (e.g., verifyEgressServiceConnectivity)
that accepts svcName, svcNS, svcLabels and a byPrefix string, moves the shared
Expect(...) check and the IPv4/IPv6 curl + verifySourceIP(...) blocks into it,
and update each original function to call that helper with the appropriate
egressSVC*Name, RDSCoreConfig.EgressServiceNS, egressSVC*Labels and message
prefix (e.g., "EgressService ETP=Cluster") to remove boilerplate and keep
behavior identical.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 469296a6-7fb7-407f-91d8-6d884c4043c2

📥 Commits

Reviewing files that changed from the base of the PR and between 8097191 and b0bbee7.

📒 Files selected for processing (1)
  • tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go (1)

521-546: Optional: consider consolidating the inline IPv4/IPv6 curl branching with the same pattern used by the new helper.

With single-stack IPv6 only, remoteTargetIP will be "" and the Is4() branch is effectively unreachable (LB ingress will only return IPv6 VIPs). The current logic is safe, but the per-family curl construction here (and again at lines 820-836 in VerifyEgressServiceWithLocalETPWrapper) is near-duplicate of what you centralized in verifyEgressServiceConnectivity. Extracting a small buildClientIPCurl(family, ip, port) helper would keep the IPv6 bracket-quoting and URL format in one place.

Not blocking.

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

In `@tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go` around
lines 521 - 546, The two-place IPv4/IPv6 curl construction in the loop that
handles svcBuilder.Object.Status.LoadBalancer.Ingress (and the similar block in
VerifyEgressServiceWithLocalETPWrapper) duplicates logic centralized in
verifyEgressServiceConnectivity; extract a small helper function
buildClientIPCurl(family string, ip string, port string) that returns the
properly bracketed URL or full curl command (handling IPv6 [] brackets and using
remoteTargetIP vs remoteTargetIPv6), then replace the inline Is4() branches in
the loop and in VerifyEgressServiceWithLocalETPWrapper to call buildClientIPCurl
and use its result for cmdToRun so URL formatting is single-sourced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go`:
- Around line 521-546: The two-place IPv4/IPv6 curl construction in the loop
that handles svcBuilder.Object.Status.LoadBalancer.Ingress (and the similar
block in VerifyEgressServiceWithLocalETPWrapper) duplicates logic centralized in
verifyEgressServiceConnectivity; extract a small helper function
buildClientIPCurl(family string, ip string, port string) that returns the
properly bracketed URL or full curl command (handling IPv6 [] brackets and using
remoteTargetIP vs remoteTargetIPv6), then replace the inline Is4() branches in
the loop and in VerifyEgressServiceWithLocalETPWrapper to call buildClientIPCurl
and use its result for cmdToRun so URL formatting is single-sourced.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a16fffc1-30da-452e-8b3b-bb27f68a2e95

📥 Commits

Reviewing files that changed from the base of the PR and between b0bbee7 and 1f6f645.

📒 Files selected for processing (1)
  • tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants