garden

package
v0.0.0-...-33bca21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2015 License: Apache-2.0, Apache-2.0 Imports: 4 Imported by: 0

README

                                                 ,-.
                                                  ) \
                                              .--'   |
                                             /       /
                                             |_______|
                                            (  O   O  )
                                             {'-(_)-'}
                                           .-{   ^   }-.
                                          /   '.___.'   \
                                         /  |    o    |  \
                                         |__|    o    |__|
                                         (((\_________/)))
                                             \___|___/
                                        jgs.--' | | '--.
                                           \__._| |_.__/

Warden in Go, because why not.

Backends

Garden provides a platform-neutral API for containerization. Backends implement support for various specific platforms. So far, the list of backends is as follows:

Garden API

The canonical API for Garden is defined as a collection of Go interfaces. See the godoc documentation for details.

For convenience during Garden development, Garden also supports a REST API which may be used to "kick the tyres". The REST API is not supported.

For example, if Garden Linux is deployed to localhost and configured to listen on port 7777, the following commands may be used to kick its tyres:

# list containers (should be empty)
curl http://127.0.0.1:7777/containers

# create a container
curl -H "Content-Type: application/json" \
  -XPOST http://127.0.0.1:7777/containers \
  -d '{"rootfs":"docker:///busybox"}'

# list containers (should list the handle returned above)
curl http://127.0.0.1:7777/containers

# spawn a process
#
# curl will choke here as the protocol is hijacked, but...it probably worked.
curl -H "Content-Type: application/json" \
  -XPOST http://127.0.0.1:7777/containers/${handle}/processes \
  -d '{"path":"sleep","args":["10"]}'

See REST API examples for more.

Testing

Pre-requisites

  • git (for garden and its dependencies on github)
  • mercurial (for some dependencies not on github)

Make a directory to contain go code:

$ mkdir ~/go

Install Go. For example, install gvm and issue:

$ gvm install go1.4.1
$ gvm use go1.4.1

Make sure that your $GOPATH and $PATH are set. For example:

$ export GOPATH=~/go:$GOPATH
$ export PATH=$PATH:~/go/bin

Get garden and its dependencies:

$ go get -t -u github.com/cloudfoundry-incubator/garden
$ cd $GOPATH/src/github.com/cloudfoundry-incubator/garden
$ go get -t -u ./...

Install ginkgo (used to test garden):

$ go install github.com/onsi/ginkgo/ginkgo

Run the tests:

$ ginkgo -r

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewServiceUnavailableError

func NewServiceUnavailableError(cause string) error

Types

type Backend

type Backend interface {
	Client

	Start() error
	Stop()

	GraceTime(Container) time.Duration
}

type BandwidthLimits

type BandwidthLimits struct {
	RateInBytesPerSecond      uint64 `json:"rate,omitempty"`
	BurstRateInBytesPerSecond uint64 `json:"burst,omitempty"`
}

type BindMount

type BindMount struct {
	// SrcPath contains the path of the directory to be mounted.
	SrcPath string `json:"src_path,omitempty"`

	// DstPath contains the path of the mount point in the container. If the
	// directory does not exist, it is created.
	DstPath string `json:"dst_path,omitempty"`

	// Mode must be either "RO" or "RW". Alternatively, mode may be omitted and defaults to RO.
	// If mode is "RO", a read-only mount point is created.
	// If mode is "RW", a read-write mount point is created.
	Mode BindMountMode `json:"mode,omitempty"`

	// BindMountOrigin must be either "Host" or "Container". Alternatively, origin may be omitted and
	// defaults to "Host".
	// If origin is "Host", src_path denotes a path in the host.
	// If origin is "Container", src_path denotes a path in the container.
	Origin BindMountOrigin `json:"origin,omitempty"`
}

BindMount specifies parameters for a single mount point.

Each mount point is mounted (with the bind option) into the container's file system. The effective permissions of the mount point are the permissions of the source directory if the mode is read-write and the permissions of the source directory with the write bits turned off if the mode of the mount point is read-only.

type BindMountMode

type BindMountMode uint8
const BindMountModeRO BindMountMode = 0
const BindMountModeRW BindMountMode = 1

type BindMountOrigin

type BindMountOrigin uint8
const BindMountOriginContainer BindMountOrigin = 1
const BindMountOriginHost BindMountOrigin = 0

type CPULimits

type CPULimits struct {
	LimitInShares uint64 `json:"limit_in_shares,omitempty"`
}

type Capacity

type Capacity struct {
	MemoryInBytes uint64 `json:"memory_in_bytes,omitempty"`
	DiskInBytes   uint64 `json:"disk_in_bytes,omitempty"`
	MaxContainers uint64 `json:"max_containers,omitempty"`
}

type Client

type Client interface {
	// Pings the garden server.
	//
	// Errors:
	// * None.
	Ping() error

	// Capacity returns the physical capacity of the server's machine.
	//
	// Errors:
	// * None.
	Capacity() (Capacity, error)

	// Create creates a new container.
	//
	// Errors:
	// * When the handle, if specified, is already taken.
	// * When one of the bind_mount paths does not exist.
	// * When resource allocations fail (subnet, user ID, etc).
	Create(ContainerSpec) (Container, error)

	// Destroy destroys a container.
	//
	// When a container is destroyed, its resource allocations are released,
	// its filesystem is removed, and all references to its handle are removed.
	//
	// All resources that have been acquired during the lifetime of the container are released.
	// Examples of these resources are its subnet, its UID, and ports that were redirected to the container.
	//
	// TODO: list the resources that can be acquired during the lifetime of a container.
	//
	// Errors:
	// * TODO.
	Destroy(handle string) error

	// Containers lists all containers filtered by Properties (which are ANDed together).
	//
	// Errors:
	// * None.
	Containers(Properties) ([]Container, error)

	// BulkInfo returns info or error for a list of containers.
	BulkInfo(handles []string) (map[string]ContainerInfoEntry, error)

	// BulkMetrics returns metrics or error for a list of containers.
	BulkMetrics(handles []string) (map[string]ContainerMetricsEntry, error)

	// Lookup returns the container with the specified handle.
	//
	// Errors:
	// * Container not found.
	Lookup(handle string) (Container, error)
}

type Container

type Container interface {
	Handle() string

	// Stop stops a container.
	//
	// If kill is false, garden stops a container by sending the processes running inside it the SIGTERM signal.
	// It then waits for the processes to terminate before returning a response.
	// If one or more processes do not terminate within 10 seconds,
	// garden sends these processes the SIGKILL signal, killing them ungracefully.
	//
	// If kill is true, garden stops a container by sending the processing running inside it a SIGKILL signal.
	//
	// Once a container is stopped, garden does not allow spawning new processes inside the container.
	// It is possible to copy files in to and out of a stopped container.
	// It is only when a container is destroyed that its filesystem is cleaned up.
	//
	// Errors:
	// * None.
	Stop(kill bool) error

	// Returns information about a container.
	Info() (ContainerInfo, error)

	// StreamIn streams data into a file in a container.
	//
	// Errors:
	// *  TODO.
	StreamIn(dstPath string, tarStream io.Reader) error

	// StreamOut streams a file out of a container.
	//
	// Errors:
	// * TODO.
	StreamOut(srcPath string) (io.ReadCloser, error)

	// Limits the network bandwidth for a container.
	LimitBandwidth(limits BandwidthLimits) error

	CurrentBandwidthLimits() (BandwidthLimits, error)

	// Limits the CPU shares for a container.
	LimitCPU(limits CPULimits) error

	CurrentCPULimits() (CPULimits, error)

	// Limits the disk usage for a container.
	//
	// The disk limits that are set by this command only have effect for the container's unprivileged user.
	// Files/directories created by its privileged user are not subject to these limits.
	//
	// TODO: explain how disk management works.
	LimitDisk(limits DiskLimits) error
	CurrentDiskLimits() (DiskLimits, error)

	// Limits the memory usage for a container.
	//
	// The limit applies to all process in the container. When the limit is
	// exceeded, the container will be automatically stopped.
	//
	// Errors:
	// * The kernel does not support setting memory.memsw.limit_in_bytes.
	LimitMemory(limits MemoryLimits) error

	CurrentMemoryLimits() (MemoryLimits, error)

	// Map a port on the host to a port in the container so that traffic to the
	// host port is forwarded to the container port.
	//
	// If a host port is not given, a port will be acquired from the server's port
	// pool.
	//
	// If a container port is not given, the port will be the same as the
	// container port.
	//
	// The two resulting ports are returned in the response.
	//
	// Errors:
	// * When no port can be acquired from the server's port pool.
	NetIn(hostPort, containerPort uint32) (uint32, uint32, error)

	// Whitelist outbound network traffic.
	//
	// If the configuration directive deny_networks is not used,
	// all networks are already whitelisted and this command is effectively a no-op.
	//
	// Later NetOut calls take precedence over earlier calls, which is
	// significant only in relation to logging.
	//
	// Errors:
	// * An error is returned if the NetOut call fails.
	NetOut(netOutRule NetOutRule) error

	// Run a script inside a container.
	//
	// The 'privileged' flag remains for backwards compatibility, but the 'user' flag is preferred.
	// 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.
	//
	// Errors:
	// * TODO.
	Run(ProcessSpec, ProcessIO) (Process, error)

	// Attach starts streaming the output back to the client from a specified process.
	//
	// Errors:
	// * processID does not refer to a running process.
	Attach(processID uint32, io ProcessIO) (Process, error)

	// Metrics returns the current set of metrics for a container
	Metrics() (Metrics, error)

	// Properties returns the current set of properties
	Properties() (Properties, error)

	// Property returns the value of the property with the specified name.
	//
	// Errors:
	// * When the property does not exist on the container.
	Property(name string) (string, error)

	// Set a named property on a container to a specified value.
	//
	// Errors:
	// * None.
	SetProperty(name string, value string) error

	// Remove a property with the specified name from a container.
	//
	// Errors:
	// * None.
	RemoveProperty(name string) error
}

type ContainerBandwidthStat

type ContainerBandwidthStat struct {
	InRate   uint64
	InBurst  uint64
	OutRate  uint64
	OutBurst uint64
}

type ContainerCPUStat

type ContainerCPUStat struct {
	Usage  uint64
	User   uint64
	System uint64
}

type ContainerDiskStat

type ContainerDiskStat struct {
	BytesUsed  uint64
	InodesUsed uint64
}

type ContainerInfo

type ContainerInfo struct {
	State         string        // Either "active" or "stopped".
	Events        []string      // List of events that occurred for the container. It currently includes only "oom" (Out Of Memory) event if it occurred.
	HostIP        string        // The IP address of the gateway which controls the host side of the container's virtual ethernet pair.
	ContainerIP   string        // The IP address of the container side of the container's virtual ethernet pair.
	ExternalIP    string        //
	ContainerPath string        // The path to the directory holding the container's files (both its control scripts and filesystem).
	ProcessIDs    []uint32      // List of running processes.
	Properties    Properties    // List of properties defined for the container.
	MappedPorts   []PortMapping //
}

ContainerInfo holds information about a container.

type ContainerInfoEntry

type ContainerInfoEntry struct {
	Info ContainerInfo
	Err  *Error
}

type ContainerMemoryStat

type ContainerMemoryStat struct {
	Cache                   uint64
	Rss                     uint64
	MappedFile              uint64
	Pgpgin                  uint64
	Pgpgout                 uint64
	Swap                    uint64
	Pgfault                 uint64
	Pgmajfault              uint64
	InactiveAnon            uint64
	ActiveAnon              uint64
	InactiveFile            uint64
	ActiveFile              uint64
	Unevictable             uint64
	HierarchicalMemoryLimit uint64
	HierarchicalMemswLimit  uint64
	TotalCache              uint64
	TotalRss                uint64
	TotalMappedFile         uint64
	TotalPgpgin             uint64
	TotalPgpgout            uint64
	TotalSwap               uint64
	TotalPgfault            uint64
	TotalPgmajfault         uint64
	TotalInactiveAnon       uint64
	TotalActiveAnon         uint64
	TotalInactiveFile       uint64
	TotalActiveFile         uint64
	TotalUnevictable        uint64
}

type ContainerMetricsEntry

type ContainerMetricsEntry struct {
	Metrics Metrics
	Err     *Error
}

type ContainerNotFoundError

type ContainerNotFoundError struct {
	Handle string
}

func (ContainerNotFoundError) Error

func (err ContainerNotFoundError) Error() string

type ContainerSpec

type ContainerSpec struct {

	// Handle, if specified, is used to refer to the
	// container in future requests. If it is not specified,
	// garden uses its internal container ID as the container handle.
	Handle string `json:"handle,omitempty"`

	// GraceTime can be used to specify how long a container can go
	// unreferenced by any client connection. After this time, the container will
	// automatically be destroyed. If not specified, the container will be
	// subject to the globally configured grace time.
	GraceTime time.Duration `json:"grace_time,omitempty"`

	// RootFSPath is a URI referring to the root file system for the container.
	// The URI scheme must either be the empty string or "docker".
	//
	// A URI with an empty scheme determines the path of a root file system.
	// If this path is empty, a default root file system is used.
	// Other parts of the URI are ignored.
	//
	// A URI with scheme "docker" refers to a Docker image. The path in the URI
	// (without the leading /) identifies a Docker image as the repository name
	// in the default Docker registry. If a fragment is specified in the URI, this
	// determines the tag associated with the image.
	// If a host is specified in the URI, this determines the Docker registry to use.
	// If no host is specified in the URI, a default Docker registry is used.
	// Other parts of the URI are ignored.
	//
	// Examples:
	// * "/some/path"
	// * "docker:///onsi/grace-busybox"
	// * "docker://index.docker.io/busybox"
	RootFSPath string `json:"rootfs,omitempty"`

	// * bind_mounts: a list of mount point descriptions which will result in corresponding mount
	// points being created in the container's file system.
	//
	// An error is returned if:
	// * one or more of the mount points has a non-existent source directory, or
	// * one or more of the mount points cannot be created.
	BindMounts []BindMount `json:"bind_mounts,omitempty"`

	// Network determines the subnet and IP address of a container.
	//
	// If not specified, a /30 subnet is allocated from a default network pool.
	//
	// If specified, it takes the form a.b.c.d/n where a.b.c.d is an IP address and n is the number of
	// bits in the network prefix. a.b.c.d masked by the first n bits is the network address of a subnet
	// called the subnet address. If the remaining bits are zero (i.e. a.b.c.d *is* the subnet address),
	// the container is allocated an unused IP address from the subnet. Otherwise, the container is given
	// the IP address a.b.c.d.
	//
	// The container IP address cannot be the subnet address or the broadcast address of the subnet
	// (all non prefix bits set) or the address one less than the broadcast address (which is reserved).
	//
	// Multiple containers may share a subnet by passing the same subnet address on the corresponding
	// create calls. Containers on the same subnet can communicate with each other over IP
	// without restriction. In particular, they are not affected by packet filtering.
	//
	// Note that a container can use TCP, UDP, and ICMP, although its external access is governed
	// by filters (see Container.NetOut()) and by any implementation-specific filters.
	//
	// An error is returned if:
	// * the IP address cannot be allocated or is already in use,
	// * the subnet specified overlaps the default network pool, or
	// * the subnet specified overlaps (but does not equal) a subnet that has
	//   already had a container allocated from it.
	Network string `json:"network,omitempty"`

	// Properties is a sequence of string key/value pairs providing arbitrary
	// data about the container. The keys are assumed to be unique but this is not
	// enforced via the protocol.
	Properties Properties `json:"properties,omitempty"`

	// TODO
	Env []string `json:"env,omitempty"`

	// If Privileged is true the container does not have a user namespace and the root user in the container
	// is the same as the root user in the host. Otherwise, the container has a user namespace and the root
	// user in the container is mapped to a non-root user in the host. Defaults to false.
	Privileged bool `json:"privileged,omitempty"`
}

ContainerSpec specifies the parameters for creating a container. All parameters are optional.

type DiskLimits

type DiskLimits struct {
	BlockSoft uint64 `json:"block_soft,omitempty"`
	BlockHard uint64 `json:"block_hard,omitempty"`

	InodeSoft uint64 `json:"inode_soft,omitempty"`
	InodeHard uint64 `json:"inode_hard,omitempty"`

	// New soft block limit specified in bytes. Only has effect when BlockSoft is not specified.
	ByteSoft uint64 `json:"byte_soft,omitempty"`

	// New hard block limit specified in bytes. Only has effect when BlockHard is not specified.
	ByteHard uint64 `json:"byte_hard,omitempty"`
}

type Error

type Error struct {
	ErrorMsg string `json:"error_msg"`
}

func NewError

func NewError(msg string) *Error

func (*Error) Error

func (e *Error) Error() string

type ICMPCode

type ICMPCode uint8

func ICMPControlCode

func ICMPControlCode(code uint8) *ICMPCode

ICMPControlCode creates a value for the Code field in ICMPControl

type ICMPControl

type ICMPControl struct {
	Type ICMPType  `json:"type,omitempty"`
	Code *ICMPCode `json:"code,omitempty"`
}

type ICMPType

type ICMPType uint8

type IPRange

type IPRange struct {
	Start net.IP `json:"start,omitempty"`
	End   net.IP `json:"end,omitempty"`
}

func IPRangeFromIP

func IPRangeFromIP(ip net.IP) IPRange

IPRangeFromIP creates an IPRange containing a single IP

func IPRangeFromIPNet

func IPRangeFromIPNet(ipNet *net.IPNet) IPRange

IPRangeFromIPNet creates an IPRange containing the same IPs as a given IPNet

type MemoryLimits

type MemoryLimits struct {
	//	Memory usage limit in bytes.
	LimitInBytes uint64 `json:"limit_in_bytes,omitempty"`
}

type Metrics

type Metrics struct {
	MemoryStat ContainerMemoryStat
	CPUStat    ContainerCPUStat
	DiskStat   ContainerDiskStat
}

type NetOutRule

type NetOutRule struct {
	// the protocol to be whitelisted; default TCP
	Protocol Protocol `json:"protocol,omitempty"`

	// a list of ranges of IP addresses to whitelist; Start to End inclusive; default all
	Networks []IPRange `json:"networks,omitempty"`

	// a list of ranges of ports to whitelist; Start to End inclusive; ignored if Protocol is ICMP; default all
	Ports []PortRange `json:"ports,omitempty"`

	// specifying which ICMP codes to whitelist; ignored if Protocol is not ICMP; default all
	ICMPs *ICMPControl `json:"icmps,omitempty"`

	// if true, logging is enabled; ignored if Protocol is not TCP or All; default false
	Log bool `json:"log,omitempty"`
}

type PortMapping

type PortMapping struct {
	HostPort      uint32
	ContainerPort uint32
}

type PortRange

type PortRange struct {
	Start uint16 `json:"start,omitempty"`
	End   uint16 `json:"end,omitempty"`
}

func PortRangeFromPort

func PortRangeFromPort(port uint16) PortRange

PortRangeFromPort creates a PortRange containing a single port

type Process

type Process interface {
	ID() uint32
	Wait() (int, error)
	SetTTY(TTYSpec) error
	Signal(Signal) error
}

type ProcessIO

type ProcessIO struct {
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
}

type ProcessSpec

type ProcessSpec struct {
	// Path to command to execute.
	Path string `json:"path,omitempty"`

	// Arguments to pass to command.
	Args []string `json:"args,omitempty"`

	// Environment variables.
	Env []string `json:"env,omitempty"`

	// Working directory (default: home directory).
	Dir string `json:"dir,omitempty"`

	// Whether to run the script as root or not. Can be overriden by 'user', if specified.
	Privileged bool `json:"privileged,omitempty"`

	// The name of a user in the container to run the process as. If not specified defaults to 'root' for privileged processes, and 'vcap' for unprivileged processes.
	User string `json:"user,omitempty"`

	// Resource limits
	Limits ResourceLimits `json:"rlimits,omitempty"`

	// Execute with a TTY for stdio.
	TTY *TTYSpec `json:"tty,omitempty"`
}

ProcessSpec contains parameters for running a script inside a container.

type Properties

type Properties map[string]string

type Protocol

type Protocol uint8
const (
	ProtocolAll Protocol = iota
	ProtocolTCP
	ProtocolUDP
	ProtocolICMP
)

type ResourceLimits

type ResourceLimits struct {
	As         *uint64 `json:"as,omitempty"`
	Core       *uint64 `json:"core,omitempty"`
	Cpu        *uint64 `json:"cpu,omitempty"`
	Data       *uint64 `json:"data,omitempty"`
	Fsize      *uint64 `json:"fsize,omitempty"`
	Locks      *uint64 `json:"locks,omitempty"`
	Memlock    *uint64 `json:"memlock,omitempty"`
	Msgqueue   *uint64 `json:"msgqueue,omitempty"`
	Nice       *uint64 `json:"nice,omitempty"`
	Nofile     *uint64 `json:"nofile,omitempty"`
	Nproc      *uint64 `json:"nproc,omitempty"`
	Rss        *uint64 `json:"rss,omitempty"`
	Rtprio     *uint64 `json:"rtprio,omitempty"`
	Sigpending *uint64 `json:"sigpending,omitempty"`
	Stack      *uint64 `json:"stack,omitempty"`
}

Resource limits.

Please refer to the manual page of getrlimit for a description of the individual fields: http://www.kernel.org/doc/man-pages/online/pages/man2/getrlimit.2.html

type ServiceUnavailableError

type ServiceUnavailableError struct {
	Cause string
}

func (*ServiceUnavailableError) Error

func (err *ServiceUnavailableError) Error() string

type Signal

type Signal int
const (
	SignalTerminate Signal = iota
	SignalKill
)

type TTYSpec

type TTYSpec struct {
	WindowSize *WindowSize `json:"window_size,omitempty"`
}

type WindowSize

type WindowSize struct {
	Columns int `json:"columns,omitempty"`
	Rows    int `json:"rows,omitempty"`
}

Directories

Path Synopsis
connection/fakes
This file was generated by counterfeiter
This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter
This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter This file was generated by counterfeiter

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL