mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	sync api/v1/pod/util with api/pod/util and remove DefaultContainers
This commit is contained in:
		@@ -47,5 +47,6 @@ go_test(
 | 
				
			|||||||
        "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
 | 
					        "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
 | 
				
			||||||
 | 
					        "//vendor/github.com/google/go-cmp/cmp:go_default_library",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,6 @@ import (
 | 
				
			|||||||
// ContainerType signifies container type
 | 
					// ContainerType signifies container type
 | 
				
			||||||
type ContainerType int
 | 
					type ContainerType int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DefaultContainers defines default behavior: Iterate containers based on feature gates
 | 
					 | 
				
			||||||
const DefaultContainers ContainerType = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	// Containers is for normal containers
 | 
						// Containers is for normal containers
 | 
				
			||||||
	Containers ContainerType = 1 << iota
 | 
						Containers ContainerType = 1 << iota
 | 
				
			||||||
@@ -44,35 +41,40 @@ const (
 | 
				
			|||||||
// AllContainers specifies that all containers be visited
 | 
					// AllContainers specifies that all containers be visited
 | 
				
			||||||
const AllContainers ContainerType = (InitContainers | Containers | EphemeralContainers)
 | 
					const AllContainers ContainerType = (InitContainers | Containers | EphemeralContainers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllFeatureEnabledContainers returns a ContainerType mask which includes all container
 | 
				
			||||||
 | 
					// types except for the ones guarded by feature gate.
 | 
				
			||||||
 | 
					func AllFeatureEnabledContainers() ContainerType {
 | 
				
			||||||
 | 
						containerType := AllContainers
 | 
				
			||||||
 | 
						if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) {
 | 
				
			||||||
 | 
							containerType &= ^EphemeralContainers
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return containerType
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContainerVisitor is called with each container spec, and returns true
 | 
					// ContainerVisitor is called with each container spec, and returns true
 | 
				
			||||||
// if visiting should continue.
 | 
					// if visiting should continue.
 | 
				
			||||||
type ContainerVisitor func(container *api.Container, containerType ContainerType) (shouldContinue bool)
 | 
					type ContainerVisitor func(container *api.Container, containerType ContainerType) (shouldContinue bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// VisitContainers invokes the visitor function with a pointer to the container
 | 
					// VisitContainers invokes the visitor function with a pointer to every container
 | 
				
			||||||
// spec of every container in the given pod spec. If visitor returns false,
 | 
					// spec in the given pod spec with type set in mask. If visitor returns false,
 | 
				
			||||||
// visiting is short-circuited. VisitContainers returns true if visiting completes,
 | 
					// visiting is short-circuited. VisitContainers returns true if visiting completes,
 | 
				
			||||||
// false if visiting was short-circuited.
 | 
					// false if visiting was short-circuited.
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// With the default mask (zero value or DefaultContainers) VisitContainers will visit all containers
 | 
					 | 
				
			||||||
// enabled by current feature gates. If mask is non-zero, VisitContainers will unconditionally visit
 | 
					 | 
				
			||||||
// container types specified by mask, and no feature gate checks will be performed.
 | 
					 | 
				
			||||||
func VisitContainers(podSpec *api.PodSpec, mask ContainerType, visitor ContainerVisitor) bool {
 | 
					func VisitContainers(podSpec *api.PodSpec, mask ContainerType, visitor ContainerVisitor) bool {
 | 
				
			||||||
	if mask == DefaultContainers || (mask&InitContainers) > 0 {
 | 
						if mask&InitContainers != 0 {
 | 
				
			||||||
		for i := range podSpec.InitContainers {
 | 
							for i := range podSpec.InitContainers {
 | 
				
			||||||
			if !visitor(&podSpec.InitContainers[i], InitContainers) {
 | 
								if !visitor(&podSpec.InitContainers[i], InitContainers) {
 | 
				
			||||||
				return false
 | 
									return false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if mask == DefaultContainers || (mask&Containers) > 0 {
 | 
						if mask&Containers != 0 {
 | 
				
			||||||
		for i := range podSpec.Containers {
 | 
							for i := range podSpec.Containers {
 | 
				
			||||||
			if !visitor(&podSpec.Containers[i], Containers) {
 | 
								if !visitor(&podSpec.Containers[i], Containers) {
 | 
				
			||||||
				return false
 | 
									return false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (mask == DefaultContainers && utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers)) ||
 | 
						if mask&EphemeralContainers != 0 {
 | 
				
			||||||
		(mask&EphemeralContainers) > 0 {
 | 
					 | 
				
			||||||
		for i := range podSpec.EphemeralContainers {
 | 
							for i := range podSpec.EphemeralContainers {
 | 
				
			||||||
			if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), EphemeralContainers) {
 | 
								if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), EphemeralContainers) {
 | 
				
			||||||
				return false
 | 
									return false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/google/go-cmp/cmp"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/api/resource"
 | 
						"k8s.io/apimachinery/pkg/api/resource"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/diff"
 | 
						"k8s.io/apimachinery/pkg/util/diff"
 | 
				
			||||||
@@ -35,74 +36,22 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestVisitContainers(t *testing.T) {
 | 
					func TestVisitContainers(t *testing.T) {
 | 
				
			||||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
		description string
 | 
							desc                       string
 | 
				
			||||||
		haveSpec    *api.PodSpec
 | 
							spec                       *api.PodSpec
 | 
				
			||||||
		wantNames   []string
 | 
							wantContainers             []string
 | 
				
			||||||
		mask                       ContainerType
 | 
							mask                       ContainerType
 | 
				
			||||||
 | 
							ephemeralContainersEnabled bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"empty podspec",
 | 
								desc:           "empty podspec",
 | 
				
			||||||
			&api.PodSpec{},
 | 
								spec:           &api.PodSpec{},
 | 
				
			||||||
			[]string{},
 | 
								wantContainers: []string{},
 | 
				
			||||||
			DefaultContainers,
 | 
								mask:           AllContainers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"regular containers",
 | 
								desc: "regular containers",
 | 
				
			||||||
			&api.PodSpec{
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
				Containers: []api.Container{
 | 
					 | 
				
			||||||
					{Name: "c1"},
 | 
					 | 
				
			||||||
					{Name: "c2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"c1", "c2"},
 | 
					 | 
				
			||||||
			DefaultContainers,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"init containers",
 | 
					 | 
				
			||||||
			&api.PodSpec{
 | 
					 | 
				
			||||||
				InitContainers: []api.Container{
 | 
					 | 
				
			||||||
					{Name: "i1"},
 | 
					 | 
				
			||||||
					{Name: "i2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"i1", "i2"},
 | 
					 | 
				
			||||||
			DefaultContainers,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"regular and init containers",
 | 
					 | 
				
			||||||
			&api.PodSpec{
 | 
					 | 
				
			||||||
				Containers: []api.Container{
 | 
					 | 
				
			||||||
					{Name: "c1"},
 | 
					 | 
				
			||||||
					{Name: "c2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				InitContainers: []api.Container{
 | 
					 | 
				
			||||||
					{Name: "i1"},
 | 
					 | 
				
			||||||
					{Name: "i2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2"},
 | 
					 | 
				
			||||||
			DefaultContainers,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ephemeral containers",
 | 
					 | 
				
			||||||
			&api.PodSpec{
 | 
					 | 
				
			||||||
				Containers: []api.Container{
 | 
					 | 
				
			||||||
					{Name: "c1"},
 | 
					 | 
				
			||||||
					{Name: "c2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				EphemeralContainers: []api.EphemeralContainer{
 | 
					 | 
				
			||||||
					{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e1"}},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"c1", "c2", "e1"},
 | 
					 | 
				
			||||||
			DefaultContainers,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"all container types",
 | 
					 | 
				
			||||||
			&api.PodSpec{
 | 
					 | 
				
			||||||
				Containers: []api.Container{
 | 
									Containers: []api.Container{
 | 
				
			||||||
					{Name: "c1"},
 | 
										{Name: "c1"},
 | 
				
			||||||
					{Name: "c2"},
 | 
										{Name: "c2"},
 | 
				
			||||||
@@ -116,12 +65,12 @@ func TestVisitContainers(t *testing.T) {
 | 
				
			|||||||
					{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
								wantContainers: []string{"c1", "c2"},
 | 
				
			||||||
			DefaultContainers,
 | 
								mask:           Containers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"all container types with init and regular container types chosen",
 | 
								desc: "init containers",
 | 
				
			||||||
			&api.PodSpec{
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
				Containers: []api.Container{
 | 
									Containers: []api.Container{
 | 
				
			||||||
					{Name: "c1"},
 | 
										{Name: "c1"},
 | 
				
			||||||
					{Name: "c2"},
 | 
										{Name: "c2"},
 | 
				
			||||||
@@ -135,12 +84,89 @@ func TestVisitContainers(t *testing.T) {
 | 
				
			|||||||
					{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2"},
 | 
								wantContainers: []string{"i1", "i2"},
 | 
				
			||||||
			Containers | InitContainers,
 | 
								mask:           InitContainers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"dropping fields",
 | 
								desc: "ephemeral containers",
 | 
				
			||||||
			&api.PodSpec{
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
 | 
									Containers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []api.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"e1", "e2"},
 | 
				
			||||||
 | 
								mask:           EphemeralContainers,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "all container types",
 | 
				
			||||||
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
 | 
									Containers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []api.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
				
			||||||
 | 
								mask:           AllContainers,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "all feature enabled container types with ephemeral containers disabled",
 | 
				
			||||||
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
 | 
									Containers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []api.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"i1", "i2", "c1", "c2"},
 | 
				
			||||||
 | 
								mask:           AllFeatureEnabledContainers(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "all feature enabled container types with ephemeral containers enabled",
 | 
				
			||||||
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
 | 
									Containers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2", SecurityContext: &api.SecurityContext{}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []api.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2", SecurityContext: &api.SecurityContext{}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []api.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers:             []string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
				
			||||||
 | 
								mask:                       AllFeatureEnabledContainers(),
 | 
				
			||||||
 | 
								ephemeralContainersEnabled: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "dropping fields",
 | 
				
			||||||
 | 
								spec: &api.PodSpec{
 | 
				
			||||||
				Containers: []api.Container{
 | 
									Containers: []api.Container{
 | 
				
			||||||
					{Name: "c1"},
 | 
										{Name: "c1"},
 | 
				
			||||||
					{Name: "c2", SecurityContext: &api.SecurityContext{}},
 | 
										{Name: "c2", SecurityContext: &api.SecurityContext{}},
 | 
				
			||||||
@@ -154,38 +180,45 @@ func TestVisitContainers(t *testing.T) {
 | 
				
			|||||||
					{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2", SecurityContext: &api.SecurityContext{}}},
 | 
										{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2", SecurityContext: &api.SecurityContext{}}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
								wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
				
			||||||
			DefaultContainers,
 | 
								mask:           AllContainers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		gotNames := []string{}
 | 
							t.Run(tc.desc, func(t *testing.T) {
 | 
				
			||||||
		VisitContainers(tc.haveSpec, tc.mask, func(c *api.Container, containerType ContainerType) bool {
 | 
								if tc.ephemeralContainersEnabled {
 | 
				
			||||||
			gotNames = append(gotNames, c.Name)
 | 
									defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, tc.ephemeralContainersEnabled)()
 | 
				
			||||||
 | 
									tc.mask = AllFeatureEnabledContainers()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								gotContainers := []string{}
 | 
				
			||||||
 | 
								VisitContainers(tc.spec, tc.mask, func(c *api.Container, containerType ContainerType) bool {
 | 
				
			||||||
 | 
									gotContainers = append(gotContainers, c.Name)
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
					c.SecurityContext = nil
 | 
										c.SecurityContext = nil
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return true
 | 
									return true
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		if !reflect.DeepEqual(gotNames, tc.wantNames) {
 | 
								if !cmp.Equal(gotContainers, tc.wantContainers) {
 | 
				
			||||||
			t.Errorf("VisitContainers() for test case %q visited containers %q, wanted to visit %q", tc.description, gotNames, tc.wantNames)
 | 
									t.Errorf("VisitContainers() = %+v, want %+v", gotContainers, tc.wantContainers)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		for _, c := range tc.haveSpec.Containers {
 | 
								for _, c := range tc.spec.Containers {
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
				t.Errorf("VisitContainers() for test case %q: got SecurityContext %#v for container %v, wanted nil", tc.description, c.SecurityContext, c.Name)
 | 
										t.Errorf("VisitContainers() did not drop SecurityContext for container %q", c.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		for _, c := range tc.haveSpec.InitContainers {
 | 
								for _, c := range tc.spec.InitContainers {
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
				t.Errorf("VisitContainers() for test case %q: got SecurityContext %#v for init container %v, wanted nil", tc.description, c.SecurityContext, c.Name)
 | 
										t.Errorf("VisitContainers() did not drop SecurityContext for init container %q", c.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		for _, c := range tc.haveSpec.EphemeralContainers {
 | 
								for _, c := range tc.spec.EphemeralContainers {
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
				t.Errorf("VisitContainers() for test case %q: got SecurityContext %#v for ephemeral container %v, wanted nil", tc.description, c.SecurityContext, c.Name)
 | 
										t.Errorf("VisitContainers() did not drop SecurityContext for ephemeral container %q", c.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ go_test(
 | 
				
			|||||||
        "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
 | 
					        "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
 | 
				
			||||||
 | 
					        "//vendor/github.com/google/go-cmp/cmp:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/stretchr/testify/assert:go_default_library",
 | 
					        "//vendor/github.com/stretchr/testify/assert:go_default_library",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,28 +50,60 @@ func FindPort(pod *v1.Pod, svcPort *v1.ServicePort) (int, error) {
 | 
				
			|||||||
	return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
 | 
						return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ContainerType signifies container type
 | 
				
			||||||
 | 
					type ContainerType int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// Containers is for normal containers
 | 
				
			||||||
 | 
						Containers ContainerType = 1 << iota
 | 
				
			||||||
 | 
						// InitContainers is for init containers
 | 
				
			||||||
 | 
						InitContainers
 | 
				
			||||||
 | 
						// EphemeralContainers is for ephemeral containers
 | 
				
			||||||
 | 
						EphemeralContainers
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllContainers specifies that all containers be visited
 | 
				
			||||||
 | 
					const AllContainers ContainerType = (InitContainers | Containers | EphemeralContainers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AllFeatureEnabledContainers returns a ContainerType mask which includes all container
 | 
				
			||||||
 | 
					// types except for the ones guarded by feature gate.
 | 
				
			||||||
 | 
					func AllFeatureEnabledContainers() ContainerType {
 | 
				
			||||||
 | 
						containerType := AllContainers
 | 
				
			||||||
 | 
						if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) {
 | 
				
			||||||
 | 
							containerType &= ^EphemeralContainers
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return containerType
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ContainerVisitor is called with each container spec, and returns true
 | 
					// ContainerVisitor is called with each container spec, and returns true
 | 
				
			||||||
// if visiting should continue.
 | 
					// if visiting should continue.
 | 
				
			||||||
type ContainerVisitor func(container *v1.Container) (shouldContinue bool)
 | 
					type ContainerVisitor func(container *v1.Container, containerType ContainerType) (shouldContinue bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// VisitContainers invokes the visitor function with a pointer to the container
 | 
					// Visitor is called with each object name, and returns true if visiting should continue
 | 
				
			||||||
// spec of every container in the given pod spec. If visitor returns false,
 | 
					type Visitor func(name string) (shouldContinue bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// VisitContainers invokes the visitor function with a pointer to every container
 | 
				
			||||||
 | 
					// spec in the given pod spec with type set in mask. If visitor returns false,
 | 
				
			||||||
// visiting is short-circuited. VisitContainers returns true if visiting completes,
 | 
					// visiting is short-circuited. VisitContainers returns true if visiting completes,
 | 
				
			||||||
// false if visiting was short-circuited.
 | 
					// false if visiting was short-circuited.
 | 
				
			||||||
func VisitContainers(podSpec *v1.PodSpec, visitor ContainerVisitor) bool {
 | 
					func VisitContainers(podSpec *v1.PodSpec, mask ContainerType, visitor ContainerVisitor) bool {
 | 
				
			||||||
 | 
						if mask&InitContainers != 0 {
 | 
				
			||||||
		for i := range podSpec.InitContainers {
 | 
							for i := range podSpec.InitContainers {
 | 
				
			||||||
		if !visitor(&podSpec.InitContainers[i]) {
 | 
								if !visitor(&podSpec.InitContainers[i], InitContainers) {
 | 
				
			||||||
				return false
 | 
									return false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if mask&Containers != 0 {
 | 
				
			||||||
		for i := range podSpec.Containers {
 | 
							for i := range podSpec.Containers {
 | 
				
			||||||
		if !visitor(&podSpec.Containers[i]) {
 | 
								if !visitor(&podSpec.Containers[i], Containers) {
 | 
				
			||||||
				return false
 | 
									return false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) {
 | 
						}
 | 
				
			||||||
 | 
						if mask&EphemeralContainers != 0 {
 | 
				
			||||||
		for i := range podSpec.EphemeralContainers {
 | 
							for i := range podSpec.EphemeralContainers {
 | 
				
			||||||
			if !visitor((*v1.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon)) {
 | 
								if !visitor((*v1.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), EphemeralContainers) {
 | 
				
			||||||
				return false
 | 
									return false
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -79,9 +111,6 @@ func VisitContainers(podSpec *v1.PodSpec, visitor ContainerVisitor) bool {
 | 
				
			|||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Visitor is called with each object name, and returns true if visiting should continue
 | 
					 | 
				
			||||||
type Visitor func(name string) (shouldContinue bool)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// VisitPodSecretNames invokes the visitor function with the name of every secret
 | 
					// VisitPodSecretNames invokes the visitor function with the name of every secret
 | 
				
			||||||
// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
 | 
					// referenced by the pod spec. If visitor returns false, visiting is short-circuited.
 | 
				
			||||||
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
 | 
					// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
 | 
				
			||||||
@@ -92,7 +121,7 @@ func VisitPodSecretNames(pod *v1.Pod, visitor Visitor) bool {
 | 
				
			|||||||
			return false
 | 
								return false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	VisitContainers(&pod.Spec, func(c *v1.Container) bool {
 | 
						VisitContainers(&pod.Spec, AllContainers, func(c *v1.Container, containerType ContainerType) bool {
 | 
				
			||||||
		return visitContainerSecretNames(c, visitor)
 | 
							return visitContainerSecretNames(c, visitor)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	var source *v1.VolumeSource
 | 
						var source *v1.VolumeSource
 | 
				
			||||||
@@ -176,7 +205,7 @@ func visitContainerSecretNames(container *v1.Container, visitor Visitor) bool {
 | 
				
			|||||||
// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
 | 
					// Transitive references (e.g. pod -> pvc -> pv -> secret) are not visited.
 | 
				
			||||||
// Returns true if visiting completed, false if visiting was short-circuited.
 | 
					// Returns true if visiting completed, false if visiting was short-circuited.
 | 
				
			||||||
func VisitPodConfigmapNames(pod *v1.Pod, visitor Visitor) bool {
 | 
					func VisitPodConfigmapNames(pod *v1.Pod, visitor Visitor) bool {
 | 
				
			||||||
	VisitContainers(&pod.Spec, func(c *v1.Container) bool {
 | 
						VisitContainers(&pod.Spec, AllContainers, func(c *v1.Container, containerType ContainerType) bool {
 | 
				
			||||||
		return visitContainerConfigmapNames(c, visitor)
 | 
							return visitContainerConfigmapNames(c, visitor)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	var source *v1.VolumeSource
 | 
						var source *v1.VolumeSource
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/google/go-cmp/cmp"
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
	v1 "k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
@@ -202,68 +203,22 @@ func TestFindPort(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestVisitContainers(t *testing.T) {
 | 
					func TestVisitContainers(t *testing.T) {
 | 
				
			||||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
		description string
 | 
							desc                       string
 | 
				
			||||||
		haveSpec    *v1.PodSpec
 | 
							spec                       *v1.PodSpec
 | 
				
			||||||
		wantNames   []string
 | 
							wantContainers             []string
 | 
				
			||||||
 | 
							mask                       ContainerType
 | 
				
			||||||
 | 
							ephemeralContainersEnabled bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"empty podspec",
 | 
								desc:           "empty podspec",
 | 
				
			||||||
			&v1.PodSpec{},
 | 
								spec:           &v1.PodSpec{},
 | 
				
			||||||
			[]string{},
 | 
								wantContainers: []string{},
 | 
				
			||||||
 | 
								mask:           AllContainers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"regular containers",
 | 
								desc: "regular containers",
 | 
				
			||||||
			&v1.PodSpec{
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
				Containers: []v1.Container{
 | 
					 | 
				
			||||||
					{Name: "c1"},
 | 
					 | 
				
			||||||
					{Name: "c2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"c1", "c2"},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"init containers",
 | 
					 | 
				
			||||||
			&v1.PodSpec{
 | 
					 | 
				
			||||||
				InitContainers: []v1.Container{
 | 
					 | 
				
			||||||
					{Name: "i1"},
 | 
					 | 
				
			||||||
					{Name: "i2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"i1", "i2"},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"regular and init containers",
 | 
					 | 
				
			||||||
			&v1.PodSpec{
 | 
					 | 
				
			||||||
				Containers: []v1.Container{
 | 
					 | 
				
			||||||
					{Name: "c1"},
 | 
					 | 
				
			||||||
					{Name: "c2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				InitContainers: []v1.Container{
 | 
					 | 
				
			||||||
					{Name: "i1"},
 | 
					 | 
				
			||||||
					{Name: "i2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2"},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"ephemeral containers",
 | 
					 | 
				
			||||||
			&v1.PodSpec{
 | 
					 | 
				
			||||||
				Containers: []v1.Container{
 | 
					 | 
				
			||||||
					{Name: "c1"},
 | 
					 | 
				
			||||||
					{Name: "c2"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				EphemeralContainers: []v1.EphemeralContainer{
 | 
					 | 
				
			||||||
					{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e1"}},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			[]string{"c1", "c2", "e1"},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			"all container types",
 | 
					 | 
				
			||||||
			&v1.PodSpec{
 | 
					 | 
				
			||||||
				Containers: []v1.Container{
 | 
									Containers: []v1.Container{
 | 
				
			||||||
					{Name: "c1"},
 | 
										{Name: "c1"},
 | 
				
			||||||
					{Name: "c2"},
 | 
										{Name: "c2"},
 | 
				
			||||||
@@ -277,11 +232,108 @@ func TestVisitContainers(t *testing.T) {
 | 
				
			|||||||
					{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
								wantContainers: []string{"c1", "c2"},
 | 
				
			||||||
 | 
								mask:           Containers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"dropping fields",
 | 
								desc: "init containers",
 | 
				
			||||||
			&v1.PodSpec{
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
 | 
									Containers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []v1.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"i1", "i2"},
 | 
				
			||||||
 | 
								mask:           InitContainers,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "ephemeral containers",
 | 
				
			||||||
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
 | 
									Containers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []v1.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"e1", "e2"},
 | 
				
			||||||
 | 
								mask:           EphemeralContainers,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "all container types",
 | 
				
			||||||
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
 | 
									Containers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []v1.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
				
			||||||
 | 
								mask:           AllContainers,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "all feature enabled container types with ephemeral containers disabled",
 | 
				
			||||||
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
 | 
									Containers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2"},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []v1.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers: []string{"i1", "i2", "c1", "c2"},
 | 
				
			||||||
 | 
								mask:           AllFeatureEnabledContainers(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "all feature enabled container types with ephemeral containers enabled",
 | 
				
			||||||
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
 | 
									Containers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "c1"},
 | 
				
			||||||
 | 
										{Name: "c2", SecurityContext: &v1.SecurityContext{}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []v1.Container{
 | 
				
			||||||
 | 
										{Name: "i1"},
 | 
				
			||||||
 | 
										{Name: "i2", SecurityContext: &v1.SecurityContext{}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									EphemeralContainers: []v1.EphemeralContainer{
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e1"}},
 | 
				
			||||||
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								wantContainers:             []string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
				
			||||||
 | 
								mask:                       AllFeatureEnabledContainers(),
 | 
				
			||||||
 | 
								ephemeralContainersEnabled: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								desc: "dropping fields",
 | 
				
			||||||
 | 
								spec: &v1.PodSpec{
 | 
				
			||||||
				Containers: []v1.Container{
 | 
									Containers: []v1.Container{
 | 
				
			||||||
					{Name: "c1"},
 | 
										{Name: "c1"},
 | 
				
			||||||
					{Name: "c2", SecurityContext: &v1.SecurityContext{}},
 | 
										{Name: "c2", SecurityContext: &v1.SecurityContext{}},
 | 
				
			||||||
@@ -295,37 +347,45 @@ func TestVisitContainers(t *testing.T) {
 | 
				
			|||||||
					{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2", SecurityContext: &v1.SecurityContext{}}},
 | 
										{EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2", SecurityContext: &v1.SecurityContext{}}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			[]string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
								wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
 | 
				
			||||||
 | 
								mask:           AllContainers,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		gotNames := []string{}
 | 
							t.Run(tc.desc, func(t *testing.T) {
 | 
				
			||||||
		VisitContainers(tc.haveSpec, func(c *v1.Container) bool {
 | 
								if tc.ephemeralContainersEnabled {
 | 
				
			||||||
			gotNames = append(gotNames, c.Name)
 | 
									defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, tc.ephemeralContainersEnabled)()
 | 
				
			||||||
 | 
									tc.mask = AllFeatureEnabledContainers()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								gotContainers := []string{}
 | 
				
			||||||
 | 
								VisitContainers(tc.spec, tc.mask, func(c *v1.Container, containerType ContainerType) bool {
 | 
				
			||||||
 | 
									gotContainers = append(gotContainers, c.Name)
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
					c.SecurityContext = nil
 | 
										c.SecurityContext = nil
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return true
 | 
									return true
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		if !reflect.DeepEqual(gotNames, tc.wantNames) {
 | 
								if !cmp.Equal(gotContainers, tc.wantContainers) {
 | 
				
			||||||
			t.Errorf("VisitContainers() for test case %q visited containers %q, wanted to visit %q", tc.description, gotNames, tc.wantNames)
 | 
									t.Errorf("VisitContainers() = %+v, want %+v", gotContainers, tc.wantContainers)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		for _, c := range tc.haveSpec.Containers {
 | 
								for _, c := range tc.spec.Containers {
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
				t.Errorf("VisitContainers() for test case %q: got SecurityContext %#v for container %v, wanted nil", tc.description, c.SecurityContext, c.Name)
 | 
										t.Errorf("VisitContainers() did not drop SecurityContext for container %q", c.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		for _, c := range tc.haveSpec.InitContainers {
 | 
								for _, c := range tc.spec.InitContainers {
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
				t.Errorf("VisitContainers() for test case %q: got SecurityContext %#v for init container %v, wanted nil", tc.description, c.SecurityContext, c.Name)
 | 
										t.Errorf("VisitContainers() did not drop SecurityContext for init container %q", c.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		for _, c := range tc.haveSpec.EphemeralContainers {
 | 
								for _, c := range tc.spec.EphemeralContainers {
 | 
				
			||||||
				if c.SecurityContext != nil {
 | 
									if c.SecurityContext != nil {
 | 
				
			||||||
				t.Errorf("VisitContainers() for test case %q: got SecurityContext %#v for ephemeral container %v, wanted nil", tc.description, c.SecurityContext, c.Name)
 | 
										t.Errorf("VisitContainers() did not drop SecurityContext for ephemeral container %q", c.Name)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -283,7 +283,7 @@ func FormatPod(pod *Pod) string {
 | 
				
			|||||||
// GetContainerSpec gets the container spec by containerName.
 | 
					// GetContainerSpec gets the container spec by containerName.
 | 
				
			||||||
func GetContainerSpec(pod *v1.Pod, containerName string) *v1.Container {
 | 
					func GetContainerSpec(pod *v1.Pod, containerName string) *v1.Container {
 | 
				
			||||||
	var containerSpec *v1.Container
 | 
						var containerSpec *v1.Container
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(c *v1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(c *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		if containerName == c.Name {
 | 
							if containerName == c.Name {
 | 
				
			||||||
			containerSpec = c
 | 
								containerSpec = c
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
@@ -296,7 +296,7 @@ func GetContainerSpec(pod *v1.Pod, containerName string) *v1.Container {
 | 
				
			|||||||
// HasPrivilegedContainer returns true if any of the containers in the pod are privileged.
 | 
					// HasPrivilegedContainer returns true if any of the containers in the pod are privileged.
 | 
				
			||||||
func HasPrivilegedContainer(pod *v1.Pod) bool {
 | 
					func HasPrivilegedContainer(pod *v1.Pod) bool {
 | 
				
			||||||
	var hasPrivileged bool
 | 
						var hasPrivileged bool
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(c *v1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(c *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		if c.SecurityContext != nil && c.SecurityContext.Privileged != nil && *c.SecurityContext.Privileged {
 | 
							if c.SecurityContext != nil && c.SecurityContext.Privileged != nil && *c.SecurityContext.Privileged {
 | 
				
			||||||
			hasPrivileged = true
 | 
								hasPrivileged = true
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,7 +101,7 @@ func makeAndSetFakePod(t *testing.T, m *kubeGenericRuntimeManager, fakeRuntime *
 | 
				
			|||||||
			state:     runtimeapi.ContainerState_CONTAINER_RUNNING,
 | 
								state:     runtimeapi.ContainerState_CONTAINER_RUNNING,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(c *v1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(c *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		containers = append(containers, makeFakeContainer(t, m, newTemplate(c)))
 | 
							containers = append(containers, makeFakeContainer(t, m, newTemplate(c)))
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -387,7 +387,7 @@ func LogLocation(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func podHasContainerWithName(pod *api.Pod, containerName string) bool {
 | 
					func podHasContainerWithName(pod *api.Pod, containerName string) bool {
 | 
				
			||||||
	var hasContainer bool
 | 
						var hasContainer bool
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, podutil.DefaultContainers, func(c *api.Container, containerType podutil.ContainerType) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(c *api.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		if c.Name == containerName {
 | 
							if c.Name == containerName {
 | 
				
			||||||
			hasContainer = true
 | 
								hasContainer = true
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
@@ -554,7 +554,7 @@ func validateContainer(container string, pod *api.Pod) (string, error) {
 | 
				
			|||||||
			return "", errors.NewBadRequest(fmt.Sprintf("a container name must be specified for pod %s", pod.Name))
 | 
								return "", errors.NewBadRequest(fmt.Sprintf("a container name must be specified for pod %s", pod.Name))
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			var containerNames []string
 | 
								var containerNames []string
 | 
				
			||||||
			podutil.VisitContainers(&pod.Spec, podutil.DefaultContainers, func(c *api.Container, containerType podutil.ContainerType) bool {
 | 
								podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(c *api.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
				containerNames = append(containerNames, c.Name)
 | 
									containerNames = append(containerNames, c.Name)
 | 
				
			||||||
				return true
 | 
									return true
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,7 @@ import (
 | 
				
			|||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
 | 
						podutil "k8s.io/kubernetes/pkg/api/v1/pod"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
						"k8s.io/kubernetes/pkg/features"
 | 
				
			||||||
@@ -79,7 +79,7 @@ func (v *validator) Validate(pod *v1.Pod) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var retErr error
 | 
						var retErr error
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(container *v1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllContainers, func(container *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		retErr = validateProfile(GetProfileName(pod, container.Name), loadedProfiles)
 | 
							retErr = validateProfile(GetProfileName(pod, container.Name), loadedProfiles)
 | 
				
			||||||
		if retErr != nil {
 | 
							if retErr != nil {
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ import (
 | 
				
			|||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	podutil "k8s.io/kubernetes/pkg/api/v1/pod"
 | 
						podutil "k8s.io/kubernetes/pkg/api/v1/pod"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,7 +73,7 @@ func getNestedMountpoints(name, baseDir string, pod v1.Pod) ([]string, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var retErr error
 | 
						var retErr error
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(c *v1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(c *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		retErr = checkContainer(c)
 | 
							retErr = checkContainer(c)
 | 
				
			||||||
		if retErr != nil {
 | 
							if retErr != nil {
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -592,7 +592,7 @@ func GetPodVolumeNames(pod *v1.Pod) (mounts sets.String, devices sets.String) {
 | 
				
			|||||||
	mounts = sets.NewString()
 | 
						mounts = sets.NewString()
 | 
				
			||||||
	devices = sets.NewString()
 | 
						devices = sets.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(container *v1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllFeatureEnabledContainers(), func(container *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		if container.VolumeMounts != nil {
 | 
							if container.VolumeMounts != nil {
 | 
				
			||||||
			for _, mount := range container.VolumeMounts {
 | 
								for _, mount := range container.VolumeMounts {
 | 
				
			||||||
				mounts.Insert(mount.Name)
 | 
									mounts.Insert(mount.Name)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -149,7 +149,7 @@ func (d *DenyExec) Validate(ctx context.Context, a admission.Attributes, o admis
 | 
				
			|||||||
// isPrivileged will return true a pod has any privileged containers
 | 
					// isPrivileged will return true a pod has any privileged containers
 | 
				
			||||||
func isPrivileged(pod *corev1.Pod) bool {
 | 
					func isPrivileged(pod *corev1.Pod) bool {
 | 
				
			||||||
	var privileged bool
 | 
						var privileged bool
 | 
				
			||||||
	podutil.VisitContainers(&pod.Spec, func(c *corev1.Container) bool {
 | 
						podutil.VisitContainers(&pod.Spec, podutil.AllContainers, func(c *corev1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
		if c.SecurityContext == nil || c.SecurityContext.Privileged == nil {
 | 
							if c.SecurityContext == nil || c.SecurityContext.Privileged == nil {
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -819,7 +819,7 @@ func (f *Framework) MatchContainerOutput(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if podErr != nil {
 | 
						if podErr != nil {
 | 
				
			||||||
		// Pod failed. Dump all logs from all containers to see what's wrong
 | 
							// Pod failed. Dump all logs from all containers to see what's wrong
 | 
				
			||||||
		_ = podutil.VisitContainers(&podStatus.Spec, func(c *v1.Container) bool {
 | 
							_ = podutil.VisitContainers(&podStatus.Spec, podutil.AllFeatureEnabledContainers(), func(c *v1.Container, containerType podutil.ContainerType) bool {
 | 
				
			||||||
			logs, err := e2epod.GetPodLogs(f.ClientSet, ns, podStatus.Name, c.Name)
 | 
								logs, err := e2epod.GetPodLogs(f.ClientSet, ns, podStatus.Name, c.Name)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				Logf("Failed to get logs from node %q pod %q container %q: %v",
 | 
									Logf("Failed to get logs from node %q pod %q container %q: %v",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user