diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index 5daab5b083f..2d665873daf 100644 --- a/charts/library/common/Chart.yaml +++ b/charts/library/common/Chart.yaml @@ -18,4 +18,4 @@ maintainers: name: common sources: null type: library -version: 6.13.11 +version: 6.14.0 diff --git a/charts/library/common/templates/_all.tpl b/charts/library/common/templates/_all.tpl index f9f82650123..11907c053ce 100644 --- a/charts/library/common/templates/_all.tpl +++ b/charts/library/common/templates/_all.tpl @@ -8,6 +8,26 @@ Main entrypoint for the common library chart. It will render all underlying temp {{- /* Build the templates */ -}} {{- include "common.pvc" . }} + {{- /* Enable code-server add-on if required */ -}} + {{- if .Values.addons.codeserver.enabled }} + {{- include "common.addon.codeserver" . }} + {{- end -}} + + {{- /* Enable VPN add-on if required */ -}} + {{- if .Values.addons.vpn.enabled }} + {{- include "common.addon.vpn" . }} + {{- end -}} + + {{- /* Enable promtail add-on if required */ -}} + {{- if .Values.addons.promtail.enabled }} + {{- include "common.addon.promtail" . }} + {{- end -}} + + {{- /* Enable netshoot add-on if required */ -}} + {{- if .Values.addons.netshoot.enabled }} + {{- include "common.addon.netshoot" . }} + {{- end -}} + {{- if .Values.serviceAccount.create -}} {{- include "common.serviceAccount" . }} {{- end -}} diff --git a/charts/library/common/templates/addons/code-server/_codeserver.tpl b/charts/library/common/templates/addons/code-server/_codeserver.tpl new file mode 100644 index 00000000000..f8b39bfcbca --- /dev/null +++ b/charts/library/common/templates/addons/code-server/_codeserver.tpl @@ -0,0 +1,51 @@ +{{/* +Template to render code-server addon +It will include / inject the required templates based on the given values. +*/}} +{{- define "common.addon.codeserver" -}} +{{- if .Values.addons.codeserver.enabled -}} + {{/* Append the code-server container to the additionalContainers */}} + {{- $container := include "common.addon.codeserver.container" . | fromYaml -}} + {{- if $container -}} + {{- $additionalContainers := append .Values.additionalContainers $container -}} + {{- $_ := set .Values "additionalContainers" $additionalContainers -}} + {{- end -}} + + {{/* Include the deployKeySecret if not empty */}} + {{- $secret := include "common.addon.codeserver.deployKeySecret" . -}} + {{- if $secret -}} + {{- $secret | nindent 0 -}} + {{- end -}} + + {{/* Append the secret volume to the volumes */}} + {{- $volume := include "common.addon.codeserver.deployKeyVolumeSpec" . | fromYaml -}} + {{- if $volume -}} + {{- $_ := set .Values.persistence "deploykey" (dict "enabled" "true" "mountPath" "-" "type" "custom" "volumeSpec" $volume) -}} + {{- end -}} + + {{/* Add the code-server service */}} + {{- if .Values.addons.codeserver.service.enabled -}} + {{- $serviceValues := .Values.addons.codeserver.service -}} + {{- $_ := set $serviceValues "nameOverride" "codeserver" -}} + {{- $_ := set $ "ObjectValues" (dict "service" $serviceValues) -}} + {{- include "common.classes.service" $ -}} + {{- $_ := unset $ "ObjectValues" -}} + {{- end -}} + + {{/* Add the code-server ingress */}} + {{- if .Values.addons.codeserver.ingress.enabled -}} + {{- $ingressValues := .Values.addons.codeserver.ingress -}} + {{- $_ := set $ingressValues "nameOverride" "codeserver" -}} + + {{/* Determine the target service name & port */}} + {{- $svcName := printf "%v-codeserver" (include "common.names.fullname" .) -}} + {{- $svcPort := .Values.addons.codeserver.service.ports.codeserver.port -}} + {{- range $_, $host := $ingressValues.hosts -}} + {{- $_ := set (index $host.paths 0) "service" (dict "name" $svcName "port" $svcPort) -}} + {{- end -}} + {{- $_ := set $ "ObjectValues" (dict "ingress" $ingressValues) -}} + {{- include "common.classes.ingress" $ -}} + {{- $_ := unset $ "ObjectValues" -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/code-server/_container.tpl b/charts/library/common/templates/addons/code-server/_container.tpl new file mode 100644 index 00000000000..23af35efda1 --- /dev/null +++ b/charts/library/common/templates/addons/code-server/_container.tpl @@ -0,0 +1,46 @@ +{{/* +The code-server sidecar container to be inserted. +*/}} +{{- define "common.addon.codeserver.container" -}} +{{- if lt (len .Values.addons.codeserver.volumeMounts) 1 }} +{{- fail "At least 1 volumeMount is required for codeserver container" }} +{{- end -}} +name: codeserver +image: "{{ .Values.addons.codeserver.image.repository }}:{{ .Values.addons.codeserver.image.tag }}" +imagePullPolicy: {{ .Values.addons.codeserver.pullPolicy }} +{{- with .Values.addons.codeserver.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.addons.codeserver.env }} +env: +{{- range $k, $v := . }} + - name: {{ $k }} + value: {{ $v | quote }} +{{- end }} +{{- end }} +ports: +- name: codeserver + containerPort: {{ .Values.addons.codeserver.service.ports.codeserver.port }} + protocol: TCP +args: +{{- range .Values.addons.codeserver.args }} +- {{ . | quote }} +{{- end }} +- "--port" +- "{{ .Values.addons.codeserver.service.ports.codeserver.port }}" +- {{ .Values.addons.codeserver.workingDir | default (first .Values.addons.codeserver.volumeMounts).mountPath }} +volumeMounts: +{{- with .Values.addons.codeserver.volumeMounts }} + {{- toYaml . | nindent 2 }} +{{- end }} +{{- if or .Values.addons.codeserver.git.deployKey .Values.addons.codeserver.git.deployKeyBase64 .Values.addons.codeserver.git.deployKeySecret }} + - name: deploykey + mountPath: /root/.ssh/id_rsa + subPath: id_rsa +{{- end }} +{{- with .Values.addons.codeserver.resources }} +resources: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/addons/code-server/_secret.tpl b/charts/library/common/templates/addons/code-server/_secret.tpl new file mode 100644 index 00000000000..14c62327996 --- /dev/null +++ b/charts/library/common/templates/addons/code-server/_secret.tpl @@ -0,0 +1,22 @@ +{{/* +The OpenVPN credentials secrets to be included. +*/}} +{{- define "common.addon.codeserver.deployKeySecret" -}} +{{- if or .Values.addons.codeserver.git.deployKey .Values.addons.codeserver.git.deployKeyBase64 }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }}-deploykey + labels: + {{- include "common.labels" . | nindent 4 }} +type: Opaque +{{- if .Values.addons.codeserver.git.deployKey }} +stringData: + id_rsa: {{ .Values.addons.codeserver.git.deployKey | quote }} +{{- else }} +data: + id_rsa: {{ .Values.addons.codeserver.git.deployKeyBase64 | quote }} +{{- end }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/addons/code-server/_volume.tpl b/charts/library/common/templates/addons/code-server/_volume.tpl new file mode 100644 index 00000000000..6e6d5947a64 --- /dev/null +++ b/charts/library/common/templates/addons/code-server/_volume.tpl @@ -0,0 +1,17 @@ +{{/* +The volume (referencing git deploykey) to be inserted into additionalVolumes. +*/}} +{{- define "common.addon.codeserver.deployKeyVolumeSpec" -}} +{{- if or .Values.addons.codeserver.git.deployKey .Values.addons.codeserver.git.deployKeyBase64 .Values.addons.codeserver.git.deployKeySecret }} +secret: + {{- if .Values.addons.codeserver.git.deployKeySecret }} + secretName: {{ .Values.addons.codeserver.git.deployKeySecret }} + {{- else }} + secretName: {{ include "common.names.fullname" . }}-deploykey + {{- end }} + defaultMode: 256 + items: + - key: id_rsa + path: id_rsa +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/netshoot/_container.tpl b/charts/library/common/templates/addons/netshoot/_container.tpl new file mode 100644 index 00000000000..3e7a429cff4 --- /dev/null +++ b/charts/library/common/templates/addons/netshoot/_container.tpl @@ -0,0 +1,27 @@ +{{/* +The netshoot sidecar container to be inserted. +*/}} +{{- define "common.addon.netshoot.container" -}} +name: netshoot +image: "{{ .Values.addons.netshoot.image.repository }}:{{ .Values.addons.netshoot.image.tag }}" +imagePullPolicy: {{ .Values.addons.netshoot.pullPolicy }} +{{- with .Values.addons.netshoot.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.addons.netshoot.env }} +env: +{{- range $k, $v := . }} + - name: {{ $k }} + value: {{ $v | quote }} +{{- end }} +{{- end }} +command: + - /bin/sh + - -c + - sleep infinity +{{- with .Values.addons.netshoot.resources }} +resources: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/addons/netshoot/_netshoot.tpl b/charts/library/common/templates/addons/netshoot/_netshoot.tpl new file mode 100644 index 00000000000..307dab53721 --- /dev/null +++ b/charts/library/common/templates/addons/netshoot/_netshoot.tpl @@ -0,0 +1,14 @@ +{{/* +Template to render netshoot addon +It will include / inject the required templates based on the given values. +*/}} +{{- define "common.addon.netshoot" -}} +{{- if .Values.addons.netshoot.enabled -}} + {{/* Append the netshoot container to the additionalContainers */}} + {{- $container := include "common.addon.netshoot.container" . | fromYaml -}} + {{- if $container -}} + {{- $additionalContainers := append .Values.additionalContainers $container -}} + {{- $_ := set .Values "additionalContainers" $additionalContainers -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/promtail/_configmap.tpl b/charts/library/common/templates/addons/promtail/_configmap.tpl new file mode 100644 index 00000000000..3b92757689e --- /dev/null +++ b/charts/library/common/templates/addons/promtail/_configmap.tpl @@ -0,0 +1,35 @@ +{{/* +The promtail config to be included. +*/}} +{{- define "common.addon.promtail.configmap" -}} +{{- if .Values.addons.promtail.enabled }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }}-promtail + labels: + {{- include "common.labels" . | nindent 4 }} +data: + promtail.yaml: | + server: + http_listen_port: 9080 + grpc_listen_port: 0 + positions: + filename: /tmp/positions.yaml + {{- with .Values.addons.promtail.loki }} + client: + url: {{ . }} + {{- end }} + scrape_configs: + {{- range .Values.addons.promtail.logs }} + - job_name: {{ .name }} + static_configs: + - targets: + - localhost + labels: + job: {{ .name }} + __path__: "{{ .path }}" + {{- end }} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/promtail/_container.tpl b/charts/library/common/templates/addons/promtail/_container.tpl new file mode 100644 index 00000000000..f4936bc4988 --- /dev/null +++ b/charts/library/common/templates/addons/promtail/_container.tpl @@ -0,0 +1,39 @@ +{{/* +The promtail sidecar container to be inserted. +*/}} +{{- define "common.addon.promtail.container" -}} +{{- if lt (len .Values.addons.promtail.volumeMounts) 1 }} +{{- fail "At least 1 volumeMount is required for the promtail container" }} +{{- end -}} +name: promtail +image: "{{ .Values.addons.promtail.image.repository }}:{{ .Values.addons.promtail.image.tag }}" +imagePullPolicy: {{ .Values.addons.promtail.pullPolicy }} +{{- with .Values.addons.promtail.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.addons.promtail.env }} +env: +{{- range $k, $v := . }} + - name: {{ $k }} + value: {{ $v | quote }} +{{- end }} +{{- end }} +args: +{{- range .Values.addons.promtail.args }} +- {{ . | quote }} +{{- end }} +- "-config.file=/etc/promtail/promtail.yaml" +volumeMounts: + - name: promtail-config + mountPath: /etc/promtail/promtail.yaml + subPath: promtail.yaml + readOnly: true +{{- with .Values.addons.promtail.volumeMounts }} + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.addons.promtail.resources }} +resources: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/addons/promtail/_promtail.tpl b/charts/library/common/templates/addons/promtail/_promtail.tpl new file mode 100644 index 00000000000..7526050563f --- /dev/null +++ b/charts/library/common/templates/addons/promtail/_promtail.tpl @@ -0,0 +1,26 @@ +{{/* +Template to render promtail addon +It will include / inject the required templates based on the given values. +*/}} +{{- define "common.addon.promtail" -}} +{{- if .Values.addons.promtail.enabled -}} + {{/* Append the promtail container to the additionalContainers */}} + {{- $container := include "common.addon.promtail.container" . | fromYaml -}} + {{- if $container -}} + {{- $additionalContainers := append .Values.additionalContainers $container -}} + {{- $_ := set .Values "additionalContainers" $additionalContainers -}} + {{- end -}} + + {{/* Include the configmap if not empty */}} + {{- $configmap := include "common.addon.promtail.configmap" . -}} + {{- if $configmap -}} + {{- $configmap | nindent 0 -}} + {{- end -}} + + {{/* Append the promtail config volume to the volumes */}} + {{- $volume := include "common.addon.promtail.volumeSpec" . | fromYaml -}} + {{- if $volume -}} + {{- $_ := set .Values.persistence "promtail-config" (dict "enabled" "true" "mountPath" "-" "type" "custom" "volumeSpec" $volume) -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/promtail/_volume.tpl b/charts/library/common/templates/addons/promtail/_volume.tpl new file mode 100644 index 00000000000..bce624b59f5 --- /dev/null +++ b/charts/library/common/templates/addons/promtail/_volume.tpl @@ -0,0 +1,7 @@ +{{/* +The volume (referencing config) to be inserted into additionalVolumes. +*/}} +{{- define "common.addon.promtail.volumeSpec" -}} +configMap: + name: {{ include "common.names.fullname" . }}-promtail +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/_configmap.tpl b/charts/library/common/templates/addons/vpn/_configmap.tpl new file mode 100644 index 00000000000..f57a6965a84 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/_configmap.tpl @@ -0,0 +1,23 @@ +{{/* +The VPN config and scripts to be included. +*/}} +{{- define "common.addon.vpn.configmap" -}} +{{- if or .Values.addons.vpn.scripts.up .Values.addons.vpn.scripts.down }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "common.names.fullname" . }}-vpn + labels: + {{- include "common.labels" . | nindent 4 }} +data: +{{- with .Values.addons.vpn.scripts.up }} + up.sh: |- + {{- . | nindent 4}} +{{- end }} +{{- with .Values.addons.vpn.scripts.down }} + down.sh: |- + {{- . | nindent 4}} +{{- end }} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/_secret.tpl b/charts/library/common/templates/addons/vpn/_secret.tpl new file mode 100644 index 00000000000..43e1c27084c --- /dev/null +++ b/charts/library/common/templates/addons/vpn/_secret.tpl @@ -0,0 +1,19 @@ +{{/* +The OpenVPN config secret to be included. +*/}} +{{- define "common.addon.vpn.secret" -}} +{{- if and .Values.addons.vpn.configFile (not .Values.addons.vpn.configFileSecret) }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }}-vpnconfig + labels: + {{- include "common.labels" $ | nindent 4 }} +stringData: + {{- with .Values.addons.vpn.configFile }} + vpnConfigfile: |- + {{- . | nindent 4}} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/_volume.tpl b/charts/library/common/templates/addons/vpn/_volume.tpl new file mode 100644 index 00000000000..184e2a99488 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/_volume.tpl @@ -0,0 +1,37 @@ +{{/* +The volume (referencing VPN scripts) to be inserted into additionalVolumes. +*/}} +{{- define "common.addon.vpn.scriptsVolumeSpec" -}} +{{- if or .Values.addons.vpn.scripts.up .Values.addons.vpn.scripts.down -}} +configMap: + name: {{ include "common.names.fullname" . }}-vpn + items: + {{- if .Values.addons.vpn.scripts.up }} + - key: up.sh + path: up.sh + mode: 0777 + {{- end }} + {{- if .Values.addons.vpn.scripts.down }} + - key: down.sh + path: down.sh + mode: 0777 + {{- end }} +{{- end -}} +{{- end -}} + +{{/* +The volume (referencing VPN config) to be inserted into additionalVolumes. +*/}} +{{- define "common.addon.vpn.configVolumeSpec" -}} +{{- if or .Values.addons.vpn.configFile .Values.addons.vpn.configFileSecret -}} +secret: + {{- if .Values.addons.vpn.configFileSecret }} + secretName: {{ .Values.addons.vpn.configFileSecret }} + {{- else }} + secretName: {{ include "common.names.fullname" . }}-vpnconfig + {{- end }} + items: + - key: vpnConfigfile + path: vpnConfigfile +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/_vpn.tpl b/charts/library/common/templates/addons/vpn/_vpn.tpl new file mode 100644 index 00000000000..0cf13254ace --- /dev/null +++ b/charts/library/common/templates/addons/vpn/_vpn.tpl @@ -0,0 +1,40 @@ +{{/* +Template to render VPN addon +It will include / inject the required templates based on the given values. +*/}} +{{- define "common.addon.vpn" -}} +{{- if .Values.addons.vpn.enabled -}} + {{- if eq "openvpn" .Values.addons.vpn.type -}} + {{- include "common.addon.openvpn" . }} + {{- end -}} + + {{- if eq "wireguard" .Values.addons.vpn.type -}} + {{- include "common.addon.wireguard" . }} + {{- end -}} + + {{/* Include the configmap if not empty */}} + {{- $configmap := include "common.addon.vpn.configmap" . -}} + {{- if $configmap -}} + {{- $configmap | nindent 0 -}} + {{- end -}} + + {{/* Include the secret if not empty */}} + {{- $secret := include "common.addon.vpn.secret" . -}} + {{- if $secret -}} + {{- $secret | nindent 0 -}} + {{- end -}} + + {{/* Append the vpn scripts volume to the volumes */}} + {{- $scriptVolume := include "common.addon.vpn.scriptsVolumeSpec" . | fromYaml -}} + {{- if $scriptVolume -}} + {{- $_ := set .Values.persistence "vpnscript" (dict "enabled" "true" "mountPath" "-" "type" "custom" "volumeSpec" $scriptVolume) -}} + {{- end -}} + + {{/* Append the vpn config volume to the volumes */}} + {{- $configVolume := include "common.addon.vpn.configVolumeSpec" . | fromYaml }} + {{ if $configVolume -}} + {{- $_ := set .Values.persistence "vpnconfig" (dict "enabled" "true" "mountPath" "-" "type" "custom" "volumeSpec" $configVolume) -}} + {{- end -}} + +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/openvpn/_addon.tpl b/charts/library/common/templates/addons/vpn/openvpn/_addon.tpl new file mode 100644 index 00000000000..32354bcbdc4 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/openvpn/_addon.tpl @@ -0,0 +1,18 @@ +{{/* +Template to render OpenVPN addon. It will add the container to the list of additionalContainers +and add a credentials secret if speciffied. +*/}} +{{- define "common.addon.openvpn" -}} + {{/* Append the openVPN container to the additionalContainers */}} + {{- $container := include "common.addon.openvpn.container" . | fromYaml -}} + {{- if $container -}} + {{- $additionalContainers := append .Values.additionalContainers $container -}} + {{- $_ := set .Values "additionalContainers" $additionalContainers -}} + {{- end -}} + + {{/* Include the secret if not empty */}} + {{- $secret := include "common.addon.openvpn.secret" . -}} + {{- if $secret -}} + {{- $secret | nindent 0 -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/openvpn/_container.tpl b/charts/library/common/templates/addons/vpn/openvpn/_container.tpl new file mode 100644 index 00000000000..c6d9412b418 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/openvpn/_container.tpl @@ -0,0 +1,61 @@ +{{/* +The OpenVPN sidecar container to be inserted. +*/}} +{{- define "common.addon.openvpn.container" -}} +name: openvpn +image: "{{ .Values.addons.vpn.openvpn.image.repository }}:{{ .Values.addons.vpn.openvpn.image.tag }}" +imagePullPolicy: {{ .Values.addons.vpn.openvpn.pullPolicy }} +{{- with .Values.addons.vpn.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.addons.vpn.env }} +env: +{{- range $k, $v := . }} + - name: {{ $k }} + value: {{ $v | quote }} +{{- end }} +{{- end }} +{{- if or .Values.addons.vpn.openvpn.auth .Values.addons.vpn.openvpn.authSecret }} +envFrom: + - secretRef: + {{- if .Values.addons.vpn.openvpn.authSecret }} + name: {{ .Values.addons.vpn.openvpn.authSecret }} + {{- else }} + name: {{ include "common.names.fullname" . }}-openvpn + {{- end }} +{{- end }} +{{- if or .Values.addons.vpn.configFile .Values.addons.vpn.configFileSecret .Values.addons.vpn.scripts.up .Values.addons.vpn.scripts.down .Values.addons.vpn.additionalVolumeMounts .Values.persistence.shared.enabled }} +volumeMounts: +{{- if or .Values.addons.vpn.configFile .Values.addons.vpn.configFileSecret }} + - name: vpnconfig + mountPath: /vpn/vpn.conf + subPath: vpnConfigfile +{{- end }} +{{- if .Values.addons.vpn.scripts.up }} + - name: vpnscript + mountPath: /vpn/up.sh + subPath: up.sh +{{- end }} +{{- if .Values.addons.vpn.scripts.down }} + - name: vpnscript + mountPath: /vpn/down.sh + subPath: down.sh +{{- end }} +{{- if .Values.persistence.shared.enabled }} + - mountPath: {{ .Values.persistence.shared.mountPath }} + name: shared +{{- end }} +{{- with .Values.addons.vpn.additionalVolumeMounts }} + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- with .Values.addons.vpn.livenessProbe }} +livenessProbe: + {{- toYaml . | nindent 2 }} +{{- end -}} +{{- with .Values.addons.vpn.resources }} +resources: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/openvpn/_secret.tpl b/charts/library/common/templates/addons/vpn/openvpn/_secret.tpl new file mode 100644 index 00000000000..f1b622570b7 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/openvpn/_secret.tpl @@ -0,0 +1,16 @@ +{{/* +The OpenVPN credentials secrets to be included. +*/}} +{{- define "common.addon.openvpn.secret" -}} +{{- with .Values.addons.vpn.openvpn.auth }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" $ }}-openvpn + labels: + {{- include "common.labels" $ | nindent 4 }} +data: + VPN_AUTH: {{ . | b64enc }} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/wireguard/_addon.tpl b/charts/library/common/templates/addons/vpn/wireguard/_addon.tpl new file mode 100644 index 00000000000..3213b5faa97 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/wireguard/_addon.tpl @@ -0,0 +1,12 @@ +{{/* +Template to render Wireguard addon. It will add the container to the list of additionalContainers. +*/}} +*/}} +{{- define "common.addon.wireguard" -}} + {{/* Append the Wireguard container to the additionalContainers */}} + {{- $container := fromYaml (include "common.addon.wireguard.container" .) -}} + {{- if $container -}} + {{- $additionalContainers := append .Values.additionalContainers $container -}} + {{- $_ := set .Values "additionalContainers" $additionalContainers -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/addons/vpn/wireguard/_container.tpl b/charts/library/common/templates/addons/vpn/wireguard/_container.tpl new file mode 100644 index 00000000000..b6e14940ef2 --- /dev/null +++ b/charts/library/common/templates/addons/vpn/wireguard/_container.tpl @@ -0,0 +1,52 @@ +{{/* +The Wireguard sidecar container to be inserted. +*/}} +{{- define "common.addon.wireguard.container" -}} +name: wireguard +image: "{{ .Values.addons.vpn.wireguard.image.repository }}:{{ .Values.addons.vpn.wireguard.image.tag }}" +imagePullPolicy: {{ .Values.addons.vpn.wireguard.pullPolicy }} +{{- with .Values.addons.vpn.securityContext }} +securityContext: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.addons.vpn.env }} +env: +{{- range $k, $v := . }} + - name: {{ $k }} + value: {{ $v | quote }} +{{- end }} +{{- end }} +{{- if or .Values.addons.vpn.configFile .Values.addons.vpn.configFileSecret .Values.addons.vpn.scripts.up .Values.addons.vpn.scripts.down .Values.addons.vpn.additionalVolumeMounts .Values.persistence.shared.enabled }} +volumeMounts: +{{- if or .Values.addons.vpn.configFile .Values.addons.vpn.configFileSecret }} + - name: vpnconfig + mountPath: /etc/wireguard/wg0.conf + subPath: vpnConfigfile +{{- end }} +{{- if .Values.addons.vpn.scripts.up }} + - name: vpnscript + mountPath: /config/up.sh + subPath: up.sh +{{- end }} +{{- if .Values.addons.vpn.scripts.down }} + - name: vpnscript + mountPath: /config/down.sh + subPath: down.sh +{{- end }} +{{- if .Values.persistence.shared.enabled }} + - mountPath: {{ .Values.persistence.shared.mountPath }} + name: shared +{{- end }} +{{- with .Values.addons.vpn.additionalVolumeMounts }} + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} +{{- with .Values.addons.vpn.livenessProbe }} +livenessProbe: + {{- toYaml . | nindent 2 }} +{{- end -}} +{{- with .Values.addons.vpn.resources }} +resources: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/tests/addon_codeserver_test.go b/charts/library/common/tests/addon_codeserver_test.go new file mode 100644 index 00000000000..4eefdd45ba5 --- /dev/null +++ b/charts/library/common/tests/addon_codeserver_test.go @@ -0,0 +1,136 @@ +package common + +import ( + "testing" + + "github.com/Jeffail/gabs/v2" + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type AddonCodeserverTestSuite struct { + suite.Suite + Chart helmunit.HelmChart + baseValues string +} + +func (suite *AddonCodeserverTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() + suite.baseValues = ` + addons: + codeserver: + enabled: true + volumeMounts: + - name: "config" + mountPath: "/data/config" + ` +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestAddonCodeserver(t *testing.T) { + suite.Run(t, new(AddonCodeserverTestSuite)) +} + +func (suite *AddonCodeserverTestSuite) TestContainer() { + tests := map[string]struct { + values *string + expectedCodeserverContainer bool + }{ + "Default": {values: nil, expectedCodeserverContainer: false}, + "AddonEnabled": {values: &suite.baseValues, expectedCodeserverContainer: true}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers := deploymentManifest.Path("spec.template.spec.containers").Children() + + var codeserverContainer *gabs.Container + for _, container := range containers { + containerName := container.Path("name").Data().(string) + if containerName == "codeserver" { + codeserverContainer = container + break + } + } + + if tc.expectedCodeserverContainer { + suite.Assertions.NotEmpty(codeserverContainer) + } else { + suite.Assertions.Empty(codeserverContainer) + } + }) + } +} + +func (suite *AddonCodeserverTestSuite) TestDeployKey() { + tests := map[string]struct { + values []string + expectSecret bool + expectedSecretName string + }{ + "Inline": {values: []string{"addons.codeserver.git.deployKey=test"}, expectSecret: true, expectedSecretName: "common-test-deploykey"}, + "InlineBase64": {values: []string{"addons.codeserver.git.deployKeyBase64=dGVzdEtleQ=="}, expectSecret: true, expectedSecretName: "common-test-deploykey"}, + "ExistingSecret": {values: []string{"addons.codeserver.git.deployKeySecret=test-secret"}, expectSecret: false, expectedSecretName: "test-secret"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, &suite.baseValues) + if err != nil { + suite.FailNow(err.Error()) + } + + secretManifest := suite.Chart.Manifests.Get("Secret", tc.expectedSecretName) + if tc.expectSecret { + suite.Assertions.NotEmpty(secretManifest) + } else { + suite.Assertions.Empty(secretManifest) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + + containers := deploymentManifest.Path("spec.template.spec.containers").Children() + var codeserverContainer *gabs.Container + for _, container := range containers { + containerName := container.Path("name").Data().(string) + if containerName == "codeserver" { + codeserverContainer = container + break + } + } + suite.Assertions.NotEmpty(codeserverContainer) + + volumeMounts := codeserverContainer.Path("volumeMounts").Children() + var gitDeploykeyVolumeMount *gabs.Container + for _, volumeMount := range volumeMounts { + volumeMountName := volumeMount.Path("name").Data().(string) + if volumeMountName == "deploykey" { + gitDeploykeyVolumeMount = volumeMount + break + } + } + suite.Assertions.NotEmpty(gitDeploykeyVolumeMount) + suite.Assertions.EqualValues("/root/.ssh/id_rsa", gitDeploykeyVolumeMount.Path("mountPath").Data()) + suite.Assertions.EqualValues("id_rsa", gitDeploykeyVolumeMount.Path("subPath").Data()) + + volumes := deploymentManifest.Path("spec.template.spec.volumes").Children() + var gitDeploykeyVolume *gabs.Container + for _, volume := range volumes { + volumeName := volume.Path("name").Data().(string) + if volumeName == "deploykey" { + gitDeploykeyVolume = volume + break + } + } + suite.Assertions.NotEmpty(gitDeploykeyVolume) + }) + } +} diff --git a/charts/library/common/tests/addon_netshoot_test.go b/charts/library/common/tests/addon_netshoot_test.go new file mode 100644 index 00000000000..1401e116aa5 --- /dev/null +++ b/charts/library/common/tests/addon_netshoot_test.go @@ -0,0 +1,64 @@ +package common + +import ( + "testing" + + "github.com/Jeffail/gabs/v2" + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type AddonNetshootTestSuite struct { + suite.Suite + Chart helmunit.HelmChart + baseValues []string +} + +func (suite *AddonNetshootTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() + suite.baseValues = []string{"addons.netshoot.enabled=true"} +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestAddonNetshoot(t *testing.T) { + suite.Run(t, new(AddonNetshootTestSuite)) +} + +func (suite *AddonNetshootTestSuite) TestContainer() { + tests := map[string]struct { + values []string + expectedNetshootContainer bool + }{ + "Default": {values: nil, expectedNetshootContainer: false}, + "AddonEnabled": {values: suite.baseValues, expectedNetshootContainer: true}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers := deploymentManifest.Path("spec.template.spec.containers").Children() + + var netshootContainer *gabs.Container + for _, container := range containers { + containerName := container.Path("name").Data().(string) + if containerName == "netshoot" { + netshootContainer = container + break + } + } + + if tc.expectedNetshootContainer { + suite.Assertions.NotEmpty(netshootContainer) + } else { + suite.Assertions.Empty(netshootContainer) + } + }) + } +} diff --git a/charts/library/common/tests/addon_vpn_test.go b/charts/library/common/tests/addon_vpn_test.go new file mode 100644 index 00000000000..40c8a11abc9 --- /dev/null +++ b/charts/library/common/tests/addon_vpn_test.go @@ -0,0 +1,129 @@ +package common + +import ( + "testing" + + "github.com/Jeffail/gabs/v2" + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type AddonVpnTestSuite struct { + suite.Suite + Chart helmunit.HelmChart + baseValues []string +} + +func (suite *AddonVpnTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() + suite.baseValues = []string{"addons.vpn.enabled=true"} +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestAddonVpn(t *testing.T) { + suite.Run(t, new(AddonVpnTestSuite)) +} + +func (suite *AddonVpnTestSuite) TestContainer() { + tests := map[string]struct { + values []string + expectedVpnContainer bool + }{ + "Default": {values: nil, expectedVpnContainer: false}, + "AddonEnabled": {values: suite.baseValues, expectedVpnContainer: true}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers := deploymentManifest.Path("spec.template.spec.containers").Children() + + var vpnContainer *gabs.Container + for _, container := range containers { + containerName := container.Path("name").Data().(string) + if containerName == "openvpn" { + vpnContainer = container + break + } + } + + if tc.expectedVpnContainer { + suite.Assertions.NotEmpty(vpnContainer) + } else { + suite.Assertions.Empty(vpnContainer) + } + }) + } +} + +func (suite *AddonVpnTestSuite) TestConfiguration() { + tests := map[string]struct { + values []string + expectSecret bool + expectedSecretName string + }{ + "InlineConfig": {values: append(suite.baseValues, "addons.vpn.configFile=test"), expectSecret: true, expectedSecretName: "common-test-vpnconfig"}, + "ExistingSecret": {values: append(suite.baseValues, "addons.vpn.configFileSecret=test-secret"), expectSecret: false, expectedSecretName: "test-secret"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + secretManifest := suite.Chart.Manifests.Get("Secret", tc.expectedSecretName) + if tc.expectSecret { + suite.Assertions.NotEmpty(secretManifest) + } else { + suite.Assertions.Empty(secretManifest) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + + containers := deploymentManifest.Path("spec.template.spec.containers").Children() + var vpnContainer *gabs.Container + for _, container := range containers { + containerName := container.Path("name").Data().(string) + if containerName == "openvpn" { + vpnContainer = container + break + } + } + suite.Assertions.NotEmpty(vpnContainer) + + volumeMounts := vpnContainer.Path("volumeMounts").Children() + var vpnConfigVolumeMount *gabs.Container + for _, volumeMount := range volumeMounts { + volumeMountName := volumeMount.Path("name").Data().(string) + if volumeMountName == "vpnconfig" { + vpnConfigVolumeMount = volumeMount + break + } + } + suite.Assertions.NotEmpty(vpnConfigVolumeMount) + suite.Assertions.EqualValues("/vpn/vpn.conf", vpnConfigVolumeMount.Path("mountPath").Data()) + suite.Assertions.EqualValues("vpnConfigfile", vpnConfigVolumeMount.Path("subPath").Data()) + + volumes := deploymentManifest.Path("spec.template.spec.volumes").Children() + var vpnConfigVolume *gabs.Container + for _, volume := range volumes { + volumeName := volume.Path("name").Data().(string) + if volumeName == "vpnconfig" { + vpnConfigVolume = volume + break + } + } + suite.Assertions.NotEmpty(vpnConfigVolume) + + }) + } +} diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index 7f094edc0c5..141d7cba579 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -613,3 +613,260 @@ resources: {} # requests: # cpu: 100m # memory: 128Mi + +# -- The common chart supports several add-ons. These can be configured under this key. +# @default -- See below +addons: + + # -- The common chart supports adding a VPN add-on. It can be configured under this key. + # For more info, check out [our docs](http://docs.k8s-at-home.com/our-helm-charts/common-library-add-ons/#wireguard-vpn) + # @default -- See values.yaml + vpn: + # -- Enable running a VPN in the pod to route traffic through a VPN + enabled: false + + # -- Specify the VPN type. Valid options are openvpn or wireguard + type: openvpn + + # -- OpenVPN specific configuration + # @default -- See below + openvpn: + image: + # -- Specify the openvpn client image + repository: dperson/openvpn-client + # -- Specify the openvpn client image tag + tag: latest + # -- Specify the openvpn client image pull policy + pullPolicy: IfNotPresent + + # -- Credentials to connect to the VPN Service (used with -a) + auth: # "user;password" + # -- Optionally specify an existing secret that contains the credentials. + # Credentials should be stored under the `VPN_AUTH` key + authSecret: # my-vpn-secret + + # -- WireGuard specific configuration + # @default -- See below + wireguard: + image: + # -- Specify the WireGuard image + repository: ghcr.io/k8s-at-home/wireguard + # -- Specify the WireGuard image tag + tag: v1.0.20210424 + # -- Specify the WireGuard image pull policy + pullPolicy: IfNotPresent + + # -- Set the VPN container securityContext + # @default -- See values.yaml + securityContext: + capabilities: + add: + - NET_ADMIN + - SYS_MODULE + + # -- All variables specified here will be added to the vpn sidecar container + # See the documentation of the VPN image for all config values + env: {} + # TZ: UTC + + # -- Provide a customized vpn configuration file to be used by the VPN. + configFile: # |- + # Some Example Config + # remote greatvpnhost.com 8888 + # auth-user-pass + # Cipher AES + + # -- Reference an existing secret that contains the VPN configuration file + # The chart expects it to be present under the `vpnConfigfile` key. + configFileSecret: + + # -- Provide custom up/down scripts that can be used by the vpn configuration. + # @default -- See values.yaml + scripts: + up: # |- + # #!/bin/bash + # echo "connected" > /shared/vpnstatus + down: # |- + # #!/bin/bash + # echo "disconnected" > /shared/vpnstatus + + additionalVolumeMounts: [] + + # -- Optionally specify a livenessProbe, e.g. to check if the connection is still + # being protected by the VPN + livenessProbe: {} + # exec: + # command: + # - sh + # - -c + # - if [ $(curl -s https://ipinfo.io/country) == 'US' ]; then exit 0; else exit $?; fi + # initialDelaySeconds: 30 + # periodSeconds: 60 + # failureThreshold: 1 + + # If set to true, will deploy a network policy that blocks all outbound + # traffic except traffic specified as allowed + networkPolicy: + enabled: false + + # The egress configuration for your network policy, All outbound traffic + # From the pod will be blocked unless specified here. Your cluster must + # have a CNI that supports network policies (Canal, Calico, etc...) + # https://kubernetes.io/docs/concepts/services-networking/network-policies/ + # https://github.com/ahmetb/kubernetes-network-policy-recipes + egress: + # - to: + # - ipBlock: + # cidr: 0.0.0.0/0 + # ports: + # - port: 53 + # protocol: UDP + # - port: 53 + # protocol: TCP + + # -- The common library supports adding a code-server add-on to access files. It can be configured under this key. + # For more info, check out [our docs](http://docs.k8s-at-home.com/our-helm-charts/common-library-add-ons/#code-server) + # @default -- See values.yaml + codeserver: + # -- Enable running a code-server container in the pod + enabled: false + + image: + # -- Specify the code-server image + repository: codercom/code-server + # -- Specify the code-server image tag + tag: 3.9.2 + # -- Specify the code-server image pull policy + pullPolicy: IfNotPresent + + # -- Set any environment variables for code-server here + env: {} + # TZ: UTC + + # -- Set codeserver command line arguments. + # Consider setting --user-data-dir to a persistent location to preserve code-server setting changes + args: + - --auth + - none + # - --user-data-dir + # - "/config/.vscode" + + # -- Specify a list of volumes that get mounted in the code-server container. + # At least 1 volumeMount is required! + volumeMounts: [] + # - name: config + # mountPath: /data/config + + # -- Specify the working dir that will be opened when code-server starts + # If not given, the app will default to the mountpah of the first specified volumeMount + workingDir: "" + + # -- Optionally allow access a Git repository by passing in a private SSH key + # @default -- See below + git: + # -- Raw SSH private key + deployKey: "" + # -- Base64-encoded SSH private key. When both variables are set, the raw SSH key takes precedence. + deployKeyBase64: "" + # -- Existing secret containing SSH private key + # The chart expects it to be present under the `id_rsa` key. + deployKeySecret: "" + + service: + # -- Enable a service for the code-server add-on. + enabled: true + type: ClusterIP + # Specify the default port information + ports: + codeserver: + port: 12321 + enabled: true + protocol: TCP + targetPort: codeserver + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + annotations: {} + labels: {} + + ingress: + # -- Enable an ingress for the code-server add-on. + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + - host: code.chart-example.local + paths: + - path: / + # Ignored if not kubeVersion >= 1.14-0 + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - code.chart-example.local + + securityContext: + runAsUser: 0 + + # -- The common library supports adding a promtail add-on to to access logs and ship them to loki. It can be configured under this key. + # @default -- See values.yaml + promtail: + # -- Enable running a promtail container in the pod + enabled: false + + image: + # -- Specify the promtail image + repository: grafana/promtail + # -- Specify the promtail image tag + tag: 2.2.0 + # -- Specify the promtail image pull policy + pullPolicy: IfNotPresent + + # -- Set any environment variables for promtail here + env: {} + + # -- Set promtail command line arguments + args: [] + + # -- The URL to Loki + loki: "" + + # -- The paths to logs on the volume + logs: [] + # - name: log + # path: /config/logs/*.log + + # -- Specify a list of volumes that get mounted in the promtail container. + # At least 1 volumeMount is required! + volumeMounts: [] + # - name: config + # mountPath: /config + # readOnly: true + + securityContext: + runAsUser: 0 + + # -- The common library supports adding a netshoot add-on to troubleshoot network issues within a Pod. It can be configured under this key. + # @default -- See values.yaml + netshoot: + # -- Enable running a netshoot container in the pod + enabled: false + + image: + # -- Specify the netshoot image + repository: nicolaka/netshoot + # -- Specify the netshoot image tag + tag: latest + # -- Specify the netshoot image pull policy + pullPolicy: Always + + # -- Set any environment variables for netshoot here + env: {} + + securityContext: + capabilities: + add: + - NET_ADMIN