<h3>Background</h3>

<p>I am using TZCronJob to run cronjobs with timezones in Kubernetes. A sample <code>cronjob.yaml</code> might look like the following (as per the <a href="https://github.com/hiddeco/cronjobber" rel="nofollow noreferrer">cronjobber docs</a>). Note the timezone specified, the schedule, and <code>kind=TZCronJob</code>:</p>

<pre><code>apiVersion: cronjobber.hidde.co/v1alpha1
kind: TZCronJob
metadata:
  name: hello
spec:
  schedule: "05 09 * * *"
  timezone: "Europe/Amsterdam"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo "Hello, World!"
          restartPolicy: OnFailure
</code></pre>

<p>Nrmally, with any old cronjob in Kubernetes, you can run <code>kubectl create job test-job --from=tzcronjob/name_of_my_cronjob</code>, as per the <a href="https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-job-em-" rel="nofollow noreferrer">kubectl create cronjob docs</a>. </p>

<h3>Error</h3>

<p>However, when I try to run it with <code>kubectl create job test-job --from=tzcronjob/name_of_my_cronjob</code> (switching the from command to <code>--from=tzcronjob/</code>) I get:</p>

<blockquote>
  <p><code>error: from must be an existing cronjob: no kind "TZCronJob" is registered for version "cronjobber.hidde.co/v1alpha1" in scheme "k8s.io/kubernetes/pkg/kubectl/scheme/scheme.go:28"</code></p>
</blockquote>

<p>When I try to take a peek at <a href="https://kubernetes.io/kubernetes/pkg/kubectl/scheme/scheme.go:28" rel="nofollow noreferrer">https://kubernetes.io/kubernetes/pkg/kubectl/scheme/scheme.go:28</a> I get 404, not found.</p>

<p>This almost worked, but to no avail: </p>

<pre><code>kubectl create job test-job-name-v1 --image=tzcronjob/name_of_image
</code></pre>

<p>How can I create a new one-off job from my chart definition?</p>

<p>In <a href="https://helm.sh/docs/" rel="nofollow noreferrer">Helm</a> there are mechanisms called <a href="https://helm.sh/docs/developing_charts/#hooks" rel="nofollow noreferrer">Hooks</a>.</p>

<p>Helm provides a hook mechanism to allow chart developers to intervene at certain points in a release’s life cycle. For example, you can use hooks to:</p>

<ul>
<li><p>Load a ConfigMap or Secret during install before any other charts are
loaded</p></li>
<li><p>Execute a Job to back up a database before installing a new chart,
and then execute a second job after the upgrade in order to restore
data</p></li>
<li><p>Run a Job before deleting a release to gracefully take a service out
of rotation before removing it.</p></li>
</ul>

<p>Hooks work like regular templates, but they have special annotations that cause Helm to utilize them differently. In this section, we cover the basic usage pattern for hooks.</p>

<p>Hooks are declared as an annotation in the metadata section of a manifest:</p>

<pre><code>apiVersion: ...
kind: ....
metadata:
  annotations:
    "helm.sh/hook": "pre-install"
</code></pre>

<p>If the resources is a Job kind, Tiller will wait until the job successfully runs to completion. And if the job fails, the release will fail. This is a blocking operation, so the Helm client will pause while the Job is run.</p>

<p><strong>HOW TO WRITE HOOKS:</strong></p>

<p>Hooks are just Kubernetes manifest files with special annotations in the metadata section. Because they are template files, you can use all of the normal template features, including <strong>reading .Values</strong>, .<strong>Release</strong>, and <strong>.Template</strong>.</p>

<p>For example, this template, stored in templates/post-install-job.yaml, declares a job to be run on post-install:</p>

<pre><code>apiVersion: batch/v1
kind: Job
metadata:
  name: "{{.Release.Name}}"
  labels:
    app.kubernetes.io/managed-by: {{.Release.Service | quote }}
    app.kubernetes.io/instance: {{.Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}"
  annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{.Release.Name}}"
      labels:
        app.kubernetes.io/managed-by: {{.Release.Service | quote }}
        app.kubernetes.io/instance: {{.Release.Name | quote }}
        helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job
        image: "alpine:3.3"
        command: ["/bin/sleep","{{default "10" .Values.sleepyTime}}"]
</code></pre>

<p>What makes this template a hook is the annotation:</p>

<pre><code>  annotations:
    "helm.sh/hook": post-install
</code></pre>
