Remove EphemeralContainers feature-gate checks

This commit is contained in:
Lee Verberne 2022-07-24 16:36:42 +02:00
parent bc3c5ae269
commit d238e67ba6
27 changed files with 51 additions and 390 deletions

View File

@ -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 {

View File

@ -43,7 +43,6 @@ func TestVisitContainers(t *testing.T) {
spec *api.PodSpec
wantContainers []string
mask ContainerType
ephemeralContainersEnabled bool
}{
{
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{
@ -164,7 +144,6 @@ func TestVisitContainers(t *testing.T) {
},
wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
mask: setAllFeatureEnabledContainersDuringTest,
ephemeralContainersEnabled: true,
},
{
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

View File

@ -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

View File

@ -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) {
@ -209,7 +206,6 @@ func TestVisitContainers(t *testing.T) {
spec *v1.PodSpec
wantContainers []string
mask ContainerType
ephemeralContainersEnabled bool
}{
{
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"},
@ -330,7 +307,6 @@ func TestVisitContainers(t *testing.T) {
},
wantContainers: []string{"i1", "i2", "c1", "c2", "e1", "e2"},
mask: setAllFeatureEnabledContainersDuringTest,
ephemeralContainersEnabled: true,
},
{
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{

View File

@ -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(),
}

View File

@ -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,14 +45,12 @@ 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
}
}
}
return true
}

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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,7 +65,6 @@ 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 {
@ -77,6 +74,5 @@ func fieldPath(pod *v1.Pod, container *v1.Container) (string, error) {
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)
}

View File

@ -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,7 +1602,6 @@ 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))
@ -1617,7 +1616,6 @@ func (kl *Kubelet) convertStatusToAPIStatus(pod *v1.Pod, podStatus *kubecontaine
len(pod.Spec.InitContainers) > 0,
false,
)
}
return &apiPodStatus
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}
})
}
}

View File

@ -578,7 +578,6 @@ 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)
@ -587,7 +586,6 @@ func (m *kubeGenericRuntimeManager) computePodActions(pod *v1.Pod, podStatus *ku
changes.EphemeralContainersToStart = append(changes.EphemeralContainersToStart, i)
}
}
}
// Check initialization progress.
initLastStatus, next, done := findNextInitContainerToRun(pod, podStatus)
@ -914,11 +912,9 @@ 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]))
}
}
// Step 6: start the init container.
if container := podContainerChanges.NextInitContainerToStart; container != nil {

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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
}
}
if resource := "bindings"; apiResourceConfigSource.ResourceEnabled(corev1.SchemeGroupVersion.WithResource(resource)) {

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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)
}

View File

@ -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()

View File

@ -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)
}
}