mirror of
https://github.com/containers/podman
synced 2024-10-21 01:34:37 +00:00
play kube envVar.valueFrom.fieldRef
add support for env vars values from pod spec fields see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core relates to issue https://github.com/containers/podman/issues/12756 Signed-off-by: Yaron Dayagi <ydayagi@redhat.com>
This commit is contained in:
parent
c96aa23adb
commit
2ceab11947
|
@ -365,6 +365,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels
|
||||
labels[k] = v
|
||||
}
|
||||
|
||||
specgenOpts := kube.CtrSpecGenOptions{
|
||||
Annotations: annotations,
|
||||
Container: initCtr,
|
||||
|
@ -405,7 +410,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels
|
||||
labels[k] = v
|
||||
}
|
||||
|
||||
specgenOpts := kube.CtrSpecGenOptions{
|
||||
Annotations: annotations,
|
||||
Container: container,
|
||||
Image: pulledImage,
|
||||
Volumes: volumes,
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -291,9 +292,9 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Only set the env if the value is not ""
|
||||
if value != "" {
|
||||
envs[env.Name] = value
|
||||
// Only set the env if the value is not nil
|
||||
if value != nil {
|
||||
envs[env.Name] = *value
|
||||
}
|
||||
}
|
||||
for _, envFrom := range opts.Container.EnvFrom {
|
||||
|
@ -609,7 +610,7 @@ func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) (map[string]
|
|||
|
||||
// envVarValue returns the environment variable value configured within the container's env setting.
|
||||
// It gets the value from a configMap or secret if specified, otherwise returns env.Value
|
||||
func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
|
||||
func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
|
||||
if env.ValueFrom != nil {
|
||||
if env.ValueFrom.ConfigMapKeyRef != nil {
|
||||
cmKeyRef := env.ValueFrom.ConfigMapKeyRef
|
||||
|
@ -618,16 +619,16 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
|
|||
for _, c := range opts.ConfigMaps {
|
||||
if cmKeyRef.Name == c.Name {
|
||||
if value, ok := c.Data[cmKeyRef.Key]; ok {
|
||||
return value, nil
|
||||
return &value, nil
|
||||
}
|
||||
err = errors.Errorf("Cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
if cmKeyRef.Optional == nil || !*cmKeyRef.Optional {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
return "", nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if env.ValueFrom.SecretKeyRef != nil {
|
||||
|
@ -635,18 +636,56 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
|
|||
secret, err := k8sSecretFromSecretManager(secKeyRef.Name, opts.SecretsManager)
|
||||
if err == nil {
|
||||
if val, ok := secret[secKeyRef.Key]; ok {
|
||||
return string(val), nil
|
||||
value := string(val)
|
||||
return &value, nil
|
||||
}
|
||||
err = errors.Errorf("Secret %v has not %v key", secKeyRef.Name, secKeyRef.Key)
|
||||
}
|
||||
if secKeyRef.Optional == nil || !*secKeyRef.Optional {
|
||||
return "", errors.Errorf("Cannot set env %v: %v", env.Name, err)
|
||||
return nil, errors.Errorf("Cannot set env %v: %v", env.Name, err)
|
||||
}
|
||||
return "", nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if env.ValueFrom.FieldRef != nil {
|
||||
return envVarValueFieldRef(env, opts)
|
||||
}
|
||||
}
|
||||
|
||||
return env.Value, nil
|
||||
return &env.Value, nil
|
||||
}
|
||||
|
||||
func envVarValueFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) {
|
||||
fieldRef := env.ValueFrom.FieldRef
|
||||
|
||||
fieldPathLabelPattern := `^metadata.labels\['(.+)'\]$`
|
||||
fieldPathLabelRegex := regexp.MustCompile(fieldPathLabelPattern)
|
||||
fieldPathAnnotationPattern := `^metadata.annotations\['(.+)'\]$`
|
||||
fieldPathAnnotationRegex := regexp.MustCompile(fieldPathAnnotationPattern)
|
||||
|
||||
fieldPath := fieldRef.FieldPath
|
||||
|
||||
if fieldPath == "metadata.name" {
|
||||
return &opts.PodName, nil
|
||||
}
|
||||
if fieldPath == "metadata.uid" {
|
||||
return &opts.PodID, nil
|
||||
}
|
||||
fieldPathMatches := fieldPathLabelRegex.FindStringSubmatch(fieldPath)
|
||||
if len(fieldPathMatches) == 2 { // 1 for entire regex and 1 for subexp
|
||||
labelValue := opts.Labels[fieldPathMatches[1]] // not existent label is OK
|
||||
return &labelValue, nil
|
||||
}
|
||||
fieldPathMatches = fieldPathAnnotationRegex.FindStringSubmatch(fieldPath)
|
||||
if len(fieldPathMatches) == 2 { // 1 for entire regex and 1 for subexp
|
||||
annotationValue := opts.Annotations[fieldPathMatches[1]] // not existent annotation is OK
|
||||
return &annotationValue, nil
|
||||
}
|
||||
|
||||
return nil, errors.Errorf(
|
||||
"Can not set env %v. Reason: fieldPath %v is either not valid or not supported",
|
||||
env.Name, fieldPath,
|
||||
)
|
||||
}
|
||||
|
||||
// getPodPorts converts a slice of kube container descriptions to an
|
||||
|
|
|
@ -189,13 +189,15 @@ func TestEnvVarValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(d)
|
||||
secretsManager := createSecrets(t, d)
|
||||
value := "foo"
|
||||
emptyValue := ""
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
envVar v1.EnvVar
|
||||
options CtrSpecGenOptions
|
||||
succeed bool
|
||||
expected string
|
||||
expected *string
|
||||
}{
|
||||
{
|
||||
"ConfigMapExists",
|
||||
|
@ -214,7 +216,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: configMapList,
|
||||
},
|
||||
true,
|
||||
"foo",
|
||||
&value,
|
||||
},
|
||||
{
|
||||
"ContainerKeyDoesNotExistInConfigMap",
|
||||
|
@ -233,7 +235,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: configMapList,
|
||||
},
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"OptionalContainerKeyDoesNotExistInConfigMap",
|
||||
|
@ -253,7 +255,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: configMapList,
|
||||
},
|
||||
true,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"ConfigMapDoesNotExist",
|
||||
|
@ -272,7 +274,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: configMapList,
|
||||
},
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"OptionalConfigMapDoesNotExist",
|
||||
|
@ -292,7 +294,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: configMapList,
|
||||
},
|
||||
true,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"EmptyConfigMapList",
|
||||
|
@ -311,7 +313,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: []v1.ConfigMap{},
|
||||
},
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"OptionalEmptyConfigMapList",
|
||||
|
@ -331,7 +333,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
ConfigMaps: []v1.ConfigMap{},
|
||||
},
|
||||
true,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"SecretExists",
|
||||
|
@ -350,7 +352,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
SecretsManager: secretsManager,
|
||||
},
|
||||
true,
|
||||
"foo",
|
||||
&value,
|
||||
},
|
||||
{
|
||||
"ContainerKeyDoesNotExistInSecret",
|
||||
|
@ -369,7 +371,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
SecretsManager: secretsManager,
|
||||
},
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"OptionalContainerKeyDoesNotExistInSecret",
|
||||
|
@ -389,7 +391,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
SecretsManager: secretsManager,
|
||||
},
|
||||
true,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"SecretDoesNotExist",
|
||||
|
@ -408,7 +410,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||
SecretsManager: secretsManager,
|
||||
},
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"OptionalSecretDoesNotExist",
|
||||
|
@ -428,7 +430,173 @@ func TestEnvVarValue(t *testing.T) {
|
|||
SecretsManager: secretsManager,
|
||||
},
|
||||
true,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataName",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.name",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
PodName: value,
|
||||
},
|
||||
true,
|
||||
&value,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataUID",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.uid",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
PodID: value,
|
||||
},
|
||||
true,
|
||||
&value,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataLabelsExist",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.labels['label']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Labels: map[string]string{"label": value},
|
||||
},
|
||||
true,
|
||||
&value,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataLabelsEmpty",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.labels['label']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Labels: map[string]string{"label": ""},
|
||||
},
|
||||
true,
|
||||
&emptyValue,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataLabelsNotExist",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.labels['label']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{},
|
||||
true,
|
||||
&emptyValue,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataAnnotationsExist",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.annotations['annotation']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Annotations: map[string]string{"annotation": value},
|
||||
},
|
||||
true,
|
||||
&value,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataAnnotationsEmpty",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.annotations['annotation']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Annotations: map[string]string{"annotation": ""},
|
||||
},
|
||||
true,
|
||||
&emptyValue,
|
||||
},
|
||||
{
|
||||
"FieldRefMetadataAnnotationsNotExist",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.annotations['annotation']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{},
|
||||
true,
|
||||
&emptyValue,
|
||||
},
|
||||
{
|
||||
"FieldRefInvalid1",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.annotations['annotation]",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{},
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"FieldRefInvalid2",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.dummy['annotation']",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{},
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"FieldRefNotSupported",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "metadata.namespace",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{},
|
||||
false,
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -2984,7 +2984,7 @@ invalid kube kind
|
|||
inspect = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
Expect(inspect.OutputToString()).To(ContainSubstring(`map[]`))
|
||||
Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue))
|
||||
})
|
||||
|
||||
It("podman play kube teardown", func() {
|
||||
|
|
Loading…
Reference in a new issue