Comprehensive toolkit for generating best practice Helm charts and resources following current standards and conventions. Use this skill when creating new Helm charts, implementing Helm templates, or building Helm projects from scratch.
Overall
score
93%
Does it follow best practices?
Validation for skill structure
Comprehensive guide to Helm template functions with practical examples.
Fails template rendering if a value is not provided.
# Syntax
{{ required "error message" .Values.some.value }}
# Example
image: {{ required "image.repository is required!" .Values.image.repository }}
tag: {{ required "image.tag is required!" .Values.image.tag }}When to use:
Provides a default value if the value is empty or undefined.
# Syntax
{{ .Values.some.value | default "default-value" }}
# Examples
replicas: {{ .Values.replicaCount | default 1 }}
image:
tag: {{ .Values.image.tag | default .Chart.AppVersion }}
pullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}
# Computed defaults
serviceName: {{ .Values.service.name | default (printf "%s-svc" (include "mychart.fullname" .)) }}When to use:
Wraps a value in double quotes, escaping special characters.
# Syntax
{{ .Values.some.value | quote }}
# Examples
env:
- name: DATABASE_URL
value: {{ .Values.database.url | quote }}
- name: API_KEY
value: {{ .Values.api.key | quote }}
# With pipeline
image: {{ .Values.image.repository | default "nginx" | quote }}When to use:
Includes a named template and allows piping the result to other functions.
# Syntax
{{ include "template-name" context }}
# Examples
metadata:
labels:
{{- include "mychart.labels" . | nindent 4 }}
# With modifications
annotations:
checksum: {{ include "mychart.config" . | sha256sum }}When to use:
include over template for better composabilityIncludes a named template (cannot be piped).
# Syntax
{{ template "template-name" context }}
# Example
metadata:
labels:
{{ template "mychart.labels" . }}When to use:
include for new code)Converts an object to YAML format.
# Syntax
{{ .Values.some.object | toYaml }}
# Examples
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 2 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 2 }}
{{- end }}When to use:
Parses a YAML string into an object.
# Syntax
{{ .Values.yamlString | fromYaml }}
# Example
{{- $config := .Values.configYaml | fromYaml }}
{{- if $config.enabled }}
# Use $config values
{{- end }}When to use:
Evaluates a string as a Go template.
# Syntax
{{ tpl .Values.templateString . }}
# Example values.yaml
config:
message: "Release: {{ .Release.Name }}"
# Template
data:
message: {{ tpl .Values.config.message . }}When to use:
Adds newline and indentation, or just indentation.
# nindent - newline + indent
metadata:
labels:
{{- include "mychart.labels" . | nindent 4 }}
# indent - just indent (no newline)
data:
config: |
{{ .Values.config | indent 4 }}When to use:
nindent for YAML blocks after keysindent for multi-line string contentFormats a string using Go's fmt.Sprintf syntax.
# Syntax
{{ printf "format" arg1 arg2 }}
# Examples
name: {{ printf "%s-%s" .Release.Name .Chart.Name }}
label: {{ printf "app.kubernetes.io/name: %s" .Chart.Name }}When to use:
{{- if .Values.ingress.enabled }}
# Ingress resource
{{- end }}
{{- if eq .Values.service.type "LoadBalancer" }}
# LoadBalancer config
{{- else if eq .Values.service.type "NodePort" }}
# NodePort config
{{- else }}
# Default config
{{- end }}{{- if and .Values.enabled (not .Values.debug) }}
# Enabled and not debug
{{- end }}
{{- if or .Values.useSSL .Values.production }}
# SSL or production
{{- end }}{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 2 }}
{{- end }}Note: Inside with, . refers to the scoped value. Use $ for root context.
eq - Equal: {{ if eq .Values.env "prod" }}ne - Not equal: {{ if ne .Values.replicas 1 }}lt - Less than: {{ if lt .Values.replicas 3 }}le - Less or equal: {{ if le .Values.replicas 5 }}gt - Greater than: {{ if gt .Values.replicas 1 }}ge - Greater or equal: {{ if ge .Values.replicas 3 }}# upper / lower
name: {{ .Values.name | upper }}
label: {{ .Values.env | lower }}
# trim / trimSuffix / trimPrefix
name: {{ .Values.name | trim }}
name: {{ .Values.name | trimSuffix "-" }}
# trunc - truncate to length
name: {{ .Values.longName | trunc 63 | trimSuffix "-" }}
# replace
chart: {{ .Chart.Name | replace "." "-" }}
# contains
{{- if contains "prod" .Values.environment }}
# Production settings
{{- end }}# hasPrefix / hasSuffix
{{- if hasPrefix "prod-" .Values.name }}
# empty - test if value is empty
{{- if not (empty .Values.optional) }}{{- $myList := list "item1" "item2" "item3" }}{{- $list := list "a" "b" }}
{{- $list = append $list "c" }}
{{- $list = prepend $list "z" }}first: {{ first .Values.items }}
last: {{ last .Values.items }}{{- if has "production" .Values.environments }}{{- $myDict := dict "key1" "value1" "key2" "value2" }}
{{- include "mychart.helper" $myDict }}{{- $_ := set .Values "newKey" "newValue" }}
{{- $_ := unset .Values "oldKey" }}{{- if hasKey .Values "optional" }}{{- $merged := merge .Values.override .Values.defaults }}{{- $type := typeOf .Values.someValue }}port: {{ .Values.port | int }}
cpu: {{ .Values.cpu | toString }}annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}data:
password: {{ .Values.password | b64enc }}annotations:
timestamp: {{ now | date "2006-01-02T15:04:05Z07:00" }}date: {{ now | date "2006-01-02" }}{{- if regexMatch "^prod-" .Values.name }}
{{- $version := .Values.image.tag | regexFind "[0-9]+" }}
label: {{ .Values.name | regexReplaceAll "[^a-z0-9-]" "-" }}# Range over list
{{- range .Values.items }}
- {{ . }}
{{- end }}
# Range over map
{{- range $key, $value := .Values.config }}
{{ $key }}: {{ $value }}
{{- end }}
# Range with index
{{- range $index, $item := .Values.items }}
{{ $index }}: {{ $item }}
{{- end }}Query existing Kubernetes resources (use with caution).
{{- $secret := lookup "v1" "Secret" .Release.Namespace "my-secret" }}
{{- if $secret }}
# Secret exists
data:
password: {{ $secret.data.password }}
{{- else }}
# Create new secret
{{- end }}⚠️ Warning: lookup queries the cluster, which:
helm template# Validate required values
name: {{ required "name is required" .Values.name }}
port: {{ required "port is required" .Values.port }}# Always provide sensible defaults
replicas: {{ .Values.replicaCount | default 1 }}
image:
pullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}# Quote string values in env vars and annotations
env:
- name: DATABASE_URL
value: {{ .Values.database.url | quote }}# Prefer include for composability
labels:
{{- include "mychart.labels" . | nindent 2 }}
# Not: {{ template "mychart.labels" . }}# Let toYaml handle complex structures
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 2 }}
{{- end }}# Use nindent for YAML blocks
metadata:
labels:
{{- include "mychart.labels" . | nindent 4 }}
# Use indent for multi-line strings
data:
config: |
{{ .Values.config | indent 4 }}# Use {{- and -}} to control whitespace
{{- if .Values.enabled }}
content
{{- end }}# Fail early if critical values missing
database:
host: {{ required "database.host is required!" .Values.database.host }}Trigger pod restart when ConfigMap changes:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
# ...
{{- end }}name: {{ include "mychart.fullname" . }}
serviceName: {{ include "mychart.fullname" . }}-svc{{- include "mychart.container" (dict "root" . "container" .Values.mainContainer) }}Then in helper:
{{- define "mychart.container" -}}
{{- $root := .root }}
{{- $container := .container }}
name: {{ $container.name }}
image: {{ $container.image }}
namespace: {{ $root.Release.Namespace }}
{{- end }}Install with Tessl CLI
npx tessl i pantheon-ai/helm-generator@0.1.0