github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podmanV2/pods/create.go (about)

     1  package pods
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/containers/libpod/cmd/podmanV2/common"
    10  	"github.com/containers/libpod/cmd/podmanV2/parse"
    11  	"github.com/containers/libpod/cmd/podmanV2/registry"
    12  	"github.com/containers/libpod/libpod/define"
    13  	"github.com/containers/libpod/pkg/domain/entities"
    14  	"github.com/containers/libpod/pkg/errorhandling"
    15  	"github.com/containers/libpod/pkg/specgen"
    16  	"github.com/containers/libpod/pkg/util"
    17  	"github.com/pkg/errors"
    18  	"github.com/spf13/cobra"
    19  )
    20  
    21  var (
    22  	podCreateDescription = `After creating the pod, the pod ID is printed to stdout.
    23  
    24    You can then start it at any time with the  podman pod start <pod_id> command. The pod will be created with the initial state 'created'.`
    25  
    26  	createCommand = &cobra.Command{
    27  		Use:   "create",
    28  		Args:  cobra.NoArgs,
    29  		Short: "Create a new empty pod",
    30  		Long:  podCreateDescription,
    31  		RunE:  create,
    32  	}
    33  )
    34  
    35  var (
    36  	createOptions     entities.PodCreateOptions
    37  	labels, labelFile []string
    38  	podIDFile         string
    39  	share             string
    40  )
    41  
    42  func init() {
    43  	registry.Commands = append(registry.Commands, registry.CliCommand{
    44  		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
    45  		Command: createCommand,
    46  		Parent:  podCmd,
    47  	})
    48  	flags := createCommand.Flags()
    49  	flags.SetInterspersed(false)
    50  	flags.AddFlagSet(common.GetNetFlags())
    51  	flags.StringVar(&createOptions.CGroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
    52  	flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
    53  	flags.StringVar(&createOptions.InfraImage, "infra-image", define.DefaultInfraImage, "The image of the infra container to associate with the pod")
    54  	flags.StringVar(&createOptions.InfraCommand, "infra-command", define.DefaultInfraCommand, "The command to run on the infra container when the pod is started")
    55  	flags.StringSliceVar(&labelFile, "label-file", []string{}, "Read in a line delimited file of labels")
    56  	flags.StringSliceVarP(&labels, "label", "l", []string{}, "Set metadata on pod (default [])")
    57  	flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod")
    58  	flags.StringVarP(&createOptions.Hostname, "hostname", "", "", "Set a hostname to the pod")
    59  	flags.StringVar(&podIDFile, "pod-id-file", "", "Write the pod ID to the file")
    60  	flags.StringVar(&share, "share", common.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share")
    61  }
    62  
    63  func create(cmd *cobra.Command, args []string) error {
    64  	var (
    65  		err       error
    66  		podIdFile *os.File
    67  	)
    68  	createOptions.Labels, err = parse.GetAllLabels(labelFile, labels)
    69  	if err != nil {
    70  		return errors.Wrapf(err, "unable to process labels")
    71  	}
    72  
    73  	if !createOptions.Infra && cmd.Flag("share").Changed && share != "none" && share != "" {
    74  		return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container")
    75  	}
    76  	createOptions.Share = strings.Split(share, ",")
    77  	if cmd.Flag("pod-id-file").Changed {
    78  		podIdFile, err = util.OpenExclusiveFile(podIDFile)
    79  		if err != nil && os.IsExist(err) {
    80  			return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", podIDFile)
    81  		}
    82  		if err != nil {
    83  			return errors.Errorf("error opening pod-id-file %s", podIDFile)
    84  		}
    85  		defer errorhandling.CloseQuiet(podIdFile)
    86  		defer errorhandling.SyncQuiet(podIdFile)
    87  	}
    88  
    89  	createOptions.Net, err = common.NetFlagsToNetOptions(cmd)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	netInput, err := cmd.Flags().GetString("network")
    94  	if err != nil {
    95  		return err
    96  	}
    97  	n := specgen.Namespace{}
    98  	switch netInput {
    99  	case "bridge":
   100  		n.NSMode = specgen.Bridge
   101  	case "host":
   102  		n.NSMode = specgen.Host
   103  	case "slip4netns":
   104  		n.NSMode = specgen.Slirp
   105  	default:
   106  		if strings.HasPrefix(netInput, "container:") { //nolint
   107  			split := strings.Split(netInput, ":")
   108  			if len(split) != 2 {
   109  				return errors.Errorf("invalid network paramater: %q", netInput)
   110  			}
   111  			n.NSMode = specgen.FromContainer
   112  			n.Value = split[1]
   113  		} else if strings.HasPrefix(netInput, "ns:") {
   114  			return errors.New("the ns: network option is not supported for pods")
   115  		} else {
   116  			n.NSMode = specgen.Bridge
   117  			createOptions.Net.CNINetworks = strings.Split(netInput, ",")
   118  		}
   119  	}
   120  	if len(createOptions.Net.PublishPorts) > 0 {
   121  		if !createOptions.Infra {
   122  			return errors.Errorf("you must have an infra container to publish port bindings to the host")
   123  		}
   124  	}
   125  
   126  	if !createOptions.Infra {
   127  		if cmd.Flag("infra-command").Changed {
   128  			return errors.New("cannot set infra-command without an infra container")
   129  		}
   130  		createOptions.InfraCommand = ""
   131  		if cmd.Flag("infra-image").Changed {
   132  			return errors.New("cannot set infra-image without an infra container")
   133  		}
   134  		createOptions.InfraImage = ""
   135  		if cmd.Flag("share").Changed {
   136  			return errors.New("cannot set share namespaces without an infra container")
   137  		}
   138  		createOptions.Share = nil
   139  	}
   140  
   141  	response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions)
   142  	if err != nil {
   143  		return err
   144  	}
   145  	fmt.Println(response.Id)
   146  	return nil
   147  }