Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
Vincent Demeester 2015-07-25 11:11:45 +02:00
Родитель 0852170e8c
Коммит 5170a2c096
17 изменённых файлов: 245 добавлений и 144 удалений

Просмотреть файл

@ -63,11 +63,11 @@ func (cli *DockerCli) CmdRun(args ...string) error {
os.Exit(1) os.Exit(1)
} }
if len(hostConfig.Dns) > 0 { if len(hostConfig.DNS) > 0 {
// check the DNS settings passed via --dns against // check the DNS settings passed via --dns against
// localhost regexp to warn if they are trying to // localhost regexp to warn if they are trying to
// set a DNS to a localhost address // set a DNS to a localhost address
for _, dnsIP := range hostConfig.Dns { for _, dnsIP := range hostConfig.DNS {
if dns.IsLocalhost(dnsIP) { if dns.IsLocalhost(dnsIP) {
fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP) fmt.Fprintf(cli.err, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP)
break break

Просмотреть файл

@ -109,14 +109,14 @@ func allocateDaemonPort(addr string) error {
func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) { func adjustCpuShares(version version.Version, hostConfig *runconfig.HostConfig) {
if version.LessThan("1.19") { if version.LessThan("1.19") {
if hostConfig != nil && hostConfig.CpuShares > 0 { if hostConfig != nil && hostConfig.CPUShares > 0 {
// Handle unsupported CpuShares // Handle unsupported CpuShares
if hostConfig.CpuShares < linuxMinCpuShares { if hostConfig.CPUShares < linuxMinCpuShares {
logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CpuShares, linuxMinCpuShares) logrus.Warnf("Changing requested CpuShares of %d to minimum allowed of %d", hostConfig.CPUShares, linuxMinCpuShares)
hostConfig.CpuShares = linuxMinCpuShares hostConfig.CPUShares = linuxMinCpuShares
} else if hostConfig.CpuShares > linuxMaxCpuShares { } else if hostConfig.CPUShares > linuxMaxCpuShares {
logrus.Warnf("Changing requested CpuShares of %d to maximum allowed of %d", hostConfig.CpuShares, linuxMaxCpuShares) logrus.Warnf("Changing requested CpuShares of %d to maximum allowed of %d", hostConfig.CPUShares, linuxMaxCpuShares)
hostConfig.CpuShares = linuxMaxCpuShares hostConfig.CPUShares = linuxMaxCpuShares
} }
} }
} }

Просмотреть файл

@ -12,28 +12,28 @@ import (
func TestAdjustCpuSharesOldApi(t *testing.T) { func TestAdjustCpuSharesOldApi(t *testing.T) {
apiVersion := version.Version("1.18") apiVersion := version.Version("1.18")
hostConfig := &runconfig.HostConfig{ hostConfig := &runconfig.HostConfig{
CpuShares: linuxMinCpuShares - 1, CPUShares: linuxMinCpuShares - 1,
} }
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != linuxMinCpuShares { if hostConfig.CPUShares != linuxMinCpuShares {
t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares) t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares)
} }
hostConfig.CpuShares = linuxMaxCpuShares + 1 hostConfig.CPUShares = linuxMaxCpuShares + 1
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != linuxMaxCpuShares { if hostConfig.CPUShares != linuxMaxCpuShares {
t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares) t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares)
} }
hostConfig.CpuShares = 0 hostConfig.CPUShares = 0
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != 0 { if hostConfig.CPUShares != 0 {
t.Error("Expected CpuShares to be unchanged") t.Error("Expected CpuShares to be unchanged")
} }
hostConfig.CpuShares = 1024 hostConfig.CPUShares = 1024
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != 1024 { if hostConfig.CPUShares != 1024 {
t.Error("Expected CpuShares to be unchanged") t.Error("Expected CpuShares to be unchanged")
} }
} }
@ -41,28 +41,28 @@ func TestAdjustCpuSharesOldApi(t *testing.T) {
func TestAdjustCpuSharesNoAdjustment(t *testing.T) { func TestAdjustCpuSharesNoAdjustment(t *testing.T) {
apiVersion := version.Version("1.19") apiVersion := version.Version("1.19")
hostConfig := &runconfig.HostConfig{ hostConfig := &runconfig.HostConfig{
CpuShares: linuxMinCpuShares - 1, CPUShares: linuxMinCpuShares - 1,
} }
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != linuxMinCpuShares-1 { if hostConfig.CPUShares != linuxMinCpuShares-1 {
t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares-1) t.Errorf("Expected CpuShares to be %d", linuxMinCpuShares-1)
} }
hostConfig.CpuShares = linuxMaxCpuShares + 1 hostConfig.CPUShares = linuxMaxCpuShares + 1
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != linuxMaxCpuShares+1 { if hostConfig.CPUShares != linuxMaxCpuShares+1 {
t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares+1) t.Errorf("Expected CpuShares to be %d", linuxMaxCpuShares+1)
} }
hostConfig.CpuShares = 0 hostConfig.CPUShares = 0
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != 0 { if hostConfig.CPUShares != 0 {
t.Error("Expected CpuShares to be unchanged") t.Error("Expected CpuShares to be unchanged")
} }
hostConfig.CpuShares = 1024 hostConfig.CPUShares = 1024
adjustCpuShares(apiVersion, hostConfig) adjustCpuShares(apiVersion, hostConfig)
if hostConfig.CpuShares != 1024 { if hostConfig.CPUShares != 1024 {
t.Error("Expected CpuShares to be unchanged") t.Error("Expected CpuShares to be unchanged")
} }
} }

Просмотреть файл

@ -607,9 +607,9 @@ func (b *builder) create() (*daemon.Container, error) {
b.Config.Image = b.image b.Config.Image = b.image
hostConfig := &runconfig.HostConfig{ hostConfig := &runconfig.HostConfig{
CpuShares: b.cpuShares, CPUShares: b.cpuShares,
CpuPeriod: b.cpuPeriod, CPUPeriod: b.cpuPeriod,
CpuQuota: b.cpuQuota, CPUQuota: b.cpuQuota,
CpusetCpus: b.cpuSetCpus, CpusetCpus: b.cpuSetCpus,
CpusetMems: b.cpuSetMems, CpusetMems: b.cpuSetMems,
CgroupParent: b.cgroupParent, CgroupParent: b.cgroupParent,

Просмотреть файл

@ -264,11 +264,11 @@ func populateCommand(c *Container, env []string) error {
resources := &execdriver.Resources{ resources := &execdriver.Resources{
Memory: c.hostConfig.Memory, Memory: c.hostConfig.Memory,
MemorySwap: c.hostConfig.MemorySwap, MemorySwap: c.hostConfig.MemorySwap,
CpuShares: c.hostConfig.CpuShares, CpuShares: c.hostConfig.CPUShares,
CpusetCpus: c.hostConfig.CpusetCpus, CpusetCpus: c.hostConfig.CpusetCpus,
CpusetMems: c.hostConfig.CpusetMems, CpusetMems: c.hostConfig.CpusetMems,
CpuPeriod: c.hostConfig.CpuPeriod, CpuPeriod: c.hostConfig.CPUPeriod,
CpuQuota: c.hostConfig.CpuQuota, CpuQuota: c.hostConfig.CPUQuota,
BlkioWeight: c.hostConfig.BlkioWeight, BlkioWeight: c.hostConfig.BlkioWeight,
Rlimits: rlimits, Rlimits: rlimits,
OomKillDisable: c.hostConfig.OomKillDisable, OomKillDisable: c.hostConfig.OomKillDisable,
@ -423,8 +423,8 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
} }
joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath)) joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath))
if len(container.hostConfig.Dns) > 0 { if len(container.hostConfig.DNS) > 0 {
dns = container.hostConfig.Dns dns = container.hostConfig.DNS
} else if len(container.daemon.config.Dns) > 0 { } else if len(container.daemon.config.Dns) > 0 {
dns = container.daemon.config.Dns dns = container.daemon.config.Dns
} }
@ -433,8 +433,8 @@ func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, err
joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d)) joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d))
} }
if len(container.hostConfig.DnsSearch) > 0 { if len(container.hostConfig.DNSSearch) > 0 {
dnsSearch = container.hostConfig.DnsSearch dnsSearch = container.hostConfig.DNSSearch
} else if len(container.daemon.config.DnsSearch) > 0 { } else if len(container.daemon.config.DnsSearch) > 0 {
dnsSearch = container.daemon.config.DnsSearch dnsSearch = container.daemon.config.DnsSearch
} }
@ -543,7 +543,7 @@ func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork
for _, tp := range exposedPorts { for _, tp := range exposedPorts {
natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port))) natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
if err != nil { 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 networkSettings.Ports[natPort] = nil
} }

Просмотреть файл

@ -185,15 +185,15 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig,
if hostConfig.MemorySwappiness != -1 && (hostConfig.MemorySwappiness < 0 || hostConfig.MemorySwappiness > 100) { 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) 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.") 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.") 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.") 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.") 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) { if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")

Просмотреть файл

@ -61,7 +61,7 @@ func (daemon *Daemon) ContainerInspectPre120(name string) (*types.ContainerJSONP
container.Config, container.Config,
container.hostConfig.Memory, container.hostConfig.Memory,
container.hostConfig.MemorySwap, container.hostConfig.MemorySwap,
container.hostConfig.CpuShares, container.hostConfig.CPUShares,
container.hostConfig.CpusetCpus, container.hostConfig.CpusetCpus,
} }

Просмотреть файл

@ -38,6 +38,7 @@ packages=(
pkg/urlutil pkg/urlutil
pkg/version pkg/version
registry registry
runconfig
utils utils
) )

Просмотреть файл

@ -17,6 +17,8 @@ type Entrypoint struct {
parts []string 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) { func (e *Entrypoint) MarshalJSON() ([]byte, error) {
if e == nil { if e == nil {
return []byte{}, nil return []byte{}, nil
@ -24,7 +26,8 @@ func (e *Entrypoint) MarshalJSON() ([]byte, error) {
return json.Marshal(e.Slice()) 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 { func (e *Entrypoint) UnmarshalJSON(b []byte) error {
if len(b) == 0 { if len(b) == 0 {
return nil return nil
@ -42,6 +45,7 @@ func (e *Entrypoint) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// Len returns the number of parts of the Entrypoint.
func (e *Entrypoint) Len() int { func (e *Entrypoint) Len() int {
if e == nil { if e == nil {
return 0 return 0
@ -49,6 +53,7 @@ func (e *Entrypoint) Len() int {
return len(e.parts) return len(e.parts)
} }
// Slice gets the parts of the Entrypoint as a Slice of string.
func (e *Entrypoint) Slice() []string { func (e *Entrypoint) Slice() []string {
if e == nil { if e == nil {
return nil return nil
@ -56,18 +61,27 @@ func (e *Entrypoint) Slice() []string {
return e.parts return e.parts
} }
// NewEntrypoint creates an Entrypoint based on the specified parts (as strings).
func NewEntrypoint(parts ...string) *Entrypoint { func NewEntrypoint(parts ...string) *Entrypoint {
return &Entrypoint{parts} 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 { type Command struct {
parts []string parts []string
} }
// ToString gets a string representing a Command.
func (e *Command) ToString() string { func (e *Command) ToString() string {
return strings.Join(e.parts, " ") 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) { func (e *Command) MarshalJSON() ([]byte, error) {
if e == nil { if e == nil {
return []byte{}, nil return []byte{}, nil
@ -75,7 +89,8 @@ func (e *Command) MarshalJSON() ([]byte, error) {
return json.Marshal(e.Slice()) 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 { func (e *Command) UnmarshalJSON(b []byte) error {
if len(b) == 0 { if len(b) == 0 {
return nil return nil
@ -93,6 +108,7 @@ func (e *Command) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// Len returns the number of parts of the Entrypoint.
func (e *Command) Len() int { func (e *Command) Len() int {
if e == nil { if e == nil {
return 0 return 0
@ -100,6 +116,7 @@ func (e *Command) Len() int {
return len(e.parts) return len(e.parts)
} }
// Slice gets the parts of the Entrypoint as a Slice of string.
func (e *Command) Slice() []string { func (e *Command) Slice() []string {
if e == nil { if e == nil {
return nil return nil
@ -107,38 +124,42 @@ func (e *Command) Slice() []string {
return e.parts return e.parts
} }
// NewCommand creates a Command based on the specified parts (as strings).
func NewCommand(parts ...string) *Command { func NewCommand(parts ...string) *Command {
return &Command{parts} 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". // Here, "portable" means "independent from the host we are running on".
// Non-portable information *should* appear in HostConfig. // Non-portable information *should* appear in HostConfig.
type Config struct { type Config struct {
Hostname string Hostname string // Hostname
Domainname string Domainname string // Domainname
User string User string // User that will run the command(s) inside the container
AttachStdin bool AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStdout bool AttachStdout bool // Attach the standard output
AttachStderr bool AttachStderr bool // Attach the standard error
ExposedPorts map[nat.Port]struct{} ExposedPorts map[nat.Port]struct{} // List of exposed ports
PublishService string 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. Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
OpenStdin bool // Open stdin OpenStdin bool // Open stdin
StdinOnce bool // If true, close stdin after the 1 attached client disconnects. StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
Env []string Env []string // List of environment variable to set in the container
Cmd *Command 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) Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
Volumes map[string]struct{} Volumes map[string]struct{} // List of volumes (mounts) used for the container
VolumeDriver string VolumeDriver string // Name of the volume driver used to mount volumes
WorkingDir string WorkingDir string // Current directory (PWD) in the command will be launched
Entrypoint *Entrypoint Entrypoint *Entrypoint // Entrypoint to run when starting the container
NetworkDisabled bool NetworkDisabled bool // Is network disabled
MacAddress string MacAddress string // Mac Address of the container
OnBuild []string OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
Labels map[string]string 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 { type ContainerConfigWrapper struct {
*Config *Config
InnerHostConfig *HostConfig `json:"HostConfig,omitempty"` 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 { func (w *ContainerConfigWrapper) GetHostConfig() *HostConfig {
hc := w.HostConfig hc := w.HostConfig
@ -159,8 +182,8 @@ func (w *ContainerConfigWrapper) GetHostConfig() *HostConfig {
if hc.MemorySwap != 0 && w.InnerHostConfig.MemorySwap == 0 { if hc.MemorySwap != 0 && w.InnerHostConfig.MemorySwap == 0 {
w.InnerHostConfig.MemorySwap = hc.MemorySwap w.InnerHostConfig.MemorySwap = hc.MemorySwap
} }
if hc.CpuShares != 0 && w.InnerHostConfig.CpuShares == 0 { if hc.CPUShares != 0 && w.InnerHostConfig.CPUShares == 0 {
w.InnerHostConfig.CpuShares = hc.CpuShares w.InnerHostConfig.CPUShares = hc.CPUShares
} }
hc = w.InnerHostConfig hc = w.InnerHostConfig

Просмотреть файл

@ -4,18 +4,24 @@ import (
flag "github.com/docker/docker/pkg/mflag" 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 { type ExecConfig struct {
User string User string // User that will run the command
Privileged bool Privileged bool // Is the container in privileged mode
Tty bool Tty bool // Attach standard streams to a tty.
Container string Container string // Name of the container (to execute in)
AttachStdin bool AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStderr bool AttachStderr bool // Attach the standard output
AttachStdout bool AttachStdout bool // Attach the standard error
Detach bool Detach bool // Execute in detach mode
Cmd []string 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) { func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
var ( var (
flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached") flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")

Просмотреть файл

@ -9,29 +9,35 @@ import (
"github.com/docker/docker/pkg/ulimit" "github.com/docker/docker/pkg/ulimit"
) )
// KeyValuePair is a structure that hold a value for a key.
type KeyValuePair struct { type KeyValuePair struct {
Key string Key string
Value string Value string
} }
// NetworkMode represents the container network stack.
type NetworkMode string type NetworkMode string
// IpcMode represents the container ipc stack.
type IpcMode string 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 { func (n IpcMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer()) return !(n.IsHost() || n.IsContainer())
} }
// IsHost indicates whether the container uses the host's ipc stack.
func (n IpcMode) IsHost() bool { func (n IpcMode) IsHost() bool {
return n == "host" return n == "host"
} }
// IsContainer indicates whether the container uses a container's ipc stack.
func (n IpcMode) IsContainer() bool { func (n IpcMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container" return len(parts) > 1 && parts[0] == "container"
} }
// Valid indicates whether the ipc stack is valid.
func (n IpcMode) Valid() bool { func (n IpcMode) Valid() bool {
parts := strings.Split(string(n), ":") parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode { switch mode := parts[0]; mode {
@ -46,6 +52,7 @@ func (n IpcMode) Valid() bool {
return true return true
} }
// Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string { func (n IpcMode) Container() string {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
if len(parts) > 1 { if len(parts) > 1 {
@ -54,17 +61,20 @@ func (n IpcMode) Container() string {
return "" return ""
} }
// UTSMode represents the UTS namespace of the container.
type UTSMode string 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 { func (n UTSMode) IsPrivate() bool {
return !(n.IsHost()) return !(n.IsHost())
} }
// IsHost indicates whether the container uses the host's UTS namespace.
func (n UTSMode) IsHost() bool { func (n UTSMode) IsHost() bool {
return n == "host" return n == "host"
} }
// Valid indicates whether the UTS namespace is valid.
func (n UTSMode) Valid() bool { func (n UTSMode) Valid() bool {
parts := strings.Split(string(n), ":") parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode { switch mode := parts[0]; mode {
@ -75,17 +85,20 @@ func (n UTSMode) Valid() bool {
return true return true
} }
// PidMode represents the pid stack of the container.
type PidMode string 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 { func (n PidMode) IsPrivate() bool {
return !(n.IsHost()) return !(n.IsHost())
} }
// IsHost indicates whether the container uses the host's pid stack.
func (n PidMode) IsHost() bool { func (n PidMode) IsHost() bool {
return n == "host" return n == "host"
} }
// Valid indicates whether the pid stack is valid.
func (n PidMode) Valid() bool { func (n PidMode) Valid() bool {
parts := strings.Split(string(n), ":") parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode { switch mode := parts[0]; mode {
@ -96,38 +109,49 @@ func (n PidMode) Valid() bool {
return true return true
} }
// DeviceMapping represents the device mapping between the host and the container.
type DeviceMapping struct { type DeviceMapping struct {
PathOnHost string PathOnHost string
PathInContainer string PathInContainer string
CgroupPermissions string CgroupPermissions string
} }
// RestartPolicy represents the restart policies of the container.
type RestartPolicy struct { type RestartPolicy struct {
Name string Name string
MaximumRetryCount int 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 { func (rp *RestartPolicy) IsNone() bool {
return rp.Name == "no" 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 { func (rp *RestartPolicy) IsAlways() bool {
return rp.Name == "always" 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 { func (rp *RestartPolicy) IsOnFailure() bool {
return rp.Name == "on-failure" return rp.Name == "on-failure"
} }
// LogConfig represents the logging configuration of the container.
type LogConfig struct { type LogConfig struct {
Type string Type string
Config map[string]string Config map[string]string
} }
// LxcConfig represents the specific LXC configuration of the container.
type LxcConfig struct { type LxcConfig struct {
values []KeyValuePair values []KeyValuePair
} }
// MarshalJSON marshals (or serializes) the LxcConfig into JSON.
func (c *LxcConfig) MarshalJSON() ([]byte, error) { func (c *LxcConfig) MarshalJSON() ([]byte, error) {
if c == nil { if c == nil {
return []byte{}, nil return []byte{}, nil
@ -135,6 +159,8 @@ func (c *LxcConfig) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Slice()) 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 { func (c *LxcConfig) UnmarshalJSON(b []byte) error {
if len(b) == 0 { if len(b) == 0 {
return nil return nil
@ -155,6 +181,7 @@ func (c *LxcConfig) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// Len returns the number of specific lxc configuration.
func (c *LxcConfig) Len() int { func (c *LxcConfig) Len() int {
if c == nil { if c == nil {
return 0 return 0
@ -162,6 +189,7 @@ func (c *LxcConfig) Len() int {
return len(c.values) return len(c.values)
} }
// Slice returns the specific lxc configuration into a slice of KeyValuePair.
func (c *LxcConfig) Slice() []KeyValuePair { func (c *LxcConfig) Slice() []KeyValuePair {
if c == nil { if c == nil {
return nil return nil
@ -169,14 +197,17 @@ func (c *LxcConfig) Slice() []KeyValuePair {
return c.values return c.values
} }
// NewLxcConfig creates a LxcConfig from the specified slice of KeyValuePair.
func NewLxcConfig(values []KeyValuePair) *LxcConfig { func NewLxcConfig(values []KeyValuePair) *LxcConfig {
return &LxcConfig{values} return &LxcConfig{values}
} }
// CapList represents the list of capabilities of the container.
type CapList struct { type CapList struct {
caps []string caps []string
} }
// MarshalJSON marshals (or serializes) the CapList into JSON.
func (c *CapList) MarshalJSON() ([]byte, error) { func (c *CapList) MarshalJSON() ([]byte, error) {
if c == nil { if c == nil {
return []byte{}, nil return []byte{}, nil
@ -184,6 +215,8 @@ func (c *CapList) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Slice()) 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 { func (c *CapList) UnmarshalJSON(b []byte) error {
if len(b) == 0 { if len(b) == 0 {
return nil return nil
@ -202,6 +235,7 @@ func (c *CapList) UnmarshalJSON(b []byte) error {
return nil return nil
} }
// Len returns the number of specific kernel capabilities.
func (c *CapList) Len() int { func (c *CapList) Len() int {
if c == nil { if c == nil {
return 0 return 0
@ -209,6 +243,7 @@ func (c *CapList) Len() int {
return len(c.caps) return len(c.caps)
} }
// Slice returns the specific capabilities into a slice of KeyValuePair.
func (c *CapList) Slice() []string { func (c *CapList) Slice() []string {
if c == nil { if c == nil {
return nil return nil
@ -216,49 +251,55 @@ func (c *CapList) Slice() []string {
return c.caps return c.caps
} }
// NewCapList creates a CapList from a slice of string.
func NewCapList(caps []string) *CapList { func NewCapList(caps []string) *CapList {
return &CapList{caps} 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 { type HostConfig struct {
Binds []string Binds []string // List of volume bindings for this container
ContainerIDFile string ContainerIDFile string // File (path) where the containerId is written
LxcConf *LxcConfig LxcConf *LxcConfig // Additional lxc configuration
Memory int64 // Memory limit (in bytes) Memory int64 // Memory limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap
CpuShares int64 // CPU shares (relative weight vs. other containers) CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
CpuPeriod int64 CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
CpusetCpus string // CpusetCpus 0-2, 0,1 CpusetCpus string // CpusetCpus 0-2, 0,1
CpusetMems string // CpusetMems 0-2, 0,1 CpusetMems string // CpusetMems 0-2, 0,1
CpuQuota int64 CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota
BlkioWeight int64 // Block IO weight (relative weight vs. other containers) BlkioWeight int64 // Block IO weight (relative weight vs. other containers)
OomKillDisable bool // Whether to disable OOM Killer or not OomKillDisable bool // Whether to disable OOM Killer or not
MemorySwappiness int64 // Tuning container memory swappiness behaviour MemorySwappiness int64 // Tuning container memory swappiness behaviour
Privileged bool Privileged bool // Is the container in privileged mode
PortBindings nat.PortMap PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
Links []string Links []string // List of links (in the name:alias form)
PublishAllPorts bool PublishAllPorts bool // Should docker publish all exposed port for the container
Dns []string DNS []string `json:"Dns"` // List of DNS server to lookup
DnsSearch []string DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
ExtraHosts []string ExtraHosts []string // List of extra hosts
VolumesFrom []string VolumesFrom []string // List of volumes to take from other container
Devices []DeviceMapping Devices []DeviceMapping // List of devices to map inside the container
NetworkMode NetworkMode NetworkMode NetworkMode // Network namespace to use for the container
IpcMode IpcMode IpcMode IpcMode // IPC namespace to use for the container
PidMode PidMode PidMode PidMode // PID namespace to use for the container
UTSMode UTSMode UTSMode UTSMode // UTS namespace to use for the container
CapAdd *CapList CapAdd *CapList // List of kernel capabilities to add to the container
CapDrop *CapList CapDrop *CapList // List of kernel capabilities to remove from the container
GroupAdd []string GroupAdd []string // List of additional groups that the container process will run as
RestartPolicy RestartPolicy RestartPolicy RestartPolicy // Restart policy to be used for the container
SecurityOpt []string SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
ReadonlyRootfs bool ReadonlyRootfs bool // Is the container root filesystem in read-only
Ulimits []*ulimit.Ulimit Ulimits []*ulimit.Ulimit // List of ulimits to be set in the container
LogConfig LogConfig LogConfig LogConfig // Configuration of the logs for this container
CgroupParent string // Parent cgroup. CgroupParent string // Parent cgroup.
ConsoleSize [2]int // Initial console size on Windows 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 { func MergeConfigs(config *Config, hostConfig *HostConfig) *ContainerConfigWrapper {
return &ContainerConfigWrapper{ return &ContainerConfigWrapper{
config, 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) { func DecodeHostConfig(src io.Reader) (*HostConfig, error) {
decoder := json.NewDecoder(src) decoder := json.NewDecoder(src)

Просмотреть файл

@ -6,19 +6,23 @@ import (
"strings" "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 { func (n NetworkMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer()) return !(n.IsHost() || n.IsContainer())
} }
// IsDefault indicates whether container uses the default network stack.
func (n NetworkMode) IsDefault() bool { func (n NetworkMode) IsDefault() bool {
return n == "default" return n == "default"
} }
// DefaultDaemonNetworkMode returns the default network stack the daemon should
// use.
func DefaultDaemonNetworkMode() NetworkMode { func DefaultDaemonNetworkMode() NetworkMode {
return NetworkMode("bridge") return NetworkMode("bridge")
} }
// NetworkName returns the name of the network stack.
func (n NetworkMode) NetworkName() string { func (n NetworkMode) NetworkName() string {
if n.IsBridge() { if n.IsBridge() {
return "bridge" return "bridge"
@ -34,19 +38,23 @@ func (n NetworkMode) NetworkName() string {
return "" return ""
} }
// IsBridge indicates whether container uses the bridge network stack
func (n NetworkMode) IsBridge() bool { func (n NetworkMode) IsBridge() bool {
return n == "bridge" return n == "bridge"
} }
// IsHost indicates whether container uses the host network stack.
func (n NetworkMode) IsHost() bool { func (n NetworkMode) IsHost() bool {
return n == "host" return n == "host"
} }
// IsContainer indicates whether container uses a container network stack.
func (n NetworkMode) IsContainer() bool { func (n NetworkMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container" return len(parts) > 1 && parts[0] == "container"
} }
// IsNone indicates whether container isn't using a network stack.
func (n NetworkMode) IsNone() bool { func (n NetworkMode) IsNone() bool {
return n == "none" return n == "none"
} }

Просмотреть файл

@ -1,13 +1,17 @@
package runconfig package runconfig
// IsDefault indicates whether container uses the default network stack.
func (n NetworkMode) IsDefault() bool { func (n NetworkMode) IsDefault() bool {
return n == "default" return n == "default"
} }
// DefaultDaemonNetworkMode returns the default network stack the daemon should
// use.
func DefaultDaemonNetworkMode() NetworkMode { func DefaultDaemonNetworkMode() NetworkMode {
return NetworkMode("default") return NetworkMode("default")
} }
// NetworkName returns the name of the network stack.
func (n NetworkMode) NetworkName() string { func (n NetworkMode) NetworkName() string {
if n.IsDefault() { if n.IsDefault() {
return "default" return "default"

Просмотреть файл

@ -6,6 +6,11 @@ import (
"github.com/docker/docker/pkg/nat" "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 { func Merge(userConf, imageConf *Config) error {
if userConf.User == "" { if userConf.User == "" {
userConf.User = imageConf.User userConf.User = imageConf.User

Просмотреть файл

@ -13,14 +13,22 @@ import (
) )
var ( 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") 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)") // ErrConflictNetworkAndDNS conflict between --dns and the network mode
ErrConflictNetworkHostname = fmt.Errorf("Conflicting options: -h and the network mode (--net)") ErrConflictNetworkAndDNS = fmt.Errorf("Conflicting options: --dns and the network mode (--net)")
ErrConflictHostNetworkAndLinks = fmt.Errorf("Conflicting options: --net=host can't be used with links. This would result in undefined behavior") // ErrConflictNetworkHostname conflict between the hostname and the network mode
ErrConflictContainerNetworkAndMac = fmt.Errorf("Conflicting options: --mac-address and the network mode (--net)") ErrConflictNetworkHostname = fmt.Errorf("Conflicting options: -h and the network mode (--net)")
ErrConflictNetworkHosts = fmt.Errorf("Conflicting options: --add-host and the network mode (--net)") // ErrConflictHostNetworkAndLinks conflict between --net=host and links
ErrConflictNetworkPublishPorts = fmt.Errorf("Conflicting options: -p, -P, --publish-all, --publish and the network mode (--net)") ErrConflictHostNetworkAndLinks = fmt.Errorf("Conflicting options: --net=host can't be used with links. This would result in undefined behavior")
ErrConflictNetworkExposePorts = fmt.Errorf("Conflicting options: --expose and the network mode (--expose)") // 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() // validateNM is the set of fields passed to validateNetMode()
@ -28,7 +36,7 @@ type validateNM struct {
netMode NetworkMode netMode NetworkMode
flHostname *string flHostname *string
flLinks opts.ListOpts flLinks opts.ListOpts
flDns opts.ListOpts flDNS opts.ListOpts
flExtraHosts opts.ListOpts flExtraHosts opts.ListOpts
flMacAddress *string flMacAddress *string
flPublish opts.ListOpts flPublish opts.ListOpts
@ -37,6 +45,9 @@ type validateNM struct {
flVolumeDriver string 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) { func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
var ( var (
// FIXME: use utils.ListOpts for attach and volumes? // 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) flPublish = opts.NewListOpts(nil)
flExpose = opts.NewListOpts(nil) flExpose = opts.NewListOpts(nil)
flDns = opts.NewListOpts(opts.ValidateIPAddress) flDNS = opts.NewListOpts(opts.ValidateIPAddress)
flDnsSearch = opts.NewListOpts(opts.ValidateDNSSearch) flDNSSearch = opts.NewListOpts(opts.ValidateDNSSearch)
flExtraHosts = opts.NewListOpts(opts.ValidateExtraHost) flExtraHosts = opts.NewListOpts(opts.ValidateExtraHost)
flVolumesFrom = opts.NewListOpts(nil) flVolumesFrom = opts.NewListOpts(nil)
flLxcOpts = 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") flMemorySwap = cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])") flUser = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container") flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)") 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") 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") 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)") 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)") 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") 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(&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(&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(&flExpose, []string{"#expose", "-expose"}, "Expose a port or a range of ports")
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom DNS servers") cmd.Var(&flDNS, []string{"#dns", "-dns"}, "Set custom DNS servers")
cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom DNS search domains") 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(&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(&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") 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, netMode: netMode,
flHostname: flHostname, flHostname: flHostname,
flLinks: flLinks, flLinks: flLinks,
flDns: flDns, flDNS: flDNS,
flExtraHosts: flExtraHosts, flExtraHosts: flExtraHosts,
flMacAddress: flMacAddress, flMacAddress: flMacAddress,
flPublish: flPublish, flPublish: flPublish,
@ -272,7 +283,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
// parse device mappings // parse device mappings
deviceMappings := []DeviceMapping{} deviceMappings := []DeviceMapping{}
for _, device := range flDevices.GetAll() { for _, device := range flDevices.GetAll() {
deviceMapping, err := ParseDevice(device) deviceMapping, err := parseDevice(device)
if err != nil { if err != nil {
return nil, nil, cmd, err return nil, nil, cmd, err
} }
@ -344,11 +355,11 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
LxcConf: lxcConf, LxcConf: lxcConf,
Memory: flMemory, Memory: flMemory,
MemorySwap: MemorySwap, MemorySwap: MemorySwap,
CpuShares: *flCpuShares, CPUShares: *flCPUShares,
CpuPeriod: *flCpuPeriod, CPUPeriod: *flCPUPeriod,
CpusetCpus: *flCpusetCpus, CpusetCpus: *flCpusetCpus,
CpusetMems: *flCpusetMems, CpusetMems: *flCpusetMems,
CpuQuota: *flCpuQuota, CPUQuota: *flCPUQuota,
BlkioWeight: *flBlkioWeight, BlkioWeight: *flBlkioWeight,
OomKillDisable: *flOomKillDisable, OomKillDisable: *flOomKillDisable,
MemorySwappiness: swappiness, MemorySwappiness: swappiness,
@ -356,8 +367,8 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
PortBindings: portBindings, PortBindings: portBindings,
Links: flLinks.GetAll(), Links: flLinks.GetAll(),
PublishAllPorts: *flPublishAll, PublishAllPorts: *flPublishAll,
Dns: flDns.GetAll(), DNS: flDNS.GetAll(),
DnsSearch: flDnsSearch.GetAll(), DNSSearch: flDNSSearch.GetAll(),
ExtraHosts: flExtraHosts.GetAll(), ExtraHosts: flExtraHosts.GetAll(),
VolumesFrom: flVolumesFrom.GetAll(), VolumesFrom: flVolumesFrom.GetAll(),
NetworkMode: netMode, NetworkMode: netMode,
@ -476,7 +487,7 @@ func parseKeyValueOpts(opts opts.ListOpts) ([]KeyValuePair, error) {
return out, nil return out, nil
} }
func ParseDevice(device string) (DeviceMapping, error) { func parseDevice(device string) (DeviceMapping, error) {
src := "" src := ""
dst := "" dst := ""
permissions := "rwm" permissions := "rwm"

Просмотреть файл

@ -246,10 +246,10 @@ func TestConflictContainerNetworkAndLinks(t *testing.T) {
} }
func TestConflictNetworkModeAndOptions(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) 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) 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 { if _, _, _, err := parseRun([]string{"--net=host", "--add-host=name:8.8.8.8", "img", "cmd"}); err != ErrConflictNetworkHosts {

Просмотреть файл

@ -35,8 +35,8 @@ func validateNetMode(vals *validateNM) error {
return ErrConflictContainerNetworkAndLinks return ErrConflictContainerNetworkAndLinks
} }
if (vals.netMode.IsHost() || vals.netMode.IsContainer()) && vals.flDns.Len() > 0 { if (vals.netMode.IsHost() || vals.netMode.IsContainer()) && vals.flDNS.Len() > 0 {
return ErrConflictNetworkAndDns return ErrConflictNetworkAndDNS
} }
if (vals.netMode.IsContainer() || vals.netMode.IsHost()) && vals.flExtraHosts.Len() > 0 { if (vals.netMode.IsContainer() || vals.netMode.IsHost()) && vals.flExtraHosts.Len() > 0 {