wizard

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package wizard collects user answers (currently non-interactive only), validates them against the package's Inputs schema, runs the package's optional Collector to discover install-time facts, and emits Selection + Inputs + Facts documents into a working directory.

Index

Constants

View Source
const (
	PresetMinimal  = "minimal"
	PresetDefault  = "default"
	PresetAll      = "all"
	PresetSelected = "selected"
)

Component-set presets the wizard offers as the high-level shortcut to component selection. Strings here are also the user-facing prompt values; keep them stable across releases.

Variables

AllPresets is the menu order shown by the wizard.

Functions

func AskOneInput

func AskOneInput(in api.Input) (string, error)

AskOneInput prompts interactively for a single input declaration using the same widget the wizard uses inline (text / select / bool). Used by `installer upgrade` to ask for new required inputs that the prior install did not answer.

func FormatNewRequiredHint

func FormatNewRequiredHint(workDir string, ins []api.Input) string

FormatNewRequiredHint renders a multiline message naming each new required input — used by `installer upgrade` in non-interactive mode to fail fast with actionable detail.

func LoadPriorState

func LoadPriorState(ctx context.Context, workDir string, warn func(string)) (*PriorState, PriorSource, error)

LoadPriorState looks for prior install state in workDir, preferring ConfigHub if upload.yaml is present. Returns SourceNone with a nil state if no prior state exists.

On ConfigHub fetch failure, falls back to local files and returns a best-effort warning via the warn callback (set by the caller — the CLI passes a function that prints to stderr; tests pass nil to drop the warning silently).

func ParseInputFlags

func ParseInputFlags(flags []string) (map[string]string, error)

ParseInputFlags parses --input k=v repeated occurrences into a map.

func ParseSetImageFlags

func ParseSetImageFlags(flags []string) (map[string]string, error)

ParseSetImageFlags parses --set-image name=ref repeated occurrences into a map. Empty name or empty ref is rejected — kustomize edit would otherwise silently misbehave.

func ResolvePreset

func ResolvePreset(pkg *api.Package, preset string) ([]string, error)

ResolvePreset turns a preset name into a component slice, without touching the filesystem or the terminal. Used by the non-interactive CLI to support `--components <preset>`.

func StringifyAny

func StringifyAny(v any) string

StringifyAny is the exported wrapper around stringifyAny — used by `installer upgrade` to round-trip prior typed values back through RawAnswers.

Types

type AskOptions

type AskOptions struct {
	// Stdio overrides the I/O streams; nil uses the real terminal.
	// Tests pass scripted streams via survey/v2's WithStdio.
	Stdio *terminal.Stdio
}

AskOptions tunes the interactive flow.

type InputDiff

type InputDiff struct {
	// Carry are values that exist in both packages with a compatible
	// type and a recorded prior value. They flow through to the new
	// inputs.yaml verbatim.
	Carry map[string]any
	// AdoptedDefaults are inputs new in this version that have a
	// declared default. The default is silently used.
	AdoptedDefaults map[string]any
	// NewRequired are inputs new in this version that are required and
	// have no default. They must be answered (interactive prompt or
	// fail-fast in non-interactive mode).
	NewRequired []api.Input
	// Dropped are prior keys whose input was removed in the new
	// package. Operator does not need to do anything; the value is
	// silently omitted from the new inputs.yaml.
	Dropped []string
	// TypeChanged are inputs whose declared Type differs between old
	// and new. The operator must re-answer because coercion may
	// silently misinterpret the value.
	TypeChanged []api.Input
}

InputDiff is the result of comparing the input schemas of an old and a new package against a set of prior values. The four buckets are mutually exclusive — every prior key + every new declared input lands in exactly one of them.

func DiffInputs

func DiffInputs(oldPkg, newPkg *api.Package, prior map[string]any) InputDiff

DiffInputs walks oldPkg's inputs and newPkg's inputs against a set of prior values (typically prior.Inputs.Spec.Values), bucketing each declared input. Inputs gated by WhenExternalRequire that the new package does not actually require are silently skipped (mirrors coerceInputs's gate).

type PriorSource

type PriorSource string

PriorSource names where the prior state came from.

const (
	// SourceNone indicates the work-dir had no usable prior state.
	SourceNone PriorSource = "none"
	// SourceLocal indicates state came from out/spec/*.yaml.
	SourceLocal PriorSource = "local"
	// SourceConfigHub indicates state came from the installer-record
	// Unit on ConfigHub (located via out/spec/upload.yaml).
	SourceConfigHub PriorSource = "confighub"
)

type PriorState

type PriorState struct {
	Selection *api.Selection
	Inputs    *api.Inputs
	Facts     *api.Facts
	// PriorPackage is the installer.yaml that produced this state —
	// recovered either from the embedded installer-record (ConfigHub
	// source) or from the work-dir's package/installer.yaml (local
	// source). Used by upgrade's schema-diff to compare new vs old.
	PriorPackage *api.Package
	// Upload is the recorded upload destination, if any.
	Upload *api.Upload
}

PriorState bundles the documents we recover from a prior install. Any field may be nil if it was never written (e.g., Facts when the package has no Collector, or PriorPackage when the loader could not fetch ConfigHub state and the work-dir's local package has been replaced).

type RawAnswers

type RawAnswers struct {
	// Inputs is the raw map from --input k=v, where v is a string.
	Inputs map[string]string
	// SelectedComponents is the list from --select (raw user picks; closure
	// happens later in the solver).
	SelectedComponents []string
	// BaseName is the chosen base from --base; "" means use the package default.
	BaseName string
	// Namespace is the Kubernetes namespace from --namespace. Persisted to
	// inputs.yaml and exposed to function-chain templates as {{ .Namespace }}.
	Namespace string
	// ImageOverrides is the map from --set-image name=ref. Merged with
	// PriorImageOverrides (this run's overrides win on conflict) and
	// persisted into Inputs.Spec.ImageOverrides so render can apply
	// `kustomize edit set image` for each entry before kustomize build.
	ImageOverrides map[string]string
	// PriorImageOverrides is the carry-forward set from a prior
	// install's Inputs.Spec.ImageOverrides. Wizard merges it under
	// ImageOverrides (this run wins on conflict) so an upgrade
	// without --set-image preserves the operator's existing
	// overrides.
	PriorImageOverrides map[string]string
}

RawAnswers are CLI-flag-shaped: parsed but not yet validated against the package's Inputs schema.

func Ask

func Ask(pkg *api.Package, prior *PriorState, opts AskOptions) (RawAnswers, error)

Ask runs the interactive wizard against pkg, optionally pre-filling every prompt from prior. Returns RawAnswers ready to feed Run().

On Ctrl+C / EOF the function returns ErrAborted so the caller can distinguish operator cancellation from a real failure.

func RawAnswersFromPrior

func RawAnswersFromPrior(pkg *api.Package, prior *PriorState) RawAnswers

RawAnswersFromPrior turns a PriorState into a RawAnswers as if the operator had just re-typed the same answers. Used for the "re-use last choices" fast path, the --reuse CLI flag, and upgrade's non-interactive carry-over.

type Result

type Result struct {
	Selection *api.Selection
	Inputs    *api.Inputs
	Facts     *api.Facts
}

Result bundles the documents the wizard produces. Facts is nil if the package declares no Collector.

func Run

func Run(ctx context.Context, pkg *api.Package, raw RawAnswers, packageDir, outDir string) (*Result, error)

Run validates answers against the package, runs the selection solver, invokes the package's Collector (if any), and writes selection.yaml + inputs.yaml + facts.yaml into outDir/spec.

packageDir is the absolute path to the loaded package working copy; the collector runs with that as its working directory.

type SelectionDiff

type SelectionDiff struct {
	// Components is the resolved new selection — the operator's
	// effective component list under the new package's component
	// graph.
	Components []string
	// PreservedFromPrior is a copy of Components for callers that want
	// to know how many entries were carried forward from the prior
	// selection.
	PreservedFromPrior []string
	// AdoptedNewDefaults names components new in this version that
	// were silently selected because the prior install used the
	// default preset and the components are flagged default: true.
	AdoptedNewDefaults []string
	// RemovedFromPrior names prior selections whose component no
	// longer exists in the new package. Silently dropped.
	RemovedFromPrior []string
	// DefaultPresetDetected is true when prior matches old package's
	// `default` preset exactly — the upgrade re-runs the default
	// preset against the new package rather than carrying the
	// (possibly stale) component list verbatim.
	DefaultPresetDetected bool
}

SelectionDiff is the result of comparing component selections.

func DiffComponents

func DiffComponents(oldPkg, newPkg *api.Package, prior []string) SelectionDiff

DiffComponents merges priorSelection's Components into the new package's component graph, honoring the prior preset. If the prior selection matches the old package's default preset (every `default: true` component, nothing else), the upgrade adopts the new package's default preset — so a new default-flagged component flows in automatically. Otherwise the prior list is filtered to components that still exist.

priorSelection may be nil (treated as empty selection).

Jump to

Keyboard shortcuts

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