github.com/jandre/docker@v1.7.0/runconfig/config.go (about) 1 package runconfig 2 3 import ( 4 "encoding/json" 5 "io" 6 "strings" 7 8 "github.com/docker/docker/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 p = append(p, string(b)) 36 } 37 e.parts = p 38 return nil 39 } 40 41 func (e *Entrypoint) Len() int { 42 if e == nil { 43 return 0 44 } 45 return len(e.parts) 46 } 47 48 func (e *Entrypoint) Slice() []string { 49 if e == nil { 50 return nil 51 } 52 return e.parts 53 } 54 55 func NewEntrypoint(parts ...string) *Entrypoint { 56 return &Entrypoint{parts} 57 } 58 59 type Command struct { 60 parts []string 61 } 62 63 func (e *Command) ToString() string { 64 return strings.Join(e.parts, " ") 65 } 66 67 func (e *Command) MarshalJSON() ([]byte, error) { 68 if e == nil { 69 return []byte{}, nil 70 } 71 return json.Marshal(e.Slice()) 72 } 73 74 // UnmarshalJSON decoded the entrypoint whether it's a string or an array of strings. 75 func (e *Command) UnmarshalJSON(b []byte) error { 76 if len(b) == 0 { 77 return nil 78 } 79 80 p := make([]string, 0, 1) 81 if err := json.Unmarshal(b, &p); err != nil { 82 p = append(p, string(b)) 83 } 84 e.parts = p 85 return nil 86 } 87 88 func (e *Command) Len() int { 89 if e == nil { 90 return 0 91 } 92 return len(e.parts) 93 } 94 95 func (e *Command) Slice() []string { 96 if e == nil { 97 return nil 98 } 99 return e.parts 100 } 101 102 func NewCommand(parts ...string) *Command { 103 return &Command{parts} 104 } 105 106 // Note: the Config structure should hold only portable information about the container. 107 // Here, "portable" means "independent from the host we are running on". 108 // Non-portable information *should* appear in HostConfig. 109 type Config struct { 110 Hostname string 111 Domainname string 112 User string 113 AttachStdin bool 114 AttachStdout bool 115 AttachStderr bool 116 PortSpecs []string // Deprecated - Can be in the format of 8080/tcp 117 ExposedPorts map[nat.Port]struct{} 118 Tty bool // Attach standard streams to a tty, including stdin if it is not closed. 119 OpenStdin bool // Open stdin 120 StdinOnce bool // If true, close stdin after the 1 attached client disconnects. 121 Env []string 122 Cmd *Command 123 Image string // Name of the image as it was passed by the operator (eg. could be symbolic) 124 Volumes map[string]struct{} 125 VolumeDriver string 126 WorkingDir string 127 Entrypoint *Entrypoint 128 NetworkDisabled bool 129 MacAddress string 130 OnBuild []string 131 Labels map[string]string 132 } 133 134 type ContainerConfigWrapper struct { 135 *Config 136 *hostConfigWrapper 137 } 138 139 func (c ContainerConfigWrapper) HostConfig() *HostConfig { 140 if c.hostConfigWrapper == nil { 141 return new(HostConfig) 142 } 143 144 return c.hostConfigWrapper.GetHostConfig() 145 } 146 147 // DecodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper 148 // struct and returns both a Config and an HostConfig struct 149 // Be aware this function is not checking whether the resulted structs are nil, 150 // it's your business to do so 151 func DecodeContainerConfig(src io.Reader) (*Config, *HostConfig, error) { 152 decoder := json.NewDecoder(src) 153 154 var w ContainerConfigWrapper 155 if err := decoder.Decode(&w); err != nil { 156 return nil, nil, err 157 } 158 159 return w.Config, w.HostConfig(), nil 160 }