helmer

module
v0.0.28 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2026 License: Apache-2.0

README

Helmer

Overview

Helmer is a tool for rendering sets of Helm charts with values from multiple sources to multiple targets.

Motivation

Have you enjoyed Kustomize’s ability to layer manifest changes to produce multiple configurations from a small set of manifests, but found yourself getting lost about which configuration patches which resource or felt uncomfortable making changes to lower layers? Missing your templates?

One of the main strengths of a Helm chart and its templates is that they dictate what can be altered. Users can't change anything other than what the template author exposes. That can be a drawback because it reduces flexibility. That's what makes Kustomize appealing: the ability to change anything. However, tools like Kustomize can be fragile. If the author of the base manifest makes a change, it can easily break kustomizations that depend on finding an element at a certain place. This is especially cumbersome in arrays, where elements are referred to by their position. Change the order and the base YAML is still valid, but a patch may hit a different element than intended. In a small set of layers with a few patches this can be manageable, but in a larger set things can easily get complicated. Changing a base manifest can result in many surprises.

Helm, on the other hand, is typically used with a single chart and a single set of values. You can run Helm multiple times to reference multiple value sets, but you'll have to manage them yourself. That's feasible, but why not make a tool to help with this?

Enter Helmer. Helmer aims to use Helm to execute multiple charts and add layering of values via separate configuration files. Those configuration files can include other files to reuse or replace value sets and chart rendering directives.

Installation

Helmer has only a compile-time dependency on Helm; the resulting binary is self-contained and has no runtime dependency on Helm or any other tools.

From source
go install github.com/stefan65535/helmer/cmd/helmer@latest

Workflow

Helmer doesn't communicate with your Kubernetes clusters (at least not in the current version; a future version might). The intended workflow is to run the tool in a CI/CD pipeline and push the generated manifests to a second Git repository, the target. The Kubernetes clusters are expected to run a GitOps tool like ArgoCD that points to a directory in the target Git repository.

This two-step process might seem overcomplicated, but it gives you a chance to review not only the chart and value changes in the source repository but also to review what will change in each cluster. This becomes more important when handling complex configurations across many clusters.

This "Git as the target" approach also lets you use Git's branching capabilities. If you set up different branches for different environments in the target repo, you can control which clusters get updated on a merge. You can give each cluster its own branch or group them into branches like sandbox, development, and production to roll out changes at a pace that suits your needs.

Usage

Run:

helmer --help

Configuration file

  • includes: A list of include elements.
  • charts: A list of chart elements.
  • values: A values element. Defines global values. Can be overriden on a chart basis.
  • capabilities: capabilities sets the anticipated capabilities of the intended Kubernetes cluster.
  • release: release Defines global release properties. Can be overriden on a chart basis.
  • target: The target element controles where rendered manifests will be written. target is only allowed to be present on the root configuration. Inclued configuration files must not contain aditional targets.
include
  • path: Tells Helmer where to find the configuration to include. The path is relative to the current configuration file. The field supports glob patterns using the Go Match syntax, filepath.Match.
chart

A chart references a Helm chart.

  • path: Where to find the chart. Currently, only local charts are supported.
  • values: A values element. If a value is present int the global values the chart value will take precedence.
  • release: A release element
  • targetDir: Set the name of the target directory. If not set the chart name will be used.
  • patches: A list of patch
  • auxTemplates: A list of auxTemplates elements.

Example:

charts:
  - path: path/to/my/helm/chart
    values:
      colour: Yellow
patch

A patch is applied to rendered Kubernetes manifests using JSON Patch (RFC 6902). This can be usefull referencing external charts that aren't fully parameterized to your liking. Pathces are applied after the chart rendering is done.

Each patch entry must identify which rendered resources it should target and then provide a JSON Patch array of operations. The target selection fields are:

  • apiVersion - apiVersion can also be expressed in seperate group and version elements.
  • group
  • version
  • kind
  • name
  • namespace

A patch entry that matches multiple resources will be applied to each matching resource.

Patch structure

A patch entry under a chart looks like:

charts:
  - path: charts/myapp
    patches:
      - target:
          kind: Deployment
          name: myapp
        patch:
          - op: replace
            path: /spec/template/spec/containers/0/image
            value: myrepo/myapp:1.2

Notes:

  • The patch field is a JSON Patch array (a list of objects with op, path, and optionally value).
  • Paths are JSON Pointer strings (RFC 6901). Use ~1 to escape slashes and ~0 to escape tildes inside key names (for example, the annotation key helm.sh/managed-by becomes helm.sh~1managed-by in the pointer).
  • Operations supported by RFC 6902 (add, remove, replace, move, copy, test) are accepted.
  • Values in a patch operation can be scalars, objects, arrays, or Helmer references ($ref).

Examples

  1. Replace container image
- target:
    kind: Deployment
    name: myapp
  patch:
    - op: replace
      path: /spec/template/spec/containers/0/image
      value: myrepo/myapp:1.2.3
  1. Add an annotation (note escaped slash)
- target:
    kind: Service
    name: my-service
  patch:
    - op: add
      path: /metadata/annotations/helm.sh~1managed-by
      value: helmer
  1. Reuse a value from your configuration via $ref
values:
  image: "myrepo/myapp:1.2.3"

charts:
  - path: charts/myapp
    patches:
      - selection:
          kind: Deployment
          name: myapp
        patch:
          - op: replace
            path: /spec/template/spec/containers/0/image
            value:
              $ref: values.image # resolves to "myrepo/myapp:1.2.3"

Behavior and best practices

  • Patches are applied after Helm template rendering and before writing manifests to the target.
  • Patches are applied in the order they appear. If multiple patches target the same path, later patches overwrite earlier ones.
  • JSON Pointer array indices are position-based; using array indices can be fragile if upstream charts reorder array elements. When possible, prefer changing chart values or replacing larger subtrees instead of relying on numeric array indices.
  • If a replace/remove operation targets a missing path, the patch will fail.

Error handling

  • If a patch fails (invalid path or operation), Helmer will surface an error for that chart/rendering step. Test patches locally against rendered output to validate pointer paths and operations before adding them to a pipeline.

This should give you the tools to target individual rendered resources and apply precise JSON Patch edits while still using $ref to keep patches data-driven and reusable.

auxTemplate

Patches can only do so much, sometimes you need to add complete templates and manifests to an external chart. auxTemplates lets you do this.

  • path Path to a Go template

Values are available just as if the template was within the chart. However special Helm functiona are not. The template is executed using the Go template lib allone.

values

Values declare a set of Helm values. Any YAML valid as Helm values can be placed here.

Example:

values:
  colour: Blue
$ref

A value node can contain a reference to another value using the $ref notation. This is useful when working with third-party charts where you can't change the value names in the chart but still want to reuse values already present in your value set. It also lets you design charts that are unaware of your global values structure in the Helmer config and instead name chart fields after their location or function.

The value of $ref uses the JSON Pointer notation. It is limited to URI fragments, i.e., it must start with #.

References are resolved after all includes are processed. This lets you reference a field anywhere in the include tree.

Example:

Let's assume you have a chart with a value field called FavouriteColor. You could introduce a value field with that name directly, but perhaps there is already a field in your Helmer config that plays the role of a favourite colour. Instead of changing your chart template, a $ref in the FavouriteColor field will pick it up for you.

charts:
  - path: "../../charts/mychart"
    values:
      favouriteColor:
        $ref: "#/colour"
values:
  colour: Blue
$file reference

A value node can contain a file reference by using the $file syntax.

values:
  colour:
    $file: ../favouriteColour.txt

This will convert the node to a scalar whose value is the content of the file.

Helm can reference files from a chart, but it is limited to files placed within the chart. A Helmer $file reference, on the other hand, can reference any file on the host.

$files reference

A value node can contain an array of file references by using the $files syntax. The result is an array of strings. One for the content of each file.

The file references are relative to the current config file. The path field supports glob patterns using the Go Match syntax, filepath.Match. The resulting array will reflect the order returned by the filesystem, which may not be deterministic.

values:
  colours:
    $files: 
      - path: ../files/favouriteColour.txt
      - path: ../files/uglyColour.txt
      - path: ../files/allColours/*.txt

Here is an example how to render all colours in a template:

{{- range .Values.Colours }}
    {{ . }}
{{- end }}  
target

A target directive controls the generation of manifests from the defined set of charts and Helm objects in the configuration.

  • path: tells Helmer where to put the generated manifests.

Example:

target:
  path: write/manifests/to/this/file
release

Sets various attributes in the Helm built-in object .Release.

Theese attributes are not used by Helmer. It is only necessary to define these if your Helm charts use them.

  • namespace: Sets the .Release.Namespace.
  • name: Sets the .Release.Name.

Example:

release:
  namespace: mynamespace

release can be set as a global directive and on chart basis. If both are set the chart will override the global value.

capabilities

This provides information about what capabilities the Kubernetes cluster supports.

As Helmer doesn't talk to your Kubernetes cluster, it can't extract cluster information by itself. Often this is not a problem when running Helm on the client side, but in the rare case you are using charts that reference the built-in object Capabilities, its values can be set explicitly through this directive.

  • apiVersions: Sets the Capabilities.APIVersions.
  • kubeVersion.version: Sets the Kubernetes Capabilities.KubeVersion.Version.
  • kubeVersion.major: Sets the Capabilities.KubeVersion.Major.
  • kubeVersion.minor: Sets the Capabilities.KubeVersion.Minor.

Helmer values

Helmer values are added to the global .Values in Helm under .Values.Helmer

  • Target
    • Path Holds the path to the target directory
    • SubDirs An array of directory names. This is where redered manifests ends up.

Example:

Some chart:

{{- range .Values.Helmer.Target.SubDir }}
---
apiVersion: acme.com/v1
kind: Kindly
spec:
  path: {{ $.Values.Helmer.Target.Path }}/{{ . }}
{{- end }}

This can be useful in, for example, an ArgoCD applications that needs to reference the target path in a repository with generated manifests.

Priority order for values

Values can be set as globals or in a chart. There are also the built-in value defaults in Helm charts themselves. Priority among these is: Chart > Globals > Chart defaults. Global values included from another configuration will have lower priority than those in the including configuration.

License

Helmer is released under the Apache 2.0 license. See LICENSE

Directories

Path Synopsis
cmd
helmer command
internal
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL