Files
podman/pkg/specgen/generate/pod_create.go
cdoern d28e85741f 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 <cdoern@redhat.com>
2021-08-26 16:05:16 -04:00

205 lines
6.6 KiB
Go

package generate
import (
"context"
"net"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
if err := p.PodSpecGen.Validate(); err != nil {
return nil, err
}
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
var err error
p.PodSpecGen.InfraContainerSpec, err = MapSpec(&p.PodSpecGen)
if err != nil {
return nil, err
}
}
options, err := createPodOptions(&p.PodSpecGen, rt, p.PodSpecGen.InfraContainerSpec)
if err != nil {
return nil, err
}
pod, err := rt.NewPod(context.Background(), p.PodSpecGen, options...)
if err != nil {
return nil, err
}
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
p.PodSpecGen.InfraContainerSpec.ContainerCreateCommand = []string{} // we do NOT want os.Args as the command, will display the pod create cmd
if p.PodSpecGen.InfraContainerSpec.Name == "" {
p.PodSpecGen.InfraContainerSpec.Name = pod.ID()[:12] + "-infra"
}
_, err = CompleteSpec(context.Background(), rt, p.PodSpecGen.InfraContainerSpec)
if err != nil {
return nil, err
}
p.PodSpecGen.InfraContainerSpec.User = "" // infraSpec user will get incorrectly assigned via the container creation process, overwrite here
rtSpec, spec, opts, err := MakeContainer(context.Background(), rt, p.PodSpecGen.InfraContainerSpec)
if err != nil {
return nil, err
}
spec.Pod = pod.ID()
opts = append(opts, rt.WithPod(pod))
spec.CgroupParent = pod.CgroupParent()
infraCtr, err := ExecuteCreate(context.Background(), rt, rtSpec, spec, true, opts...)
if err != nil {
return nil, err
}
pod, err = rt.AddInfra(context.Background(), pod, infraCtr)
if err != nil {
return nil, err
}
}
return pod, nil
}
func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime, infraSpec *specgen.SpecGenerator) ([]libpod.PodCreateOption, error) {
var (
options []libpod.PodCreateOption
)
if !p.NoInfra { //&& infraSpec != nil {
options = append(options, libpod.WithInfraContainer())
nsOptions, err := GetNamespaceOptions(p.SharedNamespaces, p.InfraContainerSpec.NetNS.IsHost())
if err != nil {
return nil, err
}
options = append(options, nsOptions...)
// Use pod user and infra userns only when --userns is not set to host
if !p.InfraContainerSpec.UserNS.IsHost() && !p.InfraContainerSpec.UserNS.IsDefault() {
options = append(options, libpod.WithPodUser())
}
}
if len(p.CgroupParent) > 0 {
options = append(options, libpod.WithPodCgroupParent(p.CgroupParent))
}
if len(p.Labels) > 0 {
options = append(options, libpod.WithPodLabels(p.Labels))
}
if len(p.Name) > 0 {
options = append(options, libpod.WithPodName(p.Name))
}
if p.PodCreateCommand != nil {
options = append(options, libpod.WithPodCreateCommand(p.PodCreateCommand))
}
if len(p.Hostname) > 0 {
options = append(options, libpod.WithPodHostname(p.Hostname))
}
return options, nil
}
// MapSpec modifies the already filled Infra specgenerator,
// replacing necessary values with those specified in pod creation
func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
if len(p.PortMappings) > 0 {
ports, _, _, err := ParsePortMapping(p.PortMappings)
if err != nil {
return nil, err
}
p.InfraContainerSpec.PortMappings = libpod.WithInfraContainerPorts(ports, p.InfraContainerSpec)
}
switch p.NetNS.NSMode {
case specgen.Default, "":
if p.NoInfra {
logrus.Debugf("No networking because the infra container is missing")
break
}
if rootless.IsRootless() {
logrus.Debugf("Pod will use slirp4netns")
if p.InfraContainerSpec.NetNS.NSMode != "host" {
p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
p.InfraContainerSpec.NetNS.NSMode = specgen.NamespaceMode("slirp4netns")
}
} else {
logrus.Debugf("Pod using bridge network mode")
}
case specgen.Bridge:
p.InfraContainerSpec.NetNS.NSMode = specgen.Bridge
logrus.Debugf("Pod using bridge network mode")
case specgen.Host:
logrus.Debugf("Pod will use host networking")
if len(p.InfraContainerSpec.PortMappings) > 0 ||
p.InfraContainerSpec.StaticIP != nil ||
p.InfraContainerSpec.StaticMAC != nil ||
len(p.InfraContainerSpec.CNINetworks) > 0 ||
p.InfraContainerSpec.NetNS.NSMode == specgen.NoNetwork {
return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
}
p.InfraContainerSpec.NetNS.NSMode = specgen.Host
case specgen.Slirp:
logrus.Debugf("Pod will use slirp4netns")
if p.InfraContainerSpec.NetNS.NSMode != "host" {
p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
p.InfraContainerSpec.NetNS.NSMode = specgen.NamespaceMode("slirp4netns")
}
case specgen.NoNetwork:
logrus.Debugf("Pod will not use networking")
if len(p.InfraContainerSpec.PortMappings) > 0 ||
p.InfraContainerSpec.StaticIP != nil ||
p.InfraContainerSpec.StaticMAC != nil ||
len(p.InfraContainerSpec.CNINetworks) > 0 ||
p.InfraContainerSpec.NetNS.NSMode == "host" {
return nil, errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified")
}
p.InfraContainerSpec.NetNS.NSMode = specgen.NoNetwork
default:
return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode)
}
libpod.WithPodCgroups()
if len(p.InfraCommand) > 0 {
p.InfraContainerSpec.Entrypoint = p.InfraCommand
}
if len(p.HostAdd) > 0 {
p.InfraContainerSpec.HostAdd = p.HostAdd
}
if len(p.DNSServer) > 0 {
var dnsServers []net.IP
dnsServers = append(dnsServers, p.DNSServer...)
p.InfraContainerSpec.DNSServers = dnsServers
}
if len(p.DNSOption) > 0 {
p.InfraContainerSpec.DNSOptions = p.DNSOption
}
if len(p.DNSSearch) > 0 {
p.InfraContainerSpec.DNSSearch = p.DNSSearch
}
if p.StaticIP != nil {
p.InfraContainerSpec.StaticIP = p.StaticIP
}
if p.StaticMAC != nil {
p.InfraContainerSpec.StaticMAC = p.StaticMAC
}
if p.NoManageResolvConf {
p.InfraContainerSpec.UseImageResolvConf = true
}
if len(p.CNINetworks) > 0 {
p.InfraContainerSpec.CNINetworks = p.CNINetworks
}
if p.NoManageHosts {
p.InfraContainerSpec.UseImageHosts = p.NoManageHosts
}
if len(p.InfraConmonPidFile) > 0 {
p.InfraContainerSpec.ConmonPidFile = p.InfraConmonPidFile
}
if p.InfraImage != config.DefaultInfraImage {
p.InfraContainerSpec.Image = p.InfraImage
}
return p.InfraContainerSpec, nil
}