github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/container_validate.go (about)

     1  package libpod
     2  
     3  import (
     4  	"github.com/containers/podman/v3/libpod/define"
     5  	spec "github.com/opencontainers/runtime-spec/specs-go"
     6  	"github.com/pkg/errors"
     7  )
     8  
     9  // Validate that the configuration of a container is valid.
    10  func (c *Container) validate() error {
    11  	imageIDSet := c.config.RootfsImageID != ""
    12  	imageNameSet := c.config.RootfsImageName != ""
    13  	rootfsSet := c.config.Rootfs != ""
    14  
    15  	// If one of RootfsImageIDor RootfsImageName are set, both must be set.
    16  	if (imageIDSet || imageNameSet) && !(imageIDSet && imageNameSet) {
    17  		return errors.Wrapf(define.ErrInvalidArg, "both RootfsImageName and RootfsImageID must be set if either is set")
    18  	}
    19  
    20  	// Cannot set RootfsImageID and Rootfs at the same time
    21  	if imageIDSet && rootfsSet {
    22  		return errors.Wrapf(define.ErrInvalidArg, "cannot set both an image ID and rootfs for a container")
    23  	}
    24  
    25  	// Must set at least one of RootfsImageID or Rootfs
    26  	if !(imageIDSet || rootfsSet) {
    27  		return errors.Wrapf(define.ErrInvalidArg, "must set root filesystem source to either image or rootfs")
    28  	}
    29  
    30  	// Cannot make a network namespace if we are joining another container's
    31  	// network namespace
    32  	if c.config.CreateNetNS && c.config.NetNsCtr != "" {
    33  		return errors.Wrapf(define.ErrInvalidArg, "cannot both create a network namespace and join another container's network namespace")
    34  	}
    35  
    36  	if c.config.CgroupsMode == cgroupSplit && c.config.CgroupParent != "" {
    37  		return errors.Wrapf(define.ErrInvalidArg, "cannot specify --cgroup-mode=split with a cgroup-parent")
    38  	}
    39  
    40  	// Not creating cgroups has a number of requirements, mostly related to
    41  	// the PID namespace.
    42  	if c.config.NoCgroups || c.config.CgroupsMode == "disabled" {
    43  		if c.config.PIDNsCtr != "" {
    44  			return errors.Wrapf(define.ErrInvalidArg, "cannot join another container's PID namespace if not creating cgroups")
    45  		}
    46  
    47  		if c.config.CgroupParent != "" {
    48  			return errors.Wrapf(define.ErrInvalidArg, "cannot set cgroup parent if not creating cgroups")
    49  		}
    50  
    51  		// Ensure we have a PID namespace
    52  		if c.config.Spec.Linux == nil {
    53  			return errors.Wrapf(define.ErrInvalidArg, "must provide Linux namespace configuration in OCI spec when using NoCgroups")
    54  		}
    55  		foundPid := false
    56  		for _, ns := range c.config.Spec.Linux.Namespaces {
    57  			if ns.Type == spec.PIDNamespace {
    58  				foundPid = true
    59  				if ns.Path != "" {
    60  					return errors.Wrapf(define.ErrInvalidArg, "containers not creating CGroups must create a private PID namespace - cannot use another")
    61  				}
    62  				break
    63  			}
    64  		}
    65  		if !foundPid {
    66  			return errors.Wrapf(define.ErrInvalidArg, "containers not creating CGroups must create a private PID namespace")
    67  		}
    68  	}
    69  
    70  	// Can only set static IP or MAC is creating a network namespace.
    71  	if !c.config.CreateNetNS && (c.config.StaticIP != nil || c.config.StaticMAC != nil) {
    72  		return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP or MAC address if not creating a network namespace")
    73  	}
    74  
    75  	// Cannot set static IP or MAC if joining >1 CNI network.
    76  	if len(c.config.Networks) > 1 && (c.config.StaticIP != nil || c.config.StaticMAC != nil) {
    77  		return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP or MAC address if joining more than one CNI network")
    78  	}
    79  
    80  	// Using image resolv.conf conflicts with various DNS settings.
    81  	if c.config.UseImageResolvConf &&
    82  		(len(c.config.DNSSearch) > 0 || len(c.config.DNSServer) > 0 ||
    83  			len(c.config.DNSOption) > 0) {
    84  		return errors.Wrapf(define.ErrInvalidArg, "cannot configure DNS options if using image's resolv.conf")
    85  	}
    86  
    87  	if c.config.UseImageHosts && len(c.config.HostAdd) > 0 {
    88  		return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if using image's /etc/hosts")
    89  	}
    90  
    91  	// Check named volume, overlay volume and image volume destination conflist
    92  	destinations := make(map[string]bool)
    93  	for _, vol := range c.config.NamedVolumes {
    94  		// Don't check if they already exist.
    95  		// If they don't we will automatically create them.
    96  		if _, ok := destinations[vol.Dest]; ok {
    97  			return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest)
    98  		}
    99  		destinations[vol.Dest] = true
   100  	}
   101  	for _, vol := range c.config.OverlayVolumes {
   102  		// Don't check if they already exist.
   103  		// If they don't we will automatically create them.
   104  		if _, ok := destinations[vol.Dest]; ok {
   105  			return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest)
   106  		}
   107  		destinations[vol.Dest] = true
   108  	}
   109  	for _, vol := range c.config.ImageVolumes {
   110  		// Don't check if they already exist.
   111  		// If they don't we will automatically create them.
   112  		if _, ok := destinations[vol.Dest]; ok {
   113  			return errors.Wrapf(define.ErrInvalidArg, "two volumes found with destination %s", vol.Dest)
   114  		}
   115  		destinations[vol.Dest] = true
   116  	}
   117  
   118  	// Check that networks and network aliases match up.
   119  	ctrNets := make(map[string]bool)
   120  	for _, net := range c.config.Networks {
   121  		ctrNets[net] = true
   122  	}
   123  	for net := range c.config.NetworkAliases {
   124  		if _, ok := ctrNets[net]; !ok {
   125  			return errors.Wrapf(define.ErrNoSuchNetwork, "container tried to set network aliases for network %s but is not connected to the network", net)
   126  		}
   127  	}
   128  
   129  	// If User in the OCI spec is set, require that c.config.User is set for
   130  	// security reasons (a lot of our code relies on c.config.User).
   131  	if c.config.User == "" && (c.config.Spec.Process.User.UID != 0 || c.config.Spec.Process.User.GID != 0) {
   132  		return errors.Wrapf(define.ErrInvalidArg, "please set User explicitly via WithUser() instead of in OCI spec directly")
   133  	}
   134  
   135  	// Init-ctrs must be used inside a Pod.  Check if a init container type is
   136  	// passed and if no pod is passed
   137  	if len(c.config.InitContainerType) > 0 && len(c.config.Pod) < 1 {
   138  		return errors.Wrap(define.ErrInvalidArg, "init containers must be created in a pod")
   139  	}
   140  	return nil
   141  }