diff --git a/api/v1alpha1/shared_types.go b/api/v1alpha1/shared_types.go index e2ce9dc55c..5636d77607 100644 --- a/api/v1alpha1/shared_types.go +++ b/api/v1alpha1/shared_types.go @@ -231,7 +231,7 @@ type KubernetesContainerSpec struct { // Image specifies the EnvoyProxy container image to be used including a tag, instead of the default image. // This field is mutually exclusive with ImageRepository. // - // +kubebuilder:validation:XValidation:rule="self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$')",message="Image must include a tag and allowed characters only (e.g., 'repo:tag')." + // +kubebuilder:validation:XValidation:rule="self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$')",message="Image must include a tag and allowed characters only (e.g., 'repo:tag')." // +optional Image *string `json:"image,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 e5e0dcee63..9a00ee43ff 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 @@ -614,7 +614,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. @@ -4459,7 +4459,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. 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 4a8675fdba..3c509d8a03 100644 --- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml +++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyproxies.yaml @@ -613,7 +613,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. @@ -4458,7 +4458,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go index 5ec5f57bd3..34b76adc0e 100644 --- a/test/cel-validation/envoyproxy_test.go +++ b/test/cel-validation/envoyproxy_test.go @@ -1669,6 +1669,42 @@ func TestEnvoyProxyProvider(t *testing.T) { }, wantErrors: []string{}, }, + { + desc: "valid: imageRepository with ip and 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("192.168.1.1:8000"), + }, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "valid: imageRepository with domain and 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("registry.com:8000"), + }, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, { desc: "valid: imageRepository set without tag, image not set", mutate: func(envoy *egv1a1.EnvoyProxy) { @@ -1760,6 +1796,42 @@ func TestEnvoyProxyProvider(t *testing.T) { }, wantErrors: []string{"Image must include a tag and allowed characters only (e.g., 'repo:tag')."}, }, + { + desc: "valid: image with domain and 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{ + Image: ptr.To("registry.com:3000/envoy:v1.2.3"), + }, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, + { + desc: "valid: image with ip and 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{ + Image: ptr.To("127.0.0.1:3000/envoy:v1.2.3"), + }, + }, + }, + }, + } + }, + wantErrors: []string{}, + }, { desc: "invalid: imageRepository contains tag", mutate: func(envoy *egv1a1.EnvoyProxy) { diff --git a/test/helm/gateway-crds-helm/all.out.yaml b/test/helm/gateway-crds-helm/all.out.yaml index 895e9850ff..74272c314f 100644 --- a/test/helm/gateway-crds-helm/all.out.yaml +++ b/test/helm/gateway-crds-helm/all.out.yaml @@ -24542,7 +24542,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. @@ -28387,7 +28387,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. 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 ca7d5d0fcf..2f5eba0e69 100644 --- a/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml +++ b/test/helm/gateway-crds-helm/envoy-gateway-crds.out.yaml @@ -7230,7 +7230,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag. @@ -11075,7 +11075,7 @@ spec: x-kubernetes-validations: - message: Image must include a tag and allowed characters only (e.g., 'repo:tag'). - rule: self.matches('^[a-zA-Z0-9._/-]+(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') + rule: self.matches('^[a-zA-Z0-9._-]+(:[0-9]+)?(/[a-zA-Z0-9._/-]+)?(:[a-zA-Z0-9._-]+)?(@sha256:[a-z0-9]+)?$') imageRepository: description: |- ImageRepository specifies the container image repository to be used without specifying a tag.