Documentation
¶
Index ¶
- Variables
- func ApplyDefaults(m Meta, params map[string]any) map[string]any
- func NormalizeParams(m *Meta) error
- func RenderAndValidate(body string, params map[string]any) (string, error)
- func RenderBody(body string, params map[string]any) (string, error)
- func ValidName(s string) bool
- func Validate(m Meta, params map[string]any, secrets map[string]string) error
- func ValidateAllowMissingSecrets(m Meta, params map[string]any, secrets map[string]string) error
- func ValidateIngress(ing *Ingress) error
- func ValidateParamDefs(m Meta) error
- type Display
- type Ingress
- type Meta
- type ParamDef
- type PreBackup
- type Secrets
- type Volume
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidParameters = errors.New("invalid parameters")
ErrInvalidParameters is the sentinel returned by Validate.
var ErrRenderInvalid = errors.New("rendered template is invalid")
ErrRenderInvalid is returned when the rendered template output is invalid.
var NameRe = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{0,38}[a-z0-9]$`)
NameRe is the DNS-label constraint for template ids and instance slugs.
It is ALSO the shape check for a new host id on POST /hosts/{host}/rename (via the API layer's validName). A change made for template-id reasons therefore silently changes what host ids the rename route will accept — and a host id that no longer matches is one nobody can rename to, even though hosts/*.yaml itself imposes no such constraint. Check both callers.
Functions ¶
func ApplyDefaults ¶
ApplyDefaults returns a copy of params with any omitted parameter filled from its ParamDef.Default. Caller-supplied values always win. Parameters without a default are left absent (Validate enforces required ones).
func NormalizeParams ¶
NormalizeParams normalizes each parameter's Type (blank → "string") and returns an error for an unknown type (allowed: string|int|bool|select).
func RenderAndValidate ¶ added in v1.0.11
RenderAndValidate renders the template body and validates the result. It calls RenderBody then checks for issues with multi-line string params whose continuation lines lack the indentation needed to stay valid in a YAML block-scalar context.
func RenderBody ¶
RenderBody substitutes params into an already-separated template body using text/template (with missingkey=error) and returns the final YAML. Callers that hold the full source (meta + body) split it with ParseMeta first; a store.Template keeps Meta and Body apart and renders the body directly.
func Validate ¶
Validate checks that params and secrets satisfy the template's contract:
- All Required parameters are present.
- No params outside the declared parameter set.
- All PerInstance secrets are present.
- No secrets outside PerInstance (PerHostReferenced are not in this map).
Returns a single error listing every problem found.
func ValidateAllowMissingSecrets ¶
ValidateAllowMissingSecrets is Validate without the "every PerInstance secret must be present" rule. It still rejects unknown secrets and enforces required parameters. The secret-rotation path uses this to re-apply a stored spec that legitimately lacks a PerInstance secret (one never set, or added to the template after deploy) without forcing the operator to re-supply it.
func ValidateIngress ¶
ValidateIngress checks an ingress declaration: container non-empty and port in 1..65535. nil is valid (no ingress).
func ValidateParamDefs ¶ added in v1.0.26
ValidateParamDefs checks the parameter declarations themselves (as opposed to Validate, which checks supplied values against them). It rejects a parameter marked `secret: true`: parameter values land in a plaintext column, so the flag cannot mean what it says. secrets.per_instance is the encrypted-at-rest path and already does this job. (#205)
Types ¶
type Display ¶
type Display struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Category string `yaml:"category,omitempty" json:"category,omitempty"`
Icon string `yaml:"icon,omitempty" json:"icon,omitempty"`
}
Display holds human-readable presentation metadata for a template.
type Ingress ¶
type Ingress struct {
Container string `yaml:"container" json:"container"`
Port int `yaml:"port" json:"port"`
}
Ingress declares which container+port in the rendered pod serves HTTP, so the ingress layer can route a domain to it. Absent on non-web templates.
type Meta ¶
type Meta struct {
ID string `yaml:"id" json:"id"`
Display Display `yaml:"display,omitempty" json:"display,omitempty"`
Parameters []ParamDef `yaml:"parameters" json:"parameters,omitempty"`
Secrets Secrets `yaml:"secrets" json:"secrets,omitempty"`
Volumes []Volume `yaml:"volumes" json:"volumes,omitempty"`
Ingress *Ingress `yaml:"ingress" json:"ingress,omitempty"`
PreBackup *PreBackup `yaml:"pre_backup,omitempty" json:"pre_backup,omitempty"`
}
Meta describes a template's parameter and secret contract. It is parsed from the leading "# template-meta:" comment block.
func ParseMeta ¶
ParseMeta extracts the template-meta block from the head of the file and returns the rest of the file as the renderable body.
The block must look like:
# template-meta: # id: postgres # parameters: ...
The parser stops at the first non-comment line. The body is everything from that point onward (with a leading "---" preserved if present).
type ParamDef ¶
type ParamDef struct {
Name string `yaml:"name" json:"name"`
Type string `yaml:"type" json:"type"`
Required bool `yaml:"required,omitempty" json:"required,omitempty"`
Label string `yaml:"label,omitempty" json:"label,omitempty"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Default any `yaml:"default,omitempty" json:"default,omitempty"`
Placeholder string `yaml:"placeholder,omitempty" json:"placeholder,omitempty"`
Options []string `yaml:"options,omitempty" json:"options,omitempty"`
// Secret is rejected, not honored: a template declaring it fails validation
// (ValidateParamDefs). Parameter values are stored in a plaintext column, so
// the flag once promised an encryption-at-rest guarantee the storage layer
// never delivered — it only ever redacted the value from GET responses.
// Authors want secrets.per_instance, which is encrypted at rest and reaches
// the pod via secretKeyRef. The field is kept solely so the flag is *seen*
// and refused: meta is decoded with non-strict YAML, so deleting it would
// silently ignore `secret: true` instead of failing on it. (#205)
Secret bool `yaml:"secret,omitempty" json:"secret,omitempty"`
}
ParamDef describes a single template parameter, its type, and constraints.
type PreBackup ¶ added in v1.0.14
type PreBackup struct {
Container string `yaml:"container" json:"container"`
Command string `yaml:"command" json:"command"`
}
PreBackup is a command run inside a named container immediately before the backup job stops+exports the instance. A non-zero exit fails the backup, so a failed dump never ships a stale/partial snapshot.
Command is rendered with the instance's parameters (text/template) and then run as `/bin/sh -lc "<rendered command>"` in Container. The target container must therefore provide /bin/sh and support a login profile — minimal or distroless images will fail the exec (and thus the backup). Because rendering happens before the shell, parameters are interpolated directly into the shell line.