Skip to content

Commit

Permalink
feat: add ability to merge custom volumes and volumeMount templates
Browse files Browse the repository at this point in the history
  • Loading branch information
strantalis committed Aug 14, 2024
1 parent e6df25b commit 0a2d6df
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 48 deletions.
2 changes: 2 additions & 0 deletions charts/platform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,5 +352,7 @@ realms:
| services.kas.config.keyring | list | `[{"alg":"ec:secp256r1","kid":"e1"},{"alg":"rsa:2048","kid":"r1"}]` | Default keys for clients to use |
| services.kas.privateKeysSecret | string | `"kas-private-keys"` | KAS secret containing keys kas-private.pem , kas-cert.pem , kas-ec-private.pem , kas-ec-cert.pem |
| tolerations | list | `[]` | Tolerations to apply to the pod (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) |
| volumeMountTemplate | string | `"platform.volumeMountsEmpty.tpl"` | Add ability for downstream chart to merge additional volumeMounts |
| volumeMounts | list | `[]` | Additional volumeMounts on the output Deployment definition. |
| volumeTemplate | string | `"platform.volumesEmpty.tpl"` | Add ability for downstream chart to merge additional volumes |
| volumes | list | `[]` | Additional volumes on the output Deployment definition. |
27 changes: 27 additions & 0 deletions charts/platform/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,31 @@ Create the name of the service account to use
{{- if and ( .Values.sdk_config.clientsecret) ( .Values.sdk_config.existingSecret.name) ( .Values.sdk_config.existingSecret.key)}}
{{- fail "You cannot set both clientsecret and existingSecret in sdk_config." }}
{{- end -}}
{{- end -}}

{{- /*
platform.util.merge will merge two YAML templates and output the result.
This takes an array of three values:
- the top context
- the template name of the overrides (destination)
- the template name of the base (source)
*/ -}}
{{- define "platform.util.merge.list" -}}
{{- $top := first . -}}
{{- $filterKey := (index . 1) }}
{{- $overrides := fromYaml (include (index . 2) $top) | default (dict) -}}
{{- $tpl := fromYaml (include (index . 3) $top) | default (dict) -}}

{{- $mergedList := index $tpl $filterKey | default (list) -}}

{{- range $key, $values := $overrides -}}
{{- if kindIs "slice" $values }}
{{- range $key2, $value := $values }}
{{- $mergedList = append $mergedList $value -}}
{{- end }}
{{- end -}}
{{- end -}}

{{- (dict $filterKey $mergedList) | toYaml }}

{{- end -}}
64 changes: 64 additions & 0 deletions charts/platform/templates/_volume.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{{ define "platform.volumesEmpty.tpl" }}
{{ end }}
{{ define "platform.volumes.tpl" }}
volumes:
- name: config
configMap:
name: {{ include "chart.fullname" . }}
{{- if or (contains .Values.mode "all") (contains .Values.mode "core") (contains .Values.mode "kas") }}
- name: kas-private-keys
secret:
secretName: {{ .Values.services.kas.privateKeysSecret }}
{{- if .Values.server.tls.enabled }}
{{- end }}
- name: tls
secret:
secretName: {{ .Values.server.tls.secret | default (printf "%s-tls" (include "chart.fullname" .)) }}
{{- end }}
{{- if or (and .Values.playground .Values.keycloak.ingress.enabled .Values.keycloak.ingress.tls) .Values.server.tls.additionalTrustedCerts }}
- name: trusted-certs
projected:
sources:
{{- if and .Values.playground .Values.keycloak.ingress.enabled .Values.keycloak.ingress.tls }}
- secret:
name: {{ .Values.keycloak.ingress.hostname }}-tls # If the fullnameOverride is set, this will break
optional: false
items:
- key: ca.crt
path: kc-ca.crt
{{- end -}}
{{- with .Values.server.tls.additionalTrustedCerts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- end }}
{{- with .Values.volumes }}
{{- toYaml . | nindent 2 }}
{{- end }}
{{ end }}


{{ define "platform.volumeMountsEmpty.tpl" }}
{{ end }}

{{ define "platform.volumeMounts.tpl" }}
volumeMounts:
- name: config
readOnly: true
mountPath: /etc/platform/config
{{- if or (contains .Values.mode "all") (contains .Values.mode "core") (contains .Values.mode "kas") }}
- name: kas-private-keys
readOnly: true
mountPath: /etc/platform/kas
{{- end }}
- name: trusted-certs
readOnly: true
mountPath: /etc/ssl/certs/platform
{{- if .Values.server.tls.enabled }}
- name: tls
readOnly: true
mountPath: /etc/platform/certs
{{- end -}}
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 2 }}
{{- end }}
{{ end }}
6 changes: 6 additions & 0 deletions charts/platform/templates/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ data:
clientsecret: {{ .Values.sdk_config.clientsecret | quote }}
{{- end }}
services:
{{- if or (contains .Values.mode "all") (contains .Values.mode "core") }}
entityresolution:
{{- .Values.services.entityresolution | toYaml | nindent 8 }}
{{- end }}
{{- if or (contains .Values.mode "all") (contains .Values.mode "core") (contains .Values.mode "kas") }}
kas:
{{- .Values.services.kas.config | toYaml | nindent 8 }}
{{- end }}
{{- if or (contains .Values.mode "all") (contains .Values.mode "core") }}
authorization:
{{- .Values.services.authorization | toYaml | nindent 8 }}
{{- end }}
{{- with .Values.services.extraServices }}
{{- toYaml . | nindent 6 }}
{{- end }}
Expand Down
52 changes: 4 additions & 48 deletions charts/platform/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{ $data := dict "Release" $.Release "Chart" $.Chart "Values" $.Values "Files" $.Files "Capabilities" .Capabilities }}
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -33,7 +34,8 @@ spec:
{{- if .Values.hostAliases }}
hostAliases:
{{- toYaml .Values.hostAliases | nindent 8 }}
{{- end }}
{{- end -}}
{{ include "platform.util.merge.list" (list $data "volumes" .Values.volumeTemplate "platform.volumes.tpl" ) | nindent 6 }}
containers:
- name: {{ .Chart.Name }}
args:
Expand Down Expand Up @@ -62,24 +64,7 @@ spec:
{{ end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: config
readOnly: true
mountPath: /etc/platform/config
- name: kas-private-keys
readOnly: true
mountPath: /etc/platform/kas
- name: trusted-certs
readOnly: true
mountPath: /etc/ssl/certs/platform
{{- if .Values.server.tls.enabled }}
- name: tls
readOnly: true
mountPath: /etc/platform/certs
{{- end -}}
{{- with .Values.volumeMounts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{ include "platform.util.merge.list" (list $data "volumeMounts" .Values.volumeMountTemplate "platform.volumeMounts.tpl" ) | nindent 10}}
env:
- name: SSL_CERT_DIR
value: '/etc/ssl/certs:/etc/ssl/certs/platform'
Expand All @@ -102,35 +87,6 @@ spec:
envFrom:
{{- toYaml . | nindent 10 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ include "chart.fullname" . }}
- name: kas-private-keys
secret:
secretName: {{ .Values.services.kas.privateKeysSecret }}
{{- if .Values.server.tls.enabled }}
- name: tls
secret:
secretName: {{ .Values.server.tls.secret | default (printf "%s-tls" (include "chart.fullname" .)) }}
{{- end }}
- name: trusted-certs
projected:
sources:
{{- if and .Values.playground .Values.keycloak.ingress.enabled .Values.keycloak.ingress.tls }}
- secret:
name: {{ .Values.keycloak.ingress.hostname }}-tls # If the fullnameOverride is set, this will break
optional: false
items:
- key: ca.crt
path: kc-ca.crt
{{- end -}}
{{- with .Values.server.tls.additionalTrustedCerts }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand Down
4 changes: 4 additions & 0 deletions charts/platform/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,17 @@ autoscaling:
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80

# -- Add ability for downstream chart to merge additional volumes
volumeTemplate: "platform.volumesEmpty.tpl"
# -- Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false

# -- Add ability for downstream chart to merge additional volumeMounts
volumeMountTemplate: "platform.volumeMountsEmpty.tpl"
# -- Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
Expand Down
98 changes: 98 additions & 0 deletions tests/chart_platform_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,101 @@ func (suite *PlatformChartTemplateSuite) Test_SDK_Config_Set_Client_Secret_AND_E
suite.Require().Error(err)
suite.Require().ErrorContains(err, "You cannot set both clientsecret and existingSecret in sdk_config.")
}

func (suite *PlatformChartTemplateSuite) Test_Playground_Enabled_AND_Keycloak_Ing_Enabled_Trusted_Cert_Mounted() {
releaseName := "basic"

namespaceName := "opentdf-" + strings.ToLower(random.UniqueId())

options := &helm.Options{
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
SetValues: map[string]string{
"image.tag": "latest",
"playground": "true",
},
}

output := helm.RenderTemplate(suite.T(), options, suite.chartPath, releaseName, []string{"templates/deployment.yaml"})
var deployment appv1.Deployment
helm.UnmarshalK8SYaml(suite.T(), output, &deployment)

// Find projected volume trusted-certs and check if keycloak cert is mounted
found := false
for _, volume := range deployment.Spec.Template.Spec.Volumes {
if volume.Projected != nil {
for _, source := range volume.Projected.Sources {
suite.T().Log("Secret Name: ", source.Secret.Name)
if source.Secret != nil && source.Secret.Name == "keycloak.local-tls" {
suite.Require().Equal("ca.crt", source.Secret.Items[0].Key)
suite.Require().Equal("kc-ca.crt", source.Secret.Items[0].Path)
}
}
}
}
suite.Require().True(found)
}

func (suite *PlatformChartTemplateSuite) Test_Playground_Enabled_AND_Keycloak_Ing_Disabled_Trusted_Cert_Not_Mounted() {
releaseName := "basic"

namespaceName := "opentdf-" + strings.ToLower(random.UniqueId())

options := &helm.Options{
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
SetValues: map[string]string{
"image.tag": "latest",
"playground": "true",
"keycloak.ingress.enabled": "false",
},
}

output := helm.RenderTemplate(suite.T(), options, suite.chartPath, releaseName, []string{"templates/deployment.yaml"})
var deployment appv1.Deployment
helm.UnmarshalK8SYaml(suite.T(), output, &deployment)

// Find projected volume trusted-certs and check if keycloak cert is mounted
found := false
for _, volume := range deployment.Spec.Template.Spec.Volumes {
if volume.Projected != nil {
for _, source := range volume.Projected.Sources {
if source.Secret != nil && source.Secret.Name == "keycloak.local-tls" {
found = true
}
}
}
}
suite.Require().False(found)
}

func (suite *PlatformChartTemplateSuite) Test_Playground_Enabled_AND_Keycloak_Ing_Enabled_AND_TLS_Disabled_Trusted_Cert_Not_Mounted() {
releaseName := "basic"

namespaceName := "opentdf-" + strings.ToLower(random.UniqueId())

options := &helm.Options{
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
SetValues: map[string]string{
"image.tag": "latest",
"playground": "true",
"keycloak.ingress.enabled": "true",
"keycloak.ingress.tls": "false",
},
}

output := helm.RenderTemplate(suite.T(), options, suite.chartPath, releaseName, []string{"templates/deployment.yaml"})
var deployment appv1.Deployment
helm.UnmarshalK8SYaml(suite.T(), output, &deployment)

// Find projected volume trusted-certs and check if keycloak cert is mounted
found := false
for _, volume := range deployment.Spec.Template.Spec.Volumes {
if volume.Projected != nil {
for _, source := range volume.Projected.Sources {
if source.Secret != nil && source.Secret.Name == "keycloak.local-tls" {
found = true
}
}
}
}
suite.Require().False(found)
}
9 changes: 9 additions & 0 deletions tests/kubeconform/extra_volumes-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
volumeMounts:
- name: test
mountPath: /extra-config
readOnly: true
volumes:
- name: test
secret:
secretName: mysecret
optional: false
1 change: 1 addition & 0 deletions tests/kubeconform/mode_all-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mode: all
1 change: 1 addition & 0 deletions tests/kubeconform/mode_combo-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mode: test,kas
1 change: 1 addition & 0 deletions tests/kubeconform/mode_core-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mode: core
1 change: 1 addition & 0 deletions tests/kubeconform/mode_kas-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mode: kas
1 change: 1 addition & 0 deletions tests/kubeconform/mode_test-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mode: test
27 changes: 27 additions & 0 deletions tests/traefik.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: platform
spec:
entryPoints:
- websecure
routes:
- match: Host(`keycloak.opentdf.local`)
kind: Rule
services:
- name: platform-keycloak
namespace: opentdf-sd1jsk
port: 80
scheme: http
passHostHeader: true
- match: Host(`platform.opentdf.local`)
kind: Rule
services:
- name: opentdf-platform
namespace: opentdf-sd1jsk
port: 9000
scheme: h2c
passHostHeader: true
tls:
secretName: platform-tls

0 comments on commit 0a2d6df

Please sign in to comment.