diff --git a/pkg/api/pod/warnings.go b/pkg/api/pod/warnings.go index 31a66b116be..d062373a2df 100644 --- a/pkg/api/pod/warnings.go +++ b/pkg/api/pod/warnings.go @@ -252,6 +252,17 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta } } } + // duplicate containers[*].ports + if len(c.Ports) > 1 { + ports := sets.NewInt64() + for i, port := range c.Ports { + if ports.Has(int64(port.ContainerPort)) { + warnings = append(warnings, fmt.Sprintf("%s: duplicate container port %d", p.Child("ports").Index(i).Child("containerPort"), port.ContainerPort)) + } else { + ports.Insert(int64(port.ContainerPort)) + } + } + } return true }) diff --git a/pkg/api/pod/warnings_test.go b/pkg/api/pod/warnings_test.go index e849fb37bef..ee7e507577e 100644 --- a/pkg/api/pod/warnings_test.go +++ b/pkg/api/pod/warnings_test.go @@ -24,7 +24,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" api "k8s.io/kubernetes/pkg/apis/core" - utilpointer "k8s.io/utils/pointer" ) func BenchmarkNoWarnings(b *testing.B) { @@ -599,6 +598,59 @@ func TestWarnings(t *testing.T) { `spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[1].podAffinityTerm.labelSelector: a null labelSelector results in matching no pod`, }, }, + { + name: "no duplicate container ports", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Containers: []api.Container{{ + Name: "foo", + Ports: []api.ContainerPort{ + {ContainerPort: 80, HostPort: 80}, + }, + }}, + }}, + expected: []string{}, + }, + + { + name: "duplicate container ports", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Containers: []api.Container{{ + Name: "foo", + Ports: []api.ContainerPort{ + {ContainerPort: 80, HostPort: 80}, + {ContainerPort: 80, HostPort: 80}, + }, + }}, + }}, + expected: []string{ + `spec.containers[0].ports[1].containerPort: duplicate container port 80`, + }, + }, + { + name: "duplicate container ports in two containers", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "foo1", + Ports: []api.ContainerPort{ + {ContainerPort: 80, HostPort: 80}, + {ContainerPort: 180, HostPort: 80}, + {ContainerPort: 80, HostPort: 80}, + }, + }, + { + Name: "foo", + Ports: []api.ContainerPort{ + {ContainerPort: 80, HostPort: 80}, + {ContainerPort: 80, HostPort: 80}, + }, + }}, + }}, + expected: []string{ + `spec.containers[0].ports[2].containerPort: duplicate container port 80`, + `spec.containers[1].ports[1].containerPort: duplicate container port 80`, + }, + }, } for _, tc := range testcases {