From 6a4751da7fa2d3b9c360f98d13e84f09dd21eaf8 Mon Sep 17 00:00:00 2001 From: HirazawaUi <695097494plus@gmail.com> Date: Mon, 2 Jun 2025 17:50:41 +0800 Subject: [PATCH 1/3] Graduate RelaxedEnvironmentVariableValidation Feature gate to GA --- pkg/features/kube_features.go | 1 + pkg/kubelet/kubelet_pods_test.go | 30 ++++---- .../reference/versioned_feature_list.yaml | 4 ++ test/e2e/common/node/configmap.go | 68 +++++++++---------- test/e2e/common/node/expansion.go | 3 +- test/e2e/common/node/secrets.go | 3 +- test/e2e/feature/feature.go | 4 -- 7 files changed, 53 insertions(+), 60 deletions(-) diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index c418e72bf71..8cf73ada6a7 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -1663,6 +1663,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate RelaxedEnvironmentVariableValidation: { {Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha}, {Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.37 }, ReloadKubeletServerCertificateFile: { diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index 6213eaaca36..56ecccafbcf 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -408,20 +408,19 @@ func TestMakeEnvironmentVariables(t *testing.T) { trueValue := true falseValue := false testCases := []struct { - name string // the name of the test case - ns string // the namespace to generate environment for - enableServiceLinks *bool // enabling service links - enableRelaxedEnvironmentVariableValidation bool // enable enableRelaxedEnvironmentVariableValidation feature gate - container *v1.Container // the container to use - nilLister bool // whether the lister should be nil - staticPod bool // whether the pod should be a static pod (versus an API pod) - unsyncedServices bool // whether the services should NOT be synced - configMap *v1.ConfigMap // an optional ConfigMap to pull from - secret *v1.Secret // an optional Secret to pull from - podIPs []string // the pod IPs - expectedEnvs []kubecontainer.EnvVar // a set of expected environment vars - expectedError bool // does the test fail - expectedEvent string // does the test emit an event + name string // the name of the test case + ns string // the namespace to generate environment for + enableServiceLinks *bool // enabling service links + container *v1.Container // the container to use + nilLister bool // whether the lister should be nil + staticPod bool // whether the pod should be a static pod (versus an API pod) + unsyncedServices bool // whether the services should NOT be synced + configMap *v1.ConfigMap // an optional ConfigMap to pull from + secret *v1.Secret // an optional Secret to pull from + podIPs []string // the pod IPs + expectedEnvs []kubecontainer.EnvVar // a set of expected environment vars + expectedError bool // does the test fail + expectedEvent string // does the test emit an event }{ { name: "if services aren't synced, non-static pods should fail", @@ -1339,7 +1338,6 @@ func TestMakeEnvironmentVariables(t *testing.T) { name: "configmap allow prefix to start with a digital", ns: "test1", enableServiceLinks: &falseValue, - enableRelaxedEnvironmentVariableValidation: true, container: &v1.Container{ EnvFrom: []v1.EnvFromSource{ { @@ -1975,8 +1973,6 @@ func TestMakeEnvironmentVariables(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RelaxedEnvironmentVariableValidation, tc.enableRelaxedEnvironmentVariableValidation) - fakeRecorder := record.NewFakeRecorder(1) testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) testKubelet.kubelet.recorder = fakeRecorder diff --git a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml index aa0dfbf5f43..c0d05d8cf9a 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -1189,6 +1189,10 @@ lockToDefault: false preRelease: Beta version: "1.32" + - default: true + lockToDefault: true + preRelease: GA + version: "1.34" - name: ReloadKubeletServerCertificateFile versionedSpecs: - default: true diff --git a/test/e2e/common/node/configmap.go b/test/e2e/common/node/configmap.go index 309441c1634..e795bd42498 100644 --- a/test/e2e/common/node/configmap.go +++ b/test/e2e/common/node/configmap.go @@ -25,7 +25,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output" imageutils "k8s.io/kubernetes/test/utils/image" @@ -250,47 +249,46 @@ var _ = SIGDescribe("ConfigMap", func() { Description: Create a Pod with an environment variable value set using a value from ConfigMap. Allows users to use envFrom to set prefix starting with a digit as environment variable names. */ - framework.It("should be consumable as environment variable names when configmap keys start with a digit", - feature.RelaxedEnvironmentVariableValidation, func(ctx context.Context) { - name := "configmap-test-" + string(uuid.NewUUID()) - configMap := newConfigMap(f, name) - ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name)) - var err error - if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, configMap, metav1.CreateOptions{}); err != nil { - framework.Failf("unable to create test configMap %s: %v", configMap.Name, err) - } + framework.It("should be consumable as environment variable names when configmap keys start with a digit", func(ctx context.Context) { + name := "configmap-test-" + string(uuid.NewUUID()) + configMap := newConfigMap(f, name) + ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name)) + var err error + if configMap, err = f.ClientSet.CoreV1().ConfigMaps(f.Namespace.Name).Create(ctx, configMap, metav1.CreateOptions{}); err != nil { + framework.Failf("unable to create test configMap %s: %v", configMap.Name, err) + } - pod := &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "pod-configmaps-" + string(uuid.NewUUID()), - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "env-test", - Image: imageutils.GetE2EImage(imageutils.BusyBox), - Command: []string{"sh", "-c", "env"}, - EnvFrom: []v1.EnvFromSource{ - { - ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, - }, - { - // prefix start with a digit can be consumed as environment variables. - Prefix: "1-", - ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, - }, + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-configmaps-" + string(uuid.NewUUID()), + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "env-test", + Image: imageutils.GetE2EImage(imageutils.BusyBox), + Command: []string{"sh", "-c", "env"}, + EnvFrom: []v1.EnvFromSource{ + { + ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, + { + // prefix start with a digit can be consumed as environment variables. + Prefix: "1-", + ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, }, }, }, - RestartPolicy: v1.RestartPolicyNever, }, - } + RestartPolicy: v1.RestartPolicyNever, + }, + } - e2epodoutput.TestContainerOutput(ctx, f, "consume configMaps", pod, 0, []string{ - "data-1=value-1", "data-2=value-2", "data-3=value-3", - "1-data-1=value-1", "1-data-2=value-2", "1-data-3=value-3", - }) + e2epodoutput.TestContainerOutput(ctx, f, "consume configMaps", pod, 0, []string{ + "data-1=value-1", "data-2=value-2", "data-3=value-3", + "1-data-1=value-1", "1-data-2=value-2", "1-data-3=value-3", }) + }) }) func newConfigMap(f *framework.Framework, name string) *v1.ConfigMap { diff --git a/test/e2e/common/node/expansion.go b/test/e2e/common/node/expansion.go index 6417ff9ff4c..702610f1343 100644 --- a/test/e2e/common/node/expansion.go +++ b/test/e2e/common/node/expansion.go @@ -22,7 +22,6 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output" @@ -379,7 +378,7 @@ var _ = SIGDescribe("Variable Expansion", func() { Description: Create a Pod with environment variables. Environment variables defined using previously defined environment variables MUST expand to proper values. Allow almost all printable ASCII characters in environment variables. */ - framework.It("allow almost all printable ASCII characters as environment variable names", feature.RelaxedEnvironmentVariableValidation, func(ctx context.Context) { + framework.It("allow almost all printable ASCII characters as environment variable names", func(ctx context.Context) { envVars := []v1.EnvVar{ { Name: "!\"#$%&'()", diff --git a/test/e2e/common/node/secrets.go b/test/e2e/common/node/secrets.go index 29be3811933..be5fe239a41 100644 --- a/test/e2e/common/node/secrets.go +++ b/test/e2e/common/node/secrets.go @@ -26,7 +26,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" - "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output" imageutils "k8s.io/kubernetes/test/utils/image" @@ -246,7 +245,7 @@ var _ = SIGDescribe("Secrets", func() { Description: Create a secret. Create a Pod with Container that declares a environment variable using 'EnvFrom' which references the secret created to extract a key value from the secret. Allows users to use envFrom to set prefix starting with a digit as environment variable names. */ - framework.It("should be consumable as environment variable names when secret keys start with a digit", feature.RelaxedEnvironmentVariableValidation, func(ctx context.Context) { + framework.It("should be consumable as environment variable names when secret keys start with a digit", func(ctx context.Context) { name := "secret-test-" + string(uuid.NewUUID()) secret := secretForTest(f.Namespace.Name, name) diff --git a/test/e2e/feature/feature.go b/test/e2e/feature/feature.go index 86caa4e5cee..7487d840906 100644 --- a/test/e2e/feature/feature.go +++ b/test/e2e/feature/feature.go @@ -368,10 +368,6 @@ var ( // TODO: document the feature (owning SIG, when to use this feature for a test) RecoverVolumeExpansionFailure = framework.WithFeature(framework.ValidFeatures.Add("RecoverVolumeExpansionFailure")) - // RelaxedEnvironmentVariableValidation used when we verify whether the pod can consume all printable ASCII characters as environment variable names, - // and whether the pod can consume configmap/secret that key starts with a number. - RelaxedEnvironmentVariableValidation = framework.WithFeature(framework.ValidFeatures.Add("RelaxedEnvironmentVariableValidation")) - // Owner: sig-network // Marks tests of KEP-4427 that require the `RelaxedDNSSearchValidation` feature gate RelaxedDNSSearchValidation = framework.WithFeature(framework.ValidFeatures.Add("RelaxedDNSSearchValidation")) From 0ca9c380addd044622175851a635f5882423c52b Mon Sep 17 00:00:00 2001 From: HirazawaUi <695097494plus@gmail.com> Date: Sat, 7 Jun 2025 17:58:14 +0800 Subject: [PATCH 2/3] update all api files --- api/openapi-spec/swagger.json | 8 ++++---- api/openapi-spec/v3/api__v1_openapi.json | 8 ++++---- api/openapi-spec/v3/apis__apps__v1_openapi.json | 8 ++++---- api/openapi-spec/v3/apis__batch__v1_openapi.json | 8 ++++---- pkg/apis/core/types.go | 5 +---- pkg/generated/openapi/zz_generated.openapi.go | 10 +++++----- staging/src/k8s.io/api/core/v1/generated.proto | 14 ++++++++------ staging/src/k8s.io/api/core/v1/types.go | 14 ++++++++------ .../api/core/v1/types_swagger_doc_generated.go | 8 ++++---- 9 files changed, 42 insertions(+), 41 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index dbb2140f879..2fbe67e7029 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -6386,7 +6386,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.EnvFromSource" }, @@ -7011,7 +7011,7 @@ "description": "The ConfigMap to select from" }, "prefix": { - "description": "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.", + "description": "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "secretRef": { @@ -7025,7 +7025,7 @@ "description": "EnvVar represents an environment variable present in a Container.", "properties": { "name": { - "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "description": "Name of the environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "value": { @@ -7097,7 +7097,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.EnvFromSource" }, diff --git a/api/openapi-spec/v3/api__v1_openapi.json b/api/openapi-spec/v3/api__v1_openapi.json index 69469cf8eb1..b0c365a8790 100644 --- a/api/openapi-spec/v3/api__v1_openapi.json +++ b/api/openapi-spec/v3/api__v1_openapi.json @@ -1161,7 +1161,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "allOf": [ { @@ -1973,7 +1973,7 @@ "description": "The ConfigMap to select from" }, "prefix": { - "description": "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.", + "description": "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "secretRef": { @@ -1992,7 +1992,7 @@ "properties": { "name": { "default": "", - "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "description": "Name of the environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "value": { @@ -2091,7 +2091,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "allOf": [ { diff --git a/api/openapi-spec/v3/apis__apps__v1_openapi.json b/api/openapi-spec/v3/apis__apps__v1_openapi.json index 0b9a9c0c0a0..a3e92317a6c 100644 --- a/api/openapi-spec/v3/apis__apps__v1_openapi.json +++ b/api/openapi-spec/v3/apis__apps__v1_openapi.json @@ -1799,7 +1799,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "allOf": [ { @@ -2136,7 +2136,7 @@ "description": "The ConfigMap to select from" }, "prefix": { - "description": "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.", + "description": "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "secretRef": { @@ -2155,7 +2155,7 @@ "properties": { "name": { "default": "", - "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "description": "Name of the environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "value": { @@ -2254,7 +2254,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "allOf": [ { diff --git a/api/openapi-spec/v3/apis__batch__v1_openapi.json b/api/openapi-spec/v3/apis__batch__v1_openapi.json index aad92809c62..bbee865b24c 100644 --- a/api/openapi-spec/v3/apis__batch__v1_openapi.json +++ b/api/openapi-spec/v3/apis__batch__v1_openapi.json @@ -1138,7 +1138,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "allOf": [ { @@ -1475,7 +1475,7 @@ "description": "The ConfigMap to select from" }, "prefix": { - "description": "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.", + "description": "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "secretRef": { @@ -1494,7 +1494,7 @@ "properties": { "name": { "default": "", - "description": "Name of the environment variable. Must be a C_IDENTIFIER.", + "description": "Name of the environment variable. May consist of any printable ASCII characters except '='.", "type": "string" }, "value": { @@ -1593,7 +1593,7 @@ "x-kubernetes-patch-strategy": "merge" }, "envFrom": { - "description": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "description": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "items": { "allOf": [ { diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index a0ce67fa8bf..bda508fce20 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -2177,10 +2177,7 @@ type VolumeDevice struct { // EnvVar represents an environment variable present in a Container. type EnvVar struct { // Required: Name of the environment variable. - // When the RelaxedEnvironmentVariableValidation feature gate is disabled, this must consist of alphabetic characters, - // digits, '_', '-', or '.', and must not start with a digit. - // When the RelaxedEnvironmentVariableValidation feature gate is enabled, - // this may contain any printable ASCII characters except '='. + // May consist of any printable ASCII characters except '='. Name string // Optional: no more than one of the following may be specified. // Optional: Defaults to ""; variable references $(VAR_NAME) are expanded diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 3c53377c9bb..8160ef6160e 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -21536,7 +21536,7 @@ func schema_k8sio_api_core_v1_Container(ref common.ReferenceCallback) common.Ope }, }, SchemaProps: spec.SchemaProps{ - Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + Description: "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -22643,7 +22643,7 @@ func schema_k8sio_api_core_v1_EnvFromSource(ref common.ReferenceCallback) common Properties: map[string]spec.Schema{ "prefix": { SchemaProps: spec.SchemaProps{ - Description: "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.", + Description: "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.", Type: []string{"string"}, Format: "", }, @@ -22677,7 +22677,7 @@ func schema_k8sio_api_core_v1_EnvVar(ref common.ReferenceCallback) common.OpenAP Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Description: "Name of the environment variable. Must be a C_IDENTIFIER.", + Description: "Name of the environment variable. May consist of any printable ASCII characters except '='.", Default: "", Type: []string{"string"}, Format: "", @@ -22845,7 +22845,7 @@ func schema_k8sio_api_core_v1_EphemeralContainer(ref common.ReferenceCallback) c }, }, SchemaProps: spec.SchemaProps{ - Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + Description: "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -23153,7 +23153,7 @@ func schema_k8sio_api_core_v1_EphemeralContainerCommon(ref common.ReferenceCallb }, }, SchemaProps: spec.SchemaProps{ - Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + Description: "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 5fa026508d8..897e3dab5bd 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -737,8 +737,8 @@ message Container { repeated ContainerPort ports = 6; // List of sources to populate environment variables in the container. - // The keys defined within a source must be a C_IDENTIFIER. All invalid keys - // will be reported as an event when the container is starting. When a key exists in multiple + // The keys defined within a source may consist of any printable ASCII characters except '='. + // When a key exists in multiple // sources, the value associated with the last source will take precedence. // Values defined by an Env with a duplicate key will take precedence. // Cannot be updated. @@ -1344,7 +1344,8 @@ message EndpointsList { // EnvFromSource represents the source of a set of ConfigMaps or Secrets message EnvFromSource { - // Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. + // Optional text to prepend to the name of each environment variable. + // May consist of any printable ASCII characters except '='. // +optional optional string prefix = 1; @@ -1359,7 +1360,8 @@ message EnvFromSource { // EnvVar represents an environment variable present in a Container. message EnvVar { - // Name of the environment variable. Must be a C_IDENTIFIER. + // Name of the environment variable. + // May consist of any printable ASCII characters except '='. optional string name = 1; // Variable references $(VAR_NAME) are expanded @@ -1479,8 +1481,8 @@ message EphemeralContainerCommon { repeated ContainerPort ports = 6; // List of sources to populate environment variables in the container. - // The keys defined within a source must be a C_IDENTIFIER. All invalid keys - // will be reported as an event when the container is starting. When a key exists in multiple + // The keys defined within a source may consist of any printable ASCII characters except '='. + // When a key exists in multiple // sources, the value associated with the last source will take precedence. // Values defined by an Env with a duplicate key will take precedence. // Cannot be updated. diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 498afe16276..bba1bb28d6b 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -2351,7 +2351,8 @@ type VolumeDevice struct { // EnvVar represents an environment variable present in a Container. type EnvVar struct { - // Name of the environment variable. Must be a C_IDENTIFIER. + // Name of the environment variable. + // May consist of any printable ASCII characters except '='. Name string `json:"name" protobuf:"bytes,1,opt,name=name"` // Optional: no more than one of the following may be specified. @@ -2439,7 +2440,8 @@ type SecretKeySelector struct { // EnvFromSource represents the source of a set of ConfigMaps or Secrets type EnvFromSource struct { - // Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. + // Optional text to prepend to the name of each environment variable. + // May consist of any printable ASCII characters except '='. // +optional Prefix string `json:"prefix,omitempty" protobuf:"bytes,1,opt,name=prefix"` // The ConfigMap to select from @@ -2805,8 +2807,8 @@ type Container struct { // +listMapKey=protocol Ports []ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort" protobuf:"bytes,6,rep,name=ports"` // List of sources to populate environment variables in the container. - // The keys defined within a source must be a C_IDENTIFIER. All invalid keys - // will be reported as an event when the container is starting. When a key exists in multiple + // The keys defined within a source may consist of any printable ASCII characters except '='. + // When a key exists in multiple // sources, the value associated with the last source will take precedence. // Values defined by an Env with a duplicate key will take precedence. // Cannot be updated. @@ -4797,8 +4799,8 @@ type EphemeralContainerCommon struct { // +listMapKey=protocol Ports []ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort" protobuf:"bytes,6,rep,name=ports"` // List of sources to populate environment variables in the container. - // The keys defined within a source must be a C_IDENTIFIER. All invalid keys - // will be reported as an event when the container is starting. When a key exists in multiple + // The keys defined within a source may consist of any printable ASCII characters except '='. + // When a key exists in multiple // sources, the value associated with the last source will take precedence. // Values defined by an Env with a duplicate key will take precedence. // Cannot be updated. 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 ba94e54bfaa..be6949478ce 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 @@ -356,7 +356,7 @@ var map_Container = map[string]string{ "args": "Arguments to the entrypoint. The container image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. \"$$(VAR_NAME)\" will produce the string literal \"$(VAR_NAME)\". Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell", "workingDir": "Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.", "ports": "List of ports to expose from the container. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default \"0.0.0.0\" address inside a container will be accessible from the network. Modifying this array with strategic merge patch may corrupt the data. For more information See https://github.com/kubernetes/kubernetes/issues/108255. Cannot be updated.", - "envFrom": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "envFrom": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "env": "List of environment variables to set in the container. Cannot be updated.", "resources": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", "resizePolicy": "Resources resize policy for the container.", @@ -597,7 +597,7 @@ func (EndpointsList) SwaggerDoc() map[string]string { var map_EnvFromSource = map[string]string{ "": "EnvFromSource represents the source of a set of ConfigMaps or Secrets", - "prefix": "Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER.", + "prefix": "Optional text to prepend to the name of each environment variable. May consist of any printable ASCII characters except '='.", "configMapRef": "The ConfigMap to select from", "secretRef": "The Secret to select from", } @@ -608,7 +608,7 @@ func (EnvFromSource) SwaggerDoc() map[string]string { var map_EnvVar = map[string]string{ "": "EnvVar represents an environment variable present in a Container.", - "name": "Name of the environment variable. Must be a C_IDENTIFIER.", + "name": "Name of the environment variable. May consist of any printable ASCII characters except '='.", "value": "Variable references $(VAR_NAME) are expanded using the previously defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. \"$$(VAR_NAME)\" will produce the string literal \"$(VAR_NAME)\". Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to \"\".", "valueFrom": "Source for the environment variable's value. Cannot be used if value is not empty.", } @@ -646,7 +646,7 @@ var map_EphemeralContainerCommon = map[string]string{ "args": "Arguments to the entrypoint. The image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. \"$$(VAR_NAME)\" will produce the string literal \"$(VAR_NAME)\". Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell", "workingDir": "Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.", "ports": "Ports are not allowed for ephemeral containers.", - "envFrom": "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", + "envFrom": "List of sources to populate environment variables in the container. The keys defined within a source may consist of any printable ASCII characters except '='. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", "env": "List of environment variables to set in the container. Cannot be updated.", "resources": "Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod.", "resizePolicy": "Resources resize policy for the container.", From ef2c18a5a0e7475072bca852bb29b90ce3b86a75 Mon Sep 17 00:00:00 2001 From: HirazawaUi <695097494plus@gmail.com> Date: Wed, 11 Jun 2025 00:02:48 +0800 Subject: [PATCH 3/3] Add more test cases --- test/e2e/common/node/configmap.go | 37 ++++++++++++++++++++++++++----- test/e2e/common/node/secrets.go | 35 ++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 11 deletions(-) diff --git a/test/e2e/common/node/configmap.go b/test/e2e/common/node/configmap.go index e795bd42498..94b7d35539c 100644 --- a/test/e2e/common/node/configmap.go +++ b/test/e2e/common/node/configmap.go @@ -244,12 +244,13 @@ var _ = SIGDescribe("ConfigMap", func() { }) /* - Release: v1.30 - Testname: ConfigMap, from environment field - Description: Create a Pod with an environment variable value set using a value from ConfigMap. - Allows users to use envFrom to set prefix starting with a digit as environment variable names. + Release: v1.34 + Testname: ConfigMap, from environment field with various prefixes + Description: Create a Pod with environment variable values set using values from ConfigMap. + Allows users to use envFrom to set prefixes with various printable ASCII characters excluding '=' as environment variable names. + This test verifies that different prefixes including digits, special characters, and letters can be correctly used. */ - framework.It("should be consumable as environment variable names when configmap keys start with a digit", func(ctx context.Context) { + framework.It("should be consumable as environment variable names with various prefixes", func(ctx context.Context) { name := "configmap-test-" + string(uuid.NewUUID()) configMap := newConfigMap(f, name) ginkgo.By(fmt.Sprintf("Creating configMap %v/%v", f.Namespace.Name, configMap.Name)) @@ -270,13 +271,29 @@ var _ = SIGDescribe("ConfigMap", func() { Command: []string{"sh", "-c", "env"}, EnvFrom: []v1.EnvFromSource{ { + // No prefix ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, }, { - // prefix start with a digit can be consumed as environment variables. + // Prefix starting with a digit Prefix: "1-", ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, }, + { + // Prefix with special characters + Prefix: "$_-", + ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, + { + // Prefix with uppercase letters + Prefix: "ABC_", + ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, + { + // Prefix with symbols + Prefix: "#@!", + ConfigMapRef: &v1.ConfigMapEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, }, }, }, @@ -285,8 +302,16 @@ var _ = SIGDescribe("ConfigMap", func() { } e2epodoutput.TestContainerOutput(ctx, f, "consume configMaps", pod, 0, []string{ + // Original values without prefix "data-1=value-1", "data-2=value-2", "data-3=value-3", + // Values with digit prefix "1-data-1=value-1", "1-data-2=value-2", "1-data-3=value-3", + // Values with special character prefix + "$_-data-1=value-1", "$_-data-2=value-2", "$_-data-3=value-3", + // Values with uppercase letter prefix + "ABC_data-1=value-1", "ABC_data-2=value-2", "ABC_data-3=value-3", + // Values with symbol prefix + "#@!data-1=value-1", "#@!data-2=value-2", "#@!data-3=value-3", }) }) }) diff --git a/test/e2e/common/node/secrets.go b/test/e2e/common/node/secrets.go index be5fe239a41..6c78158f4d1 100644 --- a/test/e2e/common/node/secrets.go +++ b/test/e2e/common/node/secrets.go @@ -240,10 +240,11 @@ var _ = SIGDescribe("Secrets", func() { }) /* - Release: v1.30 + Release: v1.34 Testname: Secrets, pod environment from source - Description: Create a secret. Create a Pod with Container that declares a environment variable using 'EnvFrom' which references the secret created to extract a key value from the secret. - Allows users to use envFrom to set prefix starting with a digit as environment variable names. + Description: Create a Pod with environment variable values set using values from Secret. + Allows users to use envFrom to set prefixes with various printable ASCII characters excluding '=' as environment variable names. + This test verifies that different prefixes including digits, special characters, and letters can be correctly used. */ framework.It("should be consumable as environment variable names when secret keys start with a digit", func(ctx context.Context) { name := "secret-test-" + string(uuid.NewUUID()) @@ -257,7 +258,7 @@ var _ = SIGDescribe("Secrets", func() { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: "pod-configmaps-" + string(uuid.NewUUID()), + Name: "pod-secret-" + string(uuid.NewUUID()), }, Spec: v1.PodSpec{ Containers: []v1.Container{ @@ -267,13 +268,29 @@ var _ = SIGDescribe("Secrets", func() { Command: []string{"sh", "-c", "env"}, EnvFrom: []v1.EnvFromSource{ { + // No prefix SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, }, { - // prefix start with a digit can be consumed as environment variables. + // Prefix starting with a digit Prefix: "1-", SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, }, + { + // Prefix with special characters + Prefix: "$_-", + SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, + { + // Prefix with uppercase letters + Prefix: "ABC_", + SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, + { + // Prefix with symbols + Prefix: "#@!", + SecretRef: &v1.SecretEnvSource{LocalObjectReference: v1.LocalObjectReference{Name: name}}, + }, }, }, }, @@ -282,8 +299,16 @@ var _ = SIGDescribe("Secrets", func() { } e2epodoutput.TestContainerOutput(ctx, f, "consume secrets", pod, 0, []string{ + // Original values without prefix "data-1=value-1", "data-2=value-2", "data-3=value-3", + // Values with digit prefix "1-data-1=value-1", "1-data-2=value-2", "1-data-3=value-3", + // Values with special character prefix + "$_-data-1=value-1", "$_-data-2=value-2", "$_-data-3=value-3", + // Values with uppercase letter prefix + "ABC_data-1=value-1", "ABC_data-2=value-2", "ABC_data-3=value-3", + // Values with symbol prefix + "#@!data-1=value-1", "#@!data-2=value-2", "#@!data-3=value-3", }) }) })