diff options
Diffstat (limited to 'cmd/podman')
28 files changed, 366 insertions, 76 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 37d6d3908..e7ad921da 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -258,6 +258,20 @@ type MountValues struct { Latest bool } +type NetworkListValues struct { + PodmanCommand + Filter []string + Quiet bool +} + +type NetworkRmValues struct { + PodmanCommand +} + +type NetworkInspectValues struct { + PodmanCommand +} + type PauseValues struct { PodmanCommand All bool @@ -286,6 +300,7 @@ type PodCreateValues struct { LabelFile []string Labels []string Name string + Hostname string PodIDFile string Publish []string Share string @@ -437,6 +452,7 @@ type RestoreValues struct { Import string Name string IgnoreRootfs bool + IgnoreStaticIP bool } type RmValues struct { diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 1e9092bd6..32478bb51 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -388,6 +388,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "publish-all", "P", false, "Publish all exposed ports to random ports on the host interface", ) + createFlags.String( + "pull", "missing", + `Pull image before creating ("always"|"missing"|"never") (default "missing")`, + ) createFlags.BoolP( "quiet", "q", false, "Suppress output information when pulling images", diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go index bee7d2199..ad7253ac0 100644 --- a/cmd/podman/cp.go +++ b/cmd/podman/cp.go @@ -140,7 +140,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin if err != nil { return errors.Wrapf(err, "error getting IDMappingOptions") } - containerOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)} + destOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)} hostUID, hostGID, err := util.GetHostIDs(convertIDMap(idMappingOpts.UIDMap), convertIDMap(idMappingOpts.GIDMap), user.UID, user.GID) if err != nil { return err @@ -183,6 +183,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin destPath = cleanedPath } } else { + destOwner = idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()} if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol { path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, srcPath) if err != nil { @@ -230,7 +231,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin src = os.Stdin.Name() extract = true } - err := copy(src, destPath, dest, idMappingOpts, &containerOwner, extract, isFromHostToCtr) + err := copy(src, destPath, dest, idMappingOpts, &destOwner, extract, isFromHostToCtr) if lastError != nil { logrus.Error(lastError) } diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index ee9e57966..a133549ea 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -15,25 +15,30 @@ import ( // GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers func GetRuntimeMigrate(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, false, true, false) + return getRuntime(ctx, c, false, true, false, true) +} + +// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify +func GetRuntimeDisableFDs(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { + return getRuntime(ctx, c, false, false, false, false) } // GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber func GetRuntimeRenumber(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, true, false, false) + return getRuntime(ctx, c, true, false, false, true) } // GetRuntime generates a new libpod runtime configured by command line options func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, false, false, false) + return getRuntime(ctx, c, false, false, false, true) } // GetRuntimeNoStore generates a new libpod runtime configured by command line options func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { - return getRuntime(ctx, c, false, false, true) + return getRuntime(ctx, c, false, false, true, true) } -func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore bool) (*libpod.Runtime, error) { +func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore, withFDS bool) (*libpod.Runtime, error) { options := []libpod.RuntimeOption{} storageOpts := storage.StoreOptions{} storageSet := false @@ -165,6 +170,10 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra infraCommand, _ := c.Flags().GetString("infra-command") options = append(options, libpod.WithDefaultInfraCommand(infraCommand)) } + + if withFDS { + options = append(options, libpod.WithEnableSDNotify()) + } if c.Flags().Changed("config") { return libpod.NewRuntimeFromConfig(ctx, c.GlobalFlags.Config, options...) } diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 1b54c9458..dc44a9110 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -101,7 +101,7 @@ func initConfig() { } func before(cmd *cobra.Command, args []string) error { - if err := libpod.SetXdgRuntimeDir(); err != nil { + if err := libpod.SetXdgDirs(); err != nil { logrus.Errorf(err.Error()) os.Exit(1) } diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index 5c8b2b1ff..587c8260f 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -1,4 +1,5 @@ // +build !remoteclient +// +build linux package main @@ -122,6 +123,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") { return nil } + podmanCmd := cliconfig.PodmanCommand{ Command: cmd, InputArgs: args, diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go index ecbb44d5a..a005e925c 100644 --- a/cmd/podman/main_remote.go +++ b/cmd/podman/main_remote.go @@ -3,13 +3,8 @@ package main import ( - "fmt" - "os" "os/user" - "path/filepath" - "github.com/docker/docker/pkg/homedir" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -30,39 +25,6 @@ func init() { rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console") } -func setSyslog() error { - // Log to file if not using syslog - homeDir := homedir.Get() - path := filepath.Join(homeDir, ".config", "containers") - - if _, err := os.Stat(path); os.IsNotExist(err) { - if err := os.MkdirAll(path, 0750); err != nil { - fmt.Fprintf(os.Stderr, "%v", err) - return err - } - } - - // Update path to include file name - path = filepath.Join(path, "podman.log") - - // Create the log file if doesn't exist. And append to it if it already exists. - file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0640) - if err != nil { - // Cannot open log file. Logging to stderr - fmt.Fprintf(os.Stderr, "%v", err) - return err - } else { - formatter := new(logrus.TextFormatter) - formatter.FullTimestamp = true - logrus.SetFormatter(formatter) - logrus.SetOutput(file) - } - - // Note this message is only logged if --log-level >= Info! - logrus.Infof("Logging level set to %s", logrus.GetLevel().String()) - return nil -} - func profileOn(cmd *cobra.Command) error { return nil } diff --git a/cmd/podman/main_remote_supported.go b/cmd/podman/main_remote_supported.go new file mode 100644 index 000000000..bb567c273 --- /dev/null +++ b/cmd/podman/main_remote_supported.go @@ -0,0 +1,57 @@ +// +build remoteclient +// +build linux darwin + +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/containers/libpod/pkg/util" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +func setSyslog() error { + var err error + cfgHomeDir := os.Getenv("XDG_CONFIG_HOME") + if cfgHomeDir == "" { + if cfgHomeDir, err = util.GetRootlessConfigHomeDir(); err != nil { + return err + } + if err = os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil { + return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME") + } + } + path := filepath.Join(cfgHomeDir, "containers") + + // Log to file if not using syslog + + if _, err := os.Stat(path); os.IsNotExist(err) { + if err := os.MkdirAll(path, 0750); err != nil { + fmt.Fprintf(os.Stderr, "%v", err) + return err + } + } + + // Update path to include file name + path = filepath.Join(path, "podman.log") + + // Create the log file if doesn't exist. And append to it if it already exists. + file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0640) + if err != nil { + // Cannot open log file. Logging to stderr + fmt.Fprintf(os.Stderr, "%v", err) + return err + } else { + formatter := new(logrus.TextFormatter) + formatter.FullTimestamp = true + logrus.SetFormatter(formatter) + logrus.SetOutput(file) + } + + // Note this message is only logged if --log-level >= Info! + logrus.Infof("Logging level set to %s", logrus.GetLevel().String()) + return nil +} diff --git a/cmd/podman/main_remote_windows.go b/cmd/podman/main_remote_windows.go new file mode 100644 index 000000000..0ef1370ce --- /dev/null +++ b/cmd/podman/main_remote_windows.go @@ -0,0 +1,7 @@ +// +build remoteclient,windows + +package main + +func setSyslog() error { + return nil +} diff --git a/cmd/podman/network.go b/cmd/podman/network.go new file mode 100644 index 000000000..83a5e71ab --- /dev/null +++ b/cmd/podman/network.go @@ -0,0 +1,31 @@ +//+build !remoteclient + +package main + +import ( + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/spf13/cobra" +) + +var networkcheckDescription = "Manage networks" +var networkcheckCommand = cliconfig.PodmanCommand{ + Command: &cobra.Command{ + Use: "network", + Short: "Manage Networks", + Long: networkcheckDescription, + RunE: commandRunE(), + }, +} + +// Commands that are universally implemented +var networkcheckCommands = []*cobra.Command{ + _networkinspectCommand, + _networklistCommand, + _networkrmCommand, +} + +func init() { + networkcheckCommand.AddCommand(networkcheckCommands...) + networkcheckCommand.SetUsageTemplate(UsageTemplate()) + rootCmd.AddCommand(networkcheckCommand.Command) +} diff --git a/cmd/podman/network_inspect.go b/cmd/podman/network_inspect.go new file mode 100644 index 000000000..38aaf6ba4 --- /dev/null +++ b/cmd/podman/network_inspect.go @@ -0,0 +1,48 @@ +// +build !remoteclient + +package main + +import ( + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/containers/libpod/pkg/rootless" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + networkinspectCommand cliconfig.NetworkInspectValues + networkinspectDescription = `Inspect network` + _networkinspectCommand = &cobra.Command{ + Use: "inspect NETWORK [NETWORK...] [flags] ", + Short: "network inspect", + Long: networkinspectDescription, + RunE: func(cmd *cobra.Command, args []string) error { + networkinspectCommand.InputArgs = args + networkinspectCommand.GlobalFlags = MainGlobalOpts + networkinspectCommand.Remote = remoteclient + return networkinspectCmd(&networkinspectCommand) + }, + Example: `podman network inspect podman`, + } +) + +func init() { + networkinspectCommand.Command = _networkinspectCommand + networkinspectCommand.SetHelpTemplate(HelpTemplate()) + networkinspectCommand.SetUsageTemplate(UsageTemplate()) +} + +func networkinspectCmd(c *cliconfig.NetworkInspectValues) error { + if rootless.IsRootless() && !remoteclient { + return errors.New("network inspect is not supported for rootless mode") + } + if len(c.InputArgs) < 1 { + return errors.Errorf("at least one network name is required") + } + runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand) + if err != nil { + return err + } + return runtime.NetworkInspect(c) +} diff --git a/cmd/podman/network_list.go b/cmd/podman/network_list.go new file mode 100644 index 000000000..16edf743b --- /dev/null +++ b/cmd/podman/network_list.go @@ -0,0 +1,53 @@ +// +build !remoteclient + +package main + +import ( + "errors" + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/containers/libpod/pkg/rootless" + "github.com/spf13/cobra" +) + +var ( + networklistCommand cliconfig.NetworkListValues + networklistDescription = `List networks` + _networklistCommand = &cobra.Command{ + Use: "ls", + Args: noSubArgs, + Short: "network list", + Long: networklistDescription, + RunE: func(cmd *cobra.Command, args []string) error { + networklistCommand.InputArgs = args + networklistCommand.GlobalFlags = MainGlobalOpts + networklistCommand.Remote = remoteclient + return networklistCmd(&networklistCommand) + }, + Example: `podman network list`, + } +) + +func init() { + networklistCommand.Command = _networklistCommand + networklistCommand.SetHelpTemplate(HelpTemplate()) + networklistCommand.SetUsageTemplate(UsageTemplate()) + flags := networklistCommand.Flags() + // TODO enable filters based on something + //flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers") + flags.BoolVarP(&networklistCommand.Quiet, "quiet", "q", false, "display only names") +} + +func networklistCmd(c *cliconfig.NetworkListValues) error { + if rootless.IsRootless() && !remoteclient { + return errors.New("network list is not supported for rootless mode") + } + if len(c.InputArgs) > 0 { + return errors.New("network list takes no arguments") + } + runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand) + if err != nil { + return err + } + return runtime.NetworkList(c) +} diff --git a/cmd/podman/network_rm.go b/cmd/podman/network_rm.go new file mode 100644 index 000000000..50bd48cea --- /dev/null +++ b/cmd/podman/network_rm.go @@ -0,0 +1,48 @@ +// +build !remoteclient + +package main + +import ( + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/containers/libpod/pkg/rootless" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + networkrmCommand cliconfig.NetworkRmValues + networkrmDescription = `Remove networks` + _networkrmCommand = &cobra.Command{ + Use: "rm [flags] NETWORK [NETWORK...]", + Short: "network rm", + Long: networkrmDescription, + RunE: func(cmd *cobra.Command, args []string) error { + networkrmCommand.InputArgs = args + networkrmCommand.GlobalFlags = MainGlobalOpts + networkrmCommand.Remote = remoteclient + return networkrmCmd(&networkrmCommand) + }, + Example: `podman network rm podman`, + } +) + +func init() { + networkrmCommand.Command = _networkrmCommand + networkrmCommand.SetHelpTemplate(HelpTemplate()) + networkrmCommand.SetUsageTemplate(UsageTemplate()) +} + +func networkrmCmd(c *cliconfig.NetworkRmValues) error { + if rootless.IsRootless() && !remoteclient { + return errors.New("network rm is not supported for rootless mode") + } + if len(c.InputArgs) < 1 { + return errors.Errorf("at least one network name is required") + } + runtime, err := adapter.GetRuntimeNoStore(getContext(), &c.PodmanCommand) + if err != nil { + return err + } + return runtime.NetworkRemove(c) +} diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go index b6154b4db..ad3c00aa8 100644 --- a/cmd/podman/pod_create.go +++ b/cmd/podman/pod_create.go @@ -52,6 +52,7 @@ func init() { flags.StringSliceVar(&podCreateCommand.LabelFile, "label-file", []string{}, "Read in a line delimited file of labels") flags.StringSliceVarP(&podCreateCommand.Labels, "label", "l", []string{}, "Set metadata on pod (default [])") flags.StringVarP(&podCreateCommand.Name, "name", "n", "", "Assign a name to the pod") + flags.StringVarP(&podCreateCommand.Hostname, "hostname", "", "", "Set a hostname to the pod") flags.StringVar(&podCreateCommand.PodIDFile, "pod-id-file", "", "Write the pod ID to the file") flags.StringSliceVarP(&podCreateCommand.Publish, "publish", "p", []string{}, "Publish a container's port, or a range of ports, to the host (default [])") flags.StringVar(&podCreateCommand.Share, "share", shared.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share") @@ -78,7 +79,7 @@ func podCreateCmd(c *cliconfig.PodCreateValues) error { if !c.Infra && c.Flag("share").Changed && c.Share != "none" && c.Share != "" { return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container") } - if c.Flag("pod-id-file").Changed && os.Geteuid() == 0 { + if c.Flag("pod-id-file").Changed { podIdFile, err = util.OpenExclusiveFile(c.PodIDFile) if err != nil && os.IsExist(err) { return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", c.PodIDFile) diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go index 46cacc026..2f1ebd3ac 100644 --- a/cmd/podman/pod_stats.go +++ b/cmd/podman/pod_stats.go @@ -15,6 +15,8 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -53,9 +55,14 @@ func init() { } func podStatsCmd(c *cliconfig.PodStatsValues) error { - - if os.Geteuid() != 0 { - return errors.New("stats is not supported in rootless mode") + if rootless.IsRootless() { + unified, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return err + } + if !unified { + return errors.New("stats is not supported in rootless mode without cgroups v2") + } } format := c.Format diff --git a/cmd/podman/port.go b/cmd/podman/port.go index 5753c8e56..4e1f9642c 100644 --- a/cmd/podman/port.go +++ b/cmd/podman/port.go @@ -48,8 +48,8 @@ func init() { func portCmd(c *cliconfig.PortValues) error { var ( - userProto, containerName string - userPort int + userProto string + userPort int ) args := c.InputArgs @@ -106,6 +106,7 @@ func portCmd(c *cliconfig.PortValues) error { if err != nil { return err } + var found bool // Iterate mappings for _, v := range portmappings { hostIP := v.HostIP @@ -125,12 +126,14 @@ func portCmd(c *cliconfig.PortValues) error { if v.ContainerPort == int32(userPort) { if userProto == "" || userProto == v.Protocol { fmt.Printf("%s:%d\n", hostIP, v.HostPort) + found = true break } - } else { - return errors.Errorf("No public port '%d' published for %s", userPort, containerName) } } + if !found && port != "" { + return errors.Errorf("failed to find published port '%d'", userPort) + } } return nil diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go index 0eee51e79..53f133929 100644 --- a/cmd/podman/pull.go +++ b/cmd/podman/pull.go @@ -150,7 +150,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) { // See https://bugzilla.redhat.com/show_bug.cgi?id=1701922 for background // information. if !c.Bool("all-tags") { - newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil) + newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) if err != nil { return errors.Wrapf(err, "error pulling image %q", imgArg) } @@ -188,7 +188,7 @@ func pullCmd(c *cliconfig.PullValues) (retError error) { var foundIDs []string foundImage := true for _, name := range names { - newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, true, nil) + newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways) if err != nil { logrus.Errorf("error pulling image %q", name) foundImage = false diff --git a/cmd/podman/remoteclientconfig/config_linux.go b/cmd/podman/remoteclientconfig/config_linux.go index b94941381..5d27f19f2 100644 --- a/cmd/podman/remoteclientconfig/config_linux.go +++ b/cmd/podman/remoteclientconfig/config_linux.go @@ -1,12 +1,17 @@ package remoteclientconfig import ( + "os" "path/filepath" "github.com/docker/docker/pkg/homedir" ) func getConfigFilePath() string { - homeDir := homedir.Get() - return filepath.Join(homeDir, ".config", "containers", remoteConfigFileName) + path := os.Getenv("XDG_CONFIG_HOME") + if path == "" { + homeDir := homedir.Get() + path = filepath.Join(homeDir, ".config") + } + return filepath.Join(path, "containers", remoteConfigFileName) } diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go index 3ae141d41..90d0b2dc4 100644 --- a/cmd/podman/restore.go +++ b/cmd/podman/restore.go @@ -46,6 +46,7 @@ func init() { flags.StringVarP(&restoreCommand.Import, "import", "i", "", "Restore from exported checkpoint archive (tar.gz)") flags.StringVarP(&restoreCommand.Name, "name", "n", "", "Specify new name for container restored from exported checkpoint (only works with --import)") flags.BoolVar(&restoreCommand.IgnoreRootfs, "ignore-rootfs", false, "Do not apply root file-system changes when importing from exported checkpoint") + flags.BoolVar(&restoreCommand.IgnoreStaticIP, "ignore-static-ip", false, "Ignore IP address set via --static-ip") markFlagHiddenForRemoteClient("latest", flags) } diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index 7f53f5ec9..5122d37d1 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -660,7 +660,7 @@ func formatGroup(key string, start, last int32) string { } // portsToString converts the ports used to a string of the from "port1, port2" -// and also groups continuous list of ports in readable format. +// and also groups a continuous list of ports into a readable format. func portsToString(ports []ocicni.PortMapping) string { type portGroup struct { first int32 @@ -732,7 +732,7 @@ func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtim registryCreds = creds } dockerRegistryOptions.DockerRegistryCreds = registryCreds - newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, signaturePolicyPath, authfile, output, &dockerRegistryOptions, image.SigningOptions{}, false, &label) + newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, signaturePolicyPath, authfile, output, &dockerRegistryOptions, image.SigningOptions{}, &label, util.PullImageMissing) } else { newImage, err = runtime.ImageRuntime().NewFromLocal(runlabelImage) } @@ -750,7 +750,7 @@ func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtim return runLabel, imageName, err } -// GenerateRunlabelCommand generates the command that will eventually be execucted by podman. +// GenerateRunlabelCommand generates the command that will eventually be execucted by Podman. func GenerateRunlabelCommand(runLabel, imageName, name string, opts map[string]string, extraArgs []string, globalOpts string) ([]string, []string, error) { // If no name is provided, we use the image's basename instead. if name == "" { @@ -809,7 +809,7 @@ func envSliceToMap(env []string) map[string]string { return m } -// GenerateKube generates kubernetes yaml based on a pod or container +// GenerateKube generates kubernetes yaml based on a pod or container. func GenerateKube(name string, service bool, r *libpod.Runtime) (*v1.Pod, *v1.Service, error) { var ( pod *libpod.Pod diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 4de68e4bc..094330e24 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -55,7 +55,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. rootfs = c.InputArgs[0] } - if c.IsSet("cidfile") && os.Geteuid() == 0 { + if c.IsSet("cidfile") { cidFile, err = util.OpenExclusiveFile(c.String("cidfile")) if err != nil && os.IsExist(err) { return nil, nil, errors.Errorf("container id file exists. Ensure another container is not using it or delete %s", c.String("cidfile")) @@ -70,8 +70,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. imageName := "" var data *inspect.ImageData = nil - // Set the storage if we are running as euid == 0 and there is no rootfs specified - if rootfs == "" && os.Geteuid() == 0 { + // Set the storage if there is no rootfs specified + if rootfs == "" { var writer io.Writer if !c.Bool("quiet") { writer = os.Stderr @@ -83,7 +83,13 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. } else { return nil, nil, errors.Errorf("error, no input arguments were provided") } - newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, GetAuthFile(""), writer, nil, image.SigningOptions{}, false, nil) + + pullType, err := util.ValidatePullType(c.String("pull")) + if err != nil { + return nil, nil, err + } + + newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, GetAuthFile(c.String("authfile")), writer, nil, image.SigningOptions{}, nil, pullType) if err != nil { return nil, nil, err } @@ -588,6 +594,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. workDir = data.Config.WorkingDir } + userCommand := []string{} entrypoint := configureEntrypoint(c, data) // Build the command // If we have an entry point, it goes first @@ -597,9 +604,11 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. if len(inputCommand) > 0 { // User command overrides data CMD command = append(command, inputCommand...) + userCommand = append(userCommand, inputCommand...) } else if data != nil && len(data.Config.Cmd) > 0 && !c.IsSet("entrypoint") { // If not user command, add CMD command = append(command, data.Config.Cmd...) + userCommand = append(userCommand, data.Config.Cmd...) } if data != nil && len(command) == 0 { @@ -624,8 +633,16 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'") } + // Check for explicit dns-search domain of '' + if c.Changed("dns-search") && len(c.StringSlice("dns-search")) == 0 { + return nil, errors.Errorf("'' is not a valid domain") + } + // Validate domains are good for _, dom := range c.StringSlice("dns-search") { + if dom == "." { + continue + } if _, err := parse.ValidateDomain(dom); err != nil { return nil, err } @@ -680,6 +697,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Cgroupns: c.String("cgroupns"), CgroupParent: c.String("cgroup-parent"), Command: command, + UserCommand: userCommand, Detach: c.Bool("detach"), Devices: c.StringSlice("device"), DNSOpt: c.StringSlice("dns-opt"), diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go index 4062ac48a..c6c32f8a9 100644 --- a/cmd/podman/shared/intermediate.go +++ b/cmd/podman/shared/intermediate.go @@ -366,6 +366,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes m["add-host"] = newCRStringSlice(c, "add-host") m["annotation"] = newCRStringSlice(c, "annotation") m["attach"] = newCRStringSlice(c, "attach") + m["authfile"] = newCRString(c, "authfile") m["blkio-weight"] = newCRString(c, "blkio-weight") m["blkio-weight-device"] = newCRStringSlice(c, "blkio-weight-device") m["cap-add"] = newCRStringSlice(c, "cap-add") @@ -435,6 +436,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes m["privileged"] = newCRBool(c, "privileged") m["publish"] = newCRStringSlice(c, "publish") m["publish-all"] = newCRBool(c, "publish-all") + m["pull"] = newCRString(c, "pull") m["quiet"] = newCRBool(c, "quiet") m["read-only"] = newCRBool(c, "read-only") m["read-only-tmpfs"] = newCRBool(c, "read-only-tmpfs") diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go index 4742d4909..9dbf83950 100644 --- a/cmd/podman/shared/intermediate_varlink.go +++ b/cmd/podman/shared/intermediate_varlink.go @@ -137,6 +137,7 @@ func (g GenericCLIResults) MakeVarlink() iopodman.Create { Privileged: BoolToPtr(g.Find("privileged")), Publish: StringSliceToPtr(g.Find("publish")), PublishAll: BoolToPtr(g.Find("publish-all")), + Pull: StringToPtr(g.Find("pull")), Quiet: BoolToPtr(g.Find("quiet")), Readonly: BoolToPtr(g.Find("read-only")), Readonlytmpfs: BoolToPtr(g.Find("read-only-tmpfs")), @@ -393,6 +394,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { m["privileged"] = boolFromVarlink(opts.Privileged, "privileged", false) m["publish"] = stringSliceFromVarlink(opts.Publish, "publish", nil) m["publish-all"] = boolFromVarlink(opts.PublishAll, "publish-all", false) + m["pull"] = stringFromVarlink(opts.Pull, "missing", nil) m["quiet"] = boolFromVarlink(opts.Quiet, "quiet", false) m["read-only"] = boolFromVarlink(opts.Readonly, "read-only", false) m["read-only-tmpfs"] = boolFromVarlink(opts.Readonlytmpfs, "read-only-tmpfs", true) diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go index 1333cf441..de289047a 100644 --- a/cmd/podman/sign.go +++ b/cmd/podman/sign.go @@ -15,6 +15,7 @@ import ( "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/trust" + "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -113,7 +114,7 @@ func signCmd(c *cliconfig.SignValues) error { if err != nil { return err } - newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, false, nil) + newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing) if err != nil { return errors.Wrapf(err, "error pulling image %s", signimage) } diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go index 3accae1b6..2f696445e 100644 --- a/cmd/podman/stats.go +++ b/cmd/podman/stats.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "os" "reflect" "strings" "time" @@ -13,6 +12,8 @@ import ( "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/docker/go-units" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -66,8 +67,14 @@ func init() { } func statsCmd(c *cliconfig.StatsValues) error { - if os.Geteuid() != 0 { - return errors.New("stats is not supported for rootless containers") + if rootless.IsRootless() { + unified, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return err + } + if !unified { + return errors.New("stats is not supported in rootless mode without cgroups v2") + } } all := c.All diff --git a/cmd/podman/system_df.go b/cmd/podman/system_df.go index 6b9824a79..44582a802 100644 --- a/cmd/podman/system_df.go +++ b/cmd/podman/system_df.go @@ -460,11 +460,11 @@ func getImageVerboseDiskUsage(ctx context.Context, images []*image.Image, images } var repo string var tag string - if len(img.Names()) == 0 { - repo = "<none>" - tag = "<none>" + var repotags []string + if len(img.Names()) != 0 { + repotags = []string{img.Names()[0]} } - repopairs, err := image.ReposToMap([]string{img.Names()[0]}) + repopairs, err := image.ReposToMap(repotags) if err != nil { logrus.Errorf("error finding tag/digest for %s", img.ID()) } diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go index 92315cd6b..5f89534be 100644 --- a/cmd/podman/varlink.go +++ b/cmd/podman/varlink.go @@ -79,7 +79,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error { timeout := time.Duration(c.Timeout) * time.Millisecond // Create a single runtime for varlink - runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand) + runtime, err := libpodruntime.GetRuntimeDisableFDs(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 73f4d1609..08a69275e 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -227,7 +227,8 @@ type InfoHost ( hostname: string, kernel: string, os: string, - uptime: string + uptime: string, + eventlogger: string ) # InfoGraphStatus describes the detailed status of the storage driver @@ -345,6 +346,7 @@ type Create ( privileged: ?bool, publish: ?[]string, publishAll: ?bool, + pull: ?string, quiet: ?bool, readonly: ?bool, readonlytmpfs: ?bool, @@ -1275,3 +1277,6 @@ error WantsMoreRequired (reason: string) # Container is already stopped error ErrCtrStopped (id: string) + +# This function requires CGroupsV2 to run in rootless mode. +error ErrRequiresCgroupsV2ForRootless(reason: string)
\ No newline at end of file |