deployer

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package deployer defines the shared interface and types for bundle deployers.

Each deployer (helm, argocd, argocd-helm, flux) produces deployment artifacts from a configured recipe. Deployers are configured as structs with all required data, then Generate is called to produce the output.

The Deployer interface enables mockability in bundler tests and provides a consistent contract across deployer implementations. All four deployers (helm, argocd, argocd-helm, flux) implement this interface.

Index

Constants

This section is empty.

Variables

View Source
var TemplateFuncs = template.FuncMap{
	"q": strconv.Quote,
}

TemplateFuncs is the FuncMap available to every deployer template, including those rendered through GenerateFromTemplate.

`q` emits a YAML double-quoted scalar. Quoting matters for any field Helm unmarshals as a string: an unquoted `appVersion: 1.2` parses as a float and fails the unmarshal, and a value carrying a quote character would break out of a hand-written literal. strconv.Quote's escape vocabulary (\", \\, \n, \xNN, \uNNNN) is a subset of what YAML's double-quoted style accepts, so the result round-trips. Same reasoning as the %q quoting in the argocd-helm deployer's Chart.yaml writer (#1034).

Functions

func GenerateFromTemplate

func GenerateFromTemplate(tmplContent string, data any, baseDir, filename string) (string, int64, error)

GenerateFromTemplate renders a template and writes it to baseDir/filename. It uses SafeJoin to verify the output path stays within baseDir.

func IsSafePathComponent

func IsSafePathComponent(name string) bool

IsSafePathComponent returns true if name is a single path component without any separators or parent directory references.

Reject embedded separators so callers can rely on the result being a single path element. filepath.IsLocal then handles emptiness, absolute paths, parent-directory refs (..), and Windows reserved names — and, unlike a substring scan for "..", accepts benign names like "foo..bak".

func NormalizeChartVersion added in v0.21.0

func NormalizeChartVersion(v string) string

NormalizeChartVersion coerces an AICR build version into a value Helm accepts for a Chart.yaml `version:` field, stripping the 'v' prefix that release tags carry inconsistently.

Helm validates that field as SemVer 2 (chart.Metadata.Validate) and refuses to load a chart whose version does not parse. An unstamped build reports defaults.DevVersion ("dev"), which does not, so every non-SemVer input — "dev", "stock-render-golden", "" — folds to defaults.DevChartVersion rather than shipping a chart Helm will reject. Without that fold, `make dev-env` and Tilt break on the first `helm install`.

The parse is deliberately the lenient semver.NewVersion rather than StrictNewVersion: it is the same call Helm makes when loading a chart, so anything returned here will load. (helm lint is stricter and warns on a partial version like "1.2"; AICR release tags are always full X.Y.Z, so that case is theoretical.)

func NormalizeVersion

func NormalizeVersion(v string) string

NormalizeVersion removes the 'v' prefix from a version string. It returns the input unchanged if no prefix is present.

func NormalizeVersionWithDefault

func NormalizeVersionWithDefault(v string) string

NormalizeVersionWithDefault removes the 'v' prefix and defaults empty strings to "0.1.0". Use this for Helm chart metadata where a version is always required.

func ResolveCRDOwners added in v0.22.0

func ResolveCRDOwners(
	ctx context.Context,
	dp recipe.DataProvider,
	refs []recipe.ComponentRef,
) (map[string]bool, error)

ResolveCRDOwners reports which of refs may have their CRDs replaced on upgrade, in one registry round-trip. Components missing from the registry are omitted and therefore read as false.

Shared by every deployer that has to decide the question, so the guard is identical across bundles: flux turns a true into `spec.upgrade.crds: CreateReplace`, helm and helmfile into an apply-crds.sh step. Argo CD does not consult this at all. It renders charts with `--include-crds` and applies CRDs as ordinary manifests every sync, so it upgrades them without an opt-in and cannot be gated by one (`skipCrds` would also suppress them on first install).

A registry failure is fatal rather than defaulting everything to false: silently treating every component as "does not own its CRDs" would quietly restore the stranded-CRD behavior the flag exists to fix.

func SafeJoin

func SafeJoin(baseDir, name string) (string, error)

SafeJoin joins baseDir and name, then verifies the result is contained within baseDir. This prevents path traversal when name comes from untrusted input (e.g., component names from recipe data).

func SortByDeploymentOrder

func SortByDeploymentOrder[T any](items []T, order []string, getName func(T) string) []T

SortByDeploymentOrder sorts items by deployment order using getName to extract the component name from each item. Items in the order list are sorted by their position; items not in the order list are placed after ordered items and sorted alphabetically by name.

func SortComponentNamesByDeploymentOrder

func SortComponentNamesByDeploymentOrder(components []string, deploymentOrder []string) []string

SortComponentNamesByDeploymentOrder sorts component name strings by deployment order.

func SortComponentRefsByDeploymentOrder

func SortComponentRefsByDeploymentOrder(refs []recipe.ComponentRef, order []string) []recipe.ComponentRef

SortComponentRefsByDeploymentOrder sorts component refs by deployment order.

func UsesRegistryChart added in v0.22.0

func UsesRegistryChart(ref recipe.ComponentRef, cfg *recipe.ComponentConfig) bool

UsesRegistryChart reports whether a ref still points at the exact chart the registry pins for its component.

ownsCRDs records the result of an audit performed against that chart: that the component solely owns every CRD it ships, and ships none using a webhook conversion strategy. A recipe may override source, chart, or version on the componentRef, and those overrides bypass registry defaulting entirely. The audit says nothing about the chart they point at, so the flag must not carry over to it — replacing CRDs from an unaudited chart is exactly the destructive case the opt-in design exists to avoid.

Fails closed: any mismatch, or a component with no Helm chart, disqualifies.

func WriteValuesFile

func WriteValuesFile(values map[string]any, baseDir, filename string) (string, int64, error)

WriteValuesFile writes a values.yaml file with header comment to baseDir/filename. It uses SafeJoin to verify the output path stays within baseDir.

Types

type Deployer

type Deployer interface {
	Generate(ctx context.Context, outputDir string) (*Output, error)
}

Deployer generates deployment bundles from configured inputs. Implementations are configured as structs, then Generate is called.

type Output

type Output struct {
	// Files contains the paths of generated files.
	Files []string

	// TotalSize is the total size of all generated files.
	TotalSize int64

	// Duration is the time taken to generate the output.
	Duration time.Duration

	// DeploymentSteps contains ordered deployment instructions for the user.
	DeploymentSteps []string

	// DeploymentNotes contains optional deployment notes or warnings.
	DeploymentNotes []string

	// Entrypoint is the bundle-root file a consumer invokes or applies for
	// this deployer, relative to the bundle root.
	Entrypoint string

	// Provenance is the chart-provenance audit file this run wrote, relative
	// to the bundle root, and empty when the run wrote none. A deployer must
	// report it rather than let a caller stat the bundle: the file is written
	// only for a vendored bundle and is never pruned, so a stat would also
	// find one left behind by an earlier run into the same directory.
	Provenance string

	// Releases is every Helm release the bundle installs, in deployment
	// order. The ordering is normative: consumers read sequence from list
	// position, so a deployer must append in the order it deploys.
	Releases []Release

	// Source is what the deployer resolved for the bundle's deployment
	// source, reported rather than re-derived by the caller: re-deriving it
	// would put each deployer's defaults in a second place to drift from.
	Source Source
}

Output contains the result of deployer generation.

func (*Output) AddDataFiles

func (o *Output) AddDataFiles(outputDir string, dataFiles []string) error

AddDataFiles resolves each relative data file path against outputDir (via SafeJoin, rejecting traversal), stats the file, and appends the absolute path to Files while adding the file size to TotalSize. Used by generators to include external --data files in their output so they are covered by checksum generation.

type Release added in v0.22.0

type Release struct {
	Name      string
	Component string
	Namespace string
	Path      string
	Manifest  string
}

Release is one Helm release a deployer emits, reported so the bundler can index the bundle without re-deriving paths the deployer already built.

Component names the recipe component the release belongs to, which equals Name for a primary release and names the parent for an injected -pre, -post, or -readiness release. Path and Manifest are relative to the bundle root; Manifest is empty for deployers that declare a release through an orchestration script rather than a file.

type Source added in v0.22.0

type Source struct {
	// RepoURL is the repository the emitted manifests point at.
	RepoURL string

	// TargetRevision is the revision those manifests pin.
	TargetRevision string

	// AppName is the parent application name the bundle installs under.
	AppName string
}

Source is the deployment-source coordinates a deployer resolved and baked into the bundle it just wrote.

A deployer sets a field only when the resolved value is observable in a file it emitted, and it reports the value it actually wrote — including a default or a placeholder the caller never supplied, because the placeholder is what the bundle ships. A field left empty means this deployer's bundle never mentions that coordinate, which is not the same as the caller omitting it.

Directories

Path Synopsis
Package argocd provides Argo CD Application generation for recipes.
Package argocd provides Argo CD Application generation for recipes.
Package argocdhelm generates a Helm chart app-of-apps for Argo CD with dynamic install-time values.
Package argocdhelm generates a Helm chart app-of-apps for Argo CD with dynamic install-time values.
Package flux provides Flux manifest generation for AICR recipes.
Package flux provides Flux manifest generation for AICR recipes.
Package helm generates per-component Helm bundles from recipe results.
Package helm generates per-component Helm bundles from recipe results.
Package helmfile generates a helmfile.yaml release graph from a configured recipe.
Package helmfile generates a helmfile.yaml release graph from a configured recipe.
Package localformat writes the uniform numbered local-chart bundle layout.
Package localformat writes the uniform numbered local-chart bundle layout.

Jump to

Keyboard shortcuts

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