github.com/wulonghui/docker@v1.8.0-rc2/runconfig/config.go (about) 1 package runconfig 2 3 import ( 4 "encoding/json" 5 "io" 6 "strings" 7 8 "github.com/docker/docker/pkg/nat" 9 ) 10 11 // Entrypoint encapsulates the container entrypoint. 12 // It might be represented as a string or an array of strings. 13 // We need to override the json decoder to accept both options. 14 // The JSON decoder will fail if the api sends an string and 15 // we try to decode it into an array of string. 16 type Entrypoint struct { 17 parts []string 18 } 19 20 func (e *Entrypoint) MarshalJSON() ([]byte, error) { 21 if e == nil { 22 return []byte{}, nil 23 } 24 return json.Marshal(e.Slice()) 25 } 26 27 // UnmarshalJSON decoded the entrypoint whether it's a string or an array of strings. 28 func (e *Entrypoint) UnmarshalJSON(b []byte) error { 29 if len(b) == 0 { 30 return nil 31 } 32 33 p := make([]string, 0, 1) 34 if err := json.Unmarshal(b, &p); err != nil { 35 var s string 36 if err := json.Unmarshal(b, &s); err != nil { 37 return err 38 } 39 p = append(p, s) 40 } 41 e.parts = p 42 return nil 43 } 44 45 func (e *Entrypoint) Len() int { 46 if e == nil { 47 return 0 48 } 49 return len(e.parts) 50 } 51 52 func (e *Entrypoint) Slice() []string { 53 if e == nil { 54 return nil 55 } 56 return e.parts 57 } 58 59 func NewEntrypoint(parts ...string) *Entrypoint { 60 return &Entrypoint{parts} 61 } 62 63 type Command struct { 64 parts []string 65 } 66 67 func (e *Command) ToString() string { 68 return strings.Join(e.parts, " ") 69 } 70 71 func (e *Command) MarshalJSON() ([]byte, error) { 72 if e == nil { 73 return []byte{}, nil 74 } 75 return json.Marshal(e.Slice()) 76 } 77 78 // UnmarshalJSON decoded the entrypoint whether it's a string or an array of strings. 79 func (e *Command) UnmarshalJSON(b []byte) error { 80 if len(b) == 0 { 81 return nil 82 } 83 84 p := make([]string, 0, 1) 85 if err := json.Unmarshal(b, &p); err != nil { 86 var s string 87 if err := json.Unmarshal(b, &s); err != nil { 88 return err 89 } 90 p = append(p, s) 91 } 92 e.parts = p 93 return nil 94 } 95 96 func (e *Command) Len() int { 97 if e == nil { 98 return 0 99 } 100 return len(e.parts) 101 } 102 103 func (e *Command) Slice() []string { 104 if e == nil { 105 return nil 106 } 107 return e.parts 108 } 109 110 func NewCommand(parts ...string) *Command { 111 return &Command{parts} 112 } 113 114 // Note: the Config structure should hold only portable information about the container. 115 // Here, "portable" means "independent from the host we are running on". 116 // Non-portable information *should* appear in HostConfig. 117 type Config struct { 118 Hostname string 119 Domainname string 120 User string 121 AttachStdin bool 122 AttachStdout bool 123 AttachStderr bool 124 ExposedPorts map[nat.Port]struct{} 125 PublishService string 126 Tty bool // Attach standard streams to a tty, including stdin if it is not closed. 127 OpenStdin bool // Open stdin 128 StdinOnce bool // If true, close stdin after the 1 attached client disconnects. 129 Env []string 130 Cmd *Command 131 Image string // Name of the image as it was passed by the operator (eg. could be symbolic) 132 Volumes map[string]struct{} 133 VolumeDriver string 134 WorkingDir string 135 Entrypoint *Entrypoint 136 NetworkDisabled bool 137 MacAddress string 138 OnBuild []string 139 Labels map[string]string 140 } 141 142 type ContainerConfigWrapper struct { 143 *Config 144 InnerHostConfig *HostConfig `json:"HostConfig,omitempty"` 145 Cpuset string `json:",omitempty"` // Deprecated. Exported for backwards compatibility. 146 *HostConfig // Deprecated. Exported to read attrubutes from json that are not in the inner host config structure. 147 148 } 149 150 func (w *ContainerConfigWrapper) GetHostConfig() *HostConfig { 151 hc := w.HostConfig 152 153 if hc == nil && w.InnerHostConfig != nil { 154 hc = w.InnerHostConfig 155 } else if w.InnerHostConfig != nil { 156 if hc.Memory != 0 && w.InnerHostConfig.Memory == 0 { 157 w.InnerHostConfig.Memory = hc.Memory 158 } 159 if hc.MemorySwap != 0 && w.InnerHostConfig.MemorySwap == 0 { 160 w.InnerHostConfig.MemorySwap = hc.MemorySwap 161 } 162 if hc.CpuShares != 0 && w.InnerHostConfig.CpuShares == 0 { 163 w.InnerHostConfig.CpuShares = hc.CpuShares 164 } 165 166 hc = w.InnerHostConfig 167 } 168 169 if hc != nil && w.Cpuset != "" && hc.CpusetCpus == "" { 170 hc.CpusetCpus = w.Cpuset 171 } 172 173 return hc 174 } 175 176 // DecodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper 177 // struct and returns both a Config and an HostConfig struct 178 // Be aware this function is not checking whether the resulted structs are nil, 179 // it's your business to do so 180 func DecodeContainerConfig(src io.Reader) (*Config, *HostConfig, error) { 181 decoder := json.NewDecoder(src) 182 183 var w ContainerConfigWrapper 184 if err := decoder.Decode(&w); err != nil { 185 return nil, nil, err 186 } 187 188 return w.Config, w.GetHostConfig(), nil 189 }