<p>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.</p>

<p>So I defined template _cron-job.yaml</p>

<pre><code>    {{- 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 -}}
</code></pre>

<p>and now I need to create job manifest that override name and args job1.yaml</p>

<pre><code>{{- 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 }}"]
</code></pre>

<p>Is there any way to do this? I didn't find this in helm docs. I did find this <a href="https://github.com/helm/charts/tree/master/incubator/common" rel="nofollow noreferrer">https://github.com/helm/charts/tree/master/incubator/common</a> but It didn't work as well and gave me error.</p>

<p>Thanks.</p>

Georgy Gobozov
<p>Solution found</p>

<p><strong>Option 1</strong>
Use example from helm github <a href="https://github.com/helm/charts/tree/master/incubator/common" rel="nofollow noreferrer">https://github.com/helm/charts/tree/master/incubator/common</a> 
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. </p>

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

<p>_common.cronjob.yaml</p>

<pre><code>{{- 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 -}}
</code></pre>

<p>Then create job manifest(s), define values to pass to common template</p>

<p>bom-cronjob.yaml</p>

<pre><code>{{ $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) -}}
</code></pre>

<p>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.</p>
