1
votes

I have multiple sucharts with applications and a parent chart that will deploy them.

All subcharts have the same manifests for the underlying application. Therefore I decided to create a library and put general variables from subcharts in it.

Example from lib:

{{- define "app.connect.common.release.common_libs.servicetemplate" -}}  
apiVersion: v1
kind: Service
metadata:
  labels:
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
  name: {{ .Values.application.name }}-service
  namespace: {{ .Values.global.environment.namespace }}
spec:
  type: LoadBalancer
  ports:
    - name: https
      port: 443
      targetPort: 8080
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app: {{ .Values.application.name }}
status:
  loadBalancer: {}
{{- end }}

I declared a dependency in Chart.yaml and executed helm dep up. Then in my subchart I'm importing this template. But when I'm trying to run --dry-run on parent chart I'm receiving the following error:

Error: template: app.connect.common.release/charts/app.connect.common.release.chtmgr/templates/service.yaml:1:4: executing "app.connect.common.release/charts/app.connect.common.release.chtmgr/templates/service.yaml" at <include "app.connect.common.release.common_libs.servicetemplate" .>: error calling include: template: app.connect.common.release/charts/app.connect.common.release.chtmgr/charts/app.connect.common.release.common_libs/templates/_helpers.tpl:169:18: executing "app.connect.common.release.common_libs.servicetemplate" at <.Values.application.name>: nil pointer evaluating interface {}.name

My values values.yaml in the subchart:

application:
  name: chtmgr-api
  image: cht-mgr-api

The same error with named template.

Is it possible to put general values from subchart in parent template(example _helper.tpl) and import it in subchart?

If not, how do you implement this?

I've checked a lot of resources but still don't have an idea am I going in the right direction.

2
Push Minimal, Reproducible Example to github repo and provide a link to it. I dont really want to guess whats wrong and would rather see the complete (not)working example.Matt
it's a private repo therefore can't share this(DavidGreen55
Just create a new one with minimal example reproducing the issueMatt
gitlab.com/spheal/examples/-/tree/master/helm/helm To see the error just run: helm template --debug --dry-run ibext.connect.common.releaseDavidGreen55

2 Answers

0
votes

The Helm template define action creates a "function". It implicitly takes a single "parameter", using the special variable name ., and .Values is actually a lookup in .. It does not "capture" .Values at the point where it is defined; it uses the Values property of the parameter that's passed to it.

This means the template will behave differently when it's called in different contexts. As the Helm documentation on Subcharts and Global Variables describes, when executing the subchart, the top-level . parameter will have its Values replaced by the subchart's key in the primary values.

There's three ways to work around this:

  1. If you're using Helm 3, you can directly import a value from the subchart into the parent. (I'm not clear what version of Helm exactly this was added, or if the syntax works in a separate requirements.yaml file.) Declare the subchart dependency in your Chart.yaml as

    dependencies:
       - name: subchart
         import-values:
           - child: application
             parent: application
    

    and the template you show should work unmodified.

    (There's a more involved path that involves the subchart explicitly exporting values to the parent. I'm not sure if this is that useful to you: the paths will still be different in the two charts, and in any case Helm values can't contain computed values.)

  2. You already use .Values.global in your example; this will have the same value in the parent chart and all included charts.

    #                vvvvvv  inserted "global" here
    name: {{ .Values.global.application.name }}-service
    namespace: {{ .Values.global.environment.namespace }}
    
  3. You can also use template logic to try to look in more places for the application dictionary. This will only work from the parent chart and the subchart proper and not any other sibling charts; I believe it will also only work if the configuration is embedded in the parent chart's values.yaml or an external helm install -f values file, but won't find content in the included chart's values.yaml.

    {{/* Get the subchart configuration, or an empty dict (assuming we're in the parent) */}}
    {{- $subchart := .Values.subchart | default dict -}}
    {{/* Find the application values (assuming first we're in the subchart) */}}
    {{- $application := .Values.application | default $subchart.application | default dict -}}
    {{/* Then use it */}}
    name: {{ $application.name }}-service
    

    This logic sets the variable $application, normally, to .Values.application. If that's not set (you're in the parent chart) then it in effect looks up .Values.subchart.application, and if that's not available either then it uses an empty dictionary. This is (again, using programming terminology) eagerly evaluated – even if you're not falling back to the default, Helm will always look up .Values.subchart – so we use a second variable to have the .Values.subchart, or an empty dict (if you're in the subchart). In both cases looking up a nonexistent key in an empty dict isn't an error but looking up on an unset value is.

0
votes

Found a solution. Problem was related to the chart/template names all of them include '.' in the names what causes problem. Don't include dots in your templates/charts names. Example how not to do: "ibext.common.connect.etc".

My assumption

I'm quite newbie in helm and my assumption that helm when template engine is looking in the subchart it goes through the following way to find variables .Values.subchartName in my case it was .Values.ibext.common.connect.etc So when it faced with .Values.ibext it can't understand what it is(but helm doesn't show anything).

But this is only my assumption. If someone there understands the behaviour of template engine in this case please reveal the secret.