1package garden
2
3import (
4	"io"
5	"time"
6)
7
8//go:generate counterfeiter . Container
9
10type Container interface {
11	Handle() string
12
13	// Stop stops a container.
14	//
15	// If kill is false, garden stops a container by sending the processes running inside it the SIGTERM signal.
16	// It then waits for the processes to terminate before returning a response.
17	// If one or more processes do not terminate within 10 seconds,
18	// garden sends these processes the SIGKILL signal, killing them ungracefully.
19	//
20	// If kill is true, garden stops a container by sending the processing running inside it a SIGKILL signal.
21	//
22	// It is possible to copy files in to and out of a stopped container.
23	// It is only when a container is destroyed that its filesystem is cleaned up.
24	//
25	// Errors:
26	// * None.
27	Stop(kill bool) error
28
29	// Returns information about a container.
30	Info() (ContainerInfo, error)
31
32	// StreamIn streams data into a file in a container.
33	//
34	// Errors:
35	// *  TODO.
36	StreamIn(spec StreamInSpec) error
37
38	// StreamOut streams a file out of a container.
39	//
40	// Errors:
41	// * TODO.
42	StreamOut(spec StreamOutSpec) (io.ReadCloser, error)
43
44	// Returns the current bandwidth limits set for the container.
45	CurrentBandwidthLimits() (BandwidthLimits, error)
46
47	// Returns the current CPU limts set for the container.
48	CurrentCPULimits() (CPULimits, error)
49
50	// Returns the current disk limts set for the container.
51	CurrentDiskLimits() (DiskLimits, error)
52
53	// Returns the current memory limts set for the container.
54	CurrentMemoryLimits() (MemoryLimits, error)
55
56	// Map a port on the host to a port in the container so that traffic to the
57	// host port is forwarded to the container port. This is deprecated in
58	// favour of passing NetIn configuration in the ContainerSpec at creation
59	// time.
60	//
61	// If a host port is not given, a port will be acquired from the server's port
62	// pool.
63	//
64	// If a container port is not given, the port will be the same as the
65	// host port.
66	//
67	// The resulting host and container ports are returned in that order.
68	//
69	// Errors:
70	// * When no port can be acquired from the server's port pool.
71	NetIn(hostPort, containerPort uint32) (uint32, uint32, error)
72
73	// Whitelist outbound network traffic. This is deprecated in favour of passing
74	// NetOut configuration in the ContainerSpec at creation time.
75	//
76	// If the configuration directive deny_networks is not used,
77	// all networks are already whitelisted and this command is effectively a no-op.
78	//
79	// Later NetOut calls take precedence over earlier calls, which is
80	// significant only in relation to logging.
81	//
82	// Errors:
83	// * An error is returned if the NetOut call fails.
84	NetOut(netOutRule NetOutRule) error
85
86	// A Bulk call for NetOut. This is deprecated in favour of passing
87	// NetOut configuration in the ContainerSpec at creation time.
88	//
89	// Errors:
90	// * An error is returned if any of the NetOut calls fail.
91	BulkNetOut(netOutRules []NetOutRule) error
92
93	// Run a script inside a container.
94	//
95	// The root user will be mapped to a non-root UID in the host unless the container (not this process) was created with 'privileged' true.
96	//
97	// Errors:
98	// * TODO.
99	Run(ProcessSpec, ProcessIO) (Process, error)
100
101	// Attach starts streaming the output back to the client from a specified process.
102	//
103	// Errors:
104	// * processID does not refer to a running process.
105	Attach(processID string, io ProcessIO) (Process, error)
106
107	// Metrics returns the current set of metrics for a container
108	Metrics() (Metrics, error)
109
110	// Sets the grace time.
111	SetGraceTime(graceTime time.Duration) error
112
113	// Properties returns the current set of properties
114	Properties() (Properties, error)
115
116	// Property returns the value of the property with the specified name.
117	//
118	// Errors:
119	// * When the property does not exist on the container.
120	Property(name string) (string, error)
121
122	// Set a named property on a container to a specified value.
123	//
124	// Errors:
125	// * None.
126	SetProperty(name string, value string) error
127
128	// Remove a property with the specified name from a container.
129	//
130	// Errors:
131	// * None.
132	RemoveProperty(name string) error
133}
134
135// ProcessSpec contains parameters for running a script inside a container.
136type ProcessSpec struct {
137	// ID for the process. If empty, an ID will be generated.
138	ID string `json:"id,omitempty"`
139
140	// Path to command to execute.
141	Path string `json:"path,omitempty"`
142
143	// Arguments to pass to command.
144	Args []string `json:"args,omitempty"`
145
146	// Environment variables.
147	Env []string `json:"env,omitempty"`
148
149	// Working directory (default: home directory).
150	Dir string `json:"dir,omitempty"`
151
152	// The name of a user in the container to run the process as.
153	// This must either be a username, or uid:gid.
154	User string `json:"user,omitempty"`
155
156	// Resource limits
157	Limits ResourceLimits `json:"rlimits,omitempty"`
158
159	// Limits to be applied to the newly created process
160	OverrideContainerLimits *ProcessLimits `json:"limits,omitempty"`
161
162	// Execute with a TTY for stdio.
163	TTY *TTYSpec `json:"tty,omitempty"`
164
165	// Execute process in own root filesystem, different from the other processes
166	// in the container.
167	Image ImageRef `json:"image,omitempty"`
168
169	// Bind mounts to be applied to the process's filesystem
170	// An error is returned if ProcessSpec.Image is not also set.
171	BindMounts []BindMount `json:"bind_mounts,omitempty"`
172}
173
174type TTYSpec struct {
175	WindowSize *WindowSize `json:"window_size,omitempty"`
176}
177
178type WindowSize struct {
179	Columns int `json:"columns,omitempty"`
180	Rows    int `json:"rows,omitempty"`
181}
182
183type ProcessIO struct {
184	Stdin  io.Reader
185	Stdout io.Writer
186	Stderr io.Writer
187}
188
189//go:generate counterfeiter . Process
190
191type Process interface {
192	ID() string
193	Wait() (int, error)
194	SetTTY(TTYSpec) error
195	Signal(Signal) error
196}
197
198type Signal int
199
200const (
201	SignalTerminate Signal = iota
202	SignalKill
203)
204
205type PortMapping struct {
206	HostPort      uint32
207	ContainerPort uint32
208}
209
210type StreamInSpec struct {
211	Path      string
212	User      string
213	TarStream io.Reader
214}
215
216type StreamOutSpec struct {
217	Path string
218	User string
219}
220
221// ContainerInfo holds information about a container.
222type ContainerInfo struct {
223	State         string        // Either "active" or "stopped".
224	Events        []string      // List of events that occurred for the container. It currently includes only "oom" (Out Of Memory) event if it occurred.
225	HostIP        string        // The IP address of the gateway which controls the host side of the container's virtual ethernet pair.
226	ContainerIP   string        // The IP address of the container side of the container's virtual ethernet pair.
227	ExternalIP    string        //
228	ContainerPath string        // The path to the directory holding the container's files (both its control scripts and filesystem).
229	ProcessIDs    []string      // List of running processes.
230	Properties    Properties    // List of properties defined for the container.
231	MappedPorts   []PortMapping //
232}
233
234type ContainerInfoEntry struct {
235	Info ContainerInfo
236	Err  *Error
237}
238
239type Metrics struct {
240	MemoryStat     ContainerMemoryStat
241	CPUStat        ContainerCPUStat
242	DiskStat       ContainerDiskStat
243	NetworkStat    ContainerNetworkStat
244	PidStat        ContainerPidStat
245	Age            time.Duration
246	CPUEntitlement uint64
247}
248
249type ContainerMetricsEntry struct {
250	Metrics Metrics
251	Err     *Error
252}
253
254type ContainerMemoryStat struct {
255	ActiveAnon              uint64 `json:"active_anon"`
256	ActiveFile              uint64 `json:"active_file"`
257	Cache                   uint64 `json:"cache"`
258	HierarchicalMemoryLimit uint64 `json:"hierarchical_memory_limit"`
259	InactiveAnon            uint64 `json:"inactive_anon"`
260	InactiveFile            uint64 `json:"inactive_file"`
261	MappedFile              uint64 `json:"mapped_file"`
262	Pgfault                 uint64 `json:"pgfault"`
263	Pgmajfault              uint64 `json:"pgmajfault"`
264	Pgpgin                  uint64 `json:"pgpgin"`
265	Pgpgout                 uint64 `json:"pgpgout"`
266	Rss                     uint64 `json:"rss"`
267	TotalActiveAnon         uint64 `json:"total_active_anon"`
268	TotalActiveFile         uint64 `json:"total_active_file"`
269	TotalCache              uint64 `json:"total_cache"`
270	TotalInactiveAnon       uint64 `json:"total_inactive_anon"`
271	TotalInactiveFile       uint64 `json:"total_inactive_file"`
272	TotalMappedFile         uint64 `json:"total_mapped_file"`
273	TotalPgfault            uint64 `json:"total_pgfault"`
274	TotalPgmajfault         uint64 `json:"total_pgmajfault"`
275	TotalPgpgin             uint64 `json:"total_pgpgin"`
276	TotalPgpgout            uint64 `json:"total_pgpgout"`
277	TotalRss                uint64 `json:"total_rss"`
278	TotalUnevictable        uint64 `json:"total_unevictable"`
279	Unevictable             uint64 `json:"unevictable"`
280	Swap                    uint64 `json:"swap"`
281	HierarchicalMemswLimit  uint64 `json:"hierarchical_memsw_limit"`
282	TotalSwap               uint64 `json:"total_swap"`
283	// A memory usage total which reports memory usage in the same way that limits are enforced.
284	// This value includes memory consumed by nested containers.
285	TotalUsageTowardLimit uint64
286}
287
288type ContainerCPUStat struct {
289	Usage  uint64
290	User   uint64
291	System uint64
292}
293
294type ContainerPidStat struct {
295	Current uint64
296	Max     uint64
297}
298
299type ContainerDiskStat struct {
300	TotalBytesUsed      uint64
301	TotalInodesUsed     uint64
302	ExclusiveBytesUsed  uint64
303	ExclusiveInodesUsed uint64
304}
305
306type ContainerBandwidthStat struct {
307	InRate   uint64
308	InBurst  uint64
309	OutRate  uint64
310	OutBurst uint64
311}
312
313type ContainerNetworkStat struct {
314	RxBytes uint64
315	TxBytes uint64
316}
317
318type BandwidthLimits struct {
319	RateInBytesPerSecond      uint64 `json:"rate,omitempty"`
320	BurstRateInBytesPerSecond uint64 `json:"burst,omitempty"`
321}
322
323type ProcessLimits struct {
324	CPU    CPULimits    `json:"cpu_limits,omitempty"`
325	Memory MemoryLimits `json:"memory_limits,omitempty"`
326}
327
328type DiskLimits struct {
329	InodeSoft uint64 `json:"inode_soft,omitempty"`
330	InodeHard uint64 `json:"inode_hard,omitempty"`
331
332	ByteSoft uint64 `json:"byte_soft,omitempty"`
333	ByteHard uint64 `json:"byte_hard,omitempty"`
334
335	Scope DiskLimitScope `json:"scope,omitempty"`
336}
337
338type MemoryLimits struct {
339	//	Memory usage limit in bytes.
340	LimitInBytes uint64 `json:"limit_in_bytes,omitempty"`
341}
342
343type CPULimits struct {
344	Weight uint64 `json:"weight,omitempty"`
345	// Deprecated: Use Weight instead.
346	LimitInShares uint64 `json:"limit_in_shares,omitempty"`
347}
348
349type PidLimits struct {
350	// Limits the number of pids a container may create before new forks or clones are disallowed to processes in the container.
351	// Note: this may only be enforced when a process attempts to fork, so it does not guarantee that a new container.Run(ProcessSpec)
352	// will not succeed even if the limit has been exceeded, but the process will not be able to spawn further processes or threads.
353	Max uint64 `json:"max,omitempty"`
354}
355
356// Resource limits.
357//
358// Please refer to the manual page of getrlimit for a description of the individual fields:
359// http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html
360type ResourceLimits struct {
361	As         *uint64 `json:"as,omitempty"`
362	Core       *uint64 `json:"core,omitempty"`
363	Cpu        *uint64 `json:"cpu,omitempty"`
364	Data       *uint64 `json:"data,omitempty"`
365	Fsize      *uint64 `json:"fsize,omitempty"`
366	Locks      *uint64 `json:"locks,omitempty"`
367	Memlock    *uint64 `json:"memlock,omitempty"`
368	Msgqueue   *uint64 `json:"msgqueue,omitempty"`
369	Nice       *uint64 `json:"nice,omitempty"`
370	Nofile     *uint64 `json:"nofile,omitempty"`
371	Nproc      *uint64 `json:"nproc,omitempty"`
372	Rss        *uint64 `json:"rss,omitempty"`
373	Rtprio     *uint64 `json:"rtprio,omitempty"`
374	Sigpending *uint64 `json:"sigpending,omitempty"`
375	Stack      *uint64 `json:"stack,omitempty"`
376}
377
378type DiskLimitScope uint8
379
380const DiskLimitScopeTotal DiskLimitScope = 0
381const DiskLimitScopeExclusive DiskLimitScope = 1
382