helm-controller icon indicating copy to clipboard operation
helm-controller copied to clipboard

helm-controller does not accept if code that helm did and throws already defined error

Open jprecuch opened this issue 2 years ago • 3 comments

We've been using until now little messy but code that worked nicely with helm (--dry-run or upgrade/install)

Example of not-accepted code:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nfsaas-configmap
  namespace: {{ .Release.Namespace }}
data:
  sdeVersion: "0.0.0"
  logLevel: "{{ .Values.dev.logLevel }}"
  zapiLogLevel: "{{ .Values.dev.zapiLogLevel }}"
  logSQL: "{{ .Values.dev.logSQL }}"
{{- if eq .Values.global.hyperscaler "azure" }}
  sdeVersion: "2.0.0"
  logLevel: "{{ .Values.azure.logLevel }}"
  zapiLogLevel: "{{ .Values.azure.zapiLogLevel }}"
  logSQL: "{{ .Values.azure.logSQL }}"
{{- else if eq .Values.global.hyperscaler "gcp" }}
  sdeVersion: "1.0.0"
  logLevel: "{{ .Values.gcp.logLevel }}"
  zapiLogLevel: "{{ .Values.gcp.zapiLogLevel }}"
  logSQL: "{{ .Values.gcp.logSQL }}"
{{- else if eq .Values.global.hyperscaler "aws" }}
  sdeVersion: "3.0.0"
  logLevel: "{{ .Values.aws.logLevel }}"
  zapiLogLevel: "{{ .Values.aws.zapiLogLevel }}"
  logSQL: "{{ .Values.aws.logSQL }}"
{{- end }}

Yes looking at this it seems there will be doubled values if we specify one of hyperscaler which is in if code. However this was properly accepted by helm and always "hyperscaler if code" took over. helm-controller however does not like this and will end with doubled values

{"level":"error","ts":"2022-02-28T15:07:23.262Z","logger":"controller.helmrelease","msg":"Reconciler error","reconciler group":"helm.toolkit.fluxcd.io","reconciler kind":"HelmRelease","name":"sde","namespace":"sde","error":"Helm upgrade failed: error while running post render on files: map[string]interface {}(nil): yaml: unmarshal errors:\n  line 16: mapping key \"sdeVersion\" already defined at line 11\n  line 17: mapping key \"logLevel\" already defined at line 12\n  line 18: mapping key \"zapiLogLevel\" already defined at line 13\n  line 19: mapping key \"logSQL\" already defined at line 14"}

Is there some easy fix for this or just adjust our helmchart to proper way? helm-controller accepts for example:

data:
{{- if eq .Values.global.hyperscaler "dev" }}
  sdeVersion: "0.0.0"
  logLevel: "{{ .Values.dev.logLevel }}"
  zapiLogLevel: "{{ .Values.dev.zapiLogLevel }}"
  logSQL: "{{ .Values.dev.logSQL }}"
{{- else if eq .Values.global.hyperscaler "azure" }}
  sdeVersion: "2.0.0"
  logLevel: "{{ .Values.azure.logLevel }}"
  zapiLogLevel: "{{ .Values.azure.zapiLogLevel }}"
  logSQL: "{{ .Values.azure.logSQL }}"
{{- else if eq .Values.global.hyperscaler "gcp" }}
  sdeVersion: "1.0.0"
  logLevel: "{{ .Values.gcp.logLevel }}"
  zapiLogLevel: "{{ .Values.gcp.zapiLogLevel }}"
  logSQL: "{{ .Values.gcp.logSQL }}"
{{- else if eq .Values.global.hyperscaler "aws" }}
  sdeVersion: "3.0.0"
  logLevel: "{{ .Values.aws.logLevel }}"
  zapiLogLevel: "{{ .Values.aws.zapiLogLevel }}"
  logSQL: "{{ .Values.aws.logSQL }}"
{{- end }}

jprecuch avatar Feb 28 '22 15:02 jprecuch

It looks like the default values that you wanted to set should be placed in an "Else" condition, and you already found that... instead of just freely floating above where they can be shadowed if any match is found in your if conditions.

I don't know if there should be a behavior difference between Helm Controller and Helm itself, but there is one here

mapping key \"sdeVersion\" already defined

Helm itself will not error out this way, but Helm Controller types and lints the data before sending it to the Kubernetes API, to check that it is valid YAML. I think of this as a feature.

The error says what the problem is: Helm Controller will only allow this value to be defined once, we render the template into data structures and pass them directly on to Kubernetes. Helm itself doesn't care about these default values I think, because it must be passing them through a stream/string interface, where a YAML parser that doesn't care about shadowing is used.

kingdonb avatar Apr 02 '22 03:04 kingdonb

@kingdonb I hit the same issue while i don't have any duplicates, it's mainly with the official kubernetes-dashboard helm chart when i define this annotation in the values

    ingress:
      annotations:
        nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

and the error i get from helm-controller

 Helm upgrade failed: error while running post render on files: map[string]interface {}(nil): yaml: unmarshal errors:
  line 36: mapping key "nginx.ingress.kubernetes.io/backend-protocol" already defined at line 30

It's only defined one time so I am not sure what is exactly the issue.

mo-saeed avatar May 25 '22 13:05 mo-saeed

@kingdonb I hit the same issue while i don't have any duplicates, it's mainly with the official kubernetes-dashboard helm chart when i define this annotation in the values

    ingress:
      annotations:
        nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

and the error i get from helm-controller

 Helm upgrade failed: error while running post render on files: map[string]interface {}(nil): yaml: unmarshal errors:
  line 36: mapping key "nginx.ingress.kubernetes.io/backend-protocol" already defined at line 30

It's only defined one time so I am not sure what is exactly the issue.

ok found the issue, it's issue with the helm chart of the dashboard as they defined the annotation hardcoded https://github.com/kubernetes/dashboard/blob/master/aio/deploy/helm-chart/kubernetes-dashboard/templates/ingress.yaml#L37 so when i add it in my code the controller detects it 2 times. Thanks

mo-saeed avatar May 25 '22 13:05 mo-saeed