go-hiera

Puppet's Hiera 5 hierarchical data-lookup engine in pure Go — faithful, no cgo.

pure Go · zero cgo hiera.yaml v5 yaml_data · json_data first · unique · hash · deep lookup_options knockout_prefix %{...} interpolation alias · scope · lookup dotted dig pluggable Scope 100% coverage 6 arches
Documentation GitHub
Documentation (MkDocs Material + mike) License: BSD-3-Clause Go 1.26.4+ Coverage 100%

go-hiera is a pure-Go (no cgo) reimplementation of Hiera 5, the hierarchical data-lookup engine behind Puppet's lookup(). It loads a hiera.yaml version-5 config — defaults plus an ordered hierarchy of levels (path, paths, glob, globs, mapped_paths) — reads data through yaml_data and json_data backends, and assembles the result with Hiera's four merge behaviours (first, unique, hash, deep) driven by lookup_options. Full %{...} interpolation — facts, trusted, scope(), lookup() / hiera(), whole-value alias() and literal() — is resolved with interpolation-loop detection. The variable / fact Scope is a pluggable interface the caller injects, so go-facter (facts) and the Ruby binding go-ruby-hiera plug in without a hard dependency. Faithful to Hiera 5 so it can back Puppet's lookup() — CGO-free, 100% coverage, green across 6 arches.

go-hiera/hiera core · engine

The Hiera 5 data-lookup engine: hiera.yaml v5 loader, yaml_data / json_data backends (pluggable via RegisterDataHash), the first / unique / hash / deep merge engine with lookup_options, dotted-key dig, and full %{...} interpolation. go get github.com/go-hiera/hiera

hiera.yaml v5 loader ready

Parses hiera.yaml version 5 — the defaults block and the ordered hierarchy of levels, with every path form: path / paths, glob / globs, and mapped_paths. Each level resolves its datadir, data_hash backend and per-level options exactly as Hiera 5 does.

yaml / json backends ready

The yaml_data backend reads through go-ruby-yaml’s pure-Go, Psych-faithful loader so YAML parses byte-for-byte the way MRI’s Ruby does; json_data reads JSON. Backends are pluggable via RegisterDataHash, so eyaml / HOCON slot in later without touching the engine.

merge engine + lookup_options ready

All four merge behaviours — first, unique, hash and deep — driven by lookup_options (per-key and ^regex keys), honouring knockout_prefix and merge_hash_arrays. The value assembled across every matching hierarchy level is the one Puppet’s lookup() would return.

%{...} interpolation + loop detection ready

Full %{...} interpolation: %{facts.x}, %{trusted.x}, %{scope('x')}, %{lookup('x')} / %{hiera('x')}, the whole-value %{alias('x')}, and %{literal('%')} — with interpolation-loop detection that stops a key that resolves back through itself.

dotted dig + defaults ready

Dotted keys (a.b.c) dig into structured hashes and arrays, and lookups fall through to caller-supplied default values / default blocks when no level matches — the same digging and defaulting semantics Puppet exposes on lookup().

Ruby surface planned

Downstream, not part of this engine module: the Ruby Hiera class and Puppet’s lookup() / automatic data-binding surface are mapped onto this engine by the go-ruby-hiera consumer. This library is the data-lookup engine; the binding is the Ruby face.

A faithful port of Puppet's Hiera 5 in pure Go, cgo disabled, so it cross-compiles and embeds anywhere. It reads hiera.yaml v5 through yaml_data (via the pure-Go, Psych-faithful go-ruby-yaml loader) and json_data, applies the first / unique / hash / deep merge behaviours with lookup_options, knockout_prefix and merge_hash_arrays, and resolves every %{...} interpolation with loop detection. The variable/fact Scope is a pluggable interface, so go-facter and the Ruby binding go-ruby-hiera — which maps Ruby's Hiera and Puppet's lookup() onto this engine — plug in downstream. Part of the sibling org github.com/go-hiera.