summaryrefslogtreecommitdiff
path: root/pkg/specgen
diff options
context:
space:
mode:
authorAlban Bedel <albeu@free.fr>2021-03-26 10:54:26 +0100
committerAlban Bedel <albeu@free.fr>2021-03-28 15:02:31 +0200
commite5ff694855820e8bf5b7f17680c3dc6586241bdd (patch)
tree5c57744226efd8b4dc3610c25f5e14c1f3f49fe1 /pkg/specgen
parent9f92b8b0d8ac34c02100579a5acf6c127392aff5 (diff)
downloadpodman-e5ff694855820e8bf5b7f17680c3dc6586241bdd.tar.gz
podman-e5ff694855820e8bf5b7f17680c3dc6586241bdd.tar.bz2
podman-e5ff694855820e8bf5b7f17680c3dc6586241bdd.zip
play kube: support optional/mandatory env var from config map
In K8S the pod creation fails if an env var reference a non existing config map key. It can be marked as optional, but per default it is mandatory. Podman on the other hand always treat such references as optional. Rework envVarsFrom() and envVarValue() to additionaly return an error and add support for the optional attribute in configMapRef and configMapKeyRef. Signed-off-by: Alban Bedel <albeu@free.fr>
Diffstat (limited to 'pkg/specgen')
-rw-r--r--pkg/specgen/generate/kube/kube.go43
-rw-r--r--pkg/specgen/generate/kube/play_test.go109
2 files changed, 139 insertions, 13 deletions
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index 6adbef2dc..f31f5e711 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -210,12 +210,18 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
}
for _, env := range opts.Container.Env {
- value := envVarValue(env, opts)
+ value, err := envVarValue(env, opts)
+ if err != nil {
+ return nil, err
+ }
envs[env.Name] = value
}
for _, envFrom := range opts.Container.EnvFrom {
- cmEnvs := envVarsFrom(envFrom, opts)
+ cmEnvs, err := envVarsFrom(envFrom, opts)
+ if err != nil {
+ return nil, err
+ }
for k, v := range cmEnvs {
envs[k] = v
@@ -326,39 +332,54 @@ func quantityToInt64(quantity *resource.Quantity) (int64, error) {
}
// envVarsFrom returns all key-value pairs as env vars from a configMap that matches the envFrom setting of a container
-func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) map[string]string {
+func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) (map[string]string, error) {
envs := map[string]string{}
if envFrom.ConfigMapRef != nil {
- cmName := envFrom.ConfigMapRef.Name
+ cmRef := envFrom.ConfigMapRef
+ err := errors.Errorf("Configmap %v not found", cmRef.Name)
for _, c := range opts.ConfigMaps {
- if cmName == c.Name {
+ if cmRef.Name == c.Name {
envs = c.Data
+ err = nil
break
}
}
+
+ if err != nil && (cmRef.Optional == nil || !*cmRef.Optional) {
+ return nil, err
+ }
}
- return envs
+ return envs, nil
}
// envVarValue returns the environment variable value configured within the container's env setting.
// It gets the value from a configMap if specified, otherwise returns env.Value
-func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) string {
+func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) {
if env.ValueFrom != nil {
if env.ValueFrom.ConfigMapKeyRef != nil {
+ cmKeyRef := env.ValueFrom.ConfigMapKeyRef
+ err := errors.Errorf("Cannot set env %v: configmap %v not found", env.Name, cmKeyRef.Name)
+
for _, c := range opts.ConfigMaps {
- if env.ValueFrom.ConfigMapKeyRef.Name == c.Name {
- if value, ok := c.Data[env.ValueFrom.ConfigMapKeyRef.Key]; ok {
- return value
+ if cmKeyRef.Name == c.Name {
+ if value, ok := c.Data[cmKeyRef.Key]; ok {
+ 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
}
}
- return env.Value
+ return env.Value, nil
}
// getPodPorts converts a slice of kube container descriptions to an
diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go
index 35975a70b..c38b3e40b 100644
--- a/pkg/specgen/generate/kube/play_test.go
+++ b/pkg/specgen/generate/kube/play_test.go
@@ -13,6 +13,7 @@ func TestEnvVarsFrom(t *testing.T) {
name string
envFrom v1.EnvFromSource
options CtrSpecGenOptions
+ succeed bool
expected map[string]string
}{
{
@@ -27,6 +28,7 @@ func TestEnvVarsFrom(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: configMapList,
},
+ true,
map[string]string{
"myvar": "foo",
},
@@ -43,6 +45,23 @@ func TestEnvVarsFrom(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: configMapList,
},
+ false,
+ nil,
+ },
+ {
+ "OptionalConfigMapDoesNotExist",
+ v1.EnvFromSource{
+ ConfigMapRef: &v1.ConfigMapEnvSource{
+ LocalObjectReference: v1.LocalObjectReference{
+ Name: "doesnotexist",
+ },
+ Optional: &optional,
+ },
+ },
+ CtrSpecGenOptions{
+ ConfigMaps: configMapList,
+ },
+ true,
map[string]string{},
},
{
@@ -57,6 +76,23 @@ func TestEnvVarsFrom(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: []v1.ConfigMap{},
},
+ false,
+ nil,
+ },
+ {
+ "OptionalEmptyConfigMapList",
+ v1.EnvFromSource{
+ ConfigMapRef: &v1.ConfigMapEnvSource{
+ LocalObjectReference: v1.LocalObjectReference{
+ Name: "foo",
+ },
+ Optional: &optional,
+ },
+ },
+ CtrSpecGenOptions{
+ ConfigMaps: []v1.ConfigMap{},
+ },
+ true,
map[string]string{},
},
}
@@ -64,7 +100,8 @@ func TestEnvVarsFrom(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
- result := envVarsFrom(test.envFrom, &test.options)
+ result, err := envVarsFrom(test.envFrom, &test.options)
+ assert.Equal(t, err == nil, test.succeed)
assert.Equal(t, test.expected, result)
})
}
@@ -75,6 +112,7 @@ func TestEnvVarValue(t *testing.T) {
name string
envVar v1.EnvVar
options CtrSpecGenOptions
+ succeed bool
expected string
}{
{
@@ -93,6 +131,7 @@ func TestEnvVarValue(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: configMapList,
},
+ true,
"foo",
},
{
@@ -111,6 +150,27 @@ func TestEnvVarValue(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: configMapList,
},
+ false,
+ "",
+ },
+ {
+ "OptionalContainerKeyDoesNotExistInConfigMap",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ConfigMapKeyRef: &v1.ConfigMapKeySelector{
+ LocalObjectReference: v1.LocalObjectReference{
+ Name: "foo",
+ },
+ Key: "doesnotexist",
+ Optional: &optional,
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ ConfigMaps: configMapList,
+ },
+ true,
"",
},
{
@@ -129,6 +189,27 @@ func TestEnvVarValue(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: configMapList,
},
+ false,
+ "",
+ },
+ {
+ "OptionalConfigMapDoesNotExist",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ConfigMapKeyRef: &v1.ConfigMapKeySelector{
+ LocalObjectReference: v1.LocalObjectReference{
+ Name: "doesnotexist",
+ },
+ Key: "myvar",
+ Optional: &optional,
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ ConfigMaps: configMapList,
+ },
+ true,
"",
},
{
@@ -147,6 +228,27 @@ func TestEnvVarValue(t *testing.T) {
CtrSpecGenOptions{
ConfigMaps: []v1.ConfigMap{},
},
+ false,
+ "",
+ },
+ {
+ "OptionalEmptyConfigMapList",
+ v1.EnvVar{
+ Name: "FOO",
+ ValueFrom: &v1.EnvVarSource{
+ ConfigMapKeyRef: &v1.ConfigMapKeySelector{
+ LocalObjectReference: v1.LocalObjectReference{
+ Name: "foo",
+ },
+ Key: "myvar",
+ Optional: &optional,
+ },
+ },
+ },
+ CtrSpecGenOptions{
+ ConfigMaps: []v1.ConfigMap{},
+ },
+ true,
"",
},
}
@@ -154,7 +256,8 @@ func TestEnvVarValue(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
- result := envVarValue(test.envVar, &test.options)
+ result, err := envVarValue(test.envVar, &test.options)
+ assert.Equal(t, err == nil, test.succeed)
assert.Equal(t, test.expected, result)
})
}
@@ -184,3 +287,5 @@ var configMapList = []v1.ConfigMap{
},
},
}
+
+var optional = true