Skip to content

Commit ab74aee

Browse files
authored
system-tests: update egress-service.go to support IPv6 single stack (#1342)
* system-tests: update egress-service.go to support IPv6 single stack * system-tests: remove the blank file * system-tests: deduplicate functions in egress-service.go * system-tests: add a helper to build curl cmd
1 parent 4990ef3 commit ab74aee

1 file changed

Lines changed: 86 additions & 74 deletions

File tree

tests/system-tests/rdscore/internal/rdscorecommon/egress-service.go

Lines changed: 86 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,52 @@ func defineService(svcName, svcNSName string,
8484
return service.NewBuilder(APIClient, svcName, svcNSName, svcSelector, svcPort)
8585
}
8686

87+
// applyIPFamilyPolicy sets Service ipFamilies and ipFamilyPolicy from configured remote target IPs.
88+
func applyIPFamilyPolicy(svcBuilder *service.Builder, remoteTargetIP, remoteTargetIPv6 string) *service.Builder {
89+
hasIPv4 := remoteTargetIP != ""
90+
hasIPv6 := remoteTargetIPv6 != ""
91+
92+
Expect(hasIPv4 || hasIPv6).To(BeTrue(),
93+
"At least one remote target IP (IPv4 or IPv6) must be configured")
94+
95+
switch {
96+
case hasIPv4 && hasIPv6:
97+
By("Setting ipFamilyPolicy to 'RequireDualStack'")
98+
99+
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Dual-stack: setting ipFamilyPolicy to RequireDualStack")
100+
101+
return svcBuilder.WithIPFamily([]corev1.IPFamily{corev1.IPv4Protocol, corev1.IPv6Protocol},
102+
corev1.IPFamilyPolicyRequireDualStack)
103+
case hasIPv6:
104+
By("Setting ipFamilyPolicy to 'SingleStack' (IPv6)")
105+
106+
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("IPv6 only: setting ipFamilyPolicy to SingleStack")
107+
108+
return svcBuilder.WithIPFamily([]corev1.IPFamily{corev1.IPv6Protocol},
109+
corev1.IPFamilyPolicySingleStack)
110+
default:
111+
By("Setting ipFamilyPolicy to 'SingleStack' (IPv4)")
112+
113+
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("IPv4 only: setting ipFamilyPolicy to SingleStack")
114+
115+
return svcBuilder.WithIPFamily([]corev1.IPFamily{corev1.IPv4Protocol},
116+
corev1.IPFamilyPolicySingleStack)
117+
}
118+
}
119+
120+
// buildEgressClientIPCurlCmd returns a curl command that hits the remote /clientip endpoint.
121+
// hostIsIPv6 selects URL form (IPv6 literals must appear in brackets).
122+
func buildEgressClientIPCurlCmd(host, port string, hostIsIPv6 bool) []string {
123+
var url string
124+
if hostIsIPv6 {
125+
url = fmt.Sprintf("http://[%s]:%s/clientip", host, port)
126+
} else {
127+
url = fmt.Sprintf("http://%s:%s/clientip", host, port)
128+
}
129+
130+
return []string{"/bin/bash", "-c", fmt.Sprintf("curl --connect-timeout 3 -Ls %s", url)}
131+
}
132+
87133
func deleteService(svcName, svcNSName string) {
88134
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Deleting service %q in %q ns", svcName, svcNSName)
89135

@@ -382,12 +428,7 @@ func VerifyEgressServiceETPClusterWrapper(
382428
svcBuilder = svcBuilder.WithAnnotation(map[string]string{
383429
"metallb.universe.tf/address-pool": ipAddrPoolName})
384430

385-
By("Setting ipFamilyPolicy to 'RequireDualStack'")
386-
387-
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Setting ipFamilyPolicy to 'RequireDualStack'")
388-
389-
svcBuilder = svcBuilder.WithIPFamily([]corev1.IPFamily{"IPv4", "IPv6"},
390-
corev1.IPFamilyPolicyRequireDualStack)
431+
svcBuilder = applyIPFamilyPolicy(svcBuilder, remoteTargetIP, remoteTargetIPv6)
391432

392433
By("Creating a service")
393434

@@ -506,15 +547,11 @@ func VerifyEgressServiceETPClusterWrapper(
506547
if myIP.Is4() {
507548
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Processing IPv4 address")
508549

509-
cmdToRun = []string{"/bin/bash", "-c",
510-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
511-
remoteTargetIP, remoteTargetPort)}
550+
cmdToRun = buildEgressClientIPCurlCmd(remoteTargetIP, remoteTargetPort, false)
512551
} else {
513552
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Processing IPv6 address")
514553

515-
cmdToRun = []string{"/bin/bash", "-c",
516-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
517-
remoteTargetIPv6, remoteTargetPort)}
554+
cmdToRun = buildEgressClientIPCurlCmd(remoteTargetIPv6, remoteTargetPort, true)
518555
}
519556

520557
if strings.EqualFold(strings.TrimSpace(string(egrSVCBuilder.Object.Spec.SourceIPBy)), "Network") {
@@ -675,10 +712,7 @@ func VerifyEgressServiceWithLocalETPWrapper(
675712
svcBuilder = svcBuilder.WithAnnotation(map[string]string{
676713
"metallb.universe.tf/address-pool": ipAddrPoolName})
677714

678-
By("Setting ipFamilyPolicy to 'RequireDualStack'")
679-
680-
svcBuilder = svcBuilder.WithIPFamily([]corev1.IPFamily{"IPv4", "IPv6"},
681-
corev1.IPFamilyPolicyRequireDualStack)
715+
svcBuilder = applyIPFamilyPolicy(svcBuilder, remoteTargetIP, remoteTargetIPv6)
682716

683717
By("Creating a service")
684718
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Creating Service object")
@@ -795,17 +829,13 @@ func VerifyEgressServiceWithLocalETPWrapper(
795829
if myIP.Is4() {
796830
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Processing IPv4 address")
797831

798-
cmdToRun = []string{"/bin/bash", "-c",
799-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
800-
remoteTargetIP, remoteTargetPort)}
832+
cmdToRun = buildEgressClientIPCurlCmd(remoteTargetIP, remoteTargetPort, false)
801833

802834
expectedIP = remoteTargetIP
803835
} else {
804836
klog.V(rdscoreparams.RDSCoreLogLevel).Infof("Processing IPv6 address")
805837

806-
cmdToRun = []string{"/bin/bash", "-c",
807-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
808-
remoteTargetIPv6, remoteTargetPort)}
838+
cmdToRun = buildEgressClientIPCurlCmd(remoteTargetIPv6, remoteTargetPort, true)
809839

810840
expectedIP = remoteTargetIPv6
811841
}
@@ -950,76 +980,58 @@ func verifySourceIP(svcName, svcNS, podLabels string, cmdToRun []string, useIPv6
950980
}
951981
}
952982

953-
// VerifyEgressServiceConnectivityETPCluster verifies source IP address when external traffic policy
954-
// is set to Cluster.
955-
func VerifyEgressServiceConnectivityETPCluster() {
956-
cmdToRun := []string{"/bin/bash", "-c",
957-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
958-
RDSCoreConfig.EgressServiceRemoteIP, RDSCoreConfig.EgressServiceRemotePort)}
983+
// verifyEgressServiceConnectivity is the shared egress connectivity check; byPrefix labels Ginkgo By steps.
984+
func verifyEgressServiceConnectivity(svcName, svcNS, svcLabels, byPrefix string) {
985+
Expect(RDSCoreConfig.EgressServiceRemoteIP != "" || RDSCoreConfig.EgressServiceRemoteIPv6 != "").To(BeTrue(),
986+
"Neither EgressServiceRemoteIP nor EgressServiceRemoteIPv6 is configured")
987+
988+
if RDSCoreConfig.EgressServiceRemoteIP != "" {
989+
By(fmt.Sprintf("Verifying EgressService %s connectivity (IPv4)", byPrefix))
990+
991+
cmdToRun := buildEgressClientIPCurlCmd(RDSCoreConfig.EgressServiceRemoteIP,
992+
RDSCoreConfig.EgressServiceRemotePort, false)
993+
994+
verifySourceIP(svcName, svcNS, svcLabels, cmdToRun, false,
995+
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
996+
}
959997

960-
verifySourceIP(egressSVC1Name, RDSCoreConfig.EgressServiceNS, egressSVC1Labels, cmdToRun, false,
961-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
998+
if RDSCoreConfig.EgressServiceRemoteIPv6 != "" {
999+
By(fmt.Sprintf("Verifying EgressService %s connectivity (IPv6)", byPrefix))
9621000

963-
cmdToRun = []string{"/bin/bash", "-c",
964-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
965-
RDSCoreConfig.EgressServiceRemoteIPv6, RDSCoreConfig.EgressServiceRemotePort)}
1001+
cmdToRun := buildEgressClientIPCurlCmd(RDSCoreConfig.EgressServiceRemoteIPv6,
1002+
RDSCoreConfig.EgressServiceRemotePort, true)
9661003

967-
verifySourceIP(egressSVC1Name, RDSCoreConfig.EgressServiceNS, egressSVC1Labels, cmdToRun, true,
968-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
1004+
verifySourceIP(svcName, svcNS, svcLabels, cmdToRun, true,
1005+
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
1006+
}
1007+
}
1008+
1009+
// VerifyEgressServiceConnectivityETPCluster verifies source IP address when external traffic policy
1010+
// is set to Cluster.
1011+
func VerifyEgressServiceConnectivityETPCluster() {
1012+
verifyEgressServiceConnectivity(egressSVC1Name, RDSCoreConfig.EgressServiceNS, egressSVC1Labels,
1013+
"ETP=Cluster")
9691014
}
9701015

9711016
// VerifyEgressServiceConnectivityETPClusterSourceIPByNetwork verifies source IP address when external traffic policy
9721017
// is set to Cluster.
9731018
func VerifyEgressServiceConnectivityETPClusterSourceIPByNetwork() {
974-
cmdToRun := []string{"/bin/bash", "-c",
975-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
976-
RDSCoreConfig.EgressServiceRemoteIP, RDSCoreConfig.EgressServiceRemotePort)}
977-
978-
verifySourceIP(egressSVC3Name, RDSCoreConfig.EgressServiceNS, egressSVC3Labels, cmdToRun, false,
979-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
980-
981-
cmdToRun = []string{"/bin/bash", "-c",
982-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
983-
RDSCoreConfig.EgressServiceRemoteIPv6, RDSCoreConfig.EgressServiceRemotePort)}
984-
985-
verifySourceIP(egressSVC3Name, RDSCoreConfig.EgressServiceNS, egressSVC3Labels, cmdToRun, true,
986-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
1019+
verifyEgressServiceConnectivity(egressSVC3Name, RDSCoreConfig.EgressServiceNS, egressSVC3Labels,
1020+
"ETP=Cluster sourceIPBy=Network")
9871021
}
9881022

9891023
// VerifyEgressServiceConnectivityETPLocal verifies source IP address when external traffic policy
9901024
// is set to Local.
9911025
func VerifyEgressServiceConnectivityETPLocal() {
992-
cmdToRun := []string{"/bin/bash", "-c",
993-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
994-
RDSCoreConfig.EgressServiceRemoteIP, RDSCoreConfig.EgressServiceRemotePort)}
995-
996-
verifySourceIP(egressSVC2Name, RDSCoreConfig.EgressServiceNS, egressSVC2Labels, cmdToRun, false,
997-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
998-
999-
cmdToRun = []string{"/bin/bash", "-c",
1000-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
1001-
RDSCoreConfig.EgressServiceRemoteIPv6, RDSCoreConfig.EgressServiceRemotePort)}
1002-
1003-
verifySourceIP(egressSVC2Name, RDSCoreConfig.EgressServiceNS, egressSVC2Labels, cmdToRun, true,
1004-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
1026+
verifyEgressServiceConnectivity(egressSVC2Name, RDSCoreConfig.EgressServiceNS, egressSVC2Labels,
1027+
"ETP=Local")
10051028
}
10061029

10071030
// VerifyEgressServiceConnectivityETPLocalSourceIPByNetwork verifies source IP address when external traffic policy
10081031
// is set to Local and sourceIPBy=Network.
10091032
func VerifyEgressServiceConnectivityETPLocalSourceIPByNetwork() {
1010-
cmdToRun := []string{"/bin/bash", "-c",
1011-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://%s:%s/clientip",
1012-
RDSCoreConfig.EgressServiceRemoteIP, RDSCoreConfig.EgressServiceRemotePort)}
1013-
1014-
verifySourceIP(egressSVC4Name, RDSCoreConfig.EgressServiceNS, egressSVC4Labels, cmdToRun, false,
1015-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
1016-
1017-
cmdToRun = []string{"/bin/bash", "-c",
1018-
fmt.Sprintf("curl --connect-timeout 3 -Ls http://[%s]:%s/clientip",
1019-
RDSCoreConfig.EgressServiceRemoteIPv6, RDSCoreConfig.EgressServiceRemotePort)}
1020-
1021-
verifySourceIP(egressSVC4Name, RDSCoreConfig.EgressServiceNS, egressSVC4Labels, cmdToRun, true,
1022-
RDSCoreConfig.EgressServiceNetworkExpectedIPs)
1033+
verifyEgressServiceConnectivity(egressSVC4Name, RDSCoreConfig.EgressServiceNS, egressSVC4Labels,
1034+
"ETP=Local sourceIPBy=Network")
10231035
}
10241036

10251037
// VerifyEgressServiceETPLocalIngressConnectivity verifies ingress IP address while accessing backend pods

0 commit comments

Comments
 (0)