Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for envFrom on container definitions #82

Merged
merged 6 commits into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion kubernetes/resource_kubernetes_pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ func TestAccKubernetesPod_basic(t *testing.T) {
resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.uid"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.0.value_from.0.secret_key_ref.0.name", secretName),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.1.value_from.0.config_map_key_ref.0.name", configMapName),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.#", "2"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.config_map_ref.#", "1"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.config_map_ref.0.name", fmt.Sprintf("%s-from", configMapName)),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.config_map_ref.0.optional", "true"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.prefix", "FROM_CM_"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.secret_ref.#", "1"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.secret_ref.0.name", fmt.Sprintf("%s-from", secretName)),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.secret_ref.0.optional", "false"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.prefix", "FROM_S_"),
resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName1),
),
},
Expand Down Expand Up @@ -654,6 +663,17 @@ resource "kubernetes_secret" "test" {
}
}

resource "kubernetes_secret" "test_from" {
metadata {
name = "%s-from"
}

data {
one = "first_from"
second = "second_from"
}
}

resource "kubernetes_config_map" "test" {
metadata {
name = "%s"
Expand All @@ -664,6 +684,17 @@ resource "kubernetes_config_map" "test" {
}
}

resource "kubernetes_config_map" "test_from" {
metadata {
name = "%s-from"
}

data {
one = "ONE_FROM"
two = "TWO_FROM"
}
}

resource "kubernetes_pod" "test" {
metadata {
labels {
Expand Down Expand Up @@ -699,6 +730,21 @@ resource "kubernetes_pod" "test" {
}
},
]

env_from = [{
config_map_ref {
name = "${kubernetes_config_map.test_from.metadata.0.name}"
optional = true
}
prefix = "FROM_CM_"
}, {
secret_ref {
name = "${kubernetes_secret.test_from.metadata.0.name}"
optional = false
}
prefix = "FROM_S_"
}]

}
volume {
name = "db"
Expand All @@ -708,7 +754,7 @@ resource "kubernetes_pod" "test" {
}
}
}
`, secretName, configMapName, podName, imageName)
`, secretName, secretName, configMapName, configMapName, podName, imageName)
}

func testAccKubernetesPodConfigWithInitContainer(podName string, image string) string {
Expand Down
55 changes: 55 additions & 0 deletions kubernetes/schema_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,61 @@ func containerFields(isUpdatable, isInitContainer bool) map[string]*schema.Schem
},
},
},
"env_from": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
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.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"config_map_ref": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Description: "The ConfigMap to select from",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
},
"optional": {
Type: schema.TypeBool,
Optional: true,
Description: "Specify whether the ConfigMap must be defined",
},
},
},
},
"prefix": {
Type: schema.TypeString,
Optional: true,
Description: "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.",
},
"secret_ref": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Description: "The Secret to select from",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
},
"optional": {
Type: schema.TypeBool,
Optional: true,
Description: "Specify whether the Secret must be defined",
},
},
},
},
},
},
},
"image": {
Type: schema.TypeString,
Optional: true,
Expand Down
116 changes: 116 additions & 0 deletions kubernetes/structures_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ func flattenProbe(in *v1.Probe) []interface{} {
return []interface{}{att}
}

func flattenConfigMapRef(in *v1.ConfigMapEnvSource) []interface{} {
att := make(map[string]interface{})

if in.Name != "" {
att["name"] = in.Name
}
if in.Optional != nil {
att["optional"] = *in.Optional
}
return []interface{}{att}
}

func flattenConfigMapKeyRef(in *v1.ConfigMapKeySelector) []interface{} {
att := make(map[string]interface{})

Expand Down Expand Up @@ -205,6 +217,18 @@ func flattenResourceFieldSelector(in *v1.ResourceFieldSelector) []interface{} {
return []interface{}{att}
}

func flattenSecretRef(in *v1.SecretEnvSource) []interface{} {
att := make(map[string]interface{})

if in.Name != "" {
att["name"] = in.Name
}
if in.Optional != nil {
att["optional"] = *in.Optional
}
return []interface{}{att}
}

func flattenSecretKeyRef(in *v1.SecretKeySelector) []interface{} {
att := make(map[string]interface{})

Expand Down Expand Up @@ -276,6 +300,25 @@ func flattenContainerEnvs(in []v1.EnvVar) []interface{} {
return att
}

func flattenContainerEnvFroms(in []v1.EnvFromSource) []interface{} {
att := make([]interface{}, len(in))
for i, v := range in {
m := map[string]interface{}{}
if v.ConfigMapRef != nil {
m["config_map_ref"] = flattenConfigMapRef(v.ConfigMapRef)
}
if v.Prefix != "" {
m["prefix"] = v.Prefix
}
if v.SecretRef != nil {
m["secret_ref"] = flattenSecretRef(v.SecretRef)
}

att[i] = m
}
return att
}

func flattenContainerPorts(in []v1.ContainerPort) []interface{} {
att := make([]interface{}, len(in))
for i, v := range in {
Expand Down Expand Up @@ -351,6 +394,9 @@ func flattenContainers(in []v1.Container) ([]interface{}, error) {
if len(v.Env) > 0 {
c["env"] = flattenContainerEnvs(v.Env)
}
if len(v.EnvFrom) > 0 {
c["env_from"] = flattenContainerEnvFroms(v.EnvFrom)
}

if len(v.VolumeMounts) > 0 {
volumeMounts, err := flattenContainerVolumeMounts(v.VolumeMounts)
Expand Down Expand Up @@ -408,6 +454,13 @@ func expandContainers(ctrs []interface{}) ([]v1.Container, error) {
return cs, err
}
}
if v, ok := ctr["env_from"].([]interface{}); ok && len(v) > 0 {
var err error
cs[i].EnvFrom, err = expandContainerEnvFrom(v)
if err != nil {
return cs, err
}
}

if policy, ok := ctr["image_pull_policy"]; ok {
cs[i].ImagePullPolicy = v1.PullPolicy(policy.(string))
Expand Down Expand Up @@ -682,6 +735,34 @@ func expandContainerEnv(in []interface{}) ([]v1.EnvVar, error) {
return envs, nil
}

func expandContainerEnvFrom(in []interface{}) ([]v1.EnvFromSource, error) {
if len(in) == 0 {
return []v1.EnvFromSource{}, nil
}
envFroms := make([]v1.EnvFromSource, len(in))
for i, c := range in {
p := c.(map[string]interface{})
if v, ok := p["config_map_ref"].([]interface{}); ok && len(v) > 0 {
var err error
envFroms[i].ConfigMapRef, err = expandConfigMapRef(v)
if err != nil {
return envFroms, err
}
}
if value, ok := p["prefix"]; ok {
envFroms[i].Prefix = value.(string)
}
if v, ok := p["secret_ref"].([]interface{}); ok && len(v) > 0 {
var err error
envFroms[i].SecretRef, err = expandSecretRef(v)
if err != nil {
return envFroms, err
}
}
}
return envFroms, nil
}

func expandContainerPort(in []interface{}) ([]v1.ContainerPort, error) {
if len(in) == 0 {
return []v1.ContainerPort{}, nil
Expand Down Expand Up @@ -754,6 +835,24 @@ func expandResourceFieldRef(r []interface{}) (*v1.ResourceFieldSelector, error)
}
return obj, nil
}

func expandSecretRef(r []interface{}) (*v1.SecretEnvSource, error) {
if len(r) == 0 || r[0] == nil {
return &v1.SecretEnvSource{}, nil
}
in := r[0].(map[string]interface{})
obj := &v1.SecretEnvSource{}

if v, ok := in["name"].(string); ok {
obj.Name = v
}
if v, ok := in["optional"]; ok {
obj.Optional = ptrToBool(v.(bool))
}

return obj, nil
}

func expandSecretKeyRef(r []interface{}) (*v1.SecretKeySelector, error) {
if len(r) == 0 || r[0] == nil {
return &v1.SecretKeySelector{}, nil
Expand Down Expand Up @@ -806,6 +905,23 @@ func expandEnvValueFrom(r []interface{}) (*v1.EnvVarSource, error) {

}

func expandConfigMapRef(r []interface{}) (*v1.ConfigMapEnvSource, error) {
if len(r) == 0 || r[0] == nil {
return &v1.ConfigMapEnvSource{}, nil
}
in := r[0].(map[string]interface{})
obj := &v1.ConfigMapEnvSource{}

if v, ok := in["name"].(string); ok {
obj.Name = v
}
if v, ok := in["optional"]; ok {
obj.Optional = ptrToBool(v.(bool))
}

return obj, nil
}

func expandContainerResourceRequirements(l []interface{}) (v1.ResourceRequirements, error) {
if len(l) == 0 || l[0] == nil {
return v1.ResourceRequirements{}, nil
Expand Down
23 changes: 23 additions & 0 deletions website/docs/r/pod.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ The following arguments are supported:
* `args` - (Optional) Arguments to the entrypoint. The docker 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. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers#containers-and-commands
* `command` - (Optional) Entrypoint array. Not executed within a shell. The docker image's ENTRYPOINT 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. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers#containers-and-commands
* `env` - (Optional) List of environment variables to set in the container. Cannot be updated.
* `env_from` - (Optional) 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.
* `image` - (Optional) Docker image name. More info: http://kubernetes.io/docs/user-guide/images
* `image_pull_policy` - (Optional) Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/images#updating-images
* `lifecycle` - (Optional) Actions that the management system should take in response to container lifecycle events
Expand Down Expand Up @@ -169,6 +170,13 @@ The following arguments are supported:
* `items` - (Optional) If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.
* `name` - (Optional) Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names

### `config_map_ref`

#### Arguments

* `name` - (Required) Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names
* `optional` - (Optional) Specify whether the ConfigMap must be defined

### `config_map_key_ref`

#### Arguments
Expand Down Expand Up @@ -197,6 +205,14 @@ The following arguments are supported:
* `value` - (Optional) Variable references $(VAR_NAME) are expanded using the previous 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. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".
* `value_from` - (Optional) Source for the environment variable's value

### `env_from`

#### Arguments

* `config_map_ref` - (Optional) The ConfigMap to select from
* `prefix` - (Optional) An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER..
* `secret_ref` - (Optional) The Secret to select from

### `exec`

#### Arguments
Expand Down Expand Up @@ -465,6 +481,13 @@ The `items` block supports the following:
* `mode` - (Optional) Mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used.
* `path` - (Required) The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'.

### `secret_ref`

#### Arguments

* `name` - (Required) Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names
* `optional` - (Optional) Specify whether the Secret must be defined

### `secret_key_ref`

#### Arguments
Expand Down
Loading