diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/build.go | 3 | ||||
-rw-r--r-- | cmd/podman/cliconfig/config.go | 18 | ||||
-rw-r--r-- | cmd/podman/common.go | 8 | ||||
-rw-r--r-- | cmd/podman/cp.go | 19 | ||||
-rw-r--r-- | cmd/podman/generate_systemd.go | 1 | ||||
-rw-r--r-- | cmd/podman/image.go | 1 | ||||
-rw-r--r-- | cmd/podman/kill.go | 4 | ||||
-rw-r--r-- | cmd/podman/main.go | 1 | ||||
-rw-r--r-- | cmd/podman/main_local.go | 6 | ||||
-rw-r--r-- | cmd/podman/play_kube.go | 3 | ||||
-rw-r--r-- | cmd/podman/pod_kill.go | 4 | ||||
-rw-r--r-- | cmd/podman/ps.go | 17 | ||||
-rw-r--r-- | cmd/podman/rmi.go | 11 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 33 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 9 | ||||
-rw-r--r-- | cmd/podman/shared/create_cli.go | 14 | ||||
-rw-r--r-- | cmd/podman/tree.go | 2 | ||||
-rw-r--r-- | cmd/podman/untag.go | 67 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 26 | ||||
-rw-r--r-- | cmd/service/main.go | 55 |
20 files changed, 233 insertions, 69 deletions
diff --git a/cmd/podman/build.go b/cmd/podman/build.go index fbf85fc97..08d3edaa3 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -375,7 +375,8 @@ func buildCmd(c *cliconfig.BuildValues) error { }, Target: c.Target, } - return runtime.Build(getContext(), c, options, containerfiles) + _, _, err = runtime.Build(getContext(), c, options, containerfiles) + return err } // useLayers returns false if BUILDAH_LAYERS is set to "0" or "false" diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index e81756808..b261599e6 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -163,6 +163,7 @@ type GenerateKubeValues struct { type GenerateSystemdValues struct { PodmanCommand Name bool + New bool Files bool RestartPolicy string StopTimeout int @@ -308,12 +309,13 @@ type HealthCheckValues struct { type KubePlayValues struct { PodmanCommand - Authfile string - CertDir string - Creds string - Quiet bool - SignaturePolicy string - TlsVerify bool + Authfile string + CertDir string + Creds string + Quiet bool + SignaturePolicy string + TlsVerify bool + SeccompProfileRoot string } type PodCreateValues struct { @@ -680,3 +682,7 @@ type SystemDfValues struct { Verbose bool Format string } + +type UntagValues struct { + PodmanCommand +} diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 69365201e..dc7590590 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -308,7 +308,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.String( "image-volume", cliconfig.DefaultImageVolume, - "Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore'", + `Tells podman how to handle the builtin image volumes ("bind"|"tmpfs"|"ignore")`, ) createFlags.Bool( "init", false, @@ -431,7 +431,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.String( "pull", "missing", - `Pull image before creating ("always"|"missing"|"never") (default "missing")`, + `Pull image before creating ("always"|"missing"|"never")`, ) createFlags.BoolP( "quiet", "q", false, @@ -447,7 +447,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.String( "restart", "", - "Restart policy to apply when a container exits", + `Restart policy to apply when a container exits ("always"|"no"|"on-failure")`, ) createFlags.Bool( "rm", false, @@ -492,7 +492,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.String( "systemd", "true", - `Run container in systemd mode ("true"|"false"|"always" (default "true")`, + `Run container in systemd mode ("true"|"false"|"always")`, ) createFlags.StringArray( "tmpfs", []string{}, diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go index 762d70252..ea97752a3 100644 --- a/cmd/podman/cp.go +++ b/cmd/podman/cp.go @@ -101,18 +101,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin } }() - // We can't pause rootless containers. - if pause && rootless.IsRootless() { - state, err := ctr.State() - if err != nil { - return err - } - if state == define.ContainerStateRunning { - return errors.Errorf("cannot copy into running rootless container with pause set - pass --pause=false to force copying") - } - } - - if pause && !rootless.IsRootless() { + if pause { if err := ctr.Pause(); err != nil { // An invalid state error is fine. // The container isn't running or is already paused. @@ -222,7 +211,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin srcPath = os.Stdin.Name() extract = true } - return copy(srcPath, destPath, dest, idMappingOpts, &destOwner, extract, isFromHostToCtr) + return copy(srcPath, destPath, src, dest, idMappingOpts, &destOwner, extract, isFromHostToCtr) } func getUser(mountPoint string, userspec string) (specs.User, error) { @@ -276,8 +265,8 @@ func getPathInfo(path string) (string, os.FileInfo, error) { return path, srcfi, nil } -func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair, extract, isFromHostToCtr bool) error { - srcPath, err := evalSymlinks(src) +func copy(srcPath, destPath, src, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair, extract, isFromHostToCtr bool) error { + srcPath, err := evalSymlinks(srcPath) if err != nil { return errors.Wrapf(err, "error evaluating symlinks %q", srcPath) } diff --git a/cmd/podman/generate_systemd.go b/cmd/podman/generate_systemd.go index aa202a68d..a9775f9cb 100644 --- a/cmd/podman/generate_systemd.go +++ b/cmd/podman/generate_systemd.go @@ -45,6 +45,7 @@ func init() { } flags.IntVarP(&containerSystemdCommand.StopTimeout, "timeout", "t", -1, "stop timeout override") flags.StringVar(&containerSystemdCommand.RestartPolicy, "restart-policy", "on-failure", "applicable systemd restart-policy") + flags.BoolVarP(&containerSystemdCommand.New, "new", "", false, "create a new container instead of starting an existing one") } func generateSystemdCmd(c *cliconfig.GenerateSystemdValues) error { diff --git a/cmd/podman/image.go b/cmd/podman/image.go index 66c141686..ce576ff4b 100644 --- a/cmd/podman/image.go +++ b/cmd/podman/image.go @@ -74,6 +74,7 @@ var imageSubCommands = []*cobra.Command{ _saveCommand, _tagCommand, _treeCommand, + _untagCommand, } func init() { diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go index aba2008ca..a10546ea9 100644 --- a/cmd/podman/kill.go +++ b/cmd/podman/kill.go @@ -3,7 +3,7 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/pkg/adapter" - "github.com/docker/docker/pkg/signal" + "github.com/containers/libpod/pkg/util" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -54,7 +54,7 @@ func killCmd(c *cliconfig.KillValues) error { // Check if the signalString provided by the user is valid // Invalid signals will return err - killSignal, err := signal.ParseSignal(c.Signal) + killSignal, err := util.ParseSignal(c.Signal) if err != nil { return err } diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 344170ddd..c727eea85 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -68,6 +68,7 @@ var mainCommands = []*cobra.Command{ imageCommand.Command, _startCommand, systemCommand.Command, + _untagCommand, } var rootCmd = &cobra.Command{ diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index bc46e4652..e5b87754b 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -33,7 +33,7 @@ const remote = false func init() { cgroupManager := define.SystemdCgroupsManager - cgroupHelp := "Cgroup manager to use (cgroupfs or systemd)" + cgroupHelp := `Cgroup manager to use ("cgroupfs"|"systemd")` cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() if rootless.IsRootless() && !cgroupv2 { cgroupManager = "" @@ -50,12 +50,12 @@ func init() { if err := rootCmd.PersistentFlags().MarkHidden("default-mounts-file"); err != nil { logrus.Error("unable to mark default-mounts-file flag as hidden") } - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", "", "Events backend to use") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", "", `Events backend to use ("file"|"journald"|"none")`) // Override default --help information of `--help` global flag var dummyHelp bool rootCmd.PersistentFlags().BoolVar(&dummyHelp, "help", false, "Help for podman") rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error, fatal or panic") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", `Log messages above specified level ("debug"|"info"|"warn"|"error"|"fatal"|"panic")`) rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations") if err := rootCmd.PersistentFlags().MarkHidden("max-workers"); err != nil { logrus.Error("unable to mark max-workers flag as hidden") diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index fc9f2d5b6..2028d2ef4 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -28,6 +28,8 @@ var ( }, Example: `podman play kube demo.yml`, } + // https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/ + defaultSeccompRoot = "/var/lib/kubelet/seccomp" ) func init() { @@ -46,6 +48,7 @@ func init() { flags.StringVar(&playKubeCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") + flags.StringVar(&playKubeCommand.SeccompProfileRoot, "seccomp-profile-root", defaultSeccompRoot, "Directory path for seccomp profiles") markFlagHidden(flags, "signature-policy") } } diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go index 064946f72..9f696073d 100644 --- a/cmd/podman/pod_kill.go +++ b/cmd/podman/pod_kill.go @@ -6,7 +6,7 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/pkg/adapter" - "github.com/docker/docker/pkg/signal" + "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -60,7 +60,7 @@ func podKillCmd(c *cliconfig.PodKillValues) error { if c.Signal != "" { // Check if the signalString provided by the user is valid // Invalid signals will return err - sysSignal, err := signal.ParseSignal(c.Signal) + sysSignal, err := util.ParseSignal(c.Signal) if err != nil { return err } diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index 9fad0ea65..d2c5e19e2 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -31,6 +31,7 @@ const ( hsize = "SIZE" hinfra = "IS INFRA" //nolint hpod = "POD" + hpodname = "POD NAME" nspid = "PID" nscgroup = "CGROUPNS" nsipc = "IPC" @@ -204,11 +205,15 @@ func checkFlagsPassed(c *cliconfig.PsValues) error { if c.Last >= 0 && c.Latest { return errors.Errorf("last and latest are mutually exclusive") } - // Quiet conflicts with size, namespace, and format with a Go template + // Quiet conflicts with size and namespace and is overridden by a Go + // template. if c.Quiet { - if c.Size || c.Namespace || (c.Flag("format").Changed && - c.Format != formats.JSONString) { - return errors.Errorf("quiet conflicts with size, namespace, and format with go template") + if c.Size || c.Namespace { + return errors.Errorf("quiet conflicts with size and namespace") + } + if c.Flag("format").Changed && c.Format != formats.JSONString { + // Quiet is overridden by Go template output. + c.Quiet = false } } // Size and namespace conflict with each other @@ -351,7 +356,7 @@ func psDisplay(c *cliconfig.PsValues, runtime *adapter.LocalRuntime) error { fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s", hid, himage, hcommand, hcreated, hstatus, hports, hnames) // User wants pod info if opts.Pod { - fmt.Fprintf(w, "\t%s", hpod) + fmt.Fprintf(w, "\t%s\t%s", hpod, hpodname) } //User wants size info if opts.Size { @@ -370,7 +375,7 @@ func psDisplay(c *cliconfig.PsValues, runtime *adapter.LocalRuntime) error { fmt.Fprintf(w, "\n%s\t%s\t%s\t%s\t%s\t%s\t%s", container.ID, container.Image, container.Command, container.Created, container.Status, container.Ports, container.Names) // User wants pod info if opts.Pod { - fmt.Fprintf(w, "\t%s", container.Pod) + fmt.Fprintf(w, "\t%s\t%s", container.Pod, container.PodName) } //User wants size info if opts.Size { diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go index 3f621116e..f4ca88ea8 100644 --- a/cmd/podman/rmi.go +++ b/cmd/podman/rmi.go @@ -68,7 +68,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { images := args[:] removeImage := func(img *adapter.ContainerImage) { - msg, err := runtime.RemoveImage(ctx, img, c.Force) + response, err := runtime.RemoveImage(ctx, img, c.Force) if err != nil { if errors.Cause(err) == storage.ErrImageUsedByContainer { fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID()) @@ -83,7 +83,14 @@ func rmiCmd(c *cliconfig.RmiValues) error { lastError = err return } - fmt.Println(msg) + // Iterate if any images tags were deleted + for _, i := range response.Untagged { + fmt.Printf("Untagged: %s\n", i) + } + // Make sure an image was deleted (and not just untagged); else print it + if len(response.Deleted) > 0 { + fmt.Printf("Deleted: %s\n", response.Deleted) + } } if removeAll { diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index 4f2002992..5f8df2e10 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -76,6 +76,7 @@ type PsContainerOutput struct { Pid int Size *ContainerSize Pod string + PodName string CreatedAt time.Time ExitedAt time.Time StartedAt time.Time @@ -112,7 +113,7 @@ type ContainerSize struct { // NewBatchContainer runs a batch process under one lock to get container information and only // be called in PBatch. -func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput, error) { +func NewBatchContainer(r *libpod.Runtime, ctr *libpod.Container, opts PsOptions) (PsContainerOutput, error) { var ( conState define.ContainerStatus command string @@ -204,11 +205,11 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput _, imageName := ctr.Image() cid := ctr.ID() - pod := ctr.PodID() + podID := ctr.PodID() if !opts.NoTrunc { cid = cid[0:cidTruncLength] - if len(pod) > podTruncLength { - pod = pod[0:podTruncLength] + if len(podID) > podTruncLength { + podID = podID[0:podTruncLength] } if len(command) > cmdTruncLength { command = command[0:cmdTruncLength] + "..." @@ -231,13 +232,29 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput pso.State = conState pso.Pid = pid pso.Size = size - pso.Pod = pod pso.ExitedAt = exitedAt pso.CreatedAt = ctr.CreatedTime() pso.StartedAt = startedAt pso.Labels = ctr.Labels() pso.Mounts = strings.Join(ctr.UserVolumes(), " ") + // Add pod name and pod ID if requested by user. + // No need to look up the pod if its ID is empty. + if opts.Pod && len(podID) > 0 { + // The pod name is not in the container definition + // so we need to retrieve it using the pod ID. + var podName string + pod, err := r.LookupPod(podID) + if err != nil { + logrus.Errorf("unable to lookup pod for container %s", ctr.ID()) + } else { + podName = pod.Name() + } + + pso.Pod = podID + pso.PodName = podName + } + if opts.Namespace { pso.Cgroup = ns.Cgroup pso.IPC = ns.IPC @@ -462,13 +479,13 @@ func GetPsContainerOutput(r *libpod.Runtime, opts PsOptions, filters []string, m outputContainers = []*libpod.Container{latestCtr} } - pss := PBatch(outputContainers, maxWorkers, opts) + pss := PBatch(r, outputContainers, maxWorkers, opts) return pss, nil } // PBatch performs batch operations on a container in parallel. It spawns the // number of workers relative to the number of parallel operations desired. -func PBatch(containers []*libpod.Container, workers int, opts PsOptions) []PsContainerOutput { +func PBatch(r *libpod.Runtime, containers []*libpod.Container, workers int, opts PsOptions) []PsContainerOutput { var wg sync.WaitGroup psResults := []PsContainerOutput{} @@ -492,7 +509,7 @@ func PBatch(containers []*libpod.Container, workers int, opts PsOptions) []PsCon j := j wg.Add(1) f := func() (PsContainerOutput, error) { - return NewBatchContainer(j, opts) + return NewBatchContainer(r, j, opts) } jobs <- workerInput{ parallelFunc: f, diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index bb4e9cd12..58cf56eea 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -24,7 +24,6 @@ import ( "github.com/containers/libpod/pkg/rootless" cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" - "github.com/docker/docker/pkg/signal" "github.com/docker/go-connections/nat" "github.com/docker/go-units" "github.com/opentracing/opentracing-go" @@ -464,7 +463,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. signalString = c.String("stop-signal") } if signalString != "" { - stopSignal, err = signal.ParseSignal(signalString) + stopSignal, err = util.ParseSignal(signalString) if err != nil { return nil, err } @@ -624,7 +623,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } if systemd { if signalString == "" { - stopSignal, err = signal.ParseSignal("RTMIN+3") + stopSignal, err = util.ParseSignal("RTMIN+3") if err != nil { return nil, errors.Wrapf(err, "error parsing systemd signal") } @@ -804,6 +803,10 @@ func CreateContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateC return nil, err } + // Set the CreateCommand explicitly. Some (future) consumers of libpod + // might not want to set it. + options = append(options, libpod.WithCreateCommand()) + ctr, err := r.NewContainer(ctx, runtimeSpec, options...) if err != nil { return nil, err diff --git a/cmd/podman/shared/create_cli.go b/cmd/podman/shared/create_cli.go index 08a40b206..00b83906d 100644 --- a/cmd/podman/shared/create_cli.go +++ b/cmd/podman/shared/create_cli.go @@ -12,11 +12,6 @@ import ( "github.com/sirupsen/logrus" ) -const ( - // It's not kernel limit, we want this 4M limit to supply a reasonable functional container - linuxMinMemory = 4194304 -) - // GetAllLabels ... func GetAllLabels(labelFile, inputLabels []string) (map[string]string, error) { labels := make(map[string]string) @@ -86,9 +81,6 @@ func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, e sysInfo := sysinfo.New(true) // memory subsystem checks and adjustments - if config.Resources.Memory != 0 && config.Resources.Memory < linuxMinMemory { - return warnings, fmt.Errorf("minimum memory limit allowed is 4MB") - } if config.Resources.Memory > 0 && !sysInfo.MemoryLimit { warnings = addWarning(warnings, "Your kernel does not support memory limit capabilities or the cgroup is not mounted. Limitation discarded.") config.Resources.Memory = 0 @@ -120,9 +112,6 @@ func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, e warnings = addWarning(warnings, "Your kernel does not support memory soft limit capabilities or the cgroup is not mounted. Limitation discarded.") config.Resources.MemoryReservation = 0 } - if config.Resources.MemoryReservation > 0 && config.Resources.MemoryReservation < linuxMinMemory { - return warnings, fmt.Errorf("minimum memory reservation allowed is 4MB") - } if config.Resources.Memory > 0 && config.Resources.MemoryReservation > 0 && config.Resources.Memory < config.Resources.MemoryReservation { return warnings, fmt.Errorf("minimum memory limit cannot be less than memory reservation limit, see usage") } @@ -130,9 +119,6 @@ func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, e warnings = addWarning(warnings, "Your kernel does not support kernel memory limit capabilities or the cgroup is not mounted. Limitation discarded.") config.Resources.KernelMemory = 0 } - if config.Resources.KernelMemory > 0 && config.Resources.KernelMemory < linuxMinMemory { - return warnings, fmt.Errorf("minimum kernel memory limit allowed is 4MB") - } if config.Resources.DisableOomKiller && !sysInfo.OomKillDisable { // only produce warnings if the setting wasn't to *disable* the OOM Kill; no point // warning the caller if they already wanted the feature to be off diff --git a/cmd/podman/tree.go b/cmd/podman/tree.go index cb1b3fc9c..566f96995 100644 --- a/cmd/podman/tree.go +++ b/cmd/podman/tree.go @@ -56,7 +56,7 @@ func treeCmd(c *cliconfig.TreeValues) error { return errors.Wrapf(err, "error creating libpod runtime") } defer runtime.DeferredShutdown(false) - imageInfo, layerInfoMap, img, err := runtime.Tree(c) + imageInfo, layerInfoMap, img, err := runtime.Tree(c.InputArgs[0]) if err != nil { return err } diff --git a/cmd/podman/untag.go b/cmd/podman/untag.go new file mode 100644 index 000000000..9ff62b808 --- /dev/null +++ b/cmd/podman/untag.go @@ -0,0 +1,67 @@ +package main + +import ( + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var ( + untagCommand cliconfig.UntagValues + + _untagCommand = &cobra.Command{ + Use: "untag [flags] IMAGE [NAME...]", + Short: "Remove a name from a local image", + Long: "Removes one or more names from a locally-stored image.", + RunE: func(cmd *cobra.Command, args []string) error { + untagCommand.InputArgs = args + untagCommand.GlobalFlags = MainGlobalOpts + untagCommand.Remote = remoteclient + return untag(&untagCommand) + }, + Example: `podman untag 0e3bbc2 + podman untag imageID:latest otherImageName:latest + podman untag httpd myregistryhost:5000/fedora/httpd:v2`, + } +) + +func init() { + untagCommand.Command = _untagCommand + untagCommand.SetHelpTemplate(HelpTemplate()) + untagCommand.SetUsageTemplate(UsageTemplate()) +} + +func untag(c *cliconfig.UntagValues) error { + args := c.InputArgs + + if len(args) == 0 { + return errors.Errorf("at least one image name needs to be specified") + } + + runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) + if err != nil { + return errors.Wrapf(err, "could not create runtime") + } + defer runtime.DeferredShutdown(false) + + newImage, err := runtime.NewImageFromLocal(args[0]) + if err != nil { + return err + } + + tags := args[1:] + if len(args) == 1 { + // Remove all tags if not explicitly specified + tags = newImage.Names() + } + logrus.Debugf("Tags to be removed: %v", tags) + + for _, tag := range tags { + if err := newImage.UntagImage(tag); err != nil { + return errors.Wrapf(err, "removing %q from %q", tag, newImage.InputName) + } + } + return nil +} diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 2251050c3..ac400a467 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -18,6 +18,11 @@ type StringResponse ( message: string ) +type RemoveImageResponse ( + untagged: []string, + deleted: string +) + type LogLine ( device: string, parseLogType : string, @@ -240,6 +245,13 @@ type InfoGraphStatus ( supports_d_type: string ) +# InfoRegistry describes the host's registry information +type InfoRegistry ( + search: []string, + insecure: []string, + blocked: []string +) + # InfoStore describes the host's storage informatoin type InfoStore ( containers: int, @@ -262,8 +274,7 @@ type InfoPodmanBinary ( # PodmanInfo describes the Podman host and build type PodmanInfo ( host: InfoHost, - registries: []string, - insecure_registries: []string, + registries: InfoRegistry, store: InfoStore, podman: InfoPodmanBinary ) @@ -855,6 +866,12 @@ method PushImage(name: string, tag: string, compress: bool, format: string, remo # be found, an [ImageNotFound](#ImageNotFound) error will be returned; otherwise, the ID of the image is returned on success. method TagImage(name: string, tagged: string) -> (image: string) +# UntagImage takes the name or ID of an image in local storage as well as the +# tag name to be removed. If the image cannot be found, an +# [ImageNotFound](#ImageNotFound) error will be returned; otherwise, the ID of +# the image is returned on success. +method UntagImage(name: string, tag: string) -> (image: string) + # RemoveImage takes the name or ID of an image as well as a boolean that determines if containers using that image # should be deleted. If the image cannot be found, an [ImageNotFound](#ImageNotFound) error will be returned. The # ID of the removed image is returned when complete. See also [DeleteUnusedImages](DeleteUnusedImages). @@ -867,6 +884,11 @@ method TagImage(name: string, tagged: string) -> (image: string) # ~~~ method RemoveImage(name: string, force: bool) -> (image: string) +# RemoveImageWithResponse takes the name or ID of an image as well as a boolean that determines if containers using that image +# should be deleted. If the image cannot be found, an [ImageNotFound](#ImageNotFound) error will be returned. The reponse is +# in the form of a RemoveImageResponse . +method RemoveImageWithResponse(name: string, force: bool) -> (response: RemoveImageResponse) + # SearchImages searches available registries for images that contain the # contents of "query" in their name. If "limit" is given, limits the amount of # search results per registry. diff --git a/cmd/service/main.go b/cmd/service/main.go new file mode 100644 index 000000000..0290de892 --- /dev/null +++ b/cmd/service/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "context" + "fmt" + "os" + + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/cmd/podman/libpodruntime" + api "github.com/containers/libpod/pkg/api/server" + "github.com/containers/storage/pkg/reexec" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func initConfig() { + // we can do more stuff in here. +} + +func main() { + if reexec.Init() { + // We were invoked with a different argv[0] indicating that we + // had a specific job to do as a subprocess, and it's done. + return + } + + cobra.OnInitialize(initConfig) + log.SetLevel(log.DebugLevel) + + config := cliconfig.PodmanCommand{ + Command: &cobra.Command{}, + InputArgs: []string{}, + GlobalFlags: cliconfig.MainFlags{}, + Remote: false, + } + // Create a single runtime for http + runtime, err := libpodruntime.GetRuntimeDisableFDs(context.Background(), &config) + if err != nil { + fmt.Printf("error creating libpod runtime: %s", err.Error()) + os.Exit(1) + } + defer runtime.DeferredShutdown(false) + + server, err := api.NewServer(runtime) + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + + err = server.Serve() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } +} |