Copilot commented on code in PR #2600:
URL: 
https://github.com/apache/apisix-ingress-controller/pull/2600#discussion_r2426066583


##########
test/e2e/webhook/gatewayproxy.go:
##########
@@ -121,9 +122,151 @@ stringData:
                err = s.DeleteResource("GatewayProxy", gpName)
                Expect(err).ShouldNot(HaveOccurred())
 
-               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gpWithSecrets, gpName, 
missingService, missingSecret))
+               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gatewayProxyTemplate, 
gpName, missingService, missingSecret))
                Expect(err).ShouldNot(HaveOccurred())
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Referenced Service '%s/%s' not found", s.Namespace(), missingService)))
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Secret key 'token' not found in Secret '%s/%s'", s.Namespace(), missingSecret)))
        })
+
+       Context("GatewayProxy configuration conflicts", func() {
+               It("should reject GatewayProxy that reuses the same Service and 
AdminKey Secret as an existing one on create and update", func() {
+                       serviceTemplate := `
+apiVersion: v1
+kind: Service
+metadata:
+  name: %s
+spec:
+  selector:
+    app: dummy-control-plane
+  ports:
+  - name: admin
+    port: 9180
+    targetPort: 9180
+`
+                       secretTemplate := `
+apiVersion: v1
+kind: Secret
+metadata:
+  name: %s
+type: Opaque
+stringData:
+  %s: %s
+`
+                       serviceName := "gatewayproxy-shared-service"
+                       secretName := "gatewayproxy-shared-secret"
+                       initialProxy := "gatewayproxy-shared-primary"
+                       conflictingProxy := "gatewayproxy-shared-conflict"
+
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
serviceName))).ShouldNot(HaveOccurred(), "creating shared Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(secretTemplate, secretName, 
"token", "value"))).ShouldNot(HaveOccurred(), "creating shared Secret")
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, initialProxy, 
serviceName, secretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating initial 
GatewayProxy")
+
+                       time.Sleep(2 * time.Second)

Review Comment:
   Hard-coded sleep statements in tests are fragile and slow down test 
execution. Consider using a polling mechanism or event-driven approach to wait 
for the resource to be properly registered in the webhook system.
   ```suggestion
                        Eventually(func() error {
                                // Replace with a check for GatewayProxy 
readiness/existence.
                                // If s.GetResource returns error when not 
found, this works.
                                return s.GetResource("GatewayProxy", 
initialProxy)
                        }, 10*time.Second, 
500*time.Millisecond).Should(Succeed(), "waiting for initial GatewayProxy to be 
registered")
   ```



##########
test/e2e/webhook/gatewayproxy.go:
##########
@@ -121,9 +122,151 @@ stringData:
                err = s.DeleteResource("GatewayProxy", gpName)
                Expect(err).ShouldNot(HaveOccurred())
 
-               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gpWithSecrets, gpName, 
missingService, missingSecret))
+               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gatewayProxyTemplate, 
gpName, missingService, missingSecret))
                Expect(err).ShouldNot(HaveOccurred())
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Referenced Service '%s/%s' not found", s.Namespace(), missingService)))
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Secret key 'token' not found in Secret '%s/%s'", s.Namespace(), missingSecret)))
        })
+
+       Context("GatewayProxy configuration conflicts", func() {
+               It("should reject GatewayProxy that reuses the same Service and 
AdminKey Secret as an existing one on create and update", func() {
+                       serviceTemplate := `
+apiVersion: v1
+kind: Service
+metadata:
+  name: %s
+spec:
+  selector:
+    app: dummy-control-plane
+  ports:
+  - name: admin
+    port: 9180
+    targetPort: 9180
+`
+                       secretTemplate := `
+apiVersion: v1
+kind: Secret
+metadata:
+  name: %s
+type: Opaque
+stringData:
+  %s: %s
+`
+                       serviceName := "gatewayproxy-shared-service"
+                       secretName := "gatewayproxy-shared-secret"
+                       initialProxy := "gatewayproxy-shared-primary"
+                       conflictingProxy := "gatewayproxy-shared-conflict"
+
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
serviceName))).ShouldNot(HaveOccurred(), "creating shared Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(secretTemplate, secretName, 
"token", "value"))).ShouldNot(HaveOccurred(), "creating shared Secret")
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, initialProxy, 
serviceName, secretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating initial 
GatewayProxy")
+
+                       time.Sleep(2 * time.Second)
+
+                       err = 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, conflictingProxy, 
serviceName, secretName))
+                       Expect(err).Should(HaveOccurred(), "expecting conflict 
for duplicated GatewayProxy")
+                       Expect(err.Error()).To(ContainSubstring("gateway proxy 
configuration conflict"))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
conflictingProxy)))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
initialProxy)))
+                       Expect(err.Error()).To(ContainSubstring("Service"))
+                       Expect(err.Error()).To(ContainSubstring("AdminKey 
secret"))
+
+                       Expect(s.DeleteResource("GatewayProxy", 
initialProxy)).ShouldNot(HaveOccurred())
+                       Expect(s.DeleteResource("Service", 
serviceName)).ShouldNot(HaveOccurred())
+                       Expect(s.DeleteResource("Secret", 
secretName)).ShouldNot(HaveOccurred())
+               })
+
+               It("should reject GatewayProxy that overlaps endpoints when 
sharing inline AdminKey value", func() {
+                       gatewayProxyTemplate := `
+apiVersion: apisix.apache.org/v1alpha1
+kind: GatewayProxy
+metadata:
+  name: %s
+spec:
+  provider:
+    type: ControlPlane
+    controlPlane:
+      endpoints:
+      - %s
+      - %s
+      auth:
+        type: AdminKey
+        adminKey:
+          value: "%s"
+`
+
+                       existingProxy := "gatewayproxy-inline-primary"
+                       conflictingProxy := "gatewayproxy-inline-conflict"
+                       endpointA := "https://127.0.0.1:9443";
+                       endpointB := "https://10.0.0.1:9443";
+                       endpointC := "https://192.168.0.1:9443";
+                       inlineKey := "inline-credential"
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, existingProxy, 
endpointA, endpointB, inlineKey))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating 
GatewayProxy with inline AdminKey")
+
+                       time.Sleep(2 * time.Second)

Review Comment:
   Multiple hard-coded sleep statements suggest a systematic issue with test 
timing. Consider implementing a helper function that polls for resource 
readiness or uses the Kubernetes client's watch functionality to wait for 
proper resource state.



##########
test/e2e/webhook/gatewayproxy.go:
##########
@@ -121,9 +122,151 @@ stringData:
                err = s.DeleteResource("GatewayProxy", gpName)
                Expect(err).ShouldNot(HaveOccurred())
 
-               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gpWithSecrets, gpName, 
missingService, missingSecret))
+               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gatewayProxyTemplate, 
gpName, missingService, missingSecret))
                Expect(err).ShouldNot(HaveOccurred())
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Referenced Service '%s/%s' not found", s.Namespace(), missingService)))
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Secret key 'token' not found in Secret '%s/%s'", s.Namespace(), missingSecret)))
        })
+
+       Context("GatewayProxy configuration conflicts", func() {
+               It("should reject GatewayProxy that reuses the same Service and 
AdminKey Secret as an existing one on create and update", func() {
+                       serviceTemplate := `
+apiVersion: v1
+kind: Service
+metadata:
+  name: %s
+spec:
+  selector:
+    app: dummy-control-plane
+  ports:
+  - name: admin
+    port: 9180
+    targetPort: 9180
+`
+                       secretTemplate := `
+apiVersion: v1
+kind: Secret
+metadata:
+  name: %s
+type: Opaque
+stringData:
+  %s: %s
+`
+                       serviceName := "gatewayproxy-shared-service"
+                       secretName := "gatewayproxy-shared-secret"
+                       initialProxy := "gatewayproxy-shared-primary"
+                       conflictingProxy := "gatewayproxy-shared-conflict"
+
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
serviceName))).ShouldNot(HaveOccurred(), "creating shared Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(secretTemplate, secretName, 
"token", "value"))).ShouldNot(HaveOccurred(), "creating shared Secret")
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, initialProxy, 
serviceName, secretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating initial 
GatewayProxy")
+
+                       time.Sleep(2 * time.Second)
+
+                       err = 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, conflictingProxy, 
serviceName, secretName))
+                       Expect(err).Should(HaveOccurred(), "expecting conflict 
for duplicated GatewayProxy")
+                       Expect(err.Error()).To(ContainSubstring("gateway proxy 
configuration conflict"))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
conflictingProxy)))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
initialProxy)))
+                       Expect(err.Error()).To(ContainSubstring("Service"))
+                       Expect(err.Error()).To(ContainSubstring("AdminKey 
secret"))
+
+                       Expect(s.DeleteResource("GatewayProxy", 
initialProxy)).ShouldNot(HaveOccurred())
+                       Expect(s.DeleteResource("Service", 
serviceName)).ShouldNot(HaveOccurred())
+                       Expect(s.DeleteResource("Secret", 
secretName)).ShouldNot(HaveOccurred())
+               })
+
+               It("should reject GatewayProxy that overlaps endpoints when 
sharing inline AdminKey value", func() {
+                       gatewayProxyTemplate := `
+apiVersion: apisix.apache.org/v1alpha1
+kind: GatewayProxy
+metadata:
+  name: %s
+spec:
+  provider:
+    type: ControlPlane
+    controlPlane:
+      endpoints:
+      - %s
+      - %s
+      auth:
+        type: AdminKey
+        adminKey:
+          value: "%s"
+`
+
+                       existingProxy := "gatewayproxy-inline-primary"
+                       conflictingProxy := "gatewayproxy-inline-conflict"
+                       endpointA := "https://127.0.0.1:9443";
+                       endpointB := "https://10.0.0.1:9443";
+                       endpointC := "https://192.168.0.1:9443";
+                       inlineKey := "inline-credential"
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, existingProxy, 
endpointA, endpointB, inlineKey))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating 
GatewayProxy with inline AdminKey")
+
+                       time.Sleep(2 * time.Second)
+
+                       err = 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, conflictingProxy, 
endpointB, endpointC, inlineKey))
+                       Expect(err).Should(HaveOccurred(), "expecting conflict 
for overlapping endpoints with shared AdminKey")
+                       Expect(err.Error()).To(ContainSubstring("gateway proxy 
configuration conflict"))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
conflictingProxy)))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
existingProxy)))
+                       Expect(err.Error()).To(ContainSubstring("control plane 
endpoints"))
+                       Expect(err.Error()).To(ContainSubstring("inline 
AdminKey value"))
+               })
+
+               It("should reject GatewayProxy update that creates conflict 
with another GatewayProxy", func() {
+                       serviceTemplate := `
+apiVersion: v1
+kind: Service
+metadata:
+  name: %s
+spec:
+  selector:
+    app: dummy-control-plane
+  ports:
+  - name: admin
+    port: 9180
+    targetPort: 9180
+`
+                       secretTemplate := `
+apiVersion: v1
+kind: Secret
+metadata:
+  name: %s
+type: Opaque
+stringData:
+  %s: %s
+`
+                       sharedServiceName := 
"gatewayproxy-update-shared-service"
+                       sharedSecretName := "gatewayproxy-update-shared-secret"
+                       uniqueServiceName := 
"gatewayproxy-update-unique-service"
+                       proxyA := "gatewayproxy-update-a"
+                       proxyB := "gatewayproxy-update-b"
+
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
sharedServiceName))).ShouldNot(HaveOccurred(), "creating shared Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
uniqueServiceName))).ShouldNot(HaveOccurred(), "creating unique Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(secretTemplate, sharedSecretName, 
"token", "value"))).ShouldNot(HaveOccurred(), "creating shared Secret")
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, proxyA, 
sharedServiceName, sharedSecretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating 
GatewayProxy A with shared Service and Secret")
+
+                       time.Sleep(2 * time.Second)
+
+                       err = 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, proxyB, 
uniqueServiceName, sharedSecretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating 
GatewayProxy B with unique Service but same Secret")
+
+                       time.Sleep(2 * time.Second)

Review Comment:
   Multiple hard-coded sleep statements suggest a systematic issue with test 
timing. Consider implementing a helper function that polls for resource 
readiness or uses the Kubernetes client's watch functionality to wait for 
proper resource state.



##########
test/e2e/webhook/gatewayproxy.go:
##########
@@ -121,9 +122,151 @@ stringData:
                err = s.DeleteResource("GatewayProxy", gpName)
                Expect(err).ShouldNot(HaveOccurred())
 
-               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gpWithSecrets, gpName, 
missingService, missingSecret))
+               output, err = 
s.CreateResourceFromStringAndGetOutput(fmt.Sprintf(gatewayProxyTemplate, 
gpName, missingService, missingSecret))
                Expect(err).ShouldNot(HaveOccurred())
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Referenced Service '%s/%s' not found", s.Namespace(), missingService)))
                Expect(output).NotTo(ContainSubstring(fmt.Sprintf("Warning: 
Secret key 'token' not found in Secret '%s/%s'", s.Namespace(), missingSecret)))
        })
+
+       Context("GatewayProxy configuration conflicts", func() {
+               It("should reject GatewayProxy that reuses the same Service and 
AdminKey Secret as an existing one on create and update", func() {
+                       serviceTemplate := `
+apiVersion: v1
+kind: Service
+metadata:
+  name: %s
+spec:
+  selector:
+    app: dummy-control-plane
+  ports:
+  - name: admin
+    port: 9180
+    targetPort: 9180
+`
+                       secretTemplate := `
+apiVersion: v1
+kind: Secret
+metadata:
+  name: %s
+type: Opaque
+stringData:
+  %s: %s
+`
+                       serviceName := "gatewayproxy-shared-service"
+                       secretName := "gatewayproxy-shared-secret"
+                       initialProxy := "gatewayproxy-shared-primary"
+                       conflictingProxy := "gatewayproxy-shared-conflict"
+
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
serviceName))).ShouldNot(HaveOccurred(), "creating shared Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(secretTemplate, secretName, 
"token", "value"))).ShouldNot(HaveOccurred(), "creating shared Secret")
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, initialProxy, 
serviceName, secretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating initial 
GatewayProxy")
+
+                       time.Sleep(2 * time.Second)
+
+                       err = 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, conflictingProxy, 
serviceName, secretName))
+                       Expect(err).Should(HaveOccurred(), "expecting conflict 
for duplicated GatewayProxy")
+                       Expect(err.Error()).To(ContainSubstring("gateway proxy 
configuration conflict"))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
conflictingProxy)))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
initialProxy)))
+                       Expect(err.Error()).To(ContainSubstring("Service"))
+                       Expect(err.Error()).To(ContainSubstring("AdminKey 
secret"))
+
+                       Expect(s.DeleteResource("GatewayProxy", 
initialProxy)).ShouldNot(HaveOccurred())
+                       Expect(s.DeleteResource("Service", 
serviceName)).ShouldNot(HaveOccurred())
+                       Expect(s.DeleteResource("Secret", 
secretName)).ShouldNot(HaveOccurred())
+               })
+
+               It("should reject GatewayProxy that overlaps endpoints when 
sharing inline AdminKey value", func() {
+                       gatewayProxyTemplate := `
+apiVersion: apisix.apache.org/v1alpha1
+kind: GatewayProxy
+metadata:
+  name: %s
+spec:
+  provider:
+    type: ControlPlane
+    controlPlane:
+      endpoints:
+      - %s
+      - %s
+      auth:
+        type: AdminKey
+        adminKey:
+          value: "%s"
+`
+
+                       existingProxy := "gatewayproxy-inline-primary"
+                       conflictingProxy := "gatewayproxy-inline-conflict"
+                       endpointA := "https://127.0.0.1:9443";
+                       endpointB := "https://10.0.0.1:9443";
+                       endpointC := "https://192.168.0.1:9443";
+                       inlineKey := "inline-credential"
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, existingProxy, 
endpointA, endpointB, inlineKey))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating 
GatewayProxy with inline AdminKey")
+
+                       time.Sleep(2 * time.Second)
+
+                       err = 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, conflictingProxy, 
endpointB, endpointC, inlineKey))
+                       Expect(err).Should(HaveOccurred(), "expecting conflict 
for overlapping endpoints with shared AdminKey")
+                       Expect(err.Error()).To(ContainSubstring("gateway proxy 
configuration conflict"))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
conflictingProxy)))
+                       
Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("%s/%s", s.Namespace(), 
existingProxy)))
+                       Expect(err.Error()).To(ContainSubstring("control plane 
endpoints"))
+                       Expect(err.Error()).To(ContainSubstring("inline 
AdminKey value"))
+               })
+
+               It("should reject GatewayProxy update that creates conflict 
with another GatewayProxy", func() {
+                       serviceTemplate := `
+apiVersion: v1
+kind: Service
+metadata:
+  name: %s
+spec:
+  selector:
+    app: dummy-control-plane
+  ports:
+  - name: admin
+    port: 9180
+    targetPort: 9180
+`
+                       secretTemplate := `
+apiVersion: v1
+kind: Secret
+metadata:
+  name: %s
+type: Opaque
+stringData:
+  %s: %s
+`
+                       sharedServiceName := 
"gatewayproxy-update-shared-service"
+                       sharedSecretName := "gatewayproxy-update-shared-secret"
+                       uniqueServiceName := 
"gatewayproxy-update-unique-service"
+                       proxyA := "gatewayproxy-update-a"
+                       proxyB := "gatewayproxy-update-b"
+
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
sharedServiceName))).ShouldNot(HaveOccurred(), "creating shared Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(serviceTemplate, 
uniqueServiceName))).ShouldNot(HaveOccurred(), "creating unique Service")
+                       
Expect(s.CreateResourceFromString(fmt.Sprintf(secretTemplate, sharedSecretName, 
"token", "value"))).ShouldNot(HaveOccurred(), "creating shared Secret")
+
+                       err := 
s.CreateResourceFromString(fmt.Sprintf(gatewayProxyTemplate, proxyA, 
sharedServiceName, sharedSecretName))
+                       Expect(err).ShouldNot(HaveOccurred(), "creating 
GatewayProxy A with shared Service and Secret")
+
+                       time.Sleep(2 * time.Second)

Review Comment:
   Multiple hard-coded sleep statements suggest a systematic issue with test 
timing. Consider implementing a helper function that polls for resource 
readiness or uses the Kubernetes client's watch functionality to wait for 
proper resource state.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to