Documentation
¶
Overview ¶
Package bundle is the charly plugin housing the `charly bundle …` deployment CLI. It is a dual-placement command plugin (F8) mirroring candy/plugin-vm: the SAME NewProvider()/NewMeta()/ CliMain compile INTO charly in-process when listed in compiled_plugins (the canonical placement, P13), or cmd/serve serves them OUT-OF-PROCESS when they are not. It provides ONE capability —
- command:bundle — `charly bundle add / del / show / export / import / reset / path / status / from-box`, the deployment CLI. COMPILED-IN, it dispatches IN-PROC via Invoke(OpRun) (runBundleCommand → kong-parse the BundleCmd tree — command.go), so the handlers run in charly's OWN process and inherit charly's real stdio/TTY natively. `add`/`del` (walk.go, the K4-C WALK PORT) drive the WHOLE deploy-tree walk plugin-side: the config loader (the merged-tree read, LoadUnified-coupled) + the del RESOLUTION (del_resolve.go, K-wave 2 cone R2 bank C) run plugin-side; the registry-backed executor-chain derivation (deriveChildExecutorForPath) stays host-side behind three narrow seams — deploy-plugins-connect / resolve-target-add / deploy-node-del-dispatch — while the tree traversal AND the per-node compile (compilePlansForRequest, IN-PROC after K4-C shape-2 — no OpCompile round-trip) run plugin-side; ResolveTarget → the deploy target's Add/Del is the host tail of the resolve-target-add / deploy-node-del-dispatch seams. Sibling `peer:` member bring-up/tear-down calls sdk/deploykit.BringUpMembers/TearDownMembers directly (#55 W3 A4 — the former deploy-members-up/-down seams are deleted). `from-box` runs fully plugin-side since K-wave 2 cone R2 (runFromBoxPod reaches deploy:pod's OpConfigSetup by direct InvokeProvider; the "deploy-from-box" seam is deleted); the config-management leaves (show/export/import/reset/status) run plugin-side — reads via loaderkit.LoadHostBundleConfigViaExecutor, writes via deploykit.SaveBundleConfig directly (#55 K4 config-write seam-collapse). `path` resolves plugin-side via kit.DefaultDeployConfigPath (no seam).
A standalone Go module (its own go.mod) importing ONLY the sdk module, compiled into charly for the canonical placement. The capability is advertised in Describe (NewMeta); command:bundle's grammar is prescanned into the CLI from plugin.providers.
Index ¶
- func CliMain(_ []string) int
- func DeployFromBox(ctx context.Context, exec *sdk.Executor, opts DeployFromBoxOpts) (string, error)
- func GenerateK8sKustomize(ctx context.Context, exec *sdk.Executor, opts K8sGenerateOpts) (string, error)
- func NewMeta() pb.PluginMetaServer
- func NewProvider() pb.ProviderServer
- func ValidateEgress(kind, label string, data []byte) error
- func ValidateEgressValue(kind, label string, v any) error
- type BundleAddCmd
- type BundleCmd
- type BundleDelCmd
- type BundleExportCmd
- type BundleFromBoxCmd
- type BundleImportCmd
- type BundlePathCmd
- type BundleResetCmd
- type BundleShowCmd
- type BundleStatusCmd
- type DeployFromBoxOpts
- type DeployRef
- type K8sGenerateOpts
- type RefKind
- type RefSource
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CliMain ¶
CliMain is the OUT-OF-PROCESS command entry — unreachable in the canonical compiled-in placement. command:bundle's handlers reach the host reverse channel (the deploy-add/del/from-box dispatch + the deploy-config seam), which is unavailable out-of-process, so this errors (like plugin-vm's CliMain).
func DeployFromBox ¶
DeployFromBox performs the source-less deploy. Returns the absolute path to the Kustomize overlay directory produced (the argument to `kubectl apply -k`).
func GenerateK8sKustomize ¶
func GenerateK8sKustomize(ctx context.Context, exec *sdk.Executor, opts K8sGenerateOpts) (string, error)
GenerateK8sKustomize dispatches to candy/plugin-kube's deploy:k8s OpEmit (materializeKustomize) via exec.InvokeProvider — the plugin-side replacement for the former core providerRegistry.ResolveDeploy("k8s") + InvokeWithExecutor registry dance. Returns the absolute path to the overlay that `kubectl apply -k` should target.
func NewMeta ¶
func NewMeta() pb.PluginMetaServer
NewMeta advertises command:bundle. The served schema carries no #*Input def — a command's args are pass-through CLI tokens, not a structured plugin_input — so the capability has no InputDef. command:bundle is COMPILED-IN and dispatched IN-PROC via Invoke(OpRun) (runBundleCommand, command.go); its grammar is prescanned into the CLI from plugin.providers.
func NewProvider ¶
func NewProvider() pb.ProviderServer
NewProvider returns the bundle provider (command:bundle Invoke surface).
func ValidateEgress ¶
ValidateEgress validates already-serialized YAML or JSON bytes against the egress kind's schema before they are written. JSON is a YAML subset, so one ingest path covers both.
func ValidateEgressValue ¶
ValidateEgressValue validates an in-memory Go value (a manifest map[string]any, a record struct) by marshalling it to JSON and validating as bytes — faithful for the data values egress gates (k8s manifests, ledger records).
Types ¶
type BundleAddCmd ¶
type BundleAddCmd struct {
Name string `arg:"" help:"Deploy name ('host' for local system; any other string is a container deploy name)"`
Ref string `arg:"" optional:"" help:"Box or candy reference (local name, ./path.yml, or github.com/org/repo[/box/<n>|/candy/<n>][@ref])"`
// Candy overlays (repeatable).
AddCandy []string `name:"add-candy" help:"Extra candy to apply on top of the base image (repeatable)"`
// Plan-level flags.
Tag string `name:"tag" help:"Image CalVer tag (empty = newest local CalVer resolved via the ai.opencharly.version OCI label)"`
DryRun bool `name:"dry-run" help:"Print the plan without executing"`
NodeOnly bool `` /* 147-byte string literal not displayed */
Format string `name:"format" default:"table" enum:"table,json" help:"Output format for --dry-run"`
Pull bool `name:"pull" help:"Force re-fetch of remote refs / image pull"`
Verify bool `name:"verify" help:"Re-run candy tests: on the host after install"`
// Host-only gates.
WithServices bool `name:"with-services" help:"Install systemd services (host target only)"`
AllowRepoChanges bool `name:"allow-repo-changes" help:"Allow repo config mutations (host target only)"`
AllowRootTasks bool `name:"allow-root-tasks" help:"Allow arbitrary root cmd: tasks (host target only)"`
SkipIncompatible bool `name:"skip-incompatible" help:"Skip candies without host-matching format (host target only)"`
BuilderImage string `name:"builder-image" help:"Override the compile builder image"`
DevLocalPkg bool `` /* 340-byte string literal not displayed */
AssumeYes bool `name:"assume-yes" short:"y" help:"Assume yes; implies all allow-* gates plus skip sudo preflight"`
// Disposable + lifecycle classification (see /charly-internals:disposable).
Disposable bool `` /* 131-byte string literal not displayed */
Lifecycle string `` /* 147-byte string literal not displayed */
// contains filtered or unexported fields
}
BundleAddCmd is the `charly bundle add <name> [<ref>]` grammar; it forwards to the deploy-add host-build seam, which runs the core add orchestration VERBATIM.
func (*BundleAddCmd) Run ¶
func (c *BundleAddCmd) Run() error
Run executes `charly bundle add` (plugin-side walk; the deploy-add host-build seam it used to forward the WHOLE Run() to is retired).
type BundleCmd ¶
type BundleCmd struct {
Add BundleAddCmd `cmd:"" help:"Apply a deploy: 'host' targets the local system; any other name targets a container"`
Del BundleDelCmd `cmd:"" help:"Tear down a deploy by name"`
FromImage BundleFromBoxCmd `` /* 149-byte string literal not displayed */
Export BundleExportCmd `cmd:"" help:"Export effective config as charly.yml"`
Import BundleImportCmd `cmd:"" help:"Import charly.yml file(s) into config"`
Path BundlePathCmd `cmd:"" help:"Print charly.yml file path"`
Reset BundleResetCmd `cmd:"" help:"Remove charly.yml overrides"`
Show BundleShowCmd `cmd:"" help:"Show current charly.yml overrides"`
Status BundleStatusCmd `cmd:"" help:"Show sync status between charly.yml and quadlet files"`
}
BundleCmd is the `charly bundle …` command group — the CLI grammar the compiled-in command:bundle plugin contributes to charly's Kong tree (dispatched in-proc via Invoke(OpRun) → dispatchBundleCLI).
type BundleDelCmd ¶
type BundleDelCmd struct {
Name string `arg:"" help:"Deploy name (literal 'host' or a container deploy name)"`
AssumeYes bool `name:"assume-yes" short:"y" help:"Skip confirmation prompts"`
KeepRepoChanges bool `name:"keep-repo-changes" help:"Don't revert repo config even at zero refcount"`
KeepServices bool `name:"keep-services" help:"Don't disable systemd units (just stop tracking)"`
KeepImage bool `name:"keep-image" help:"Don't remove the synthesized overlay image (container target only)"`
DryRun bool `name:"dry-run" help:"Print the teardown plan without executing"`
}
BundleDelCmd is the `charly bundle del <name>` grammar; Run() (walk.go) drives the deploy-del-resolve / deploy-node-del-dispatch seams plus a direct deploykit.TearDownMembers call (#55 W3 A4 — the former deploy-members-down HostBuild seam is deleted). The AssumeYes field renders as `--assume-yes`, stated by an explicit `name:` tag rather than left to Kong's derivation from the field, with `-y` as the short form — the exact contract spec.BundleDelArgv relies on.
func (*BundleDelCmd) Run ¶
func (c *BundleDelCmd) Run() error
Run executes `charly bundle del` (plugin-side; the deploy-del host-build seam it used to forward the WHOLE Run() to is retired). The ledger lock spans resolve → members-down → node-del-dispatch — kit.AcquireLedgerLock is a pure sdk/kit filesystem primitive, so acquiring it plugin-side (the compiled-in placement shares charly's own process/filesystem) reproduces the SAME lock scope the OLD in-core Run() held.
type BundleExportCmd ¶
type BundleExportCmd struct {
Boxes []string `arg:"" optional:"" help:"Boxes to export (default: all with overrides)"`
Output string `short:"o" help:"Write to file instead of stdout"`
All bool `help:"Export all enabled boxes with all runtime fields"`
}
BundleExportCmd is the `charly bundle export [boxes…]` grammar (K4-C: runs plugin-side; --all reaches the project via the established InvokeProvider("build","project") seam).
func (*BundleExportCmd) Run ¶
func (c *BundleExportCmd) Run() error
type BundleFromBoxCmd ¶
type BundleFromBoxCmd struct {
Ref string `arg:"" help:"Full image ref (local or registry), e.g. ghcr.io/opencharly/selkies-kde-nvidia:latest"`
Name string `arg:"" optional:"" help:"Deploy name (default: the image-ref basename without tag)"`
Instance string `short:"i" name:"instance" help:"Instance name"`
Env []string `short:"e" name:"env" sep:"none" help:"Set container env var (KEY=VALUE)"`
Port []string `short:"p" help:"Remap host port (newHost:containerPort)"`
Cluster string `name:"cluster" help:"Target a K8s cluster profile instead of a local pod (emits Kustomize via the K8s from-box path)"`
Namespace string `name:"namespace" help:"K8s namespace override (--cluster only)"`
}
BundleFromBoxCmd is the `charly bundle from-box <ref> [name]` grammar. The pod path (default) runs ENTIRELY plugin-side (from_box_pod.go — a source-less deploy from an image's baked OCI labels, reaching deploy:pod's OpConfigSetup directly, no HostBuild round-trip); the --cluster path (Cone A shape 3) is handled plugin-side too — see deploy_from_box.go — reaching the k8s cluster lookup + the deploy:k8s substrate directly.
func (*BundleFromBoxCmd) Run ¶
func (c *BundleFromBoxCmd) Run() error
type BundleImportCmd ¶
type BundleImportCmd struct {
Files []string `arg:"" help:"Deploy YAML files to import (merged left-to-right)"`
Replace bool `help:"Replace entire charly.yml instead of merging with existing"`
Box string `name:"box" help:"Import only this box's config"`
}
BundleImportCmd is the `charly bundle import <files…>` grammar (K4-C: runs plugin-side; the SAVE step writes plugin-side too — deploykit.SaveBundleConfig, #55 K4 config-write seam-collapse).
func (*BundleImportCmd) Run ¶
func (c *BundleImportCmd) Run() error
type BundlePathCmd ¶
type BundlePathCmd struct{}
BundlePathCmd is the `charly bundle path` grammar. It resolves the per-host deploy-overlay path entirely plugin-side (kit.DefaultDeployConfigPath — the SAME resolver core's DeployConfigPath aliases, R3), so it needs no host seam.
func (*BundlePathCmd) Run ¶
func (c *BundlePathCmd) Run() error
type BundleResetCmd ¶
type BundleResetCmd struct {
Box string `arg:"" optional:"" help:"Box to reset (omit to clear all)"`
Instance string `short:"i" name:"instance" help:"Instance name"`
}
BundleResetCmd is the `charly bundle reset [box]` grammar (K4-C: runs plugin-side; the SAVE step writes plugin-side too — deploykit.SaveBundleConfig, #55 K4 config-write seam-collapse).
func (*BundleResetCmd) Run ¶
func (c *BundleResetCmd) Run() error
type BundleShowCmd ¶
type BundleShowCmd struct {
Box string `arg:"" optional:"" help:"Show overrides for a specific box"`
Instance string `short:"i" name:"instance" help:"Instance name"`
}
BundleShowCmd is the `charly bundle show [box]` grammar (K4-C: runs entirely plugin-side — deploykit.LoadBundleConfig/DeployKey are already sdk-portable, no seam needed).
func (*BundleShowCmd) Run ¶
func (c *BundleShowCmd) Run() error
type BundleStatusCmd ¶
type BundleStatusCmd struct{}
BundleStatusCmd is the `charly bundle status` grammar (K4-C: runs entirely plugin-side).
func (*BundleStatusCmd) Run ¶
func (c *BundleStatusCmd) Run() error
type DeployFromBoxOpts ¶
type DeployFromBoxOpts struct {
Engine string // "podman" | "docker" (auto-detected if empty)
ImageRef string // fully-qualified registry/name:tag
DeploymentName string // optional override; defaults to the basename of ImageRef without tag
Instance string // optional "image/instance" suffix
ClusterName string // cluster profile name
Namespace string // optional override of the cluster's default namespace
DeployOverlay *spec.Deploy
OutputDir string // defaults to <cwd>/.opencharly/k8s
ProjectDir string // for the self-loaded kind:k8s cluster lookup (resolveK8sSpec)
}
DeployFromBoxOpts carries the source-less-deploy inputs.
type DeployRef ¶
type DeployRef struct {
Raw string // original input
Kind RefKind // box or candy
Source RefSource // local-name | local-path | remote
Name string // resolved short name (ripgrep, fedora-coder, …)
Path string // absolute path (local-path only; unset for local-name)
Remote *spec.ParsedRef // populated for remote refs
}
DeployRef is a parsed `<box-or-candy-ref>`. The plugin resolver populates Raw/Kind/Source/Name (and Remote for a remote ref) — the compile is off the envelope, so no host-side Path load is needed (the host resolver's Path field is deliberately unused here).
type K8sGenerateOpts ¶
type K8sGenerateOpts struct {
DeploymentName string // the deployment's base name
Instance string // "" for the bare overlay; non-empty for image/instance
ImageRef string // fully qualified image ref (registry/name:tag)
Deploy spec.Deploy
Capabilities *spec.BoxMetadata
Cluster *spec.ResolvedK8s
OutputDir string // usually <projectDir>/.opencharly/k8s
}
K8sGenerateOpts carries the inputs a Kustomize emit needs.
Source Files
¶
- box_select.go
- builder_preresolve.go
- bundle_cmd.go
- candy_select.go
- command.go
- compile.go
- config_cmd.go
- del_resolve.go
- deploy_from_box.go
- deploy_ref.go
- deploy_target.go
- dispatch.go
- egress.go
- ephemeral.go
- from_box_pod.go
- host_seams.go
- load_executor.go
- members_persist.go
- node_resolve.go
- plugin.go
- secrets_artifacts.go
- verify_local.go
- walk.go