Documentation
¶
Overview ¶
Package plugins mirrors d8 CLI plugins into the images bundle.
Plugins live in a single registry catalog OUTSIDE the edition segment (same asymmetry as the installer):
<root>/deckhouse-cli/plugins - catalog; its tags are plugin names <root>/deckhouse-cli/plugins/<name>:<vX.Y.Z> - one plugin version (multi-platform OCI index)
A plugin declares its requirements (Deckhouse modules, other plugins, platform versions) in a contract: a base64-JSON annotation on the image manifest. Reading a contract is a single manifest fetch, so deciding WHAT to mirror needs no layer downloads.
Selection principle: nothing extra, with one standing exception. A plugin enters the bundle when a mirrored module needs it (its contract names that module), when another selected plugin requires it, or when the user asks for it explicitly with --include-plugin.
The exception is PlatformPlugins: they ship with the platform rather than with any module, so mirroring the platform mirrors them too, unconditionally. A bundle without them can install the platform but not operate it.
A dependency whose name matches a built-in d8 command is mirrored when it is published and falls back to the built-in when it is not, so it can never block the bundle - see ResolveInput.Builtins.
Index ¶
Constants ¶
const PlatformSubject = "platform"
PlatformSubject is the Reason.Subject of a ReasonPlatform edge - the plugin was pulled because the platform was mirrored, not because any module asked for it.
Variables ¶
var ErrInvalidContract = errors.New("invalid plugin contract")
ErrInvalidContract marks a deterministic content problem of a published contract (broken base64, malformed JSON, failed domain validation). The resolver skips such versions and tries older ones; transport errors never carry this sentinel and fail the pull instead.
var PlatformPlugins = []string{"package", "system"}
PlatformPlugins ship with the Deckhouse platform rather than with a module, so mirroring the platform mirrors them too - unconditionally, with no module pairing and regardless of --include-plugin. Without them a bundle can install the platform but not operate it.
The names match the built-in commands of the same name (see SystemPluginName and PackagePluginName in internal/plugins/cmd): a plugin takes the command over once installed, so the bundle must carry it.
Functions ¶
This section is empty.
Types ¶
type Catalog ¶
type Catalog interface {
// PluginNames lists the plugin names published in the catalog.
PluginNames(ctx context.Context) ([]string, error)
// PluginVersions lists a plugin's published stable versions, newest
// first. Non-semver tags (werf build junk) and genuine pre-releases are
// dropped - the same notion of "stable" that plugin install uses.
PluginVersions(ctx context.Context, name string) ([]*semver.Version, error)
// Contract returns the decoded contract of one plugin version. An image
// without a contract annotation yields a degenerate {Name, Version}
// contract, not an error.
Contract(ctx context.Context, name string, version *semver.Version) (*internal.Plugin, error)
}
Catalog is the resolver's read model of the plugins registry catalog. Results are memoized for the lifetime of the catalog (one pull), so however many resolution paths probe the same plugin, the registry is asked once.
func NewCatalog ¶
func NewCatalog(service *registryservice.PluginsService, logger *dkplog.Logger) Catalog
NewCatalog creates a memoizing catalog over the plugins registry service.
type ModuleInBundle ¶
ModuleInBundle is one mirrored module with the exact versions selected into the bundle. The pull orchestrator builds this list from the modules phase stats and hands it to the plugins phase.
type Options ¶
type Options struct {
// Filter carries --include-plugin expressions (whitelist, additive to the
// module-driven auto-selection). May be nil.
Filter *modules.Filter
// Builtins are d8 built-in command names that satisfy a same-named plugin
// dependency by presence (never pulled).
Builtins map[string]struct{}
// BundleDir is the directory to store the bundle.
BundleDir string
// BundleChunkSize is the max size of bundle chunks in bytes (0 = no chunking).
BundleChunkSize int64
// DryRun prints the pull plan without downloading any image blobs.
DryRun bool
// ProxyRegistry means the registry serves no catalog: auto-selection is
// impossible, only explicit exact pins are resolved.
ProxyRegistry bool
}
Options contains configuration options for the plugins service.
type PluginStat ¶
type PluginStat struct {
Name string
Images int
// Versions are the pulled versions, newest first. Filled at resolution
// time, so available in dry-run too.
Versions []PluginVersionStat
}
PluginStat is one plugin's contribution to the pull.
type PluginToMirror ¶
type PluginToMirror struct {
Name string
// Versions to pull, newest first. Several versions appear when different
// bundled module versions need different plugin versions.
Versions []SelectedVersion
}
PluginToMirror is the resolver's verdict for one plugin.
type PluginVersionStat ¶
PluginVersionStat is one pulled plugin version with its provenance, ready for the summary's per-module grouping.
type PluginsStats ¶
type PluginsStats struct {
Attempted bool
Plugins []PluginStat
Skipped []SkippedPlugin
Warnings []string
TotalImages int
}
PluginsStats is the plugins phase's accounting, mapped into the top-level summary by the pull orchestrator.
type PullInput ¶
type PullInput struct {
// Modules are the mirrored modules with their bundled versions.
Modules []ModuleInBundle
// PlatformVersions are the mirrored Deckhouse platform versions.
PlatformVersions []*semver.Version
}
PullInput is the cross-phase handoff: what the earlier pull phases put into the bundle. Built by the pull orchestrator, never by this package.
type Reason ¶
type Reason struct {
Kind ReasonKind
Subject string
// Constraint is the requirement constraint that created the edge,
// empty when none was declared.
Constraint string
}
Reason is one provenance edge of a selected plugin version: who needed it and under which constraint. The summary renders these edges as the per-module plugin tree.
type ReasonKind ¶
type ReasonKind int
ReasonKind classifies why a plugin version is in the bundle.
const ( // ReasonModule marks a plugin required by a mirrored module. // Reason.Subject is the module name. ReasonModule ReasonKind = iota // ReasonDependency marks a mandatory dependency of another selected // plugin. Reason.Subject is "<dependent>@<version>". ReasonDependency // ReasonExplicit marks a plugin named by --include-plugin. // Reason.Subject is the flag expression. ReasonExplicit // ReasonPlatform marks a plugin that ships with the platform and is // therefore pulled whenever the platform is mirrored, with no module // pairing. Reason.Subject is PlatformSubject. ReasonPlatform )
func (ReasonKind) String ¶
func (k ReasonKind) String() string
String returns the stable lowercase label of the kind, used by the pull summary ("module", "dependency", "explicit").
type Resolution ¶
type Resolution struct {
// Plugins to mirror, sorted by name for deterministic output.
Plugins []PluginToMirror
Skipped []SkippedPlugin
// Warnings are advisories that do not block the pull (e.g. an explicitly
// included plugin whose required module is not in the bundle).
Warnings []string
}
Resolution is the resolver's full output.
type ResolveInput ¶
type ResolveInput struct {
// Modules are the modules mirrored into this bundle with their versions.
// Empty when modules were not mirrored: nothing is auto-selected then and
// only explicit --include-plugin entries are resolved.
Modules []ModuleInBundle
// PlatformVersions are the mirrored Deckhouse platform versions. Empty
// when the platform phase was skipped; the contract's deckhouse
// constraint is then not checked.
PlatformVersions []*semver.Version
// Filter carries --include-plugin expressions. Explicit picks are
// additive: they are pulled on top of the module-driven selection.
Filter *modules.Filter
// Builtins are d8 built-in command names (e.g. delivery-kit, package)
// that satisfy a same-named plugin dependency by presence, so such a
// dependency never blocks the bundle. The plugin is still mirrored when
// the registry publishes it - once installed it takes the command over,
// and an air-gapped cluster has no other way to obtain it.
Builtins map[string]struct{}
// NoCatalog means the registry serves no plugin version listing
// (--proxy-registry). Dependencies then resolve only against versions
// the user pinned explicitly; nothing is looked up.
NoCatalog bool
}
ResolveInput is everything the resolver knows about the bundle being built.
type Resolver ¶
type Resolver interface {
Resolve(ctx context.Context, in ResolveInput) (*Resolution, error)
}
Resolver picks which plugin versions belong to the bundle.
type SelectedVersion ¶
SelectedVersion is one plugin version to mirror, with its provenance.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the plugins phase of mirror pull: resolve which plugin versions the bundle needs, pull them (multi-platform indexes whole), pack one plugin-<name>.tar per plugin.
func NewService ¶
func NewService( registryService *registryservice.Service, workingDir string, options *Options, logger *dkplog.Logger, userLogger *log.SLogger, ) *Service
NewService creates the plugins phase service.
func (*Service) PullPlugins ¶
PullPlugins mirrors the plugins the bundle needs: plugins whose contracts name the mirrored modules (per bundled module version), their mandatory plugin dependencies, and explicit --include-plugin entries.
func (*Service) Stats ¶
func (svc *Service) Stats() PluginsStats
Stats returns accounting for the plugins phase.
type SkippedPlugin ¶
SkippedPlugin is a plugin the resolver considered and dropped, with the reason spelled out for the summary (e.g. `requires module "postgresql" >=2.0.0, bundle has v1.4.1`).