diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 432c8f216eee..323763866462 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -7860,7 +7860,7 @@ }, "os": { "$ref": "#/definitions/io.k8s.api.core.v1.PodOS", - "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature" + "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup" }, "overhead": { "additionalProperties": { diff --git a/api/openapi-spec/v3/api__v1_openapi.json b/api/openapi-spec/v3/api__v1_openapi.json index 881e24573a23..1be2523809b7 100644 --- a/api/openapi-spec/v3/api__v1_openapi.json +++ b/api/openapi-spec/v3/api__v1_openapi.json @@ -5083,7 +5083,7 @@ "$ref": "#/components/schemas/io.k8s.api.core.v1.PodOS" } ], - "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature" + "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup" }, "overhead": { "additionalProperties": { diff --git a/api/openapi-spec/v3/apis__apps__v1_openapi.json b/api/openapi-spec/v3/apis__apps__v1_openapi.json index 8f1336f7db70..cb759a90983b 100644 --- a/api/openapi-spec/v3/apis__apps__v1_openapi.json +++ b/api/openapi-spec/v3/apis__apps__v1_openapi.json @@ -3506,7 +3506,7 @@ "$ref": "#/components/schemas/io.k8s.api.core.v1.PodOS" } ], - "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature" + "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup" }, "overhead": { "additionalProperties": { diff --git a/api/openapi-spec/v3/apis__batch__v1_openapi.json b/api/openapi-spec/v3/apis__batch__v1_openapi.json index 9421226a7f30..3774968b8d34 100644 --- a/api/openapi-spec/v3/apis__batch__v1_openapi.json +++ b/api/openapi-spec/v3/apis__batch__v1_openapi.json @@ -2585,7 +2585,7 @@ "$ref": "#/components/schemas/io.k8s.api.core.v1.PodOS" } ], - "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature" + "description": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup" }, "overhead": { "additionalProperties": { diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 70d8a5cdaeeb..3f485aad1ee9 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -418,8 +418,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po AllowWindowsHostProcessField: utilfeature.DefaultFeatureGate.Enabled(features.WindowsHostProcessContainers), // Allow pod spec with expanded DNS configuration AllowExpandedDNSConfig: utilfeature.DefaultFeatureGate.Enabled(features.ExpandedDNSConfig) || haveSameExpandedDNSConfig(podSpec, oldPodSpec), - // Allow pod spec to use OS field - AllowOSField: utilfeature.DefaultFeatureGate.Enabled(features.IdentifyPodOS), } if oldPodSpec != nil { @@ -435,9 +433,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po // if old spec has Windows Host Process fields set, we must allow it opts.AllowWindowsHostProcessField = opts.AllowWindowsHostProcessField || setsWindowsHostProcess(oldPodSpec) - // if old spec has OS field set, we must allow it - opts.AllowOSField = opts.AllowOSField || oldPodSpec.OS != nil - // if old spec used non-integer multiple of huge page unit size, we must allow it opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec) @@ -556,10 +551,6 @@ func dropDisabledFields( dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec) - if !utilfeature.DefaultFeatureGate.Enabled(features.IdentifyPodOS) && !podOSInUse(oldPodSpec) { - podSpec.OS = nil - } - dropDisabledTopologySpreadConstraintsFields(podSpec, oldPodSpec) dropDisabledNodeInclusionPolicyFields(podSpec, oldPodSpec) } @@ -591,17 +582,6 @@ func minDomainsInUse(podSpec *api.PodSpec) bool { return false } -// podOSInUse returns true if the pod spec is non-nil and has OS field set -func podOSInUse(podSpec *api.PodSpec) bool { - if podSpec == nil { - return false - } - if podSpec.OS != nil { - return true - } - return false -} - // dropDisabledProcMountField removes disabled fields from PodSpec related // to ProcMount only if it is not already used by the old spec func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) { diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index 8444c24a458b..4e95e70a0e5d 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -1687,88 +1687,6 @@ func TestDropDisabledTopologySpreadConstraintsFields(t *testing.T) { } } -func TestDropOSField(t *testing.T) { - podWithOSField := func() *api.Pod { - osField := api.PodOS{Name: "linux"} - return &api.Pod{ - Spec: api.PodSpec{ - OS: &osField, - }, - } - } - podWithoutOSField := func() *api.Pod { return &api.Pod{} } - podInfo := []struct { - description string - hasPodOSField bool - pod func() *api.Pod - }{ - { - description: "has PodOS field", - hasPodOSField: true, - pod: podWithOSField, - }, - { - description: "does not have PodOS field", - hasPodOSField: false, - pod: podWithoutOSField, - }, - { - description: "is nil", - hasPodOSField: false, - pod: func() *api.Pod { return nil }, - }, - } - - for _, enabled := range []bool{true, false} { - for _, oldPodInfo := range podInfo { - for _, newPodInfo := range podInfo { - oldPodHasOsField, oldPod := oldPodInfo.hasPodOSField, oldPodInfo.pod() - newPodHasOSField, newPod := newPodInfo.hasPodOSField, 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.IdentifyPodOS, 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 || oldPodHasOsField: - // 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 newPodHasOSField: - // new pod should be changed - if reflect.DeepEqual(newPod, newPodInfo.pod()) { - t.Errorf("new pod was not changed") - } - // new pod should not have OSfield - if !reflect.DeepEqual(newPod, podWithoutOSField()) { - t.Errorf("new pod has OS field: %v", cmp.Diff(newPod, podWithoutOSField())) - } - 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 TestDropNodeInclusionPolicyFields(t *testing.T) { ignore := api.NodeInclusionPolicyIgnore honor := api.NodeInclusionPolicyHonor diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index 47422df57a4b..9cfba71322ac 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -2992,7 +2992,6 @@ type PodSpec struct { // - spec.containers[*].securityContext.runAsUser // - spec.containers[*].securityContext.runAsGroup // +optional - // This is a beta field and requires the IdentifyPodOS feature OS *PodOS } diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index a8adf223cb3d..8476f1955e16 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -3396,8 +3396,6 @@ type PodValidationOptions struct { AllowWindowsHostProcessField bool // Allow more DNSSearchPaths and longer DNSSearchListChars AllowExpandedDNSConfig bool - // Allow OSField to be set in the pod spec - AllowOSField bool } // validatePodMetadataAndSpec tests if required fields in the pod.metadata and pod.spec are set, @@ -6345,9 +6343,6 @@ func validateOS(podSpec *core.PodSpec, fldPath *field.Path, opts PodValidationOp if os == nil { return allErrs } - if !opts.AllowOSField { - return append(allErrs, field.Forbidden(fldPath, "cannot be set when IdentifyPodOS feature is not enabled")) - } if len(os.Name) == 0 { return append(allErrs, field.Required(fldPath.Child("name"), "cannot be empty")) } diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index ec2b42a6eb3c..84da5da4fdaa 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -6851,40 +6851,24 @@ func TestValidateWindowsPodSecurityContext(t *testing.T) { validWindowsSC := &core.PodSecurityContext{WindowsOptions: &core.WindowsSecurityContextOptions{RunAsUserName: utilpointer.String("dummy")}} invalidWindowsSC := &core.PodSecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummyRole"}} cases := map[string]struct { - podSec *core.PodSpec - expectErr bool - errorType field.ErrorType - errorDetail string - featureEnabled bool + podSec *core.PodSpec + expectErr bool + errorType field.ErrorType + errorDetail string }{ "valid SC, windows, no error": { - podSec: &core.PodSpec{SecurityContext: validWindowsSC}, - expectErr: false, - featureEnabled: true, + podSec: &core.PodSpec{SecurityContext: validWindowsSC}, + expectErr: false, }, "invalid SC, windows, error": { - podSec: &core.PodSpec{SecurityContext: invalidWindowsSC}, - errorType: "FieldValueForbidden", - errorDetail: "cannot be set for a windows pod", - expectErr: true, - featureEnabled: true, - }, - "valid SC, windows, no error, no IdentifyPodOS featuregate": { - podSec: &core.PodSpec{SecurityContext: validWindowsSC}, - expectErr: false, - featureEnabled: false, - }, - "invalid SC, windows, error, no IdentifyPodOS featuregate": { - podSec: &core.PodSpec{SecurityContext: invalidWindowsSC}, - errorType: "FieldValueForbidden", - errorDetail: "cannot be set for a windows pod", - expectErr: true, - featureEnabled: false, + podSec: &core.PodSpec{SecurityContext: invalidWindowsSC}, + errorType: "FieldValueForbidden", + errorDetail: "cannot be set for a windows pod", + expectErr: true, }, } for k, v := range cases { t.Run(k, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IdentifyPodOS, v.featureEnabled)() errs := validateWindows(v.podSec, field.NewPath("field")) if v.expectErr && len(errs) > 0 { if errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { @@ -6916,40 +6900,24 @@ func TestValidateLinuxPodSecurityContext(t *testing.T) { } cases := map[string]struct { - podSpec *core.PodSpec - expectErr bool - errorType field.ErrorType - errorDetail string - featureEnabled bool + podSpec *core.PodSpec + expectErr bool + errorType field.ErrorType + errorDetail string }{ "valid SC, linux, no error": { - podSpec: &core.PodSpec{SecurityContext: validLinuxSC}, - expectErr: false, - featureEnabled: true, + podSpec: &core.PodSpec{SecurityContext: validLinuxSC}, + expectErr: false, }, "invalid SC, linux, error": { - podSpec: &core.PodSpec{SecurityContext: invalidLinuxSC}, - errorType: "FieldValueForbidden", - errorDetail: "windows options cannot be set for a linux pod", - expectErr: true, - featureEnabled: true, - }, - "valid SC, linux, no error, no IdentifyPodOS featuregate": { - podSpec: &core.PodSpec{SecurityContext: validLinuxSC}, - expectErr: false, - featureEnabled: false, - }, - "invalid SC, linux, error, no IdentifyPodOS featuregate": { - podSpec: &core.PodSpec{SecurityContext: invalidLinuxSC}, - errorType: "FieldValueForbidden", - errorDetail: "windows options cannot be set for a linux pod", - expectErr: true, - featureEnabled: false, + podSpec: &core.PodSpec{SecurityContext: invalidLinuxSC}, + errorType: "FieldValueForbidden", + errorDetail: "windows options cannot be set for a linux pod", + expectErr: true, }, } for k, v := range cases { t.Run(k, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IdentifyPodOS, v.featureEnabled)() errs := validateLinux(v.podSpec, field.NewPath("field")) if v.expectErr && len(errs) > 0 { if errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { @@ -9964,11 +9932,10 @@ func TestValidatePodUpdate(t *testing.T) { ) tests := []struct { - new core.Pod - old core.Pod - err string - test string - enablePodOS bool + new core.Pod + old core.Pod + err string + test string }{ {new: core.Pod{}, old: core.Pod{}, err: "", test: "nothing"}, { @@ -10792,9 +10759,8 @@ func TestValidatePodUpdate(t *testing.T) { SecurityContext: &core.PodSecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}, }, }, - err: "Forbidden: pod updates may not change fields other than `spec.containers[*].image`,", - test: "pod OS changing from Linux to Windows, no IdentifyPodOS featuregate set, no validation done", - enablePodOS: false, + err: "Forbidden: pod updates may not change fields other than `spec.containers[*].image", + test: "pod OS changing from Linux to Windows, IdentifyPodOS featuregate set", }, { new: core.Pod{ @@ -10815,32 +10781,8 @@ func TestValidatePodUpdate(t *testing.T) { SecurityContext: &core.PodSecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}, }, }, - err: "Forbidden: pod updates may not change fields other than `spec.containers[*].image", - test: "pod OS changing from Linux to Windows, IdentifyPodOS featuregate set", - enablePodOS: true, - }, - { - new: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Spec: core.PodSpec{ - OS: &core.PodOS{Name: core.Windows}, - SecurityContext: &core.PodSecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}, - }, - }, - old: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Spec: core.PodSpec{ - OS: &core.PodOS{Name: core.Linux}, - SecurityContext: &core.PodSecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}, - }, - }, - err: "spec.securityContext.seLinuxOptions: Forbidden", - test: "pod OS changing from Linux to Windows, IdentifyPodOS featuregate set, we'd get SELinux errors as well", - enablePodOS: true, + err: "spec.securityContext.seLinuxOptions: Forbidden", + test: "pod OS changing from Linux to Windows, IdentifyPodOS featuregate set, we'd get SELinux errors as well", }, { new: core.Pod{ @@ -10857,28 +10799,8 @@ func TestValidatePodUpdate(t *testing.T) { }, Spec: core.PodSpec{}, }, - err: "Forbidden: pod updates may not change fields other than `spec.containers[*].image", - test: "invalid PodOS update, IdentifyPodOS featuregate set", - enablePodOS: true, - }, - { - new: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Spec: core.PodSpec{ - OS: &core.PodOS{Name: core.Windows}, - }, - }, - old: core.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Spec: core.PodSpec{}, - }, - err: "Forbidden: pod updates may not change fields other than `spec.containers[*].image", - test: "no pod spec OS to a valid value, no featuregate", - enablePodOS: false, + err: "Forbidden: pod updates may not change fields other than `spec.containers[*].image", + test: "invalid PodOS update, IdentifyPodOS featuregate set", }, { new: core.Pod{ @@ -10927,7 +10849,7 @@ func TestValidatePodUpdate(t *testing.T) { test.old.Spec.RestartPolicy = "Always" } - errs := ValidatePodUpdate(&test.new, &test.old, PodValidationOptions{AllowOSField: test.enablePodOS}) + errs := ValidatePodUpdate(&test.new, &test.old, PodValidationOptions{}) if test.err == "" { if len(errs) != 0 { t.Errorf("unexpected invalid: %s (%+v)\nA: %+v\nB: %+v", test.test, errs, test.new, test.old) @@ -17504,61 +17426,34 @@ func TestValidateEndpointsUpdate(t *testing.T) { func TestValidateWindowsSecurityContext(t *testing.T) { tests := []struct { - name string - sc *core.PodSpec - expectError bool - errorMsg string - errorType field.ErrorType - featureEnabled bool + name string + sc *core.PodSpec + expectError bool + errorMsg string + errorType field.ErrorType }{ { - name: "pod with SELinux Options", - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}}}}, - expectError: true, - errorMsg: "cannot be set for a windows pod", - errorType: "FieldValueForbidden", - featureEnabled: true, - }, - { - name: "pod with SeccompProfile", - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{SeccompProfile: &core.SeccompProfile{LocalhostProfile: utilpointer.String("dummy")}}}}}, - expectError: true, - errorMsg: "cannot be set for a windows pod", - errorType: "FieldValueForbidden", - featureEnabled: true, - }, - { - name: "pod with WindowsOptions, no error", - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{WindowsOptions: &core.WindowsSecurityContextOptions{RunAsUserName: utilpointer.String("dummy")}}}}}, - expectError: false, - featureEnabled: true, - }, - { - name: "pod with SELinux Options, no IdentifyPodOS enabled", - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}}}}, - expectError: true, - errorMsg: "cannot be set for a windows pod", - errorType: "FieldValueForbidden", - featureEnabled: false, + name: "pod with SELinux Options", + sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{SELinuxOptions: &core.SELinuxOptions{Role: "dummy"}}}}}, + expectError: true, + errorMsg: "cannot be set for a windows pod", + errorType: "FieldValueForbidden", }, { - name: "pod with SeccompProfile, no IdentifyPodOS enabled", - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{SeccompProfile: &core.SeccompProfile{LocalhostProfile: utilpointer.String("dummy")}}}}}, - expectError: true, - errorMsg: "cannot be set for a windows pod", - errorType: "FieldValueForbidden", - featureEnabled: false, + name: "pod with SeccompProfile", + sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{SeccompProfile: &core.SeccompProfile{LocalhostProfile: utilpointer.String("dummy")}}}}}, + expectError: true, + errorMsg: "cannot be set for a windows pod", + errorType: "FieldValueForbidden", }, { - name: "pod with WindowsOptions, no error, no IdentifyPodOS enabled", - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{WindowsOptions: &core.WindowsSecurityContextOptions{RunAsUserName: utilpointer.String("dummy")}}}}}, - expectError: false, - featureEnabled: false, + name: "pod with WindowsOptions, no error", + sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: &core.SecurityContext{WindowsOptions: &core.WindowsSecurityContextOptions{RunAsUserName: utilpointer.String("dummy")}}}}}, + expectError: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IdentifyPodOS, test.featureEnabled)() errs := validateWindows(test.sc, field.NewPath("field")) if test.expectError && len(errs) > 0 { if errs[0].Type != test.errorType { @@ -17843,40 +17738,24 @@ func TestValidateLinuxSecurityContext(t *testing.T) { WindowsOptions: &core.WindowsSecurityContextOptions{RunAsUserName: utilpointer.String("myUser")}, } cases := map[string]struct { - sc *core.PodSpec - expectErr bool - errorType field.ErrorType - errorDetail string - featureEnabled bool + sc *core.PodSpec + expectErr bool + errorType field.ErrorType + errorDetail string }{ "valid SC, linux, no error": { - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: validLinuxSC}}}, - expectErr: false, - featureEnabled: true, + sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: validLinuxSC}}}, + expectErr: false, }, "invalid SC, linux, error": { - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: invalidLinuxSC}}}, - errorType: "FieldValueForbidden", - errorDetail: "windows options cannot be set for a linux pod", - expectErr: true, - featureEnabled: true, - }, - "valid SC, linux, no error, no IdentifyPodOS featuregate": { - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: validLinuxSC}}}, - expectErr: false, - featureEnabled: false, - }, - "invalid SC, linux, error, no IdentifyPodOS featuregate": { - sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: invalidLinuxSC}}}, - errorType: "FieldValueForbidden", - errorDetail: "windows options cannot be set for a linux pod", - expectErr: true, - featureEnabled: false, + sc: &core.PodSpec{Containers: []core.Container{{SecurityContext: invalidLinuxSC}}}, + errorType: "FieldValueForbidden", + errorDetail: "windows options cannot be set for a linux pod", + expectErr: true, }, } for k, v := range cases { t.Run(k, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IdentifyPodOS, v.featureEnabled)() errs := validateLinux(v.sc, field.NewPath("field")) if v.expectErr && len(errs) > 0 { if errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { @@ -20377,83 +20256,44 @@ func TestValidateWindowsHostProcessPod(t *testing.T) { func TestValidateOS(t *testing.T) { testCases := []struct { - name string - expectError bool - featureEnabled bool - podSpec *core.PodSpec + name string + expectError bool + podSpec *core.PodSpec }{ { - name: "no OS field, featuregate", - expectError: false, - featureEnabled: true, - podSpec: &core.PodSpec{OS: nil}, - }, - { - name: "empty OS field, featuregate", - expectError: true, - featureEnabled: true, - podSpec: &core.PodSpec{OS: &core.PodOS{}}, - }, - { - name: "no OS field, no featuregate", - expectError: false, - featureEnabled: false, - podSpec: &core.PodSpec{OS: nil}, - }, - { - name: "empty OS field, no featuregate", - expectError: true, - featureEnabled: false, - podSpec: &core.PodSpec{OS: &core.PodOS{}}, - }, - { - name: "OS field, featuregate, valid OS", - expectError: false, - featureEnabled: true, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: core.Linux}}, - }, - { - name: "OS field, featuregate, valid OS", - expectError: false, - featureEnabled: true, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: core.Windows}}, + name: "no OS field, featuregate", + expectError: false, + podSpec: &core.PodSpec{OS: nil}, }, { - name: "OS field, featuregate, empty OS", - expectError: true, - featureEnabled: true, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: ""}}, + name: "empty OS field, featuregate", + expectError: true, + podSpec: &core.PodSpec{OS: &core.PodOS{}}, }, { - name: "OS field, no featuregate, empty OS", - expectError: true, - featureEnabled: false, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: ""}}, + name: "OS field, featuregate, valid OS", + expectError: false, + podSpec: &core.PodSpec{OS: &core.PodOS{Name: core.Linux}}, }, { - name: "OS field, featuregate, invalid OS", - expectError: true, - featureEnabled: true, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: "dummyOS"}}, + name: "OS field, featuregate, valid OS", + expectError: false, + podSpec: &core.PodSpec{OS: &core.PodOS{Name: core.Windows}}, }, { - name: "OS field, no featuregate, valid OS", - expectError: true, - featureEnabled: false, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: core.Linux}}, + name: "OS field, featuregate, empty OS", + expectError: true, + podSpec: &core.PodSpec{OS: &core.PodOS{Name: ""}}, }, { - name: "OS field, no featuregate, invalid OS", - expectError: true, - featureEnabled: false, - podSpec: &core.PodSpec{OS: &core.PodOS{Name: "dummyOS"}}, + name: "OS field, featuregate, invalid OS", + expectError: true, + podSpec: &core.PodSpec{OS: &core.PodOS{Name: "dummyOS"}}, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IdentifyPodOS, testCase.featureEnabled)() - - errs := validateOS(testCase.podSpec, field.NewPath("spec"), PodValidationOptions{AllowOSField: testCase.featureEnabled}) + errs := validateOS(testCase.podSpec, field.NewPath("spec"), PodValidationOptions{}) if testCase.expectError && len(errs) == 0 { t.Errorf("Unexpected success") } diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 908f76bd7624..8dff0fc0829f 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -374,6 +374,7 @@ const ( // owner: @ravig // alpha: v1.23 // beta: v1.24 + // GA: v1.25 // IdentifyPodOS allows user to specify OS on which they'd like the Pod run. The user should still set the nodeSelector // with appropriate `kubernetes.io/os` label for scheduler to identify appropriate node for the pod to run. IdentifyPodOS featuregate.Feature = "IdentifyPodOS" @@ -904,7 +905,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS HonorPVReclaimPolicy: {Default: false, PreRelease: featuregate.Alpha}, - IdentifyPodOS: {Default: true, PreRelease: featuregate.Beta}, + IdentifyPodOS: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27 InTreePluginAWSUnregister: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index f82adba6d709..53b017024c27 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -22176,7 +22176,7 @@ func schema_k8sio_api_core_v1_PodSpec(ref common.ReferenceCallback) common.OpenA }, "os": { SchemaProps: spec.SchemaProps{ - Description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature", + Description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup", Ref: ref("k8s.io/api/core/v1.PodOS"), }, }, diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 657c3af90b82..b706f7fd78c9 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -3728,7 +3728,6 @@ message PodSpec { // - spec.containers[*].securityContext.runAsUser // - spec.containers[*].securityContext.runAsGroup // +optional - // This is a beta field and requires the IdentifyPodOS feature optional PodOS os = 36; } diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index ddc7023948c5..bdd3da4d6bcc 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -3305,7 +3305,6 @@ type PodSpec struct { // - spec.containers[*].securityContext.runAsUser // - spec.containers[*].securityContext.runAsGroup // +optional - // This is a beta field and requires the IdentifyPodOS feature OS *PodOS `json:"os,omitempty" protobuf:"bytes,36,opt,name=os"` } diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index cbbca1b8ace4..bc9e2e039f01 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1670,7 +1670,7 @@ var map_PodSpec = map[string]string{ "overhead": "Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. This field will be autopopulated at admission time by the RuntimeClass admission controller. If the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. The RuntimeClass admission controller will reject Pod create requests which have the overhead already set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md", "topologySpreadConstraints": "TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed.", "setHostnameAsFQDN": "If true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters to FQDN. If a pod does not have FQDN, this has no effect. Default to false.", - "os": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature", + "os": "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set.\n\nIf the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions\n\nIf the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup", } func (PodSpec) SwaggerDoc() map[string]string {