Documentation
¶
Overview ¶
Package container is the spec fabric slice for container-engine host helpers — resolving which engine binary to invoke, its GPU run-args, and auto-detecting the installed engine. RELOCATED from sdk/kit (#55 fabric-primitive extraction). It carries os/exec (the engine auto-detect shells `LookPath`) in its OWN slice (Rule 2) so a consumer needing only value types never drags os/exec. charly core inlines from here; sdk/kit re-exports the same symbols so existing kit.EngineBinary / kit.GPURunArgs / kit.DetectEngine call sites are untouched.
spec/container/transfer.go — the container-engine image-transfer host primitive, RELOCATED from sdk/kit by #55 coneC (charly/ off sdk/kit): it pipes an image from one engine's local store to another via `save | load` (os/exec), the fabric twin of the LocalImageExists probe that already lives in this slice. sdk/kit re-exports it (var TransferImage = container.TransferImage) so every existing kit.TransferImage call site (candy/plugin-build, candy/plugin-box, candy/plugin-deploy-pod, …) is unchanged; charly core inlines from here. Co-located with EngineBinary (same package) and the LocalImageExists family this transfer path complements.
Index ¶
- Variables
- func ContainerImage(engine, containerName string) string
- func ContainerImageRef(engine, containerName string) (string, error)
- func DetectEngine() (string, error)
- func EngineBinary(engine string) string
- func ExtractCalVerTag(ref string) string
- func ExtractMetadata(engine, imageRef string) (*spec.BoxMetadata, error)
- func GPURunArgs(engine string) []string
- func InspectImageLabels(engine, imageRef string) (map[string]string, error)
- func IsHostNetworked(engine, containerName string) bool
- func LooksLikeFullRef(ref string) bool
- func ParsePublishedPort(output string, port int) (string, error)
- func ResolveLocalImageRef(engine, input string) (string, error)
- func ResolveNewestLocalCalVer(engine, short string) (string, error)
- func ResolveShellImageRef(registry, name, tag string) string
- func TransferImage(srcEngine, dstEngine, imageRef string) error
- type LocalImageInfo
Constants ¶
This section is empty.
Variables ¶
var InspectLabels = InspectImageLabels
InspectLabels reads OCI labels from a local image via engine inspect. Package-level var for testability — defaults to the canonical InspectImageLabels (spec/container/image_inspect.go, coneA). Override this var (not kit/deploykit's re-exports) to stub label reads in tests of ExtractMetadata's decode logic.
var ListLocalImages = defaultListLocalImages
ListLocalImages returns all images in the engine's local storage. Package-level var for testability (same pattern as LocalImageExists, DetectEngine).
var LocalImageExists = defaultLocalImageExists
LocalImageExists checks whether an image reference exists in the given engine's local store. Package-level var for testability (same pattern as DetectEngine). Co-located with the resolution family because ResolveLocalImageRef reads it; kit re-exports it (kit.LocalImageExists = container.LocalImageExists) so existing direct callers (candy/plugin-build, candy/plugin-box, candy/plugin-deploy-pod, candy/plugin-kube, charly core) are unchanged.
Functions ¶
func ContainerImage ¶
ContainerImage returns the image ref for a running container, best-effort ("" on error). Thin wrapper over ContainerImageRef.
func ContainerImageRef ¶
ContainerImageRef returns the image ref backing a running container (.Config.Image via `<engine> inspect`). THE single container→image-ref inspector — there is exactly one inspect implementation.
func DetectEngine ¶
DetectEngine auto-detects the container engine: prefers podman, falls back to docker.
func EngineBinary ¶
EngineBinary returns the CLI binary name for a container engine. "auto" resolves via DetectEngine (podman preferred), falling back to "docker".
func ExtractCalVerTag ¶
ExtractCalVerTag returns the CalVer portion of a ref's tag, or "" if the tag is not a recognisable CalVer (`YYYY.DDD.HHMM`). Lets the resolver distinguish CalVer tags from legacy floats like `:latest` (which should never be chosen as the newest candidate).
func ExtractMetadata ¶
func ExtractMetadata(engine, imageRef string) (*spec.BoxMetadata, error)
ExtractMetadata reads OCI labels from a local image and returns parsed spec.BoxMetadata. Returns nil if the image has no ai.opencharly labels. Returns spec.ErrImageNotLocal wrapped with the image ref if the image is not in local storage.
func GPURunArgs ¶
GPURunArgs returns the engine-specific run flags that expose all host GPUs to a container.
func InspectImageLabels ¶
InspectImageLabels reads a local image's OCI labels via engine inspect. Pure container-storage probe: no charly-core coupling.
func IsHostNetworked ¶
IsHostNetworked checks if a running container uses --network host.
func LooksLikeFullRef ¶
LooksLikeFullRef returns true if the image ref contains a registry segment (a "/" before any ":") — e.g. "ghcr.io/org/name:tag" — so it can be pulled without charly.yml resolution.
func ParsePublishedPort ¶
ParsePublishedPort extracts the host "ip:port" from `<engine> port` output for an in-container port, normalizing 0.0.0.0 / [::] to 127.0.0.1.
func ResolveLocalImageRef ¶
ResolveLocalImageRef resolves a user-supplied image reference against the engine's local storage — never reads charly.yml. Used by test-mode commands (charly check live, charly check box) so they stay within the test-mode input set.
For full refs (registry prefix present) it validates the image exists locally and passes through unchanged. For short names it resolves via CalVer: collect every candidate ref and pick the one with the highest `ai.opencharly.version` label (falling back to the highest tag CalVer). charly is CalVer-only — no `:latest` fallback. See `/charly-build:build` "CalVer-only" for the contract.
A candidate ref must satisfy BOTH halves: its image is identified as the short name (preferred: an `ai.opencharly.image=<short>` label; fallback: no such label) AND the ref ITSELF is named `<short>` in its trailing repo component. The second half is not cosmetic — a label-family image accumulates the deploy-name alias tags of every OTHER deployment built on the same base box, and they inherit its label, so without it an untagged resolve can return a sibling deployment's image (see the invariant comment in the label branch below).
Returns `spec.ErrImageNotLocal` when nothing matches. An ambiguous result across multiple repos with the same highest CalVer tag surfaces as an explicit error asking for a full ref.
func ResolveNewestLocalCalVer ¶
ResolveNewestLocalCalVer is the canonical "find the newest local image for this short name" helper. Thin wrapper around ResolveLocalImageRef — exposed so callers that start with an explicit short-name + empty-tag can resolve uniformly.
func ResolveShellImageRef ¶
ResolveShellImageRef builds the full image reference from registry, name, and tag, for a caller about to run an engine command (podman/docker) against it. When tag is empty, it resolves to the newest local CalVer for the given short name via ResolveNewestLocalCalVer — the CalVer-only contract (`/charly-build:build` "Cache Efficiency"). A caller that wants a specific tag passes it; a caller whose `--tag` flag is empty gets the newest CalVer with no extra work. When registry is set AND tag is empty, there's no way to guess a remote CalVer without a registry-list call, so the caller gets `<registry>/<name>` back with no tag suffix — the engine resolves it locally first (matching any single local tag) or errors. (P14: relocated from charly/shell.go's resolveShellImageRef, which now delegates here — R3, single source for every caller: candy/plugin-box's `merge` command plus charly core's own fleet_add/config_image/ensure_image/remote_image/pod_lifecycle_resolve/update_deploy_dispatch.)
func TransferImage ¶
TransferImage pipes an image from one engine to another via save | load.
Types ¶
type LocalImageInfo ¶
type LocalImageInfo struct {
ID string // image ID (sha256:...) — used by `charly clean` to skip in-use images
Names []string // Full refs: ["ghcr.io/opencharly/jupyter:latest", ...]
Labels map[string]string // OCI labels from the image config
Size int64 // reported storage size in bytes (podman's "Size" field; 0 if absent/unparsed)
}
LocalImageInfo describes an image present in the engine's local storage. Populated by ListLocalImages from `{podman,docker} images --format json`.
func ParseLocalImagesJSON ¶
func ParseLocalImagesJSON(out []byte) ([]LocalImageInfo, error)
ParseLocalImagesJSON parses `{podman,docker} images --format json` output into ONE LocalImageInfo per distinct image ID, with that id's tag refs merged into Names.
This dedup is load-bearing: podman emits ONE ROW PER TAG, and each row's Names array already lists EVERY tag on that id. A naive row-by-row mapping therefore produces N near-identical entries for an id with N tags — which made `charly clean`'s keep-N retention over-count entries and, worse, remove an id's whole Names array per "extra" entry (deleting tags it meant to keep). Collapsing to one-id-with-a-tag-list matches the struct's shape and what every consumer (retention prune, short-name resolver) expects.
Empty-id rows (dangling/untagged) are kept separate via a per-row sentinel key so they never merge into one another.