build

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: Apache-2.0, MIT Imports: 15 Imported by: 0

Documentation

Overview

Package build is the domain core of incusos-builder: it resolves a release from update-server metadata, probes the acquired image's GPT, renders and splices the seed tar, and orchestrates offline rescue-media construction — all through ports, with no direct network or filesystem side effects.

The ports (ImageSource, VerifiedAsset, Reporter, RescueWriter) are defined here and implemented by the adapters in internal/update, internal/media, and internal/ux. Build takes an explicit SeedRenderFunc (typically seed.Render) rather than importing internal/seed, which would cycle because Seeds is defined here.

Index

Constants

This section is empty.

Variables

View Source
var ErrOutput = errdefs.ErrOutput

ErrOutput is returned when writing a built artifact fails (the image stream or, via the media adapter, rescue media). Callers map it to process exit code 6. It is the package-local name for errdefs.ErrOutput.

View Source
var ErrVersionNotFound = errdefs.ErrVersionNotFound

ErrVersionNotFound is returned when Resolve cannot select a release (unknown pin, empty channel, missing image, or a requested application the update does not carry). Callers map it to process exit code 5. The error text lists nearby versions or the applications the update does carry. It is the package-local name for errdefs.ErrVersionNotFound.

Functions

This section is empty.

Types

type Architecture

type Architecture string

Architecture is an update-server CPU architecture name.

const (
	// ArchX8664 is the x86_64 architecture.
	ArchX8664 Architecture = "x86_64"
	// ArchAarch64 is the aarch64 architecture.
	ArchAarch64 Architecture = "aarch64"
)

Architectures accepted by the update server.

type Channel

type Channel string

Channel names an update-server release channel (free text upstream; default "stable").

const DefaultChannel Channel = "stable"

DefaultChannel is applied when the config omits image.channel.

type ImageSource

type ImageSource interface {
	// Index returns the update-server index used to resolve a release.
	// Failures wrap [errdefs.ErrFetch].
	Index(ctx context.Context) (apiimages.Index, error)

	// Asset verifies and retains one asset, returning a reusable handle.
	// Verification of Size and Sha256 happens once per call. Download
	// progress is reported through the Reporter the adapter was constructed
	// with. Failures wrap [errdefs.ErrFetch].
	Asset(ctx context.Context, version string, file apiimages.UpdateFile) (VerifiedAsset, error)

	// ReleaseMetadata returns the release's update.json and update.sjson
	// bodies verbatim. They are not UpdateFile entries, so the adapter
	// validates them structurally: each read is size-capped; update.sjson
	// must be a multipart/signed S/MIME message whose clear-text payload
	// decodes as apiimages.Update with Version == version and whose Files
	// cover every selected Filename and Sha256; update.json must decode as
	// apiimages.Update with the same Version. This is structural consistency,
	// not signature authentication. Failures wrap [errdefs.ErrFetch].
	ReleaseMetadata(ctx context.Context, version string, selected []apiimages.UpdateFile) (ReleaseMetadata, error)
}

ImageSource acquires update metadata and verified assets.

type ImageType

type ImageType string

ImageType selects the artifact layout of the built image.

const (
	// ImageTypeISO is the iso9660 installer artifact.
	ImageTypeISO ImageType = "iso"
	// ImageTypeRaw is the raw disk artifact.
	ImageTypeRaw ImageType = "raw"
)

Image types accepted by the update server's asset naming (image-iso / image-raw) and by upstream's customizer.

type Plan

type Plan struct {
	// Version is the selected update version (the pin, or the highest
	// version in the channel).
	Version string
	// Image is the unique image-iso or image-raw asset for the spec's
	// type and architecture.
	Image apiimages.UpdateFile
	// Apps are the application assets matched as <name>.raw.gz against
	// the selected update, in spec order. Filenames keep the per-arch
	// prefix published by the server (for example aarch64/incus.raw.gz).
	// Empty unless spec.Offline; online builds skip application matching.
	Apps []apiimages.UpdateFile
}

Plan is the resolved release: one OS image file plus the application files requested by the spec. Resolve produces it from a Spec and an update-server index; Build consumes it.

func Resolve

func Resolve(spec Spec, index apiimages.Index) (Plan, error)

Resolve selects a release from index the way upstream filterAssets does: channel membership, an exact Release pin or the highest version by string compare of upstream version names, then exactly one image-iso/image-raw for the spec's type and architecture. Application assets are matched only when spec.Offline (sendOSImage never looks at applications; sendRescueImage does). Matching uses path.Base so per-arch prefixes (aarch64/incus.raw.gz) still hit. A missing application wraps ErrVersionNotFound and lists what the update does carry.

type Release

type Release string

Release is an exact update version pin (upstream ImagesPost.Version). Empty means "highest version in the channel".

type ReleaseMetadata

type ReleaseMetadata struct {
	// UpdateJSON is the parsed, version-checked update.json body, stored
	// verbatim.
	UpdateJSON []byte
	// UpdateSJSON is the structurally validated update.sjson body, stored
	// verbatim.
	UpdateSJSON []byte
}

ReleaseMetadata carries the verbatim release documents for rescue media.

type Reporter

type Reporter interface {
	// Step announces that a named build step has started.
	Step(name string)
	// Progress reports bytes completed of a known total.
	Progress(done, total int64)
	// Done announces that a named build step has finished.
	Done(name string)
}

Reporter receives build-step and progress events. The update adapter and the domain both hold one.

type RescueAsset

type RescueAsset struct {
	// RelPath is the path inside the media, such as
	// "update/aarch64/incus.raw.gz".
	RelPath string
	// Asset is opened once by the writer and streamed into the media.
	Asset VerifiedAsset
}

RescueAsset names one file inside the media's update/ tree and the verified handle its bytes stream from.

type RescueInput

type RescueInput struct {
	// Assets are the application files staged under update/.
	Assets []RescueAsset
	// UpdateJSON is written verbatim to update/update.json.
	UpdateJSON []byte
	// UpdateSJSON is written verbatim to update/update.sjson. Empty is
	// refused by WriteRescue.
	UpdateSJSON []byte
}

RescueInput is everything staged under the media's update/ tree.

type RescueWriter

type RescueWriter interface {
	// WriteRescue writes rescue media of typ into tmpPath. The caller
	// creates and owns tmpPath and must reopen it by path after the call
	// returns, because WriteRescue replaces the inode. An empty
	// UpdateSJSON is refused: media without update.sjson leaves the
	// booted system silently unrecovered. Assets are streamed from their
	// VerifiedAsset handles. Failures wrap [ErrOutput].
	WriteRescue(ctx context.Context, typ ImageType, in RescueInput, tmpPath string) error
}

RescueWriter builds RESCUE_DATA media into a caller-owned tmpPath.

type Result

type Result struct {
	// Version is the resolved update version written into the image.
	Version string
	// Channel is the channel the version was selected from.
	Channel Channel
	// Type is the image type that was built (iso or raw).
	Type ImageType
	// Architecture is the CPU architecture that was built (x86_64 or
	// aarch64).
	Architecture Architecture
	// BytesWritten is the number of decompressed bytes written to out
	// (the spliced OS image).
	BytesWritten int64
	// SeedBytes is the size of the spliced seed tar.
	SeedBytes int64
	// Offline is true when rescue media was also produced.
	Offline bool
	// ResourcesTmp is the caller-owned temp path rescue media was written
	// to. Empty when Offline is false.
	ResourcesTmp string
}

Result is what Build reports after a successful run. Digests and final paths are a publication concern of internal/cli, not the domain.

func Build

func Build(
	ctx context.Context,
	spec Spec,
	src ImageSource,
	rescue RescueWriter,
	rep Reporter,
	render SeedRenderFunc,
	out io.Writer,
	resourcesTmp string,
) (Result, error)

Build resolves a release, probes the image GPT, splices the seed tar, and optionally builds offline rescue media. src, rescue, and rep are ports; render is wired to seed.Render in main; out is the caller-owned image stream; resourcesTmp is the caller-owned rescue temp path. There is no filesystem or network I/O in this function beyond the injected ports, renderer, and streams.

type SeedRenderFunc

type SeedRenderFunc func(Seeds) ([]byte, int64, error)

SeedRenderFunc renders a seed tar from Seeds. Production wiring assigns seed.Render; tests inject a stub. The type lives here so Build does not import internal/seed (Seeds is defined in this package).

type Seeds

type Seeds struct {
	// Applications seeds preinstalled applications.
	Applications *apiseed.Applications
	// Incus seeds the full Incus init preseed.
	Incus *apiseed.Incus
	// Install seeds the installer (target selection, security flags).
	Install *apiseed.Install
	// MigrationManager seeds the migration-manager service.
	MigrationManager *apiseed.MigrationManager
	// Network seeds the network configuration.
	Network *apiseed.Network
	// OperationsCenter seeds the operations-center service.
	OperationsCenter *apiseed.OperationsCenter
	// Provider seeds the provider registration.
	Provider *apiseed.Provider
	// Services seeds auxiliary service toggles.
	Services *apiseed.Services
	// Update seeds the update daemon configuration.
	Update *apiseed.Update
	// Kernel seeds kernel configuration (CLI extension).
	Kernel *apiseed.Kernel
	// Security seeds security configuration (CLI extension; validation
	// rejects non-empty encryption_recovery_keys because incus-osd fatally
	// rejects them at boot).
	Security *apiseed.Security
}

Seeds aggregates all eleven seed sections incus-osd reads from the seed-data partition. The nine web-API sections mirror upstream customizer.ImagesPostSeeds field-for-field; Kernel and Security are CLI-exclusive extensions (the web service cannot emit them). Nil sections are omitted from the seed tar.

type Spec

type Spec struct {
	// Type selects iso or raw output.
	Type ImageType
	// Architecture selects the update-server architecture.
	Architecture Architecture
	// Channel filters candidate updates; default "stable".
	Channel Channel
	// Release pins an exact version; empty selects the highest in Channel.
	Release Release
	// Offline additionally builds RESCUE_DATA resources media.
	Offline bool
	// Seeds holds every seed section to splice into the image.
	Seeds Seeds
}

Spec is the fully validated build specification produced by internal/config and consumed by Build. It carries no I/O handles.

type VerifiedAsset

type VerifiedAsset interface {
	// Open returns a fresh reader over the verified compressed bytes.
	// The caller that opened the reader closes it.
	Open(ctx context.Context) (io.ReadCloser, error)
	// Size is the exact verified byte count, equal to UpdateFile.Size.
	Size() int64
}

VerifiedAsset is a handle to one verified asset retained by the source. Open may be called any number of times; each call returns a fresh reader over the same verified bytes (compressed, exactly as served). The caller that opened a reader closes it. Handles stay valid for the process lifetime: the cache has no eviction.

Jump to

Keyboard shortcuts

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