helmfile icon indicating copy to clipboard operation
helmfile copied to clipboard

"prepare" hook is not executed before apply command

Open AbbasHallal opened this issue 3 years ago • 6 comments

I have a use case where I need to avoid hardcoding the default serviceaccount token. This value is declared in values.yaml and I am referring it in my release. My logic is to execute a script via a Prepare hook however I understand that even this hook is triggered before the release, the apply command still saves a state first before where the kubernetesAuthSecret is still XXXXXX, which is before the script execution. Once the release is installed, I can check the values.yaml and I can see that the new token updated but I have the XXXXXX in my cluster. Steps to reproduce:

 values:
    - environment: poc
    - namespace: myns
    - kubernetesAuthSecret: XXXXXX
- name: "{{ .Values.releaseName }}-cert"
  chart: incubator/raw
  version: 0.2.5
  namespace: "{{ .Values.namespace }}"
  hooks:
   - events: ["prepare"]
     showlogs: true
     command: "../../../scripts/getKubernetesAuthSecret.sh"
     args: ["{{ .Values.namespace }}","{{ .Environment.Name }}"]`
#!/bin/bash
ns=$1
env=$2
kubectl get namespace $ns 2> /dev/null
if [ "$?" -eq 0 ]
then
   token=$(kubectl get serviceaccounts default -n $ns -ojson | jq -r '.secrets | .[0].name')
   sed -i "/$env/,/kubernetesAuthSecret/s/kubernetesAuthSecret:.*/kubernetesAuthSecret: "$token"/" ./helmfile.yaml
``
else
   echo "$ns doesn't exist, consider changing or creating it."
 fi

command:

helmfile -e poc --debug -i -f helmfile.yaml apply 

AbbasHallal avatar Jan 26 '22 13:01 AbbasHallal

@AbbasHallal Hey! Would you mind completing your example so that I can reproduce it?

Two things:

  • You seem to be running sed against ./helmfile.yaml, but it should be values.yaml if I took your description of This value is declared in values.yaml and I am referring it in my release. as the truth?
  • Your release is missing values section at all. should't it be something like the below?
- name: "{{ .Values.releaseName }}-cert"
  chart: incubator/raw
  version: 0.2.5
  namespace: "{{ .Values.namespace }}"
  hooks:
   - events: ["prepare"]
     showlogs: true
     command: "../../../scripts/getKubernetesAuthSecret.sh"
     args: ["{{ .Values.namespace }}","{{ .Environment.Name }}"]`
  # Didn't you miss this?
  values:
  - values.yaml

mumoshu avatar Jan 26 '22 23:01 mumoshu

Ok will paste for you my exact config so that you will be able to reproduce because there's something missing and it created confusion helmfile.yaml:

environments:
  poc:
    values:
    - environment: poc
    - namespace: myns
    - releaseName: myrelease
    - kubernetesAuthSecret: xxxxx
    secrets:
    - secrets.yaml
 {{ tpl (readFile "../../bases/cert.yaml") . }}

script:

#!/bin/bash
ns=$1
env=$2
kubectl get namespace $ns 2> /dev/null
if [ "$?" -eq 0 ]
then
  token=$(oc get serviceaccounts default -n $ns -ojson | jq -r '.secrets | .[0].name')
  sed -i "/$env/,/kubernetesAuthSecret/s/kubernetesAuthSecret:.*/kubernetesAuthSecret: "$token"/" ./helmfile.yaml

else
  echo "$ns doesn't exist, consider changing or creating it."
fi

cert.yaml:

- name: "{{ .Values.releaseName }}-cert"
  chart: incubator/raw
  version: 0.2.5
  namespace: "{{ .Values.namespace }}"
  hooks:
   - events: ["presync"]
     showlogs: true
     command: "../../../scripts/getKubernetesAuthSecret.sh"
     args: ["{{ .Values.namespace }}","{{ .Environment.Name }}"]
  labels:
    app: cert
  values:
  - resources:
     - kind: Secret
      apiVersion: v1
      metadata:
        name: secret
      data:
        kubernetesAuthSecret: {{ .Values.kubernetesAuthSecret | b64enc  }}
      type: Opaque

So in the above scenario, I want to change kubernetesAuthSecret from xxxxx which is a random variable and varies among different namespaces to the value of the current namespace where the release is installed. It's not working through the prepare hook. I am getting the xxxx as value in the secret.Lets say the release was installed and I checked the helmfile.yaml again, the kubernetesAuthSecret will be default-token-fdwcc. As far as my understanding, the apply command is saving an initial state and ignoring what is called after it.

AbbasHallal avatar Jan 27 '22 13:01 AbbasHallal

@mumoshu Hello, Were my description clear so you can reproduce it?

AbbasHallal avatar Feb 02 '22 08:02 AbbasHallal

@AbbasHallal Thanks. But I'm pretty confused! Your getKubernetesAuthSecret script seems to be trying to modify the helmfile.yaml that called it, and you want helmfile to magically reload the helmfile.yaml after the hook is called, right? Helmfile won't work that way..

mumoshu avatar Feb 02 '22 08:02 mumoshu

@mumoshu I thought the prepare hook would be able to modify values is helmfile.yaml but seems not logical in this way I am doing it. You're right, trying to edit a helmfile by a hook that was created by it.

AbbasHallal avatar Feb 02 '22 09:02 AbbasHallal

@AbbasHallal prepare hook was originally added to dynamically generate or modify the chart. I have not tried myself but you could exploit it to dynamically generate a chart values file, I guess.

releases:
- name: ...
  values:
  - generateme.yaml

and use the hook to update the generateme.yaml.

mumoshu avatar Feb 02 '22 09:02 mumoshu