From 5170a2c096ff64d4bfbe0fab296ec6777c412bc3 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sat, 25 Jul 2015 11:11:45 +0200 Subject: [PATCH] Lint fixes on runconfig Signed-off-by: Vincent Demeester --- api/client/run.go | 4 +- api/server/server_linux.go | 14 ++-- api/server/server_linux_test.go | 32 ++++----- builder/internals.go | 6 +- daemon/container_unix.go | 16 ++--- daemon/daemon_unix.go | 8 +-- daemon/inspect.go | 2 +- hack/make/validate-lint | 1 + runconfig/config.go | 77 +++++++++++++------- runconfig/exec.go | 24 ++++--- runconfig/hostconfig.go | 121 ++++++++++++++++++++++---------- runconfig/hostconfig_unix.go | 10 ++- runconfig/hostconfig_windows.go | 4 ++ runconfig/merge.go | 5 ++ runconfig/parse.go | 57 +++++++++------ runconfig/parse_test.go | 4 +- runconfig/parse_unix.go | 4 +- 17 files changed, 245 insertions(+), 144 deletions(-) diff --git a/api/client/run.go b/api/client/run.go index 182dc4b1f9..50fccfa390 100644 --- a/api/client/run.go +++ b/api/client/run.go @@ -63,11 +63,11 @@ func (cli *DockerCli) CmdRun(args ...string) error { os.Exit(1) } - if len(hostConfig.Dns) > 0 { + if len(hostConfig.DNS) > 0 { // check the DNS settings passed via --dns against // localhost regexp to warn if they are trying to // set a DNS to a localhost address - for _, dnsIP := range hostConfig.Dns { + for _, dnsIP := range hostConfig.DNS { if dns.IsLocalhost(dnsIP) { fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP) break diff --git a/api/server/server_linux.go b/api/server/server_linux.go index f6ad26a9bf..70a170bd9f 100644 --- a/api/server/server_linux.go +++ b/api/server/server_linux.go @@ -109,14 +109,14 @@ func allocateDaemonPort(addr string) error { func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) { if version.LessThan("1.19") { - if hostConfig != nil && hostConfig.CpuShares > 0 { + if hostConfig != nil && hostConfig.CPUShares > 0 { // Handle unsupported CpuShares - if hostConfig.CpuShares < linuxMinCpuShares { - logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CpuShares, linuxMinCpuShares) - hostConfig.CpuShares = linuxMinCpuShares - } else if hostConfig.CpuShares > linuxMaxCpuShares { - logrus.Warnf("Changing requested CpuShares of %d to maximum allowed of %d", hostConfig.CpuShares, linuxMaxCpuShares) - hostConfig.CpuShares = linuxMaxCpuShares + if hostConfig.CPUShares < linuxMinCpuShares { + logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCpuShares) + hostConfig.CPUShares = linuxMinCpuShares + } else if hostConfig.CPUShares > linuxMaxCpuShares { + logrus.Warnf("Changing requested CpuShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCpuShares) + hostConfig.CPUShares = linuxMaxCpuShares } } } diff --git a/api/server/server_linux_test.go b/api/server/server_linux_test.go index 47289653eb..e019caaa91 100644 --- a/api/server/server_linux_test.go +++ b/api/server/server_linux_test.go @@ -12,28 +12,28 @@ import ( func TestAdjustCpuSharesOldApi(t *testing.T) { apiVersion := version.Version("1.18") hostConfig := &runconfig.HostConfig{ - CpuShares: linuxMinCpuShares - 1, + CPUShares: linuxMinCpuShares - 1, } adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != linuxMinCpuShares { + if hostConfig.CPUShares != linuxMinCpuShares { t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares) } - hostConfig.CpuShares = linuxMaxCpuShares + 1 + hostConfig.CPUShares = linuxMaxCpuShares + 1 adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != linuxMaxCpuShares { + if hostConfig.CPUShares != linuxMaxCpuShares { t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares) } - hostConfig.CpuShares = 0 + hostConfig.CPUShares = 0 adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != 0 { + if hostConfig.CPUShares != 0 { t.Error("Expected CpuShares to be unchanged") } - hostConfig.CpuShares = 1024 + hostConfig.CPUShares = 1024 adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != 1024 { + if hostConfig.CPUShares != 1024 { t.Error("Expected CpuShares to be unchanged") } } @@ -41,28 +41,28 @@ func TestAdjustCpuSharesOldApi(t *testing.T) { func TestAdjustCpuSharesNoAdjustment(t *testing.T) { apiVersion := version.Version("1.19") hostConfig := &runconfig.HostConfig{ - CpuShares: linuxMinCpuShares - 1, + CPUShares: linuxMinCpuShares - 1, } adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != linuxMinCpuShares-1 { + if hostConfig.CPUShares != linuxMinCpuShares-1 { t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares-1) } - hostConfig.CpuShares = linuxMaxCpuShares + 1 + hostConfig.CPUShares = linuxMaxCpuShares + 1 adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != linuxMaxCpuShares+1 { + if hostConfig.CPUShares != linuxMaxCpuShares+1 { t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares+1) } - hostConfig.CpuShares = 0 + hostConfig.CPUShares = 0 adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != 0 { + if hostConfig.CPUShares != 0 { t.Error("Expected CpuShares to be unchanged") } - hostConfig.CpuShares = 1024 + hostConfig.CPUShares = 1024 adjustCpuShares(apiVersion, hostConfig) - if hostConfig.CpuShares != 1024 { + if hostConfig.CPUShares != 1024 { t.Error("Expected CpuShares to be unchanged") } } diff --git a/builder/internals.go b/builder/internals.go index a8e14160a9..b23b49e8f0 100644 --- a/builder/internals.go +++ b/builder/internals.go @@ -607,9 +607,9 @@ func (b *builder) create() (*daemon.Container, error) { b.Config.Image = b.image hostConfig := &runconfig.HostConfig{ - CpuShares: b.cpuShares, - CpuPeriod: b.cpuPeriod, - CpuQuota: b.cpuQuota, + CPUShares: b.cpuShares, + CPUPeriod: b.cpuPeriod, + CPUQuota: b.cpuQuota, CpusetCpus: b.cpuSetCpus, CpusetMems: b.cpuSetMems, CgroupParent: b.cgroupParent, diff --git a/daemon/container_unix.go b/daemon/container_unix.go index 6ae56cb8c9..49ee6b6789 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -264,11 +264,11 @@ func populateCommand(c *Container, env []string) error { resources := &execdriver.Resources{ Memory: c.hostConfig.Memory, MemorySwap: c.hostConfig.MemorySwap, - CpuShares: c.hostConfig.CpuShares, + CpuShares: c.hostConfig.CPUShares, CpusetCpus: c.hostConfig.CpusetCpus, CpusetMems: c.hostConfig.CpusetMems, - CpuPeriod: c.hostConfig.CpuPeriod, - CpuQuota: c.hostConfig.CpuQuota, + CpuPeriod: c.hostConfig.CPUPeriod, + CpuQuota: c.hostConfig.CPUQuota, BlkioWeight: c.hostConfig.BlkioWeight, Rlimits: rlimits, OomKillDisable: c.hostConfig.OomKillDisable, @@ -423,8 +423,8 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err } joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath)) - if len(container.hostConfig.Dns) > 0 { - dns = container.hostConfig.Dns + if len(container.hostConfig.DNS) > 0 { + dns = container.hostConfig.DNS } else if len(container.daemon.config.Dns) > 0 { dns = container.daemon.config.Dns } @@ -433,8 +433,8 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d)) } - if len(container.hostConfig.DnsSearch) > 0 { - dnsSearch = container.hostConfig.DnsSearch + if len(container.hostConfig.DNSSearch) > 0 { + dnsSearch = container.hostConfig.DNSSearch } else if len(container.daemon.config.DnsSearch) > 0 { dnsSearch = container.daemon.config.DnsSearch } @@ -543,7 +543,7 @@ func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork for _, tp := range exposedPorts { natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port))) if err != nil { - return nil, fmt.Errorf("Error parsing Port value(%s):%v", tp.Port, err) + return nil, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err) } networkSettings.Ports[natPort] = nil } diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 83adea9f9e..3b59eff56d 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -185,15 +185,15 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig, if hostConfig.MemorySwappiness != -1 && (hostConfig.MemorySwappiness < 0 || hostConfig.MemorySwappiness > 100) { return warnings, fmt.Errorf("Invalid value: %d, valid memory swappiness range is 0-100.", hostConfig.MemorySwappiness) } - if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod { + if hostConfig.CPUPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod { warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.") logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.") - hostConfig.CpuPeriod = 0 + hostConfig.CPUPeriod = 0 } - if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota { + if hostConfig.CPUQuota > 0 && !daemon.SystemConfig().CpuCfsQuota { warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.") - hostConfig.CpuQuota = 0 + hostConfig.CPUQuota = 0 } if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) { return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") diff --git a/daemon/inspect.go b/daemon/inspect.go index a2cea99df8..d4e96e2e48 100644 --- a/daemon/inspect.go +++ b/daemon/inspect.go @@ -61,7 +61,7 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONP container.Config, container.hostConfig.Memory, container.hostConfig.MemorySwap, - container.hostConfig.CpuShares, + container.hostConfig.CPUShares, container.hostConfig.CpusetCpus, } diff --git a/hack/make/validate-lint b/hack/make/validate-lint index c39dd7e08e..9b18308956 100644 --- a/hack/make/validate-lint +++ b/hack/make/validate-lint @@ -38,6 +38,7 @@ packages=( pkg/urlutil pkg/version registry + runconfig utils ) diff --git a/runconfig/config.go b/runconfig/config.go index 2196828d10..0312cc4c88 100644 --- a/runconfig/config.go +++ b/runconfig/config.go @@ -17,6 +17,8 @@ type Entrypoint struct { parts []string } +// MarshalJSON Marshals (or serializes) the Entrypoint into the json format. +// This method is needed to implement json.Marshaller. func (e *Entrypoint) MarshalJSON() ([]byte, error) { if e == nil { return []byte{}, nil @@ -24,7 +26,8 @@ func (e *Entrypoint) MarshalJSON() ([]byte, error) { return json.Marshal(e.Slice()) } -// UnmarshalJSON decoded the entrypoint whether it's a string or an array of strings. +// UnmarshalJSON decodes the entrypoint whether it's a string or an array of strings. +// This method is needed to implement json.Unmarshaler. func (e *Entrypoint) UnmarshalJSON(b []byte) error { if len(b) == 0 { return nil @@ -42,6 +45,7 @@ func (e *Entrypoint) UnmarshalJSON(b []byte) error { return nil } +// Len returns the number of parts of the Entrypoint. func (e *Entrypoint) Len() int { if e == nil { return 0 @@ -49,6 +53,7 @@ func (e *Entrypoint) Len() int { return len(e.parts) } +// Slice gets the parts of the Entrypoint as a Slice of string. func (e *Entrypoint) Slice() []string { if e == nil { return nil @@ -56,18 +61,27 @@ func (e *Entrypoint) Slice() []string { return e.parts } +// NewEntrypoint creates an Entrypoint based on the specified parts (as strings). func NewEntrypoint(parts ...string) *Entrypoint { return &Entrypoint{parts} } +// Command encapsulates the container command. +// It might be represented as a string or an array of strings. +// We need to override the json decoder to accept both options. +// The JSON decoder will fail if the api sends an string and +// we try to decode it into an array of string. type Command struct { parts []string } +// ToString gets a string representing a Command. func (e *Command) ToString() string { return strings.Join(e.parts, " ") } +// MarshalJSON Marshals (or serializes) the Command into the json format. +// This method is needed to implement json.Marshaller. func (e *Command) MarshalJSON() ([]byte, error) { if e == nil { return []byte{}, nil @@ -75,7 +89,8 @@ func (e *Command) MarshalJSON() ([]byte, error) { return json.Marshal(e.Slice()) } -// UnmarshalJSON decoded the entrypoint whether it's a string or an array of strings. +// UnmarshalJSON decodes the entrypoint whether it's a string or an array of strings. +// This method is needed to implement json.Unmarshaler. func (e *Command) UnmarshalJSON(b []byte) error { if len(b) == 0 { return nil @@ -93,6 +108,7 @@ func (e *Command) UnmarshalJSON(b []byte) error { return nil } +// Len returns the number of parts of the Entrypoint. func (e *Command) Len() int { if e == nil { return 0 @@ -100,6 +116,7 @@ func (e *Command) Len() int { return len(e.parts) } +// Slice gets the parts of the Entrypoint as a Slice of string. func (e *Command) Slice() []string { if e == nil { return nil @@ -107,38 +124,42 @@ func (e *Command) Slice() []string { return e.parts } +// NewCommand creates a Command based on the specified parts (as strings). func NewCommand(parts ...string) *Command { return &Command{parts} } -// Note: the Config structure should hold only portable information about the container. +// Config contains the configuration data about a container. +// It should hold only portable information about the container. // Here, "portable" means "independent from the host we are running on". // Non-portable information *should* appear in HostConfig. type Config struct { - Hostname string - Domainname string - User string - AttachStdin bool - AttachStdout bool - AttachStderr bool - ExposedPorts map[nat.Port]struct{} - PublishService string - Tty bool // Attach standard streams to a tty, including stdin if it is not closed. - OpenStdin bool // Open stdin - StdinOnce bool // If true, close stdin after the 1 attached client disconnects. - Env []string - Cmd *Command - Image string // Name of the image as it was passed by the operator (eg. could be symbolic) - Volumes map[string]struct{} - VolumeDriver string - WorkingDir string - Entrypoint *Entrypoint - NetworkDisabled bool - MacAddress string - OnBuild []string - Labels map[string]string + Hostname string // Hostname + Domainname string // Domainname + User string // User that will run the command(s) inside the container + AttachStdin bool // Attach the standard input, makes possible user interaction + AttachStdout bool // Attach the standard output + AttachStderr bool // Attach the standard error + ExposedPorts map[nat.Port]struct{} // List of exposed ports + PublishService string // Name of the network service exposed by the container + Tty bool // Attach standard streams to a tty, including stdin if it is not closed. + OpenStdin bool // Open stdin + StdinOnce bool // If true, close stdin after the 1 attached client disconnects. + Env []string // List of environment variable to set in the container + Cmd *Command // Command to run when starting the container + Image string // Name of the image as it was passed by the operator (eg. could be symbolic) + Volumes map[string]struct{} // List of volumes (mounts) used for the container + VolumeDriver string // Name of the volume driver used to mount volumes + WorkingDir string // Current directory (PWD) in the command will be launched + Entrypoint *Entrypoint // Entrypoint to run when starting the container + NetworkDisabled bool // Is network disabled + MacAddress string // Mac Address of the container + OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile + Labels map[string]string // List of labels set to this container } +// ContainerConfigWrapper is a Config wrapper that hold the container Config (portable) +// and the corresponding HostConfig (non-portable). type ContainerConfigWrapper struct { *Config InnerHostConfig *HostConfig `json:"HostConfig,omitempty"` @@ -147,6 +168,8 @@ type ContainerConfigWrapper struct { } +// GetHostConfig gets the HostConfig of the Config. +// It's mostly there to handle Deprecated fields of the ContainerConfigWrapper func (w *ContainerConfigWrapper) GetHostConfig() *HostConfig { hc := w.HostConfig @@ -159,8 +182,8 @@ func (w *ContainerConfigWrapper) GetHostConfig() *HostConfig { if hc.MemorySwap != 0 && w.InnerHostConfig.MemorySwap == 0 { w.InnerHostConfig.MemorySwap = hc.MemorySwap } - if hc.CpuShares != 0 && w.InnerHostConfig.CpuShares == 0 { - w.InnerHostConfig.CpuShares = hc.CpuShares + if hc.CPUShares != 0 && w.InnerHostConfig.CPUShares == 0 { + w.InnerHostConfig.CPUShares = hc.CPUShares } hc = w.InnerHostConfig diff --git a/runconfig/exec.go b/runconfig/exec.go index 781cb3550f..1f13d7dd0f 100644 --- a/runconfig/exec.go +++ b/runconfig/exec.go @@ -4,18 +4,24 @@ import ( flag "github.com/docker/docker/pkg/mflag" ) +// ExecConfig is a small subset of the Config struct that hold the configuration +// for the exec feature of docker. type ExecConfig struct { - User string - Privileged bool - Tty bool - Container string - AttachStdin bool - AttachStderr bool - AttachStdout bool - Detach bool - Cmd []string + User string // User that will run the command + Privileged bool // Is the container in privileged mode + Tty bool // Attach standard streams to a tty. + Container string // Name of the container (to execute in) + AttachStdin bool // Attach the standard input, makes possible user interaction + AttachStderr bool // Attach the standard output + AttachStdout bool // Attach the standard error + Detach bool // Execute in detach mode + Cmd []string // Execution commands and args } +// ParseExec parses the specified args for the specified command and generates +// an ExecConfig from it. +// If the minimal number of specified args is not right or if specified args are +// not valid, it will return an error. func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) { var ( flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached") diff --git a/runconfig/hostconfig.go b/runconfig/hostconfig.go index 21b40dc104..fdf64029a4 100644 --- a/runconfig/hostconfig.go +++ b/runconfig/hostconfig.go @@ -9,29 +9,35 @@ import ( "github.com/docker/docker/pkg/ulimit" ) +// KeyValuePair is a structure that hold a value for a key. type KeyValuePair struct { Key string Value string } +// NetworkMode represents the container network stack. type NetworkMode string +// IpcMode represents the container ipc stack. type IpcMode string -// IsPrivate indicates whether container use it's private ipc stack +// IsPrivate indicates whether the container uses it's private ipc stack. func (n IpcMode) IsPrivate() bool { return !(n.IsHost() || n.IsContainer()) } +// IsHost indicates whether the container uses the host's ipc stack. func (n IpcMode) IsHost() bool { return n == "host" } +// IsContainer indicates whether the container uses a container's ipc stack. func (n IpcMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) return len(parts) > 1 && parts[0] == "container" } +// Valid indicates whether the ipc stack is valid. func (n IpcMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { @@ -46,6 +52,7 @@ func (n IpcMode) Valid() bool { return true } +// Container returns the name of the container ipc stack is going to be used. func (n IpcMode) Container() string { parts := strings.SplitN(string(n), ":", 2) if len(parts) > 1 { @@ -54,17 +61,20 @@ func (n IpcMode) Container() string { return "" } +// UTSMode represents the UTS namespace of the container. type UTSMode string -// IsPrivate indicates whether container use it's private UTS namespace +// IsPrivate indicates whether the container uses it's private UTS namespace. func (n UTSMode) IsPrivate() bool { return !(n.IsHost()) } +// IsHost indicates whether the container uses the host's UTS namespace. func (n UTSMode) IsHost() bool { return n == "host" } +// Valid indicates whether the UTS namespace is valid. func (n UTSMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { @@ -75,17 +85,20 @@ func (n UTSMode) Valid() bool { return true } +// PidMode represents the pid stack of the container. type PidMode string -// IsPrivate indicates whether container use it's private pid stack +// IsPrivate indicates whether the container uses it's private pid stack. func (n PidMode) IsPrivate() bool { return !(n.IsHost()) } +// IsHost indicates whether the container uses the host's pid stack. func (n PidMode) IsHost() bool { return n == "host" } +// Valid indicates whether the pid stack is valid. func (n PidMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { @@ -96,38 +109,49 @@ func (n PidMode) Valid() bool { return true } +// DeviceMapping represents the device mapping between the host and the container. type DeviceMapping struct { PathOnHost string PathInContainer string CgroupPermissions string } +// RestartPolicy represents the restart policies of the container. type RestartPolicy struct { Name string MaximumRetryCount int } +// IsNone indicates whether the container has the "no" restart policy. +// This means the container will not automatically restart when exiting. func (rp *RestartPolicy) IsNone() bool { return rp.Name == "no" } +// IsAlways indicates whether the container has the "always" restart policy. +// This means the container will automatically restart regardless of the exit status. func (rp *RestartPolicy) IsAlways() bool { return rp.Name == "always" } +// IsOnFailure indicates whether the container has the "on-failure" restart policy. +// This means the contain will automatically restart of exiting with a non-zero exit status. func (rp *RestartPolicy) IsOnFailure() bool { return rp.Name == "on-failure" } +// LogConfig represents the logging configuration of the container. type LogConfig struct { Type string Config map[string]string } +// LxcConfig represents the specific LXC configuration of the container. type LxcConfig struct { values []KeyValuePair } +// MarshalJSON marshals (or serializes) the LxcConfig into JSON. func (c *LxcConfig) MarshalJSON() ([]byte, error) { if c == nil { return []byte{}, nil @@ -135,6 +159,8 @@ func (c *LxcConfig) MarshalJSON() ([]byte, error) { return json.Marshal(c.Slice()) } +// UnmarshalJSON unmarshals (or deserializes) the specified byte slices from JSON to +// a LxcConfig. func (c *LxcConfig) UnmarshalJSON(b []byte) error { if len(b) == 0 { return nil @@ -155,6 +181,7 @@ func (c *LxcConfig) UnmarshalJSON(b []byte) error { return nil } +// Len returns the number of specific lxc configuration. func (c *LxcConfig) Len() int { if c == nil { return 0 @@ -162,6 +189,7 @@ func (c *LxcConfig) Len() int { return len(c.values) } +// Slice returns the specific lxc configuration into a slice of KeyValuePair. func (c *LxcConfig) Slice() []KeyValuePair { if c == nil { return nil @@ -169,14 +197,17 @@ func (c *LxcConfig) Slice() []KeyValuePair { return c.values } +// NewLxcConfig creates a LxcConfig from the specified slice of KeyValuePair. func NewLxcConfig(values []KeyValuePair) *LxcConfig { return &LxcConfig{values} } +// CapList represents the list of capabilities of the container. type CapList struct { caps []string } +// MarshalJSON marshals (or serializes) the CapList into JSON. func (c *CapList) MarshalJSON() ([]byte, error) { if c == nil { return []byte{}, nil @@ -184,6 +215,8 @@ func (c *CapList) MarshalJSON() ([]byte, error) { return json.Marshal(c.Slice()) } +// UnmarshalJSON unmarshals (or deserializes) the specified byte slices +// from JSON to a CapList. func (c *CapList) UnmarshalJSON(b []byte) error { if len(b) == 0 { return nil @@ -202,6 +235,7 @@ func (c *CapList) UnmarshalJSON(b []byte) error { return nil } +// Len returns the number of specific kernel capabilities. func (c *CapList) Len() int { if c == nil { return 0 @@ -209,6 +243,7 @@ func (c *CapList) Len() int { return len(c.caps) } +// Slice returns the specific capabilities into a slice of KeyValuePair. func (c *CapList) Slice() []string { if c == nil { return nil @@ -216,49 +251,55 @@ func (c *CapList) Slice() []string { return c.caps } +// NewCapList creates a CapList from a slice of string. func NewCapList(caps []string) *CapList { return &CapList{caps} } +// HostConfig the non-portable Config structure of a container. +// Here, "non-portable" means "dependent of the host we are running on". +// Portable information *should* appear in Config. type HostConfig struct { - Binds []string - ContainerIDFile string - LxcConf *LxcConfig - Memory int64 // Memory limit (in bytes) - MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap - CpuShares int64 // CPU shares (relative weight vs. other containers) - CpuPeriod int64 - CpusetCpus string // CpusetCpus 0-2, 0,1 - CpusetMems string // CpusetMems 0-2, 0,1 - CpuQuota int64 - BlkioWeight int64 // Block IO weight (relative weight vs. other containers) - OomKillDisable bool // Whether to disable OOM Killer or not - MemorySwappiness int64 // Tuning container memory swappiness behaviour - Privileged bool - PortBindings nat.PortMap - Links []string - PublishAllPorts bool - Dns []string - DnsSearch []string - ExtraHosts []string - VolumesFrom []string - Devices []DeviceMapping - NetworkMode NetworkMode - IpcMode IpcMode - PidMode PidMode - UTSMode UTSMode - CapAdd *CapList - CapDrop *CapList - GroupAdd []string - RestartPolicy RestartPolicy - SecurityOpt []string - ReadonlyRootfs bool - Ulimits []*ulimit.Ulimit - LogConfig LogConfig - CgroupParent string // Parent cgroup. - ConsoleSize [2]int // Initial console size on Windows + Binds []string // List of volume bindings for this container + ContainerIDFile string // File (path) where the containerId is written + LxcConf *LxcConfig // Additional lxc configuration + Memory int64 // Memory limit (in bytes) + MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap + CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers) + CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period + CpusetCpus string // CpusetCpus 0-2, 0,1 + CpusetMems string // CpusetMems 0-2, 0,1 + CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota + BlkioWeight int64 // Block IO weight (relative weight vs. other containers) + OomKillDisable bool // Whether to disable OOM Killer or not + MemorySwappiness int64 // Tuning container memory swappiness behaviour + Privileged bool // Is the container in privileged mode + PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host + Links []string // List of links (in the name:alias form) + PublishAllPorts bool // Should docker publish all exposed port for the container + DNS []string `json:"Dns"` // List of DNS server to lookup + DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for + ExtraHosts []string // List of extra hosts + VolumesFrom []string // List of volumes to take from other container + Devices []DeviceMapping // List of devices to map inside the container + NetworkMode NetworkMode // Network namespace to use for the container + IpcMode IpcMode // IPC namespace to use for the container + PidMode PidMode // PID namespace to use for the container + UTSMode UTSMode // UTS namespace to use for the container + CapAdd *CapList // List of kernel capabilities to add to the container + CapDrop *CapList // List of kernel capabilities to remove from the container + GroupAdd []string // List of additional groups that the container process will run as + RestartPolicy RestartPolicy // Restart policy to be used for the container + SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux. + ReadonlyRootfs bool // Is the container root filesystem in read-only + Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container + LogConfig LogConfig // Configuration of the logs for this container + CgroupParent string // Parent cgroup. + ConsoleSize [2]int // Initial console size on Windows } +// MergeConfigs merges the specified container Config and HostConfig. +// It creates a ContainerConfigWrapper. func MergeConfigs(config *Config, hostConfig *HostConfig) *ContainerConfigWrapper { return &ContainerConfigWrapper{ config, @@ -267,6 +308,8 @@ func MergeConfigs(config *Config, hostConfig *HostConfig) *ContainerConfigWrappe } } +// DecodeHostConfig creates a HostConfig based on the specified Reader. +// It assumes the content of the reader will be JSON, and decodes it. func DecodeHostConfig(src io.Reader) (*HostConfig, error) { decoder := json.NewDecoder(src) diff --git a/runconfig/hostconfig_unix.go b/runconfig/hostconfig_unix.go index af470a8b3d..5239cb7d90 100644 --- a/runconfig/hostconfig_unix.go +++ b/runconfig/hostconfig_unix.go @@ -6,19 +6,23 @@ import ( "strings" ) -// IsPrivate indicates whether container use it's private network stack +// IsPrivate indicates whether container uses it's private network stack. func (n NetworkMode) IsPrivate() bool { return !(n.IsHost() || n.IsContainer()) } +// IsDefault indicates whether container uses the default network stack. func (n NetworkMode) IsDefault() bool { return n == "default" } +// DefaultDaemonNetworkMode returns the default network stack the daemon should +// use. func DefaultDaemonNetworkMode() NetworkMode { return NetworkMode("bridge") } +// NetworkName returns the name of the network stack. func (n NetworkMode) NetworkName() string { if n.IsBridge() { return "bridge" @@ -34,19 +38,23 @@ func (n NetworkMode) NetworkName() string { return "" } +// IsBridge indicates whether container uses the bridge network stack func (n NetworkMode) IsBridge() bool { return n == "bridge" } +// IsHost indicates whether container uses the host network stack. func (n NetworkMode) IsHost() bool { return n == "host" } +// IsContainer indicates whether container uses a container network stack. func (n NetworkMode) IsContainer() bool { parts := strings.SplitN(string(n), ":", 2) return len(parts) > 1 && parts[0] == "container" } +// IsNone indicates whether container isn't using a network stack. func (n NetworkMode) IsNone() bool { return n == "none" } diff --git a/runconfig/hostconfig_windows.go b/runconfig/hostconfig_windows.go index 6f96d3f42f..a4c0297bb3 100644 --- a/runconfig/hostconfig_windows.go +++ b/runconfig/hostconfig_windows.go @@ -1,13 +1,17 @@ package runconfig +// IsDefault indicates whether container uses the default network stack. func (n NetworkMode) IsDefault() bool { return n == "default" } +// DefaultDaemonNetworkMode returns the default network stack the daemon should +// use. func DefaultDaemonNetworkMode() NetworkMode { return NetworkMode("default") } +// NetworkName returns the name of the network stack. func (n NetworkMode) NetworkName() string { if n.IsDefault() { return "default" diff --git a/runconfig/merge.go b/runconfig/merge.go index df53ef964b..9a020a8894 100644 --- a/runconfig/merge.go +++ b/runconfig/merge.go @@ -6,6 +6,11 @@ import ( "github.com/docker/docker/pkg/nat" ) +// Merge merges two Config, the image container configuration (defaults values), +// and the user container configuration, either passed by the API or generated +// by the cli. +// It will mutate the specified user configuration (userConf) with the image +// configuration where the user configuration is incomplete. func Merge(userConf, imageConf *Config) error { if userConf.User == "" { userConf.User = imageConf.User diff --git a/runconfig/parse.go b/runconfig/parse.go index c83d5bea17..c1b5ea2daa 100644 --- a/runconfig/parse.go +++ b/runconfig/parse.go @@ -13,14 +13,22 @@ import ( ) var ( + // ErrConflictContainerNetworkAndLinks conflict between --net=container and links ErrConflictContainerNetworkAndLinks = fmt.Errorf("Conflicting options: --net=container can't be used with links. This would result in undefined behavior") - ErrConflictNetworkAndDns = fmt.Errorf("Conflicting options: --dns and the network mode (--net)") - ErrConflictNetworkHostname = fmt.Errorf("Conflicting options: -h and the network mode (--net)") - ErrConflictHostNetworkAndLinks = fmt.Errorf("Conflicting options: --net=host can't be used with links. This would result in undefined behavior") - ErrConflictContainerNetworkAndMac = fmt.Errorf("Conflicting options: --mac-address and the network mode (--net)") - ErrConflictNetworkHosts = fmt.Errorf("Conflicting options: --add-host and the network mode (--net)") - ErrConflictNetworkPublishPorts = fmt.Errorf("Conflicting options: -p, -P, --publish-all, --publish and the network mode (--net)") - ErrConflictNetworkExposePorts = fmt.Errorf("Conflicting options: --expose and the network mode (--expose)") + // ErrConflictNetworkAndDNS conflict between --dns and the network mode + ErrConflictNetworkAndDNS = fmt.Errorf("Conflicting options: --dns and the network mode (--net)") + // ErrConflictNetworkHostname conflict between the hostname and the network mode + ErrConflictNetworkHostname = fmt.Errorf("Conflicting options: -h and the network mode (--net)") + // ErrConflictHostNetworkAndLinks conflict between --net=host and links + ErrConflictHostNetworkAndLinks = fmt.Errorf("Conflicting options: --net=host can't be used with links. This would result in undefined behavior") + // ErrConflictContainerNetworkAndMac conflict between the mac address and the network mode + ErrConflictContainerNetworkAndMac = fmt.Errorf("Conflicting options: --mac-address and the network mode (--net)") + // ErrConflictNetworkHosts conflict between add-host and the network mode + ErrConflictNetworkHosts = fmt.Errorf("Conflicting options: --add-host and the network mode (--net)") + // ErrConflictNetworkPublishPorts conflict between the pulbish options and the network mode + ErrConflictNetworkPublishPorts = fmt.Errorf("Conflicting options: -p, -P, --publish-all, --publish and the network mode (--net)") + // ErrConflictNetworkExposePorts conflict between the expose option and the network mode + ErrConflictNetworkExposePorts = fmt.Errorf("Conflicting options: --expose and the network mode (--expose)") ) // validateNM is the set of fields passed to validateNetMode() @@ -28,7 +36,7 @@ type validateNM struct { netMode NetworkMode flHostname *string flLinks opts.ListOpts - flDns opts.ListOpts + flDNS opts.ListOpts flExtraHosts opts.ListOpts flMacAddress *string flPublish opts.ListOpts @@ -37,6 +45,9 @@ type validateNM struct { flVolumeDriver string } +// Parse parses the specified args for the specified command and generates a Config, +// a HostConfig and returns them with the specified command. +// If the specified args are not valid, it will return an error. func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) { var ( // FIXME: use utils.ListOpts for attach and volumes? @@ -51,8 +62,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe flPublish = opts.NewListOpts(nil) flExpose = opts.NewListOpts(nil) - flDns = opts.NewListOpts(opts.ValidateIPAddress) - flDnsSearch = opts.NewListOpts(opts.ValidateDNSSearch) + flDNS = opts.NewListOpts(opts.ValidateIPAddress) + flDNSSearch = opts.NewListOpts(opts.ValidateDNSSearch) flExtraHosts = opts.NewListOpts(opts.ValidateExtraHost) flVolumesFrom = opts.NewListOpts(nil) flLxcOpts = opts.NewListOpts(nil) @@ -79,9 +90,9 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe flMemorySwap = cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap") flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: [:])") flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container") - flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") - flCpuPeriod = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period") - flCpuQuota = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota") + flCPUShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") + flCPUPeriod = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period") + flCPUQuota = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit CPU CFS (Completely Fair Scheduler) quota") flCpusetCpus = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)") flCpusetMems = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)") flBlkioWeight = cmd.Int64([]string{"-blkio-weight"}, 0, "Block IO (relative weight), between 10 and 1000") @@ -106,8 +117,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe cmd.Var(&flEnvFile, []string{"-env-file"}, "Read in a file of environment variables") cmd.Var(&flPublish, []string{"p", "-publish"}, "Publish a container's port(s) to the host") cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port or a range of ports") - cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom DNS servers") - cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom DNS search domains") + cmd.Var(&flDNS, []string{"#dns", "-dns"}, "Set custom DNS servers") + cmd.Var(&flDNSSearch, []string{"-dns-search"}, "Set custom DNS search domains") cmd.Var(&flExtraHosts, []string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)") cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)") cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options") @@ -141,7 +152,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe netMode: netMode, flHostname: flHostname, flLinks: flLinks, - flDns: flDns, + flDNS: flDNS, flExtraHosts: flExtraHosts, flMacAddress: flMacAddress, flPublish: flPublish, @@ -272,7 +283,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe // parse device mappings deviceMappings := []DeviceMapping{} for _, device := range flDevices.GetAll() { - deviceMapping, err := ParseDevice(device) + deviceMapping, err := parseDevice(device) if err != nil { return nil, nil, cmd, err } @@ -344,11 +355,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe LxcConf: lxcConf, Memory: flMemory, MemorySwap: MemorySwap, - CpuShares: *flCpuShares, - CpuPeriod: *flCpuPeriod, + CPUShares: *flCPUShares, + CPUPeriod: *flCPUPeriod, CpusetCpus: *flCpusetCpus, CpusetMems: *flCpusetMems, - CpuQuota: *flCpuQuota, + CPUQuota: *flCPUQuota, BlkioWeight: *flBlkioWeight, OomKillDisable: *flOomKillDisable, MemorySwappiness: swappiness, @@ -356,8 +367,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe PortBindings: portBindings, Links: flLinks.GetAll(), PublishAllPorts: *flPublishAll, - Dns: flDns.GetAll(), - DnsSearch: flDnsSearch.GetAll(), + DNS: flDNS.GetAll(), + DNSSearch: flDNSSearch.GetAll(), ExtraHosts: flExtraHosts.GetAll(), VolumesFrom: flVolumesFrom.GetAll(), NetworkMode: netMode, @@ -476,7 +487,7 @@ func parseKeyValueOpts(opts opts.ListOpts) ([]KeyValuePair, error) { return out, nil } -func ParseDevice(device string) (DeviceMapping, error) { +func parseDevice(device string) (DeviceMapping, error) { src := "" dst := "" permissions := "rwm" diff --git a/runconfig/parse_test.go b/runconfig/parse_test.go index 5e91876955..8916e7d4df 100644 --- a/runconfig/parse_test.go +++ b/runconfig/parse_test.go @@ -246,10 +246,10 @@ func TestConflictContainerNetworkAndLinks(t *testing.T) { } func TestConflictNetworkModeAndOptions(t *testing.T) { - if _, _, _, err := parseRun([]string{"--net=host", "--dns=8.8.8.8", "img", "cmd"}); err != ErrConflictNetworkAndDns { + if _, _, _, err := parseRun([]string{"--net=host", "--dns=8.8.8.8", "img", "cmd"}); err != ErrConflictNetworkAndDNS { t.Fatalf("Expected error ErrConflictNetworkAndDns, got %s", err) } - if _, _, _, err := parseRun([]string{"--net=container:other", "--dns=8.8.8.8", "img", "cmd"}); err != ErrConflictNetworkAndDns { + if _, _, _, err := parseRun([]string{"--net=container:other", "--dns=8.8.8.8", "img", "cmd"}); err != ErrConflictNetworkAndDNS { t.Fatalf("Expected error ErrConflictNetworkAndDns, got %s", err) } if _, _, _, err := parseRun([]string{"--net=host", "--add-host=name:8.8.8.8", "img", "cmd"}); err != ErrConflictNetworkHosts { diff --git a/runconfig/parse_unix.go b/runconfig/parse_unix.go index 067140c7b7..7086b1ad08 100644 --- a/runconfig/parse_unix.go +++ b/runconfig/parse_unix.go @@ -35,8 +35,8 @@ func validateNetMode(vals *validateNM) error { return ErrConflictContainerNetworkAndLinks } - if (vals.netMode.IsHost() || vals.netMode.IsContainer()) && vals.flDns.Len() > 0 { - return ErrConflictNetworkAndDns + if (vals.netMode.IsHost() || vals.netMode.IsContainer()) && vals.flDNS.Len() > 0 { + return ErrConflictNetworkAndDNS } if (vals.netMode.IsContainer() || vals.netMode.IsHost()) && vals.flExtraHosts.Len() > 0 {