github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/specgen/generate/pod_create.go (about)

     1  package generate
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  
     7  	"github.com/hanks177/podman/v4/libpod"
     8  	"github.com/hanks177/podman/v4/libpod/define"
     9  	"github.com/hanks177/podman/v4/pkg/domain/entities"
    10  	"github.com/hanks177/podman/v4/pkg/specgen"
    11  	"github.com/pkg/errors"
    12  	"github.com/sirupsen/logrus"
    13  )
    14  
    15  func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
    16  	if err := p.PodSpecGen.Validate(); err != nil {
    17  		return nil, err
    18  	}
    19  
    20  	if !p.PodSpecGen.NoInfra {
    21  		imageName, err := PullOrBuildInfraImage(rt, p.PodSpecGen.InfraImage)
    22  		if err != nil {
    23  			return nil, err
    24  		}
    25  		p.PodSpecGen.InfraImage = imageName
    26  		p.PodSpecGen.InfraContainerSpec.RawImageName = imageName
    27  	}
    28  
    29  	if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
    30  		var err error
    31  		p.PodSpecGen.InfraContainerSpec, err = MapSpec(&p.PodSpecGen)
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  	}
    36  
    37  	options, err := createPodOptions(&p.PodSpecGen)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	pod, err := rt.NewPod(context.Background(), p.PodSpecGen, options...)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
    46  		if p.PodSpecGen.InfraContainerSpec.Name == "" {
    47  			p.PodSpecGen.InfraContainerSpec.Name = pod.ID()[:12] + "-infra"
    48  		}
    49  		_, err = CompleteSpec(context.Background(), rt, p.PodSpecGen.InfraContainerSpec)
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  		p.PodSpecGen.InfraContainerSpec.User = "" // infraSpec user will get incorrectly assigned via the container creation process, overwrite here
    54  		rtSpec, spec, opts, err := MakeContainer(context.Background(), rt, p.PodSpecGen.InfraContainerSpec, false, nil)
    55  		if err != nil {
    56  			return nil, err
    57  		}
    58  		spec.Pod = pod.ID()
    59  		opts = append(opts, rt.WithPod(pod))
    60  		spec.CgroupParent = pod.CgroupParent()
    61  		infraCtr, err := ExecuteCreate(context.Background(), rt, rtSpec, spec, true, opts...)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		pod, err = rt.AddInfra(context.Background(), pod, infraCtr)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  	} else {
    70  		// SavePod is used to save the pod state and trigger a create event even if infra is not created
    71  		err := rt.SavePod(pod)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  	}
    76  	return pod, nil
    77  }
    78  
    79  func createPodOptions(p *specgen.PodSpecGenerator) ([]libpod.PodCreateOption, error) {
    80  	var (
    81  		options []libpod.PodCreateOption
    82  	)
    83  	if !p.NoInfra {
    84  		options = append(options, libpod.WithInfraContainer())
    85  		if p.ShareParent == nil || (p.ShareParent != nil && *p.ShareParent) {
    86  			options = append(options, libpod.WithPodParent())
    87  		}
    88  		nsOptions, err := GetNamespaceOptions(p.SharedNamespaces, p.InfraContainerSpec.NetNS.IsHost())
    89  		if err != nil {
    90  			return nil, err
    91  		}
    92  		options = append(options, nsOptions...)
    93  		// Use pod user and infra userns only when --userns is not set to host
    94  		if !p.InfraContainerSpec.UserNS.IsHost() && !p.InfraContainerSpec.UserNS.IsDefault() {
    95  			options = append(options, libpod.WithPodUser())
    96  		}
    97  	}
    98  
    99  	if len(p.ServiceContainerID) > 0 {
   100  		options = append(options, libpod.WithServiceContainer(p.ServiceContainerID))
   101  	}
   102  
   103  	if len(p.CgroupParent) > 0 {
   104  		options = append(options, libpod.WithPodCgroupParent(p.CgroupParent))
   105  	}
   106  	if len(p.Labels) > 0 {
   107  		options = append(options, libpod.WithPodLabels(p.Labels))
   108  	}
   109  	if len(p.Name) > 0 {
   110  		options = append(options, libpod.WithPodName(p.Name))
   111  	}
   112  	if p.PodCreateCommand != nil {
   113  		options = append(options, libpod.WithPodCreateCommand(p.PodCreateCommand))
   114  	}
   115  
   116  	if len(p.Hostname) > 0 {
   117  		options = append(options, libpod.WithPodHostname(p.Hostname))
   118  	}
   119  
   120  	options = append(options, libpod.WithPodExitPolicy(p.ExitPolicy))
   121  
   122  	return options, nil
   123  }
   124  
   125  // MapSpec modifies the already filled Infra specgenerator,
   126  // replacing necessary values with those specified in pod creation
   127  func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
   128  	if len(p.PortMappings) > 0 {
   129  		ports, err := ParsePortMapping(p.PortMappings, nil)
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  		p.InfraContainerSpec.PortMappings = ports
   134  	}
   135  	switch p.NetNS.NSMode {
   136  	case specgen.Default, "":
   137  		if p.NoInfra {
   138  			logrus.Debugf("No networking because the infra container is missing")
   139  			break
   140  		}
   141  	case specgen.Bridge:
   142  		p.InfraContainerSpec.NetNS.NSMode = specgen.Bridge
   143  		logrus.Debugf("Pod using bridge network mode")
   144  	case specgen.Private:
   145  		p.InfraContainerSpec.NetNS.NSMode = specgen.Private
   146  		logrus.Debugf("Pod will use default network mode")
   147  	case specgen.Host:
   148  		logrus.Debugf("Pod will use host networking")
   149  		if len(p.InfraContainerSpec.PortMappings) > 0 ||
   150  			len(p.InfraContainerSpec.Networks) > 0 ||
   151  			p.InfraContainerSpec.NetNS.NSMode == specgen.NoNetwork {
   152  			return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified")
   153  		}
   154  		p.InfraContainerSpec.NetNS.NSMode = specgen.Host
   155  	case specgen.Slirp:
   156  		logrus.Debugf("Pod will use slirp4netns")
   157  		if p.InfraContainerSpec.NetNS.NSMode != specgen.Host {
   158  			p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
   159  			p.InfraContainerSpec.NetNS.NSMode = specgen.Slirp
   160  		}
   161  	case specgen.NoNetwork:
   162  		logrus.Debugf("Pod will not use networking")
   163  		if len(p.InfraContainerSpec.PortMappings) > 0 ||
   164  			len(p.InfraContainerSpec.Networks) > 0 ||
   165  			p.InfraContainerSpec.NetNS.NSMode == specgen.Host {
   166  			return nil, errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified")
   167  		}
   168  		p.InfraContainerSpec.NetNS.NSMode = specgen.NoNetwork
   169  	default:
   170  		return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode)
   171  	}
   172  
   173  	if len(p.InfraCommand) > 0 {
   174  		p.InfraContainerSpec.Entrypoint = p.InfraCommand
   175  	}
   176  
   177  	if len(p.HostAdd) > 0 {
   178  		p.InfraContainerSpec.HostAdd = p.HostAdd
   179  	}
   180  	if len(p.DNSServer) > 0 {
   181  		var dnsServers []net.IP
   182  		dnsServers = append(dnsServers, p.DNSServer...)
   183  
   184  		p.InfraContainerSpec.DNSServers = dnsServers
   185  	}
   186  	if len(p.DNSOption) > 0 {
   187  		p.InfraContainerSpec.DNSOptions = p.DNSOption
   188  	}
   189  	if len(p.DNSSearch) > 0 {
   190  		p.InfraContainerSpec.DNSSearch = p.DNSSearch
   191  	}
   192  	if p.NoManageResolvConf {
   193  		p.InfraContainerSpec.UseImageResolvConf = true
   194  	}
   195  	if len(p.Networks) > 0 {
   196  		p.InfraContainerSpec.Networks = p.Networks
   197  	}
   198  	// deprecated cni networks for api users
   199  	if len(p.CNINetworks) > 0 {
   200  		p.InfraContainerSpec.CNINetworks = p.CNINetworks
   201  	}
   202  	if p.NoManageHosts {
   203  		p.InfraContainerSpec.UseImageHosts = p.NoManageHosts
   204  	}
   205  
   206  	if len(p.InfraConmonPidFile) > 0 {
   207  		p.InfraContainerSpec.ConmonPidFile = p.InfraConmonPidFile
   208  	}
   209  
   210  	p.InfraContainerSpec.Image = p.InfraImage
   211  	return p.InfraContainerSpec, nil
   212  }