github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/runlabel.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strings"
     8  
     9  	buildahcli "github.com/containers/buildah/pkg/cli"
    10  	"github.com/containers/image/v5/types"
    11  	"github.com/containers/libpod/cmd/podman/cliconfig"
    12  	"github.com/containers/libpod/cmd/podman/libpodruntime"
    13  	"github.com/containers/libpod/cmd/podman/shared"
    14  	"github.com/containers/libpod/libpod/define"
    15  	"github.com/containers/libpod/libpod/image"
    16  	"github.com/containers/libpod/pkg/util"
    17  	"github.com/containers/libpod/utils"
    18  	"github.com/pkg/errors"
    19  	"github.com/sirupsen/logrus"
    20  	"github.com/spf13/cobra"
    21  )
    22  
    23  var (
    24  	runlabelCommand     cliconfig.RunlabelValues
    25  	runlabelDescription = `
    26  Executes a command as described by a container image label.
    27  `
    28  	_runlabelCommand = &cobra.Command{
    29  		Use:   "runlabel [flags] LABEL IMAGE [ARG...]",
    30  		Short: "Execute the command described by an image label",
    31  		Long:  runlabelDescription,
    32  		RunE: func(cmd *cobra.Command, args []string) error {
    33  			runlabelCommand.InputArgs = args
    34  			runlabelCommand.GlobalFlags = MainGlobalOpts
    35  			runlabelCommand.Remote = remoteclient
    36  			return runlabelCmd(&runlabelCommand)
    37  		},
    38  		Example: `podman container runlabel run imageID
    39    podman container runlabel --pull install imageID arg1 arg2
    40    podman container runlabel --display run myImage`,
    41  	}
    42  )
    43  
    44  func init() {
    45  	runlabelCommand.Command = _runlabelCommand
    46  	runlabelCommand.SetHelpTemplate(HelpTemplate())
    47  	runlabelCommand.SetUsageTemplate(UsageTemplate())
    48  	flags := runlabelCommand.Flags()
    49  	flags.StringVar(&runlabelCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
    50  	flags.BoolVar(&runlabelCommand.Display, "display", false, "Preview the command that the label would run")
    51  	flags.BoolVar(&runlabelCommand.Replace, "replace", false, "Replace existing container with a new one from the image")
    52  	flags.StringVarP(&runlabelCommand.Name, "name", "n", "", "Assign a name to the container")
    53  
    54  	flags.StringVar(&runlabelCommand.Opt1, "opt1", "", "Optional parameter to pass for install")
    55  	flags.StringVar(&runlabelCommand.Opt2, "opt2", "", "Optional parameter to pass for install")
    56  	flags.StringVar(&runlabelCommand.Opt3, "opt3", "", "Optional parameter to pass for install")
    57  	markFlagHidden(flags, "opt1")
    58  	markFlagHidden(flags, "opt2")
    59  	markFlagHidden(flags, "opt3")
    60  	flags.BoolP("pull", "p", false, "Pull the image if it does not exist locally prior to executing the label contents")
    61  	flags.BoolVarP(&runlabelCommand.Quiet, "quiet", "q", false, "Suppress output information when installing images")
    62  	// Disabled flags for the remote client
    63  	if !remote {
    64  		flags.StringVar(&runlabelCommand.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
    65  		flags.StringVar(&runlabelCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
    66  		flags.StringVar(&runlabelCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
    67  		flags.BoolVar(&runlabelCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
    68  
    69  		if err := flags.MarkDeprecated("pull", "podman will pull if not found in local storage"); err != nil {
    70  			logrus.Error("unable to mark pull flag deprecated")
    71  		}
    72  		markFlagHidden(flags, "signature-policy")
    73  	}
    74  }
    75  
    76  // installCmd gets the data from the command line and calls installImage
    77  // to copy an image from a registry to a local machine
    78  func runlabelCmd(c *cliconfig.RunlabelValues) error {
    79  	var (
    80  		imageName      string
    81  		stdErr, stdOut io.Writer
    82  		stdIn          io.Reader
    83  		extraArgs      []string
    84  	)
    85  
    86  	// Evil images could trick into recursively executing the runlabel
    87  	// command.  Avoid this by setting the "PODMAN_RUNLABEL_NESTED" env
    88  	// variable when executing a label first.
    89  	nested := os.Getenv("PODMAN_RUNLABEL_NESTED")
    90  	if nested == "1" {
    91  		return fmt.Errorf("nested runlabel calls: runlabels cannot execute the runlabel command")
    92  	}
    93  
    94  	opts := make(map[string]string)
    95  	runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand)
    96  	if err != nil {
    97  		return errors.Wrapf(err, "could not get runtime")
    98  	}
    99  	defer runtime.DeferredShutdown(false)
   100  
   101  	if c.Authfile != "" {
   102  		if _, err := os.Stat(c.Authfile); err != nil {
   103  			return errors.Wrapf(err, "error getting authfile %s", c.Authfile)
   104  		}
   105  	}
   106  
   107  	args := c.InputArgs
   108  	if len(args) < 2 {
   109  		return errors.Errorf("the runlabel command requires at least 2 arguments: LABEL IMAGE")
   110  	}
   111  	if c.Display && c.Quiet {
   112  		return errors.Errorf("the display and quiet flags cannot be used together.")
   113  	}
   114  
   115  	if len(args) > 2 {
   116  		extraArgs = args[2:]
   117  	}
   118  	label := args[0]
   119  
   120  	runlabelImage := args[1]
   121  
   122  	if c.Flag("opt1").Changed {
   123  		opts["opt1"] = c.Opt1
   124  	}
   125  
   126  	if c.Flag("opt2").Changed {
   127  		opts["opt2"] = c.Opt2
   128  	}
   129  	if c.Flag("opt3").Changed {
   130  		opts["opt3"] = c.Opt3
   131  	}
   132  
   133  	ctx := getContext()
   134  
   135  	stdErr = os.Stderr
   136  	stdOut = os.Stdout
   137  	stdIn = os.Stdin
   138  
   139  	if c.Quiet {
   140  		stdErr = nil
   141  		stdOut = nil
   142  		stdIn = nil
   143  	}
   144  
   145  	dockerRegistryOptions := image.DockerRegistryOptions{
   146  		DockerCertPath: c.CertDir,
   147  	}
   148  	if c.Flag("tls-verify").Changed {
   149  		dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
   150  	}
   151  
   152  	runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, true, c.Creds, dockerRegistryOptions, c.Authfile, c.SignaturePolicy, stdOut)
   153  	if err != nil {
   154  		return err
   155  	}
   156  	if runLabel == "" {
   157  		return errors.Errorf("%s does not have a label of %s", runlabelImage, label)
   158  	}
   159  
   160  	globalOpts := util.GetGlobalOpts(c)
   161  	cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.Name, opts, extraArgs, globalOpts)
   162  	if err != nil {
   163  		return err
   164  	}
   165  	if !c.Quiet {
   166  		fmt.Printf("command: %s\n", strings.Join(append([]string{os.Args[0]}, cmd[1:]...), " "))
   167  		if c.Display {
   168  			return nil
   169  		}
   170  	}
   171  
   172  	// If container already exists && --replace given -- Nuke it
   173  	if c.Replace {
   174  		for i, entry := range cmd {
   175  			if entry == "--name" {
   176  				name := cmd[i+1]
   177  				ctr, err := runtime.LookupContainer(name)
   178  				if err != nil {
   179  					if errors.Cause(err) != define.ErrNoSuchCtr {
   180  						logrus.Debugf("Error occurred searching for container %s: %s", name, err.Error())
   181  						return err
   182  					}
   183  				} else {
   184  					logrus.Debugf("Runlabel --replace option given. Container %s will be deleted. The new container will be named %s", ctr.ID(), name)
   185  					if err := runtime.RemoveContainer(ctx, ctr, true, false); err != nil {
   186  						return err
   187  					}
   188  				}
   189  				break
   190  			}
   191  		}
   192  	}
   193  
   194  	return utils.ExecCmdWithStdStreams(stdIn, stdOut, stdErr, env, cmd[0], cmd[1:]...)
   195  }