github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/runconfig/config.go (about) 1 package runconfig 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 8 "github.com/docker/docker/api/types/container" 9 networktypes "github.com/docker/docker/api/types/network" 10 "github.com/docker/docker/volume" 11 ) 12 13 // ContainerDecoder implements httputils.ContainerDecoder 14 // calling DecodeContainerConfig. 15 type ContainerDecoder struct{} 16 17 // DecodeConfig makes ContainerDecoder to implement httputils.ContainerDecoder 18 func (r ContainerDecoder) DecodeConfig(src io.Reader) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) { 19 return DecodeContainerConfig(src) 20 } 21 22 // DecodeHostConfig makes ContainerDecoder to implement httputils.ContainerDecoder 23 func (r ContainerDecoder) DecodeHostConfig(src io.Reader) (*container.HostConfig, error) { 24 return DecodeHostConfig(src) 25 } 26 27 // DecodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper 28 // struct and returns both a Config and a HostConfig struct 29 // Be aware this function is not checking whether the resulted structs are nil, 30 // it's your business to do so 31 func DecodeContainerConfig(src io.Reader) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) { 32 var w ContainerConfigWrapper 33 34 decoder := json.NewDecoder(src) 35 if err := decoder.Decode(&w); err != nil { 36 return nil, nil, nil, err 37 } 38 39 hc := w.getHostConfig() 40 41 // Perform platform-specific processing of Volumes and Binds. 42 if w.Config != nil && hc != nil { 43 44 // Initialize the volumes map if currently nil 45 if w.Config.Volumes == nil { 46 w.Config.Volumes = make(map[string]struct{}) 47 } 48 49 // Now validate all the volumes and binds 50 if err := validateVolumesAndBindSettings(w.Config, hc); err != nil { 51 return nil, nil, nil, err 52 } 53 } 54 55 // Certain parameters need daemon-side validation that cannot be done 56 // on the client, as only the daemon knows what is valid for the platform. 57 if err := ValidateNetMode(w.Config, hc); err != nil { 58 return nil, nil, nil, err 59 } 60 61 // Validate isolation 62 if err := ValidateIsolation(hc); err != nil { 63 return nil, nil, nil, err 64 } 65 66 // Validate QoS 67 if err := ValidateQoS(hc); err != nil { 68 return nil, nil, nil, err 69 } 70 return w.Config, hc, w.NetworkingConfig, nil 71 } 72 73 // validateVolumesAndBindSettings validates each of the volumes and bind settings 74 // passed by the caller to ensure they are valid. 75 func validateVolumesAndBindSettings(c *container.Config, hc *container.HostConfig) error { 76 if len(hc.Mounts) > 0 { 77 if len(hc.Binds) > 0 { 78 return conflictError(fmt.Errorf("must not specify both Binds and Mounts")) 79 } 80 81 if len(c.Volumes) > 0 { 82 return conflictError(fmt.Errorf("must not specify both Volumes and Mounts")) 83 } 84 85 if len(hc.VolumeDriver) > 0 { 86 return conflictError(fmt.Errorf("must not specify both VolumeDriver and Mounts")) 87 } 88 } 89 90 // Ensure all volumes and binds are valid. 91 for spec := range c.Volumes { 92 if _, err := volume.ParseMountRaw(spec, hc.VolumeDriver); err != nil { 93 return fmt.Errorf("invalid volume spec %q: %v", spec, err) 94 } 95 } 96 for _, spec := range hc.Binds { 97 if _, err := volume.ParseMountRaw(spec, hc.VolumeDriver); err != nil { 98 return fmt.Errorf("invalid bind mount spec %q: %v", spec, err) 99 } 100 } 101 102 return nil 103 }