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