Documentation
¶
Overview ¶
Package docker wraps the official Docker SDK with the small surface hope needs: list containers grouped into compose stacks by label, control a single container, and open log/stat streams. Domain types here are plain JSON shapes for the frontend — they do not leak SDK types over the wire.
Index ¶
- Constants
- func PluginNetAlias(containerID string) string
- func ReplicaAlias(project, service string) string
- func WithManaged(in map[string]string) map[string]string
- type API
- type Client
- func (c *Client) AddRegistryCreds(server, user, pass string, source RegistrySource)
- func (c *Client) AllUpdates(ctx context.Context) ([]ClusterUpdate, time.Time, error)
- func (c *Client) AttachNetwork(ctx context.Context, containerID, netName string, aliases []string) error
- func (c *Client) AuthedRegistries() []string
- func (c *Client) BuildImageStream(ctx context.Context, dockerfile, tag string, emit func(string)) error
- func (c *Client) CachedStatus(ref string) string
- func (c *Client) Close() error
- func (c *Client) Connectors(ctx context.Context) ([]Connector, error)
- func (c *Client) ContainerImage(ctx context.Context, id string) (string, error)
- func (c *Client) ContainerMatchInfo(ctx context.Context, id string) (image string, labels map[string]string, err error)
- func (c *Client) ContainerName(ctx context.Context, id string) (string, error)
- func (c *Client) ContainerNetworks(ctx context.Context, id string) ([]string, error)
- func (c *Client) ContainerSpecOf(ctx context.Context, id string) (*stackspec.ContainerSpec, error)
- func (c *Client) CreateContainer(ctx context.Context, name string, spec stackspec.ContainerSpec, pull bool, ...) (string, error)
- func (c *Client) CreateNetwork(ctx context.Context, spec stackspec.NetworkSpec) (string, error)
- func (c *Client) CreateVolume(ctx context.Context, spec stackspec.VolumeSpec) (string, error)
- func (c *Client) DeployConnector(ctx context.Context, name, tunnelID, token string, isDefault bool) (string, error)
- func (c *Client) DetachNetwork(ctx context.Context, containerID, netName string) error
- func (c *Client) DiskUsage(ctx context.Context) (any, error)
- func (c *Client) DiskUsageCached() (any, time.Time)
- func (c *Client) EnsurePluginNetwork(ctx context.Context) error
- func (c *Client) EnsureTunnelsNetwork(ctx context.Context) (string, error)
- func (c *Client) Exists(ctx context.Context, id string) bool
- func (c *Client) History(ctx context.Context, id string) ([]ImageLayer, error)
- func (c *Client) ImageByRef(ctx context.Context, ref string) (*ImageInfo, error)
- func (c *Client) ImageInUse(ctx context.Context, id string) (bool, []ImageUser, error)
- func (c *Client) Images(ctx context.Context) ([]ImageInfo, error)
- func (c *Client) ImagesForProject(ctx context.Context, project string) ([]string, error)
- func (c *Client) Info(ctx context.Context) (any, error)
- func (c *Client) Inspect(ctx context.Context, id string) (any, error)
- func (c *Client) IsConfigRegistry(server string) bool
- func (c *Client) IsLocalSocket() bool
- func (c *Client) Kill(ctx context.Context, id string) error
- func (c *Client) NetworkByRef(ctx context.Context, ref string) (*NetworkInfo, error)
- func (c *Client) NetworkExists(ctx context.Context, name string) (bool, error)
- func (c *Client) Networks(ctx context.Context) ([]NetworkInfo, error)
- func (c *Client) OriginIndex(ctx context.Context) (map[string]OriginRef, error)
- func (c *Client) Ping(ctx context.Context) error
- func (c *Client) PluginContainers(ctx context.Context) ([]PluginContainer, error)
- func (c *Client) PluginDialCandidates(ctx context.Context, id string, port int) (netTargets, directTargets []string, attachNet string, err error)
- func (c *Client) PluginNetworkIP(ctx context.Context, id string) string
- func (c *Client) ProjectContainerIDs(ctx context.Context, project string) ([]string, error)
- func (c *Client) ProjectContainers(ctx context.Context, project, service string) ([]ContainerRef, error)
- func (c *Client) ProjectSpec(ctx context.Context, project string) (*stackspec.StackSpec, error)
- func (c *Client) ProjectStats(ctx context.Context, project string) ([]ContainerStat, error)
- func (c *Client) ProjectUpdates(ctx context.Context, project string) ([]ImageUpdate, error)
- func (c *Client) PruneBuildCache(ctx context.Context) (uint64, error)
- func (c *Client) PruneImages(ctx context.Context, all bool) (PruneResult, error)
- func (c *Client) PruneImagesStream(ctx context.Context, all bool, emit func(string)) error
- func (c *Client) PullContainers(ctx context.Context, ids []string, emit func(string)) error
- func (c *Client) PullImage(ctx context.Context, ref string) error
- func (c *Client) PullImageStream(ctx context.Context, ref string, emit func(string)) error
- func (c *Client) Recreate(ctx context.Context, id string) error
- func (c *Client) RecreateFromSpec(ctx context.Context, id string, spec stackspec.ContainerSpec, pull bool, ...) error
- func (c *Client) RecreateManaged(ctx context.Context, id string) error
- func (c *Client) RedeployContainer(ctx context.Context, id string, pull, force bool, emit func(string)) error
- func (c *Client) RedeployProject(ctx context.Context, project string, pull, force bool, emit func(string)) error
- func (c *Client) RefreshDiskUsage(ctx context.Context) (any, time.Time, error)
- func (c *Client) RefreshImageStatus(ctx context.Context, ref string)
- func (c *Client) RefreshProjectStatus(ctx context.Context, project string)
- func (c *Client) RefreshUpdates(ctx context.Context)
- func (c *Client) RegistryList() []RegistryEntry
- func (c *Client) Remove(ctx context.Context, id string) error
- func (c *Client) RemoveImage(ctx context.Context, id string, force bool) error
- func (c *Client) RemoveManagedResources(ctx context.Context, project string, emit func(string)) (int, error)
- func (c *Client) RemoveNetwork(ctx context.Context, id string) error
- func (c *Client) RemoveRegistryCreds(server string) bool
- func (c *Client) RemoveVolume(ctx context.Context, name string, force bool) error
- func (c *Client) Restart(ctx context.Context, id string) error
- func (c *Client) SDK() *client.Client
- func (c *Client) SelfContainerID(ctx context.Context) string
- func (c *Client) SelfID() string
- func (c *Client) ServerInfo(ctx context.Context) (ServerInfo, error)
- func (c *Client) SetSelfID(id string)
- func (c *Client) SetUpdateCache(store UpdateCacheStore, key string)
- func (c *Client) SetUpdateHook(fn func())
- func (c *Client) Stacks(ctx context.Context) ([]StackSummary, error)
- func (c *Client) Start(ctx context.Context, id string) error
- func (c *Client) StartCredWatcher(ctx context.Context, every time.Duration)
- func (c *Client) StartDiskCrawler(ctx context.Context, every time.Duration)
- func (c *Client) StartUpdateCrawler(ctx context.Context, every time.Duration, cachePath string)
- func (c *Client) StatsSnapshot(ctx context.Context, id string) (ContainerStat, error)
- func (c *Client) Stop(ctx context.Context, id string) error
- func (c *Client) Top(ctx context.Context, id string) (TopResult, error)
- func (c *Client) VerifyRegistry(ctx context.Context, server, user, pass string) error
- func (c *Client) VolumeExists(ctx context.Context, name string) (bool, error)
- func (c *Client) Volumes(ctx context.Context) ([]VolumeInfo, error)
- type ClusterUpdate
- type Connector
- type ContainerRef
- type ContainerStat
- type ContainerSummary
- type ImageInfo
- type ImageLayer
- type ImageUpdate
- type ImageUser
- type NetworkInfo
- type OriginRef
- type PluginContainer
- type PruneResult
- type RegistryEntry
- type RegistrySource
- type ResourceUser
- type ServerInfo
- type StackSummary
- type TopResult
- type UpdateCacheStore
- type VolumeInfo
Constants ¶
const ( LabelProject = "com.docker.compose.project" LabelService = "com.docker.compose.service" LabelNumber = "com.docker.compose.container-number" // LabelManaged marks a container/network/volume hope created via a deploy, so // the UI and teardown can tell hope-owned objects from externally-created ones. LabelManaged = "ink.hope.managed" // LabelSystem marks a hope-owned INFRASTRUCTURE network — the plugin bridge and // the tunnel fallback bridge. Distinct from LabelManaged (which also lands on // ordinary stack networks, which stay deletable): hope refuses to delete a network // carrying this, since removing it breaks plugin/tunnel connectivity. LabelSystem = "ink.hope.system" )
Exported compose + hope label keys, so other packages (internal/deploy) build on these instead of redefining the same string literals. The unexported aliases in docker.go keep internal call sites terse.
const ( LabelPlugin = labelPlugin LabelPluginPort = labelPluginPort LabelPluginPath = labelPluginPath LabelPluginTitle = labelPluginTitle LabelPluginIcon = labelPluginIcon )
Exported plugin label keys — the installer stamps these on a deployed plugin container so discovery picks it up (the same labels an author would set by hand).
const PluginNetwork = "ink-plugins"
PluginNetwork is the dedicated user bridge hope uses to reach plugins on a daemon: hope (or the agent) and each enabled plugin container both join it, and hope dials the plugin by a stable alias on it — no published port, no hairpin, deterministic DNS. Created on demand per daemon (local socket, or an agent's daemon over tunnel).
Variables ¶
This section is empty.
Functions ¶
func PluginNetAlias ¶
PluginNetAlias is the DNS name hope dials a plugin container by on the shared network: its SHORT container id. docker's embedded DNS registers the short id (the default hostname) automatically on every user network the container joins — so a plain NetworkConnect (no explicit alias) is enough, sidestepping the "already connected, custom alias dropped" no-op. Always a valid DNS label (hex).
func ReplicaAlias ¶
ReplicaAlias is the stack-network alias hope assigns to every replica of a scaled service so a tunnel route can round-robin across them. The tunnels router ATTACHES this alias to each replica; OriginIndex RECONSTRUCTS it from labels to map a route origin back to its stack/service — the two must be byte-identical, so both go through here rather than hand-building the string.
Types ¶
type API ¶
type API interface {
AddRegistryCreds(server, user, pass string, source RegistrySource)
AllUpdates(ctx context.Context) ([]ClusterUpdate, time.Time, error)
AttachNetwork(ctx context.Context, containerID, netName string, aliases []string) error
AuthedRegistries() []string
CachedStatus(ref string) string
Close() error
Connectors(ctx context.Context) ([]Connector, error)
ContainerImage(ctx context.Context, id string) (string, error)
ContainerMatchInfo(ctx context.Context, id string) (image string, labels map[string]string, err error)
ContainerName(ctx context.Context, id string) (string, error)
BuildImageStream(ctx context.Context, dockerfile, tag string, emit func(string)) error
ContainerNetworks(ctx context.Context, id string) ([]string, error)
ContainerSpecOf(ctx context.Context, id string) (*stackspec.ContainerSpec, error)
CreateContainer(ctx context.Context, name string, spec stackspec.ContainerSpec, pull bool, emit func(string)) (string, error)
CreateNetwork(ctx context.Context, spec stackspec.NetworkSpec) (string, error)
CreateVolume(ctx context.Context, spec stackspec.VolumeSpec) (string, error)
DeployConnector(ctx context.Context, name, tunnelID, token string, isDefault bool) (string, error)
DetachNetwork(ctx context.Context, containerID, netName string) error
DiskUsage(ctx context.Context) (any, error)
DiskUsageCached() (any, time.Time)
EnsurePluginNetwork(ctx context.Context) error
EnsureTunnelsNetwork(ctx context.Context) (string, error)
Exists(ctx context.Context, id string) bool
History(ctx context.Context, id string) ([]ImageLayer, error)
ImageByRef(ctx context.Context, ref string) (*ImageInfo, error)
ImageInUse(ctx context.Context, id string) (bool, []ImageUser, error)
Images(ctx context.Context) ([]ImageInfo, error)
ImagesForProject(ctx context.Context, project string) ([]string, error)
Info(ctx context.Context) (any, error)
Inspect(ctx context.Context, id string) (any, error)
IsConfigRegistry(server string) bool
IsLocalSocket() bool
Kill(ctx context.Context, id string) error
NetworkByRef(ctx context.Context, ref string) (*NetworkInfo, error)
NetworkExists(ctx context.Context, name string) (bool, error)
Networks(ctx context.Context) ([]NetworkInfo, error)
OriginIndex(ctx context.Context) (map[string]OriginRef, error)
Ping(ctx context.Context) error
PluginContainers(ctx context.Context) ([]PluginContainer, error)
PluginDialCandidates(ctx context.Context, id string, port int) (netTargets, directTargets []string, attachNet string, err error)
PluginNetworkIP(ctx context.Context, id string) string
ProjectContainerIDs(ctx context.Context, project string) ([]string, error)
ProjectContainers(ctx context.Context, project, service string) ([]ContainerRef, error)
ProjectSpec(ctx context.Context, project string) (*stackspec.StackSpec, error)
ProjectStats(ctx context.Context, project string) ([]ContainerStat, error)
ProjectUpdates(ctx context.Context, project string) ([]ImageUpdate, error)
PruneBuildCache(ctx context.Context) (uint64, error)
PruneImages(ctx context.Context, all bool) (PruneResult, error)
PruneImagesStream(ctx context.Context, all bool, emit func(string)) error
PullContainers(ctx context.Context, ids []string, emit func(string)) error
PullImage(ctx context.Context, ref string) error
PullImageStream(ctx context.Context, ref string, emit func(string)) error
Recreate(ctx context.Context, id string) error
RecreateFromSpec(ctx context.Context, id string, spec stackspec.ContainerSpec, pull bool, emit func(string)) error
RecreateManaged(ctx context.Context, id string) error
RedeployContainer(ctx context.Context, id string, pull, force bool, emit func(string)) error
RedeployProject(ctx context.Context, project string, pull, force bool, emit func(string)) error
RefreshDiskUsage(ctx context.Context) (any, time.Time, error)
RefreshImageStatus(ctx context.Context, ref string)
RefreshProjectStatus(ctx context.Context, project string)
RefreshUpdates(ctx context.Context)
RegistryList() []RegistryEntry
Remove(ctx context.Context, id string) error
RemoveImage(ctx context.Context, id string, force bool) error
RemoveManagedResources(ctx context.Context, project string, emit func(string)) (int, error)
RemoveNetwork(ctx context.Context, id string) error
RemoveRegistryCreds(server string) bool
RemoveVolume(ctx context.Context, name string, force bool) error
Restart(ctx context.Context, id string) error
SDK() *client.Client
SelfContainerID(ctx context.Context) string
SelfID() string
ServerInfo(ctx context.Context) (ServerInfo, error)
SetSelfID(id string)
SetUpdateCache(store UpdateCacheStore, key string)
SetUpdateHook(fn func())
Stacks(ctx context.Context) ([]StackSummary, error)
Start(ctx context.Context, id string) error
StartCredWatcher(ctx context.Context, every time.Duration)
StartDiskCrawler(ctx context.Context, every time.Duration)
StartUpdateCrawler(ctx context.Context, every time.Duration, cachePath string)
StatsSnapshot(ctx context.Context, id string) (ContainerStat, error)
Stop(ctx context.Context, id string) error
Top(ctx context.Context, id string) (TopResult, error)
VerifyRegistry(ctx context.Context, server, user, pass string) error
VolumeExists(ctx context.Context, name string) (bool, error)
Volumes(ctx context.Context) ([]VolumeInfo, error)
}
API is the full method surface of *Client. hosts.ActiveFor and friends hand callers an API rather than a concrete *Client, so the routers (containers/stacks/system/ deploy/tunnels/pluginhost) that reach the daemon through the hosts seam can be exercised in tests against a mock. *Client is the only production implementation; the assertion below fails the build if any signature drifts from it. Test mocks embed API and override only the methods the test touches.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is hope's Docker facade over a single daemon endpoint. The underlying SDK handle is held atomically so the active daemon can be retargeted at runtime (Adopt) — e.g. binding a late-connecting agent tunnel as the primary host without rebuilding the routers that hold this client.
func New ¶
New dials the Docker daemon at host (e.g. "unix:///var/run/docker.sock" or "tcp://host:2375") with API-version negotiation. configPath points at a docker config.json for private-registry pull credentials (empty = the default ~/.docker/config.json).
func NewOverDialer ¶
func NewOverDialer(configPath string, dial func(ctx context.Context, network, addr string) (net.Conn, error)) (*Client, error)
NewOverDialer builds a Client that talks to a Docker daemon reached through a custom dialer — e.g. a hope-agent tunnel, where every connection is a stream back to a remote host's socket. The SDK speaks plain HTTP over the dialer, so all of hope's existing operations work against the remote daemon unchanged.
func (*Client) AddRegistryCreds ¶
func (c *Client) AddRegistryCreds(server, user, pass string, source RegistrySource)
AddRegistryCreds registers an explicit registry credential and rebuilds the auth map. Works without a credential helper. source tags where it came from (config vs runtime db) so the UI can gate editing. Re-adding the same server upserts (replacing any prior entry for that host).
func (*Client) AllUpdates ¶
AllUpdates maps the running containers to the cached freshness verdicts and returns them with the time of the last crawl. Containers whose ref hasn't been crawled yet read as "unknown".
func (*Client) AttachNetwork ¶
func (c *Client) AttachNetwork(ctx context.Context, containerID, netName string, aliases []string) error
AttachNetwork connects a container to a network (optionally with aliases). A no-op-safe wrapper: "already exists" is treated as success.
func (*Client) AuthedRegistries ¶
AuthedRegistries lists the registries hope currently has credentials for — a startup diagnostic so "still rate-limited?" has an obvious answer.
func (*Client) BuildImageStream ¶
func (c *Client) BuildImageStream(ctx context.Context, dockerfile, tag string, emit func(string)) error
BuildImageStream builds an image from a CONTEXTLESS Dockerfile — its text alone, with no build context. A Dockerfile that COPY/ADDs from a local path therefore can't resolve its sources; callers reject those before getting here (see the deploy engine / UI). It's the clean subset for one-off "bring your own Dockerfile" deploys (FROM + RUN + ENV + CMD). Progress lines from the daemon are forwarded via emit; a mid-stream error (a failed RUN, an unreachable base image) is surfaced as an error rather than draining silently.
func (*Client) CachedStatus ¶
CachedStatus returns the cached freshness verdict for an image ref ("current" | "outdated" | "unknown") with no network call.
func (*Client) Connectors ¶
Connectors lists hope-managed cloudflared connectors on this daemon.
func (*Client) ContainerImage ¶
ContainerImage returns the image reference a container was created from.
func (*Client) ContainerMatchInfo ¶
func (c *Client) ContainerMatchInfo(ctx context.Context, id string) (image string, labels map[string]string, err error)
ContainerMatchInfo returns a container's image ref + labels, for evaluating a plugin's container-surface match against it.
func (*Client) ContainerName ¶
ContainerName returns a container's friendly name (leading slash trimmed), for user-facing notifications. Best-effort — callers fall back to the short id.
func (*Client) ContainerNetworks ¶
ContainerNetworks returns the user-defined networks a container is attached to.
func (*Client) ContainerSpecOf ¶
ContainerSpecOf reconstructs a single container's editable spec from its live inspect — the seed for the "edit container" form. name is the compose service when set, else the container name.
func (*Client) CreateContainer ¶
func (c *Client) CreateContainer(ctx context.Context, name string, spec stackspec.ContainerSpec, pull bool, emit func(string)) (string, error)
CreateContainer creates and starts a container from spec under the given docker name. spec.Labels, spec.Networks and spec.Image are taken as final (the deploy engine resolves compose labels, network name prefixes, etc. before calling). When pull is true the image is pulled first, streaming progress to emit. Returns the new container id.
func (*Client) CreateNetwork ¶
CreateNetwork creates a network from spec, returning its id. It generalizes the hardcoded bridge create used for the tunnels fallback network.
func (*Client) CreateVolume ¶
CreateVolume creates a named volume from spec, returning its name.
func (*Client) DeployConnector ¶
func (c *Client) DeployConnector(ctx context.Context, name, tunnelID, token string, isDefault bool) (string, error)
DeployConnector pulls cloudflared and runs it as a hope-managed connector for the given tunnel token, labeled so Connectors() discovers it. Returns the new container id.
func (*Client) DetachNetwork ¶
DetachNetwork disconnects a container from a network (ignores "not connected").
func (*Client) DiskUsageCached ¶
DiskUsageCached returns the last crawled disk usage and when it was taken.
func (*Client) EnsurePluginNetwork ¶
EnsurePluginNetwork creates the shared ink-plugins bridge if missing (idempotent).
func (*Client) EnsureTunnelsNetwork ¶
EnsureTunnelsNetwork makes sure the fallback user-defined bridge exists (for loose containers that only have the default bridge, which lacks name DNS).
func (*Client) Exists ¶
Exists reports whether a container id/name resolves — used by the logstream plugin to reject a stream before the first byte.
func (*Client) History ¶
History returns an image's layer history (`docker history`) — how it was built, layer by layer, with per-layer size. Newest layer first.
func (*Client) ImageByRef ¶
ImageByRef finds a single local image by id (full or short), an exact tag, or a repo digest — for the shared image-detail modal opened from anywhere a container's image is shown. Returns (nil, nil) when nothing matches.
func (*Client) ImageInUse ¶
ImageInUse reports whether any container (running or stopped) references the image, and by whom. Used to refuse a (force-)remove of an in-use image at the RPC layer — the UI hides that action, but the guard must live on the server.
func (*Client) Images ¶
Images lists local top-level images, tagging each with whether a container uses it and whether it's dangling (untagged). Sorted largest first.
func (*Client) ImagesForProject ¶
ImagesForProject returns the unique image references used by a project's containers, for a stack-wide pull.
func (*Client) Inspect ¶
Inspect returns the full raw inspect JSON for a container (rendered as-is in the UI's inspect panel).
func (*Client) IsConfigRegistry ¶
IsConfigRegistry reports whether a server's credential is config-sourced (config.json or [registry]) and therefore read-only. Used to reject UI edits that would shadow a config entry.
func (*Client) IsLocalSocket ¶
IsLocalSocket reports whether this client talks to a local unix socket (as opposed to a remote tcp:// daemon). Only for a local socket can hope join the plugin's network and reach it by container DNS; a remote tcp daemon needs a published port.
func (*Client) NetworkByRef ¶
NetworkByRef finds a single network by id (full or short) or exact name, with its attached-container mapping — for the shared network-detail modal opened from anywhere a network is shown. Returns (nil, nil) when nothing matches.
func (*Client) NetworkExists ¶
NetworkExists reports whether a network with the exact name already exists.
func (*Client) Networks ¶
func (c *Client) Networks(ctx context.Context) ([]NetworkInfo, error)
Networks lists Docker networks with the containers attached to each (the "who's on this network" reverse mapping), busiest first.
func (*Client) OriginIndex ¶
OriginIndex maps container name AND per-network alias -> OriginRef, so an ingress service URL host ("blog-web-1" or "hope-blog-web") resolves to a stack.
func (*Client) PluginContainers ¶
func (c *Client) PluginContainers(ctx context.Context) ([]PluginContainer, error)
PluginContainers lists containers on this daemon that opt into the plugin system (label hope.plugin truthy) and declare a valid port. Mirrors Connectors.
func (*Client) PluginDialCandidates ¶
func (c *Client) PluginDialCandidates(ctx context.Context, id string, port int) (netTargets, directTargets []string, attachNet string, err error)
PluginDialCandidates returns ordered host:port addresses hope can try to reach a container's port, plus the user network to attach to. Order:
- the container's network IP (works when hope shares the network — the normal containerized deployment, after AttachNetwork);
- any PUBLISHED host port at 127.0.0.1 (works for NATIVE hope, including Docker Desktop, which forwards published ports to localhost) — the dev fast path.
Errors only if the container exposes neither. PluginDialCandidates resolves how hope can reach a plugin container. It returns two kinds of address:
- netTargets: the container's network IP:port — reachable only from the plugin's docker network (hope attaches to it locally, or the agent dials it on the host).
- directTargets: a published host port at an address hope can reach DIRECTLY — 127.0.0.1 for a local daemon, or the daemon's host IP when the daemon is a remote TCP endpoint (so a plugin published on the remote host is reachable at <daemon-host>:<published> without an agent on that host).
attachNet is the user network name to attach the routing container to for the container-IP path.
func (*Client) PluginNetworkIP ¶
PluginNetworkIP returns the container's IP address on the shared ink-plugins network, or "" if it isn't attached (or can't be inspected). Used as a DNS-INDEPENDENT dial fallback right after a live AttachNetwork: docker's embedded DNS record for the freshly-joined alias can lag the first request (NXDOMAIN), whereas the endpoint IP is present in inspect immediately. A port-less plugin (no published port) has no other fallback, so without this a disable→re-enable races the DNS registration and the schema query fails.
func (*Client) ProjectContainerIDs ¶
ProjectContainerIDs returns the container ids of a compose project, ordered by service then container-number for stable operation order.
func (*Client) ProjectContainers ¶
func (c *Client) ProjectContainers(ctx context.Context, project, service string) ([]ContainerRef, error)
ProjectContainers returns refs for a project, optionally filtered to a single compose service. Ordered by service then container-number.
func (*Client) ProjectSpec ¶
ProjectSpec reconstructs a StackSpec from the live containers of a project (compose labels + inspect). It powers the editor's "adopt an existing stack" path — including stacks hope did not deploy. Replicas collapse to one service; the reconstruction is best-effort and portable (no live IPs/MACs).
func (*Client) ProjectStats ¶
ProjectStats snapshots every running container in a compose project, concurrently. Non-running containers are skipped; per-container errors are dropped so one bad container doesn't fail the whole snapshot.
func (*Client) ProjectUpdates ¶
ProjectUpdates checks every container in a project against its registry. The registry lookup is done once per distinct image ref (deduped), concurrently.
func (*Client) PruneBuildCache ¶
PruneBuildCache clears the builder cache (the layer/step cache from image builds — often the biggest reclaimable chunk, and invisible to image prune). Returns bytes reclaimed.
func (*Client) PruneImages ¶
PruneImages removes unreferenced images: dangling-only by default, or every unused image when all is true. Returns how many were deleted and bytes freed.
func (*Client) PruneImagesStream ¶
PruneImagesStream removes unused images one at a time, emitting a line per image (removed / skipped + reason) so the UI can show live progress and the exact reason an image can't be deleted.
func (*Client) PullContainers ¶
PullContainers pulls the images backing the given containers (deduped), streaming progress to emit. It does not recreate anything.
func (*Client) PullImage ¶
PullImage pulls ref and consumes the progress stream, surfacing any error the registry reports MID-STREAM (rate limits, auth failures). The daemon returns those as JSON `error` lines, not as a transport error — so draining blindly would make a throttled pull look successful and a redeploy keep the old image.
func (*Client) PullImageStream ¶
PullImageStream pulls ref and forwards human-readable progress to emit, one line per layer status change (chatty per-chunk progress is deduped). Returns the registry's error on failure, like PullImage.
func (*Client) Recreate ¶
Recreate rebuilds a container in place so it picks up a freshly pulled image, preserving its config, host config, name, labels (so it stays grouped in its compose project), and network attachments. This is the API-only equivalent of `docker compose up -d --force-recreate` for one container.
func (*Client) RecreateFromSpec ¶
func (c *Client) RecreateFromSpec(ctx context.Context, id string, spec stackspec.ContainerSpec, pull bool, emit func(string)) error
RecreateFromSpec rebuilds a container in place under its current name with the edited spec — the API-only "edit container settings". The container's internal compose/hope labels are preserved (so it stays grouped/managed); the user labels come from the spec. Networks in the spec are taken as-is (the edit form seeds them from the live container).
func (*Client) RecreateManaged ¶
RecreateManaged recreates a container, but if it's a hope-image container (hope itself, or a hope-agent — anything carrying HOPE_MANAGED=1) it hands the job to a detached helper. Recreating such a container directly would stop it mid-request over the very connection it provides (hope's process, or the agent tunnel), severing that connection before the recreate completes — the EOF. Keyed on the image marker, not os.Hostname()-based self detection (which is unreliable when the container runs with a custom --hostname or host network).
func (*Client) RedeployContainer ¶
func (c *Client) RedeployContainer(ctx context.Context, id string, pull, force bool, emit func(string)) error
RedeployContainer pulls a container's image (streaming progress to emit) then recreates it, emitting step lines. The terminal "done" frame is the caller's.
func (*Client) RedeployProject ¶
func (c *Client) RedeployProject(ctx context.Context, project string, pull, force bool, emit func(string)) error
RedeployProject pulls every image in a project then recreates each container, streaming progress to emit. With pull off it skips the pull; with force off it leaves containers already running the current image untouched.
func (*Client) RefreshDiskUsage ¶
RefreshDiskUsage runs a live df, updates the cache, and returns it — for the user-triggered "refresh" button.
func (*Client) RefreshImageStatus ¶
RefreshImageStatus re-checks one image ref and updates the cache. Call it after a pull/redeploy so the freshness tag doesn't go stale.
func (*Client) RefreshProjectStatus ¶
RefreshProjectStatus re-checks every distinct image ref in a project and merges the results into the cache (used after stack-wide pull/redeploy).
func (*Client) RefreshUpdates ¶
RefreshUpdates runs an immediate cluster-wide crawl (user-triggered) and updates the cache.
func (*Client) RegistryList ¶
func (c *Client) RegistryList() []RegistryEntry
RegistryList returns the credential-free view of every known registry (config + runtime), sorted by server, for the UI. Passwords are never included.
func (*Client) Remove ¶
Remove stops (graceful) then removes a container. Force covers the case where it's already stopped or won't stop in time.
func (*Client) RemoveImage ¶
RemoveImage deletes a single image (force allows removing a tagged image even if it has stopped containers / multiple tags).
func (*Client) RemoveManagedResources ¶
func (c *Client) RemoveManagedResources(ctx context.Context, project string, emit func(string)) (int, error)
RemoveManagedResources removes the hope-managed networks and volumes belonging to a project (labeled com.docker.compose.project=<project> AND ink.hope.managed=1) — the ones a hope deploy created. Externally-created resources are never touched. Returns the count removed. Errors on individual resources (e.g. still in use) are emitted but not fatal.
func (*Client) RemoveNetwork ¶
RemoveNetwork deletes a network by id.
func (*Client) RemoveRegistryCreds ¶
RemoveRegistryCreds drops a runtime (db) credential for a server and rebuilds the auth map. Config-sourced creds are left untouched (read-only). Reports whether anything was removed.
func (*Client) RemoveVolume ¶
RemoveVolume deletes a volume by name (force removes even if referenced).
func (*Client) SelfContainerID ¶
SelfContainerID resolves the container id of the process on THIS daemon that should join the plugin network — hope on the local daemon, the agent on a tunnel. It tries the hostname/hint first (usually the container id), then falls back to the daemon's HOPE_MANAGED container (hope + agent images bake HOPE_MANAGED=1) — robust even when a custom --hostname hides the id. Returns "" if none is found.
func (*Client) SelfID ¶
SelfID is the exported view of selfID — this client's own container id (hope's on the local daemon, the agent's on a tunnel). Used by the plugin host to attach hope to a plugin's network before dialing it.
func (*Client) ServerInfo ¶
func (c *Client) ServerInfo(ctx context.Context) (ServerInfo, error)
ServerInfo returns the daemon version + counts.
func (*Client) SetSelfID ¶
SetSelfID records the container id this client runs as (used by agent clients so self-recreate detection works across the tunnel).
func (*Client) SetUpdateCache ¶
func (c *Client) SetUpdateCache(store UpdateCacheStore, key string)
SetUpdateCache routes freshness-cache persistence through a key/value store (the state db) under the given key, instead of a JSON file. Call before StartUpdateCrawler.
func (*Client) SetUpdateHook ¶
func (c *Client) SetUpdateHook(fn func())
SetUpdateHook registers a callback fired once per crawl when some image newly flips to "outdated". The caller closes over its host id + the event bus to publish an image.update event. Set before StartUpdateCrawler.
func (*Client) Stacks ¶
func (c *Client) Stacks(ctx context.Context) ([]StackSummary, error)
Stacks lists all containers (running and stopped) grouped by compose project. Containers without a compose project land under "(ungrouped)".
func (*Client) StartCredWatcher ¶
StartCredWatcher polls the config.json checksum and reloads credentials when it changes, so a fresh `docker login` takes effect without restarting hope.
func (*Client) StartDiskCrawler ¶
StartDiskCrawler computes docker disk usage on boot, then every `every`. `docker system df` is expensive on big hosts, so the UI reads the cache.
func (*Client) StartUpdateCrawler ¶
StartUpdateCrawler loads any persisted cache, runs an immediate crawl, then re-crawls every `every`. cachePath (if non-empty, and no state-db backend is set) persists the cache across restarts — mount it to survive recreates.
func (*Client) StatsSnapshot ¶
StatsSnapshot reads a single CPU/memory sample for a container. CPU% needs a delta, so it reads two frames of the stats stream (the second carries a valid precpu) and then closes.
func (*Client) Top ¶
Top returns a container's running processes (the `docker top` equivalent): the daemon runs ps in the container's PID namespace and returns the columns + rows. Works over the agent tunnel like every other call.
func (*Client) VerifyRegistry ¶
VerifyRegistry checks a credential against the registry by performing a login (auth handshake only, no image pull), so the UI can reject bad creds at add time instead of failing silently on the next pull. Returns nil when the creds authenticate.
func (*Client) VolumeExists ¶
VolumeExists reports whether a named volume already exists.
type ClusterUpdate ¶
type ClusterUpdate struct {
ID string `json:"id"`
Project string `json:"project"`
Service string `json:"service"`
Name string `json:"name"`
Image string `json:"image"`
Status string `json:"status"`
Detail string `json:"detail,omitempty"`
}
ClusterUpdate is a per-container freshness row spanning all projects, for the dashboard. Carries enough identity to render and link the container.
type Connector ¶
type Connector struct {
ContainerID string `json:"container_id"`
Name string `json:"name"` // container name (no leading slash)
TunnelID string `json:"tunnel_id"`
Title string `json:"title"` // friendly label, else name
Default bool `json:"default"` // the shared/default connector
Project string `json:"project"` // compose project, if the connector lives in a stack
Networks []string `json:"networks"` // user-defined networks it's attached to
Image string `json:"image"` // the cloudflared image ref
Running bool `json:"running"`
}
Connector is a cloudflared container hope will manage routes for.
type ContainerRef ¶
ContainerRef is a minimal container identity for multiplexed log streaming.
type ContainerStat ¶
type ContainerStat struct {
ID string `json:"id"`
CPUPercent float64 `json:"cpu_percent"`
MemUsed uint64 `json:"mem_used"`
MemLimit uint64 `json:"mem_limit"`
}
ContainerStat is a point-in-time CPU/memory reading for one container.
type ContainerSummary ¶
type ContainerSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Service string `json:"service"`
Image string `json:"image"`
State string `json:"state"` // running, exited, restarting, ...
Status string `json:"status"` // human "Up 3 days" / "Restarting (2) ..."
Health string `json:"health"` // healthy/unhealthy/starting/""
Created int64 `json:"created"`
Number int `json:"number"` // compose container-number
Ports []string `json:"ports"`
Labels map[string]string `json:"labels,omitempty"`
}
ContainerSummary is the per-container shape sent to the frontend.
type ImageInfo ¶
type ImageInfo struct {
ID string `json:"id"`
Tags []string `json:"tags"`
Size int64 `json:"size"`
Created int64 `json:"created"` // unix seconds
Dangling bool `json:"dangling"`
InUse bool `json:"in_use"`
UsedBy []ImageUser `json:"used_by"` // containers referencing this image
Registry string `json:"registry"` // where it came from: registry host (docker.io, ghcr.io, ...)
Digests []string `json:"digests,omitempty"` // repo@sha256 refs (the pulled-from source)
}
ImageInfo is a clean, frontend-facing view of a local image.
type ImageLayer ¶
type ImageLayer struct {
ID string `json:"id"` // layer image id, or "<missing>" for squashed base layers
Created int64 `json:"created"` // unix seconds
CreatedBy string `json:"created_by"` // the Dockerfile instruction that built it
Size int64 `json:"size"` // bytes this layer adds
Comment string `json:"comment"`
Tags []string `json:"tags"`
Empty bool `json:"empty"` // a metadata-only layer (0 bytes, e.g. ENV/LABEL/CMD)
}
ImageLayer is one entry of an image's build history (`docker history`): the instruction that created the layer, its size, and age. Layers are returned newest-first (as the daemon reports them).
type ImageUpdate ¶
type ImageUpdate struct {
ID string `json:"id"`
Image string `json:"image"`
Status string `json:"status"`
Detail string `json:"detail,omitempty"`
}
ImageUpdate reports whether a container's image is current with its registry. Status is one of: "current", "outdated", "unknown".
type ImageUser ¶
type ImageUser struct {
ID string `json:"id"`
Name string `json:"name"`
Service string `json:"service"`
Project string `json:"project"`
}
ImageUser identifies a container (and its stack) that references an image.
type NetworkInfo ¶
type NetworkInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Driver string `json:"driver"`
Scope string `json:"scope"`
Internal bool `json:"internal"`
Attachable bool `json:"attachable"`
IPv6 bool `json:"ipv6"`
Subnet string `json:"subnet"` // first IPAM pool
Gateway string `json:"gateway"` // first IPAM gateway
Options map[string]string `json:"options"`
Labels map[string]string `json:"labels,omitempty"`
Created int64 `json:"created"` // unix seconds
UsedBy []ResourceUser `json:"used_by"`
}
NetworkInfo is a Docker network plus the containers attached to it.
type OriginRef ¶
type OriginRef struct {
ContainerID string
Name string // container name
Project string
Service string
Networks []string // user-defined networks this container is on
Aliases []string // per-network aliases (union)
}
OriginRef identifies a tunnel origin (a container) so ingress URLs can be resolved back to a stack/service in the UI.
type PluginContainer ¶
type PluginContainer struct {
ContainerID string `json:"container_id"`
Name string `json:"name"` // container name (no leading slash)
Port int `json:"port"`
Path string `json:"path"`
Title string `json:"title"` // pre-manifest hint, else name
Icon string `json:"icon"` // pre-manifest hint
Project string `json:"project"`
Service string `json:"service"` // compose service — part of the stable identity
Networks []string `json:"networks"`
Image string `json:"image"`
ImageID string `json:"image_id"` // image digest — part of the trust fingerprint
Running bool `json:"running"`
}
PluginContainer is a container that declares a hope plugin endpoint. Identity (name/version/icons/capabilities) comes from the plugin's own getSchema; these fields are only what the labels + docker tell us — where to dial and enough to list it before it's trusted.
type PruneResult ¶
PruneResult reports the outcome of an image prune.
type RegistryEntry ¶
type RegistryEntry struct {
Server string
Username string
HasPassword bool
Source RegistrySource
}
RegistryEntry is the credential-free view of a known registry for the UI.
type RegistrySource ¶
type RegistrySource string
RegistrySource records where a credential came from, so the UI can show config-loaded registries as read-only and only let the operator edit/remove the ones they added at runtime.
const ( // RegistrySourceConfig: from config.json or [[registry]] — read-only in the UI. RegistrySourceConfig RegistrySource = "config" // RegistrySourceDB: added at runtime (persisted in the state db) — editable. RegistrySourceDB RegistrySource = "db" )
type ResourceUser ¶
type ResourceUser struct {
ID string `json:"id"`
Name string `json:"name"`
Service string `json:"service"`
Project string `json:"project"`
}
ResourceUser is a container that references a network or volume, with its compose identity so the UI can group/link it.
type ServerInfo ¶
type ServerInfo struct {
Version string `json:"version"`
Containers int `json:"containers"`
Running int `json:"running"`
Images int `json:"images"`
}
ServerInfo is a small typed slice of the daemon info (for the agents view).
type StackSummary ¶
type StackSummary struct {
Project string `json:"project"`
WorkingDir string `json:"working_dir"`
ConfigFiles []string `json:"config_files"`
Containers []ContainerSummary `json:"containers"`
Running int `json:"running"`
Total int `json:"total"`
// Restarting flags a stack with any container in a restart loop — the
// dashboard surfaces these in red.
Restarting bool `json:"restarting"`
// ComposeAvailable is true when hope can read this stack's compose file
// (file-based features like the compose viewer). False over a remote daemon
// or when the project dir is not mounted — API ops still work regardless.
ComposeAvailable bool `json:"compose_available"`
}
StackSummary groups a compose project's containers with the on-disk metadata needed to drive its lifecycle.
type TopResult ¶
TopResult is a container's live process list (the `docker top` equivalent): the ps column titles and one row of cells per process.
type UpdateCacheStore ¶
UpdateCacheStore is an optional key/value backend for the freshness cache (the embedded state db). When set it supersedes the JSON file path, so the cache lives in hope.db instead of a separate mounted file.
type VolumeInfo ¶
type VolumeInfo struct {
Name string `json:"name"`
Driver string `json:"driver"`
Mountpoint string `json:"mountpoint"`
CreatedAt string `json:"created_at"`
Scope string `json:"scope,omitempty"`
Size int64 `json:"size"` // bytes; -1 when the daemon didn't compute it
Options map[string]string `json:"options,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
UsedBy []ResourceUser `json:"used_by"`
}
VolumeInfo is a Docker volume plus the containers mounting it.