Skip to content

Commit

Permalink
[Backport] codegen: allow extra passthrough env vars (#449)
Browse files Browse the repository at this point in the history
  • Loading branch information
shashankram authored May 17, 2023
1 parent 6d942c6 commit d9546f8
Show file tree
Hide file tree
Showing 19 changed files with 367 additions and 3 deletions.
6 changes: 6 additions & 0 deletions changelog/v0.29.7/extra-envs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
changelog:
- type: NEW_FEATURE
issueLink: https://github.com/solo-io/skv2/issues/447
description: >
"Allow setting passthrough env vars"
skipCI: false
81 changes: 78 additions & 3 deletions codegen/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1158,9 +1158,9 @@ var _ = Describe("Cmd", func() {
Enabled bool `json:"enabled"`
}
helmValues := map[string]*enabledThing{
"painter": &enabledThing{Enabled: true},
"test1": &enabledThing{Enabled: false},
"test2": &enabledThing{Enabled: false},
"painter": {Enabled: true},
"test1": {Enabled: false},
"test2": {Enabled: false},
}

renderedManifests := helmTemplate("codegen/test/chart", helmValues)
Expand Down Expand Up @@ -1418,6 +1418,81 @@ var _ = Describe("Cmd", func() {
Entry("camelCase sidecar name", "fooBar", "fooBar"),
Entry("hyphened sidecar name", "foo-bar", "fooBar"),
)

DescribeTable("rendering extra env vars",
func(extraEnvs map[string]interface{}, expectedEnvVars []v1.EnvVar) {
cmd := &Command{
Chart: &Chart{
Operators: []Operator{
{
Name: "painter",
Deployment: Deployment{
Container: Container{
Image: Image{
Tag: "v0.0.0",
Repository: "painter",
Registry: "quay.io/solo-io",
PullPolicy: "IfNotPresent",
},
},
},
},
},

Values: nil,
Data: Data{
ApiVersion: "v1",
Description: "",
Name: "Painting Operator",
Version: "v0.0.1",
Home: "https://docs.solo.io/skv2/latest",
Sources: []string{
"https://github.com/solo-io/skv2",
},
},
},

ManifestRoot: "codegen/test/chart-envvars",
}

err := cmd.Execute()
Expect(err).NotTo(HaveOccurred())

painterValues := map[string]interface{}{"extraEnvs": extraEnvs}
helmValues := map[string]interface{}{"painter": painterValues}

renderedManifests := helmTemplate("codegen/test/chart-envvars", helmValues)

var renderedDeployment *appsv1.Deployment
decoder := kubeyaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(renderedManifests), 4096)
for {
obj := &unstructured.Unstructured{}
err := decoder.Decode(obj)
if err != nil {
break
}
if obj.GetName() != "painter" || obj.GetKind() != "Deployment" {
continue
}

bytes, err := obj.MarshalJSON()
Expect(err).NotTo(HaveOccurred())
renderedDeployment = &appsv1.Deployment{}
err = json.Unmarshal(bytes, renderedDeployment)
Expect(err).NotTo(HaveOccurred())
}
Expect(renderedDeployment).NotTo(BeNil())
renderedEnvVars := renderedDeployment.Spec.Template.Spec.Containers[0].Env
Expect(renderedEnvVars).To(ConsistOf(expectedEnvVars))
},
Entry("no env vars",
nil, nil),
Entry("value env var",
map[string]interface{}{"FOO": map[string]interface{}{"value": "bar"}}, []v1.EnvVar{{Name: "FOO", Value: "bar"}}),
Entry("valueFrom env var",
map[string]interface{}{"FOO": map[string]interface{}{"valueFrom": map[string]interface{}{"secretKeyRef": map[string]interface{}{"name": "bar", "key": "baz"}}}},
[]v1.EnvVar{{Name: "FOO", ValueFrom: &v1.EnvVarSource{SecretKeyRef: &v1.SecretKeySelector{LocalObjectReference: v1.LocalObjectReference{Name: "bar"}, Key: "baz"}}}}),
)
})

func helmTemplate(path string, values interface{}) []byte {
Expand Down
1 change: 1 addition & 0 deletions codegen/model/values/helm_chart_values.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type UserValues struct {
type UserContainerValues struct {
Image Image `json:"image" desc:"Container image."`
Env []v1.EnvVar `json:"env" desc:"Environment variables for the container. For more info, see the [Kubernetes documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#envvarsource-v1-core)." omitChildren:"true"`
ExtraEnvs struct{} `json:"extraEnvs" desc:"Extra environment variables for the container"`
Resources *v1.ResourceRequirements `json:"resources,omitempty" desc:"Container resource requirements. For more info, see the [Kubernetes documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#resourcerequirements-v1-core)." omitChildren:"true"`
SecurityContext *v1.SecurityContext `json:"securityContext,omitempty" desc:"Container security context. Set to 'false' to omit the security context entirely. For more info, see the [Kubernetes documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#securitycontext-v1-core)." omitChildren:"true"`
}
Expand Down
6 changes: 6 additions & 0 deletions codegen/templates/chart/operator-deployment.yamltmpl
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ spec:
{{- if [[ $containerVar ]].env }}
env:
{{ toYaml [[ $containerVar ]].env | indent 10 }}
{{- else if [[ $containerVar ]].extraEnvs }}
env:
{{- end }}
{{- range $name, $item := [[ $containerVar ]].extraEnvs }}
- name: {{ $name }}
{{- $item | toYaml | nindent 12 }}
{{- end }}
[[- if $container.VolumeMounts ]]
volumeMounts:
Expand Down
8 changes: 8 additions & 0 deletions codegen/test/chart-envvars/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Code generated by skv2. DO NOT EDIT.

apiVersion: v1
home: https://docs.solo.io/skv2/latest
name: Painting Operator
sources:
- https://github.com/solo-io/skv2
version: v0.0.1
54 changes: 54 additions & 0 deletions codegen/test/chart-envvars/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Code generated by skv2. DO NOT EDIT.



{{/* Below are library functions provided by skv2 */}}

{{- /*
"skv2.utils.merge" takes an array of three values:
- the top context
- the yaml block that will be merged in (override)
- the name of the base template (source)
note: the source must be a named template (helm partial). This is necessary for the merging logic.
The behaviour is as follows, to align with already existing helm behaviour:
- If no source is found (template is empty), the merged output will be empty
- If no overrides are specified, the source is rendered as is
- If overrides are specified and source is not empty, overrides will be merged in to the source.
Overrides can replace / add to deeply nested dictionaries, but will completely replace lists.
Examples:
┌─────────────────────┬───────────────────────┬────────────────────────┐
│ Source (template) │ Overrides │ Result │
├─────────────────────┼───────────────────────┼────────────────────────┤
│ metadata: │ metadata: │ metadata: │
│ labels: │ labels: │ labels: │
│ app: gloo │ app: gloo1 │ app: gloo1 │
│ cluster: useast │ author: infra-team │ author: infra-team │
│ │ │ cluster: useast │
├─────────────────────┼───────────────────────┼────────────────────────┤
│ lists: │ lists: │ lists: │
│ groceries: │ groceries: │ groceries: │
│ - apple │ - grapes │ - grapes │
│ - banana │ │ │
└─────────────────────┴───────────────────────┴────────────────────────┘
skv2.utils.merge is a fork of a helm library chart function (https://github.com/helm/charts/blob/master/incubator/common/templates/_util.tpl).
This includes some optimizations to speed up chart rendering time, and merges in a value (overrides) with a named template, unlike the upstream
version, which merges two named templates.
*/ -}}
{{- define "skv2.utils.merge" -}}
{{- $top := first . -}}
{{- $overrides := (index . 1) -}}
{{- $tpl := fromYaml (include (index . 2) $top) -}}
{{- if or (empty $overrides) (empty $tpl) -}}
{{ include (index . 2) $top }} {{/* render source as is */}}
{{- else -}}
{{- $merged := merge $overrides $tpl -}}
{{- toYaml $merged -}} {{/* render source with overrides as YAML */}}
{{- end -}}
{{- end -}}
135 changes: 135 additions & 0 deletions codegen/test/chart-envvars/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Code generated by skv2. DO NOT EDIT.



{{- $painter := $.Values.painter}}
---

{{- define "painter.deploymentSpec"}}

# Deployment manifest for painter

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: painter
annotations:
app.kubernetes.io/name: painter
name: painter
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: painter
template:
metadata:
labels:
app: painter
annotations:
app.kubernetes.io/name: painter
prometheus.io/path: /metrics
prometheus.io/port: "9091"
prometheus.io/scrape: "true"
spec:
serviceAccountName: painter
containers:
{{- $painter := $.Values.painter }}
{{- $painterImage := $painter.image }}
- name: painter
image: {{ $painterImage.registry }}/{{ $painterImage.repository }}:{{ $painterImage.tag }}
imagePullPolicy: {{ $painterImage.pullPolicy }}
{{- if $painter.env }}
env:
{{ toYaml $painter.env | indent 10 }}
{{- else if $painter.extraEnvs }}
env:
{{- end }}
{{- range $name, $item := $painter.extraEnvs }}
- name: {{ $name }}
{{- $item | toYaml | nindent 12 }}
{{- end }}
resources:
{{- if $painter.resources }}
{{ toYaml $painter.resources | indent 10}}
{{- else}}
requests:
cpu: 500m
memory: 256Mi
{{- end}}
{{- /*
Render securityContext configs if it is set.
If securityContext is not set, render the default securityContext.
If securityContext is set to 'false', render an empty map.
*/}}
securityContext:
{{- if or ($painter.securityContext) (eq "map[]" (printf "%v" $painter.securityContext)) }}
{{ toYaml $painter.securityContext | indent 10}}
{{/* Because securityContext is nil by default we can only perform following conversion if it is a boolean. Skip conditional otherwise. */}}
{{- else if eq (ternary $painter.securityContext true (eq "bool" (printf "%T" $painter.securityContext))) false }}
{}
{{- else}}
runAsNonRoot: true
{{- if not $painter.floatingUserId }}
runAsUser: {{ printf "%.0f" (float64 $painter.runAsUser) }}
{{- end }}
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
{{- end}}
{{- if $painterImage.pullSecret }}
imagePullSecrets:
- name: {{ $painterImage.pullSecret }}
{{- end}}
{{- end }} {{/* define "painter.deploymentSpec" */}}

{{/* Render painter deployment template with overrides from values*/}}
{{- if $painter.enabled }}
{{- $painterDeploymentOverrides := dict }}
{{- if $painter.deploymentOverrides }}
{{- $painterDeploymentOverrides = $painter.deploymentOverrides }}
{{- end }}
---
{{ include "skv2.utils.merge" (list . $painterDeploymentOverrides "painter.deploymentSpec") }}
{{- end }}
---

{{- if $painter.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: painter
{{- if $painter.serviceAccount}}
{{- if $painter.serviceAccount.extraAnnotations }}
annotations:
{{- range $key, $value := $painter.serviceAccount.extraAnnotations }}
{{ $key }}: {{ $value }}
{{- end }}
{{- end }}
{{- end}}
name: painter
namespace: {{ $.Release.Namespace }}
{{- end }}


{{- define "painter.serviceSpec"}}

{{- end }} {{/* define "painter.serviceSpec" */}}

{{- if $painter.enabled }}
{{/* Render painter service template with overrides from values*/}}
{{- $painterServiceOverrides := dict }}
{{- if $painter.serviceOverrides }}
{{- $painterServiceOverrides = $painter.serviceOverrides }}
{{- end }}

---

{{ include "skv2.utils.merge" (list . $painterServiceOverrides "painter.serviceSpec") }}
{{- end }}

---

2 changes: 2 additions & 0 deletions codegen/test/chart-envvars/templates/rbac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Code generated by skv2. DO NOT EDIT.

17 changes: 17 additions & 0 deletions codegen/test/chart-envvars/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Code generated by skv2. DO NOT EDIT.

painter:
enabled: true
env: null
extraEnvs: {}
floatingUserId: false
image:
pullPolicy: IfNotPresent
registry: quay.io/solo-io
repository: painter
tag: v0.0.0
ports: {}
runAsUser: 10101
serviceType: ""
sidecars: {}

12 changes: 12 additions & 0 deletions codegen/test/chart-no-desc/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ spec:
{{- if $painter.env }}
env:
{{ toYaml $painter.env | indent 10 }}
{{- else if $painter.extraEnvs }}
env:
{{- end }}
{{- range $name, $item := $painter.extraEnvs }}
- name: {{ $name }}
{{- $item | toYaml | nindent 12 }}
{{- end }}
resources:
{{- if $painter.resources }}
Expand Down Expand Up @@ -100,6 +106,12 @@ spec:
{{- if $palette.env }}
env:
{{ toYaml $palette.env | indent 10 }}
{{- else if $palette.extraEnvs }}
env:
{{- end }}
{{- range $name, $item := $palette.extraEnvs }}
- name: {{ $name }}
{{- $item | toYaml | nindent 12 }}
{{- end }}
volumeMounts:
- mountPath: /etc/paint
Expand Down
2 changes: 2 additions & 0 deletions codegen/test/chart-no-desc/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ painter:
env:
- name: FOO
value: BAR
extraEnvs: {}
floatingUserId: false
image:
pullPolicy: IfNotPresent
Expand All @@ -17,6 +18,7 @@ painter:
sidecars:
palette:
env: null
extraEnvs: {}
image:
pullPolicy: IfNotPresent
registry: quay.io/solo-io
Expand Down
Loading

0 comments on commit d9546f8

Please sign in to comment.