config.go 3.2 KB

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