mirror of
https://github.com/containers/podman.git
synced 2025-06-20 00:51:16 +08: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:
@ -365,6 +365,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
specgenOpts := kube.CtrSpecGenOptions{
|
specgenOpts := kube.CtrSpecGenOptions{
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
Container: initCtr,
|
Container: initCtr,
|
||||||
@ -405,7 +410,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
specgenOpts := kube.CtrSpecGenOptions{
|
specgenOpts := kube.CtrSpecGenOptions{
|
||||||
|
Annotations: annotations,
|
||||||
Container: container,
|
Container: container,
|
||||||
Image: pulledImage,
|
Image: pulledImage,
|
||||||
Volumes: volumes,
|
Volumes: volumes,
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -291,9 +292,9 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only set the env if the value is not ""
|
// Only set the env if the value is not nil
|
||||||
if value != "" {
|
if value != nil {
|
||||||
envs[env.Name] = value
|
envs[env.Name] = *value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, envFrom := range opts.Container.EnvFrom {
|
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.
|
// 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
|
// 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 != nil {
|
||||||
if env.ValueFrom.ConfigMapKeyRef != nil {
|
if env.ValueFrom.ConfigMapKeyRef != nil {
|
||||||
cmKeyRef := env.ValueFrom.ConfigMapKeyRef
|
cmKeyRef := env.ValueFrom.ConfigMapKeyRef
|
||||||
@ -618,16 +619,16 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
|
|||||||
for _, c := range opts.ConfigMaps {
|
for _, c := range opts.ConfigMaps {
|
||||||
if cmKeyRef.Name == c.Name {
|
if cmKeyRef.Name == c.Name {
|
||||||
if value, ok := c.Data[cmKeyRef.Key]; ok {
|
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)
|
err = errors.Errorf("Cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cmKeyRef.Optional == nil || !*cmKeyRef.Optional {
|
if cmKeyRef.Optional == nil || !*cmKeyRef.Optional {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return "", nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if env.ValueFrom.SecretKeyRef != 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)
|
secret, err := k8sSecretFromSecretManager(secKeyRef.Name, opts.SecretsManager)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if val, ok := secret[secKeyRef.Key]; ok {
|
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)
|
err = errors.Errorf("Secret %v has not %v key", secKeyRef.Name, secKeyRef.Key)
|
||||||
}
|
}
|
||||||
if secKeyRef.Optional == nil || !*secKeyRef.Optional {
|
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
|
// getPodPorts converts a slice of kube container descriptions to an
|
||||||
|
@ -189,13 +189,15 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.RemoveAll(d)
|
defer os.RemoveAll(d)
|
||||||
secretsManager := createSecrets(t, d)
|
secretsManager := createSecrets(t, d)
|
||||||
|
value := "foo"
|
||||||
|
emptyValue := ""
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
envVar v1.EnvVar
|
envVar v1.EnvVar
|
||||||
options CtrSpecGenOptions
|
options CtrSpecGenOptions
|
||||||
succeed bool
|
succeed bool
|
||||||
expected string
|
expected *string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"ConfigMapExists",
|
"ConfigMapExists",
|
||||||
@ -214,7 +216,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: configMapList,
|
ConfigMaps: configMapList,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
"foo",
|
&value,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ContainerKeyDoesNotExistInConfigMap",
|
"ContainerKeyDoesNotExistInConfigMap",
|
||||||
@ -233,7 +235,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: configMapList,
|
ConfigMaps: configMapList,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OptionalContainerKeyDoesNotExistInConfigMap",
|
"OptionalContainerKeyDoesNotExistInConfigMap",
|
||||||
@ -253,7 +255,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: configMapList,
|
ConfigMaps: configMapList,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ConfigMapDoesNotExist",
|
"ConfigMapDoesNotExist",
|
||||||
@ -272,7 +274,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: configMapList,
|
ConfigMaps: configMapList,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OptionalConfigMapDoesNotExist",
|
"OptionalConfigMapDoesNotExist",
|
||||||
@ -292,7 +294,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: configMapList,
|
ConfigMaps: configMapList,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"EmptyConfigMapList",
|
"EmptyConfigMapList",
|
||||||
@ -311,7 +313,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: []v1.ConfigMap{},
|
ConfigMaps: []v1.ConfigMap{},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OptionalEmptyConfigMapList",
|
"OptionalEmptyConfigMapList",
|
||||||
@ -331,7 +333,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
ConfigMaps: []v1.ConfigMap{},
|
ConfigMaps: []v1.ConfigMap{},
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SecretExists",
|
"SecretExists",
|
||||||
@ -350,7 +352,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
SecretsManager: secretsManager,
|
SecretsManager: secretsManager,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
"foo",
|
&value,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ContainerKeyDoesNotExistInSecret",
|
"ContainerKeyDoesNotExistInSecret",
|
||||||
@ -369,7 +371,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
SecretsManager: secretsManager,
|
SecretsManager: secretsManager,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OptionalContainerKeyDoesNotExistInSecret",
|
"OptionalContainerKeyDoesNotExistInSecret",
|
||||||
@ -389,7 +391,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
SecretsManager: secretsManager,
|
SecretsManager: secretsManager,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"SecretDoesNotExist",
|
"SecretDoesNotExist",
|
||||||
@ -408,7 +410,7 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
SecretsManager: secretsManager,
|
SecretsManager: secretsManager,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
"",
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OptionalSecretDoesNotExist",
|
"OptionalSecretDoesNotExist",
|
||||||
@ -428,7 +430,173 @@ func TestEnvVarValue(t *testing.T) {
|
|||||||
SecretsManager: secretsManager,
|
SecretsManager: secretsManager,
|
||||||
},
|
},
|
||||||
true,
|
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 = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"})
|
||||||
inspect.WaitWithDefaultTimeout()
|
inspect.WaitWithDefaultTimeout()
|
||||||
Expect(inspect).Should(Exit(0))
|
Expect(inspect).Should(Exit(0))
|
||||||
Expect(inspect.OutputToString()).To(ContainSubstring(`map[]`))
|
Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman play kube teardown", func() {
|
It("podman play kube teardown", func() {
|
||||||
|
Reference in New Issue
Block a user