nil pointer evaluating interface when installing a helm chart
Asked Answered
P

3

11

I'm trying to install a chart to my cluster but I'm getting a error

Error: template: go-api/templates/deployment.yaml:18:24: executing "go-api/templates/deployment.yaml" 
at <.Values.deployment.container.name>: nil pointer evaluating interface {}.name

However I executed the same commands for another 2 charts and it worked fine.

The template file I'm using is this:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: {{ .Values.namespace}}
  labels: {{- include "chart.labels" . | nindent 4 }}
  name: {{ .Values.deployment.name}}
spec:
  replicas: {{ .Values.deployment.replicas}}
  selector:
    matchLabels: {{ include "chart.matchLabels" . | nindent 6 }}
  template:
    metadata:
      labels: 
        app.kubernetes.io/name: {{ template "chart.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      containers:
      - name: {{ .Values.deployment.container.name }}
        image: {{ .Values.deployment.container.image }}
        imagePullPolicy: Never
        ports:
          - containerPort: {{ .Values.deployment.container.port }}

Premonish answered 19/1, 2021 at 11:47 Comment(2)
I had this problem where linting succeeded (false positive) on macOS (development machine), but on Linux (in CI) it failed with this error. I wondered why it was failing in CI, but perhaps there is a bug with the macOS linter.Promethean
If deployment.container is optional then take a look on the answers on how to deal with the optional nested variables.Indeed
P
14

This can happen if the Helm values you're using to install don't have that particular block:

namespace: default
deployment:
  name: a-name
  replicas: 1
  # but no container:

To avoid this specific error in the template code, it's useful to pick out the parent dictionary into a variable; then if the parent is totally absent, you can decide what to do about it. This technique is a little more useful if there are optional fields or sensible defaults:

{{- $deployment := .Values.deployment | default dict }}
metadata:
  name: {{ $deployment.name | default (include "chart.fullname" .) }}
spec:
{{- if $deployment.replicas }}
  replicas: {{ $deployment.replicas }}
{{- end }}

If you really can't work without the value, Helm has an undocumented required function that can print a more specific error message.

{{- $deployment := .Values.deployment | required "deployment configuration is required" }}

(My experience has been that required values are somewhat frustrating as an end user, particularly if you're trying to run someone else's chart, and I would try to avoid this if possible.)

Given what you show, it's also possible you're making the chart too configurable. The container name, for example, is mostly a detail that only appears if you have a multi-container pod (or are using Istio); the container port is a fixed attribute of the image you're running. You can safely fix these values in the Helm template file, and then it's reasonable to provide defaults for things like the replica count or image name (consider setting the repository name, image name, and tag as separate variables).

{{- $deployment := .Values.deployment | default dict }}
{{- $registry := $deployment.registry | default "docker.io" }}
{{- $image := $deployment.image | default "my/image" }}
{{- $tag := $deployment.tag | default "latest" }}
containers:
  - name: app # fixed
    image: {{ printf "%s/%s:%s" $registry $image $tag }}
{{- with .Values.imagePullPolicy }}
    imagePullPolicy: {{ . }}
{{- end }}
    ports:
      - name: http
        containerPort: 3000 # fixed
Patellate answered 19/1, 2021 at 12:37 Comment(0)
A
11

If the value is defined in your values file, and you're still getting the error then the issue could be due to accessing that value inside range or similar function which changes the context.

For example, to use a named template mySuffix that has been defined with .Values and using that inside range with template function, we need to provide $ to the template function instead of the usual .:

{{- define "mySuffix" -}}
{{- .Values.suffix }}
{{- end }}
...
{{- range .Values.listOfValues }}
  echo {{ template "mySuffix" $ }}
{{- end }}
Aloe answered 3/2, 2022 at 16:30 Comment(2)
I've always thought that go templates were ugly and not easy to manage whitespaces. Now I really hate them :(Quantifier
Another option is to just add $ when operating within the range. E.g. echo {{ $.Values.suffix }}. I still can't believe that it was an acceptable syntax choice in Go templates for range and other functions to modify the context like thisReceptive
S
0

Check if your Values.yaml file name is too big? And make sure there aren't many characters in desribing a value. This resolved my issue.

Sooksoon answered 8/2 at 19:52 Comment(1)
Can you provide more details? What is “too big” for a Values.yaml file? And what are too “many characters” too many “in describing a value”?Monotint

© 2022 - 2024 — McMap. All rights reserved.