From d28e85741fedb89be48a03d4f05687e970eb71b9 Mon Sep 17 00:00:00 2001 From: cdoern Date: Wed, 14 Jul 2021 16:30:28 -0400 Subject: InfraContainer Rework InfraContainer should go through the same creation process as regular containers. This change was from the cmd level down, involving new container CLI opts and specgen creating functions. What now happens is that both container and pod cli options are populated in cmd and used to create a podSpecgen and a containerSpecgen. The process then goes as follows FillOutSpecGen (infra) -> MapSpec (podOpts -> infraOpts) -> PodCreate -> MakePod -> createPodOptions -> NewPod -> CompleteSpec (infra) -> MakeContainer -> NewContainer -> newContainer -> AddInfra (to pod state) Signed-off-by: cdoern --- libpod/options.go | 480 ++++-------------------------------------------------- 1 file changed, 33 insertions(+), 447 deletions(-) (limited to 'libpod/options.go') diff --git a/libpod/options.go b/libpod/options.go index 0bcd1e3a6..4cbd2b5e2 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -14,6 +14,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/events" + netTypes "github.com/containers/podman/v3/libpod/network/types" "github.com/containers/podman/v3/pkg/namespaces" "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/podman/v3/pkg/specgen" @@ -21,7 +22,6 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -713,7 +713,6 @@ func (r *Runtime) WithPod(pod *Pod) CtrCreateOption { if pod == nil { return define.ErrInvalidArg } - ctr.config.Pod = pod.ID() return nil @@ -1430,20 +1429,6 @@ func WithRestartRetries(tries uint) CtrCreateOption { } } -// withIsInfra sets the container to be an infra container. This means the container will be sometimes hidden -// and expected to be the first container in the pod. -func withIsInfra() CtrCreateOption { - return func(ctr *Container) error { - if ctr.valid { - return define.ErrCtrFinalized - } - - ctr.config.IsInfra = true - - return nil - } -} - // WithNamedVolumes adds the given named volumes to the container. func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption { return func(ctr *Container) error { @@ -1541,6 +1526,20 @@ func WithCreateCommand(cmd []string) CtrCreateOption { } } +// withIsInfra allows us to dfferentiate between infra containers and regular containers +// within the container config +func withIsInfra() CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return define.ErrCtrFinalized + } + + ctr.config.IsInfra = true + + return nil + } +} + // WithCreateWorkingDir tells Podman to create the container's working directory // if it does not exist. func WithCreateWorkingDir() CtrCreateOption { @@ -1812,45 +1811,14 @@ func WithInitCtrType(containerType string) CtrCreateOption { // Pod Creation Options -// WithInfraImage sets the infra image for libpod. -// An infra image is used for inter-container kernel -// namespace sharing within a pod. Typically, an infra -// container is lightweight and is there to reap -// zombie processes within its pid namespace. -func WithInfraImage(img string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - pod.config.InfraContainer.InfraImage = img - - return nil - } -} - -// WithInfraCommand sets the command to -// run on pause container start up. -func WithInfraCommand(cmd []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - pod.config.InfraContainer.InfraCommand = cmd - return nil - } -} - -// WithInfraName sets the infra container name for a single pod. -func WithInfraName(name string) PodCreateOption { +// WithPodCreateCommand adds the full command plus arguments of the current +// process to the pod config. +func WithPodCreateCommand(createCmd []string) PodCreateOption { return func(pod *Pod) error { if pod.valid { return define.ErrPodFinalized } - - pod.config.InfraContainer.InfraName = name - + pod.config.CreateCommand = createCmd return nil } } @@ -1891,26 +1859,14 @@ func WithPodHostname(hostname string) PodCreateOption { } } -// WithPodCreateCommand adds the full command plus arguments of the current -// process to the pod config. -func WithPodCreateCommand(createCmd []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - pod.config.CreateCommand = createCmd - return nil - } -} - // WithInfraConmonPidFile sets the path to a custom conmon PID file for the // infra container. -func WithInfraConmonPidFile(path string) PodCreateOption { +func WithInfraConmonPidFile(path string, infraSpec *specgen.SpecGenerator) PodCreateOption { return func(pod *Pod) error { if pod.valid { return define.ErrPodFinalized } - pod.config.InfraContainer.ConmonPidFile = path + infraSpec.ConmonPidFile = path return nil } } @@ -2099,320 +2055,25 @@ func WithInfraContainer() PodCreateOption { if pod.valid { return define.ErrPodFinalized } - - pod.config.InfraContainer.HasInfraContainer = true + pod.config.HasInfra = true return nil } } // WithInfraContainerPorts tells the pod to add port bindings to the pause container -func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot set pod ports as no infra container is being created") - } - pod.config.InfraContainer.PortBindings = bindings - return nil - } -} - -// WithPodStaticIP sets a static IP for the pod. -func WithPodStaticIP(ip net.IP) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static IP as no infra container is being created") - } - - if pod.config.InfraContainer.HostNetwork { - return errors.Wrapf(define.ErrInvalidArg, "cannot set static IP if host network is specified") - } - - if len(pod.config.InfraContainer.Networks) > 1 { - return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if joining more than 1 CNI network") - } - - pod.config.InfraContainer.StaticIP = ip - - return nil - } -} - -// WithPodStaticMAC sets a static MAC address for the pod. -func WithPodStaticMAC(mac net.HardwareAddr) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot set pod static MAC as no infra container is being created") - } - - if pod.config.InfraContainer.HostNetwork { - return errors.Wrapf(define.ErrInvalidArg, "cannot set static MAC if host network is specified") - } - - if len(pod.config.InfraContainer.Networks) > 1 { - return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if joining more than 1 CNI network") - } - - pod.config.InfraContainer.StaticMAC = mac - - return nil - } -} - -// WithPodUseImageResolvConf sets a pod to use an image's resolv.conf and not -// create its own. -func WithPodUseImageResolvConf() PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created") - } - - if len(pod.config.InfraContainer.DNSServer) != 0 || - len(pod.config.InfraContainer.DNSSearch) != 0 || - len(pod.config.InfraContainer.DNSOption) != 0 { - return errors.Wrapf(define.ErrInvalidArg, "requested use of image resolv.conf conflicts with already-configured DNS settings") - } - - pod.config.InfraContainer.UseImageResolvConf = true - - return nil - } -} - -// WithPodDNS sets the DNS Servers for a pod. -func WithPodDNS(dnsServer []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created") - } - - if pod.config.InfraContainer.UseImageResolvConf { - return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS servers if pod will not create /etc/resolv.conf") - } - - pod.config.InfraContainer.DNSServer = dnsServer - - return nil - } -} - -// WithPodDNSSearch sets the DNS Search domains for a pod. -func WithPodDNSSearch(dnsSearch []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created") - } - - if pod.config.InfraContainer.UseImageResolvConf { - return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS search domains if pod will not create /etc/resolv.conf") - } - - pod.config.InfraContainer.DNSSearch = dnsSearch - - return nil - } -} - -// WithPodDNSOption sets DNS Options for a pod. -func WithPodDNSOption(dnsOption []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod DNS as no infra container is being created") - } - - if pod.config.InfraContainer.UseImageResolvConf { - return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if pod will not create /etc/resolv.conf") - } - - pod.config.InfraContainer.DNSOption = dnsOption - - return nil - } -} - -// WithPodUseImageHosts tells the pod not to create /etc/hosts and instead to -// use the one provided by the image. -func WithPodUseImageHosts() PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created") - } - - if len(pod.config.InfraContainer.HostAdd) != 0 { - return errors.Wrapf(define.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file") - } - - pod.config.InfraContainer.UseImageHosts = true - - return nil - } -} - -// WithPodHosts adds additional entries to the pod's /etc/hosts -func WithPodHosts(hosts []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod hosts as no infra container is being created") - } - - if pod.config.InfraContainer.UseImageHosts { - return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if container is using image hosts") - } - - pod.config.InfraContainer.HostAdd = hosts - - return nil - } -} - -// WithPodNetworks sets additional CNI networks for the pod to join. -func WithPodNetworks(networks []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod CNI networks as no infra container is being created") - } - - if (pod.config.InfraContainer.StaticIP != nil || pod.config.InfraContainer.StaticMAC != nil) && - len(networks) > 1 { - return errors.Wrapf(define.ErrInvalidArg, "cannot join more than one CNI network if setting a static IP or MAC address") - } - - if pod.config.InfraContainer.HostNetwork { - return errors.Wrapf(define.ErrInvalidArg, "cannot join pod to CNI networks if host network is specified") - } - - pod.config.InfraContainer.Networks = networks - - return nil - } -} - -// WithPodNoNetwork tells the pod to disable external networking. -func WithPodNoNetwork() PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod networking as no infra container is being created") - } - - if len(pod.config.InfraContainer.PortBindings) > 0 || - pod.config.InfraContainer.StaticIP != nil || - pod.config.InfraContainer.StaticMAC != nil || - len(pod.config.InfraContainer.Networks) > 0 || - pod.config.InfraContainer.HostNetwork { - return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified") - } - - pod.config.InfraContainer.NoNetwork = true - - return nil - } -} - -// WithPodHostNetwork tells the pod to use the host's network namespace. -func WithPodHostNetwork() PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod host networking as no infra container is being created") - } - - if len(pod.config.InfraContainer.PortBindings) > 0 || - pod.config.InfraContainer.StaticIP != nil || - pod.config.InfraContainer.StaticMAC != nil || - len(pod.config.InfraContainer.Networks) > 0 || - pod.config.InfraContainer.NoNetwork { - return errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified") - } - - pod.config.InfraContainer.HostNetwork = true - - return nil - } -} - -// WithPodInfraExitCommand sets an exit command for the pod's infra container. -// Semantics are identical to WithExitCommand() above - the ID of the container -// will be appended to the end of the provided command (note that this will -// specifically be the ID of the infra container *and not the pod's id*. -func WithPodInfraExitCommand(exitCmd []string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod infra container exit command as no infra container is being created") - } - - pod.config.InfraContainer.ExitCommand = exitCmd - - return nil - } -} - -// WithPodSlirp4netns tells the pod to use slirp4netns. -func WithPodSlirp4netns(networkOptions map[string][]string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod networking as no infra container is being created") - } - if pod.config.InfraContainer.HostNetwork { - return errors.Wrapf(define.ErrInvalidArg, "cannot set both HostNetwork and Slirp4netns") - } - pod.config.InfraContainer.Slirp4netns = true - pod.config.InfraContainer.NetworkOptions = networkOptions - - return nil +func WithInfraContainerPorts(bindings []ocicni.PortMapping, infraSpec *specgen.SpecGenerator) []netTypes.PortMapping { + bindingSpec := []netTypes.PortMapping{} + for _, bind := range bindings { + currBind := netTypes.PortMapping{} + currBind.ContainerPort = uint16(bind.ContainerPort) + currBind.HostIP = bind.HostIP + currBind.HostPort = uint16(bind.HostPort) + currBind.Protocol = bind.Protocol + bindingSpec = append(bindingSpec, currBind) } + infraSpec.PortMappings = bindingSpec + return infraSpec.PortMappings } // WithVolatile sets the volatile flag for the container storage. @@ -2428,78 +2089,3 @@ func WithVolatile() CtrCreateOption { return nil } } - -// WithPodUserns sets the userns for the infra container in a pod. -func WithPodUserns(userns specgen.Namespace) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - - if !pod.config.InfraContainer.HasInfraContainer { - return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod userns as no infra container is being created") - } - - pod.config.InfraContainer.Userns = userns - - return nil - } -} - -// WithPodCPUPAQ takes the given cpu period and quota and inserts them in the proper place. -func WithPodCPUPAQ(period uint64, quota int64) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - if pod.CPUPeriod() != 0 && pod.CPUQuota() != 0 { - pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{ - Period: &period, - Quota: "a, - } - } else { - pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{} - pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{ - Period: &period, - Quota: "a, - } - } - return nil - } -} - -// WithPodCPUSetCPUS computes and sets the Cpus linux resource string which determines the amount of cores, from those available, we are allowed to execute on -func WithPodCPUSetCPUs(inp string) PodCreateOption { - return func(pod *Pod) error { - if pod.valid { - return define.ErrPodFinalized - } - if pod.ResourceLim().CPU.Period != nil { - pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp - } else { - pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{} - pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{} - pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp - } - return nil - } -} - -func WithPodPidNS(inp specgen.Namespace) PodCreateOption { - return func(p *Pod) error { - if p.valid { - return define.ErrPodFinalized - } - if p.config.UsePodPID { - switch inp.NSMode { - case "container": - return errors.Wrap(define.ErrInvalidArg, "Cannot take container in a different NS as an argument") - case "host": - p.config.UsePodPID = false - } - p.config.InfraContainer.PidNS = inp - } - - return nil - } -} -- cgit v1.2.3-54-g00ecf