values

package
v0.4.8 Latest Latest
Warning

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

Go to latest
Published: Jun 16, 2026 License: AGPL-3.0 Imports: 15 Imported by: 0

Documentation

Overview

Package values implements HelmRelease values resolution and Kustomization postBuild substitution. It is the bridge between authored manifests and rendered manifests: it consults the central Store for ConfigMap/Secret content and merges referenced data into a HelmRelease's values map or a Kustomization's postBuild substitution table.

Two key behaviors mirror flux-local:

  • Deep merge follows Helm semantics: nested maps are merged, but lists are REPLACED entirely (not concatenated).
  • When a valuesFrom reference is optional and the target ConfigMap / Secret (or values key) is missing, it is skipped silently so the render proceeds; a wiped Secret value (a placeholder token the manifest parser injects for SOPS-encrypted data) is treated as empty rather than failing the whole HelmRelease.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DeepMerge

func DeepMerge(base, override map[string]any) map[string]any

DeepMerge returns a new map with override's keys merged into base. Nested maps recurse; lists and scalars from override fully replace values from base — matching Helm's merge semantics. Both inputs are read-only.

Implemented as deepMergeShared over a fresh shallow copy of base: the copy makes the top-level map owned, and deepMergeShared's copy-on-collision recursion keeps every borrowed (base) sub-tree read-only, so neither input is mutated.

func DeepMergeInto

func DeepMergeInto(dst, override map[string]any) map[string]any

DeepMergeInto merges override's keys into dst in place. Same merge semantics as DeepMerge but mutates dst instead of allocating a new map. Callers MUST own dst and any sub-maps reachable from it — passing a map that shares sub-trees with another reachable reference will corrupt that reference. Designed for hot paths (ExpandValueReferences's per-ref loop) where the caller is building up a fresh map across N refs and the N-1 intermediate allocations DeepMerge would do are wasted.

Sub-maps coming from override are inserted by reference (not cloned) when no existing key collides — same as DeepMerge. Returns dst for fluent-style use.

func ExpandPostBuildSubstituteReference

func ExpandPostBuildSubstituteReference(ks *manifest.Kustomization, p Provider) error

ExpandPostBuildSubstituteReference resolves substituteFrom references against the provider and updates ks.PostBuildSubstitute (and its raw Contents). Missing references are logged (Secrets silently) and the substitution proceeds with what's available.

func ExpandValueReferences

func ExpandValueReferences(hr *manifest.HelmRelease, provider Provider, cache *Cache) error

ExpandValueReferences resolves all spec.valuesFrom references on hr, merges them with hr.Values (inline values take precedence per Helm semantics), and writes the result back to hr.Values.

Honors ValuesReference.Optional: missing resources or values keys on Optional=true refs are skipped silently; Optional=false refs fail. Matches Flux helm-controller chartutil semantics.

Hard errors from the lookup itself — unsupported kind, malformed binaryData — always bubble up; they are unrelated to whether the ref is optional.

cache may be nil — tests and embedders without an orchestrator pass nil and pay the (small) per-ref yaml.Unmarshal cost. Orchestrators supply a Cache constructed at startup so refs shared across HRs (a common pattern for platform-wide values CMs) parse exactly once.

func UnreadableSubstituteSecrets added in v0.4.7

func UnreadableSubstituteSecrets(ks *manifest.Kustomization, p Provider) []string

UnreadableSubstituteSecrets returns the names of ks.PostBuildSubstituteFrom Secret references whose data flate can't read offline — an absent Secret or an ExternalSecret-synthesized empty target, both of which yield no data so the ${VAR}s they would supply expand to the empty string. SOPS-encrypted Secrets are NOT reported: their data is wiped to placeholders, so their vars still substitute. Optional refs are skipped (the author marked them best-effort). The result is sorted and de-duplicated; nil when none.

This is a pure advisory query — it does not affect substitution. The Kustomization controller surfaces the result as a WarnUnresolvedSubstitution Warning so an unreadable secret is explained rather than silently leaving empty values behind.

func VarsMap

func VarsMap(in map[string]any) map[string]string

VarsMap returns the substitution variables for use with kustomize.Substitute. Non-string scalar values are stringified; nested maps/slices and other unsupported shapes are silently dropped with a Debug log rather than rendered as Go's default `map[k:v]` / `[1 2 3]` representation, which produced literal garbage substitutions diverging from upstream kustomize-controller (whose LoadVariables only accepts flat string→string). Newline characters are stripped from every value — upstream does the same so multi-line entries can't break inline substitution into single-line YAML fields.

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache memoizes parsed-YAML output of valuesFrom refs across HRs. One HR with N valuesFrom refs hits each entry once; M HRs sharing the same ConfigMap/Secret/key tuple (a common pattern when a platform values CM is referenced by every app HR) re-yaml.Unmarshal'd the same bytes M times. Cache key folds the content hash so a mutation to the underlying object (re-AddObject) invalidates naturally without an explicit listener.

Stored values are TREATED AS IMMUTABLE — callers receive a deep clone before mutation so concurrent ExpandValueReferences calls can't observe a partially-modified sub-tree. The cache itself is safe for concurrent use.

Zero value is a no-op cache: NewCache or a non-nil *Cache must be supplied to opt into memoization. nil is the legacy fast path for tests / one-shot embedders.

func NewCache

func NewCache() *Cache

NewCache returns an empty *Cache ready for use. Construct one per orchestrator run and pass to ExpandValueReferences.

type Provider

type Provider interface {
	ConfigMap(namespace, name string) *manifest.ConfigMap
	Secret(namespace, name string) *manifest.Secret
}

Provider exposes the ConfigMap/Secret lookups needed for value reference expansion. The controllers implement it against the central store (see NewStoreProvider); tests use SliceProvider.

func NewStoreProvider

func NewStoreProvider(s *store.Store) Provider

NewStoreProvider returns a Provider backed by the central Store.

Jump to

Keyboard shortcuts

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