Repository: envoyproxy/gateway

Issue:
imageRepository may contains colons, for example imageRepository use custom port
https://github.com/envoyproxy/gateway/blob/8d32d0fc034c561d91dbf76e2abede75dcb6a4da/api/v1alpha1/shared_types.go#L242

Hints from issue comments:
@woodgear: registry.xxx.cn:60080/xx/envoyproxy/gateway:v1.5.0-rc.1


Solution patch:
diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go
index 797fbece6..f9bff1d18 100644
--- a/api/v1alpha1/shared_types.go
+++ b/api/v1alpha1/shared_types.go
@@ -239,7 +239,7 @@ type KubernetesContainerSpec struct {
 	// The default tag will be used.
 	// This field is mutually exclusive with Image.
 	//
-	// +kubebuilder:validation:XValidation:rule="self.matches('^[a-zA-Z0-9._/-]+$')",message="ImageRepository must contain only allowed characters and must not include a tag or any colons."
+	// +kubebuilder:validation:XValidation:rule="self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')",message="ImageRepository must contain only allowed characters and must not include a tag."
 	// +optional
 	ImageRepository *string `json:"imageRepository,omitempty"`
 
diff --git a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 5cb364725..bca62d14d 100644
--- a/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-crds-helm/templates/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -623,8 +623,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.
@@ -4468,8 +4468,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
index 6302ee471..fe454279c 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml
@@ -622,8 +622,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.
@@ -4467,8 +4467,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.



Test patch:
diff --git a/internal/infrastructure/kubernetes/proxy/resource_test.go b/internal/infrastructure/kubernetes/proxy/resource_test.go
index 8025b7b05..bcf5de36f 100644
--- a/internal/infrastructure/kubernetes/proxy/resource_test.go
+++ b/internal/infrastructure/kubernetes/proxy/resource_test.go
@@ -105,6 +105,13 @@ func TestResolveProxyImage(t *testing.T) {
 			},
 			expected: fmt.Sprintf("envoyproxy/envoy:%s", defaultTag),
 		},
+		{
+			name: "imageRepository with port",
+			container: &egv1a1.KubernetesContainerSpec{
+				ImageRepository: ptr.To("docker.io:443/envoyproxy/envoy"),
+			},
+			expected: fmt.Sprintf("docker.io:443/envoyproxy/envoy:%s", defaultTag),
+		},
 	}
 
 	for _, tc := range tests {
diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go
index cd0e37995..0f7bf5d6b 100644
--- a/test/cel-validation/envoyproxy_test.go
+++ b/test/cel-validation/envoyproxy_test.go
@@ -1740,7 +1740,43 @@ func TestEnvoyProxyProvider(t *testing.T) {
 					},
 				}
 			},
-			wantErrors: []string{"ImageRepository must contain only allowed characters and must not include a tag or any colons."},
+			wantErrors: []string{"ImageRepository must contain only allowed characters and must not include a tag."},
+		},
+		{
+			desc: "valid: imageRepository set with port",
+			mutate: func(envoy *egv1a1.EnvoyProxy) {
+				envoy.Spec = egv1a1.EnvoyProxySpec{
+					Provider: &egv1a1.EnvoyProxyProvider{
+						Type: egv1a1.ProviderTypeKubernetes,
+						Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{
+							EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{
+								Container: &egv1a1.KubernetesContainerSpec{
+									ImageRepository: ptr.To("docker.io:443/envoyproxy/envoy"),
+								},
+							},
+						},
+					},
+				}
+			},
+			wantErrors: []string{},
+		},
+		{
+			desc: "invalid: imageRepository set with port and tag",
+			mutate: func(envoy *egv1a1.EnvoyProxy) {
+				envoy.Spec = egv1a1.EnvoyProxySpec{
+					Provider: &egv1a1.EnvoyProxyProvider{
+						Type: egv1a1.ProviderTypeKubernetes,
+						Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{
+							EnvoyDeployment: &egv1a1.KubernetesDeploymentSpec{
+								Container: &egv1a1.KubernetesContainerSpec{
+									ImageRepository: ptr.To("docker.io:443/envoyproxy/envoy:v1.2.3"),
+								},
+							},
+						},
+					},
+				}
+			},
+			wantErrors: []string{"ImageRepository must contain only allowed characters and must not include a tag."},
 		},
 	}
 
diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml
index 3bc2a49e1..c32cc359f 100644
--- a/test/helm/gateway-crds-helm/all.out.yaml
+++ b/test/helm/gateway-crds-helm/all.out.yaml
@@ -24547,8 +24547,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.
@@ -28392,8 +28392,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.
diff --git a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
index 4ab5cb551..bf8389a94 100644
--- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
+++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml
@@ -7235,8 +7235,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.
@@ -11080,8 +11080,8 @@ spec:
                                 type: string
                                 x-kubernetes-validations:
                                 - message: ImageRepository must contain only allowed
-                                    characters and must not include a tag or any colons.
-                                  rule: self.matches('^[a-zA-Z0-9._/-]+$')
+                                    characters and must not include a tag.
+                                  rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?[a-zA-Z0-9._/-]+$')
                               resources:
                                 description: |-
                                   Resources required by this container.