recipebuilder

package
v0.14.32-dev Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package recipebuilder is the per-node half of the DKS "recipes, not blobs" image-distribution model (dhnt/docs/dks-image-recipe-distribution-design.md).

It polls cloudbox's recipe index (GET /api/v1/recipes, scope recipes:read), and for each recipe this node doesn't already have built, resolves the build context, builds the image NATIVELY with `bashy podman`, and imports it into this node's k3s containerd. No image blob is ever transferred — each node reproduces the image from the recipe. It is the automated form of script/dks-image/build-load.sh.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Materialize added in v0.14.30

func Materialize(ctx context.Context, r Runner, workDir, platform string, rec Recipe, runtimeContainer string) error

Materialize resolves a recipe's build context, builds it NATIVELY for platform, and loads it into runtimeContainer's containerd. It is the exact sequence the polling Builder runs, factored out so the peer path cannot drift from it.

It does not verify the result; callers confirm residency by content digest.

func PackInlineRecipe added in v0.14.30

func PackInlineRecipe(out io.Writer, spec InlineRecipeSpec) error

PackInlineRecipe writes a flat ImageRecipe YAML document containing a deterministic tar.gz context. Only explicitly listed paths are included.

Types

type Builder

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

Builder polls the cloudbox recipe index and builds+loads each recipe locally.

func New

func New(cfg Config) *Builder

New constructs a Builder, applying defaults.

func (*Builder) Run

func (b *Builder) Run(ctx context.Context) error

Run blocks until ctx is canceled, polling on the configured cadence. A misconfigured Builder (unpaired, no runtime container) logs once and blocks — it never errors the errgroup it runs under.

type Config

type Config struct {
	// CloudboxBase is the cloudbox origin (scheme+host); recipesPath is appended.
	CloudboxBase string
	// AccessToken is the per-outpost bearer; must carry recipes:read.
	AccessToken string
	// RuntimeContainer is the <AgentName>-runtime container whose k3s containerd
	// receives the built images.
	RuntimeContainer string
	// WorkDir holds cloned git build contexts. Empty → <TempDir>/outpost-recipes.
	WorkDir string
	// Platform is the build target, e.g. "linux/arm64". Empty → linux/<GOARCH>
	// (native — the whole point: no cross-arch, no manifest lists).
	Platform string
	// Interval between polls. <=0 → defaultInterval.
	Interval time.Duration
	// HTTPClient for the recipe fetch. nil → http.DefaultClient.
	HTTPClient *http.Client
	// Runner performs clone/build/load. nil → a bashy-shelling execRunner
	// (BashyBin must then be set).
	Runner Runner
	// BashyBin is the resolved `bashy` executable for the default execRunner.
	BashyBin string
}

Config configures a Builder. CloudboxBase, AccessToken and RuntimeContainer are required; the rest default.

type InlineRecipeSpec added in v0.14.30

type InlineRecipeSpec struct {
	Name       string
	Tag        string
	LocalRef   string
	ContextDir string
	Dockerfile string
	Includes   []string
	BaseImages []string
}

InlineRecipeSpec describes a generic, explicitly-whitelisted source context. It deliberately has no cloudbox-specific defaults: proprietary callers choose their own context root and includes without embedding those sources in outpost.

type Recipe

type Recipe struct {
	Name           string
	Tag            string
	LocalRef       string   // what the node loads it as (localhost/cluster/<n>)
	ContextType    string   // git | local | inline_tar
	ContextRepo    string   // git remote (context_type=git)
	ContextRef     string   // pinned commit/ref (context_type=git)
	ContextSubdir  string   // build context root within the checkout
	ContextPath    string   // local path (context_type=local; same-host only)
	ContextArchive string   // base64 tar or tar.gz bytes (context_type=inline_tar)
	Dockerfile     string   // relative to the context root
	BaseImages     []string // declared bases (mirrored to GHCR out of band)
	ContextSha256  string   // provenance of source (verified, not output digest)
}

Recipe is the parsed build recipe (the YAML carried in a cloudbox Recipe asset's Content). The wire/authoring form is the flat YAML in script/dks-image/recipes/*.yaml; we hand-parse the top-level keys we need so the lean outpost daemon adds no YAML dependency.

func ParseRecipe added in v0.14.30

func ParseRecipe(body string) (Recipe, error)

ParseRecipe decodes and validates a flat ImageRecipe YAML document. A recipe that does not validate is an error, never a partially-populated Recipe — a half-parsed recipe is exactly the kind of thing that builds the wrong image.

func (Recipe) Canonical added in v0.14.30

func (r Recipe) Canonical() []byte

Canonical is the recipe's deterministic identity form: sorted "key=value" lines over the fields that decide WHAT gets built. Formatting, comment and key-order differences in the authored YAML do not change it.

The inline archive itself is represented by context_sha256 rather than by its bytes. That digest is verified byte-for-byte before extraction (see decodeInlineArchive), so it is a faithful stand-in for the source and keeps the canonical form small enough to log and compare.

func (Recipe) Digest added in v0.14.30

func (r Recipe) Digest() string

Digest is "sha256:<hex>" over Canonical() — the recipe's CROSS-NODE identity. Two nodes that built from the same recipe agree on this value even though their resulting image content digests differ (container builds are not bit-reproducible).

func (Recipe) Ref added in v0.14.30

func (r Recipe) Ref() string

Ref is the image reference this recipe builds to ("<local_ref>:<tag>").

type Runner

type Runner interface {
	// Clone resolves a git build context (repo@ref) into dest.
	Clone(ctx context.Context, repo, ref, dest string) error
	// Build builds contextDir's dockerfile natively into ref.
	Build(ctx context.Context, platform, dockerfile, ref, contextDir string) error
	// Load streams the built image into the node's k3s containerd (via the
	// <name>-runtime container's `k3s ctr images import`).
	Load(ctx context.Context, ref, runtimeContainer string) error
	// ImagePresent checks the image store of the current runtime container, not
	// the host build cache. Runtime recreation can erase containerd while the
	// recipe digest remains unchanged.
	ImagePresent(ctx context.Context, ref, runtimeContainer string) (bool, error)
}

Runner performs the three side-effecting steps of building a recipe. It is an interface so the poll/build orchestration is unit-testable without a real podman/git — the daemon uses execRunner, tests use a fake.

func NewBashyRunner added in v0.14.30

func NewBashyRunner(path func(ctx context.Context) (string, error)) Runner

NewBashyRunner returns a Runner that shells out to `bashy podman`/`bashy git`, resolving the bashy executable through path on EVERY call. Construction therefore never blocks on provisioning a missing userland: the daemon wires path to its self-healing resolver (cmd/outpost's bashyResolver.Path), whose cached fast path makes repeat calls cheap, and a host that lacks bashy today recovers the moment one appears rather than needing a daemon restart.

Jump to

Keyboard shortcuts

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