diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 3f485aad1ee..bf14aceed93 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -46,11 +46,7 @@ const AllContainers ContainerType = (InitContainers | Containers | EphemeralCont // 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 + return AllContainers } // ContainerVisitor is called with each container spec, and returns true @@ -529,10 +525,6 @@ func dropDisabledFields( } } - if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) && !ephemeralContainersInUse(oldPodSpec) { - podSpec.EphemeralContainers = nil - } - if !utilfeature.DefaultFeatureGate.Enabled(features.ProbeTerminationGracePeriod) && !probeGracePeriodInUse(oldPodSpec) { // Set pod-level terminationGracePeriodSeconds to nil if the feature is disabled and it is not used VisitContainers(podSpec, AllContainers, func(c *api.Container, containerType ContainerType) bool { @@ -654,13 +646,6 @@ func nodeTaintsPolicyInUse(podSpec *api.PodSpec) bool { return false } -func ephemeralContainersInUse(podSpec *api.PodSpec) bool { - if podSpec == nil { - return false - } - return len(podSpec.EphemeralContainers) > 0 -} - // procMountInUse returns true if the pod spec is non-nil and has a SecurityContext's ProcMount field set to a non-default value func procMountInUse(podSpec *api.PodSpec) bool { if podSpec == nil { diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index 4e95e70a0e5..130d7c79286 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -39,11 +39,10 @@ import ( func TestVisitContainers(t *testing.T) { setAllFeatureEnabledContainersDuringTest := ContainerType(0) testCases := []struct { - desc string - spec *api.PodSpec - wantContainers []string - mask ContainerType - ephemeralContainersEnabled bool + desc string + spec *api.PodSpec + wantContainers []string + mask ContainerType }{ { desc: "empty podspec", @@ -127,25 +126,6 @@ func TestVisitContainers(t *testing.T) { 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: setAllFeatureEnabledContainersDuringTest, - }, { desc: "all feature enabled container types with ephemeral containers enabled", spec: &api.PodSpec{ @@ -162,9 +142,8 @@ func TestVisitContainers(t *testing.T) { {EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}}, }, }, - wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"}, - mask: setAllFeatureEnabledContainersDuringTest, - ephemeralContainersEnabled: true, + wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"}, + mask: setAllFeatureEnabledContainersDuringTest, }, { desc: "dropping fields", @@ -189,8 +168,6 @@ func TestVisitContainers(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, tc.ephemeralContainersEnabled)() - if tc.mask == setAllFeatureEnabledContainersDuringTest { tc.mask = AllFeatureEnabledContainers() } @@ -226,8 +203,6 @@ func TestVisitContainers(t *testing.T) { } func TestPodSecrets(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Stub containing all possible secret references in a pod. // The names of the referenced secrets match struct paths detected by reflection. pod := &api.Pod{ @@ -425,8 +400,6 @@ func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, n } func TestPodConfigmaps(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Stub containing all possible ConfigMap references in a pod. // The names of the referenced ConfigMaps match struct paths detected by reflection. pod := &api.Pod{ @@ -1023,95 +996,6 @@ func TestDropProbeGracePeriod(t *testing.T) { } } -func TestDropEphemeralContainers(t *testing.T) { - podWithEphemeralContainers := func() *api.Pod { - return &api.Pod{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - EphemeralContainers: []api.EphemeralContainer{{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "container1", Image: "testimage"}}}, - }, - } - } - podWithoutEphemeralContainers := func() *api.Pod { - return &api.Pod{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - }, - } - } - - podInfo := []struct { - description string - hasEphemeralContainers bool - pod func() *api.Pod - }{ - { - description: "has ephemeral containers", - hasEphemeralContainers: true, - pod: podWithEphemeralContainers, - }, - { - description: "does not have ephemeral containers", - hasEphemeralContainers: false, - pod: podWithoutEphemeralContainers, - }, - { - description: "is nil", - hasEphemeralContainers: false, - pod: func() *api.Pod { return nil }, - }, - } - - for _, enabled := range []bool{true, false} { - for _, oldPodInfo := range podInfo { - for _, newPodInfo := range podInfo { - oldPodHasEphemeralContainers, oldPod := oldPodInfo.hasEphemeralContainers, oldPodInfo.pod() - newPodHasEphemeralContainers, newPod := newPodInfo.hasEphemeralContainers, newPodInfo.pod() - if newPod == nil { - continue - } - - t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, enabled)() - - var oldPodSpec *api.PodSpec - if oldPod != nil { - oldPodSpec = &oldPod.Spec - } - dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil) - - // old pod should never be changed - if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) { - t.Errorf("old pod changed: %v", cmp.Diff(oldPod, oldPodInfo.pod())) - } - - switch { - case enabled || oldPodHasEphemeralContainers: - // new pod should not be changed if the feature is enabled, or if the old pod had subpaths - if !reflect.DeepEqual(newPod, newPodInfo.pod()) { - t.Errorf("new pod changed: %v", cmp.Diff(newPod, newPodInfo.pod())) - } - case newPodHasEphemeralContainers: - // new pod should be changed - if reflect.DeepEqual(newPod, newPodInfo.pod()) { - t.Errorf("new pod was not changed") - } - // new pod should not have subpaths - if !reflect.DeepEqual(newPod, podWithoutEphemeralContainers()) { - t.Errorf("new pod had subpaths: %v", cmp.Diff(newPod, podWithoutEphemeralContainers())) - } - default: - // new pod should not need to be changed - if !reflect.DeepEqual(newPod, newPodInfo.pod()) { - t.Errorf("new pod changed: %v", cmp.Diff(newPod, newPodInfo.pod())) - } - } - }) - } - } - } -} - func TestValidatePodDeletionCostOption(t *testing.T) { testCases := []struct { name string diff --git a/pkg/api/v1/pod/util.go b/pkg/api/v1/pod/util.go index 8bfc21a67f4..8cefc94641e 100644 --- a/pkg/api/v1/pod/util.go +++ b/pkg/api/v1/pod/util.go @@ -23,8 +23,6 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" ) // FindPort locates the container port for the given pod and portName. If the @@ -68,11 +66,7 @@ const AllContainers ContainerType = (InitContainers | Containers | EphemeralCont // 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 + return AllContainers } // ContainerVisitor is called with each container spec, and returns true diff --git a/pkg/api/v1/pod/util_test.go b/pkg/api/v1/pod/util_test.go index b8e4f4e6d76..20b32206f20 100644 --- a/pkg/api/v1/pod/util_test.go +++ b/pkg/api/v1/pod/util_test.go @@ -29,9 +29,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/kubernetes/pkg/features" ) func TestFindPort(t *testing.T) { @@ -205,11 +202,10 @@ func TestFindPort(t *testing.T) { func TestVisitContainers(t *testing.T) { setAllFeatureEnabledContainersDuringTest := ContainerType(0) testCases := []struct { - desc string - spec *v1.PodSpec - wantContainers []string - mask ContainerType - ephemeralContainersEnabled bool + desc string + spec *v1.PodSpec + wantContainers []string + mask ContainerType }{ { desc: "empty podspec", @@ -294,26 +290,7 @@ func TestVisitContainers(t *testing.T) { 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: setAllFeatureEnabledContainersDuringTest, - }, - { - desc: "all feature enabled container types with ephemeral containers enabled", + desc: "all feature enabled container types", spec: &v1.PodSpec{ Containers: []v1.Container{ {Name: "c1"}, @@ -328,9 +305,8 @@ func TestVisitContainers(t *testing.T) { {EphemeralContainerCommon: v1.EphemeralContainerCommon{Name: "e2"}}, }, }, - wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"}, - mask: setAllFeatureEnabledContainersDuringTest, - ephemeralContainersEnabled: true, + wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"}, + mask: setAllFeatureEnabledContainersDuringTest, }, { desc: "dropping fields", @@ -355,8 +331,6 @@ func TestVisitContainers(t *testing.T) { for _, tc := range testCases { t.Run(tc.desc, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, tc.ephemeralContainersEnabled)() - if tc.mask == setAllFeatureEnabledContainersDuringTest { tc.mask = AllFeatureEnabledContainers() } @@ -392,8 +366,6 @@ func TestVisitContainers(t *testing.T) { } func TestPodSecrets(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Stub containing all possible secret references in a pod. // The names of the referenced secrets match struct paths detected by reflection. pod := &v1.Pod{ @@ -591,8 +563,6 @@ func collectResourcePaths(t *testing.T, resourcename string, path *field.Path, n } func TestPodConfigmaps(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Stub containing all possible ConfigMap references in a pod. // The names of the referenced ConfigMaps match struct paths detected by reflection. pod := &v1.Pod{ diff --git a/pkg/apis/apps/validation/validation_test.go b/pkg/apis/apps/validation/validation_test.go index 6d34ea5a532..99147f00e9f 100644 --- a/pkg/apis/apps/validation/validation_test.go +++ b/pkg/apis/apps/validation/validation_test.go @@ -2396,8 +2396,6 @@ func TestValidateDaemonSetUpdate(t *testing.T) { } func TestValidateDaemonSet(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - validSelector := map[string]string{"a": "b"} validPodTemplate := api.PodTemplate{ Template: api.PodTemplateSpec{ @@ -2660,8 +2658,6 @@ func validDeployment() *apps.Deployment { } func TestValidateDeployment(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - successCases := []*apps.Deployment{ validDeployment(), } diff --git a/pkg/apis/core/pods/helpers.go b/pkg/apis/core/pods/helpers.go index e05a313a1f1..71810c5005c 100644 --- a/pkg/apis/core/pods/helpers.go +++ b/pkg/apis/core/pods/helpers.go @@ -20,9 +20,7 @@ import ( "fmt" "k8s.io/apimachinery/pkg/util/validation/field" - utilfeature "k8s.io/apiserver/pkg/util/feature" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/fieldpath" ) @@ -47,12 +45,10 @@ func VisitContainersWithPath(podSpec *api.PodSpec, specPath *field.Path, visitor return false } } - if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - fldPath = specPath.Child("ephemeralContainers") - for i := range podSpec.EphemeralContainers { - if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), fldPath.Index(i)) { - return false - } + fldPath = specPath.Child("ephemeralContainers") + for i := range podSpec.EphemeralContainers { + if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), fldPath.Index(i)) { + return false } } return true diff --git a/pkg/apis/core/pods/helpers_test.go b/pkg/apis/core/pods/helpers_test.go index 1a357301b93..5552a55a720 100644 --- a/pkg/apis/core/pods/helpers_test.go +++ b/pkg/apis/core/pods/helpers_test.go @@ -21,15 +21,10 @@ import ( "testing" "k8s.io/apimachinery/pkg/util/validation/field" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" ) func TestVisitContainersWithPath(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - testCases := []struct { description string path *field.Path diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index ff7bc068445..0feda38c954 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -11485,8 +11485,6 @@ func makeValidService() core.Service { } func TestValidatePodEphemeralContainersUpdate(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - makePod := func(ephemeralContainers []core.EphemeralContainer) *core.Pod { return &core.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -20312,7 +20310,6 @@ func TestValidateWindowsHostProcessPod(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsHostProcessContainers, testCase.featureEnabled)() - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() opts := PodValidationOptions{AllowWindowsHostProcessField: testCase.featureEnabled} diff --git a/pkg/kubelet/container/helpers_test.go b/pkg/kubelet/container/helpers_test.go index 9e894b2072f..fcd5b6fb6ea 100644 --- a/pkg/kubelet/container/helpers_test.go +++ b/pkg/kubelet/container/helpers_test.go @@ -26,9 +26,6 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/kubernetes/pkg/features" ) func TestEnvVarsToMap(t *testing.T) { @@ -326,7 +323,6 @@ func TestExpandVolumeMountsWithSubpath(t *testing.T) { } func TestGetContainerSpec(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() for _, tc := range []struct { name string havePod *v1.Pod diff --git a/pkg/kubelet/container/ref.go b/pkg/kubelet/container/ref.go index e4f860378a1..3d84a963e59 100644 --- a/pkg/kubelet/container/ref.go +++ b/pkg/kubelet/container/ref.go @@ -20,10 +20,8 @@ import ( "fmt" v1 "k8s.io/api/core/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" ref "k8s.io/client-go/tools/reference" "k8s.io/kubernetes/pkg/api/legacyscheme" - "k8s.io/kubernetes/pkg/features" ) // ImplicitContainerPrefix is a container name prefix that will indicate that container was started implicitly (like the pod infra container). @@ -67,15 +65,13 @@ func fieldPath(pod *v1.Pod, container *v1.Container) (string, error) { return fmt.Sprintf("spec.initContainers{%s}", here.Name), nil } } - if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - for i := range pod.Spec.EphemeralContainers { - here := &pod.Spec.EphemeralContainers[i] - if here.Name == container.Name { - if here.Name == "" { - return fmt.Sprintf("spec.ephemeralContainers[%d]", i), nil - } - return fmt.Sprintf("spec.ephemeralContainers{%s}", here.Name), nil + for i := range pod.Spec.EphemeralContainers { + here := &pod.Spec.EphemeralContainers[i] + if here.Name == container.Name { + if here.Name == "" { + return fmt.Sprintf("spec.ephemeralContainers[%d]", i), nil } + return fmt.Sprintf("spec.ephemeralContainers{%s}", here.Name), nil } } return "", fmt.Errorf("container %q not found in pod %s/%s", container.Name, pod.Namespace, pod.Name) diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index a69558261e8..3ca002f458e 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -1221,7 +1221,7 @@ func (kl *Kubelet) validateContainerLogStatus(podName string, podStatus *v1.PodS if !found { cStatus, found = podutil.GetContainerStatus(podStatus.InitContainerStatuses, containerName) } - if !found && utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { + if !found { cStatus, found = podutil.GetContainerStatus(podStatus.EphemeralContainerStatuses, containerName) } if !found { @@ -1602,23 +1602,21 @@ func (kl *Kubelet) convertStatusToAPIStatus(pod *v1.Pod, podStatus *kubecontaine len(pod.Spec.InitContainers) > 0, true, ) - if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - var ecSpecs []v1.Container - for i := range pod.Spec.EphemeralContainers { - ecSpecs = append(ecSpecs, v1.Container(pod.Spec.EphemeralContainers[i].EphemeralContainerCommon)) - } - - // #80875: By now we've iterated podStatus 3 times. We could refactor this to make a single - // pass through podStatus.ContainerStatuses - apiPodStatus.EphemeralContainerStatuses = kl.convertToAPIContainerStatuses( - pod, podStatus, - oldPodStatus.EphemeralContainerStatuses, - ecSpecs, - len(pod.Spec.InitContainers) > 0, - false, - ) + var ecSpecs []v1.Container + for i := range pod.Spec.EphemeralContainers { + ecSpecs = append(ecSpecs, v1.Container(pod.Spec.EphemeralContainers[i].EphemeralContainerCommon)) } + // #80875: By now we've iterated podStatus 3 times. We could refactor this to make a single + // pass through podStatus.ContainerStatuses + apiPodStatus.EphemeralContainerStatuses = kl.convertToAPIContainerStatuses( + pod, podStatus, + oldPodStatus.EphemeralContainerStatuses, + ecSpecs, + len(pod.Spec.InitContainers) > 0, + false, + ) + return &apiPodStatus } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 1ea7723f813..eaa85c39f13 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -46,9 +46,7 @@ import ( kubetypes "k8s.io/apimachinery/pkg/types" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" - "k8s.io/kubernetes/pkg/features" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/cri/remote" "k8s.io/kubernetes/pkg/kubelet/events" @@ -120,7 +118,7 @@ func ephemeralContainerStartSpec(ec *v1.EphemeralContainer) *startSpec { // usually isn't a problem since ephemeral containers aren't allowed at pod creation time. // This always returns nil when the EphemeralContainers feature is disabled. func (s *startSpec) getTargetID(podStatus *kubecontainer.PodStatus) (*kubecontainer.ContainerID, error) { - if s.ephemeralContainer == nil || s.ephemeralContainer.TargetContainerName == "" || !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { + if s.ephemeralContainer == nil || s.ephemeralContainer.TargetContainerName == "" { return nil, nil } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go b/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go index 29d0bbfc9b4..307a40d0188 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container_linux_test.go @@ -520,7 +520,6 @@ func TestGetHugepageLimitsFromResources(t *testing.T) { } func TestGenerateLinuxContainerConfigNamespaces(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() _, _, m, err := createTestRuntimeManager() if err != nil { t.Fatalf("error creating test RuntimeManager: %v", err) diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_test.go b/pkg/kubelet/kuberuntime/kuberuntime_container_test.go index 91d73097611..115b0a6f676 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container_test.go @@ -17,7 +17,6 @@ limitations under the License. package kuberuntime import ( - "fmt" "io/ioutil" "os" "path/filepath" @@ -32,10 +31,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/api/core/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" - "k8s.io/kubernetes/pkg/features" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" "k8s.io/kubernetes/pkg/kubelet/lifecycle" @@ -405,23 +401,12 @@ func TestStartSpec(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() if got, err := tc.spec.getTargetID(podStatus); err != nil { t.Fatalf("%v: getTargetID got unexpected error: %v", t.Name(), err) } else if diff := cmp.Diff(tc.want, got); diff != "" { t.Errorf("%v: getTargetID got unexpected result. diff:\n%v", t.Name(), diff) } }) - - // Test with feature disabled in self-contained section which can be removed when feature flag is removed. - t.Run(fmt.Sprintf("%s (disabled)", tc.name), func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, false)() - if got, err := tc.spec.getTargetID(podStatus); err != nil { - t.Fatalf("%v: getTargetID got unexpected error: %v", t.Name(), err) - } else if got != nil { - t.Errorf("%v: getTargetID got: %v, wanted nil", t.Name(), got) - } - }) } } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index 6b2761a38e1..dedb35042a3 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -578,14 +578,12 @@ func (m *kubeGenericRuntimeManager) computePodActions(pod *v1.Pod, podStatus *ku } // Ephemeral containers may be started even if initialization is not yet complete. - if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - for i := range pod.Spec.EphemeralContainers { - c := (*v1.Container)(&pod.Spec.EphemeralContainers[i].EphemeralContainerCommon) + for i := range pod.Spec.EphemeralContainers { + c := (*v1.Container)(&pod.Spec.EphemeralContainers[i].EphemeralContainerCommon) - // Ephemeral Containers are never restarted - if podStatus.FindContainerStatusByName(c.Name) == nil { - changes.EphemeralContainersToStart = append(changes.EphemeralContainersToStart, i) - } + // Ephemeral Containers are never restarted + if podStatus.FindContainerStatusByName(c.Name) == nil { + changes.EphemeralContainersToStart = append(changes.EphemeralContainersToStart, i) } } @@ -914,10 +912,8 @@ func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, podStatus *kubecontaine // These are started "prior" to init containers to allow running ephemeral containers even when there // are errors starting an init container. In practice init containers will start first since ephemeral // containers cannot be specified on pod creation. - if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - for _, idx := range podContainerChanges.EphemeralContainersToStart { - start("ephemeral container", metrics.EphemeralContainer, ephemeralContainerStartSpec(&pod.Spec.EphemeralContainers[idx])) - } + for _, idx := range podContainerChanges.EphemeralContainersToStart { + start("ephemeral container", metrics.EphemeralContainer, ephemeralContainerStartSpec(&pod.Spec.EphemeralContainers[idx])) } // Step 6: start the init container. diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go index 8bec90c8f84..8e2daef2810 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager_test.go @@ -35,14 +35,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/util/flowcontrol" - featuregatetesting "k8s.io/component-base/featuregate/testing" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" apitest "k8s.io/cri-api/pkg/apis/testing" podutil "k8s.io/kubernetes/pkg/api/v1/pod" "k8s.io/kubernetes/pkg/credentialprovider" - "k8s.io/kubernetes/pkg/features" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" proberesults "k8s.io/kubernetes/pkg/kubelet/prober/results" @@ -490,9 +487,6 @@ func TestGetPods(t *testing.T) { } func TestKillPod(t *testing.T) { - // Tests that KillPod also kills Ephemeral Containers - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - fakeRuntime, _, m, err := createTestRuntimeManager() assert.NoError(t, err) @@ -1372,7 +1366,6 @@ func makeBasePodAndStatusWithInitContainers() (*v1.Pod, *kubecontainer.PodStatus } func TestComputePodActionsWithInitAndEphemeralContainers(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() // Make sure existing test cases pass with feature enabled TestComputePodActions(t) TestComputePodActionsWithInitContainers(t) diff --git a/pkg/kubelet/pod/pod_manager.go b/pkg/kubelet/pod/pod_manager.go index ce342ac7209..2eeb4788af8 100644 --- a/pkg/kubelet/pod/pod_manager.go +++ b/pkg/kubelet/pod/pod_manager.go @@ -22,8 +22,6 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/configmap" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/metrics" @@ -162,10 +160,6 @@ func (pm *basicManager) UpdatePod(pod *v1.Pod) { // updateMetrics updates the metrics surfaced by the pod manager. // oldPod or newPod may be nil to signify creation or deletion. func updateMetrics(oldPod, newPod *v1.Pod) { - if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - return - } - var numEC int if oldPod != nil { numEC -= len(oldPod.Spec.EphemeralContainers) diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index 4c31bb6a4ac..95e9f287222 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -916,7 +916,7 @@ func (s *Server) checkpoint(request *restful.Request, response *restful.Response } } } - if !found && utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { + if !found { for _, container := range pod.Spec.EphemeralContainers { if container.Name == containerName { found = true diff --git a/pkg/registry/core/pod/storage/storage.go b/pkg/registry/core/pod/storage/storage.go index c426b8727ed..27af1f4d9ed 100644 --- a/pkg/registry/core/pod/storage/storage.go +++ b/pkg/registry/core/pod/storage/storage.go @@ -33,12 +33,10 @@ import ( "k8s.io/apiserver/pkg/storage" storeerr "k8s.io/apiserver/pkg/storage/errors" "k8s.io/apiserver/pkg/util/dryrun" - utilfeature "k8s.io/apiserver/pkg/util/feature" policyclient "k8s.io/client-go/kubernetes/typed/policy/v1" podutil "k8s.io/kubernetes/pkg/api/pod" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/validation" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" @@ -330,10 +328,6 @@ var _ = rest.Patcher(&EphemeralContainersREST{}) // Get retrieves the object from the storage. It is required to support Patch. func (r *EphemeralContainersREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { - if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - return nil, errors.NewBadRequest("feature EphemeralContainers disabled") - } - return r.store.Get(ctx, name, options) } @@ -350,10 +344,6 @@ func (r *EphemeralContainersREST) Destroy() { // Update alters the EphemeralContainers field in PodSpec func (r *EphemeralContainersREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { - if !utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - return nil, false, errors.NewBadRequest("feature EphemeralContainers disabled") - } - // We are explicitly setting forceAllowCreate to false in the call to the underlying storage because // subresources should never allow create on update. return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options) diff --git a/pkg/registry/core/pod/strategy_test.go b/pkg/registry/core/pod/strategy_test.go index 742578e734a..7e6022e7598 100644 --- a/pkg/registry/core/pod/strategy_test.go +++ b/pkg/registry/core/pod/strategy_test.go @@ -35,12 +35,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/tools/cache" - featuregatetesting "k8s.io/component-base/featuregate/testing" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/kubelet/client" utilpointer "k8s.io/utils/pointer" @@ -355,7 +352,6 @@ func (g mockPodGetter) Get(context.Context, string, *metav1.GetOptions) (runtime } func TestCheckLogLocation(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() ctx := genericapirequest.NewDefaultContext() fakePodName := "test" tcs := []struct { diff --git a/pkg/registry/core/rest/storage_core.go b/pkg/registry/core/rest/storage_core.go index c9f8e039136..206e87e8909 100644 --- a/pkg/registry/core/rest/storage_core.go +++ b/pkg/registry/core/rest/storage_core.go @@ -36,13 +36,11 @@ import ( genericapiserver "k8s.io/apiserver/pkg/server" serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/apiserver/pkg/storage/etcd3" - utilfeature "k8s.io/apiserver/pkg/util/feature" policyclient "k8s.io/client-go/kubernetes/typed/policy/v1" restclient "k8s.io/client-go/rest" "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/cluster/ports" - "k8s.io/kubernetes/pkg/features" kubeletclient "k8s.io/kubernetes/pkg/kubelet/client" "k8s.io/kubernetes/pkg/registry/core/componentstatus" configmapstore "k8s.io/kubernetes/pkg/registry/core/configmap/storage" @@ -291,9 +289,7 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(apiResourceConfigSource if podStorage.Eviction != nil { storage[resource+"/eviction"] = podStorage.Eviction } - if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) { - storage[resource+"/ephemeralcontainers"] = podStorage.EphemeralContainers - } + storage[resource+"/ephemeralcontainers"] = podStorage.EphemeralContainers } if resource := "bindings"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) { diff --git a/pkg/volume/util/util_test.go b/pkg/volume/util/util_test.go index 715838c5e31..9b7e7559144 100644 --- a/pkg/volume/util/util_test.go +++ b/pkg/volume/util/util_test.go @@ -28,10 +28,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" _ "k8s.io/kubernetes/pkg/apis/core/install" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/util/slice" "k8s.io/kubernetes/pkg/volume" utilptr "k8s.io/utils/pointer" @@ -581,7 +578,6 @@ func TestMakeAbsolutePath(t *testing.T) { } func TestGetPodVolumeNames(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() tests := []struct { name string pod *v1.Pod diff --git a/test/e2e/common/node/ephemeral_containers.go b/test/e2e/common/node/ephemeral_containers.go index 066652eb1c1..69899ddf7d7 100644 --- a/test/e2e/common/node/ephemeral_containers.go +++ b/test/e2e/common/node/ephemeral_containers.go @@ -20,12 +20,10 @@ import ( "time" v1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/kubernetes/pkg/kubelet/util/format" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" - e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" imageutils "k8s.io/kubernetes/test/utils/image" admissionapi "k8s.io/pod-security-admission/api" @@ -69,11 +67,6 @@ var _ = SIGDescribe("Ephemeral Containers [NodeConformance]", func() { }, } err := podClient.AddEphemeralContainerSync(pod, ec, time.Minute) - // BEGIN TODO: Remove when EphemeralContainers feature gate is retired. - if apierrors.IsNotFound(err) { - e2eskipper.Skipf("Skipping test because EphemeralContainers feature disabled (error: %q)", err) - } - // END TODO: Remove when EphemeralContainers feature gate is retired. framework.ExpectNoError(err, "Failed to patch ephemeral containers in pod %q", format.Pod(pod)) ginkgo.By("checking pod container endpoints") diff --git a/test/e2e/framework/util.go b/test/e2e/framework/util.go index 3429ec2ba1a..54bde0cb964 100644 --- a/test/e2e/framework/util.go +++ b/test/e2e/framework/util.go @@ -50,7 +50,6 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/watch" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/dynamic" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" @@ -58,7 +57,6 @@ import ( "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" watchtools "k8s.io/client-go/tools/watch" - "k8s.io/component-base/featuregate" testutils "k8s.io/kubernetes/test/utils" imageutils "k8s.io/kubernetes/test/utils/image" uexec "k8s.io/utils/exec" @@ -776,8 +774,6 @@ func (f *Framework) testContainerOutputMatcher(scenarioName string, type ContainerType int const ( - // FeatureEphemeralContainers allows running an ephemeral container in pod namespaces to troubleshoot a running pod - FeatureEphemeralContainers featuregate.Feature = "EphemeralContainers" // Containers is for normal containers Containers ContainerType = 1 << iota // InitContainers is for init containers @@ -790,11 +786,7 @@ const ( // types except for the ones guarded by feature gate. // Copied from pkg/api/v1/pod to avoid pulling extra dependencies func allFeatureEnabledContainers() ContainerType { - containerType := AllContainers - if !utilfeature.DefaultFeatureGate.Enabled(FeatureEphemeralContainers) { - containerType &= ^EphemeralContainers - } - return containerType + return AllContainers } // ContainerVisitor is called with each container spec, and returns true diff --git a/test/e2e/framework/volume/fixtures.go b/test/e2e/framework/volume/fixtures.go index 54d0418a415..bba6fa05365 100644 --- a/test/e2e/framework/volume/fixtures.go +++ b/test/e2e/framework/volume/fixtures.go @@ -609,12 +609,6 @@ func testVolumeClient(f *framework.Framework, config TestConfig, fsGroup *int64, ec.Name = "volume-ephemeral-container" err = f.PodClient().AddEphemeralContainerSync(clientPod, ec, timeouts.PodStart) // The API server will return NotFound for the subresource when the feature is disabled - // BEGIN TODO: remove after EphemeralContainers feature gate is retired - if apierrors.IsNotFound(err) { - framework.Logf("Skipping ephemeral container re-test because feature is disabled (error: %q)", err) - return - } - // END TODO: remove after EphemeralContainers feature gate is retired framework.ExpectNoError(err, "failed to add ephemeral container for re-test") testVolumeContent(f, clientPod, ec.Name, fsGroup, fsType, tests) } diff --git a/test/integration/apiserver/admissionwebhook/admission_test.go b/test/integration/apiserver/admissionwebhook/admission_test.go index eee81848208..64f612f996e 100644 --- a/test/integration/apiserver/admissionwebhook/admission_test.go +++ b/test/integration/apiserver/admissionwebhook/admission_test.go @@ -491,7 +491,7 @@ func testWebhookAdmission(t *testing.T, watchCache bool) { // force enable all resources so we can check storage. "--runtime-config=api/all=true", // enable feature-gates that protect resources to check their storage, too. - "--feature-gates=EphemeralContainers=true", + // e.g. "--feature-gates=EphemeralContainers=true", }, etcdConfig) defer server.TearDownFn() diff --git a/test/integration/pods/pods_test.go b/test/integration/pods/pods_test.go index 7f69d6a11fe..225ff46b10e 100644 --- a/test/integration/pods/pods_test.go +++ b/test/integration/pods/pods_test.go @@ -23,15 +23,11 @@ import ( "testing" v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" typedv1 "k8s.io/client-go/kubernetes/typed/core/v1" - featuregatetesting "k8s.io/component-base/featuregate/testing" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/test/integration" "k8s.io/kubernetes/test/integration/framework" ) @@ -190,8 +186,6 @@ func TestPodReadOnlyFilesystem(t *testing.T) { } func TestPodCreateEphemeralContainers(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd()) defer server.TearDownFn() @@ -261,8 +255,6 @@ func setUpEphemeralContainers(podsClient typedv1.PodInterface, pod *v1.Pod, cont } func TestPodPatchEphemeralContainers(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd()) defer server.TearDownFn() @@ -494,8 +486,6 @@ func TestPodPatchEphemeralContainers(t *testing.T) { } func TestPodUpdateEphemeralContainers(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, true)() - // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd()) defer server.TearDownFn() @@ -684,61 +674,3 @@ func TestPodUpdateEphemeralContainers(t *testing.T) { integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name) } } - -// TestPodEphemeralContainersDisabled tests that the API server returns a 404 when the feature is disabled (because the subresource won't exist). -// This validates that the feature gate is working, but kubectl also uses the 404 to guess that the feature is disabled on the server. -func TestPodEphemeralContainersDisabled(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.EphemeralContainers, false)() - - // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. - server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins=ServiceAccount"}, framework.SharedEtcd()) - defer server.TearDownFn() - - client := clientset.NewForConfigOrDie(server.ClientConfig) - - ns := framework.CreateNamespaceOrDie(client, "pod-ephemeral-containers-disabled", t) - defer framework.DeleteNamespaceOrDie(client, ns, t) - - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ephemeral-container-pod", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "fake-name", - Image: "fakeimage", - }, - }, - }, - } - pod, err := setUpEphemeralContainers(client.CoreV1().Pods(ns.Name), pod, nil) - if err != nil { - t.Fatal(err) - } - defer integration.DeletePodOrErrorf(t, client, ns.Name, pod.Name) - - pod.Spec.EphemeralContainers = append(pod.Spec.EphemeralContainers, v1.EphemeralContainer{ - EphemeralContainerCommon: v1.EphemeralContainerCommon{ - Name: "debugger", - Image: "debugimage", - ImagePullPolicy: "Always", - TerminationMessagePolicy: "File", - }, - }) - - if _, err = client.CoreV1().Pods(ns.Name).UpdateEphemeralContainers(context.TODO(), pod.Name, pod, metav1.UpdateOptions{}); err == nil { - t.Fatalf("got nil error when updating ephemeral containers with feature disabled, wanted %q", metav1.StatusReasonNotFound) - } - - se, ok := err.(*errors.StatusError) - if !ok { - t.Fatalf("got error %#v, expected StatusError", err) - } - if se.ErrStatus.Reason != metav1.StatusReasonNotFound { - t.Errorf("got error reason %q when updating ephemeral containers with feature disabled, want %q: %#v", se.ErrStatus.Reason, metav1.StatusReasonNotFound, se) - } - if se.ErrStatus.Details.Name != "" { - t.Errorf("got error details with name %q, want %q: %#v", se.ErrStatus.Details.Name, "", se) - } -}