github.com/moby/docker@v26.1.3+incompatible/runconfig/config.go (about)

     1  package runconfig // import "github.com/docker/docker/runconfig"
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  
     7  	"github.com/docker/docker/api/types/container"
     8  	networktypes "github.com/docker/docker/api/types/network"
     9  	"github.com/docker/docker/pkg/sysinfo"
    10  )
    11  
    12  // ContainerDecoder implements httputils.ContainerDecoder
    13  // calling DecodeContainerConfig.
    14  type ContainerDecoder struct {
    15  	GetSysInfo func() *sysinfo.SysInfo
    16  }
    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  	var si *sysinfo.SysInfo
    21  	if r.GetSysInfo != nil {
    22  		si = r.GetSysInfo()
    23  	} else {
    24  		si = sysinfo.New()
    25  	}
    26  
    27  	return decodeContainerConfig(src, si)
    28  }
    29  
    30  // decodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper
    31  // struct and returns both a Config and a HostConfig struct, and performs some
    32  // validation. Certain parameters need daemon-side validation that cannot be done
    33  // on the client, as only the daemon knows what is valid for the platform.
    34  // Be aware this function is not checking whether the resulted structs are nil,
    35  // it's your business to do so
    36  func decodeContainerConfig(src io.Reader, si *sysinfo.SysInfo) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
    37  	var w ContainerConfigWrapper
    38  	if err := loadJSON(src, &w); err != nil {
    39  		return nil, nil, nil, err
    40  	}
    41  
    42  	hc := w.getHostConfig()
    43  	if hc == nil {
    44  		// We may not be passed a host config, such as in the case of docker commit
    45  		return w.Config, hc, w.NetworkingConfig, nil
    46  	}
    47  	if err := validateNetMode(w.Config, hc); err != nil {
    48  		return nil, nil, nil, err
    49  	}
    50  	if err := validateIsolation(hc); err != nil {
    51  		return nil, nil, nil, err
    52  	}
    53  	if err := validateQoS(hc); err != nil {
    54  		return nil, nil, nil, err
    55  	}
    56  	if err := validateResources(hc, si); err != nil {
    57  		return nil, nil, nil, err
    58  	}
    59  	if err := validatePrivileged(hc); err != nil {
    60  		return nil, nil, nil, err
    61  	}
    62  	if err := validateReadonlyRootfs(hc); err != nil {
    63  		return nil, nil, nil, err
    64  	}
    65  	if w.Config != nil && w.Config.Volumes == nil {
    66  		w.Config.Volumes = make(map[string]struct{})
    67  	}
    68  	return w.Config, hc, w.NetworkingConfig, nil
    69  }
    70  
    71  // loadJSON is similar to api/server/httputils.ReadJSON()
    72  func loadJSON(src io.Reader, out interface{}) error {
    73  	dec := json.NewDecoder(src)
    74  	if err := dec.Decode(&out); err != nil {
    75  		return invalidJSONError{Err: err}
    76  	}
    77  	if dec.More() {
    78  		return validationError("unexpected content after JSON")
    79  	}
    80  	return nil
    81  }