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.
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
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
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.
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
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.