localformat

package
v0.12.1 Latest Latest
Warning

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

Go to latest
Published: May 1, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package localformat writes the uniform numbered local-chart bundle layout. Currently consumed by the helm deployer (--deployer helm). Designed to be consumable by additional deployers (e.g. helmfile per #632, argocd, Flux) without per-deployer changes to the writer; those integrations are not yet wired in this package.

Layout

Each emitted folder is named NNN-<component>/ where NNN is a zero-padded 1-based index. Folders are one of two kinds, distinguished solely by the presence or absence of Chart.yaml:

  • KindUpstreamHelm — no Chart.yaml. The folder carries values.yaml, cluster-values.yaml, upstream.env (CHART/REPO/VERSION), and a rendered install.sh that installs the upstream chart via `helm upgrade --install`.

  • KindLocalHelm — Chart.yaml + templates/ present. The folder is a self-contained Helm chart; install.sh installs `./` as a local chart.

The Chart.yaml presence rule is the sole branch point for consumers. No component-kind metadata is re-read at deploy time. This is deliberate: a previous design branched deploy.sh on Helm/Kustomize/raw-manifest kinds, which bled component-type classification into every deployer. Chart.yaml presence reduces that to a single on-disk signal every deployer honors.

Classification

Recipe shape determines the folder kind:

Helm repository set, no manifests             → KindUpstreamHelm
Helm repository set, with raw manifests       → KindUpstreamHelm primary +
                                                 KindLocalHelm "-post" injection
Helm repository empty, manifests only         → KindLocalHelm (wrapped)
Kustomize (Tag/Path set)                      → KindLocalHelm (kustomize build
                                                 output wrapped as templates/manifest.yaml)

Mixed components and the "-post" injection

When a single recipe component declares both an upstream Helm chart and raw manifests, Write emits two adjacent folders: the primary NNN-<name>/ as KindUpstreamHelm, immediately followed by (NNN+1)-<name>-post/ as KindLocalHelm wrapping the raw manifests. Subsequent components shift by one. The "mixed" concept does not appear in the recipe types, deployment order, or bundle result — it exists only in the bundle layout.

The -post folder deploys after the upstream chart, so raw manifests that reference the chart's CRDs apply against a cluster where those CRDs already exist. This is what makes the earlier pre-apply-with-retry mechanism (which applied raw manifests before the chart and retried on "CRD not found" errors) structurally unnecessary.

Base-format invariants

These are load-bearing contracts. Callers and contributors should not violate them without changing the design:

  1. localformat never writes deployer-specific files. deploy.sh, helmfile.yaml, argocd Application CRs, Flux HelmReleases, and the like are produced by the respective deployer after Write returns. Write owns per-folder content; deployers own top-level orchestration files. This separation is what makes a single folder layout consumable by every deployer without localformat growing per-deployer branches.

  2. install.sh is never name-customized. Rendered from one of exactly two templates (upstream-helm, local-helm), parameterized only by data (name, namespace, upstream ref). Name-keyed component quirks (kai-scheduler async skip, skyhook taint cleanup, DRA restart, orphan CRD scan) stay in deploy.sh as name-matched blocks — not in install.sh. This is the structural barrier that keeps per-folder scripts from accumulating drift the way deploy.sh's branching did.

  3. Write is deterministic and idempotent. Same Options in, same on-disk bytes and same Folder slice out. Map iteration is sorted; no timestamps or random suffixes are embedded in generated content.

Caller contract

Callers pass an ordered Components slice (sorted by deployment order) and a ComponentManifests map (name → path → rendered bytes) that drives both the -post injection for mixed components and the template contents for manifest-only wrapped charts. Write returns a []Folder manifest so deployers can generate their own orchestration files without re-classifying or re-reading disk.

Further detail: ticket #662 carries the original design discussion and alternatives considered.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Component

type Component struct {
	Name      string
	Namespace string
	// Helm upstream ref (empty for manifest-only components)
	Repository string
	ChartName  string
	Version    string
	IsOCI      bool
	// Kustomize (empty for helm components)
	Tag  string
	Path string
	// Values hydrated by the component bundler
	Values       map[string]any
	DynamicPaths []string // paths moved from values.yaml into cluster-values.yaml
}

Component is the per-component input for Write. Fields mirror the subset of pkg/bundler/deployer/helm.ComponentData that localformat needs.

type Folder

type Folder struct {
	Index    int    // 1-based; rendered as zero-padded 3-digit prefix in Dir
	Dir      string // e.g. "001-nfd"
	Kind     FolderKind
	Name     string    // component name, or "<name>-post" for injected
	Parent   string    // component this folder belongs to (== Name for primary)
	Upstream *Upstream // set iff Kind == KindUpstreamHelm
	Files    []string  // relative paths (to OutputDir) of files written in this folder
}

Folder describes one written folder. Returned by Write so callers (deployers) can generate orchestration files without re-classifying.

func Write

func Write(ctx context.Context, opts Options) ([]Folder, error)

Write emits the numbered folder layout. Deterministic and idempotent.

Removes any pre-existing NNN-* folders under OutputDir before writing, so reusing the same --output across recipe regenerations does not leave stale component folders that the deployer's loop would later install. Top-level orchestration files (deploy.sh, undeploy.sh, README.md, attestation/) are left intact; only files under [0-9][0-9][0-9]-* are removed.

type FolderKind

type FolderKind int

FolderKind classifies a written folder by the presence/absence of Chart.yaml.

const (
	// KindUpstreamHelm: folder contains no Chart.yaml; install.sh references
	// an upstream Helm chart via upstream.env.
	KindUpstreamHelm FolderKind = iota
	// KindLocalHelm: folder contains a generated Chart.yaml + templates/;
	// install.sh installs ./ as a local chart.
	KindLocalHelm
)

func (FolderKind) String

func (k FolderKind) String() string

String returns the stable textual name for the kind. Used by logs and golden-file diagnostics so diffs show kind names rather than integers.

type Options

type Options struct {
	OutputDir          string
	Components         []Component                  // ordered per DeploymentOrder
	ComponentManifests map[string]map[string][]byte // name → path → rendered bytes
}

Options configures Write.

type Upstream

type Upstream struct {
	Chart   string
	Repo    string
	Version string
}

Upstream holds upstream chart reference fields written to upstream.env.

Jump to

Keyboard shortcuts

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