Search code examples
templateskuberneteschartsoverridingkubernetes-helm

Helm Override common template values


First day helm user here. Trying to understand how to build common templates for k8s resources. Let's say I have 10 cron jobs within single chart, all of them different by args and names only. Today 10 full job manifests exists and 95% of manifest content is equal. I want to move common part in template and create 10 manifests where I will provide specific values for args and names.

So I defined template _cron-job.yaml

    {{- define "common.cron-job"}}
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: {{ include "costing-report.name" . }}-bom-{{ .Values.env }}
  labels:
{{ include "costing-report.labels" . | indent 4 }}
spec:
  schedule: "{{ .Values.cronjob.scheduleBom }}"
  suspend: {{ .Values.cronjob.suspendBom }}
  {{- with .Values.cronjob.concurrencyPolicy }}
  concurrencyPolicy: {{ . }}
  {{- end }}
  {{- with .Values.cronjob.failedJobsHistoryLimit }}
  failedJobsHistoryLimit: {{ . }}
  {{- end }}
  {{- with .Values.cronjob.successfulJobsHistoryLimit }}
  successfulJobsHistoryLimit: {{ . }}
  {{- end }}
  jobTemplate:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "costing-report.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      template:
        spec:
          containers:
            - name: {{ .Chart.Name }}
              image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
              imagePullPolicy: {{ .Values.image.pullPolicy }}
              args: ["--report=Bom","--email={{ .Values.configmap.service.email_bom }}"]
              env:
                - name: spring_profiles_active
                  value: "{{ .Values.env }}"
              envFrom:
                - configMapRef:
                    name: {{ include "costing-report.fullname" . }}
                - secretRef:
                    name: {{ .Values.secrets.properties }}
          restartPolicy: Never
          {{- with .Values.imagePullSecrets }}
          imagePullSecrets:
            {{- toYaml . | nindent 8 }}
          {{- end }}    
{{- end -}}

and now I need to create job manifest that override name and args job1.yaml

{{- template "common.cron-job" . -}}
??? override ???
name: {{ include "cost-report.name" . }}-job1-{{ .Values.env }}
jobTemplate:
spec:
  template:
    spec:
      containers:
        args: ["--report=Bom","--email={{ .Values.configmap.service.email_bom }}"]

Is there any way to do this? I didn't find this in helm docs. I did find this https://github.com/helm/charts/tree/master/incubator/common but It didn't work as well and gave me error.

Thanks.


Solution

  • Solution found

    Option 1 Use example from helm github https://github.com/helm/charts/tree/master/incubator/common Solution based on yaml merging and values override. Pretty flexible, allow you to define common templates and the use them to compose final k8s manifest.

    Option 2 Define common template and pass parameters with desired values. In my case it looks smth like this.

    _common.cronjob.yaml

    {{- define "common.cronjob" -}}
    {{- $root := .root -}} 
    {{- $name := .name -}} 
    {{- $schedule := .schedule -}} 
    {{- $suspend := .suspend -}} 
    {{- $args := .args -}} 
    
    apiVersion: batch/v1beta1
    kind: CronJob
    metadata:
      name: {{ $name }}
      labels:
    {{ include "costing-report.labels" $root | indent 4 }}
    spec:
      schedule: {{ $schedule }}
      suspend: {{ $suspend }}
      {{- with $root.Values.cronjob.concurrencyPolicy }}
      concurrencyPolicy: {{ . }}
      {{- end }}
      {{- with $root.Values.cronjob.failedJobsHistoryLimit }}
      failedJobsHistoryLimit: {{ . }}
      {{- end }}
      {{- with $root.Values.cronjob.successfulJobsHistoryLimit }}
      successfulJobsHistoryLimit: {{ . }}
      {{- end }}
      jobTemplate:
        metadata:
          labels:
            app.kubernetes.io/name: {{ include "costing-report.name" $root }}
            app.kubernetes.io/instance: {{ $root.Release.Name }}
        spec:
          template:
            spec:
              containers:
                - name: {{ $root.Chart.Name }}
                  image: "{{ $root.Values.image.repository }}:{{ $root.Values.image.tag }}"
                  imagePullPolicy: {{ $root.Values.image.pullPolicy }}
                  args: {{ $args }}
                  env:
                    - name: spring_profiles_active
                      value: "{{ $root.Values.env }}"
                  envFrom:
                    - configMapRef:
                        name: {{ include "costing-report.fullname" $root }}
                    - secretRef:
                        name: {{ $root.Values.secrets.properties }}
              restartPolicy: Never
              {{- with $root.Values.imagePullSecrets }}
              imagePullSecrets:
                {{- toYaml . | nindent 8 }}
              {{- end }}
    {{- end -}}
    

    Then create job manifest(s), define values to pass to common template

    bom-cronjob.yaml

    {{ $bucket := (printf "%s%s%s" "\"--bucket=ll-costing-report-" .Values.env "\"," )}}
    {{ $email := (printf "%s%s%s" "\"--email=" .Values.configmap.service.email_bom "\"") }}
    {{ $args := (list "\"--report=Bom\"," "\"--reportType=load\"," "\"--source=bamboorose\"," $bucket "\"--table=COSTING_BOM\"," "\"--ignoreLines=1\"," "\"--truncate=true\"," $email )}}
    {{ $name := (printf "%s%s" "costing-report.name-bom-" .Values.env )}}
    {{- template "common.cronjob" (dict "root" . "name" $name "schedule" .Values.cronjob.scheduleBom "suspend" .Values.cronjob.suspendBom "args" $args) -}}
    

    Last line do the trick. Trick is that you can pass only single argument to template, in my case it's dictionary with all values that I need on template side. You can omit defining template variables and use dict values right away. Please note that I pass root context (scope) as "root" and prefix . with "root" in template.