Documentation
¶
Overview ¶
Package charts implements a Helm-inspired package manager for Docker Swarm.
A chart is a versioned package of Docker Stack (Compose) templates plus default values and metadata. Installing a chart produces a release: a Docker stack whose revision history is stored append-only in Docker Configs. The package is pure Go (no Bubble Tea / TUI) so it can back both the non-interactive CLI and, later, a TUI browser view.
Index ¶
- Constants
- func EngineVersion() string
- func HasErrors(findings []LintFinding) bool
- func IsPathRef(ref string) bool
- func MergeValues(defaults map[string]any, files [][]byte, sets []string) (map[string]any, error)
- func Render(ch *Chart, ctx RenderContext) (string, error)
- func ValidateValues(schema []byte, values map[string]any) error
- type Action
- type ApplyResult
- type Backend
- type Chart
- type ChartHit
- type ChartMeta
- type ChartSource
- type Chartfile
- type CompatFinding
- type CompatStatus
- type ConfigMeta
- type Dependency
- type Engine
- func (e *Engine) Apply(ctx context.Context, plan *Plan, opts InstallOptions) ([]ApplyResult, error)
- func (e *Engine) GetRevision(ctx context.Context, release string, rev int) (*Release, error)
- func (e *Engine) History(ctx context.Context, release string) ([]Release, error)
- func (e *Engine) Install(ctx context.Context, release string, chart ReleaseChart, values map[string]any, ...) (*Release, error)
- func (e *Engine) List(ctx context.Context) ([]Release, error)
- func (e *Engine) PlanApply(ctx context.Context, rf *ReleaseFile, src ChartSource) (*Plan, error)
- func (e *Engine) Prune(ctx context.Context, release string, keep int, dryRun bool) (PruneResult, error)
- func (e *Engine) PruneAll(ctx context.Context, keep int, dryRun bool) ([]PruneResult, error)
- func (e *Engine) Rollback(ctx context.Context, release string, targetRev int, opts InstallOptions) (*Release, error)
- func (e *Engine) Status(ctx context.Context, release string) (*Release, []ServiceState, error)
- func (e *Engine) Uninstall(ctx context.Context, release string, purgeVolumes bool) (*UninstallResult, error)
- func (e *Engine) Upgrade(ctx context.Context, release string, chart ReleaseChart, values map[string]any, ...) (*Release, error)
- type Index
- type IndexEntry
- type InstallOptions
- type LintFinding
- type LintSeverity
- type Maintainer
- type NetworkRequirement
- type OutdatedEntry
- type Plan
- type PruneAction
- type PruneResult
- type Release
- type ReleaseChart
- type ReleaseFile
- type ReleaseMeta
- type ReleasePlan
- type ReleaseSpec
- type RenderContext
- type RepoEntry
- type RepoSpec
- type RepoStore
- func (s *RepoStore) Add(name, repoURL string) error
- func (s *RepoStore) EnsureRepos(specs []RepoSpec) error
- func (s *RepoStore) Indexes() (map[string]*Index, error)
- func (s *RepoStore) List() ([]RepoEntry, error)
- func (s *RepoStore) LoadIndex(name string) (*Index, error)
- func (s *RepoStore) Pull(entry IndexEntry, baseURL string) (*Chart, error)
- func (s *RepoStore) Remove(name string) error
- func (s *RepoStore) Resolve(ref, version string) (IndexEntry, string, error)
- func (s *RepoStore) Search(keyword string) ([]ChartHit, error)
- func (s *RepoStore) Update(name string) (changed, unchanged []string, err error)
- type Requirements
- type ResourceRequirement
- type ServiceState
- type UninstallResult
Constants ¶
const ( LabelType = "com.swarmcli.type" // always "release" LabelRelease = "com.swarmcli.release" // release name LabelChart = "com.swarmcli.chart" // chart name LabelChartVersion = "com.swarmcli.chart.version" // chart SemVer LabelRevision = "com.swarmcli.revision" // revision number LabelStatus = "com.swarmcli.status" // see Status* constants LabelCreated = "com.swarmcli.created" // RFC3339 timestamp TypeRelease = "release" )
Label keys applied to every release-history Docker Config. They mirror the scheme documented in issue #413 and let list/status/history queries filter Configs by release without an external database.
const ( StatusPendingInstall = "pending-install" StatusDeployed = "deployed" StatusSuperseded = "superseded" StatusFailed = "failed" StatusUninstalled = "uninstalled" )
Release status values, following Helm's deploy/superseded/failed lifecycle.
Variables ¶
This section is empty.
Functions ¶
func EngineVersion ¶
func EngineVersion() string
EngineVersion reports the chart-engine version this binary embeds, or the empty string for an unstamped build.
func HasErrors ¶
func HasErrors(findings []LintFinding) bool
HasErrors reports whether any finding is fatal, i.e. whether the lint failed.
func IsPathRef ¶
IsPathRef reports whether ref names a local chart path rather than a "<repo>/<chart>" reference. The test is deliberately SYNTACTIC: a release file is committed to git and must resolve the same way on every machine, so whether a reference is a path cannot depend on what happens to exist on the disk of whichever CI runner picked up the job.
func MergeValues ¶
MergeValues computes the effective values for a render, applying Helm's precedence: chart defaults < each --values file (in order) < --set overrides. Maps are deep-merged; scalars and sequences replace.
func Render ¶
func Render(ch *Chart, ctx RenderContext) (string, error)
Render evaluates every templates/*.yaml file with text/template + Sprig, deep-merges the resulting Compose fragments into a single document, and returns it as validated YAML. Files whose names start with "_" (e.g. templates/_helpers.tpl) define named templates only and emit no document.
Types ¶
type ApplyResult ¶
type ApplyResult struct {
Name string
Action Action
Revision int // 0 when unchanged (nothing was recorded)
}
ApplyResult is what Apply actually did to one release.
type Backend ¶
type Backend interface {
DeployStack(name, manifest string) error
RemoveStack(name string) error
// RefreshSnapshot invalidates the shared Docker state cache after a mutation
// so subsequent reads (status, convergence polling) do not see stale data.
RefreshSnapshot() error
CreateConfig(ctx context.Context, name string, data []byte, labels map[string]string) error
ListConfigs(ctx context.Context) ([]ConfigMeta, error)
InspectConfig(ctx context.Context, name string) ([]byte, error)
DeleteConfig(ctx context.Context, name string) error
StackServices(name string) []ServiceState
StackVolumes(ctx context.Context, name string) ([]string, error)
RemoveVolume(ctx context.Context, name string) error
// NetworkScopes returns existing network names mapped to their scope
// (e.g. "swarm", "local"), used to pre-flight a chart's external networks.
NetworkScopes(ctx context.Context) (map[string]string, error)
// CreateOverlayNetwork creates a swarm-scoped network with the given driver
// and attachability (driver defaults to "overlay" when a chart does not
// declare one in requirements.yaml).
CreateOverlayNetwork(ctx context.Context, name, driver string, attachable bool) error
// RemoveOverlayNetwork removes a network by name, used to roll back networks
// auto-created for an install whose deploy then failed. A no-op if absent.
RemoveOverlayNetwork(ctx context.Context, name string) error
// SecretNames returns the set of existing swarm secret names, used to
// pre-flight a chart's external secrets (which cannot be auto-created).
SecretNames(ctx context.Context) (map[string]struct{}, error)
}
Backend abstracts the Docker operations the release engine needs, so the lifecycle logic is unit-testable without a live Swarm.
type Chart ¶
type Chart struct {
Metadata Chartfile
Values map[string]any // parsed values.yaml (defaults)
ValuesRaw []byte // raw values.yaml bytes, nil if absent (preserves comments/order)
Schema []byte // raw values.schema.json, nil if absent
Templates map[string]string // template path -> source, e.g. "templates/stack.yaml"
Readme string // README.md, empty if absent
Requirements *Requirements // parsed requirements.yaml (raw, unrendered), nil if absent
RequirementsRaw []byte // raw requirements.yaml bytes, nil if absent; re-rendered with values at pre-flight
}
Chart is a loaded chart: its metadata, default values, optional values schema, and raw template sources keyed by their path under templates/.
func LoadChartArchive ¶
LoadChartArchive loads a chart from a gzipped tar (.tgz) stream. The archive is expected to contain a single top-level directory (the chart), as produced by chart packaging; the leading directory component is stripped.
func LoadChartDir ¶
LoadChartDir loads a chart from a directory on disk.
type ChartHit ¶
type ChartHit struct {
Repo string
Entry IndexEntry
}
ChartHit is a search result: one chart version in a repository.
type ChartSource ¶
type ChartSource interface {
// Load returns the chart named by ref. ref is either a local path (a chart
// directory or a .tgz) or a "<repo>/<chart>" reference resolved through the
// configured repositories. version selects a repository chart version; it is
// meaningless for a local path and rejected there rather than ignored.
Load(ref, version string) (*Chart, error)
}
ChartSource resolves a chart reference to a loaded chart. It is the seam that lets release planning be unit-tested without a repository, a network or a filesystem: the whole of Engine.PlanApply depends on this interface and not on RepoStore.
func NewChartSource ¶
func NewChartSource(store *RepoStore) ChartSource
NewChartSource returns the standard source, backed by the configured chart repositories for "<repo>/<chart>" references.
type Chartfile ¶
type Chartfile struct {
APIVersion string `yaml:"apiVersion"`
Name string `yaml:"name"`
Version string `yaml:"version"`
AppVersion string `yaml:"appVersion,omitempty"`
// SwarmcliVersion is a SemVer constraint on the chart engine this chart
// needs, e.g. ">= 1.13.0". Optional; absent means any. It constrains the
// engine's version rather than the running binary's — see buildinfo.go.
SwarmcliVersion string `yaml:"swarmcliVersion,omitempty"`
Description string `yaml:"description,omitempty"`
Maintainers []Maintainer `yaml:"maintainers,omitempty"`
// Dependencies are parsed but not resolved in Phase 1 (subcharts are Phase 3).
Dependencies []Dependency `yaml:"dependencies,omitempty"`
}
Chartfile is the parsed Chart.yaml metadata.
type CompatFinding ¶
type CompatFinding struct {
Chart string // "<name> <version>", for messages
Required string // the chart's constraint as declared, e.g. ">= 1.13.0"
Engine string // this build's chart-engine version; "" when unstamped
Status CompatStatus
Reason string // why the check was skipped; set only with CompatUnknown
}
CompatFinding is the result of checking one chart against this build.
func CheckCompat ¶
func CheckCompat(cf Chartfile) CompatFinding
CheckCompat classifies a chart's swarmcliVersion constraint against the chart engine this binary embeds.
func CheckCompatAgainst ¶
func CheckCompatAgainst(cf Chartfile, engine string) CompatFinding
CheckCompatAgainst classifies a chart's swarmcliVersion against an arbitrary chart-engine version rather than this build's. It is what lets `charts lint --for-version` ask "does this chart's declared floor admit X?" without an X to hand.
Note what that question is NOT: whether the chart actually runs on X. This binary carries one engine's behaviour, so it cannot emulate another's — only a real X can prove that. This checks the claim's shape, not its truth.
It never returns an error. A constraint this build cannot make sense of yields CompatUnknown, not a failure: the check is a compatibility aid, not a security boundary — a chart already renders to an arbitrary stack — so failing open on our own inability to parse costs nothing, whereas failing closed would break working charts for a cosmetic reason.
func (CompatFinding) Message ¶
func (f CompatFinding) Message(binaryVersion string) string
Message renders the finding as a one-line diagnostic naming what the chart wants and what this build has.
binaryVersion is the version the binary reports for itself. When it differs from the engine's, both are named: a binary embedding this module may carry its own version, and naming only the engine's would cite a release the user cannot map back to anything they installed. Pass "" to name only the engine.
type CompatStatus ¶
type CompatStatus int
CompatStatus classifies a chart's declared engine requirement against this build.
const ( // CompatUnknown means the chart declared no requirement, this build reports // no engine version, or the declared constraint could not be parsed. // Callers must not block on it: it is not evidence of an incompatible chart. CompatUnknown CompatStatus = iota // CompatOK means this build's chart engine satisfies the constraint. CompatOK // CompatIncompatible means it does not. This is the only status callers // block on. CompatIncompatible )
type ConfigMeta ¶
ConfigMeta is the edition-agnostic view of a stored release Config.
type Dependency ¶
type Dependency struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
Repository string `yaml:"repository,omitempty"`
}
Dependency is a declared subchart requirement (resolution deferred to Phase 3).
type Engine ¶
type Engine struct {
Backend Backend
// contains filtered or unexported fields
}
Engine drives release lifecycle operations against a Backend.
func NewEngine ¶
func NewEngine() *Engine
NewEngine returns an Engine bound to the live Docker backend.
func NewEngineWith ¶
NewEngineWith returns an Engine bound to a custom backend (used in tests).
func (*Engine) Apply ¶
func (e *Engine) Apply(ctx context.Context, plan *Plan, opts InstallOptions) ([]ApplyResult, error)
Apply converges the swarm to a plan, in file order.
It never deletes. A release on the swarm that is absent from the file is reported (Plan.Unmanaged) and left alone: a Release carries no marker saying which manifest produced it, so a prune could not distinguish a release owned by a second manifest, or one installed by hand, from a genuinely obsolete one.
Unchanged releases are skipped entirely. That is not an optimisation but a requirement: history is one Docker Config per revision, so an apply that recorded a revision even when nothing changed would grow the swarm's config store on every CI run, forever.
It stops at the first failure and returns the results completed so far alongside the error, so a partial apply still reports what it did. Re-running is safe: the successful releases become no-ops.
func (*Engine) GetRevision ¶
GetRevision returns a specific revision of a release, or the current one when rev <= 0.
func (*Engine) History ¶
History returns every stored revision of a release, ascending, with derived display statuses.
func (*Engine) Install ¶
func (e *Engine) Install(ctx context.Context, release string, chart ReleaseChart, values map[string]any, manifest string, opts InstallOptions) (*Release, error)
Install deploys a freshly rendered manifest as revision 1 of a new release and records it. It refuses to install over an existing, non-uninstalled release (use upgrade — Phase 2). manifest must already be rendered and validated.
func (*Engine) PlanApply ¶
func (e *Engine) PlanApply(ctx context.Context, rf *ReleaseFile, src ChartSource) (*Plan, error)
PlanApply computes what Apply would do, without writing anything.
Every release is resolved, merged, schema-validated and rendered BEFORE any of them is deployed. A bad value in the third release therefore aborts the whole apply instead of leaving the swarm half-converged — and `--dry-run` is just "stop after planning".
func (*Engine) Prune ¶
func (e *Engine) Prune(ctx context.Context, release string, keep int, dryRun bool) (PruneResult, error)
Prune deletes superseded revisions of one release beyond the keep window, always retaining the current (highest) revision. keep <= 0 keeps everything. On a dry run no Config is touched. Deletion failures are aggregated and returned, but pruning of the remaining revisions continues.
func (*Engine) PruneAll ¶
PruneAll prunes every release to the keep window, returning one result per release (sorted by name). Per-release errors are aggregated; a failing release does not stop the others.
func (*Engine) Rollback ¶
func (e *Engine) Rollback(ctx context.Context, release string, targetRev int, opts InstallOptions) (*Release, error)
Rollback deploys a new revision whose content is copied from a previous revision (append-only, mirroring Helm). targetRev must be an existing, non-failed revision.
func (*Engine) Uninstall ¶
func (e *Engine) Uninstall(ctx context.Context, release string, purgeVolumes bool) (*UninstallResult, error)
Uninstall removes the release's stack and its recorded revisions, retaining volumes unless purgeVolumes is set. It returns an UninstallResult describing the auto-created external networks left in place so the caller can surface them; the networks themselves are not removed.
func (*Engine) Upgrade ¶
func (e *Engine) Upgrade(ctx context.Context, release string, chart ReleaseChart, values map[string]any, manifest string, opts InstallOptions) (*Release, error)
Upgrade deploys a new revision of an existing release. When the release does not exist it errors unless opts.Install is set (the `upgrade --install` behavior). manifest must already be rendered and validated.
type Index ¶
type Index struct {
APIVersion string `yaml:"apiVersion"`
Entries map[string][]IndexEntry `yaml:"entries"`
}
Index is the parsed index.yaml of a chart repository, mapping a chart name to its available versions (Helm repository index format, subset).
type IndexEntry ¶
type IndexEntry struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
AppVersion string `yaml:"appVersion,omitempty"`
Description string `yaml:"description,omitempty"`
URLs []string `yaml:"urls"` // tarball download URLs (absolute or index-relative)
Digest string `yaml:"digest,omitempty"`
}
IndexEntry describes one published chart version within an Index.
type InstallOptions ¶
type InstallOptions struct {
DryRun bool
Wait bool
Install bool // upgrade: create the release if it does not exist
Timeout time.Duration
HistoryMax int // 0 = keep all
// Requirements is the chart's parsed requirements.yaml, when present. It
// drives the external-resource pre-flight (auto-create vs validate-only, the
// network driver/attachability, and remediation descriptions) and, when set,
// every external resource the manifest references must be declared in it. Nil
// falls back to manifest-driven pre-flight (auto-create attachable overlays).
Requirements *Requirements
}
InstallOptions tune an install or upgrade.
type LintFinding ¶
type LintFinding struct {
Severity LintSeverity
Message string
}
LintFinding is one thing lint noticed about a chart.
func Lint ¶
func Lint(ch *Chart, engine string, files [][]byte, sets []string) []LintFinding
Lint checks a loaded chart against the chart engine named by engine — this build's, or one the caller is asking about via --for-version.
files and sets are extra values layered over the chart defaults for the render check, exactly as `charts template -f/--set` would: a chart that requires an input it deliberately leaves undefaulted (a {{ required }} / {{ fail }} guard) cannot render from bare defaults, so linting it needs the same values a real install would supply. Pass nil for both to lint against defaults alone.
It reports everything it finds instead of stopping at the first problem: a chart author wants the list, not a game of whack-a-mole.
Structural validation already happened in LoadChartDir / LoadChartArchive, which refuse a chart with no name, version or templates, or an apiVersion this build cannot read. Lint covers what only becomes visible once a chart is rendered.
One thing it deliberately cannot do: prove a chart runs on the version it declares. This binary carries one engine's behaviour and cannot emulate another's — rendering with a real binary of that version is the only thing that settles it. See CheckCompatAgainst.
type LintSeverity ¶
type LintSeverity int
LintSeverity ranks a lint finding. Only LintError fails a lint.
const ( // LintWarning is advice: the chart works, but something is worth fixing. LintWarning LintSeverity = iota // LintError means the chart is broken — either outright, or for the engine // version it was linted against. LintError )
func (LintSeverity) String ¶
func (s LintSeverity) String() string
type Maintainer ¶
type Maintainer struct {
Name string `yaml:"name"`
Email string `yaml:"email,omitempty"`
URL string `yaml:"url,omitempty"`
}
Maintainer identifies a chart maintainer.
type NetworkRequirement ¶
type NetworkRequirement struct {
Name string `yaml:"name"`
Driver string `yaml:"driver"` // default "overlay"
Attachable *bool `yaml:"attachable"` // default true
AutoCreate *bool `yaml:"autoCreate"` // default true; false => validate-only
Description string `yaml:"description"`
}
NetworkRequirement declares one external network a chart needs. AutoCreate and Attachable are pointers so an omitted key defaults to true (preserving the historical auto-create-as-attachable-overlay behaviour) while an explicit false is distinguishable. After parseRequirements they are always non-nil and Driver is non-empty.
type OutdatedEntry ¶
type OutdatedEntry struct {
Release string
Chart string
Repo string
Installed string
Latest string
}
OutdatedEntry is one installed release with a newer chart version available.
func Outdated ¶
func Outdated(rels []Release, indexes map[string]*Index) []OutdatedEntry
Outdated joins installed releases against the newest version of their chart in any configured repository index. Releases already at the newest version, and those whose chart appears in no index (a local chart), are omitted.
A Release does not record which repository it came from, so a chart present in two repositories resolves to the highest version across them, reporting the repository that supplied it. That ambiguity is documented rather than designed away: recording the source repository is a change to persisted release state, which is not worth making for a case most users never hit.
type Plan ¶
type Plan struct {
// Releases, in file order.
Releases []ReleasePlan
// Unmanaged names releases that exist on the swarm but are absent from the
// file. Apply never touches them — see Engine.Apply.
Unmanaged []string
}
Plan is what apply would do to the whole swarm.
type PruneAction ¶
type PruneAction struct {
Revision int
Delete bool
Current bool // the live (highest) revision; never deleted
}
PruneAction is the keep/delete decision for one revision in a prune.
type PruneResult ¶
type PruneResult struct {
Release string
Actions []PruneAction
}
PruneResult reports what a prune did (or, for a dry run, would do) for one release. Actions are ascending by revision.
func (PruneResult) Deleted ¶
func (r PruneResult) Deleted() []int
Deleted returns the revision numbers Prune removed (or would remove).
type Release ¶
type Release struct {
Name string `yaml:"release"`
Revision int `yaml:"revision"`
Status string `yaml:"status"`
Chart ReleaseChart `yaml:"chart"`
Values map[string]any `yaml:"values"`
Manifest string `yaml:"manifest"` // rendered Compose document
Created string `yaml:"created"` // RFC3339
Namespace string `yaml:"namespace"`
// ManagedNetworks are the external networks swarmcli auto-created for this
// revision. Persisted so uninstall can report what it left behind (it does
// not remove them — they may be shared). Omitted for revisions that created
// none and for records written before this field existed.
ManagedNetworks []string `yaml:"managedNetworks,omitempty"`
}
Release is the payload stored (gzipped) inside a release-history Config. It fully describes one deployed revision so it can be inspected or rolled back.
type ReleaseChart ¶
type ReleaseChart struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
AppVersion string `yaml:"appVersion,omitempty"`
}
ReleaseChart is the chart reference recorded in a Release.
func ReleaseChartOf ¶
func ReleaseChartOf(ch *Chart) ReleaseChart
ReleaseChartOf projects a loaded chart into the metadata recorded on a release.
type ReleaseFile ¶
type ReleaseFile struct {
APIVersion string `yaml:"apiVersion,omitempty"`
Repositories []RepoSpec `yaml:"repositories,omitempty"`
Releases []ReleaseSpec `yaml:"releases"`
// Dir is the directory containing the file. Values files and local chart
// paths resolve against it, never the process working directory, so the
// manifest is relocatable: a CI job gets the same result no matter where it
// invoked swarmcli from.
Dir string `yaml:"-"`
// Path is the file as given, used to prefix error messages.
Path string `yaml:"-"`
}
ReleaseFile is a declarative release manifest: the desired set of releases on a swarm, plus the repositories their charts come from. It is the GitOps entry point — `charts install` and `charts upgrade` are imperative and release state lives in the swarm, so without this file there is nothing in git for an automated updater (Renovate, Dependabot, a bot of your own) to edit.
The key names deliberately mirror Helmfile's. Renovate ships a `helmfile` manager that reads exactly `repositories[].{name,url}` and `releases[].{name,chart,version}`, so pointing it at this file needs one line of config and no hand-written regex:
{"helmfile": {"managerFilePatterns": ["/(^|/)swarmcli-release\\.ya?ml$/"]}}
Unknown keys are a hard error (see ParseReleaseFile), which also contains the obvious hazard of borrowing another tool's vocabulary: pasting real Helmfile syntax fails loudly and names the key, rather than silently doing half of what was meant.
func LoadReleaseFile ¶
func LoadReleaseFile(path string) (*ReleaseFile, error)
LoadReleaseFile reads and validates a release manifest.
func ParseReleaseFile ¶
func ParseReleaseFile(data []byte, path string) (*ReleaseFile, error)
ParseReleaseFile decodes and validates a release manifest. Unknown keys are rejected: this is a file an automated updater rewrites, so a misspelled `version:` must fail loudly rather than silently leave the release floating.
func (*ReleaseFile) ChartRef ¶
func (rf *ReleaseFile) ChartRef(r ReleaseSpec) string
ChartRef resolves a release's chart reference, joining local paths against the manifest's directory and passing "<repo>/<chart>" references through.
func (*ReleaseFile) ValuesPaths ¶
func (rf *ReleaseFile) ValuesPaths(r ReleaseSpec) []string
ValuesPaths resolves a release's values files against the manifest's directory.
type ReleaseMeta ¶
ReleaseMeta is the .Release object available to templates.
type ReleasePlan ¶
type ReleasePlan struct {
Name string
Ref string
Action Action
// FromVersion is the currently deployed chart version, empty for an install.
FromVersion string
ToVersion string
Chart ReleaseChart
Values map[string]any
Manifest string
Requirements *Requirements
// CurrentManifest is the deployed manifest, for diffing. Empty for an install.
CurrentManifest string
// Compat is the chart's engine requirement checked against this build.
// Planning records it but never acts on it: apply's contract is to plan
// every release before converging any, so the whole plan is gated at once
// by the caller — which is also the layer that knows whether blocking is
// appropriate for the verb being run.
Compat CompatFinding
}
ReleasePlan is the computed desired state of one release.
type ReleaseSpec ¶
type ReleaseSpec struct {
Name string `yaml:"name"`
Chart string `yaml:"chart"`
Version string `yaml:"version,omitempty"`
Values []string `yaml:"values,omitempty"`
}
ReleaseSpec is one desired release.
type RenderContext ¶
type RenderContext struct {
Values map[string]any
Release ReleaseMeta
Chart ChartMeta
}
RenderContext is the data exposed to chart templates, mirroring Helm's top-level objects: .Values, .Release, .Chart.
type RepoStore ¶
type RepoStore struct {
// Warnf, when set, receives non-fatal diagnostics: a chart whose index entry
// publishes no digest, so its integrity could not be verified, and a
// repository whose index could not be refreshed, so a cached one is in use.
// charts is a library with no output of its own; nil is silent, and cli wires
// this to stderr.
Warnf func(format string, a ...any)
// contains filtered or unexported fields
}
RepoStore persists configured repositories and caches their indexes under a base directory (default: the XDG state dir, ~/.local/state/swarmcli/charts).
func NewRepoStore ¶
NewRepoStore returns a store rooted at the standard charts state directory.
func NewRepoStoreAt ¶
NewRepoStoreAt returns a store rooted at dir (used in tests).
func (*RepoStore) Add ¶
Add registers a repository and downloads its index. It rejects duplicate names and invalid URLs.
func (*RepoStore) EnsureRepos ¶
EnsureRepos makes the repositories a release manifest declares available, adding those that are absent and refreshing the rest. It exists so that `charts apply -f file` is the only command a CI job needs to run.
What it writes is a name-to-URL mapping plus a cached index — a cache, not user data. The one thing it will not do is silently repoint an existing repository at a different origin.
func (*RepoStore) Indexes ¶
Indexes returns the cached index of every configured repository, keyed by repository name. Repositories with no cached index are skipped, as in Search.
func (*RepoStore) Pull ¶
func (s *RepoStore) Pull(entry IndexEntry, baseURL string) (*Chart, error)
Pull downloads and loads the chart described by entry, resolving relative URLs against baseURL.
func (*RepoStore) Resolve ¶
func (s *RepoStore) Resolve(ref, version string) (IndexEntry, string, error)
Resolve looks up a "repo/chart" reference and returns the chosen index entry (the requested version, or the latest when version is empty) plus the repo's base URL for resolving relative tarball URLs.
type Requirements ¶
type Requirements struct {
Networks []NetworkRequirement `yaml:"networks"`
Secrets []ResourceRequirement `yaml:"secrets"`
Configs []ResourceRequirement `yaml:"configs"`
}
Requirements is the parsed, defaulted requirements.yaml: the external networks/secrets/configs a chart needs. It is optional — a chart without it falls back to manifest-driven pre-flight. When present it is authoritative: every external resource the rendered manifest references must be declared.
func RenderRequirements ¶
func RenderRequirements(ch *Chart, ctx RenderContext) (*Requirements, error)
RenderRequirements renders the chart's requirements.yaml through the same template engine and context as the manifest, then parses the result. This lets requirements.yaml reference .Values (e.g. an operator-chosen network name) while staying authoritative — the declared names are resolved against the same values that produced the manifest. Returns (nil, nil) when the chart ships no requirements.yaml.
Templated values must be quoted (name: "{{ .Values.x }}") so requirements.yaml still parses as YAML at chart-load time; the real value is resolved here, at the install/upgrade pre-flight.
type ResourceRequirement ¶
type ResourceRequirement struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
}
ResourceRequirement declares one external secret or config a chart needs. These cannot be auto-created; Description enriches the remediation message.
type ServiceState ¶
type ServiceState struct {
Name string
Mode string
Replicas string // "running/desired" for replicated, "" otherwise
Status string
}
ServiceState is a minimal live status line for a release's services.
type UninstallResult ¶
type UninstallResult struct {
OrphanedNetworks []string
}
UninstallResult reports what an uninstall left behind. OrphanedNetworks are the external networks swarmcli auto-created for the release that still exist after the stack is removed — `docker stack rm` does not remove external networks, and swarmcli deliberately leaves them (they may be shared with other stacks) and reports them instead.