Curl commands on helm chart install/upgrade
Tags: docker, kubernetes, devops, architecture
Published: 2021-02-27 21:51:50

Deploying an app with Helm and Kubernetes is great but making it possible to fire a confetti cannon (or anything else you want to do with a curl call) when deploying the app is even better!

>####The challenge
>Perform a curl call on every install/update of a helm chart.

<!-- -->
>####The tools
>Kubernetes, Helm, Confetti cannon (optional)

###Aaand go!
Ok, we’re not actually going to fire a confetti cannon, disappointing I know and I'm sorry. The actual use case is making a CURL call when a Helm chart gets deployed.
 
####Kubernetes
In order to get this to work some sort of container must be deployed alongside the rest of the chart and after some research I ended up with the [curlimages/curl](https://hub.docker.com/r/curlimages/curl) container.

Now it’s time to create the Kubernetes workload. After a quick scan of [the workloads](https://kubernetes.io/docs/concepts/workloads/) of Kubernetes the [job workload](https://kubernetes.io/docs/concepts/workloads/controllers/job/) is definitely the way to go here. So the setup so far becomes:

```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-curl-confetti
spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: job-curl-confetti
          image: curlimages/curl
          command: [ 'sh', '-c']
          args: <curl command here>
```
This is a fine way to start the job and perform a CURL call but there are still some issues to tackle like cleaning up the job when it is done and running the job on an upgrade.

####Helm
This is where Helm comes into action. Helm has a cool option for exactly the issues we're currently running in to named [chart hooks](https://helm.sh/docs/topics/charts_hooks/). These hooks can be used to deploy certain Kubernetes workloads and also come with a hook-deletion-policy which can be extremely useful.

In this case we're going to use the post-install and post-upgrade hooks because we want our Job to run immediately after an install or upgrade. This is achieved by the following changes to the job:

```yaml
#apiVersion: batch/v1
#kind: Job
metadata:
#  name: job-curl-confetti
  annotations:
    "helm.sh/hook": post-install,post-upgrade
    "helm.sh/hook-delete-policy": before-hook-creation
#spec:
#  template:
#    spec:
#      restartPolicy: OnFailure
#      containers:
#        - name: job-curl-confetti
#          image: curlimages/curl
#          command: [ 'sh', '-c']
#          args: <curl command here>
```
 
####Developer joy (optional)
> Not really optional if you love the job

Everything works! But why stop here, why not try to make the chart more accessible for other developers (secretly making it easier to implement the confetti cannon after all). Helm is the right tool for this, let’s make Helm read all files in a directory and create a CURL job executing the curl call in each one of them.

I'm not going into detail about the implementation of this, that is something for a next blogpost about Helm, but this is the code I eventually ended up with.

```yaml
{{- range $path, $bytes := .Files.Glob "jobs/curl/**" }}
{{- $name := base (dir $path) }}
apiVersion: batch/v1
kind: Job
metadata:
  name: job-curl-{{$name}}
  annotations:
    "helm.sh/hook": post-install,post-upgrade
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: job-curl-{{$name}}
          image: curlimages/curl
          command: [ 'sh', '-c']
          args:
            - |-
{{ tpl ($.Files.Get $path) $ | indent  14 }}
---
{{- end }}
``` 
This helm templates takes all the files in the jobs/curl folder and generates a job for each of them using the helm tpl function so variables form the values file can be used inside the curl call.

I'm actually pretty proud of it and love the extra mile I put into it. Please let me know what you think!