Merge pull request #123385 from HirazawaUi/allow-special-characters

Allow almost all printable ASCII characters in environment variables
This commit is contained in:
Kubernetes Prow Robot
2024-03-05 17:31:06 -08:00
committed by GitHub
13 changed files with 1064 additions and 191 deletions

View File

@@ -50,10 +50,11 @@ import (
)
const (
dnsLabelErrMsg = "a lowercase RFC 1123 label must consist of"
dnsSubdomainLabelErrMsg = "a lowercase RFC 1123 subdomain"
envVarNameErrMsg = "a valid environment variable name must consist of"
defaultGracePeriod = int64(30)
dnsLabelErrMsg = "a lowercase RFC 1123 label must consist of"
dnsSubdomainLabelErrMsg = "a lowercase RFC 1123 subdomain"
envVarNameErrMsg = "a valid environment variable name must consist of"
relaxedEnvVarNameFmtErrMsg string = "a valid environment variable names must be printable ASCII characters other than '=' character"
defaultGracePeriod = int64(30)
)
var (
@@ -5981,6 +5982,361 @@ func TestHugePagesEnv(t *testing.T) {
}
}
func TestRelaxedValidateEnv(t *testing.T) {
successCase := []core.EnvVar{
{Name: "!\"#$%&'()", Value: "value"},
{Name: "* +,-./0123456789", Value: "value"},
{Name: ":;<>?@", Value: "value"},
{Name: "ABCDEFG", Value: "value"},
{Name: "abcdefghijklmn", Value: "value"},
{Name: "[\\]^_`{}|~", Value: "value"},
{
Name: "!\"#$%&'()",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.annotations['key']",
},
},
}, {
Name: "!\"#$%&'()",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.labels['key']",
},
},
}, {
Name: "* +,-./0123456789",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
},
}, {
Name: "* +,-./0123456789",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.namespace",
},
},
}, {
Name: "* +,-./0123456789",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.uid",
},
},
}, {
Name: ":;<>?@",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "spec.nodeName",
},
},
}, {
Name: ":;<>?@",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "spec.serviceAccountName",
},
},
}, {
Name: ":;<>?@",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "status.hostIP",
},
},
}, {
Name: ":;<>?@",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "status.podIP",
},
},
}, {
Name: "abcdefghijklmn",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "status.podIPs",
},
},
},
{
Name: "abcdefghijklmn",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "some-secret",
},
Key: "secret-key",
},
},
}, {
Name: "!\"#$%&'()",
ValueFrom: &core.EnvVarSource{
ConfigMapKeyRef: &core.ConfigMapKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "some-config-map",
},
Key: "some-key",
},
},
},
}
if errs := ValidateEnv(successCase, field.NewPath("field"), PodValidationOptions{AllowRelaxedEnvironmentVariableValidation: true}); len(errs) != 0 {
t.Errorf("expected success, got: %v", errs)
}
errorCases := []struct {
name string
envs []core.EnvVar
expectedError string
}{{
name: "illegal character",
envs: []core.EnvVar{{Name: "=abc"}},
expectedError: `[0].name: Invalid value: "=abc": ` + relaxedEnvVarNameFmtErrMsg,
}, {
name: "zero-length name",
envs: []core.EnvVar{{Name: ""}},
expectedError: "[0].name: Required value",
}, {
name: "value and valueFrom specified",
envs: []core.EnvVar{{
Name: "abc",
Value: "foo",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
},
}},
expectedError: "[0].valueFrom: Invalid value: \"\": may not be specified when `value` is not empty",
}, {
name: "valueFrom without a source",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{},
}},
expectedError: "[0].valueFrom: Invalid value: \"\": must specify one of: `fieldRef`, `resourceFieldRef`, `configMapKeyRef` or `secretKeyRef`",
}, {
name: "valueFrom.fieldRef and valueFrom.secretKeyRef specified",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "a-secret",
},
Key: "a-key",
},
},
}},
expectedError: "[0].valueFrom: Invalid value: \"\": may not have more than one field specified at a time",
}, {
name: "valueFrom.fieldRef and valueFrom.configMapKeyRef set",
envs: []core.EnvVar{{
Name: "some_var_name",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
ConfigMapKeyRef: &core.ConfigMapKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "some-config-map",
},
Key: "some-key",
},
},
}},
expectedError: `[0].valueFrom: Invalid value: "": may not have more than one field specified at a time`,
}, {
name: "valueFrom.fieldRef and valueFrom.secretKeyRef specified",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
FieldPath: "metadata.name",
},
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "a-secret",
},
Key: "a-key",
},
ConfigMapKeyRef: &core.ConfigMapKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "some-config-map",
},
Key: "some-key",
},
},
}},
expectedError: `[0].valueFrom: Invalid value: "": may not have more than one field specified at a time`,
}, {
name: "valueFrom.secretKeyRef.name invalid",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
SecretKeyRef: &core.SecretKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "$%^&*#",
},
Key: "a-key",
},
},
}},
}, {
name: "valueFrom.configMapKeyRef.name invalid",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
ConfigMapKeyRef: &core.ConfigMapKeySelector{
LocalObjectReference: core.LocalObjectReference{
Name: "$%^&*#",
},
Key: "some-key",
},
},
}},
}, {
name: "missing FieldPath on ObjectFieldSelector",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
APIVersion: "v1",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Required value`,
}, {
name: "missing APIVersion on ObjectFieldSelector",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.apiVersion: Required value`,
}, {
name: "invalid fieldPath",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.whoops",
APIVersion: "v1",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Invalid value: "metadata.whoops": error converting fieldPath`,
}, {
name: "metadata.name with subscript",
envs: []core.EnvVar{{
Name: "labels",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.name['key']",
APIVersion: "v1",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Invalid value: "metadata.name['key']": error converting fieldPath: field label does not support subscript`,
}, {
name: "metadata.labels without subscript",
envs: []core.EnvVar{{
Name: "labels",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.labels",
APIVersion: "v1",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.hostIPs", "status.podIP", "status.podIPs"`,
}, {
name: "metadata.annotations without subscript",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.annotations",
APIVersion: "v1",
},
},
}},
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.hostIPs", "status.podIP", "status.podIPs"`,
}, {
name: "metadata.annotations with invalid key",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.annotations['invalid~key']",
APIVersion: "v1",
},
},
}},
expectedError: `field[0].valueFrom.fieldRef: Invalid value: "invalid~key"`,
}, {
name: "metadata.labels with invalid key",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "metadata.labels['Www.k8s.io/test']",
APIVersion: "v1",
},
},
}},
expectedError: `field[0].valueFrom.fieldRef: Invalid value: "Www.k8s.io/test"`,
}, {
name: "unsupported fieldPath",
envs: []core.EnvVar{{
Name: "abc",
ValueFrom: &core.EnvVarSource{
FieldRef: &core.ObjectFieldSelector{
FieldPath: "status.phase",
APIVersion: "v1",
},
},
}},
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.hostIPs", "status.podIP", "status.podIPs"`,
},
}
for _, tc := range errorCases {
if errs := ValidateEnv(tc.envs, field.NewPath("field"), PodValidationOptions{AllowRelaxedEnvironmentVariableValidation: true}); len(errs) == 0 {
t.Errorf("expected failure for %s", tc.name)
} else {
for i := range errs {
str := errs[i].Error()
if str != "" && !strings.Contains(str, tc.expectedError) {
t.Errorf("%s: expected error detail either empty or %q, got %q", tc.name, tc.expectedError, str)
}
}
}
}
}
func TestValidateEnv(t *testing.T) {
successCase := []core.EnvVar{
{Name: "abc", Value: "value"},
@@ -6094,6 +6450,67 @@ func TestValidateEnv(t *testing.T) {
t.Errorf("expected success, got: %v", errs)
}
updateSuccessCase := []core.EnvVar{
{Name: "!\"#$%&'()", Value: "value"},
{Name: "* +,-./0123456789", Value: "value"},
{Name: ":;<>?@", Value: "value"},
{Name: "ABCDEFG", Value: "value"},
{Name: "abcdefghijklmn", Value: "value"},
{Name: "[\\]^_`{}|~", Value: "value"},
}
if errs := ValidateEnv(updateSuccessCase, field.NewPath("field"), PodValidationOptions{AllowRelaxedEnvironmentVariableValidation: true}); len(errs) != 0 {
t.Errorf("expected success, got: %v", errs)
}
updateErrorCase := []struct {
name string
envs []core.EnvVar
expectedError string
}{
{
name: "invalid name a",
envs: []core.EnvVar{
{Name: "!\"#$%&'()", Value: "value"},
},
expectedError: `field[0].name: Invalid value: ` + "\"!\\\"#$%&'()\": " + envVarNameErrMsg,
},
{
name: "invalid name b",
envs: []core.EnvVar{
{Name: "* +,-./0123456789", Value: "value"},
},
expectedError: `field[0].name: Invalid value: ` + "\"* +,-./0123456789\": " + envVarNameErrMsg,
},
{
name: "invalid name c",
envs: []core.EnvVar{
{Name: ":;<>?@", Value: "value"},
},
expectedError: `field[0].name: Invalid value: ` + "\":;<>?@\": " + envVarNameErrMsg,
},
{
name: "invalid name d",
envs: []core.EnvVar{
{Name: "[\\]^_{}|~", Value: "value"},
},
expectedError: `field[0].name: Invalid value: ` + "\"[\\\\]^_{}|~\": " + envVarNameErrMsg,
},
}
for _, tc := range updateErrorCase {
if errs := ValidateEnv(tc.envs, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 {
t.Errorf("expected failure for %s", tc.name)
} else {
for i := range errs {
str := errs[i].Error()
if str != "" && !strings.Contains(str, tc.expectedError) {
t.Errorf("%s: expected error detail either empty or %q, got %q", tc.name, tc.expectedError, str)
}
}
}
}
errorCases := []struct {
name string
envs []core.EnvVar
@@ -6102,22 +6519,6 @@ func TestValidateEnv(t *testing.T) {
name: "zero-length name",
envs: []core.EnvVar{{Name: ""}},
expectedError: "[0].name: Required value",
}, {
name: "illegal character",
envs: []core.EnvVar{{Name: "a!b"}},
expectedError: `[0].name: Invalid value: "a!b": ` + envVarNameErrMsg,
}, {
name: "dot only",
envs: []core.EnvVar{{Name: "."}},
expectedError: `[0].name: Invalid value: ".": must not be`,
}, {
name: "double dots only",
envs: []core.EnvVar{{Name: ".."}},
expectedError: `[0].name: Invalid value: "..": must not be`,
}, {
name: "leading double dots",
envs: []core.EnvVar{{Name: "..abc"}},
expectedError: `[0].name: Invalid value: "..abc": must not start with`,
}, {
name: "value and valueFrom specified",
envs: []core.EnvVar{{
@@ -6377,10 +6778,112 @@ func TestValidateEnvFrom(t *testing.T) {
},
},
}
if errs := ValidateEnvFrom(successCase, field.NewPath("field")); len(errs) != 0 {
if errs := ValidateEnvFrom(successCase, nil, PodValidationOptions{}); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
updateSuccessCase := []core.EnvFromSource{{
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: "* +,-./0123456789",
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: ":;<>?@",
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: "abcdefghijklmn",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: "[\\]^_`{}|~",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}}
if errs := ValidateEnvFrom(updateSuccessCase, field.NewPath("field"), PodValidationOptions{AllowRelaxedEnvironmentVariableValidation: true}); len(errs) != 0 {
t.Errorf("expected success, got: %v", errs)
}
updateErrorCase := []struct {
name string
envs []core.EnvFromSource
expectedError string
}{
{
name: "invalid name a",
envs: []core.EnvFromSource{
{
Prefix: "!\"#$%&'()",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
},
},
expectedError: `field[0].prefix: Invalid value: ` + "\"!\\\"#$%&'()\": " + envVarNameErrMsg,
},
{
name: "invalid name b",
envs: []core.EnvFromSource{
{
Prefix: "* +,-./0123456789",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
},
},
expectedError: `field[0].prefix: Invalid value: ` + "\"* +,-./0123456789\": " + envVarNameErrMsg,
},
{
name: "invalid name c",
envs: []core.EnvFromSource{
{
Prefix: ":;<>?@",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
},
},
expectedError: `field[0].prefix: Invalid value: ` + "\":;<>?@\": " + envVarNameErrMsg,
},
{
name: "invalid name d",
envs: []core.EnvFromSource{
{
Prefix: "[\\]^_{}|~",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
},
},
expectedError: `field[0].prefix: Invalid value: ` + "\"[\\\\]^_{}|~\": " + envVarNameErrMsg,
},
}
for _, tc := range updateErrorCase {
if errs := ValidateEnvFrom(tc.envs, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 {
t.Errorf("expected failure for %s", tc.name)
} else {
for i := range errs {
str := errs[i].Error()
if str != "" && !strings.Contains(str, tc.expectedError) {
t.Errorf("%s: expected error detail either empty or %q, got %q", tc.name, tc.expectedError, str)
}
}
}
}
errorCases := []struct {
name string
envs []core.EnvFromSource
@@ -6399,14 +6902,6 @@ func TestValidateEnvFrom(t *testing.T) {
LocalObjectReference: core.LocalObjectReference{Name: "$"}},
}},
expectedError: "field[0].configMapRef.name: Invalid value",
}, {
name: "invalid prefix",
envs: []core.EnvFromSource{{
Prefix: "a!b",
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"}},
}},
expectedError: `field[0].prefix: Invalid value: "a!b": ` + envVarNameErrMsg,
}, {
name: "zero-length name",
envs: []core.EnvFromSource{{
@@ -6421,14 +6916,6 @@ func TestValidateEnvFrom(t *testing.T) {
LocalObjectReference: core.LocalObjectReference{Name: "&"}},
}},
expectedError: "field[0].secretRef.name: Invalid value",
}, {
name: "invalid prefix",
envs: []core.EnvFromSource{{
Prefix: "a!b",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"}},
}},
expectedError: `field[0].prefix: Invalid value: "a!b": ` + envVarNameErrMsg,
}, {
name: "no refs",
envs: []core.EnvFromSource{
@@ -6461,7 +6948,123 @@ func TestValidateEnvFrom(t *testing.T) {
},
}
for _, tc := range errorCases {
if errs := ValidateEnvFrom(tc.envs, field.NewPath("field")); len(errs) == 0 {
if errs := ValidateEnvFrom(tc.envs, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 {
t.Errorf("expected failure for %s", tc.name)
} else {
for i := range errs {
str := errs[i].Error()
if str != "" && !strings.Contains(str, tc.expectedError) {
t.Errorf("%s: expected error detail either empty or %q, got %q", tc.name, tc.expectedError, str)
}
}
}
}
}
func TestRelaxedValidateEnvFrom(t *testing.T) {
successCase := []core.EnvFromSource{{
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: "!\"#$%&'()",
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: "* +,-./0123456789",
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: ":;<>?@",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
}, {
Prefix: "[\\]^_`{}|~",
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"},
},
},
}
if errs := ValidateEnvFrom(successCase, field.NewPath("field"), PodValidationOptions{AllowRelaxedEnvironmentVariableValidation: true}); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}
errorCases := []struct {
name string
envs []core.EnvFromSource
expectedError string
}{
{
name: "zero-length name",
envs: []core.EnvFromSource{{
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: ""}},
}},
expectedError: "field[0].configMapRef.name: Required value",
},
{
name: "invalid prefix",
envs: []core.EnvFromSource{{
Prefix: "=abc",
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"}},
}},
expectedError: `field[0].prefix: Invalid value: "=abc": ` + relaxedEnvVarNameFmtErrMsg,
},
{
name: "zero-length name",
envs: []core.EnvFromSource{{
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: ""}},
}},
expectedError: "field[0].secretRef.name: Required value",
}, {
name: "invalid name",
envs: []core.EnvFromSource{{
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "&"}},
}},
expectedError: "field[0].secretRef.name: Invalid value",
}, {
name: "no refs",
envs: []core.EnvFromSource{
{},
},
expectedError: "field: Invalid value: \"\": must specify one of: `configMapRef` or `secretRef`",
}, {
name: "multiple refs",
envs: []core.EnvFromSource{{
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"}},
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "abc"}},
}},
expectedError: "field: Invalid value: \"\": may not have more than one field specified at a time",
}, {
name: "invalid secret ref name",
envs: []core.EnvFromSource{{
SecretRef: &core.SecretEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "$%^&*#"}},
}},
expectedError: "field[0].secretRef.name: Invalid value: \"$%^&*#\": " + dnsSubdomainLabelErrMsg,
}, {
name: "invalid config ref name",
envs: []core.EnvFromSource{{
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{Name: "$%^&*#"}},
}},
expectedError: "field[0].configMapRef.name: Invalid value: \"$%^&*#\": " + dnsSubdomainLabelErrMsg,
},
}
for _, tc := range errorCases {
if errs := ValidateEnvFrom(tc.envs, field.NewPath("field"), PodValidationOptions{AllowRelaxedEnvironmentVariableValidation: true}); len(errs) == 0 {
t.Errorf("expected failure for %s", tc.name)
} else {
for i := range errs {