1// Package out defines output ports (interfaces) for infrastructure.
2// These interfaces define the contract between use cases and driven adapters
3// (Docker, filesystem, etc.).
4package out
5
6import (
7 "context"
8 "io"
9 "time"
10
11 "github.com/bnema/gordon/internal/domain"
12)
13
14// ContainerRuntime defines the contract for container runtime operations.
15// This interface abstracts the underlying container runtime (Docker, Podman, etc.).
16type ContainerRuntime interface {
17 // Container lifecycle
18 CreateContainer(ctx context.Context, config *domain.ContainerConfig) (*domain.Container, error)
19 StartContainer(ctx context.Context, containerID string) error
20 // StopContainer stops one exact container, giving it grace to exit
21 // before the runtime kills it. A non-positive grace keeps the
22 // runtime's own default.
23 StopContainer(ctx context.Context, containerID string, grace time.Duration) error
24 // RestartContainer restarts one exact container, giving it grace to
25 // exit before the runtime kills it. A non-positive grace keeps the
26 // runtime's own default.
27 RestartContainer(ctx context.Context, containerID string, grace time.Duration) error
28 RemoveContainer(ctx context.Context, containerID string, force bool) error
29 RenameContainer(ctx context.Context, containerID, newName string) error
30
31 // Container inspection
32 ListContainers(ctx context.Context, all bool) ([]*domain.Container, error)
33 InspectContainer(ctx context.Context, containerID string) (*domain.Container, error)
34 GetContainerLogs(ctx context.Context, containerID string, follow bool) (io.ReadCloser, error)
35 // GetContainerLogsSince returns logs emitted at or after since, so
36 // readiness can scope a probe to the current execution of one
37 // exact container ID. A missing container reports the
38 // domain.ErrContainerNotFound sentinel.
39 GetContainerLogsSince(ctx context.Context, containerID string, since time.Time, follow bool) (io.ReadCloser, error)
40
41 // Image operations
42 PullImage(ctx context.Context, image string) error
43 PullImageWithOptions(ctx context.Context, request domain.ImagePullRequest) error
44 PullImageWithAuth(ctx context.Context, image, username, password string) error
45 TagImage(ctx context.Context, sourceRef, targetRef string) error
46 UntagImage(ctx context.Context, imageRef string) error
47 RemoveImage(ctx context.Context, image string, force bool) error
48 ListImages(ctx context.Context) ([]string, error)
49
50 // Runtime information
51 Ping(ctx context.Context) error
52 Version(ctx context.Context) (string, error)
53 // SupportsCDIDevices reports whether the connected engine can serve
54 // native CDI device requests. It fails closed with
55 // domain.ErrRuntimeUnsupported on engines below the support matrix
56 // (Podman 5.4+, Docker 28.3+). Callers invoke it before any workload
57 // mutation so an unsupported engine fails in preflight, never after
58 // withdrawing the serving generation.
59 SupportsCDIDevices(ctx context.Context) error
60
61 // Health and status
62 IsContainerRunning(ctx context.Context, containerID string) (bool, error)
63 GetContainerHealthStatus(ctx context.Context, containerID string) (status string, hasHealthcheck bool, err error)
64 // GetContainerBackendBinds resolves protocol-specific container ports to
65 // their host binds in one container inspection.
66 GetContainerBackendBinds(ctx context.Context, containerID string, ports []domain.ContainerBackendPort) ([]domain.ContainerBackendBind, error)
67
68 // Image and port inspection
69 GetImageExposedPorts(ctx context.Context, imageRef string) ([]int, error)
70 GetContainerExposedPorts(ctx context.Context, containerID string) ([]int, error)
71 GetContainerNetworkInfo(ctx context.Context, containerID string) (string, int, error)
72 GetContainerNetwork(ctx context.Context, containerID string) (string, error)
73
74 // Volume management
75 InspectImageVolumes(ctx context.Context, imageRef string) ([]string, error)
76 VolumeExists(ctx context.Context, volumeName string) (bool, error)
77 // CreateVolume creates one named volume with the given labels.
78 // Labels carry ownership provenance; a caller that omits them
79 // creates an unmanaged volume that prune never adopts.
80 CreateVolume(ctx context.Context, volumeName string, labels map[string]string) error
81 RemoveVolume(ctx context.Context, volumeName string, force bool) error
82 ListVolumes(ctx context.Context) ([]*domain.VolumeInfo, error)
83
84 // Environment inspection
85 InspectImageEnv(ctx context.Context, imageRef string) ([]string, error)
86
87 // Label inspection
88 GetImageLabels(ctx context.Context, imageRef string) (map[string]string, error)
89
90 // Image identity
91 GetImageID(ctx context.Context, imageRef string) (string, error)
92 VerifyImageDigest(ctx context.Context, imageRef, digest string) error
93
94 // In-container operations
95 ExecInContainer(ctx context.Context, containerID string, cmd []string) (*ExecResult, error)
96 CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, error)
97
98 // Network management
99 CreateNetwork(ctx context.Context, name string, config domain.NetworkConfig) error
100 RemoveNetwork(ctx context.Context, name string) error
101 ListNetworks(ctx context.Context) ([]*domain.NetworkInfo, error)
102 NetworkExists(ctx context.Context, name string) (bool, error)
103 ConnectContainerToNetwork(ctx context.Context, containerName, networkName string) error
104 DisconnectContainerFromNetwork(ctx context.Context, containerName, networkName string) error
105
106 // Bounded network readiness
107 //
108 // ProbeContainerNetwork runs one bounded readiness session against one
109 // declared internal container port, which has no host publication. The
110 // adapter owns the helper lifecycle: it resolves the target endpoint on
111 // the exact network in the request, runs one hardened helper attached
112 // only to that network, and always removes the helper under an
113 // independent bounded cleanup context. It never publishes a host port
114 // and never targets a service alias.
115 ProbeContainerNetwork(ctx context.Context, request domain.ContainerNetworkProbeRequest) (domain.ContainerNetworkProbeResult, error)
116}
117
118// ContainerLister is the subset of ContainerRuntime needed by the orphan GC.
119type ContainerLister interface {
120 ListContainers(ctx context.Context, all bool) ([]*domain.Container, error)
121}
122
123// ExecResult holds the result of executing a command in a container.
124type ExecResult struct {
125 ExitCode int
126 Stdout []byte
127 Stderr []byte
128}