Skip to content

Commit 5de2ce8

Browse files
BBBmaujrhouston
andauthored
Add support for initContainers in kubernetes_env resource (#2067)
Co-authored-by: John Houston <[email protected]>
1 parent 927c705 commit 5de2ce8

File tree

5 files changed

+574
-30
lines changed

5 files changed

+574
-30
lines changed

.changelog/2067.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
`kubernetes/resource_kubernetes_env.go`: add support for initContainers
3+
```

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ require (
141141
k8s.io/component-base v0.25.5 // indirect
142142
k8s.io/klog/v2 v2.80.1 // indirect
143143
k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715 // indirect
144-
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
144+
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448
145145
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
146146
sigs.k8s.io/kustomize/api v0.12.1 // indirect
147147
sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect

kubernetes/resource_kubernetes_env.go

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,18 @@ func resourceKubernetesEnv() *schema.Resource {
5656
},
5757
},
5858
"container": {
59-
Type: schema.TypeString,
60-
Description: "Name of the container for which we are updating the environment variables.",
61-
Required: true,
59+
Type: schema.TypeString,
60+
Description: "Name of the container for which we are updating the environment variables.",
61+
Optional: true,
62+
ValidateFunc: validation.StringIsNotWhiteSpace,
63+
ExactlyOneOf: []string{"container", "init_container"},
64+
},
65+
"init_container": {
66+
Type: schema.TypeString,
67+
Description: "Name of the initContainer for which we are updating the environment variables.",
68+
Optional: true,
69+
ValidateFunc: validation.StringIsNotWhiteSpace,
70+
ExactlyOneOf: []string{"container", "init_container"},
6271
},
6372
"api_version": {
6473
Type: schema.TypeString,
@@ -281,13 +290,21 @@ func resourceKubernetesEnvRead(ctx context.Context, d *schema.ResourceData, m in
281290
configuredEnvs[e.(map[string]interface{})["name"].(string)] = ""
282291
}
283292

293+
var container string
294+
if c := d.Get("container").(string); c != "" {
295+
container = c
296+
} else {
297+
container = d.Get("init_container").(string)
298+
}
299+
284300
// strip out envs not managed by Terraform
285301
fieldManagerName := d.Get("field_manager").(string)
286302
managedEnvs, err := getManagedEnvs(res.GetManagedFields(), fieldManagerName, d, res)
287303
if err != nil {
288304
return diag.FromErr(err)
289305
}
290-
responseEnvs, err := getResponseEnvs(res, d.Get("container").(string), d.Get("kind").(string))
306+
307+
responseEnvs, err := getResponseEnvs(res, container, d.Get("kind").(string))
291308
if err != nil {
292309
return diag.FromErr(err)
293310
}
@@ -310,13 +327,20 @@ func resourceKubernetesEnvRead(ctx context.Context, d *schema.ResourceData, m in
310327

311328
func getResponseEnvs(u *unstructured.Unstructured, containerName string, kind string) ([]interface{}, error) {
312329
var containers []interface{}
330+
var initContainers []interface{}
313331

314-
containers, _, _ = unstructured.NestedSlice(u.Object, "spec", "template", "spec", "containers")
332+
initContainers, _, _ = unstructured.NestedSlice(u.Object, "spec", "template", "spec", "initContainers")
333+
if kind == "CronJob" {
334+
initContainers, _, _ = unstructured.NestedSlice(u.Object, "spec", "jobTemplate", "spec", "template", "spec", "initContainers")
335+
}
315336

337+
containers, _, _ = unstructured.NestedSlice(u.Object, "spec", "template", "spec", "containers")
316338
if kind == "CronJob" {
317339
containers, _, _ = unstructured.NestedSlice(u.Object, "spec", "jobTemplate", "spec", "template", "spec", "containers")
318340
}
319341

342+
containers = append(containers, initContainers...)
343+
320344
for _, c := range containers {
321345
container := c.(map[string]interface{})
322346
if container["name"].(string) == containerName {
@@ -341,16 +365,22 @@ func getManagedEnvs(managedFields []v1.ManagedFieldsEntry, manager string, d *sc
341365
}
342366

343367
spec, _, err := unstructured.NestedMap(u.Object, "f:spec", "f:template", "f:spec")
344-
if "CronJob" == kind {
368+
if kind == "CronJob" {
345369
spec, _, err = unstructured.NestedMap(u.Object, "f:spec", "f:jobTemplate", "f:spec", "f:template", "f:spec")
346370
}
347371
if err == nil {
348372
return nil, err
349373
}
350374

351-
containers := spec["f:containers"].(map[string]interface{})
352-
containerName := fmt.Sprintf(`k:{"name":%q}`, d.Get("container").(string))
353-
k := containers[containerName].(map[string]interface{})
375+
fieldManagerKey := "f:containers"
376+
containerName := d.Get("container").(string)
377+
if v := d.Get("init_container").(string); v != "" {
378+
containerName = v
379+
fieldManagerKey = "f:initContainers"
380+
}
381+
containers := spec[fieldManagerKey].(map[string]interface{})
382+
containerKey := fmt.Sprintf(`k:{"name":%q}`, containerName)
383+
k := containers[containerKey].(map[string]interface{})
354384
if e, ok := k["f:env"].(map[string]interface{}); ok {
355385
envs = e
356386
}
@@ -425,46 +455,51 @@ func resourceKubernetesEnvUpdate(ctx context.Context, d *schema.ResourceData, m
425455
env = []map[string]interface{}{}
426456
}
427457

458+
containersField := "containers"
459+
containerName := d.Get("container")
460+
if v := d.Get("init_container").(string); v != "" {
461+
containersField = "initContainers"
462+
containerName = v
463+
}
464+
465+
containerSpec := map[string]interface{}{
466+
"name": containerName,
467+
"env": env,
468+
}
469+
428470
spec := map[string]interface{}{
429471
"template": map[string]interface{}{
430472
"spec": map[string]interface{}{
431-
"containers": []interface{}{
432-
map[string]interface{}{
433-
"name": d.Get("container").(string),
434-
"env": env,
435-
},
473+
containersField: []interface{}{
474+
containerSpec,
436475
},
437476
},
438477
},
439478
}
479+
440480
if kind == "CronJob" {
441-
// patch for CronJob
481+
// CronJob nests under an additional jobTemplate field
442482
spec = map[string]interface{}{
443483
"jobTemplate": map[string]interface{}{
444484
"spec": map[string]interface{}{
445485
"template": map[string]interface{}{
446486
"spec": map[string]interface{}{
447-
"containers": []interface{}{
448-
map[string]interface{}{
449-
"name": d.Get("container").(string),
450-
"env": env,
451-
},
487+
containersField: []interface{}{
488+
containerSpec,
452489
},
453490
},
454491
},
455492
},
456493
},
457494
}
458495
}
496+
459497
patchObj := map[string]interface{}{
460498
"apiVersion": apiVersion,
461499
"kind": kind,
462500
"metadata": patchmeta,
463501
"spec": spec,
464502
}
465-
466-
// structure for a Deployment kind
467-
468503
patch := unstructured.Unstructured{}
469504
patch.Object = patchObj
470505
patchbytes, err := patch.MarshalJSON()

0 commit comments

Comments
 (0)