diff options
Diffstat (limited to 'cmd/podmanV2')
101 files changed, 0 insertions, 9260 deletions
diff --git a/cmd/podmanV2/Makefile b/cmd/podmanV2/Makefile deleted file mode 100644 index 8a924670a..000000000 --- a/cmd/podmanV2/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -all: podman podman-remote - -BUILD_TAGS='ABISupport systemd varlink seccomp selinux exclude_graphdriver_devicemapper' - -podman: - CGO_ENABLED=1 GO111MODULE=off go build -tags $(BUILD_TAGS) - -podman-remote: - CGO_ENABLED=1 GO111MODULE=off go build -tags '!ABISupport systemd seccomp selinux' -o podmanV2-remote - -clean: - rm podmanV2 podmanV2-remote diff --git a/cmd/podmanV2/README.md b/cmd/podmanV2/README.md deleted file mode 100644 index a17e6f850..000000000 --- a/cmd/podmanV2/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# Adding a podman V2 commands - -## Build podman V2 - -```shell script -$ cd $GOPATH/src/github.com/containers/libpod/cmd/podmanV2 -``` -If you wish to include the libpod library in your program, -```shell script -$ go build -tags 'ABISupport' . -``` -The `--remote` flag may be used to connect to the Podman service using the API. -Otherwise, direct calls will be made to the Libpod library. -```shell script -$ go build -tags '!ABISupport' . -``` -The Libpod library is not linked into the executable. -All calls are made via the API and `--remote=False` is an error condition. - -## Adding a new command `podman manifests` -```shell script -$ mkdir -p $GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests -``` -Create the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests/manifest.go``` -```go -package manifests - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // podman _manifests_ - manifestCmd = &cobra.Command{ - Use: "manifest", - Short: "Manage manifests", - Long: "Manage manifests", - Example: "podman manifests IMAGE", - TraverseChildren: true, - PersistentPreRunE: preRunE, - RunE: registry.SubCommandExists, // Report error if there is no sub command given - } -) -func init() { - // Subscribe command to podman - registry.Commands = append(registry.Commands, registry.CliCommand{ - // _podman manifest_ will support both ABIMode and TunnelMode - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - // The definition for this command - Command: manifestCmd, - }) - // Setup cobra templates, sub commands will inherit - manifestCmd.SetHelpTemplate(registry.HelpTemplate()) - manifestCmd.SetUsageTemplate(registry.UsageTemplate()) -} - -// preRunE populates the image engine for sub commands -func preRunE(cmd *cobra.Command, args []string) error { - _, err := registry.NewImageEngine(cmd, args) - return err -} -``` -To "wire" in the `manifest` command, edit the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/main.go``` to add: -```go -package main - -import _ "github.com/containers/libpod/cmd/podmanV2/manifests" -``` - -## Adding a new sub command `podman manifests list` -Create the file ```$GOPATH/src/github.com/containers/libpod/cmd/podmanV2/manifests/inspect.go``` -```go -package manifests - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // podman manifests _inspect_ - inspectCmd = &cobra.Command{ - Use: "inspect IMAGE", - Short: "Display manifest from image", - Long: "Displays the low-level information on a manifest identified by image name or ID", - RunE: inspect, - Example: "podman manifest DEADBEEF", - } -) - -func init() { - // Subscribe inspect sub command to manifest command - registry.Commands = append(registry.Commands, registry.CliCommand{ - // _podman manifest inspect_ will support both ABIMode and TunnelMode - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - // The definition for this command - Command: inspectCmd, - Parent: manifestCmd, - }) - - // This is where you would configure the cobra flags using inspectCmd.Flags() -} - -// Business logic: cmd is inspectCmd, args is the positional arguments from os.Args -func inspect(cmd *cobra.Command, args []string) error { - // Business logic using registry.ImageEngine - // Do not pull from libpod directly use the domain objects and types - return nil -} -``` diff --git a/cmd/podmanV2/common/create.go b/cmd/podmanV2/common/create.go deleted file mode 100644 index 0b2f4532c..000000000 --- a/cmd/podmanV2/common/create.go +++ /dev/null @@ -1,517 +0,0 @@ -package common - -import ( - "fmt" - - buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/spf13/pflag" -) - -const sizeWithUnitFormat = "(format: `<number>[<unit>]`, where unit = b (bytes), k (kilobytes), m (megabytes), or g (gigabytes))" - -var containerConfig = registry.NewPodmanConfig() - -func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { - createFlags := pflag.FlagSet{} - createFlags.StringSliceVar( - &cf.Annotation, - "annotation", []string{}, - "Add annotations to container (key:value)", - ) - createFlags.StringSliceVarP( - &cf.Attach, - "attach", "a", []string{}, - "Attach to STDIN, STDOUT or STDERR", - ) - createFlags.StringVar( - &cf.Authfile, - "authfile", buildahcli.GetDefaultAuthFile(), - "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override", - ) - createFlags.StringVar( - &cf.BlkIOWeight, - "blkio-weight", "", - "Block IO weight (relative weight) accepts a weight value between 10 and 1000.", - ) - createFlags.StringSliceVar( - &cf.BlkIOWeightDevice, - "blkio-weight-device", []string{}, - "Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)", - ) - createFlags.StringSliceVar( - &cf.CapAdd, - "cap-add", []string{}, - "Add capabilities to the container", - ) - createFlags.StringSliceVar( - &cf.CapDrop, - "cap-drop", []string{}, - "Drop capabilities from the container", - ) - createFlags.StringVar( - &cf.CGroupsNS, - "cgroupns", getDefaultCgroupNS(), - "cgroup namespace to use", - ) - createFlags.StringVar( - &cf.CGroups, - "cgroups", "enabled", - `control container cgroup configuration ("enabled"|"disabled"|"no-conmon")`, - ) - createFlags.StringVar( - &cf.CGroupParent, - "cgroup-parent", "", - "Optional parent cgroup for the container", - ) - createFlags.StringVar( - &cf.CIDFile, - "cidfile", "", - "Write the container ID to the file", - ) - createFlags.StringVar( - &cf.ConmonPIDFile, - "conmon-pidfile", "", - "Path to the file that will receive the PID of conmon", - ) - createFlags.Uint64Var( - &cf.CPUPeriod, - "cpu-period", 0, - "Limit the CPU CFS (Completely Fair Scheduler) period", - ) - createFlags.Int64Var( - &cf.CPUQuota, - "cpu-quota", 0, - "Limit the CPU CFS (Completely Fair Scheduler) quota", - ) - createFlags.Uint64Var( - &cf.CPURTPeriod, - "cpu-rt-period", 0, - "Limit the CPU real-time period in microseconds", - ) - createFlags.Int64Var( - &cf.CPURTRuntime, - "cpu-rt-runtime", 0, - "Limit the CPU real-time runtime in microseconds", - ) - createFlags.Uint64Var( - &cf.CPUShares, - "cpu-shares", 0, - "CPU shares (relative weight)", - ) - createFlags.Float64Var( - &cf.CPUS, - "cpus", 0, - "Number of CPUs. The default is 0.000 which means no limit", - ) - createFlags.StringVar( - &cf.CPUSetCPUs, - "cpuset-cpus", "", - "CPUs in which to allow execution (0-3, 0,1)", - ) - createFlags.StringVar( - &cf.CPUSetMems, - "cpuset-mems", "", - "Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.", - ) - createFlags.BoolVarP( - &cf.Detach, - "detach", "d", false, - "Run container in background and print container ID", - ) - createFlags.StringVar( - &cf.DetachKeys, - "detach-keys", GetDefaultDetachKeys(), - "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-cf`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`", - ) - createFlags.StringSliceVar( - &cf.Device, - "device", getDefaultDevices(), - fmt.Sprintf("Add a host device to the container"), - ) - createFlags.StringSliceVar( - &cf.DeviceCGroupRule, - "device-cgroup-rule", []string{}, - "Add a rule to the cgroup allowed devices list", - ) - createFlags.StringSliceVar( - &cf.DeviceReadBPs, - "device-read-bps", []string{}, - "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)", - ) - createFlags.StringSliceVar( - &cf.DeviceReadIOPs, - "device-read-iops", []string{}, - "Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000)", - ) - createFlags.StringSliceVar( - &cf.DeviceWriteBPs, - "device-write-bps", []string{}, - "Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb)", - ) - createFlags.StringSliceVar( - &cf.DeviceWriteIOPs, - "device-write-iops", []string{}, - "Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)", - ) - createFlags.StringVar( - &cf.Entrypoint, - "entrypoint", "", - "Overwrite the default ENTRYPOINT of the image", - ) - createFlags.StringArrayVarP( - &cf.env, - "env", "e", getDefaultEnv(), - "Set environment variables in container", - ) - createFlags.BoolVar( - &cf.EnvHost, - "env-host", false, "Use all current host environment variables in container", - ) - createFlags.StringSliceVar( - &cf.EnvFile, - "env-file", []string{}, - "Read in a file of environment variables", - ) - createFlags.StringSliceVar( - &cf.Expose, - "expose", []string{}, - "Expose a port or a range of ports", - ) - createFlags.StringSliceVar( - &cf.GIDMap, - "gidmap", []string{}, - "GID map to use for the user namespace", - ) - createFlags.StringSliceVar( - &cf.GroupAdd, - "group-add", []string{}, - "Add additional groups to join", - ) - createFlags.Bool( - "help", false, "", - ) - createFlags.StringVar( - &cf.HealthCmd, - "health-cmd", "", - "set a healthcheck command for the container ('none' disables the existing healthcheck)", - ) - createFlags.StringVar( - &cf.HealthInterval, - "health-interval", DefaultHealthCheckInterval, - "set an interval for the healthchecks (a value of disable results in no automatic timer setup)", - ) - createFlags.UintVar( - &cf.HealthRetries, - "health-retries", DefaultHealthCheckRetries, - "the number of retries allowed before a healthcheck is considered to be unhealthy", - ) - createFlags.StringVar( - &cf.HealthStartPeriod, - "health-start-period", DefaultHealthCheckStartPeriod, - "the initialization time needed for a container to bootstrap", - ) - createFlags.StringVar( - &cf.HealthTimeout, - "health-timeout", DefaultHealthCheckTimeout, - "the maximum time allowed to complete the healthcheck before an interval is considered failed", - ) - createFlags.StringVarP( - &cf.Hostname, - "hostname", "h", "", - "Set container hostname", - ) - createFlags.BoolVar( - &cf.HTTPProxy, - "http-proxy", true, - "Set proxy environment variables in the container based on the host proxy vars", - ) - createFlags.StringVar( - &cf.ImageVolume, - "image-volume", DefaultImageVolume, - `Tells podman how to handle the builtin image volumes ("bind"|"tmpfs"|"ignore")`, - ) - createFlags.BoolVar( - &cf.Init, - "init", false, - "Run an init binary inside the container that forwards signals and reaps processes", - ) - createFlags.StringVar( - &cf.InitPath, - "init-path", getDefaultInitPath(), - // Do not use the Value field for setting the default value to determine user input (i.e., non-empty string) - fmt.Sprintf("Path to the container-init binary"), - ) - createFlags.BoolVarP( - &cf.Interactive, - "interactive", "i", false, - "Keep STDIN open even if not attached", - ) - createFlags.StringVar( - &cf.IPC, - "ipc", getDefaultIPCNS(), - "IPC namespace to use", - ) - createFlags.StringVar( - &cf.KernelMemory, - "kernel-memory", "", - "Kernel memory limit "+sizeWithUnitFormat, - ) - createFlags.StringArrayVarP( - &cf.Label, - "label", "l", []string{}, - "Set metadata on container", - ) - createFlags.StringSliceVar( - &cf.LabelFile, - "label-file", []string{}, - "Read in a line delimited file of labels", - ) - createFlags.StringVar( - &cf.LogDriver, - "log-driver", "", - "Logging driver for the container", - ) - createFlags.StringSliceVar( - &cf.LogOptions, - "log-opt", []string{}, - "Logging driver options", - ) - createFlags.StringVarP( - &cf.Memory, - "memory", "m", "", - "Memory limit "+sizeWithUnitFormat, - ) - createFlags.StringVar( - &cf.MemoryReservation, - "memory-reservation", "", - "Memory soft limit "+sizeWithUnitFormat, - ) - createFlags.StringVar( - &cf.MemorySwap, - "memory-swap", "", - "Swap limit equal to memory plus swap: '-1' to enable unlimited swap", - ) - createFlags.Int64Var( - &cf.MemorySwappiness, - "memory-swappiness", -1, - "Tune container memory swappiness (0 to 100, or -1 for system default)", - ) - createFlags.StringVar( - &cf.Name, - "name", "", - "Assign a name to the container", - ) - createFlags.BoolVar( - &cf.NoHealthCheck, - "no-healthcheck", false, - "Disable healthchecks on container", - ) - createFlags.BoolVar( - &cf.OOMKillDisable, - "oom-kill-disable", false, - "Disable OOM Killer", - ) - createFlags.IntVar( - &cf.OOMScoreAdj, - "oom-score-adj", 0, - "Tune the host's OOM preferences (-1000 to 1000)", - ) - createFlags.StringVar( - &cf.OverrideArch, - "override-arch", "", - "use `ARCH` instead of the architecture of the machine for choosing images", - ) - // markFlagHidden(createFlags, "override-arch") - createFlags.StringVar( - &cf.OverrideOS, - "override-os", "", - "use `OS` instead of the running OS for choosing images", - ) - // markFlagHidden(createFlags, "override-os") - createFlags.StringVar( - &cf.PID, - "pid", getDefaultPidNS(), - "PID namespace to use", - ) - createFlags.Int64Var( - &cf.PIDsLimit, - "pids-limit", getDefaultPidsLimit(), - getDefaultPidsDescription(), - ) - createFlags.StringVar( - &cf.Pod, - "pod", "", - "Run container in an existing pod", - ) - createFlags.BoolVar( - &cf.Privileged, - "privileged", false, - "Give extended privileges to container", - ) - createFlags.BoolVarP( - &cf.PublishAll, - "publish-all", "P", false, - "Publish all exposed ports to random ports on the host interface", - ) - createFlags.StringVar( - &cf.Pull, - "pull", "missing", - `Pull image before creating ("always"|"missing"|"never")`, - ) - createFlags.BoolVarP( - &cf.Quiet, - "quiet", "q", false, - "Suppress output information when pulling images", - ) - createFlags.BoolVar( - &cf.ReadOnly, - "read-only", false, - "Make containers root filesystem read-only", - ) - createFlags.BoolVar( - &cf.ReadOnlyTmpFS, - "read-only-tmpfs", true, - "When running containers in read-only mode mount a read-write tmpfs on /run, /tmp and /var/tmp", - ) - createFlags.StringVar( - &cf.Restart, - "restart", "", - `Restart policy to apply when a container exits ("always"|"no"|"on-failure")`, - ) - createFlags.BoolVar( - &cf.Rm, - "rm", false, - "Remove container (and pod if created) after exit", - ) - createFlags.BoolVar( - &cf.RootFS, - "rootfs", false, - "The first argument is not an image but the rootfs to the exploded container", - ) - createFlags.StringArrayVar( - &cf.SecurityOpt, - "security-opt", getDefaultSecurityOptions(), - "Security Options", - ) - createFlags.StringVar( - &cf.ShmSize, - "shm-size", getDefaultShmSize(), - "Size of /dev/shm "+sizeWithUnitFormat, - ) - createFlags.StringVar( - &cf.StopSignal, - "stop-signal", "", - "Signal to stop a container. Default is SIGTERM", - ) - createFlags.UintVar( - &cf.StopTimeout, - "stop-timeout", containerConfig.Engine.StopTimeout, - "Timeout (in seconds) to stop a container. Default is 10", - ) - createFlags.StringSliceVar( - &cf.StoreageOpt, - "storage-opt", []string{}, - "Storage driver options per container", - ) - createFlags.StringVar( - &cf.SubUIDName, - "subgidname", "", - "Name of range listed in /etc/subgid for use in user namespace", - ) - createFlags.StringVar( - &cf.SubGIDName, - "subuidname", "", - "Name of range listed in /etc/subuid for use in user namespace", - ) - - createFlags.StringSliceVar( - &cf.Sysctl, - "sysctl", getDefaultSysctls(), - "Sysctl options", - ) - createFlags.StringVar( - &cf.SystemdD, - "systemd", "true", - `Run container in systemd mode ("true"|"false"|"always")`, - ) - createFlags.StringArrayVar( - &cf.TmpFS, - "tmpfs", []string{}, - "Mount a temporary filesystem (`tmpfs`) into a container", - ) - createFlags.BoolVarP( - &cf.TTY, - "tty", "t", false, - "Allocate a pseudo-TTY for container", - ) - createFlags.StringSliceVar( - &cf.UIDMap, - "uidmap", []string{}, - "UID map to use for the user namespace", - ) - createFlags.StringSliceVar( - &cf.Ulimit, - "ulimit", getDefaultUlimits(), - "Ulimit options", - ) - createFlags.StringVarP( - &cf.User, - "user", "u", "", - "Username or UID (format: <name|uid>[:<group|gid>])", - ) - createFlags.StringVar( - &cf.UserNS, - "userns", getDefaultUserNS(), - "User namespace to use", - ) - createFlags.StringVar( - &cf.UTS, - "uts", getDefaultUTSNS(), - "UTS namespace to use", - ) - createFlags.StringArrayVar( - &cf.Mount, - "mount", []string{}, - "Attach a filesystem mount to the container", - ) - createFlags.StringArrayVarP( - &cf.Volume, - "volume", "v", getDefaultVolumes(), - "Bind mount a volume into the container", - ) - createFlags.StringSliceVar( - &cf.VolumesFrom, - "volumes-from", []string{}, - "Mount volumes from the specified container(s)", - ) - createFlags.StringVarP( - &cf.Workdir, - "workdir", "w", "", - "Working directory inside the container", - ) - createFlags.StringVar( - &cf.SeccompPolicy, - "seccomp-policy", "default", - "Policy for selecting a seccomp profile (experimental)", - ) - return &createFlags -} - -func AliasFlags(_ *pflag.FlagSet, name string) pflag.NormalizedName { - switch name { - case "healthcheck-command": - name = "health-cmd" - case "healthcheck-interval": - name = "health-interval" - case "healthcheck-retries": - name = "health-retries" - case "healthcheck-start-period": - name = "health-start-period" - case "healthcheck-timeout": - name = "health-timeout" - case "net": - name = "network" - } - return pflag.NormalizedName(name) -} diff --git a/cmd/podmanV2/common/create_opts.go b/cmd/podmanV2/common/create_opts.go deleted file mode 100644 index 9d12e4b26..000000000 --- a/cmd/podmanV2/common/create_opts.go +++ /dev/null @@ -1,103 +0,0 @@ -package common - -import "github.com/containers/libpod/pkg/domain/entities" - -type ContainerCLIOpts struct { - Annotation []string - Attach []string - Authfile string - BlkIOWeight string - BlkIOWeightDevice []string - CapAdd []string - CapDrop []string - CGroupsNS string - CGroups string - CGroupParent string - CIDFile string - ConmonPIDFile string - CPUPeriod uint64 - CPUQuota int64 - CPURTPeriod uint64 - CPURTRuntime int64 - CPUShares uint64 - CPUS float64 - CPUSetCPUs string - CPUSetMems string - Detach bool - DetachKeys string - Device []string - DeviceCGroupRule []string - DeviceReadBPs []string - DeviceReadIOPs []string - DeviceWriteBPs []string - DeviceWriteIOPs []string - Entrypoint string - env []string - EnvHost bool - EnvFile []string - Expose []string - GIDMap []string - GroupAdd []string - HealthCmd string - HealthInterval string - HealthRetries uint - HealthStartPeriod string - HealthTimeout string - Hostname string - HTTPProxy bool - ImageVolume string - Init bool - InitPath string - Interactive bool - IPC string - KernelMemory string - Label []string - LabelFile []string - LogDriver string - LogOptions []string - Memory string - MemoryReservation string - MemorySwap string - MemorySwappiness int64 - Name string - NoHealthCheck bool - OOMKillDisable bool - OOMScoreAdj int - OverrideArch string - OverrideOS string - PID string - PIDsLimit int64 - Pod string - Privileged bool - PublishAll bool - Pull string - Quiet bool - ReadOnly bool - ReadOnlyTmpFS bool - Restart string - Rm bool - RootFS bool - SecurityOpt []string - ShmSize string - StopSignal string - StopTimeout uint - StoreageOpt []string - SubUIDName string - SubGIDName string - Sysctl []string - SystemdD string - TmpFS []string - TTY bool - UIDMap []string - Ulimit []string - User string - UserNS string - UTS string - Mount []string - Volume []string - VolumesFrom []string - Workdir string - SeccompPolicy string - - Net *entities.NetOptions -} diff --git a/cmd/podmanV2/common/createparse.go b/cmd/podmanV2/common/createparse.go deleted file mode 100644 index 89524a04b..000000000 --- a/cmd/podmanV2/common/createparse.go +++ /dev/null @@ -1,51 +0,0 @@ -package common - -import ( - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/pkg/util" - "github.com/pkg/errors" -) - -// validate determines if the flags and values given by the user are valid. things checked -// by validate must not need any state information on the flag (i.e. changed) -func (c *ContainerCLIOpts) validate() error { - var () - if c.Rm && c.Restart != "" && c.Restart != "no" { - return errors.Errorf("the --rm option conflicts with --restart") - } - - if _, err := util.ValidatePullType(c.Pull); err != nil { - return err - } - // Verify the additional hosts are in correct format - for _, host := range c.Net.AddHosts { - if _, err := parse.ValidateExtraHost(host); err != nil { - return err - } - } - - if dnsSearches := c.Net.DNSSearch; len(dnsSearches) > 0 { - // Validate domains are good - for _, dom := range dnsSearches { - if dom == "." { - if len(dnsSearches) > 1 { - return errors.Errorf("cannot pass additional search domains when also specifying '.'") - } - continue - } - if _, err := parse.ValidateDomain(dom); err != nil { - return err - } - } - } - var imageVolType = map[string]string{ - "bind": "", - "tmpfs": "", - "ignore": "", - } - if _, ok := imageVolType[c.ImageVolume]; !ok { - return errors.Errorf("invalid image-volume type %q. Pick one of bind, tmpfs, or ignore", c.ImageVolume) - } - return nil - -} diff --git a/cmd/podmanV2/common/default.go b/cmd/podmanV2/common/default.go deleted file mode 100644 index 853f87ab6..000000000 --- a/cmd/podmanV2/common/default.go +++ /dev/null @@ -1,135 +0,0 @@ -package common - -import ( - "fmt" - "os" - - "github.com/containers/buildah/pkg/parse" - "github.com/containers/libpod/pkg/apparmor" - "github.com/containers/libpod/pkg/cgroups" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/specgen" - "github.com/containers/libpod/pkg/sysinfo" - "github.com/opencontainers/selinux/go-selinux" -) - -var ( - // DefaultHealthCheckInterval default value - DefaultHealthCheckInterval = "30s" - // DefaultHealthCheckRetries default value - DefaultHealthCheckRetries uint = 3 - // DefaultHealthCheckStartPeriod default value - DefaultHealthCheckStartPeriod = "0s" - // DefaultHealthCheckTimeout default value - DefaultHealthCheckTimeout = "30s" - // DefaultImageVolume default value - DefaultImageVolume = "bind" -) - -// TODO these options are directly embedded into many of the CLI cobra values, as such -// this approach will not work in a remote client. so we will need to likely do something like a -// supported and unsupported approach here and backload these options into the specgen -// once we are "on" the host system. -func getDefaultSecurityOptions() []string { - securityOpts := []string{} - if containerConfig.Containers.SeccompProfile != "" && containerConfig.Containers.SeccompProfile != parse.SeccompDefaultPath { - securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", containerConfig.Containers.SeccompProfile)) - } - if apparmor.IsEnabled() && containerConfig.Containers.ApparmorProfile != "" { - securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", containerConfig.Containers.ApparmorProfile)) - } - if selinux.GetEnabled() && !containerConfig.Containers.EnableLabeling { - securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0])) - } - return securityOpts -} - -// getDefaultSysctls -func getDefaultSysctls() []string { - return containerConfig.Containers.DefaultSysctls -} - -func getDefaultVolumes() []string { - return containerConfig.Containers.Volumes -} - -func getDefaultDevices() []string { - return containerConfig.Containers.Devices -} - -func getDefaultDNSServers() []string { //nolint - return containerConfig.Containers.DNSServers -} - -func getDefaultDNSSearches() []string { //nolint - return containerConfig.Containers.DNSSearches -} - -func getDefaultDNSOptions() []string { //nolint - return containerConfig.Containers.DNSOptions -} - -func getDefaultEnv() []string { - return containerConfig.Containers.Env -} - -func getDefaultInitPath() string { - return containerConfig.Containers.InitPath -} - -func getDefaultIPCNS() string { - return containerConfig.Containers.IPCNS -} - -func getDefaultPidNS() string { - return containerConfig.Containers.PidNS -} - -func getDefaultNetNS() string { //nolint - if containerConfig.Containers.NetNS == string(specgen.Private) && rootless.IsRootless() { - return string(specgen.Slirp) - } - return containerConfig.Containers.NetNS -} - -func getDefaultCgroupNS() string { - return containerConfig.Containers.CgroupNS -} - -func getDefaultUTSNS() string { - return containerConfig.Containers.UTSNS -} - -func getDefaultShmSize() string { - return containerConfig.Containers.ShmSize -} - -func getDefaultUlimits() []string { - return containerConfig.Containers.DefaultUlimits -} - -func getDefaultUserNS() string { - userns := os.Getenv("PODMAN_USERNS") - if userns != "" { - return userns - } - return containerConfig.Containers.UserNS -} - -func getDefaultPidsLimit() int64 { - if rootless.IsRootless() { - cgroup2, _ := cgroups.IsCgroup2UnifiedMode() - if cgroup2 { - return containerConfig.Containers.PidsLimit - } - } - return sysinfo.GetDefaultPidsLimit() -} - -func getDefaultPidsDescription() string { - return "Tune container pids limit (set 0 for unlimited)" -} - -func GetDefaultDetachKeys() string { - return containerConfig.Engine.DetachKeys -} diff --git a/cmd/podmanV2/common/inspect.go b/cmd/podmanV2/common/inspect.go deleted file mode 100644 index dfc6fe679..000000000 --- a/cmd/podmanV2/common/inspect.go +++ /dev/null @@ -1,18 +0,0 @@ -package common - -import ( - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -// AddInspectFlagSet takes a command and adds the inspect flags and returns an InspectOptions object -// Since this cannot live in `package main` it lives here until a better home is found -func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions { - opts := entities.InspectOptions{} - - flags := cmd.Flags() - flags.BoolVarP(&opts.Size, "size", "s", false, "Display total file size") - flags.StringVarP(&opts.Format, "format", "f", "", "Change the output format to a Go template") - - return &opts -} diff --git a/cmd/podmanV2/common/netflags.go b/cmd/podmanV2/common/netflags.go deleted file mode 100644 index 41eed2988..000000000 --- a/cmd/podmanV2/common/netflags.go +++ /dev/null @@ -1,100 +0,0 @@ -package common - -import ( - "net" - - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func GetNetFlags() *pflag.FlagSet { - netFlags := pflag.FlagSet{} - netFlags.StringSlice( - "add-host", []string{}, - "Add a custom host-to-IP mapping (host:ip) (default [])", - ) - netFlags.StringSlice( - "dns", getDefaultDNSServers(), - "Set custom DNS servers", - ) - netFlags.StringSlice( - "dns-opt", getDefaultDNSOptions(), - "Set custom DNS options", - ) - netFlags.StringSlice( - "dns-search", getDefaultDNSSearches(), - "Set custom DNS search domains", - ) - netFlags.String( - "ip", "", - "Specify a static IPv4 address for the container", - ) - netFlags.String( - "mac-address", "", - "Container MAC address (e.g. 92:d0:c6:0a:29:33)", - ) - netFlags.String( - "network", getDefaultNetNS(), - "Connect a container to a network", - ) - netFlags.StringSliceP( - "publish", "p", []string{}, - "Publish a container's port, or a range of ports, to the host (default [])", - ) - netFlags.Bool( - "no-hosts", false, - "Do not create /etc/hosts within the container, instead use the version from the image", - ) - return &netFlags -} - -func NetFlagsToNetOptions(cmd *cobra.Command) (*entities.NetOptions, error) { - var ( - err error - ) - opts := entities.NetOptions{} - opts.AddHosts, err = cmd.Flags().GetStringSlice("add-host") - if err != nil { - return nil, err - } - servers, err := cmd.Flags().GetStringSlice("dns") - if err != nil { - return nil, err - } - for _, d := range servers { - if d == "none" { - opts.DNSHost = true - break - } - opts.DNSServers = append(opts.DNSServers, net.ParseIP(d)) - } - opts.DNSSearch, err = cmd.Flags().GetStringSlice("dns-search") - if err != nil { - return nil, err - } - - m, err := cmd.Flags().GetString("mac-address") - if err != nil { - return nil, err - } - if len(m) > 0 { - mac, err := net.ParseMAC(m) - if err != nil { - return nil, err - } - opts.StaticMAC = &mac - } - inputPorts, err := cmd.Flags().GetStringSlice("publish") - if err != nil { - return nil, err - } - if len(inputPorts) > 0 { - opts.PublishPorts, err = createPortBindings(inputPorts) - if err != nil { - return nil, err - } - } - opts.NoHosts, err = cmd.Flags().GetBool("no-hosts") - return &opts, err -} diff --git a/cmd/podmanV2/common/ports.go b/cmd/podmanV2/common/ports.go deleted file mode 100644 index 7e2b1e79d..000000000 --- a/cmd/podmanV2/common/ports.go +++ /dev/null @@ -1,126 +0,0 @@ -package common - -import ( - "fmt" - "net" - "strconv" - - "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/docker/go-connections/nat" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// ExposedPorts parses user and image ports and returns binding information -func ExposedPorts(expose []string, publish []ocicni.PortMapping, publishAll bool, imageExposedPorts map[string]struct{}) ([]ocicni.PortMapping, error) { - containerPorts := make(map[string]string) - - // TODO this needs to be added into a something that - // has access to an imageengine - // add expose ports from the image itself - //for expose := range imageExposedPorts { - // _, port := nat.SplitProtoPort(expose) - // containerPorts[port] = "" - //} - - // add the expose ports from the user (--expose) - // can be single or a range - for _, expose := range expose { - //support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>] - _, port := nat.SplitProtoPort(expose) - //parse the start and end port and create a sequence of ports to expose - //if expose a port, the start and end port are the same - start, end, err := nat.ParsePortRange(port) - if err != nil { - return nil, fmt.Errorf("invalid range format for --expose: %s, error: %s", expose, err) - } - for i := start; i <= end; i++ { - containerPorts[strconv.Itoa(int(i))] = "" - } - } - - // TODO/FIXME this is hell reencarnated - // parse user inputted port bindings - pbPorts, portBindings, err := nat.ParsePortSpecs([]string{}) - if err != nil { - return nil, err - } - - // delete exposed container ports if being used by -p - for i := range pbPorts { - delete(containerPorts, i.Port()) - } - - // iterate container ports and make port bindings from them - if publishAll { - for e := range containerPorts { - //support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>] - //proto, port := nat.SplitProtoPort(e) - p, err := nat.NewPort("tcp", e) - if err != nil { - return nil, err - } - rp, err := getRandomPort() - if err != nil { - return nil, err - } - logrus.Debug(fmt.Sprintf("Using random host port %d with container port %d", rp, p.Int())) - portBindings[p] = CreatePortBinding(rp, "") - } - } - - // We need to see if any host ports are not populated and if so, we need to assign a - // random port to them. - for k, pb := range portBindings { - if pb[0].HostPort == "" { - hostPort, err := getRandomPort() - if err != nil { - return nil, err - } - logrus.Debug(fmt.Sprintf("Using random host port %d with container port %s", hostPort, k.Port())) - pb[0].HostPort = strconv.Itoa(hostPort) - } - } - var pms []ocicni.PortMapping - for k, v := range portBindings { - for _, pb := range v { - hp, err := strconv.Atoi(pb.HostPort) - if err != nil { - return nil, err - } - pms = append(pms, ocicni.PortMapping{ - HostPort: int32(hp), - ContainerPort: int32(k.Int()), - //Protocol: "", - HostIP: pb.HostIP, - }) - } - } - return pms, nil -} - -func getRandomPort() (int, error) { - l, err := net.Listen("tcp", ":0") - if err != nil { - return 0, errors.Wrapf(err, "unable to get free port") - } - defer l.Close() - _, randomPort, err := net.SplitHostPort(l.Addr().String()) - if err != nil { - return 0, errors.Wrapf(err, "unable to determine free port") - } - rp, err := strconv.Atoi(randomPort) - if err != nil { - return 0, errors.Wrapf(err, "unable to convert random port to int") - } - return rp, nil -} - -//CreatePortBinding takes port (int) and IP (string) and creates an array of portbinding structs -func CreatePortBinding(hostPort int, hostIP string) []nat.PortBinding { - pb := nat.PortBinding{ - HostPort: strconv.Itoa(hostPort), - } - pb.HostIP = hostIP - return []nat.PortBinding{pb} -} diff --git a/cmd/podmanV2/common/specgen.go b/cmd/podmanV2/common/specgen.go deleted file mode 100644 index 2232fb4ba..000000000 --- a/cmd/podmanV2/common/specgen.go +++ /dev/null @@ -1,647 +0,0 @@ -package common - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/containers/image/v5/manifest" - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/libpod/define" - ann "github.com/containers/libpod/pkg/annotations" - envLib "github.com/containers/libpod/pkg/env" - ns "github.com/containers/libpod/pkg/namespaces" - "github.com/containers/libpod/pkg/specgen" - systemdGen "github.com/containers/libpod/pkg/systemd/generate" - "github.com/containers/libpod/pkg/util" - "github.com/docker/go-units" - "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" -) - -func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) error { - var ( - err error - //namespaces map[string]string - ) - - // validate flags as needed - if err := c.validate(); err != nil { - return nil - } - - inputCommand := args[1:] - if len(c.HealthCmd) > 0 { - s.HealthConfig, err = makeHealthCheckFromCli(c.HealthCmd, c.HealthInterval, c.HealthRetries, c.HealthTimeout, c.HealthStartPeriod) - if err != nil { - return err - } - } - - s.IDMappings, err = util.ParseIDMapping(ns.UsernsMode(c.UserNS), c.UIDMap, c.GIDMap, c.SubUIDName, c.SubGIDName) - if err != nil { - return err - } - if m := c.Memory; len(m) > 0 { - ml, err := units.RAMInBytes(m) - if err != nil { - return errors.Wrapf(err, "invalid value for memory") - } - s.ResourceLimits.Memory.Limit = &ml - } - if m := c.MemoryReservation; len(m) > 0 { - mr, err := units.RAMInBytes(m) - if err != nil { - return errors.Wrapf(err, "invalid value for memory") - } - s.ResourceLimits.Memory.Reservation = &mr - } - if m := c.MemorySwap; len(m) > 0 { - var ms int64 - if m == "-1" { - ms = int64(-1) - s.ResourceLimits.Memory.Swap = &ms - } else { - ms, err = units.RAMInBytes(m) - if err != nil { - return errors.Wrapf(err, "invalid value for memory") - } - } - s.ResourceLimits.Memory.Swap = &ms - } - if m := c.KernelMemory; len(m) > 0 { - mk, err := units.RAMInBytes(m) - if err != nil { - return errors.Wrapf(err, "invalid value for kernel-memory") - } - s.ResourceLimits.Memory.Kernel = &mk - } - if b := c.BlkIOWeight; len(b) > 0 { - u, err := strconv.ParseUint(b, 10, 16) - if err != nil { - return errors.Wrapf(err, "invalid value for blkio-weight") - } - nu := uint16(u) - s.ResourceLimits.BlockIO.Weight = &nu - } - - s.Terminal = c.TTY - ep, err := ExposedPorts(c.Expose, c.Net.PublishPorts, c.PublishAll, nil) - if err != nil { - return err - } - s.PortMappings = ep - s.Pod = c.Pod - - //s.CgroupNS = specgen.Namespace{ - // NSMode: , - // Value: "", - //} - - //s.UserNS = specgen.Namespace{} - - // Kernel Namespaces - // TODO Fix handling of namespace from pod - // Instead of integrating here, should be done in libpod - // However, that also involves setting up security opts - // when the pod's namespace is integrated - //namespaces = map[string]string{ - // "cgroup": c.CGroupsNS, - // "pid": c.PID, - // //"net": c.Net.Network.Value, // TODO need help here - // "ipc": c.IPC, - // "user": c.User, - // "uts": c.UTS, - //} - // - //if len(c.PID) > 0 { - // split := strings.SplitN(c.PID, ":", 2) - // // need a way to do thsi - // specgen.Namespace{ - // NSMode: split[0], - // } - // //Value: split1 if len allows - //} - // TODO this is going to have be done after things like pod creation are done because - // pod creation changes these values. - //pidMode := ns.PidMode(namespaces["pid"]) - //usernsMode := ns.UsernsMode(namespaces["user"]) - //utsMode := ns.UTSMode(namespaces["uts"]) - //cgroupMode := ns.CgroupMode(namespaces["cgroup"]) - //ipcMode := ns.IpcMode(namespaces["ipc"]) - //// Make sure if network is set to container namespace, port binding is not also being asked for - //netMode := ns.NetworkMode(namespaces["net"]) - //if netMode.IsContainer() { - // if len(portBindings) > 0 { - // return nil, errors.Errorf("cannot set port bindings on an existing container network namespace") - // } - //} - - // TODO Remove when done with namespaces for realz - // Setting a default for IPC to get this working - s.IpcNS = specgen.Namespace{ - NSMode: specgen.Private, - Value: "", - } - - // TODO this is going to have to be done the libpod/server end of things - // USER - //user := c.String("user") - //if user == "" { - // switch { - // case usernsMode.IsKeepID(): - // user = fmt.Sprintf("%d:%d", rootless.GetRootlessUID(), rootless.GetRootlessGID()) - // case data == nil: - // user = "0" - // default: - // user = data.Config.User - // } - //} - - // STOP SIGNAL - signalString := "TERM" - if sig := c.StopSignal; len(sig) > 0 { - signalString = sig - } - stopSignal, err := util.ParseSignal(signalString) - if err != nil { - return err - } - s.StopSignal = &stopSignal - - // ENVIRONMENT VARIABLES - // - // Precedence order (higher index wins): - // 1) env-host, 2) image data, 3) env-file, 4) env - env := map[string]string{ - "container": "podman", - } - - // First transform the os env into a map. We need it for the labels later in - // any case. - osEnv, err := envLib.ParseSlice(os.Environ()) - if err != nil { - return errors.Wrap(err, "error parsing host environment variables") - } - - if c.EnvHost { - env = envLib.Join(env, osEnv) - } - // env-file overrides any previous variables - for _, f := range c.EnvFile { - fileEnv, err := envLib.ParseFile(f) - if err != nil { - return err - } - // File env is overridden by env. - env = envLib.Join(env, fileEnv) - } - - // env overrides any previous variables - if cmdLineEnv := c.env; len(cmdLineEnv) > 0 { - parsedEnv, err := envLib.ParseSlice(cmdLineEnv) - if err != nil { - return err - } - env = envLib.Join(env, parsedEnv) - } - s.Env = env - - // LABEL VARIABLES - labels, err := parse.GetAllLabels(c.LabelFile, c.Label) - if err != nil { - return errors.Wrapf(err, "unable to process labels") - } - - if systemdUnit, exists := osEnv[systemdGen.EnvVariable]; exists { - labels[systemdGen.EnvVariable] = systemdUnit - } - - s.Labels = labels - - // ANNOTATIONS - annotations := make(map[string]string) - - // First, add our default annotations - annotations[ann.TTY] = "false" - if c.TTY { - annotations[ann.TTY] = "true" - } - - // Last, add user annotations - for _, annotation := range c.Annotation { - splitAnnotation := strings.SplitN(annotation, "=", 2) - if len(splitAnnotation) < 2 { - return errors.Errorf("Annotations must be formatted KEY=VALUE") - } - annotations[splitAnnotation[0]] = splitAnnotation[1] - } - s.Annotations = annotations - - workDir := "/" - if wd := c.Workdir; len(wd) > 0 { - workDir = wd - } - s.WorkDir = workDir - entrypoint := []string{} - userCommand := []string{} - if ep := c.Entrypoint; len(ep) > 0 { - // Check if entrypoint specified is json - if err := json.Unmarshal([]byte(c.Entrypoint), &entrypoint); err != nil { - entrypoint = append(entrypoint, ep) - } - } - - var command []string - - // Build the command - // If we have an entry point, it goes first - if len(entrypoint) > 0 { - command = entrypoint - } - if len(inputCommand) > 0 { - // User command overrides data CMD - command = append(command, inputCommand...) - userCommand = append(userCommand, inputCommand...) - } - - if len(inputCommand) > 0 { - s.Command = userCommand - } else { - s.Command = command - } - - // SHM Size - shmSize, err := units.FromHumanSize(c.ShmSize) - if err != nil { - return errors.Wrapf(err, "unable to translate --shm-size") - } - s.ShmSize = &shmSize - s.HostAdd = c.Net.AddHosts - s.DNSServer = c.Net.DNSServers - s.DNSSearch = c.Net.DNSSearch - s.DNSOption = c.Net.DNSOptions - - // deferred, must be added on libpod side - //var ImageVolumes map[string]struct{} - //if data != nil && c.String("image-volume") != "ignore" { - // ImageVolumes = data.Config.Volumes - //} - - s.ImageVolumeMode = c.ImageVolume - systemd := c.SystemdD == "always" - if !systemd && command != nil { - x, err := strconv.ParseBool(c.SystemdD) - if err != nil { - return errors.Wrapf(err, "cannot parse bool %s", c.SystemdD) - } - if x && (command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd")) { - systemd = true - } - } - if systemd { - if s.StopSignal == nil { - stopSignal, err = util.ParseSignal("RTMIN+3") - if err != nil { - return errors.Wrapf(err, "error parsing systemd signal") - } - s.StopSignal = &stopSignal - } - } - swappiness := uint64(c.MemorySwappiness) - if s.ResourceLimits == nil { - s.ResourceLimits = &specs.LinuxResources{} - } - if s.ResourceLimits.Memory == nil { - s.ResourceLimits.Memory = &specs.LinuxMemory{} - } - s.ResourceLimits.Memory.Swappiness = &swappiness - - if s.LogConfiguration == nil { - s.LogConfiguration = &specgen.LogConfig{} - } - s.LogConfiguration.Driver = define.KubernetesLogging - if ld := c.LogDriver; len(ld) > 0 { - s.LogConfiguration.Driver = ld - } - if s.ResourceLimits.Pids == nil { - s.ResourceLimits.Pids = &specs.LinuxPids{} - } - s.ResourceLimits.Pids.Limit = c.PIDsLimit - if c.CGroups == "disabled" && c.PIDsLimit > 0 { - s.ResourceLimits.Pids.Limit = -1 - } - // TODO WTF - //cgroup := &cc.CgroupConfig{ - // Cgroups: c.String("cgroups"), - // Cgroupns: c.String("cgroupns"), - // CgroupParent: c.String("cgroup-parent"), - // CgroupMode: cgroupMode, - //} - // - //userns := &cc.UserConfig{ - // GroupAdd: c.StringSlice("group-add"), - // IDMappings: idmappings, - // UsernsMode: usernsMode, - // User: user, - //} - // - //uts := &cc.UtsConfig{ - // UtsMode: utsMode, - // NoHosts: c.Bool("no-hosts"), - // HostAdd: c.StringSlice("add-host"), - // Hostname: c.String("hostname"), - //} - - sysctl := map[string]string{} - if ctl := c.Sysctl; len(ctl) > 0 { - sysctl, err = util.ValidateSysctls(ctl) - if err != nil { - return err - } - } - s.Sysctl = sysctl - - s.CapAdd = c.CapAdd - s.CapDrop = c.CapDrop - s.Privileged = c.Privileged - s.ReadOnlyFilesystem = c.ReadOnly - - // TODO - // ouitside of specgen and oci though - // defaults to true, check spec/storage - //s.readon = c.ReadOnlyTmpFS - // TODO convert to map? - // check if key=value and convert - sysmap := make(map[string]string) - for _, ctl := range c.Sysctl { - splitCtl := strings.SplitN(ctl, "=", 2) - if len(splitCtl) < 2 { - return errors.Errorf("invalid sysctl value %q", ctl) - } - sysmap[splitCtl[0]] = splitCtl[1] - } - s.Sysctl = sysmap - - for _, opt := range c.SecurityOpt { - if opt == "no-new-privileges" { - s.ContainerSecurityConfig.NoNewPrivileges = true - } else { - con := strings.SplitN(opt, "=", 2) - if len(con) != 2 { - return fmt.Errorf("invalid --security-opt 1: %q", opt) - } - - switch con[0] { - case "label": - // TODO selinux opts and label opts are the same thing - s.ContainerSecurityConfig.SelinuxOpts = append(s.ContainerSecurityConfig.SelinuxOpts, con[1]) - case "apparmor": - s.ContainerSecurityConfig.ApparmorProfile = con[1] - case "seccomp": - s.SeccompProfilePath = con[1] - default: - return fmt.Errorf("invalid --security-opt 2: %q", opt) - } - } - } - - // TODO any idea why this was done - // storage.go from spec/ - // grab it - //volumes := rtc.Containers.Volumes - // TODO conflict on populate? - //if v := c.Volume; len(v)> 0 { - // s.Volumes = append(volumes, c.StringSlice("volume")...) - //} - //s.volu - - //s.Mounts = c.Mount - s.VolumesFrom = c.VolumesFrom - - // TODO any idea why this was done - //devices := rtc.Containers.Devices - // TODO conflict on populate? - // - //if c.Changed("device") { - // devices = append(devices, c.StringSlice("device")...) - //} - - // TODO things i cannot find in spec - // we dont think these are in the spec - // init - initbinary - // initpath - s.Stdin = c.Interactive - // quiet - //DeviceCgroupRules: c.StringSlice("device-cgroup-rule"), - - if bps := c.DeviceReadBPs; len(bps) > 0 { - if s.ThrottleReadBpsDevice, err = parseThrottleBPSDevices(bps); err != nil { - return err - } - } - - if bps := c.DeviceWriteBPs; len(bps) > 0 { - if s.ThrottleWriteBpsDevice, err = parseThrottleBPSDevices(bps); err != nil { - return err - } - } - - if iops := c.DeviceReadIOPs; len(iops) > 0 { - if s.ThrottleReadIOPSDevice, err = parseThrottleIOPsDevices(iops); err != nil { - return err - } - } - - if iops := c.DeviceWriteIOPs; len(iops) > 0 { - if s.ThrottleWriteIOPSDevice, err = parseThrottleIOPsDevices(iops); err != nil { - return err - } - } - - s.ResourceLimits.Memory.DisableOOMKiller = &c.OOMKillDisable - - // Rlimits/Ulimits - for _, u := range c.Ulimit { - if u == "host" { - s.Rlimits = nil - break - } - ul, err := units.ParseUlimit(u) - if err != nil { - return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u) - } - rl := specs.POSIXRlimit{ - Type: ul.Name, - Hard: uint64(ul.Hard), - Soft: uint64(ul.Soft), - } - s.Rlimits = append(s.Rlimits, rl) - } - - //Tmpfs: c.StringArray("tmpfs"), - - // TODO how to handle this? - //Syslog: c.Bool("syslog"), - - logOpts := make(map[string]string) - for _, o := range c.LogOptions { - split := strings.SplitN(o, "=", 2) - if len(split) < 2 { - return errors.Errorf("invalid log option %q", o) - } - logOpts[split[0]] = split[1] - } - s.LogConfiguration.Options = logOpts - s.Name = c.Name - - if err := parseWeightDevices(c.BlkIOWeightDevice, s); err != nil { - return err - } - - if s.ResourceLimits.CPU == nil { - s.ResourceLimits.CPU = &specs.LinuxCPU{} - } - s.ResourceLimits.CPU.Shares = &c.CPUShares - s.ResourceLimits.CPU.Period = &c.CPUPeriod - - // TODO research these - //s.ResourceLimits.CPU.Cpus = c.CPUS - //s.ResourceLimits.CPU.Cpus = c.CPUSetCPUs - - //s.ResourceLimits.CPU. = c.CPUSetCPUs - s.ResourceLimits.CPU.Mems = c.CPUSetMems - s.ResourceLimits.CPU.Quota = &c.CPUQuota - s.ResourceLimits.CPU.RealtimePeriod = &c.CPURTPeriod - s.ResourceLimits.CPU.RealtimeRuntime = &c.CPURTRuntime - s.OOMScoreAdj = &c.OOMScoreAdj - s.RestartPolicy = c.Restart - s.Remove = c.Rm - s.StopTimeout = &c.StopTimeout - - // TODO where should we do this? - //func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) { - return nil -} - -func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, startPeriod string) (*manifest.Schema2HealthConfig, error) { - // Every healthcheck requires a command - if len(inCmd) == 0 { - return nil, errors.New("Must define a healthcheck command for all healthchecks") - } - - // first try to parse option value as JSON array of strings... - cmd := []string{} - err := json.Unmarshal([]byte(inCmd), &cmd) - if err != nil { - // ...otherwise pass it to "/bin/sh -c" inside the container - cmd = []string{"CMD-SHELL", inCmd} - } - hc := manifest.Schema2HealthConfig{ - Test: cmd, - } - - if interval == "disable" { - interval = "0" - } - intervalDuration, err := time.ParseDuration(interval) - if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-interval %s ", interval) - } - - hc.Interval = intervalDuration - - if retries < 1 { - return nil, errors.New("healthcheck-retries must be greater than 0.") - } - hc.Retries = int(retries) - timeoutDuration, err := time.ParseDuration(timeout) - if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-timeout %s", timeout) - } - if timeoutDuration < time.Duration(1) { - return nil, errors.New("healthcheck-timeout must be at least 1 second") - } - hc.Timeout = timeoutDuration - - startPeriodDuration, err := time.ParseDuration(startPeriod) - if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-start-period %s", startPeriod) - } - if startPeriodDuration < time.Duration(0) { - return nil, errors.New("healthcheck-start-period must be 0 seconds or greater") - } - hc.StartPeriod = startPeriodDuration - - return &hc, nil -} - -func parseWeightDevices(weightDevs []string, s *specgen.SpecGenerator) error { - for _, val := range weightDevs { - split := strings.SplitN(val, ":", 2) - if len(split) != 2 { - return fmt.Errorf("bad format: %s", val) - } - if !strings.HasPrefix(split[0], "/dev/") { - return fmt.Errorf("bad format for device path: %s", val) - } - weight, err := strconv.ParseUint(split[1], 10, 0) - if err != nil { - return fmt.Errorf("invalid weight for device: %s", val) - } - if weight > 0 && (weight < 10 || weight > 1000) { - return fmt.Errorf("invalid weight for device: %s", val) - } - w := uint16(weight) - s.WeightDevice[split[0]] = specs.LinuxWeightDevice{ - Weight: &w, - LeafWeight: nil, - } - } - return nil -} - -func parseThrottleBPSDevices(bpsDevices []string) (map[string]specs.LinuxThrottleDevice, error) { - td := make(map[string]specs.LinuxThrottleDevice) - for _, val := range bpsDevices { - split := strings.SplitN(val, ":", 2) - if len(split) != 2 { - return nil, fmt.Errorf("bad format: %s", val) - } - if !strings.HasPrefix(split[0], "/dev/") { - return nil, fmt.Errorf("bad format for device path: %s", val) - } - rate, err := units.RAMInBytes(split[1]) - if err != nil { - return nil, fmt.Errorf("invalid rate for device: %s. The correct format is <device-path>:<number>[<unit>]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb", val) - } - if rate < 0 { - return nil, fmt.Errorf("invalid rate for device: %s. The correct format is <device-path>:<number>[<unit>]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb", val) - } - td[split[0]] = specs.LinuxThrottleDevice{Rate: uint64(rate)} - } - return td, nil -} - -func parseThrottleIOPsDevices(iopsDevices []string) (map[string]specs.LinuxThrottleDevice, error) { - td := make(map[string]specs.LinuxThrottleDevice) - for _, val := range iopsDevices { - split := strings.SplitN(val, ":", 2) - if len(split) != 2 { - return nil, fmt.Errorf("bad format: %s", val) - } - if !strings.HasPrefix(split[0], "/dev/") { - return nil, fmt.Errorf("bad format for device path: %s", val) - } - rate, err := strconv.ParseUint(split[1], 10, 64) - if err != nil { - return nil, fmt.Errorf("invalid rate for device: %s. The correct format is <device-path>:<number>. Number must be a positive integer", val) - } - td[split[0]] = specs.LinuxThrottleDevice{Rate: rate} - } - return td, nil -} diff --git a/cmd/podmanV2/common/types.go b/cmd/podmanV2/common/types.go deleted file mode 100644 index 2427ae975..000000000 --- a/cmd/podmanV2/common/types.go +++ /dev/null @@ -1,3 +0,0 @@ -package common - -var DefaultKernelNamespaces = "cgroup,ipc,net,uts" diff --git a/cmd/podmanV2/common/util.go b/cmd/podmanV2/common/util.go deleted file mode 100644 index 47bbe12fa..000000000 --- a/cmd/podmanV2/common/util.go +++ /dev/null @@ -1,43 +0,0 @@ -package common - -import ( - "strconv" - - "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/docker/go-connections/nat" - "github.com/pkg/errors" -) - -// createPortBindings iterates ports mappings and exposed ports into a format CNI understands -func createPortBindings(ports []string) ([]ocicni.PortMapping, error) { - // TODO wants someone to rewrite this code in the future - var portBindings []ocicni.PortMapping - // The conversion from []string to natBindings is temporary while mheon reworks the port - // deduplication code. Eventually that step will not be required. - _, natBindings, err := nat.ParsePortSpecs(ports) - if err != nil { - return nil, err - } - for containerPb, hostPb := range natBindings { - var pm ocicni.PortMapping - pm.ContainerPort = int32(containerPb.Int()) - for _, i := range hostPb { - var hostPort int - var err error - pm.HostIP = i.HostIP - if i.HostPort == "" { - hostPort = containerPb.Int() - } else { - hostPort, err = strconv.Atoi(i.HostPort) - if err != nil { - return nil, errors.Wrapf(err, "unable to convert host port to integer") - } - } - - pm.HostPort = int32(hostPort) - pm.Protocol = containerPb.Proto() - portBindings = append(portBindings, pm) - } - } - return portBindings, nil -} diff --git a/cmd/podmanV2/containers/attach.go b/cmd/podmanV2/containers/attach.go deleted file mode 100644 index 9b6de0051..000000000 --- a/cmd/podmanV2/containers/attach.go +++ /dev/null @@ -1,59 +0,0 @@ -package containers - -import ( - "os" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively." - attachCommand = &cobra.Command{ - Use: "attach [flags] CONTAINER", - Short: "Attach to a running container", - Long: attachDescription, - RunE: attach, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) > 1 || (len(args) == 0 && !cmd.Flag("latest").Changed) { - return errors.Errorf("attach requires the name or id of one running container or the latest flag") - } - return nil - }, - Example: `podman attach ctrID - podman attach 1234 - podman attach --no-stdin foobar`, - } -) - -var ( - attachOpts entities.AttachOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: attachCommand, - }) - flags := attachCommand.Flags() - flags.StringVar(&attachOpts.DetachKeys, "detach-keys", common.GetDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") - flags.BoolVar(&attachOpts.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") - flags.BoolVar(&attachOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process") - flags.BoolVarP(&attachOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func attach(cmd *cobra.Command, args []string) error { - attachOpts.Stdin = os.Stdin - if attachOpts.NoStdin { - attachOpts.Stdin = nil - } - attachOpts.Stdout = os.Stdout - attachOpts.Stderr = os.Stderr - return registry.ContainerEngine().ContainerAttach(registry.GetContext(), args[0], attachOpts) -} diff --git a/cmd/podmanV2/containers/checkpoint.go b/cmd/podmanV2/containers/checkpoint.go deleted file mode 100644 index 7c3e551bc..000000000 --- a/cmd/podmanV2/containers/checkpoint.go +++ /dev/null @@ -1,79 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - checkpointDescription = ` - podman container checkpoint - - Checkpoints one or more running containers. The container name or ID can be used. -` - checkpointCommand = &cobra.Command{ - Use: "checkpoint [flags] CONTAINER [CONTAINER...]", - Short: "Checkpoints one or more containers", - Long: checkpointDescription, - RunE: checkpoint, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman container checkpoint --keep ctrID - podman container checkpoint --all - podman container checkpoint --leave-running --latest`, - } -) - -var ( - checkpointOptions entities.CheckpointOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: checkpointCommand, - Parent: containerCmd, - }) - flags := checkpointCommand.Flags() - flags.BoolVarP(&checkpointOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files") - flags.BoolVarP(&checkpointOptions.LeaveRuninng, "leave-running", "R", false, "Leave the container running after writing checkpoint to disk") - flags.BoolVar(&checkpointOptions.TCPEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections") - flags.BoolVarP(&checkpointOptions.All, "all", "a", false, "Checkpoint all running containers") - flags.BoolVarP(&checkpointOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.StringVarP(&checkpointOptions.Export, "export", "e", "", "Export the checkpoint image to a tar.gz") - flags.BoolVar(&checkpointOptions.IgnoreRootFS, "ignore-rootfs", false, "Do not include root file-system changes when exporting") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func checkpoint(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors - if rootless.IsRootless() { - return errors.New("checkpointing a container requires root") - } - if checkpointOptions.Export == "" && checkpointOptions.IgnoreRootFS { - return errors.Errorf("--ignore-rootfs can only be used with --export") - } - responses, err := registry.ContainerEngine().ContainerCheckpoint(context.Background(), args, checkpointOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/cleanup.go b/cmd/podmanV2/containers/cleanup.go deleted file mode 100644 index 3f45db160..000000000 --- a/cmd/podmanV2/containers/cleanup.go +++ /dev/null @@ -1,75 +0,0 @@ -package containers - -import ( - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - cleanupDescription = ` - podman container cleanup - - Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits. -` - cleanupCommand = &cobra.Command{ - Use: "cleanup [flags] CONTAINER [CONTAINER...]", - Short: "Cleanup network and mountpoints of one or more containers", - Long: cleanupDescription, - RunE: cleanup, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman container cleanup --latest - podman container cleanup ctrID1 ctrID2 ctrID3 - podman container cleanup --all`, - } -) - -var ( - cleanupOptions entities.ContainerCleanupOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Parent: containerCmd, - Command: cleanupCommand, - }) - flags := cleanupCommand.Flags() - flags.BoolVarP(&cleanupOptions.All, "all", "a", false, "Cleans up all containers") - flags.BoolVarP(&cleanupOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&cleanupOptions.Remove, "rm", false, "After cleanup, remove the container entirely") - flags.BoolVar(&cleanupOptions.RemoveImage, "rmi", false, "After cleanup, remove the image entirely") - -} - -func cleanup(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().ContainerCleanup(registry.GetContext(), args, cleanupOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.CleanErr == nil && r.RmErr == nil && r.RmiErr == nil { - fmt.Println(r.Id) - continue - } - if r.RmErr != nil { - errs = append(errs, r.RmErr) - } - if r.RmiErr != nil { - errs = append(errs, r.RmiErr) - } - if r.CleanErr != nil { - errs = append(errs, r.CleanErr) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/commit.go b/cmd/podmanV2/containers/commit.go deleted file mode 100644 index 083fcbc6c..000000000 --- a/cmd/podmanV2/containers/commit.go +++ /dev/null @@ -1,78 +0,0 @@ -package containers - -import ( - "context" - "fmt" - "io/ioutil" - "os" - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - commitDescription = `Create an image from a container's changes. Optionally tag the image created, set the author with the --author flag, set the commit message with the --message flag, and make changes to the instructions with the --change flag.` - - commitCommand = &cobra.Command{ - Use: "commit [flags] CONTAINER [IMAGE]", - Short: "Create new image based on the changed container", - Long: commitDescription, - RunE: commit, - Args: cobra.MinimumNArgs(1), - Example: `podman commit -q --message "committing container to image" reverent_golick image-committed - podman commit -q --author "firstName lastName" reverent_golick image-committed - podman commit -q --pause=false containerID image-committed - podman commit containerID`, - } - - // ChangeCmds is the list of valid Changes commands to passed to the Commit call - ChangeCmds = []string{"CMD", "ENTRYPOINT", "ENV", "EXPOSE", "LABEL", "ONBUILD", "STOPSIGNAL", "USER", "VOLUME", "WORKDIR"} -) - -var ( - commitOptions = entities.CommitOptions{ - ImageName: "", - } - iidFile string -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: commitCommand, - }) - flags := commitCommand.Flags() - flags.StringArrayVarP(&commitOptions.Changes, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): "+strings.Join(ChangeCmds, " | ")) - flags.StringVarP(&commitOptions.Format, "format", "f", "oci", "`Format` of the image manifest and metadata") - flags.StringVarP(&iidFile, "iidfile", "", "", "`file` to write the image ID to") - flags.StringVarP(&commitOptions.Message, "message", "m", "", "Set commit message for imported image") - flags.StringVarP(&commitOptions.Author, "author", "a", "", "Set the author for the image committed") - flags.BoolVarP(&commitOptions.Pause, "pause", "p", false, "Pause container during commit") - flags.BoolVarP(&commitOptions.Quiet, "quiet", "q", false, "Suppress output") - flags.BoolVar(&commitOptions.IncludeVolumes, "include-volumes", false, "Include container volumes as image volumes") - -} -func commit(cmd *cobra.Command, args []string) error { - container := args[0] - if len(args) > 1 { - commitOptions.ImageName = args[1] - } - if !commitOptions.Quiet { - commitOptions.Writer = os.Stderr - } - - response, err := registry.ContainerEngine().ContainerCommit(context.Background(), container, commitOptions) - if err != nil { - return err - } - if len(iidFile) > 0 { - if err = ioutil.WriteFile(iidFile, []byte(response.Id), 0644); err != nil { - return errors.Wrapf(err, "failed to write image ID to file %q", iidFile) - } - } - fmt.Println(response.Id) - return nil -} diff --git a/cmd/podmanV2/containers/container.go b/cmd/podmanV2/containers/container.go deleted file mode 100644 index 30829991d..000000000 --- a/cmd/podmanV2/containers/container.go +++ /dev/null @@ -1,40 +0,0 @@ -package containers - -import ( - "os" - - "github.com/containers/common/pkg/config" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var ( - // Command: podman _container_ - containerCmd = &cobra.Command{ - Use: "container", - Short: "Manage containers", - Long: "Manage containers", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } - - defaultContainerConfig = getDefaultContainerConfig() -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: containerCmd, - }) -} - -func getDefaultContainerConfig() *config.Config { - defaultContainerConfig, err := config.Default() - if err != nil { - logrus.Error(err) - os.Exit(1) - } - return defaultContainerConfig -} diff --git a/cmd/podmanV2/containers/create.go b/cmd/podmanV2/containers/create.go deleted file mode 100644 index 8cfb74539..000000000 --- a/cmd/podmanV2/containers/create.go +++ /dev/null @@ -1,102 +0,0 @@ -package containers - -import ( - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/specgen" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var ( - createDescription = `Creates a new container from the given image or storage and prepares it for running the specified command. - - The container ID is then printed to stdout. You can then start it at any time with the podman start <container_id> command. The container will be created with the initial state 'created'.` - createCommand = &cobra.Command{ - Use: "create [flags] IMAGE [COMMAND [ARG...]]", - Short: "Create but do not start a container", - Long: createDescription, - RunE: create, - Args: cobra.MinimumNArgs(1), - Example: `podman create alpine ls - podman create --annotation HELLO=WORLD alpine ls - podman create -t -i --name myctr alpine ls`, - } -) - -var ( - cliVals common.ContainerCLIOpts -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: createCommand, - }) - //common.GetCreateFlags(createCommand) - flags := createCommand.Flags() - flags.SetInterspersed(false) - flags.AddFlagSet(common.GetCreateFlags(&cliVals)) - flags.AddFlagSet(common.GetNetFlags()) - flags.SetNormalizeFunc(common.AliasFlags) -} - -func create(cmd *cobra.Command, args []string) error { - var ( - err error - rawImageInput string - ) - cliVals.Net, err = common.NetFlagsToNetOptions(cmd) - if err != nil { - return err - } - if rfs := cliVals.RootFS; !rfs { - rawImageInput = args[0] - } - - if err := createInit(cmd); err != nil { - return err - } - //TODO rootfs still - s := specgen.NewSpecGenerator(rawImageInput) - if err := common.FillOutSpecGen(s, &cliVals, args); err != nil { - return err - } - - report, err := registry.ContainerEngine().ContainerCreate(registry.GetContext(), s) - if err != nil { - return err - } - fmt.Println(report.Id) - return nil -} - -func createInit(c *cobra.Command) error { - if c.Flag("privileged").Changed && c.Flag("security-opt").Changed { - logrus.Warn("setting security options with --privileged has no effect") - } - - if (c.Flag("dns").Changed || c.Flag("dns-opt").Changed || c.Flag("dns-search").Changed) && (cliVals.Net.Network.NSMode == specgen.NoNetwork || cliVals.Net.Network.IsContainer()) { - return errors.Errorf("conflicting options: dns and the network mode.") - } - - if c.Flag("cpu-period").Changed && c.Flag("cpus").Changed { - return errors.Errorf("--cpu-period and --cpus cannot be set together") - } - if c.Flag("cpu-quota").Changed && c.Flag("cpus").Changed { - return errors.Errorf("--cpu-quota and --cpus cannot be set together") - } - - if c.Flag("no-hosts").Changed && c.Flag("add-host").Changed { - return errors.Errorf("--no-hosts and --add-host cannot be set together") - } - - // Docker-compatibility: the "-h" flag for run/create is reserved for - // the hostname (see https://github.com/containers/libpod/issues/1367). - - return nil -} diff --git a/cmd/podmanV2/containers/diff.go b/cmd/podmanV2/containers/diff.go deleted file mode 100644 index eb76858f3..000000000 --- a/cmd/podmanV2/containers/diff.go +++ /dev/null @@ -1,66 +0,0 @@ -package containers - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/report" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - // podman container _diff_ - diffCmd = &cobra.Command{ - Use: "diff [flags] CONTAINER", - Args: registry.IdOrLatestArgs, - Short: "Inspect changes on container's file systems", - Long: `Displays changes on a container filesystem. The container will be compared to its parent layer.`, - RunE: diff, - Example: `podman container diff myCtr - podman container diff -l --format json myCtr`, - } - diffOpts *entities.DiffOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: diffCmd, - Parent: containerCmd, - }) - - diffOpts = &entities.DiffOptions{} - flags := diffCmd.Flags() - flags.BoolVar(&diffOpts.Archive, "archive", true, "Save the diff as a tar archive") - _ = flags.MarkHidden("archive") - flags.StringVar(&diffOpts.Format, "format", "", "Change the output format") - - if !registry.IsRemote() { - flags.BoolVarP(&diffOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - } -} - -func diff(cmd *cobra.Command, args []string) error { - if len(args) == 0 && !diffOpts.Latest { - return errors.New("container must be specified: podman container diff [options [...]] ID-NAME") - } - - results, err := registry.ContainerEngine().ContainerDiff(registry.GetContext(), args[0], entities.DiffOptions{}) - if err != nil { - return err - } - - switch diffOpts.Format { - case "": - return report.ChangesToTable(results) - case "json": - return report.ChangesToJSON(results) - default: - return errors.New("only supported value for '--format' is 'json'") - } -} - -func Diff(cmd *cobra.Command, args []string, options entities.DiffOptions) error { - diffOpts = &options - return diff(cmd, args) -} diff --git a/cmd/podmanV2/containers/exec.go b/cmd/podmanV2/containers/exec.go deleted file mode 100644 index b4583909e..000000000 --- a/cmd/podmanV2/containers/exec.go +++ /dev/null @@ -1,92 +0,0 @@ -package containers - -import ( - "bufio" - "os" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - envLib "github.com/containers/libpod/pkg/env" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - execDescription = `Execute the specified command inside a running container. -` - execCommand = &cobra.Command{ - Use: "exec [flags] CONTAINER [COMMAND [ARG...]]", - Short: "Run a process in a running container", - Long: execDescription, - RunE: exec, - Example: `podman exec -it ctrID ls - podman exec -it -w /tmp myCtr pwd - podman exec --user root ctrID ls`, - } -) - -var ( - envInput, envFile []string - execOpts entities.ExecOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: execCommand, - }) - flags := execCommand.Flags() - flags.SetInterspersed(false) - flags.StringVar(&execOpts.DetachKeys, "detach-keys", common.GetDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") - flags.StringArrayVarP(&envInput, "env", "e", []string{}, "Set environment variables") - flags.StringSliceVar(&envFile, "env-file", []string{}, "Read in a file of environment variables") - flags.BoolVarP(&execOpts.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") - flags.BoolVarP(&execOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&execOpts.Privileged, "privileged", false, "Give the process extended Linux capabilities inside the container. The default is false") - flags.BoolVarP(&execOpts.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false") - flags.StringVarP(&execOpts.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command") - flags.UintVar(&execOpts.PreserveFDs, "preserve-fds", 0, "Pass N additional file descriptors to the container") - flags.StringVarP(&execOpts.WorkDir, "workdir", "w", "", "Working directory inside the container") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - _ = flags.MarkHidden("preserve-fds") - } - -} -func exec(cmd *cobra.Command, args []string) error { - var nameOrId string - execOpts.Cmd = args - if !execOpts.Latest { - execOpts.Cmd = args[1:] - nameOrId = args[0] - } - // Validate given environment variables - execOpts.Envs = make(map[string]string) - for _, f := range envFile { - fileEnv, err := envLib.ParseFile(f) - if err != nil { - return err - } - execOpts.Envs = envLib.Join(execOpts.Envs, fileEnv) - } - - cliEnv, err := envLib.ParseSlice(envInput) - if err != nil { - return errors.Wrap(err, "error parsing environment variables") - } - - execOpts.Envs = envLib.Join(execOpts.Envs, cliEnv) - execOpts.Streams.OutputStream = os.Stdout - execOpts.Streams.ErrorStream = os.Stderr - if execOpts.Interactive { - execOpts.Streams.InputStream = bufio.NewReader(os.Stdin) - execOpts.Streams.AttachInput = true - } - execOpts.Streams.AttachOutput = true - execOpts.Streams.AttachError = true - - exitCode, err := registry.ContainerEngine().ContainerExec(registry.GetContext(), nameOrId, execOpts) - registry.SetExitCode(exitCode) - return err -} diff --git a/cmd/podmanV2/containers/exists.go b/cmd/podmanV2/containers/exists.go deleted file mode 100644 index 22c798fcd..000000000 --- a/cmd/podmanV2/containers/exists.go +++ /dev/null @@ -1,43 +0,0 @@ -package containers - -import ( - "context" - "os" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - containerExistsDescription = `If the named container exists in local storage, podman container exists exits with 0, otherwise the exit code will be 1.` - - existsCommand = &cobra.Command{ - Use: "exists CONTAINER", - Short: "Check if a container exists in local storage", - Long: containerExistsDescription, - Example: `podman container exists containerID - podman container exists myctr || podman run --name myctr [etc...]`, - RunE: exists, - Args: cobra.ExactArgs(1), - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: existsCommand, - Parent: containerCmd, - }) -} - -func exists(cmd *cobra.Command, args []string) error { - response, err := registry.ContainerEngine().ContainerExists(context.Background(), args[0]) - if err != nil { - return err - } - if !response.Value { - os.Exit(1) - } - return nil -} diff --git a/cmd/podmanV2/containers/export.go b/cmd/podmanV2/containers/export.go deleted file mode 100644 index a7befdae9..000000000 --- a/cmd/podmanV2/containers/export.go +++ /dev/null @@ -1,54 +0,0 @@ -package containers - -import ( - "context" - "os" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" -) - -var ( - exportDescription = "Exports container's filesystem contents as a tar archive" + - " and saves it on the local machine." - - exportCommand = &cobra.Command{ - Use: "export [flags] CONTAINER", - Short: "Export container's filesystem contents as a tar archive", - Long: exportDescription, - RunE: export, - Args: cobra.ExactArgs(1), - Example: `podman export ctrID > myCtr.tar - podman export --output="myCtr.tar" ctrID`, - } -) - -var ( - exportOpts entities.ContainerExportOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: exportCommand, - }) - flags := exportCommand.Flags() - flags.StringVarP(&exportOpts.Output, "output", "o", "", "Write to a specified file (default: stdout, which must be redirected)") -} - -func export(cmd *cobra.Command, args []string) error { - if len(exportOpts.Output) == 0 { - file := os.Stdout - if terminal.IsTerminal(int(file.Fd())) { - return errors.Errorf("refusing to export to terminal. Use -o flag or redirect") - } - exportOpts.Output = "/dev/stdout" - } else if err := parse.ValidateFileName(exportOpts.Output); err != nil { - return err - } - return registry.ContainerEngine().ContainerExport(context.Background(), args[0], exportOpts) -} diff --git a/cmd/podmanV2/containers/init.go b/cmd/podmanV2/containers/init.go deleted file mode 100644 index 0060c8f09..000000000 --- a/cmd/podmanV2/containers/init.go +++ /dev/null @@ -1,59 +0,0 @@ -package containers - -import ( - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - initDescription = `Initialize one or more containers, creating the OCI spec and mounts for inspection. Container names or IDs can be used.` - - initCommand = &cobra.Command{ - Use: "init [flags] CONTAINER [CONTAINER...]", - Short: "Initialize one or more containers", - Long: initDescription, - RunE: initContainer, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman init --latest - podman init 3c45ef19d893 - podman init test1`, - } -) - -var ( - initOptions entities.ContainerInitOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: initCommand, - }) - flags := initCommand.Flags() - flags.BoolVarP(&initOptions.All, "all", "a", false, "Initialize all containers") - flags.BoolVarP(&initOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - _ = flags.MarkHidden("latest") -} - -func initContainer(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors - report, err := registry.ContainerEngine().ContainerInit(registry.GetContext(), args, initOptions) - if err != nil { - return err - } - for _, r := range report { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/inspect.go b/cmd/podmanV2/containers/inspect.go deleted file mode 100644 index e6d4cb6bc..000000000 --- a/cmd/podmanV2/containers/inspect.go +++ /dev/null @@ -1,78 +0,0 @@ -package containers - -import ( - "context" - "fmt" - "os" - "strings" - "text/template" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - - "github.com/containers/libpod/pkg/domain/entities" - json "github.com/json-iterator/go" - "github.com/spf13/cobra" -) - -var ( - // podman container _inspect_ - inspectCmd = &cobra.Command{ - Use: "inspect [flags] CONTAINER", - Short: "Display the configuration of a container", - Long: `Displays the low-level information on a container identified by name or ID.`, - RunE: inspect, - Example: `podman container inspect myCtr - podman container inspect -l --format '{{.Id}} {{.Config.Labels}}'`, - } - inspectOpts *entities.InspectOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: inspectCmd, - Parent: containerCmd, - }) - inspectOpts = common.AddInspectFlagSet(inspectCmd) - flags := inspectCmd.Flags() - - if !registry.IsRemote() { - flags.BoolVarP(&inspectOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - } - -} - -func inspect(cmd *cobra.Command, args []string) error { - responses, err := registry.ContainerEngine().ContainerInspect(context.Background(), args, *inspectOpts) - if err != nil { - return err - } - if inspectOpts.Format == "" { - b, err := json.MarshalIndent(responses, "", " ") - if err != nil { - return err - } - fmt.Println(string(b)) - return nil - } - format := inspectOpts.Format - if !strings.HasSuffix(format, "\n") { - format += "\n" - } - tmpl, err := template.New("inspect").Parse(format) - if err != nil { - return err - } - for _, i := range responses { - if err := tmpl.Execute(os.Stdout, i); err != nil { - return err - } - } - return nil -} - -func Inspect(cmd *cobra.Command, args []string, options *entities.InspectOptions) error { - inspectOpts = options - return inspect(cmd, args) -} diff --git a/cmd/podmanV2/containers/kill.go b/cmd/podmanV2/containers/kill.go deleted file mode 100644 index e145fbc3f..000000000 --- a/cmd/podmanV2/containers/kill.go +++ /dev/null @@ -1,76 +0,0 @@ -package containers - -import ( - "context" - "errors" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/signal" - "github.com/spf13/cobra" -) - -var ( - killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal." - killCommand = &cobra.Command{ - Use: "kill [flags] CONTAINER [CONTAINER...]", - Short: "Kill one or more running containers with a specific signal", - Long: killDescription, - RunE: kill, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman kill mywebserver - podman kill 860a4b23 - podman kill --signal TERM ctrID`, - } -) - -var ( - killOptions = entities.KillOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: killCommand, - }) - flags := killCommand.Flags() - flags.BoolVarP(&killOptions.All, "all", "a", false, "Signal all running containers") - flags.StringVarP(&killOptions.Signal, "signal", "s", "KILL", "Signal to send to the container") - flags.BoolVarP(&killOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func kill(cmd *cobra.Command, args []string) error { - var ( - err error - errs utils.OutputErrors - ) - // Check if the signalString provided by the user is valid - // Invalid signals will return err - sig, err := signal.ParseSignalNameOrNumber(killOptions.Signal) - if err != nil { - return err - } - if sig < 1 || sig > 64 { - return errors.New("valid signals are 1 through 64") - } - responses, err := registry.ContainerEngine().ContainerKill(context.Background(), args, killOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/list.go b/cmd/podmanV2/containers/list.go deleted file mode 100644 index 630d9bbc7..000000000 --- a/cmd/podmanV2/containers/list.go +++ /dev/null @@ -1,34 +0,0 @@ -package containers - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // podman container _list_ - listCmd = &cobra.Command{ - Use: "list", - Aliases: []string{"ls"}, - Args: cobra.NoArgs, - Short: "List containers", - Long: "Prints out information about the containers", - RunE: containers, - Example: `podman container list -a - podman container list -a --format "{{.ID}} {{.Image}} {{.Labels}} {{.Mounts}}" - podman container list --size --sort names`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: listCmd, - Parent: containerCmd, - }) -} - -func containers(cmd *cobra.Command, args []string) error { - return nil -} diff --git a/cmd/podmanV2/containers/logs.go b/cmd/podmanV2/containers/logs.go deleted file mode 100644 index db549c03b..000000000 --- a/cmd/podmanV2/containers/logs.go +++ /dev/null @@ -1,103 +0,0 @@ -package containers - -import ( - "os" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/util" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// logsOptionsWrapper wraps entities.LogsOptions and prevents leaking -// CLI-only fields into the API types. -type logsOptionsWrapper struct { - entities.ContainerLogsOptions - - SinceRaw string -} - -var ( - logsOptions logsOptionsWrapper - logsDescription = `Retrieves logs for one or more containers. - - This does not guarantee execution order when combined with podman run (i.e., your run may not have generated any logs at the time you execute podman logs). -` - logsCommand = &cobra.Command{ - Use: "logs [flags] CONTAINER [CONTAINER...]", - Short: "Fetch the logs of one or more container", - Long: logsDescription, - RunE: logs, - Example: `podman logs ctrID - podman logs --names ctrID1 ctrID2 - podman logs --tail 2 mywebserver - podman logs --follow=true --since 10m ctrID - podman logs mywebserver mydbserver`, - } - - containerLogsCommand = &cobra.Command{ - Use: logsCommand.Use, - Short: logsCommand.Short, - Long: logsCommand.Long, - RunE: logsCommand.RunE, - Example: `podman container logs ctrID - podman container logs --names ctrID1 ctrID2 - podman container logs --tail 2 mywebserver - podman container logs --follow=true --since 10m ctrID - podman container logs mywebserver mydbserver`, - } -) - -func init() { - // logs - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: logsCommand, - }) - - flags := logsCommand.Flags() - logsFlags(flags) - - // container logs - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: containerLogsCommand, - Parent: containerCmd, - }) - - containerLogsFlags := containerLogsCommand.Flags() - logsFlags(containerLogsFlags) -} - -func logsFlags(flags *pflag.FlagSet) { - flags.BoolVar(&logsOptions.Details, "details", false, "Show extra details provided to the logs") - flags.BoolVarP(&logsOptions.Follow, "follow", "f", false, "Follow log output. The default is false") - flags.BoolVarP(&logsOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.StringVar(&logsOptions.SinceRaw, "since", "", "Show logs since TIMESTAMP") - flags.Int64Var(&logsOptions.Tail, "tail", -1, "Output the specified number of LINES at the end of the logs. Defaults to -1, which prints all lines") - flags.BoolVarP(&logsOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") - flags.BoolVarP(&logsOptions.Names, "names", "n", false, "Output the container name in the log") - flags.SetInterspersed(false) - _ = flags.MarkHidden("details") -} - -func logs(cmd *cobra.Command, args []string) error { - if len(args) > 0 && logsOptions.Latest { - return errors.New("no containers can be specified when using 'latest'") - } - if !logsOptions.Latest && len(args) < 1 { - return errors.New("specify at least one container name or ID to log") - } - if logsOptions.SinceRaw != "" { - // parse time, error out if something is wrong - since, err := util.ParseInputTime(logsOptions.SinceRaw) - if err != nil { - return errors.Wrapf(err, "error parsing --since %q", logsOptions.SinceRaw) - } - logsOptions.Since = since - } - logsOptions.Writer = os.Stdout - return registry.ContainerEngine().ContainerLogs(registry.GetContext(), args, logsOptions.ContainerLogsOptions) -} diff --git a/cmd/podmanV2/containers/mount.go b/cmd/podmanV2/containers/mount.go deleted file mode 100644 index dbd83de57..000000000 --- a/cmd/podmanV2/containers/mount.go +++ /dev/null @@ -1,123 +0,0 @@ -package containers - -import ( - "encoding/json" - "fmt" - "os" - "text/tabwriter" - "text/template" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - mountDescription = `podman mount - Lists all mounted containers mount points if no container is specified - - podman mount CONTAINER-NAME-OR-ID - Mounts the specified container and outputs the mountpoint -` - - mountCommand = &cobra.Command{ - Use: "mount [flags] [CONTAINER]", - Short: "Mount a working container's root filesystem", - Long: mountDescription, - RunE: mount, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, true, false) - }, - Annotations: map[string]string{ - registry.ParentNSRequired: "", - }, - } -) - -var ( - mountOpts entities.ContainerMountOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: mountCommand, - }) - flags := mountCommand.Flags() - flags.BoolVarP(&mountOpts.All, "all", "a", false, "Mount all containers") - flags.StringVar(&mountOpts.Format, "format", "", "Change the output format to Go template") - flags.BoolVarP(&mountOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&mountOpts.NoTruncate, "notruncate", false, "Do not truncate output") -} - -func mount(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - mrs []mountReporter - ) - reports, err := registry.ContainerEngine().ContainerMount(registry.GetContext(), args, mountOpts) - if err != nil { - return err - } - if len(args) > 0 || mountOpts.Latest || mountOpts.All { - for _, r := range reports { - if r.Err == nil { - fmt.Println(r.Path) - continue - } - errs = append(errs, r.Err) - } - return errs.PrintErrors() - } - if mountOpts.Format == "json" { - return printJSON(reports) - } - for _, r := range reports { - mrs = append(mrs, mountReporter{r}) - } - row := "{{.ID}} {{.Path}}" - format := "{{range . }}" + row + "{{end}}" - tmpl, err := template.New("mounts").Parse(format) - if err != nil { - return err - } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - defer w.Flush() - return tmpl.Execute(w, mrs) -} - -func printJSON(reports []*entities.ContainerMountReport) error { - type jreport struct { - ID string `json:"id"` - Names []string - Mountpoint string `json:"mountpoint"` - } - var jreports []jreport - - for _, r := range reports { - jreports = append(jreports, jreport{ - ID: r.Id, - Names: []string{r.Name}, - Mountpoint: r.Path, - }) - } - b, err := json.MarshalIndent(jreports, "", " ") - if err != nil { - return err - } - fmt.Println(string(b)) - return nil -} - -type mountReporter struct { - *entities.ContainerMountReport -} - -func (m mountReporter) ID() string { - if mountOpts.NoTruncate { - return m.Id - } - return m.Id[0:12] -} diff --git a/cmd/podmanV2/containers/pause.go b/cmd/podmanV2/containers/pause.go deleted file mode 100644 index d5493167c..000000000 --- a/cmd/podmanV2/containers/pause.go +++ /dev/null @@ -1,61 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - pauseDescription = `Pauses one or more running containers. The container name or ID can be used.` - pauseCommand = &cobra.Command{ - Use: "pause [flags] CONTAINER [CONTAINER...]", - Short: "Pause all the processes in one or more containers", - Long: pauseDescription, - RunE: pause, - Example: `podman pause mywebserver - podman pause 860a4b23 - podman pause -a`, - } - - pauseOpts = entities.PauseUnPauseOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pauseCommand, - }) - flags := pauseCommand.Flags() - flags.BoolVarP(&pauseOpts.All, "all", "a", false, "Pause all running containers") -} - -func pause(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - if rootless.IsRootless() && !registry.IsRemote() { - return errors.New("pause is not supported for rootless containers") - } - if len(args) < 1 && !pauseOpts.All { - return errors.Errorf("you must provide at least one container name or id") - } - responses, err := registry.ContainerEngine().ContainerPause(context.Background(), args, pauseOpts) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/prune.go b/cmd/podmanV2/containers/prune.go deleted file mode 100644 index 2d3af5d1d..000000000 --- a/cmd/podmanV2/containers/prune.go +++ /dev/null @@ -1,86 +0,0 @@ -package containers - -import ( - "bufio" - "context" - "fmt" - "net/url" - "os" - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - pruneDescription = fmt.Sprintf(`podman container prune - - Removes all stopped | exited containers`) - pruneCommand = &cobra.Command{ - Use: "prune [flags]", - Short: "Remove all stopped | exited containers", - Long: pruneDescription, - RunE: prune, - Example: `podman container prune`, - } - force bool - filter = []string{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pruneCommand, - Parent: containerCmd, - }) - flags := pruneCommand.Flags() - flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation. The default is false") - flags.StringArrayVar(&filter, "filter", []string{}, "Provide filter values (e.g. 'label=<key>=<value>')") -} - -func prune(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - pruneOptions = entities.ContainerPruneOptions{} - ) - if len(args) > 0 { - return errors.Errorf("`%s` takes no arguments", cmd.CommandPath()) - } - if !force { - reader := bufio.NewReader(os.Stdin) - fmt.Println("WARNING! This will remove all stopped containers.") - fmt.Print("Are you sure you want to continue? [y/N] ") - answer, err := reader.ReadString('\n') - if err != nil { - return errors.Wrapf(err, "error reading input") - } - if strings.ToLower(answer)[0] != 'y' { - return nil - } - } - - // TODO Remove once filter refactor is finished and url.Values done. - for _, f := range filter { - t := strings.SplitN(f, "=", 2) - pruneOptions.Filters = make(url.Values) - if len(t) < 2 { - return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) - } - pruneOptions.Filters.Add(t[0], t[1]) - } - responses, err := registry.ContainerEngine().ContainerPrune(context.Background(), pruneOptions) - - if err != nil { - return err - } - for k := range responses.ID { - fmt.Println(k) - } - for _, v := range responses.Err { - errs = append(errs, v) - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/ps.go b/cmd/podmanV2/containers/ps.go deleted file mode 100644 index 355b1b4be..000000000 --- a/cmd/podmanV2/containers/ps.go +++ /dev/null @@ -1,413 +0,0 @@ -package containers - -import ( - "encoding/json" - "fmt" - "os" - "sort" - "strconv" - "strings" - "text/tabwriter" - "text/template" - "time" - - tm "github.com/buger/goterm" - "github.com/containers/buildah/pkg/formats" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/cri-o/ocicni/pkg/ocicni" - "github.com/docker/go-units" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - psDescription = "Prints out information about the containers" - psCommand = &cobra.Command{ - Use: "ps", - Args: checkFlags, - Short: "List containers", - Long: psDescription, - RunE: ps, - Example: `podman ps -a - podman ps -a --format "{{.ID}} {{.Image}} {{.Labels}} {{.Mounts}}" - podman ps --size --sort names`, - } -) -var ( - listOpts = entities.ContainerListOptions{ - Filters: make(map[string][]string), - } - filters []string - noTrunc bool - defaultHeaders string = "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES" -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: psCommand, - }) - flags := psCommand.Flags() - flags.BoolVarP(&listOpts.All, "all", "a", false, "Show all the containers, default is only running containers") - flags.StringSliceVarP(&filters, "filter", "f", []string{}, "Filter output based on conditions given") - flags.StringVar(&listOpts.Format, "format", "", "Pretty-print containers to JSON or using a Go template") - flags.IntVarP(&listOpts.Last, "last", "n", -1, "Print the n last created containers (all states)") - flags.BoolVarP(&listOpts.Latest, "latest", "l", false, "Show the latest container created (all states)") - flags.BoolVar(&listOpts.Namespace, "namespace", false, "Display namespace information") - flags.BoolVar(&listOpts.Namespace, "ns", false, "Display namespace information") - flags.BoolVar(&noTrunc, "no-trunc", false, "Display the extended information") - flags.BoolVarP(&listOpts.Pod, "pod", "p", false, "Print the ID and name of the pod the containers are associated with") - flags.BoolVarP(&listOpts.Quiet, "quiet", "q", false, "Print the numeric IDs of the containers only") - flags.BoolVarP(&listOpts.Size, "size", "s", false, "Display the total file sizes") - flags.StringVar(&listOpts.Sort, "sort", "created", "Sort output by command, created, id, image, names, runningfor, size, or status") - flags.BoolVar(&listOpts.Sync, "sync", false, "Sync container state with OCI runtime") - flags.UintVarP(&listOpts.Watch, "watch", "w", 0, "Watch the ps output on an interval in seconds") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} -func checkFlags(c *cobra.Command, args []string) error { - // latest, and last are mutually exclusive. - if listOpts.Last >= 0 && listOpts.Latest { - return errors.Errorf("last and latest are mutually exclusive") - } - // Filter on status forces all - for _, filter := range filters { - splitFilter := strings.SplitN(filter, "=", 2) - if strings.ToLower(splitFilter[0]) == "status" { - listOpts.All = true - break - } - } - // Quiet conflicts with size and namespace and is overridden by a Go - // template. - if listOpts.Quiet { - if listOpts.Size || listOpts.Namespace { - return errors.Errorf("quiet conflicts with size and namespace") - } - if c.Flag("format").Changed && listOpts.Format != formats.JSONString { - // Quiet is overridden by Go template output. - listOpts.Quiet = false - } - } - // Size and namespace conflict with each other - if listOpts.Size && listOpts.Namespace { - return errors.Errorf("size and namespace options conflict") - } - - if listOpts.Watch > 0 && listOpts.Latest { - return errors.New("the watch and latest flags cannot be used together") - } - return nil -} - -func jsonOut(responses []entities.ListContainer) error { - b, err := json.MarshalIndent(responses, "", " ") - if err != nil { - return err - } - fmt.Println(string(b)) - return nil -} - -func quietOut(responses []entities.ListContainer) error { - for _, r := range responses { - id := r.ID - if !noTrunc { - id = id[0:12] - } - fmt.Println(id) - } - return nil -} - -func getResponses() ([]entities.ListContainer, error) { - responses, err := registry.ContainerEngine().ContainerList(registry.GetContext(), listOpts) - if err != nil { - return nil, err - } - if len(listOpts.Sort) > 0 { - responses, err = entities.SortPsOutput(listOpts.Sort, responses) - if err != nil { - return nil, err - } - } - return responses, nil -} - -func ps(cmd *cobra.Command, args []string) error { - var responses []psReporter - for _, f := range filters { - split := strings.SplitN(f, "=", 2) - if len(split) == 1 { - return errors.Errorf("invalid filter %q", f) - } - listOpts.Filters[split[0]] = append(listOpts.Filters[split[0]], split[1]) - } - listContainers, err := getResponses() - if err != nil { - return err - } - if len(listOpts.Sort) > 0 { - listContainers, err = entities.SortPsOutput(listOpts.Sort, listContainers) - if err != nil { - return err - } - } - if listOpts.Format == "json" { - return jsonOut(listContainers) - } - if listOpts.Quiet { - return quietOut(listContainers) - } - - for _, r := range listContainers { - responses = append(responses, psReporter{r}) - } - - headers, row := createPsOut() - if cmd.Flag("format").Changed { - row = listOpts.Format - if !strings.HasPrefix(row, "\n") { - row += "\n" - } - } - format := "{{range . }}" + row + "{{end}}" - if !listOpts.Quiet && !cmd.Flag("format").Changed { - format = headers + format - } - tmpl, err := template.New("listContainers").Parse(format) - if err != nil { - return err - } - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - if listOpts.Watch > 0 { - for { - var responses []psReporter - tm.Clear() - tm.MoveCursor(1, 1) - tm.Flush() - listContainers, err := getResponses() - for _, r := range listContainers { - responses = append(responses, psReporter{r}) - } - if err != nil { - return err - } - if err := tmpl.Execute(w, responses); err != nil { - return nil - } - if err := w.Flush(); err != nil { - return err - } - time.Sleep(time.Duration(listOpts.Watch) * time.Second) - tm.Clear() - tm.MoveCursor(1, 1) - tm.Flush() - } - } else if listOpts.Watch < 1 { - if err := tmpl.Execute(w, responses); err != nil { - return err - } - return w.Flush() - } - return nil -} - -func createPsOut() (string, string) { - var row string - if listOpts.Namespace { - headers := "CONTAINER ID\tNAMES\tPID\tCGROUPNS\tIPC\tMNT\tNET\tPIDN\tUSERNS\tUTS\n" - row := "{{.ID}}\t{{.Names}}\t{{.Pid}}\t{{.Namespaces.Cgroup}}\t{{.Namespaces.IPC}}\t{{.Namespaces.MNT}}\t{{.Namespaces.NET}}\t{{.Namespaces.PIDNS}}\t{{.Namespaces.User}}\t{{.Namespaces.UTS}}\n" - return headers, row - } - headers := defaultHeaders - row += "{{.ID}}" - row += "\t{{.Image}}\t{{.Command}}\t{{.CreatedHuman}}\t{{.State}}\t{{.Ports}}\t{{.Names}}" - - if listOpts.Pod { - headers += "\tPOD ID\tPODNAME" - row += "\t{{.Pod}}\t{{.PodName}}" - } - - if listOpts.Size { - headers += "\tSIZE" - row += "\t{{.Size}}" - } - if !strings.HasSuffix(headers, "\n") { - headers += "\n" - } - if !strings.HasSuffix(row, "\n") { - row += "\n" - } - return headers, row -} - -type psReporter struct { - entities.ListContainer -} - -// ID returns the ID of the container -func (l psReporter) ID() string { - if !noTrunc { - return l.ListContainer.ID[0:12] - } - return l.ListContainer.ID -} - -// Pod returns the ID of the pod the container -// belongs to and appropriately truncates the ID -func (l psReporter) Pod() string { - if !noTrunc && len(l.ListContainer.Pod) > 0 { - return l.ListContainer.Pod[0:12] - } - return l.ListContainer.Pod -} - -// State returns the container state in human duration -func (l psReporter) State() string { - var state string - switch l.ListContainer.State { - case "running": - t := units.HumanDuration(time.Since(time.Unix(l.StartedAt, 0))) - state = "Up " + t + " ago" - case "configured": - state = "Created" - case "exited", "stopped": - t := units.HumanDuration(time.Since(time.Unix(l.ExitedAt, 0))) - state = fmt.Sprintf("Exited (%d) %s ago", l.ExitCode, t) - default: - state = l.ListContainer.State - } - return state -} - -// Command returns the container command in string format -func (l psReporter) Command() string { - return strings.Join(l.ListContainer.Command, " ") -} - -// Size returns the rootfs and virtual sizes in human duration in -// and output form (string) suitable for ps -func (l psReporter) Size() string { - virt := units.HumanSizeWithPrecision(float64(l.ListContainer.Size.RootFsSize), 3) - s := units.HumanSizeWithPrecision(float64(l.ListContainer.Size.RwSize), 3) - return fmt.Sprintf("%s (virtual %s)", s, virt) -} - -// Names returns the container name in string format -func (l psReporter) Names() string { - return l.ListContainer.Names[0] -} - -// Ports converts from Portmappings to the string form -// required by ps -func (l psReporter) Ports() string { - if len(l.ListContainer.Ports) < 1 { - return "" - } - return portsToString(l.ListContainer.Ports) -} - -// CreatedAt returns the container creation time in string format. podman -// and docker both return a timestamped value for createdat -func (l psReporter) CreatedAt() string { - return time.Unix(l.Created, 0).String() -} - -// CreateHuman allows us to output the created time in human readable format -func (l psReporter) CreatedHuman() string { - return units.HumanDuration(time.Since(time.Unix(l.Created, 0))) + " ago" -} - -// portsToString converts the ports used to a string of the from "port1, port2" -// and also groups a continuous list of ports into a readable format. -func portsToString(ports []ocicni.PortMapping) string { - type portGroup struct { - first int32 - last int32 - } - var portDisplay []string - if len(ports) == 0 { - return "" - } - //Sort the ports, so grouping continuous ports become easy. - sort.Slice(ports, func(i, j int) bool { - return comparePorts(ports[i], ports[j]) - }) - - // portGroupMap is used for grouping continuous ports. - portGroupMap := make(map[string]*portGroup) - var groupKeyList []string - - for _, v := range ports { - - hostIP := v.HostIP - if hostIP == "" { - hostIP = "0.0.0.0" - } - // If hostPort and containerPort are not same, consider as individual port. - if v.ContainerPort != v.HostPort { - portDisplay = append(portDisplay, fmt.Sprintf("%s:%d->%d/%s", hostIP, v.HostPort, v.ContainerPort, v.Protocol)) - continue - } - - portMapKey := fmt.Sprintf("%s/%s", hostIP, v.Protocol) - - portgroup, ok := portGroupMap[portMapKey] - if !ok { - portGroupMap[portMapKey] = &portGroup{first: v.ContainerPort, last: v.ContainerPort} - // This list is required to traverse portGroupMap. - groupKeyList = append(groupKeyList, portMapKey) - continue - } - - if portgroup.last == (v.ContainerPort - 1) { - portgroup.last = v.ContainerPort - continue - } - } - // For each portMapKey, format group list and appned to output string. - for _, portKey := range groupKeyList { - group := portGroupMap[portKey] - portDisplay = append(portDisplay, formatGroup(portKey, group.first, group.last)) - } - return strings.Join(portDisplay, ", ") -} - -func comparePorts(i, j ocicni.PortMapping) bool { - if i.ContainerPort != j.ContainerPort { - return i.ContainerPort < j.ContainerPort - } - - if i.HostIP != j.HostIP { - return i.HostIP < j.HostIP - } - - if i.HostPort != j.HostPort { - return i.HostPort < j.HostPort - } - - return i.Protocol < j.Protocol -} - -// formatGroup returns the group as <IP:startPort:lastPort->startPort:lastPort/Proto> -// e.g 0.0.0.0:1000-1006->1000-1006/tcp. -func formatGroup(key string, start, last int32) string { - parts := strings.Split(key, "/") - groupType := parts[0] - var ip string - if len(parts) > 1 { - ip = parts[0] - groupType = parts[1] - } - group := strconv.Itoa(int(start)) - if start != last { - group = fmt.Sprintf("%s-%d", group, last) - } - if ip != "" { - group = fmt.Sprintf("%s:%s->%s", ip, group, group) - } - return fmt.Sprintf("%s/%s", group, groupType) -} diff --git a/cmd/podmanV2/containers/restart.go b/cmd/podmanV2/containers/restart.go deleted file mode 100644 index becc56616..000000000 --- a/cmd/podmanV2/containers/restart.go +++ /dev/null @@ -1,79 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - restartDescription = fmt.Sprintf(`Restarts one or more running containers. The container ID or name can be used. - - A timeout before forcibly stopping can be set, but defaults to %d seconds.`, defaultContainerConfig.Engine.StopTimeout) - - restartCommand = &cobra.Command{ - Use: "restart [flags] CONTAINER [CONTAINER...]", - Short: "Restart one or more containers", - Long: restartDescription, - RunE: restart, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman restart ctrID - podman restart --latest - podman restart ctrID1 ctrID2`, - } -) - -var ( - restartOptions = entities.RestartOptions{} - restartTimeout uint -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: restartCommand, - }) - flags := restartCommand.Flags() - flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all non-running containers") - flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&restartOptions.Running, "running", false, "Restart only running containers when --all is used") - flags.UintVarP(&restartTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } - flags.SetNormalizeFunc(utils.AliasFlags) -} - -func restart(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - if len(args) < 1 && !restartOptions.Latest && !restartOptions.All { - return errors.Wrapf(define.ErrInvalidArg, "you must provide at least one container name or ID") - } - - if cmd.Flag("time").Changed { - restartOptions.Timeout = &restartTimeout - } - responses, err := registry.ContainerEngine().ContainerRestart(context.Background(), args, restartOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/restore.go b/cmd/podmanV2/containers/restore.go deleted file mode 100644 index 6cab6ab50..000000000 --- a/cmd/podmanV2/containers/restore.go +++ /dev/null @@ -1,104 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - restoreDescription = ` - podman container restore - - Restores a container from a checkpoint. The container name or ID can be used. -` - restoreCommand = &cobra.Command{ - Use: "restore [flags] CONTAINER [CONTAINER...]", - Short: "Restores one or more containers from a checkpoint", - Long: restoreDescription, - RunE: restore, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, true, false) - }, - Example: `podman container restore ctrID - podman container restore --latest - podman container restore --all`, - } -) - -var ( - restoreOptions entities.RestoreOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: restoreCommand, - Parent: containerCmd, - }) - flags := restoreCommand.Flags() - flags.BoolVarP(&restoreOptions.All, "all", "a", false, "Restore all checkpointed containers") - flags.BoolVarP(&restoreOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files") - flags.BoolVarP(&restoreOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&restoreOptions.TCPEstablished, "tcp-established", false, "Restore a container with established TCP connections") - flags.StringVarP(&restoreOptions.Import, "import", "i", "", "Restore from exported checkpoint archive (tar.gz)") - flags.StringVarP(&restoreOptions.Name, "name", "n", "", "Specify new name for container restored from exported checkpoint (only works with --import)") - flags.BoolVar(&restoreOptions.IgnoreRootFS, "ignore-rootfs", false, "Do not apply root file-system changes when importing from exported checkpoint") - flags.BoolVar(&restoreOptions.IgnoreStaticIP, "ignore-static-ip", false, "Ignore IP address set via --static-ip") - flags.BoolVar(&restoreOptions.IgnoreStaticMAC, "ignore-static-mac", false, "Ignore MAC address set via --mac-address") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func restore(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors - if rootless.IsRootless() { - return errors.New("restoring a container requires root") - } - if restoreOptions.Import == "" && restoreOptions.IgnoreRootFS { - return errors.Errorf("--ignore-rootfs can only be used with --import") - } - if restoreOptions.Import == "" && restoreOptions.Name != "" { - return errors.Errorf("--name can only be used with --import") - } - if restoreOptions.Name != "" && restoreOptions.TCPEstablished { - return errors.Errorf("--tcp-established cannot be used with --name") - } - - argLen := len(args) - if restoreOptions.Import != "" { - if restoreOptions.All || restoreOptions.Latest { - return errors.Errorf("Cannot use --import with --all or --latest") - } - if argLen > 0 { - return errors.Errorf("Cannot use --import with positional arguments") - } - } - if (restoreOptions.All || restoreOptions.Latest) && argLen > 0 { - return errors.Errorf("no arguments are needed with --all or --latest") - } - if argLen < 1 && !restoreOptions.All && !restoreOptions.Latest && restoreOptions.Import == "" { - return errors.Errorf("you must provide at least one name or id") - } - responses, err := registry.ContainerEngine().ContainerRestore(context.Background(), args, restoreOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() - -} diff --git a/cmd/podmanV2/containers/rm.go b/cmd/podmanV2/containers/rm.go deleted file mode 100644 index 916dd2577..000000000 --- a/cmd/podmanV2/containers/rm.go +++ /dev/null @@ -1,93 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var ( - rmDescription = `Removes one or more containers from the host. The container name or ID can be used. - - Command does not remove images. Running or unusable containers will not be removed without the -f option.` - rmCommand = &cobra.Command{ - Use: "rm [flags] CONTAINER [CONTAINER...]", - Short: "Remove one or more containers", - Long: rmDescription, - RunE: rm, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, true) - }, - Example: `podman rm imageID - podman rm mywebserver myflaskserver 860a4b23 - podman rm --force --all - podman rm -f c684f0d469f2`, - } -) - -var ( - rmOptions = entities.RmOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: rmCommand, - }) - flags := rmCommand.Flags() - flags.BoolVarP(&rmOptions.All, "all", "a", false, "Remove all containers") - flags.BoolVarP(&rmOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") - flags.BoolVarP(&rmOptions.Force, "force", "f", false, "Force removal of a running or unusable container. The default is false") - flags.BoolVarP(&rmOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&rmOptions.Storage, "storage", false, "Remove container from storage library") - flags.BoolVarP(&rmOptions.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container") - flags.StringArrayVarP(&rmOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - _ = flags.MarkHidden("ignore") - _ = flags.MarkHidden("cidfile") - _ = flags.MarkHidden("storage") - } - -} - -func rm(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - // Storage conflicts with --all/--latest/--volumes/--cidfile/--ignore - if rmOptions.Storage { - if rmOptions.All || rmOptions.Ignore || rmOptions.Latest || rmOptions.Volumes || rmOptions.CIDFiles != nil { - return errors.Errorf("--storage conflicts with --volumes, --all, --latest, --ignore and --cidfile") - } - } - responses, err := registry.ContainerEngine().ContainerRm(context.Background(), args, rmOptions) - if err != nil { - // TODO exitcode is a global main variable to track exit codes. - // we need this enabled - //if len(c.InputArgs) < 2 { - // exitCode = setExitCode(err) - //} - return err - } - for _, r := range responses { - if r.Err != nil { - // TODO this will not work with the remote client - if errors.Cause(err) == define.ErrWillDeadlock { - logrus.Errorf("Potential deadlock detected - please run 'podman system renumber' to resolve") - } - errs = append(errs, r.Err) - } else { - fmt.Println(r.Id) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/run.go b/cmd/podmanV2/containers/run.go deleted file mode 100644 index ca9db88f8..000000000 --- a/cmd/podmanV2/containers/run.go +++ /dev/null @@ -1,147 +0,0 @@ -package containers - -import ( - "fmt" - "os" - "strings" - - "github.com/containers/common/pkg/config" - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/specgen" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var ( - runDescription = "Runs a command in a new container from the given image" - runCommand = &cobra.Command{ - Use: "run [flags] IMAGE [COMMAND [ARG...]]", - Short: "Run a command in a new container", - Long: runDescription, - RunE: run, - Example: `podman run imageID ls -alF /etc - podman run --network=host imageID dnf -y install java - podman run --volume /var/hostdir:/var/ctrdir -i -t fedora /bin/bash`, - } -) - -var ( - runOpts = entities.ContainerRunOptions{ - OutputStream: os.Stdout, - InputStream: os.Stdin, - ErrorStream: os.Stderr, - } - runRmi bool -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: runCommand, - }) - flags := runCommand.Flags() - flags.SetInterspersed(false) - flags.AddFlagSet(common.GetCreateFlags(&cliVals)) - flags.AddFlagSet(common.GetNetFlags()) - flags.SetNormalizeFunc(common.AliasFlags) - flags.BoolVar(&runOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process") - flags.BoolVar(&runRmi, "rmi", false, "Remove container image unless used by other containers") - if registry.IsRemote() { - _ = flags.MarkHidden("authfile") - } -} - -func run(cmd *cobra.Command, args []string) error { - var err error - cliVals.Net, err = common.NetFlagsToNetOptions(cmd) - if err != nil { - return err - } - - if af := cliVals.Authfile; len(af) > 0 { - if _, err := os.Stat(af); err != nil { - return errors.Wrapf(err, "error checking authfile path %s", af) - } - } - runOpts.Rm = cliVals.Rm - if err := createInit(cmd); err != nil { - return err - } - - br, err := registry.ImageEngine().Exists(registry.GetContext(), args[0]) - if err != nil { - return err - } - pullPolicy, err := config.ValidatePullPolicy(cliVals.Pull) - if err != nil { - return err - } - if !br.Value || pullPolicy == config.PullImageAlways { - if pullPolicy == config.PullImageNever { - return errors.New("unable to find a name and tag match for busybox in repotags: no such image") - } - _, pullErr := registry.ImageEngine().Pull(registry.GetContext(), args[0], entities.ImagePullOptions{ - Authfile: cliVals.Authfile, - Quiet: cliVals.Quiet, - }) - if pullErr != nil { - return pullErr - } - } - // If -i is not set, clear stdin - if !cliVals.Interactive { - runOpts.InputStream = nil - } - - // If attach is set, clear stdin/stdout/stderr and only attach requested - if cmd.Flag("attach").Changed { - runOpts.OutputStream = nil - runOpts.ErrorStream = nil - if !cliVals.Interactive { - runOpts.InputStream = nil - } - - for _, stream := range cliVals.Attach { - switch strings.ToLower(stream) { - case "stdout": - runOpts.OutputStream = os.Stdout - case "stderr": - runOpts.ErrorStream = os.Stderr - case "stdin": - runOpts.InputStream = os.Stdin - default: - return errors.Wrapf(define.ErrInvalidArg, "invalid stream %q for --attach - must be one of stdin, stdout, or stderr", stream) - } - } - } - runOpts.Detach = cliVals.Detach - runOpts.DetachKeys = cliVals.DetachKeys - s := specgen.NewSpecGenerator(args[0]) - if err := common.FillOutSpecGen(s, &cliVals, args); err != nil { - return err - } - runOpts.Spec = s - - report, err := registry.ContainerEngine().ContainerRun(registry.GetContext(), runOpts) - // report.ExitCode is set by ContainerRun even it it returns an error - if report != nil { - registry.SetExitCode(report.ExitCode) - } - if err != nil { - return err - } - if cliVals.Detach { - fmt.Println(report.Id) - } - if runRmi { - _, err := registry.ImageEngine().Delete(registry.GetContext(), []string{args[0]}, entities.ImageDeleteOptions{}) - if err != nil { - logrus.Errorf("%s", errors.Wrapf(err, "failed removing image")) - } - } - return nil -} diff --git a/cmd/podmanV2/containers/start.go b/cmd/podmanV2/containers/start.go deleted file mode 100644 index b5ed6d6f6..000000000 --- a/cmd/podmanV2/containers/start.go +++ /dev/null @@ -1,86 +0,0 @@ -package containers - -import ( - "fmt" - "os" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - startDescription = `Starts one or more containers. The container name or ID can be used.` - startCommand = &cobra.Command{ - Use: "start [flags] CONTAINER [CONTAINER...]", - Short: "Start one or more containers", - Long: startDescription, - RunE: start, - Args: cobra.MinimumNArgs(1), - Example: `podman start --latest - podman start 860a4b231279 5421ab43b45 - podman start --interactive --attach imageID`, - } -) - -var ( - startOptions entities.ContainerStartOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: startCommand, - }) - flags := startCommand.Flags() - flags.BoolVarP(&startOptions.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR") - flags.StringVar(&startOptions.DetachKeys, "detach-keys", common.GetDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") - flags.BoolVarP(&startOptions.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") - flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.BoolVar(&startOptions.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - _ = flags.MarkHidden("sig-proxy") - } - -} - -func start(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors - if len(args) > 1 && startOptions.Attach { - return errors.Errorf("you cannot start and attach multiple containers at once") - } - - sigProxy := startOptions.SigProxy || startOptions.Attach - if cmd.Flag("sig-proxy").Changed { - sigProxy = startOptions.SigProxy - } - - if sigProxy && !startOptions.Attach { - return errors.Wrapf(define.ErrInvalidArg, "you cannot use sig-proxy without --attach") - } - if startOptions.Attach { - startOptions.Stdin = os.Stdin - startOptions.Stderr = os.Stderr - startOptions.Stdout = os.Stdout - } - - responses, err := registry.ContainerEngine().ContainerStart(registry.GetContext(), args, startOptions) - if err != nil { - return err - } - - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - // TODO need to understand an implement exitcodes - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/stop.go b/cmd/podmanV2/containers/stop.go deleted file mode 100644 index d94df69be..000000000 --- a/cmd/podmanV2/containers/stop.go +++ /dev/null @@ -1,77 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - stopDescription = fmt.Sprintf(`Stops one or more running containers. The container name or ID can be used. - - A timeout to forcibly stop the container can also be set but defaults to %d seconds otherwise.`, defaultContainerConfig.Engine.StopTimeout) - stopCommand = &cobra.Command{ - Use: "stop [flags] CONTAINER [CONTAINER...]", - Short: "Stop one or more containers", - Long: stopDescription, - RunE: stop, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, true) - }, - Example: `podman stop ctrID - podman stop --latest - podman stop --time 2 mywebserver 6e534f14da9d`, - } -) - -var ( - stopOptions = entities.StopOptions{} - stopTimeout uint -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: stopCommand, - }) - flags := stopCommand.Flags() - flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running containers") - flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") - flags.StringArrayVarP(&stopOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") - flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.UintVarP(&stopTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") - if registry.PodmanOptions.EngineMode == entities.ABIMode { - _ = flags.MarkHidden("latest") - _ = flags.MarkHidden("cidfile") - _ = flags.MarkHidden("ignore") - } - flags.SetNormalizeFunc(utils.AliasFlags) -} - -func stop(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - stopOptions.Timeout = defaultContainerConfig.Engine.StopTimeout - if cmd.Flag("time").Changed { - stopOptions.Timeout = stopTimeout - } - - responses, err := registry.ContainerEngine().ContainerStop(context.Background(), args, stopOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/top.go b/cmd/podmanV2/containers/top.go deleted file mode 100644 index 233085e75..000000000 --- a/cmd/podmanV2/containers/top.go +++ /dev/null @@ -1,87 +0,0 @@ -package containers - -import ( - "context" - "fmt" - "os" - "strings" - "text/tabwriter" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/psgo" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - topDescription = fmt.Sprintf(`Similar to system "top" command. - - Specify format descriptors to alter the output. - - Running "podman top -l pid pcpu seccomp" will print the process ID, the CPU percentage and the seccomp mode of each process of the latest container. - Format Descriptors: - %s`, strings.Join(psgo.ListDescriptors(), ",")) - - topOptions = entities.TopOptions{} - - topCommand = &cobra.Command{ - Use: "top [flags] CONTAINER [FORMAT-DESCRIPTORS|ARGS]", - Short: "Display the running processes of a container", - Long: topDescription, - RunE: top, - Args: cobra.ArbitraryArgs, - Example: `podman top ctrID -podman top --latest -podman top ctrID pid seccomp args %C -podman top ctrID -eo user,pid,comm`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: topCommand, - }) - - flags := topCommand.Flags() - flags.SetInterspersed(false) - flags.BoolVar(&topOptions.ListDescriptors, "list-descriptors", false, "") - flags.BoolVarP(&topOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - - _ = flags.MarkHidden("list-descriptors") // meant only for bash completion - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func top(cmd *cobra.Command, args []string) error { - if topOptions.ListDescriptors { - fmt.Println(strings.Join(psgo.ListDescriptors(), "\n")) - return nil - } - - if len(args) < 1 && !topOptions.Latest { - return errors.Errorf("you must provide the name or id of a running container") - } - - if topOptions.Latest { - topOptions.Descriptors = args - } else { - topOptions.NameOrID = args[0] - topOptions.Descriptors = args[1:] - } - - topResponse, err := registry.ContainerEngine().ContainerTop(context.Background(), topOptions) - if err != nil { - return err - } - - w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) - for _, proc := range topResponse.Value { - if _, err := fmt.Fprintln(w, proc); err != nil { - return err - } - } - return w.Flush() -} diff --git a/cmd/podmanV2/containers/unmount.go b/cmd/podmanV2/containers/unmount.go deleted file mode 100644 index ef6add950..000000000 --- a/cmd/podmanV2/containers/unmount.go +++ /dev/null @@ -1,64 +0,0 @@ -package containers - -import ( - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - description = `Container storage increments a mount counter each time a container is mounted. - - When a container is unmounted, the mount counter is decremented. The container's root filesystem is physically unmounted only when the mount counter reaches zero indicating no other processes are using the mount. - - An unmount can be forced with the --force flag. -` - umountCommand = &cobra.Command{ - Use: "umount [flags] CONTAINER [CONTAINER...]", - Aliases: []string{"unmount"}, - Short: "Unmounts working container's root filesystem", - Long: description, - RunE: unmount, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman umount ctrID - podman umount ctrID1 ctrID2 ctrID3 - podman umount --all`, - } -) - -var ( - unmountOpts entities.ContainerUnmountOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: umountCommand, - }) - flags := umountCommand.Flags() - flags.BoolVarP(&unmountOpts.All, "all", "a", false, "Umount all of the currently mounted containers") - flags.BoolVarP(&unmountOpts.Force, "force", "f", false, "Force the complete umount all of the currently mounted containers") - flags.BoolVarP(&unmountOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") -} - -func unmount(cmd *cobra.Command, args []string) error { - var errs utils.OutputErrors - reports, err := registry.ContainerEngine().ContainerUnmount(registry.GetContext(), args, unmountOpts) - if err != nil { - return err - } - for _, r := range reports { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/unpause.go b/cmd/podmanV2/containers/unpause.go deleted file mode 100644 index 8b8cde9b2..000000000 --- a/cmd/podmanV2/containers/unpause.go +++ /dev/null @@ -1,60 +0,0 @@ -package containers - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - unpauseDescription = `Unpauses one or more previously paused containers. The container name or ID can be used.` - unpauseCommand = &cobra.Command{ - Use: "unpause [flags] CONTAINER [CONTAINER...]", - Short: "Unpause the processes in one or more containers", - Long: unpauseDescription, - RunE: unpause, - Example: `podman unpause ctrID - podman unpause --all`, - } - unPauseOptions = entities.PauseUnPauseOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: unpauseCommand, - Parent: containerCmd, - }) - flags := unpauseCommand.Flags() - flags.BoolVarP(&unPauseOptions.All, "all", "a", false, "Pause all running containers") -} - -func unpause(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - if rootless.IsRootless() && !registry.IsRemote() { - return errors.New("unpause is not supported for rootless containers") - } - if len(args) < 1 && !unPauseOptions.All { - return errors.Errorf("you must provide at least one container name or id") - } - responses, err := registry.ContainerEngine().ContainerUnpause(context.Background(), args, unPauseOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/containers/utils.go b/cmd/podmanV2/containers/utils.go deleted file mode 100644 index 0c09d3e40..000000000 --- a/cmd/podmanV2/containers/utils.go +++ /dev/null @@ -1 +0,0 @@ -package containers diff --git a/cmd/podmanV2/containers/wait.go b/cmd/podmanV2/containers/wait.go deleted file mode 100644 index 0a165317b..000000000 --- a/cmd/podmanV2/containers/wait.go +++ /dev/null @@ -1,78 +0,0 @@ -package containers - -import ( - "context" - "fmt" - "time" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - waitDescription = `Block until one or more containers stop and then print their exit codes. -` - waitCommand = &cobra.Command{ - Use: "wait [flags] CONTAINER [CONTAINER...]", - Short: "Block on one or more containers", - Long: waitDescription, - RunE: wait, - Args: registry.IdOrLatestArgs, - Example: `podman wait --latest - podman wait --interval 5000 ctrID - podman wait ctrID1 ctrID2`, - } -) - -var ( - waitOptions = entities.WaitOptions{} - waitCondition string -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: waitCommand, - }) - - flags := waitCommand.Flags() - flags.DurationVarP(&waitOptions.Interval, "interval", "i", time.Duration(250), "Milliseconds to wait before polling for completion") - flags.BoolVarP(&waitOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.StringVar(&waitCondition, "condition", "stopped", "Condition to wait on") - if registry.PodmanOptions.EngineMode == entities.ABIMode { - // TODO: This is the same as V1. We could skip creating the flag altogether in V2... - _ = flags.MarkHidden("latest") - } -} - -func wait(cmd *cobra.Command, args []string) error { - var ( - err error - errs utils.OutputErrors - ) - if waitOptions.Interval == 0 { - return errors.New("interval must be greater then 0") - } - - waitOptions.Condition, err = define.StringToContainerStatus(waitCondition) - if err != nil { - return err - } - - responses, err := registry.ContainerEngine().ContainerWait(context.Background(), args, waitOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Error == nil { - fmt.Println(r.ExitCode) - } else { - errs = append(errs, r.Error) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/diff.go b/cmd/podmanV2/diff.go deleted file mode 100644 index 73f4661db..000000000 --- a/cmd/podmanV2/diff.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/containers" - "github.com/containers/libpod/cmd/podmanV2/images" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -// Inspect is one of the outlier commands in that it operates on images/containers/... - -var ( - // Command: podman _diff_ Object_ID - diffDescription = `Displays changes on a container or image's filesystem. The container or image will be compared to its parent layer.` - diffCmd = &cobra.Command{ - Use: "diff [flags] {CONTAINER_ID | IMAGE_ID}", - Args: registry.IdOrLatestArgs, - Short: "Display the changes of object's file system", - Long: diffDescription, - TraverseChildren: true, - RunE: diff, - Example: `podman diff imageID - podman diff ctrID - podman diff --format json redis:alpine`, - } - - diffOpts = entities.DiffOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: diffCmd, - }) - flags := diffCmd.Flags() - flags.BoolVar(&diffOpts.Archive, "archive", true, "Save the diff as a tar archive") - _ = flags.MarkHidden("archive") - flags.StringVar(&diffOpts.Format, "format", "", "Change the output format") - - if !registry.IsRemote() { - flags.BoolVarP(&diffOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - } -} - -func diff(cmd *cobra.Command, args []string) error { - if found, err := registry.ImageEngine().Exists(registry.GetContext(), args[0]); err != nil { - return err - } else if found.Value { - return images.Diff(cmd, args, diffOpts) - } - - if found, err := registry.ContainerEngine().ContainerExists(registry.GetContext(), args[0]); err != nil { - return err - } else if found.Value { - return containers.Diff(cmd, args, diffOpts) - } - return fmt.Errorf("%s not found on system", args[0]) -} diff --git a/cmd/podmanV2/healthcheck/healthcheck.go b/cmd/podmanV2/healthcheck/healthcheck.go deleted file mode 100644 index e859f9463..000000000 --- a/cmd/podmanV2/healthcheck/healthcheck.go +++ /dev/null @@ -1,25 +0,0 @@ -package healthcheck - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // Command: healthcheck - healthCmd = &cobra.Command{ - Use: "healthcheck", - Short: "Manage Healthcheck", - Long: "Manage Healthcheck", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: healthCmd, - }) -} diff --git a/cmd/podmanV2/healthcheck/run.go b/cmd/podmanV2/healthcheck/run.go deleted file mode 100644 index bb2962eaf..000000000 --- a/cmd/podmanV2/healthcheck/run.go +++ /dev/null @@ -1,42 +0,0 @@ -package healthcheck - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - healthcheckRunDescription = "run the health check of a container" - healthcheckrunCommand = &cobra.Command{ - Use: "run [flags] CONTAINER", - Short: "run the health check of a container", - Long: healthcheckRunDescription, - Example: `podman healthcheck run mywebapp`, - RunE: run, - Args: cobra.ExactArgs(1), - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: healthcheckrunCommand, - Parent: healthCmd, - }) -} - -func run(cmd *cobra.Command, args []string) error { - response, err := registry.ContainerEngine().HealthCheckRun(context.Background(), args[0], entities.HealthCheckOptions{}) - if err != nil { - return err - } - if response.Status == "unhealthy" { - registry.SetExitCode(1) - } - fmt.Println(response.Status) - return err -} diff --git a/cmd/podmanV2/images/diff.go b/cmd/podmanV2/images/diff.go deleted file mode 100644 index b54cb39a8..000000000 --- a/cmd/podmanV2/images/diff.go +++ /dev/null @@ -1,62 +0,0 @@ -package images - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/report" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - // podman container _inspect_ - diffCmd = &cobra.Command{ - Use: "diff [flags] CONTAINER", - Args: registry.IdOrLatestArgs, - Short: "Inspect changes on image's file systems", - Long: `Displays changes on a image's filesystem. The image will be compared to its parent layer.`, - RunE: diff, - Example: `podman image diff myImage - podman image diff --format json redis:alpine`, - } - diffOpts *entities.DiffOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: diffCmd, - Parent: imageCmd, - }) - - diffOpts = &entities.DiffOptions{} - flags := diffCmd.Flags() - flags.BoolVar(&diffOpts.Archive, "archive", true, "Save the diff as a tar archive") - _ = flags.MarkHidden("archive") - flags.StringVar(&diffOpts.Format, "format", "", "Change the output format") -} - -func diff(cmd *cobra.Command, args []string) error { - if len(args) == 0 && !diffOpts.Latest { - return errors.New("image must be specified: podman image diff [options [...]] ID-NAME") - } - - results, err := registry.ImageEngine().Diff(registry.GetContext(), args[0], entities.DiffOptions{}) - if err != nil { - return err - } - - switch diffOpts.Format { - case "": - return report.ChangesToTable(results) - case "json": - return report.ChangesToJSON(results) - default: - return errors.New("only supported value for '--format' is 'json'") - } -} - -func Diff(cmd *cobra.Command, args []string, options entities.DiffOptions) error { - diffOpts = &options - return diff(cmd, args) -} diff --git a/cmd/podmanV2/images/exists.go b/cmd/podmanV2/images/exists.go deleted file mode 100644 index d35d6825e..000000000 --- a/cmd/podmanV2/images/exists.go +++ /dev/null @@ -1,40 +0,0 @@ -package images - -import ( - "os" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - existsCmd = &cobra.Command{ - Use: "exists IMAGE", - Short: "Check if an image exists in local storage", - Long: `If the named image exists in local storage, podman image exists exits with 0, otherwise the exit code will be 1.`, - Args: cobra.ExactArgs(1), - RunE: exists, - Example: `podman image exists ID - podman image exists IMAGE && podman pull IMAGE`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: existsCmd, - Parent: imageCmd, - }) -} - -func exists(cmd *cobra.Command, args []string) error { - found, err := registry.ImageEngine().Exists(registry.GetContext(), args[0]) - if err != nil { - return err - } - if !found.Value { - os.Exit(1) - } - return nil -} diff --git a/cmd/podmanV2/images/history.go b/cmd/podmanV2/images/history.go deleted file mode 100644 index d2e880ef7..000000000 --- a/cmd/podmanV2/images/history.go +++ /dev/null @@ -1,152 +0,0 @@ -package images - -import ( - "context" - "fmt" - "os" - "strings" - "text/tabwriter" - "text/template" - "time" - "unicode" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/docker/go-units" - jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - long = `Displays the history of an image. - - The information can be printed out in an easy to read, or user specified format, and can be truncated.` - - // podman _history_ - historyCmd = &cobra.Command{ - Use: "history [flags] IMAGE", - Short: "Show history of a specified image", - Long: long, - Example: "podman history quay.io/fedora/fedora", - Args: cobra.ExactArgs(1), - RunE: history, - } - - opts = struct { - human bool - noTrunc bool - quiet bool - format string - }{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: historyCmd, - }) - - flags := historyCmd.Flags() - flags.StringVar(&opts.format, "format", "", "Change the output to JSON or a Go template") - flags.BoolVarP(&opts.human, "human", "H", true, "Display sizes and dates in human readable format") - flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate the output") - flags.BoolVar(&opts.noTrunc, "notruncate", false, "Do not truncate the output") - flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Display the numeric IDs only") -} - -func history(cmd *cobra.Command, args []string) error { - results, err := registry.ImageEngine().History(context.Background(), args[0], entities.ImageHistoryOptions{}) - if err != nil { - return err - } - - if opts.format == "json" { - var err error - if len(results.Layers) == 0 { - _, err = fmt.Fprintf(os.Stdout, "[]\n") - } else { - // ah-hoc change to "Created": type and format - type layer struct { - entities.ImageHistoryLayer - Created string `json:"Created"` - } - - layers := make([]layer, len(results.Layers)) - for i, l := range results.Layers { - layers[i].ImageHistoryLayer = l - layers[i].Created = l.Created.Format(time.RFC3339) - } - json := jsoniter.ConfigCompatibleWithStandardLibrary - enc := json.NewEncoder(os.Stdout) - err = enc.Encode(layers) - } - return err - } - var hr []historyreporter - for _, l := range results.Layers { - hr = append(hr, historyreporter{l}) - } - // Defaults - hdr := "ID\tCREATED\tCREATED BY\tSIZE\tCOMMENT\n" - row := "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" - - if len(opts.format) > 0 { - hdr = "" - row = opts.format - if !strings.HasSuffix(opts.format, "\n") { - row += "\n" - } - } else { - switch { - case opts.human: - row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" - case opts.noTrunc: - row = "{{.ID}}\t{{.Created}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}\n" - case opts.quiet: - hdr = "" - row = "{{.ID}}\n" - } - } - format := hdr + "{{range . }}" + row + "{{end}}" - - tmpl := template.Must(template.New("report").Parse(format)) - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - err = tmpl.Execute(w, hr) - if err != nil { - fmt.Fprintln(os.Stderr, errors.Wrapf(err, "Failed to print report")) - } - w.Flush() - return nil -} - -type historyreporter struct { - entities.ImageHistoryLayer -} - -func (h historyreporter) Created() string { - if opts.human { - return units.HumanDuration(time.Since(h.ImageHistoryLayer.Created)) + " ago" - } - return h.ImageHistoryLayer.Created.Format(time.RFC3339) -} - -func (h historyreporter) Size() string { - s := units.HumanSizeWithPrecision(float64(h.ImageHistoryLayer.Size), 3) - i := strings.LastIndexFunc(s, unicode.IsNumber) - return s[:i+1] + " " + s[i+1:] -} - -func (h historyreporter) CreatedBy() string { - if len(h.ImageHistoryLayer.CreatedBy) > 45 { - return h.ImageHistoryLayer.CreatedBy[:45-3] + "..." - } - return h.ImageHistoryLayer.CreatedBy -} - -func (h historyreporter) ID() string { - if !opts.noTrunc && len(h.ImageHistoryLayer.ID) >= 12 { - return h.ImageHistoryLayer.ID[0:12] - } - return h.ImageHistoryLayer.ID -} diff --git a/cmd/podmanV2/images/image.go b/cmd/podmanV2/images/image.go deleted file mode 100644 index 7b469bc59..000000000 --- a/cmd/podmanV2/images/image.go +++ /dev/null @@ -1,25 +0,0 @@ -package images - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // Command: podman _image_ - imageCmd = &cobra.Command{ - Use: "image", - Short: "Manage images", - Long: "Manage images", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: imageCmd, - }) -} diff --git a/cmd/podmanV2/images/images.go b/cmd/podmanV2/images/images.go deleted file mode 100644 index 588369a7e..000000000 --- a/cmd/podmanV2/images/images.go +++ /dev/null @@ -1,30 +0,0 @@ -package images - -import ( - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // podman _images_ Alias for podman image _list_ - imagesCmd = &cobra.Command{ - Use: strings.Replace(listCmd.Use, "list", "images", 1), - Args: listCmd.Args, - Short: listCmd.Short, - Long: listCmd.Long, - RunE: listCmd.RunE, - Example: strings.Replace(listCmd.Example, "podman image list", "podman images", -1), - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: imagesCmd, - }) - - imageListFlagSet(imagesCmd.Flags()) -} diff --git a/cmd/podmanV2/images/import.go b/cmd/podmanV2/images/import.go deleted file mode 100644 index c86db34bf..000000000 --- a/cmd/podmanV2/images/import.go +++ /dev/null @@ -1,84 +0,0 @@ -package images - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/hashicorp/go-multierror" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - importDescription = `Create a container image from the contents of the specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz). - - Note remote tar balls can be specified, via web address. - Optionally tag the image. You can specify the instructions using the --change option.` - importCommand = &cobra.Command{ - Use: "import [flags] PATH [REFERENCE]", - Short: "Import a tarball to create a filesystem image", - Long: importDescription, - RunE: importCon, - Example: `podman import http://example.com/ctr.tar url-image - cat ctr.tar | podman -q import --message "importing the ctr.tar tarball" - image-imported - cat ctr.tar | podman import -`, - } -) - -var ( - importOpts entities.ImageImportOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: importCommand, - }) - - flags := importCommand.Flags() - flags.StringArrayVarP(&importOpts.Changes, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR") - flags.StringVarP(&importOpts.Message, "message", "m", "", "Set commit message for imported image") - flags.BoolVarP(&importOpts.Quiet, "quiet", "q", false, "Suppress output") -} - -func importCon(cmd *cobra.Command, args []string) error { - var ( - source string - reference string - ) - switch len(args) { - case 0: - return errors.Errorf("need to give the path to the tarball, or must specify a tarball of '-' for stdin") - case 1: - source = args[0] - case 2: - source = args[0] - // TODO when save is merged, we need to process reference - // like it is done in there or we end up with docker.io prepends - // instead of the localhost ones - reference = args[1] - default: - return errors.Errorf("too many arguments. Usage TARBALL [REFERENCE]") - } - errFileName := parse.ValidateFileName(source) - errURL := parse.ValidURL(source) - if errURL == nil { - importOpts.SourceIsURL = true - } - if errFileName != nil && errURL != nil { - return multierror.Append(errFileName, errURL) - } - - importOpts.Source = source - importOpts.Reference = reference - - response, err := registry.ImageEngine().Import(context.Background(), importOpts) - if err != nil { - return err - } - fmt.Println(response.Id) - return nil -} diff --git a/cmd/podmanV2/images/inspect.go b/cmd/podmanV2/images/inspect.go deleted file mode 100644 index 2ee2d86ee..000000000 --- a/cmd/podmanV2/images/inspect.go +++ /dev/null @@ -1,108 +0,0 @@ -package images - -import ( - "context" - "encoding/json" - "fmt" - "os" - "strings" - "text/tabwriter" - "text/template" - - "github.com/containers/buildah/pkg/formats" - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - // Command: podman image _inspect_ - inspectCmd = &cobra.Command{ - Use: "inspect [flags] IMAGE", - Short: "Display the configuration of an image", - Long: `Displays the low-level information on an image identified by name or ID.`, - RunE: inspect, - Example: `podman image inspect alpine`, - } - inspectOpts *entities.InspectOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: inspectCmd, - Parent: imageCmd, - }) - inspectOpts = common.AddInspectFlagSet(inspectCmd) -} - -func inspect(cmd *cobra.Command, args []string) error { - latestContainer := inspectOpts.Latest - - if len(args) == 0 && !latestContainer { - return errors.Errorf("container or image name must be specified: podman inspect [options [...]] name") - } - - if len(args) > 0 && latestContainer { - return errors.Errorf("you cannot provide additional arguments with --latest") - } - - results, err := registry.ImageEngine().Inspect(context.Background(), args, *inspectOpts) - if err != nil { - return err - } - - if len(results.Images) > 0 { - if inspectOpts.Format == "" { - buf, err := json.MarshalIndent(results.Images, "", " ") - if err != nil { - return err - } - fmt.Println(string(buf)) - - for id, e := range results.Errors { - fmt.Fprintf(os.Stderr, "%s: %s\n", id, e.Error()) - } - return nil - } - row := inspectFormat(inspectOpts.Format) - format := "{{range . }}" + row + "{{end}}" - tmpl, err := template.New("inspect").Parse(format) - if err != nil { - return err - } - - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - defer func() { _ = w.Flush() }() - err = tmpl.Execute(w, results.Images) - if err != nil { - return err - } - } - - for id, e := range results.Errors { - fmt.Fprintf(os.Stderr, "%s: %s\n", id, e.Error()) - } - return nil -} - -func inspectFormat(row string) string { - r := strings.NewReplacer("{{.Id}}", formats.IDString, - ".Src", ".Source", - ".Dst", ".Destination", - ".ImageID", ".Image", - ) - row = r.Replace(row) - - if !strings.HasSuffix(row, "\n") { - row += "\n" - } - return row -} - -func Inspect(cmd *cobra.Command, args []string, options *entities.InspectOptions) error { - inspectOpts = options - return inspect(cmd, args) -} diff --git a/cmd/podmanV2/images/list.go b/cmd/podmanV2/images/list.go deleted file mode 100644 index d594a4323..000000000 --- a/cmd/podmanV2/images/list.go +++ /dev/null @@ -1,273 +0,0 @@ -package images - -import ( - "errors" - "fmt" - "os" - "sort" - "strings" - "text/tabwriter" - "text/template" - "time" - "unicode" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/docker/go-units" - jsoniter "github.com/json-iterator/go" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -type listFlagType struct { - format string - history bool - noHeading bool - noTrunc bool - quiet bool - sort string - readOnly bool - digests bool -} - -var ( - // Command: podman image _list_ - listCmd = &cobra.Command{ - Use: "list [flag] [IMAGE]", - Aliases: []string{"ls"}, - Args: cobra.MaximumNArgs(1), - Short: "List images in local storage", - Long: "Lists images previously pulled to the system or created on the system.", - RunE: images, - Example: `podman image list --format json - podman image list --sort repository --format "table {{.ID}} {{.Repository}} {{.Tag}}" - podman image list --filter dangling=true`, - } - - // Options to pull data - listOptions = entities.ImageListOptions{} - - // Options for presenting data - listFlag = listFlagType{} - - sortFields = entities.NewStringSet( - "created", - "id", - "repository", - "size", - "tag") -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: listCmd, - Parent: imageCmd, - }) - imageListFlagSet(listCmd.Flags()) -} - -func imageListFlagSet(flags *pflag.FlagSet) { - flags.BoolVarP(&listOptions.All, "all", "a", false, "Show all images (default hides intermediate images)") - flags.StringSliceVarP(&listOptions.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])") - flags.StringVar(&listFlag.format, "format", "", "Change the output format to JSON or a Go template") - flags.BoolVar(&listFlag.digests, "digests", false, "Show digests") - flags.BoolVarP(&listFlag.noHeading, "noheading", "n", false, "Do not print column headings") - flags.BoolVar(&listFlag.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&listFlag.noTrunc, "notruncate", false, "Do not truncate output") - flags.BoolVarP(&listFlag.quiet, "quiet", "q", false, "Display only image IDs") - flags.StringVar(&listFlag.sort, "sort", "created", "Sort by "+sortFields.String()) - flags.BoolVarP(&listFlag.history, "history", "", false, "Display the image name history") -} - -func images(cmd *cobra.Command, args []string) error { - if len(listOptions.Filter) > 0 && len(args) > 0 { - return errors.New("cannot specify an image and a filter(s)") - } - - if len(listOptions.Filter) < 1 && len(args) > 0 { - listOptions.Filter = append(listOptions.Filter, "reference="+args[0]) - } - - if cmd.Flag("sort").Changed && !sortFields.Contains(listFlag.sort) { - return fmt.Errorf("\"%s\" is not a valid field for sorting. Choose from: %s", - listFlag.sort, sortFields.String()) - } - - summaries, err := registry.ImageEngine().List(registry.GetContext(), listOptions) - if err != nil { - return err - } - - imageS := summaries - sort.Slice(imageS, sortFunc(listFlag.sort, imageS)) - - if cmd.Flag("format").Changed && listFlag.format == "json" { - return writeJSON(imageS) - } else { - return writeTemplate(imageS, err) - } -} - -func writeJSON(imageS []*entities.ImageSummary) error { - type image struct { - entities.ImageSummary - Created string - } - - imgs := make([]image, 0, len(imageS)) - for _, e := range imageS { - var h image - h.ImageSummary = *e - h.Created = time.Unix(e.Created, 0).Format(time.RFC3339) - h.RepoTags = nil - - imgs = append(imgs, h) - } - - json := jsoniter.ConfigCompatibleWithStandardLibrary - enc := json.NewEncoder(os.Stdout) - return enc.Encode(imgs) -} - -func writeTemplate(imageS []*entities.ImageSummary, err error) error { - var ( - hdr, row string - ) - imgs := make([]imageReporter, 0, len(imageS)) - for _, e := range imageS { - for _, tag := range e.RepoTags { - var h imageReporter - h.ImageSummary = *e - h.Repository, h.Tag = tokenRepoTag(tag) - imgs = append(imgs, h) - } - if e.IsReadOnly() { - listFlag.readOnly = true - } - } - if len(listFlag.format) < 1 { - hdr, row = imageListFormat(listFlag) - } else { - row = listFlag.format - if !strings.HasSuffix(row, "\n") { - row += "\n" - } - } - format := hdr + "{{range . }}" + row + "{{end}}" - tmpl := template.Must(template.New("list").Parse(format)) - w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - defer w.Flush() - return tmpl.Execute(w, imgs) -} - -func tokenRepoTag(tag string) (string, string) { - tokens := strings.SplitN(tag, ":", 2) - switch len(tokens) { - case 0: - return tag, "" - case 1: - return tokens[0], "" - case 2: - return tokens[0], tokens[1] - default: - return "<N/A>", "" - } -} - -func sortFunc(key string, data []*entities.ImageSummary) func(i, j int) bool { - switch key { - case "id": - return func(i, j int) bool { - return data[i].ID < data[j].ID - } - case "repository": - return func(i, j int) bool { - return data[i].RepoTags[0] < data[j].RepoTags[0] - } - case "size": - return func(i, j int) bool { - return data[i].Size < data[j].Size - } - case "tag": - return func(i, j int) bool { - return data[i].RepoTags[0] < data[j].RepoTags[0] - } - default: - // case "created": - return func(i, j int) bool { - return data[i].Created >= data[j].Created - } - } -} - -func imageListFormat(flags listFlagType) (string, string) { - if flags.quiet { - return "", "{{.ID}}\n" - } - - // Defaults - hdr := "REPOSITORY\tTAG" - row := "{{.Repository}}\t{{if .Tag}}{{.Tag}}{{else}}<none>{{end}}" - - if flags.digests { - hdr += "\tDIGEST" - row += "\t{{.Digest}}" - } - - hdr += "\tIMAGE ID" - if flags.noTrunc { - row += "\tsha256:{{.ID}}" - } else { - row += "\t{{.ID}}" - } - - hdr += "\tCREATED\tSIZE" - row += "\t{{.Created}}\t{{.Size}}" - - if flags.history { - hdr += "\tHISTORY" - row += "\t{{if .History}}{{.History}}{{else}}<none>{{end}}" - } - - if flags.readOnly { - hdr += "\tReadOnly" - row += "\t{{.ReadOnly}}" - } - - if flags.noHeading { - hdr = "" - } else { - hdr += "\n" - } - - row += "\n" - return hdr, row -} - -type imageReporter struct { - Repository string `json:"repository,omitempty"` - Tag string `json:"tag,omitempty"` - entities.ImageSummary -} - -func (i imageReporter) ID() string { - if !listFlag.noTrunc && len(i.ImageSummary.ID) >= 12 { - return i.ImageSummary.ID[0:12] - } - return i.ImageSummary.ID -} - -func (i imageReporter) Created() string { - return units.HumanDuration(time.Since(time.Unix(i.ImageSummary.Created, 0))) + " ago" -} - -func (i imageReporter) Size() string { - s := units.HumanSizeWithPrecision(float64(i.ImageSummary.Size), 3) - j := strings.LastIndexFunc(s, unicode.IsNumber) - return s[:j+1] + " " + s[j+1:] -} - -func (i imageReporter) History() string { - return strings.Join(i.ImageSummary.History, ", ") -} diff --git a/cmd/podmanV2/images/load.go b/cmd/podmanV2/images/load.go deleted file mode 100644 index 004daa288..000000000 --- a/cmd/podmanV2/images/load.go +++ /dev/null @@ -1,94 +0,0 @@ -package images - -import ( - "context" - "fmt" - "io" - "io/ioutil" - "os" - - "github.com/containers/image/v5/docker/reference" - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/util" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" -) - -var ( - loadDescription = "Loads an image from a locally stored archive (tar file) into container storage." - loadCommand = &cobra.Command{ - Use: "load [flags] [NAME[:TAG]]", - Short: "Load an image from container archive", - Long: loadDescription, - RunE: load, - Args: cobra.MaximumNArgs(1), - } -) - -var ( - loadOpts entities.ImageLoadOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: loadCommand, - }) - - flags := loadCommand.Flags() - flags.StringVarP(&loadOpts.Input, "input", "i", "", "Read from specified archive file (default: stdin)") - flags.BoolVarP(&loadOpts.Quiet, "quiet", "q", false, "Suppress the output") - flags.StringVar(&loadOpts.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file") - if registry.IsRemote() { - _ = flags.MarkHidden("signature-policy") - } - -} - -func load(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - ref, err := reference.Parse(args[0]) - if err != nil { - return err - } - if t, ok := ref.(reference.Tagged); ok { - loadOpts.Tag = t.Tag() - } else { - loadOpts.Tag = "latest" - } - if r, ok := ref.(reference.Named); ok { - fmt.Println(r.Name()) - loadOpts.Name = r.Name() - } - } - if len(loadOpts.Input) > 0 { - if err := parse.ValidateFileName(loadOpts.Input); err != nil { - return err - } - } else { - if terminal.IsTerminal(int(os.Stdin.Fd())) { - return errors.Errorf("cannot read from terminal. Use command-line redirection or the --input flag.") - } - outFile, err := ioutil.TempFile(util.Tmpdir(), "podman") - if err != nil { - return errors.Errorf("error creating file %v", err) - } - defer os.Remove(outFile.Name()) - defer outFile.Close() - - _, err = io.Copy(outFile, os.Stdin) - if err != nil { - return errors.Errorf("error copying file %v", err) - } - loadOpts.Input = outFile.Name() - } - response, err := registry.ImageEngine().Load(context.Background(), loadOpts) - if err != nil { - return err - } - fmt.Println("Loaded image: " + response.Name) - return nil -} diff --git a/cmd/podmanV2/images/prune.go b/cmd/podmanV2/images/prune.go deleted file mode 100644 index 6577c458e..000000000 --- a/cmd/podmanV2/images/prune.go +++ /dev/null @@ -1,86 +0,0 @@ -package images - -import ( - "bufio" - "fmt" - "os" - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - pruneDescription = `Removes all unnamed images from local storage. - - If an image is not being used by a container, it will be removed from the system.` - pruneCmd = &cobra.Command{ - Use: "prune", - Args: cobra.NoArgs, - Short: "Remove unused images", - Long: pruneDescription, - RunE: prune, - Example: `podman image prune`, - } - - pruneOpts = entities.ImagePruneOptions{} - force bool - filter = []string{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pruneCmd, - Parent: imageCmd, - }) - - flags := pruneCmd.Flags() - flags.BoolVarP(&pruneOpts.All, "all", "a", false, "Remove all unused images, not just dangling ones") - flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation") - flags.StringArrayVar(&filter, "filter", []string{}, "Provide filter values (e.g. 'label=<key>=<value>')") - -} - -func prune(cmd *cobra.Command, args []string) error { - if !force { - reader := bufio.NewReader(os.Stdin) - fmt.Printf(` -WARNING! This will remove all dangling images. -Are you sure you want to continue? [y/N] `) - answer, err := reader.ReadString('\n') - if err != nil { - return errors.Wrapf(err, "error reading input") - } - if strings.ToLower(answer)[0] != 'y' { - return nil - } - } - - // TODO Remove once filter refactor is finished and url.Values rules :) - for _, f := range filter { - t := strings.SplitN(f, "=", 2) - pruneOpts.Filters.Add(t[0], t[1]) - } - - results, err := registry.ImageEngine().Prune(registry.GetContext(), pruneOpts) - if err != nil { - return err - } - - for _, i := range results.Report.Id { - fmt.Println(i) - } - - for _, e := range results.Report.Err { - fmt.Fprint(os.Stderr, e.Error()+"\n") - } - - if results.Size > 0 { - fmt.Fprintf(os.Stdout, "Size: %d\n", results.Size) - } - - return nil -} diff --git a/cmd/podmanV2/images/pull.go b/cmd/podmanV2/images/pull.go deleted file mode 100644 index 74090dee4..000000000 --- a/cmd/podmanV2/images/pull.go +++ /dev/null @@ -1,118 +0,0 @@ -package images - -import ( - "fmt" - - buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/image/v5/types" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// pullOptionsWrapper wraps entities.ImagePullOptions and prevents leaking -// CLI-only fields into the API types. -type pullOptionsWrapper struct { - entities.ImagePullOptions - TLSVerifyCLI bool // CLI only -} - -var ( - pullOptions = pullOptionsWrapper{} - pullDescription = `Pulls an image from a registry and stores it locally. - - An image can be pulled by tag or digest. If a tag is not specified, the image with the 'latest' tag is pulled.` - - // Command: podman pull - pullCmd = &cobra.Command{ - Use: "pull [flags] IMAGE", - Args: cobra.ExactArgs(1), - Short: "Pull an image from a registry", - Long: pullDescription, - RunE: imagePull, - Example: `podman pull imageName - podman pull fedora:latest`, - } - - // Command: podman image pull - // It's basically a clone of `pullCmd` with the exception of being a - // child of the images command. - imagesPullCmd = &cobra.Command{ - Use: pullCmd.Use, - Short: pullCmd.Short, - Long: pullCmd.Long, - RunE: pullCmd.RunE, - Example: `podman image pull imageName - podman image pull fedora:latest`, - } -) - -func init() { - // pull - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pullCmd, - }) - - flags := pullCmd.Flags() - pullFlags(flags) - - // images pull - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: imagesPullCmd, - Parent: imageCmd, - }) - - imagesPullFlags := imagesPullCmd.Flags() - pullFlags(imagesPullFlags) -} - -// pullFlags set the flags for the pull command. -func pullFlags(flags *pflag.FlagSet) { - flags.BoolVar(&pullOptions.AllTags, "all-tags", false, "All tagged images in the repository will be pulled") - flags.StringVar(&pullOptions.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") - flags.StringVar(&pullOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys") - flags.StringVar(&pullOptions.Credentials, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") - flags.StringVar(&pullOptions.OverrideArch, "override-arch", "", "Use `ARCH` instead of the architecture of the machine for choosing images") - flags.StringVar(&pullOptions.OverrideOS, "override-os", "", "Use `OS` instead of the running OS for choosing images") - flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images") - flags.StringVar(&pullOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") - flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - - if registry.IsRemote() { - _ = flags.MarkHidden("authfile") - _ = flags.MarkHidden("cert-dir") - _ = flags.MarkHidden("signature-policy") - _ = flags.MarkHidden("tls-verify") - } -} - -// imagePull is implement the command for pulling images. -func imagePull(cmd *cobra.Command, args []string) error { - pullOptsAPI := pullOptions.ImagePullOptions - // TLS verification in c/image is controlled via a `types.OptionalBool` - // which allows for distinguishing among set-true, set-false, unspecified - // which is important to implement a sane way of dealing with defaults of - // boolean CLI flags. - if cmd.Flags().Changed("tls-verify") { - pullOptsAPI.TLSVerify = types.NewOptionalBool(pullOptions.TLSVerifyCLI) - } - - // Let's do all the remaining Yoga in the API to prevent us from - // scattering logic across (too) many parts of the code. - pullReport, err := registry.ImageEngine().Pull(registry.GetContext(), args[0], pullOptsAPI) - if err != nil { - return err - } - - if len(pullReport.Images) > 1 { - fmt.Println("Pulled Images:") - } - for _, img := range pullReport.Images { - fmt.Println(img) - } - - return nil -} diff --git a/cmd/podmanV2/images/push.go b/cmd/podmanV2/images/push.go deleted file mode 100644 index 51a60664b..000000000 --- a/cmd/podmanV2/images/push.go +++ /dev/null @@ -1,120 +0,0 @@ -package images - -import ( - buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/image/v5/types" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// pushOptionsWrapper wraps entities.ImagepushOptions and prevents leaking -// CLI-only fields into the API types. -type pushOptionsWrapper struct { - entities.ImagePushOptions - TLSVerifyCLI bool // CLI only -} - -var ( - pushOptions = pushOptionsWrapper{} - pushDescription = `Pushes a source image to a specified destination. - - The Image "DESTINATION" uses a "transport":"details" format. See podman-push(1) section "DESTINATION" for the expected format.` - - // Command: podman push - pushCmd = &cobra.Command{ - Use: "push [flags] SOURCE DESTINATION", - Short: "Push an image to a specified destination", - Long: pushDescription, - RunE: imagePush, - Example: `podman push imageID docker://registry.example.com/repository:tag - podman push imageID oci-archive:/path/to/layout:image:tag`, - } - - // Command: podman image push - // It's basically a clone of `pushCmd` with the exception of being a - // child of the images command. - imagePushCmd = &cobra.Command{ - Use: pushCmd.Use, - Short: pushCmd.Short, - Long: pushCmd.Long, - RunE: pushCmd.RunE, - Example: `podman image push imageID docker://registry.example.com/repository:tag - podman image push imageID oci-archive:/path/to/layout:image:tag`, - } -) - -func init() { - // push - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pushCmd, - }) - - flags := pushCmd.Flags() - pushFlags(flags) - - // images push - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: imagePushCmd, - Parent: imageCmd, - }) - - pushFlags(imagePushCmd.Flags()) -} - -// pushFlags set the flags for the push command. -func pushFlags(flags *pflag.FlagSet) { - flags.StringVar(&pushOptions.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") - flags.StringVar(&pushOptions.CertDir, "cert-dir", "", "Path to a directory containing TLS certificates and keys") - flags.BoolVar(&pushOptions.Compress, "compress", false, "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)") - flags.StringVar(&pushOptions.Credentials, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") - flags.StringVar(&pushOptions.DigestFile, "digestfile", "", "Write the digest of the pushed image to the specified file") - flags.StringVarP(&pushOptions.Format, "format", "f", "", "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir' transport (default is manifest type of source)") - flags.BoolVarP(&pushOptions.Quiet, "quiet", "q", false, "Suppress output information when pushing images") - flags.BoolVar(&pushOptions.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image") - flags.StringVar(&pushOptions.SignaturePolicy, "signature-policy", "", "Path to a signature-policy file") - flags.StringVar(&pushOptions.SignBy, "sign-by", "", "Add a signature at the destination using the specified key") - flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - - if registry.IsRemote() { - _ = flags.MarkHidden("authfile") - _ = flags.MarkHidden("cert-dir") - _ = flags.MarkHidden("compress") - _ = flags.MarkHidden("quiet") - _ = flags.MarkHidden("signature-policy") - _ = flags.MarkHidden("tls-verify") - } -} - -// imagePush is implement the command for pushing images. -func imagePush(cmd *cobra.Command, args []string) error { - var source, destination string - switch len(args) { - case 1: - source = args[0] - case 2: - source = args[0] - destination = args[1] - case 0: - fallthrough - default: - return errors.New("push requires at least one image name, or optionally a second to specify a different destination") - } - - pushOptsAPI := pushOptions.ImagePushOptions - // TLS verification in c/image is controlled via a `types.OptionalBool` - // which allows for distinguishing among set-true, set-false, unspecified - // which is important to implement a sane way of dealing with defaults of - // boolean CLI flags. - if cmd.Flags().Changed("tls-verify") { - pushOptsAPI.TLSVerify = types.NewOptionalBool(pushOptions.TLSVerifyCLI) - } - - // Let's do all the remaining Yoga in the API to prevent us from scattering - // logic across (too) many parts of the code. - return registry.ImageEngine().Push(registry.GetContext(), source, destination, pushOptsAPI) -} diff --git a/cmd/podmanV2/images/rm.go b/cmd/podmanV2/images/rm.go deleted file mode 100644 index f93d6ed50..000000000 --- a/cmd/podmanV2/images/rm.go +++ /dev/null @@ -1,71 +0,0 @@ -package images - -import ( - "fmt" - "os" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -var ( - rmDescription = "Removes one or more previously pulled or locally created images." - rmCmd = &cobra.Command{ - Use: "rm [flags] IMAGE [IMAGE...]", - Short: "Removes one or more images from local storage", - Long: rmDescription, - RunE: rm, - Example: `podman image rm imageID - podman image rm --force alpine - podman image rm c4dfb1609ee2 93fd78260bd1 c0ed59d05ff7`, - } - - imageOpts = entities.ImageDeleteOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: rmCmd, - Parent: imageCmd, - }) - - imageRemoveFlagSet(rmCmd.Flags()) -} - -func imageRemoveFlagSet(flags *pflag.FlagSet) { - flags.BoolVarP(&imageOpts.All, "all", "a", false, "Remove all images") - flags.BoolVarP(&imageOpts.Force, "force", "f", false, "Force Removal of the image") -} -func rm(cmd *cobra.Command, args []string) error { - - if len(args) < 1 && !imageOpts.All { - return errors.Errorf("image name or ID must be specified") - } - if len(args) > 0 && imageOpts.All { - return errors.Errorf("when using the --all switch, you may not pass any images names or IDs") - } - report, err := registry.ImageEngine().Delete(registry.GetContext(), args, imageOpts) - if err != nil { - switch { - case report != nil && report.ImageNotFound != nil: - fmt.Fprintln(os.Stderr, err.Error()) - registry.SetExitCode(2) - case report != nil && report.ImageInUse != nil: - fmt.Fprintln(os.Stderr, err.Error()) - default: - return err - } - } - - for _, u := range report.Untagged { - fmt.Println("Untagged: " + u) - } - for _, d := range report.Deleted { - fmt.Println("Deleted: " + d) - } - return nil -} diff --git a/cmd/podmanV2/images/rmi.go b/cmd/podmanV2/images/rmi.go deleted file mode 100644 index ae199b789..000000000 --- a/cmd/podmanV2/images/rmi.go +++ /dev/null @@ -1,28 +0,0 @@ -package images - -import ( - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - rmiCmd = &cobra.Command{ - Use: strings.Replace(rmCmd.Use, "rm ", "rmi ", 1), - Args: rmCmd.Args, - Short: rmCmd.Short, - Long: rmCmd.Long, - RunE: rmCmd.RunE, - Example: strings.Replace(rmCmd.Example, "podman image rm", "podman rmi", -1), - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: rmiCmd, - }) - imageRemoveFlagSet(rmiCmd.Flags()) -} diff --git a/cmd/podmanV2/images/save.go b/cmd/podmanV2/images/save.go deleted file mode 100644 index 29ee79392..000000000 --- a/cmd/podmanV2/images/save.go +++ /dev/null @@ -1,86 +0,0 @@ -package images - -import ( - "context" - "os" - "strings" - - "github.com/containers/libpod/libpod/define" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/util" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" -) - -var validFormats = []string{define.OCIManifestDir, define.OCIArchive, define.V2s2ManifestDir, define.V2s2Archive} - -var ( - saveDescription = `Save an image to docker-archive or oci-archive on the local machine. Default is docker-archive.` - - saveCommand = &cobra.Command{ - Use: "save [flags] IMAGE", - Short: "Save image to an archive", - Long: saveDescription, - RunE: save, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return errors.Errorf("need at least 1 argument") - } - format, err := cmd.Flags().GetString("format") - if err != nil { - return err - } - if !util.StringInSlice(format, validFormats) { - return errors.Errorf("format value must be one of %s", strings.Join(validFormats, " ")) - } - return nil - }, - Example: `podman save --quiet -o myimage.tar imageID - podman save --format docker-dir -o ubuntu-dir ubuntu - podman save > alpine-all.tar alpine:latest`, - } -) - -var ( - saveOpts entities.ImageSaveOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: saveCommand, - }) - flags := saveCommand.Flags() - flags.BoolVar(&saveOpts.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)") - flags.StringVar(&saveOpts.Format, "format", define.V2s2Archive, "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-archive, docker-dir (directory with v2s2 manifest type)") - flags.StringVarP(&saveOpts.Output, "output", "o", "", "Write to a specified file (default: stdout, which must be redirected)") - flags.BoolVarP(&saveOpts.Quiet, "quiet", "q", false, "Suppress the output") - -} - -func save(cmd *cobra.Command, args []string) error { - var ( - tags []string - ) - if cmd.Flag("compress").Changed && (saveOpts.Format != define.OCIManifestDir && saveOpts.Format != define.V2s2ManifestDir && saveOpts.Format == "") { - return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'") - } - if len(saveOpts.Output) == 0 { - fi := os.Stdout - if terminal.IsTerminal(int(fi.Fd())) { - return errors.Errorf("refusing to save to terminal. Use -o flag or redirect") - } - saveOpts.Output = "/dev/stdout" - } - if err := parse.ValidateFileName(saveOpts.Output); err != nil { - return err - } - if len(args) > 1 { - tags = args[1:] - } - return registry.ImageEngine().Save(context.Background(), args[0], tags, saveOpts) -} diff --git a/cmd/podmanV2/images/search.go b/cmd/podmanV2/images/search.go deleted file mode 100644 index 17c72784c..000000000 --- a/cmd/podmanV2/images/search.go +++ /dev/null @@ -1,156 +0,0 @@ -package images - -import ( - "reflect" - "strings" - - buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/buildah/pkg/formats" - "github.com/containers/image/v5/types" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/util/camelcase" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// searchOptionsWrapper wraps entities.ImagePullOptions and prevents leaking -// CLI-only fields into the API types. -type searchOptionsWrapper struct { - entities.ImageSearchOptions - // CLI only flags - TLSVerifyCLI bool // Used to convert to an optional bool later - Format string // For go templating -} - -var ( - searchOptions = searchOptionsWrapper{} - searchDescription = `Search registries for a given image. Can search all the default registries or a specific registry. - - Users can limit the number of results, and filter the output based on certain conditions.` - - // Command: podman search - searchCmd = &cobra.Command{ - Use: "search [flags] TERM", - Short: "Search registry for image", - Long: searchDescription, - RunE: imageSearch, - Args: cobra.ExactArgs(1), - Annotations: map[string]string{ - registry.ParentNSRequired: "", - }, - Example: `podman search --filter=is-official --limit 3 alpine - podman search registry.fedoraproject.org/ # only works with v2 registries - podman search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`, - } - - // Command: podman image search - imageSearchCmd = &cobra.Command{ - Use: searchCmd.Use, - Short: searchCmd.Short, - Long: searchCmd.Long, - RunE: searchCmd.RunE, - Args: searchCmd.Args, - Example: `podman image search --filter=is-official --limit 3 alpine - podman image search registry.fedoraproject.org/ # only works with v2 registries - podman image search --format "table {{.Index}} {{.Name}}" registry.fedoraproject.org/fedora`, - } -) - -func init() { - // search - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: searchCmd, - }) - - flags := searchCmd.Flags() - searchFlags(flags) - - // images search - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: imageSearchCmd, - Parent: imageCmd, - }) - - imageSearchFlags := imageSearchCmd.Flags() - searchFlags(imageSearchFlags) -} - -// searchFlags set the flags for the pull command. -func searchFlags(flags *pflag.FlagSet) { - flags.StringSliceVarP(&searchOptions.Filters, "filter", "f", []string{}, "Filter output based on conditions provided (default [])") - flags.StringVar(&searchOptions.Format, "format", "", "Change the output format to a Go template") - flags.IntVar(&searchOptions.Limit, "limit", 0, "Limit the number of results") - flags.BoolVar(&searchOptions.NoTrunc, "no-trunc", false, "Do not truncate the output") - flags.StringVar(&searchOptions.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") - flags.BoolVar(&searchOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") - if registry.IsRemote() { - _ = flags.MarkHidden("authfile") - _ = flags.MarkHidden("tls-verify") - } -} - -// imageSearch implements the command for searching images. -func imageSearch(cmd *cobra.Command, args []string) error { - searchTerm := "" - switch len(args) { - case 1: - searchTerm = args[0] - default: - return errors.Errorf("search requires exactly one argument") - } - - sarchOptsAPI := searchOptions.ImageSearchOptions - // TLS verification in c/image is controlled via a `types.OptionalBool` - // which allows for distinguishing among set-true, set-false, unspecified - // which is important to implement a sane way of dealing with defaults of - // boolean CLI flags. - if cmd.Flags().Changed("tls-verify") { - sarchOptsAPI.TLSVerify = types.NewOptionalBool(pullOptions.TLSVerifyCLI) - } - - searchReport, err := registry.ImageEngine().Search(registry.GetContext(), searchTerm, sarchOptsAPI) - if err != nil { - return err - } - - format := genSearchFormat(searchOptions.Format) - if len(searchReport) == 0 { - return nil - } - out := formats.StdoutTemplateArray{Output: searchToGeneric(searchReport), Template: format, Fields: searchHeaderMap()} - return out.Out() -} - -// searchHeaderMap returns the headers of a SearchResult. -func searchHeaderMap() map[string]string { - s := new(entities.ImageSearchReport) - v := reflect.Indirect(reflect.ValueOf(s)) - values := make(map[string]string, v.NumField()) - - for i := 0; i < v.NumField(); i++ { - key := v.Type().Field(i).Name - value := key - values[key] = strings.ToUpper(strings.Join(camelcase.Split(value), " ")) - } - return values -} - -func genSearchFormat(format string) string { - if format != "" { - // "\t" from the command line is not being recognized as a tab - // replacing the string "\t" to a tab character if the user passes in "\t" - return strings.Replace(format, `\t`, "\t", -1) - } - return "table {{.Index}}\t{{.Name}}\t{{.Description}}\t{{.Stars}}\t{{.Official}}\t{{.Automated}}\t" -} - -func searchToGeneric(params []entities.ImageSearchReport) (genericParams []interface{}) { - for _, v := range params { - genericParams = append(genericParams, interface{}(v)) - } - return genericParams -} diff --git a/cmd/podmanV2/images/tag.go b/cmd/podmanV2/images/tag.go deleted file mode 100644 index bf3cf0de6..000000000 --- a/cmd/podmanV2/images/tag.go +++ /dev/null @@ -1,32 +0,0 @@ -package images - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - tagDescription = "Adds one or more additional names to locally-stored image." - tagCommand = &cobra.Command{ - Use: "tag [flags] IMAGE TARGET_NAME [TARGET_NAME...]", - Short: "Add an additional name to a local image", - Long: tagDescription, - RunE: tag, - Args: cobra.MinimumNArgs(2), - Example: `podman tag 0e3bbc2 fedora:latest - podman tag imageID:latest myNewImage:newTag - podman tag httpd myregistryhost:5000/fedora/httpd:v2`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: tagCommand, - }) -} - -func tag(cmd *cobra.Command, args []string) error { - return registry.ImageEngine().Tag(registry.GetContext(), args[0], args[1:], entities.ImageTagOptions{}) -} diff --git a/cmd/podmanV2/images/untag.go b/cmd/podmanV2/images/untag.go deleted file mode 100644 index 5eca1cb78..000000000 --- a/cmd/podmanV2/images/untag.go +++ /dev/null @@ -1,31 +0,0 @@ -package images - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - 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: untag, - Args: cobra.MinimumNArgs(1), - Example: `podman untag 0e3bbc2 - podman untag imageID:latest otherImageName:latest - podman untag httpd myregistryhost:5000/fedora/httpd:v2`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: untagCommand, - }) -} - -func untag(cmd *cobra.Command, args []string) error { - return registry.ImageEngine().Untag(registry.GetContext(), args[0], args[1:], entities.ImageUntagOptions{}) -} diff --git a/cmd/podmanV2/inspect.go b/cmd/podmanV2/inspect.go deleted file mode 100644 index 25024d6f8..000000000 --- a/cmd/podmanV2/inspect.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/containers" - "github.com/containers/libpod/cmd/podmanV2/images" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -// Inspect is one of the outlier commands in that it operates on images/containers/... - -var ( - inspectOpts *entities.InspectOptions - - // Command: podman _inspect_ Object_ID - inspectCmd = &cobra.Command{ - Use: "inspect [flags] {CONTAINER_ID | IMAGE_ID}", - Args: cobra.ExactArgs(1), - Short: "Display the configuration of object denoted by ID", - Long: "Displays the low-level information on an object identified by name or ID", - TraverseChildren: true, - RunE: inspect, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: inspectCmd, - }) - inspectOpts = common.AddInspectFlagSet(inspectCmd) -} - -func inspect(cmd *cobra.Command, args []string) error { - if found, err := registry.ImageEngine().Exists(context.Background(), args[0]); err != nil { - return err - } else if found.Value { - return images.Inspect(cmd, args, inspectOpts) - } - - if found, err := registry.ContainerEngine().ContainerExists(context.Background(), args[0]); err != nil { - return err - } else if found.Value { - return containers.Inspect(cmd, args, inspectOpts) - } - return fmt.Errorf("%s not found on system", args[0]) -} diff --git a/cmd/podmanV2/main.go b/cmd/podmanV2/main.go deleted file mode 100644 index de5308121..000000000 --- a/cmd/podmanV2/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "os" - - _ "github.com/containers/libpod/cmd/podmanV2/containers" - _ "github.com/containers/libpod/cmd/podmanV2/healthcheck" - _ "github.com/containers/libpod/cmd/podmanV2/images" - _ "github.com/containers/libpod/cmd/podmanV2/networks" - _ "github.com/containers/libpod/cmd/podmanV2/pods" - "github.com/containers/libpod/cmd/podmanV2/registry" - _ "github.com/containers/libpod/cmd/podmanV2/system" - _ "github.com/containers/libpod/cmd/podmanV2/volumes" - "github.com/containers/storage/pkg/reexec" -) - -func init() { - // This is the bootstrap configuration, if user gives - // CLI flags parts of this configuration may be overwritten - registry.PodmanOptions = registry.NewPodmanConfig() -} - -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 - } - - for _, c := range registry.Commands { - for _, m := range c.Mode { - if registry.PodmanOptions.EngineMode == m { - parent := rootCmd - if c.Parent != nil { - parent = c.Parent - } - parent.AddCommand(c.Command) - - // - templates need to be set here, as PersistentPreRunE() is - // not called when --help is used. - // - rootCmd uses cobra default template not ours - c.Command.SetHelpTemplate(helpTemplate) - c.Command.SetUsageTemplate(usageTemplate) - } - } - } - - Execute() - os.Exit(0) -} diff --git a/cmd/podmanV2/networks/network.go b/cmd/podmanV2/networks/network.go deleted file mode 100644 index 85fec545b..000000000 --- a/cmd/podmanV2/networks/network.go +++ /dev/null @@ -1,25 +0,0 @@ -package images - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // Command: podman _network_ - cmd = &cobra.Command{ - Use: "network", - Short: "Manage networks", - Long: "Manage networks", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: cmd, - }) -} diff --git a/cmd/podmanV2/parse/common.go b/cmd/podmanV2/parse/common.go deleted file mode 100644 index a5e9b4fc2..000000000 --- a/cmd/podmanV2/parse/common.go +++ /dev/null @@ -1,50 +0,0 @@ -package parse - -import ( - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -// CheckAllLatestAndCIDFile checks that --all and --latest are used correctly. -// If cidfile is set, also check for the --cidfile flag. -func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool, cidfile bool) error { - argLen := len(args) - if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { - if !cidfile { - return errors.New("unable to lookup values for 'latest' or 'all'") - } else if c.Flags().Lookup("cidfile") == nil { - return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'") - } - } - - specifiedAll, _ := c.Flags().GetBool("all") - specifiedLatest, _ := c.Flags().GetBool("latest") - specifiedCIDFile := false - if cid, _ := c.Flags().GetStringArray("cidfile"); len(cid) > 0 { - specifiedCIDFile = true - } - - if specifiedCIDFile && (specifiedAll || specifiedLatest) { - return errors.Errorf("--all, --latest and --cidfile cannot be used together") - } else if specifiedAll && specifiedLatest { - return errors.Errorf("--all and --latest cannot be used together") - } - - if ignoreArgLen { - return nil - } - if (argLen > 0) && (specifiedAll || specifiedLatest) { - return errors.Errorf("no arguments are needed with --all or --latest") - } else if cidfile && (argLen > 0) && (specifiedAll || specifiedLatest || specifiedCIDFile) { - return errors.Errorf("no arguments are needed with --all, --latest or --cidfile") - } - - if specifiedCIDFile { - return nil - } - - if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedCIDFile { - return errors.Errorf("you must provide at least one name or id") - } - return nil -} diff --git a/cmd/podmanV2/parse/net.go b/cmd/podmanV2/parse/net.go deleted file mode 100644 index 03cda268c..000000000 --- a/cmd/podmanV2/parse/net.go +++ /dev/null @@ -1,188 +0,0 @@ -//nolint -// most of these validate and parse functions have been taken from projectatomic/docker -// and modified for cri-o -package parse - -import ( - "bufio" - "fmt" - "net" - "net/url" - "os" - "regexp" - "strings" - - "github.com/pkg/errors" -) - -const ( - Protocol_TCP Protocol = 0 - Protocol_UDP Protocol = 1 -) - -type Protocol int32 - -// PortMapping specifies the port mapping configurations of a sandbox. -type PortMapping struct { - // Protocol of the port mapping. - Protocol Protocol `protobuf:"varint,1,opt,name=protocol,proto3,enum=runtime.Protocol" json:"protocol,omitempty"` - // Port number within the container. Default: 0 (not specified). - ContainerPort int32 `protobuf:"varint,2,opt,name=container_port,json=containerPort,proto3" json:"container_port,omitempty"` - // Port number on the host. Default: 0 (not specified). - HostPort int32 `protobuf:"varint,3,opt,name=host_port,json=hostPort,proto3" json:"host_port,omitempty"` - // Host IP. - HostIp string `protobuf:"bytes,4,opt,name=host_ip,json=hostIp,proto3" json:"host_ip,omitempty"` -} - -// Note: for flags that are in the form <number><unit>, use the RAMInBytes function -// from the units package in docker/go-units/size.go - -var ( - whiteSpaces = " \t" - alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) - domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`) -) - -// validateExtraHost validates that the specified string is a valid extrahost and returns it. -// ExtraHost is in the form of name:ip where the ip has to be a valid ip (ipv4 or ipv6). -// for add-host flag -func ValidateExtraHost(val string) (string, error) { //nolint - // allow for IPv6 addresses in extra hosts by only splitting on first ":" - arr := strings.SplitN(val, ":", 2) - if len(arr) != 2 || len(arr[0]) == 0 { - return "", fmt.Errorf("bad format for add-host: %q", val) - } - if _, err := validateIPAddress(arr[1]); err != nil { - return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1]) - } - return val, nil -} - -// validateIPAddress validates an Ip address. -// for dns, ip, and ip6 flags also -func validateIPAddress(val string) (string, error) { - var ip = net.ParseIP(strings.TrimSpace(val)) - if ip != nil { - return ip.String(), nil - } - return "", fmt.Errorf("%s is not an ip address", val) -} - -func ValidateDomain(val string) (string, error) { - if alphaRegexp.FindString(val) == "" { - return "", fmt.Errorf("%s is not a valid domain", val) - } - ns := domainRegexp.FindSubmatch([]byte(val)) - if len(ns) > 0 && len(ns[1]) < 255 { - return string(ns[1]), nil - } - return "", fmt.Errorf("%s is not a valid domain", val) -} - -// GetAllLabels retrieves all labels given a potential label file and a number -// of labels provided from the command line. -func GetAllLabels(labelFile, inputLabels []string) (map[string]string, error) { - labels := make(map[string]string) - for _, file := range labelFile { - // Use of parseEnvFile still seems safe, as it's missing the - // extra parsing logic of parseEnv. - // There's an argument that we SHOULD be doing that parsing for - // all environment variables, even those sourced from files, but - // that would require a substantial rework. - if err := parseEnvFile(labels, file); err != nil { - // FIXME: parseEnvFile is using parseEnv, so we need to add extra - // logic for labels. - return nil, err - } - } - for _, label := range inputLabels { - split := strings.SplitN(label, "=", 2) - if split[0] == "" { - return nil, errors.Errorf("invalid label format: %q", label) - } - value := "" - if len(split) > 1 { - value = split[1] - } - labels[split[0]] = value - } - return labels, nil -} - -func parseEnv(env map[string]string, line string) error { - data := strings.SplitN(line, "=", 2) - - // catch invalid variables such as "=" or "=A" - if data[0] == "" { - return errors.Errorf("invalid environment variable: %q", line) - } - - // trim the front of a variable, but nothing else - name := strings.TrimLeft(data[0], whiteSpaces) - if strings.ContainsAny(name, whiteSpaces) { - return errors.Errorf("name %q has white spaces, poorly formatted name", name) - } - - if len(data) > 1 { - env[name] = data[1] - } else { - if strings.HasSuffix(name, "*") { - name = strings.TrimSuffix(name, "*") - for _, e := range os.Environ() { - part := strings.SplitN(e, "=", 2) - if len(part) < 2 { - continue - } - if strings.HasPrefix(part[0], name) { - env[part[0]] = part[1] - } - } - } else { - // if only a pass-through variable is given, clean it up. - if val, ok := os.LookupEnv(name); ok { - env[name] = val - } - } - } - return nil -} - -// parseEnvFile reads a file with environment variables enumerated by lines -func parseEnvFile(env map[string]string, filename string) error { - fh, err := os.Open(filename) - if err != nil { - return err - } - defer fh.Close() - - scanner := bufio.NewScanner(fh) - for scanner.Scan() { - // trim the line from all leading whitespace first - line := strings.TrimLeft(scanner.Text(), whiteSpaces) - // line is not empty, and not starting with '#' - if len(line) > 0 && !strings.HasPrefix(line, "#") { - if err := parseEnv(env, line); err != nil { - return err - } - } - } - return scanner.Err() -} - -// ValidateFileName returns an error if filename contains ":" -// as it is currently not supported -func ValidateFileName(filename string) error { - if strings.Contains(filename, ":") { - return errors.Errorf("invalid filename (should not contain ':') %q", filename) - } - return nil -} - -// ValidURL checks a string urlStr is a url or not -func ValidURL(urlStr string) error { - _, err := url.ParseRequestURI(urlStr) - if err != nil { - return errors.Wrapf(err, "invalid url path: %q", urlStr) - } - return nil -} diff --git a/cmd/podmanV2/parse/net_test.go b/cmd/podmanV2/parse/net_test.go deleted file mode 100644 index a6ddc2be9..000000000 --- a/cmd/podmanV2/parse/net_test.go +++ /dev/null @@ -1,152 +0,0 @@ -//nolint -// most of these validate and parse functions have been taken from projectatomic/docker -// and modified for cri-o -package parse - -import ( - "io/ioutil" - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - Var1 = []string{"ONE=1", "TWO=2"} -) - -func createTmpFile(content []byte) (string, error) { - tmpfile, err := ioutil.TempFile(os.TempDir(), "unittest") - if err != nil { - return "", err - } - - if _, err := tmpfile.Write(content); err != nil { - return "", err - - } - if err := tmpfile.Close(); err != nil { - return "", err - } - return tmpfile.Name(), nil -} - -func TestValidateExtraHost(t *testing.T) { - type args struct { - val string - } - tests := []struct { - name string - args args - want string - wantErr bool - }{ - //2001:0db8:85a3:0000:0000:8a2e:0370:7334 - {name: "good-ipv4", args: args{val: "foobar:192.168.1.1"}, want: "foobar:192.168.1.1", wantErr: false}, - {name: "bad-ipv4", args: args{val: "foobar:999.999.999.99"}, want: "", wantErr: true}, - {name: "bad-ipv4", args: args{val: "foobar:999.999.999"}, want: "", wantErr: true}, - {name: "noname-ipv4", args: args{val: "192.168.1.1"}, want: "", wantErr: true}, - {name: "noname-ipv4", args: args{val: ":192.168.1.1"}, want: "", wantErr: true}, - {name: "noip", args: args{val: "foobar:"}, want: "", wantErr: true}, - {name: "noip", args: args{val: "foobar"}, want: "", wantErr: true}, - {name: "good-ipv6", args: args{val: "foobar:2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "foobar:2001:0db8:85a3:0000:0000:8a2e:0370:7334", wantErr: false}, - {name: "bad-ipv6", args: args{val: "foobar:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true}, - {name: "bad-ipv6", args: args{val: "foobar:0db8:85a3:0000:0000:8a2e:0370:7334.0000.0000.000"}, want: "", wantErr: true}, - {name: "noname-ipv6", args: args{val: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true}, - {name: "noname-ipv6", args: args{val: ":2001:0db8:85a3:0000:0000:8a2e:0370:7334"}, want: "", wantErr: true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ValidateExtraHost(tt.args.val) - if (err != nil) != tt.wantErr { - t.Errorf("ValidateExtraHost() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("ValidateExtraHost() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_validateIPAddress(t *testing.T) { - type args struct { - val string - } - tests := []struct { - name string - args args - want string - wantErr bool - }{ - {name: "ipv4-good", args: args{val: "192.168.1.1"}, want: "192.168.1.1", wantErr: false}, - {name: "ipv4-bad", args: args{val: "192.168.1.1.1"}, want: "", wantErr: true}, - {name: "ipv4-bad", args: args{val: "192."}, want: "", wantErr: true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := validateIPAddress(tt.args.val) - if (err != nil) != tt.wantErr { - t.Errorf("validateIPAddress() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("validateIPAddress() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestValidateFileName(t *testing.T) { - type args struct { - filename string - } - tests := []struct { - name string - args args - wantErr bool - }{ - {name: "good", args: args{filename: "/some/rand/path"}, wantErr: false}, - {name: "good", args: args{filename: "some/rand/path"}, wantErr: false}, - {name: "good", args: args{filename: "/"}, wantErr: false}, - {name: "bad", args: args{filename: "/:"}, wantErr: true}, - {name: "bad", args: args{filename: ":/"}, wantErr: true}, - {name: "bad", args: args{filename: "/some/rand:/path"}, wantErr: true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := ValidateFileName(tt.args.filename); (err != nil) != tt.wantErr { - t.Errorf("ValidateFileName() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestGetAllLabels(t *testing.T) { - fileLabels := []string{} - labels, _ := GetAllLabels(fileLabels, Var1) - assert.Equal(t, len(labels), 2) -} - -func TestGetAllLabelsBadKeyValue(t *testing.T) { - inLabels := []string{"=badValue", "="} - fileLabels := []string{} - _, err := GetAllLabels(fileLabels, inLabels) - assert.Error(t, err, assert.AnError) -} - -func TestGetAllLabelsBadLabelFile(t *testing.T) { - fileLabels := []string{"/foobar5001/be"} - _, err := GetAllLabels(fileLabels, Var1) - assert.Error(t, err, assert.AnError) -} - -func TestGetAllLabelsFile(t *testing.T) { - content := []byte("THREE=3") - tFile, err := createTmpFile(content) - defer os.Remove(tFile) - assert.NoError(t, err) - fileLabels := []string{tFile} - result, _ := GetAllLabels(fileLabels, Var1) - assert.Equal(t, len(result), 3) -} diff --git a/cmd/podmanV2/pods/create.go b/cmd/podmanV2/pods/create.go deleted file mode 100644 index 2aaf0cd2c..000000000 --- a/cmd/podmanV2/pods/create.go +++ /dev/null @@ -1,147 +0,0 @@ -package pods - -import ( - "context" - "fmt" - "os" - "strings" - - "github.com/containers/libpod/cmd/podmanV2/common" - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/errorhandling" - "github.com/containers/libpod/pkg/specgen" - "github.com/containers/libpod/pkg/util" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - podCreateDescription = `After creating the pod, the pod ID is printed to stdout. - - 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'.` - - createCommand = &cobra.Command{ - Use: "create", - Args: cobra.NoArgs, - Short: "Create a new empty pod", - Long: podCreateDescription, - RunE: create, - } -) - -var ( - createOptions entities.PodCreateOptions - labels, labelFile []string - podIDFile string - share string -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: createCommand, - Parent: podCmd, - }) - flags := createCommand.Flags() - flags.SetInterspersed(false) - flags.AddFlagSet(common.GetNetFlags()) - flags.StringVar(&createOptions.CGroupParent, "cgroup-parent", "", "Set parent cgroup for the pod") - flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with") - flags.StringVar(&createOptions.InfraImage, "infra-image", define.DefaultInfraImage, "The image of the infra container to associate with the pod") - flags.StringVar(&createOptions.InfraCommand, "infra-command", define.DefaultInfraCommand, "The command to run on the infra container when the pod is started") - flags.StringSliceVar(&labelFile, "label-file", []string{}, "Read in a line delimited file of labels") - flags.StringSliceVarP(&labels, "label", "l", []string{}, "Set metadata on pod (default [])") - flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod") - flags.StringVarP(&createOptions.Hostname, "hostname", "", "", "Set a hostname to the pod") - flags.StringVar(&podIDFile, "pod-id-file", "", "Write the pod ID to the file") - flags.StringVar(&share, "share", common.DefaultKernelNamespaces, "A comma delimited list of kernel namespaces the pod will share") -} - -func create(cmd *cobra.Command, args []string) error { - var ( - err error - podIdFile *os.File - ) - createOptions.Labels, err = parse.GetAllLabels(labelFile, labels) - if err != nil { - return errors.Wrapf(err, "unable to process labels") - } - - if !createOptions.Infra && cmd.Flag("share").Changed && share != "none" && share != "" { - return errors.Errorf("You cannot share kernel namespaces on the pod level without an infra container") - } - createOptions.Share = strings.Split(share, ",") - if cmd.Flag("pod-id-file").Changed { - podIdFile, err = util.OpenExclusiveFile(podIDFile) - if err != nil && os.IsExist(err) { - return errors.Errorf("pod id file exists. Ensure another pod is not using it or delete %s", podIDFile) - } - if err != nil { - return errors.Errorf("error opening pod-id-file %s", podIDFile) - } - defer errorhandling.CloseQuiet(podIdFile) - defer errorhandling.SyncQuiet(podIdFile) - } - - createOptions.Net, err = common.NetFlagsToNetOptions(cmd) - if err != nil { - return err - } - netInput, err := cmd.Flags().GetString("network") - if err != nil { - return err - } - n := specgen.Namespace{} - switch netInput { - case "bridge": - n.NSMode = specgen.Bridge - case "host": - n.NSMode = specgen.Host - case "slip4netns": - n.NSMode = specgen.Slirp - default: - if strings.HasPrefix(netInput, "container:") { //nolint - split := strings.Split(netInput, ":") - if len(split) != 2 { - return errors.Errorf("invalid network paramater: %q", netInput) - } - n.NSMode = specgen.FromContainer - n.Value = split[1] - } else if strings.HasPrefix(netInput, "ns:") { - return errors.New("the ns: network option is not supported for pods") - } else { - n.NSMode = specgen.Bridge - createOptions.Net.CNINetworks = strings.Split(netInput, ",") - } - } - if len(createOptions.Net.PublishPorts) > 0 { - if !createOptions.Infra { - return errors.Errorf("you must have an infra container to publish port bindings to the host") - } - } - - if !createOptions.Infra { - if cmd.Flag("infra-command").Changed { - return errors.New("cannot set infra-command without an infra container") - } - createOptions.InfraCommand = "" - if cmd.Flag("infra-image").Changed { - return errors.New("cannot set infra-image without an infra container") - } - createOptions.InfraImage = "" - if cmd.Flag("share").Changed { - return errors.New("cannot set share namespaces without an infra container") - } - createOptions.Share = nil - } - - response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions) - if err != nil { - return err - } - fmt.Println(response.Id) - return nil -} diff --git a/cmd/podmanV2/pods/exists.go b/cmd/podmanV2/pods/exists.go deleted file mode 100644 index e37f2ebd7..000000000 --- a/cmd/podmanV2/pods/exists.go +++ /dev/null @@ -1,43 +0,0 @@ -package pods - -import ( - "context" - "os" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podExistsDescription = `If the named pod exists in local storage, podman pod exists exits with 0, otherwise the exit code will be 1.` - - existsCommand = &cobra.Command{ - Use: "exists POD", - Short: "Check if a pod exists in local storage", - Long: podExistsDescription, - RunE: exists, - Args: cobra.ExactArgs(1), - Example: `podman pod exists podID - podman pod exists mypod || podman pod create --name mypod`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: existsCommand, - Parent: podCmd, - }) -} - -func exists(cmd *cobra.Command, args []string) error { - response, err := registry.ContainerEngine().PodExists(context.Background(), args[0]) - if err != nil { - return err - } - if !response.Value { - os.Exit(1) - } - return nil -} diff --git a/cmd/podmanV2/pods/inspect.go b/cmd/podmanV2/pods/inspect.go deleted file mode 100644 index 9aab610f2..000000000 --- a/cmd/podmanV2/pods/inspect.go +++ /dev/null @@ -1,64 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - inspectOptions = entities.PodInspectOptions{} -) - -var ( - inspectDescription = fmt.Sprintf(`Display the configuration for a pod by name or id - - By default, this will render all results in a JSON array.`) - - inspectCmd = &cobra.Command{ - Use: "inspect [flags] POD [POD...]", - Short: "Displays a pod configuration", - Long: inspectDescription, - RunE: inspect, - Example: `podman pod inspect podID`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: inspectCmd, - Parent: podCmd, - }) - flags := inspectCmd.Flags() - flags.BoolVarP(&inspectOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func inspect(cmd *cobra.Command, args []string) error { - - if len(args) < 1 && !inspectOptions.Latest { - return errors.Errorf("you must provide the name or id of a running pod") - } - - if !inspectOptions.Latest { - inspectOptions.NameOrID = args[0] - } - responses, err := registry.ContainerEngine().PodInspect(context.Background(), inspectOptions) - if err != nil { - return err - } - b, err := jsoniter.MarshalIndent(responses, "", " ") - if err != nil { - return err - } - fmt.Println(string(b)) - return nil -} diff --git a/cmd/podmanV2/pods/kill.go b/cmd/podmanV2/pods/kill.go deleted file mode 100644 index 06cca916c..000000000 --- a/cmd/podmanV2/pods/kill.go +++ /dev/null @@ -1,68 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podKillDescription = `Signals are sent to the main process of each container inside the specified pod. - - The default signal is SIGKILL, or any signal specified with option --signal.` - killCommand = &cobra.Command{ - Use: "kill [flags] POD [POD...]", - Short: "Send the specified signal or SIGKILL to containers in pod", - Long: podKillDescription, - RunE: kill, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod kill podID - podman pod kill --signal TERM mywebserver - podman pod kill --latest`, - } -) - -var ( - killOpts entities.PodKillOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: killCommand, - Parent: podCmd, - }) - flags := killCommand.Flags() - flags.BoolVarP(&killOpts.All, "all", "a", false, "Kill all containers in all pods") - flags.BoolVarP(&killOpts.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - flags.StringVarP(&killOpts.Signal, "signal", "s", "KILL", "Signal to send to the containers in the pod") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } - -} -func kill(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().PodKill(context.Background(), args, killOpts) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if len(r.Errs) == 0 { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Errs...) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/pods/pause.go b/cmd/podmanV2/pods/pause.go deleted file mode 100644 index dc86e534d..000000000 --- a/cmd/podmanV2/pods/pause.go +++ /dev/null @@ -1,66 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podPauseDescription = `The pod name or ID can be used. - - All running containers within each specified pod will then be paused.` - pauseCommand = &cobra.Command{ - Use: "pause [flags] POD [POD...]", - Short: "Pause one or more pods", - Long: podPauseDescription, - RunE: pause, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod pause podID1 podID2 - podman pod pause --latest - podman pod pause --all`, - } -) - -var ( - pauseOptions entities.PodPauseOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pauseCommand, - Parent: podCmd, - }) - flags := pauseCommand.Flags() - flags.BoolVarP(&pauseOptions.All, "all", "a", false, "Pause all running pods") - flags.BoolVarP(&pauseOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} -func pause(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().PodPause(context.Background(), args, pauseOptions) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if len(r.Errs) == 0 { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Errs...) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/pods/pod.go b/cmd/podmanV2/pods/pod.go deleted file mode 100644 index 3434bfc02..000000000 --- a/cmd/podmanV2/pods/pod.go +++ /dev/null @@ -1,25 +0,0 @@ -package pods - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // Command: podman _pod_ - podCmd = &cobra.Command{ - Use: "pod", - Short: "Manage pods", - Long: "Manage pods", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: podCmd, - }) -} diff --git a/cmd/podmanV2/pods/ps.go b/cmd/podmanV2/pods/ps.go deleted file mode 100644 index 3dac607df..000000000 --- a/cmd/podmanV2/pods/ps.go +++ /dev/null @@ -1,229 +0,0 @@ -package pods - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - "strings" - "text/tabwriter" - "text/template" - "time" - - "github.com/docker/go-units" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - psDescription = "List all pods on system including their names, ids and current state." - - // Command: podman pod _ps_ - psCmd = &cobra.Command{ - Use: "ps", - Aliases: []string{"ls", "list"}, - Short: "list pods", - Long: psDescription, - RunE: pods, - } -) - -var ( - defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED" - inputFilters string - noTrunc bool - psInput entities.PodPSOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: psCmd, - Parent: podCmd, - }) - flags := psCmd.Flags() - flags.BoolVar(&psInput.CtrNames, "ctr-names", false, "Display the container names") - flags.BoolVar(&psInput.CtrIds, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated") - flags.BoolVar(&psInput.CtrStatus, "ctr-status", false, "Display the container status") - // TODO should we make this a [] ? - flags.StringVarP(&inputFilters, "filter", "f", "", "Filter output based on conditions given") - flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template") - flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod") - flags.BoolVar(&psInput.Namespace, "ns", false, "Display namespace information of the pod") - flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate pod and container IDs") - flags.BoolVarP(&psInput.Quiet, "quiet", "q", false, "Print the numeric IDs of the pods only") - flags.StringVar(&psInput.Sort, "sort", "created", "Sort output by created, id, name, or number") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func pods(cmd *cobra.Command, args []string) error { - var ( - w io.Writer = os.Stdout - row string - lpr []ListPodReporter - ) - if cmd.Flag("filter").Changed { - for _, f := range strings.Split(inputFilters, ",") { - split := strings.Split(f, "=") - if len(split) < 2 { - return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) - } - psInput.Filters[split[0]] = append(psInput.Filters[split[0]], split[1]) - } - } - responses, err := registry.ContainerEngine().PodPs(context.Background(), psInput) - if err != nil { - return err - } - - if psInput.Format == "json" { - b, err := json.MarshalIndent(responses, "", " ") - if err != nil { - return err - } - fmt.Println(string(b)) - return nil - } - - for _, r := range responses { - lpr = append(lpr, ListPodReporter{r}) - } - headers, row := createPodPsOut() - if psInput.Quiet { - if noTrunc { - row = "{{.Id}}\n" - } else { - row = "{{slice .Id 0 12}}\n" - } - } - if cmd.Flag("format").Changed { - row = psInput.Format - if !strings.HasPrefix(row, "\n") { - row += "\n" - } - } - format := "{{range . }}" + row + "{{end}}" - if !psInput.Quiet && !cmd.Flag("format").Changed { - format = headers + format - } - tmpl, err := template.New("listPods").Parse(format) - if err != nil { - return err - } - if !psInput.Quiet { - w = tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0) - } - if err := tmpl.Execute(w, lpr); err != nil { - return err - } - if flusher, ok := w.(interface{ Flush() error }); ok { - return flusher.Flush() - } - return nil -} - -func createPodPsOut() (string, string) { - var row string - headers := defaultHeaders - if noTrunc { - row += "{{.Id}}" - } else { - row += "{{slice .Id 0 12}}" - } - - row += "\t{{.Name}}\t{{.Status}}\t{{.Created}}" - - if psInput.CtrIds { - headers += "\tIDS" - row += "\t{{.ContainerIds}}" - } - if psInput.CtrNames { - headers += "\tNAMES" - row += "\t{{.ContainerNames}}" - } - if psInput.CtrStatus { - headers += "\tSTATUS" - row += "\t{{.ContainerStatuses}}" - } - if psInput.Namespace { - headers += "\tCGROUP\tNAMESPACES" - row += "\t{{.Cgroup}}\t{{.Namespace}}" - } - if !psInput.CtrStatus && !psInput.CtrNames && !psInput.CtrIds { - headers += "\t# OF CONTAINERS" - row += "\t{{.NumberOfContainers}}" - - } - headers += "\tINFRA ID\n" - if noTrunc { - row += "\t{{.InfraId}}\n" - } else { - row += "\t{{slice .InfraId 0 12}}\n" - } - return headers, row -} - -// ListPodReporter is a struct for pod ps output -type ListPodReporter struct { - *entities.ListPodsReport -} - -// Created returns a human readable created time/date -func (l ListPodReporter) Created() string { - return units.HumanDuration(time.Since(l.ListPodsReport.Created)) + " ago" -} - -// NumberofContainers returns an int representation for -// the number of containers belonging to the pod -func (l ListPodReporter) NumberOfContainers() int { - return len(l.Containers) -} - -// Added for backwards compatibility with podmanv1 -func (l ListPodReporter) InfraID() string { - return l.InfraId() -} - -// InfraId returns the infra container id for the pod -// depending on trunc -func (l ListPodReporter) InfraId() string { - if noTrunc { - return l.ListPodsReport.InfraId - } - return l.ListPodsReport.InfraId[0:12] -} - -func (l ListPodReporter) ContainerIds() string { - var ctrids []string - for _, c := range l.Containers { - id := c.Id - if !noTrunc { - id = id[0:12] - } - ctrids = append(ctrids, id) - } - return strings.Join(ctrids, ",") -} - -func (l ListPodReporter) ContainerNames() string { - var ctrNames []string - for _, c := range l.Containers { - ctrNames = append(ctrNames, c.Names) - } - return strings.Join(ctrNames, ",") -} - -func (l ListPodReporter) ContainerStatuses() string { - var statuses []string - for _, c := range l.Containers { - statuses = append(statuses, c.Status) - } - return strings.Join(statuses, ",") -} diff --git a/cmd/podmanV2/pods/restart.go b/cmd/podmanV2/pods/restart.go deleted file mode 100644 index 1c8709704..000000000 --- a/cmd/podmanV2/pods/restart.go +++ /dev/null @@ -1,68 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podRestartDescription = `The pod ID or name can be used. - - All of the containers within each of the specified pods will be restarted. If a container in a pod is not currently running it will be started.` - restartCommand = &cobra.Command{ - Use: "restart [flags] POD [POD...]", - Short: "Restart one or more pods", - Long: podRestartDescription, - RunE: restart, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod restart podID1 podID2 - podman pod restart --latest - podman pod restart --all`, - } -) - -var ( - restartOptions = entities.PodRestartOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: restartCommand, - Parent: podCmd, - }) - - flags := restartCommand.Flags() - flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all running pods") - flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func restart(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().PodRestart(context.Background(), args, restartOptions) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if len(r.Errs) == 0 { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Errs...) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/pods/rm.go b/cmd/podmanV2/pods/rm.go deleted file mode 100644 index b43dd2d6c..000000000 --- a/cmd/podmanV2/pods/rm.go +++ /dev/null @@ -1,71 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podRmDescription = fmt.Sprintf(`podman rm will remove one or more stopped pods and their containers from the host. - - The pod name or ID can be used. A pod with containers will not be removed without --force. If --force is specified, all containers will be stopped, then removed.`) - rmCommand = &cobra.Command{ - Use: "rm [flags] POD [POD...]", - Short: "Remove one or more pods", - Long: podRmDescription, - RunE: rm, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod rm mywebserverpod - podman pod rm -f 860a4b23 - podman pod rm -f -a`, - } -) - -var ( - rmOptions = entities.PodRmOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: rmCommand, - Parent: podCmd, - }) - - flags := rmCommand.Flags() - flags.BoolVarP(&rmOptions.All, "all", "a", false, "Restart all running pods") - flags.BoolVarP(&rmOptions.Force, "force", "f", false, "Force removal of a running pod by first stopping all containers, then removing all containers in the pod. The default is false") - flags.BoolVarP(&rmOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing") - flags.BoolVarP(&rmOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - _ = flags.MarkHidden("ignore") - } -} - -func rm(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().PodRm(context.Background(), args, rmOptions) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/pods/start.go b/cmd/podmanV2/pods/start.go deleted file mode 100644 index 11ac312f9..000000000 --- a/cmd/podmanV2/pods/start.go +++ /dev/null @@ -1,68 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podStartDescription = `The pod name or ID can be used. - - All containers defined in the pod will be started.` - startCommand = &cobra.Command{ - Use: "start [flags] POD [POD...]", - Short: "Start one or more pods", - Long: podStartDescription, - RunE: start, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod start podID - podman pod start --latest - podman pod start --all`, - } -) - -var ( - startOptions = entities.PodStartOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: startCommand, - Parent: podCmd, - }) - - flags := startCommand.Flags() - flags.BoolVarP(&startOptions.All, "all", "a", false, "Restart all running pods") - flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func start(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().PodStart(context.Background(), args, startOptions) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if len(r.Errs) == 0 { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Errs...) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/pods/stop.go b/cmd/podmanV2/pods/stop.go deleted file mode 100644 index 403c7d95d..000000000 --- a/cmd/podmanV2/pods/stop.go +++ /dev/null @@ -1,79 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podStopDescription = `The pod name or ID can be used. - - This command will stop all running containers in each of the specified pods.` - - stopCommand = &cobra.Command{ - Use: "stop [flags] POD [POD...]", - Short: "Stop one or more pods", - Long: podStopDescription, - RunE: stop, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod stop mywebserverpod - podman pod stop --latest - podman pod stop --time 0 490eb 3557fb`, - } -) - -var ( - stopOptions = entities.PodStopOptions{ - Timeout: -1, - } - timeout uint -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: stopCommand, - Parent: podCmd, - }) - flags := stopCommand.Flags() - flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running pods") - flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing") - flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Stop the latest pod podman is aware of") - flags.UintVarP(&timeout, "time", "t", 0, "Seconds to wait for pod stop before killing the container") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - _ = flags.MarkHidden("ignore") - - } - flags.SetNormalizeFunc(utils.AliasFlags) -} - -func stop(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - if cmd.Flag("time").Changed { - stopOptions.Timeout = int(timeout) - } - responses, err := registry.ContainerEngine().PodStop(context.Background(), args, stopOptions) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if len(r.Errs) == 0 { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Errs...) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/pods/top.go b/cmd/podmanV2/pods/top.go deleted file mode 100644 index e501bb478..000000000 --- a/cmd/podmanV2/pods/top.go +++ /dev/null @@ -1,86 +0,0 @@ -package pods - -import ( - "context" - "fmt" - "os" - "strings" - "text/tabwriter" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/psgo" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - topDescription = fmt.Sprintf(`Specify format descriptors to alter the output. - - You may run "podman pod top -l pid pcpu seccomp" to print the process ID, the CPU percentage and the seccomp mode of each process of the latest pod. - Format Descriptors: - %s`, strings.Join(psgo.ListDescriptors(), ",")) - - topOptions = entities.PodTopOptions{} - - topCommand = &cobra.Command{ - Use: "top [flags] POD [FORMAT-DESCRIPTORS|ARGS]", - Short: "Display the running processes in a pod", - Long: topDescription, - RunE: top, - Args: cobra.ArbitraryArgs, - Example: `podman pod top podID -podman pod top --latest -podman pod top podID pid seccomp args %C -podman pod top podID -eo user,pid,comm`, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: topCommand, - Parent: podCmd, - }) - - flags := topCommand.Flags() - flags.SetInterspersed(false) - flags.BoolVar(&topOptions.ListDescriptors, "list-descriptors", false, "") - flags.BoolVarP(&topOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - - _ = flags.MarkHidden("list-descriptors") // meant only for bash completion - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} - -func top(cmd *cobra.Command, args []string) error { - if topOptions.ListDescriptors { - fmt.Println(strings.Join(psgo.ListDescriptors(), "\n")) - return nil - } - - if len(args) < 1 && !topOptions.Latest { - return errors.Errorf("you must provide the name or id of a running pod") - } - - if topOptions.Latest { - topOptions.Descriptors = args - } else { - topOptions.NameOrID = args[0] - topOptions.Descriptors = args[1:] - } - - topResponse, err := registry.ContainerEngine().PodTop(context.Background(), topOptions) - if err != nil { - return err - } - - w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0) - for _, proc := range topResponse.Value { - if _, err := fmt.Fprintln(w, proc); err != nil { - return err - } - } - return w.Flush() -} diff --git a/cmd/podmanV2/pods/unpause.go b/cmd/podmanV2/pods/unpause.go deleted file mode 100644 index 2de7b964f..000000000 --- a/cmd/podmanV2/pods/unpause.go +++ /dev/null @@ -1,66 +0,0 @@ -package pods - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - podUnpauseDescription = `The podman unpause command will unpause all "paused" containers assigned to the pod. - - The pod name or ID can be used.` - unpauseCommand = &cobra.Command{ - Use: "unpause [flags] POD [POD...]", - Short: "Unpause one or more pods", - Long: podUnpauseDescription, - RunE: unpause, - Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) - }, - Example: `podman pod unpause podID1 podID2 - podman pod unpause --all - podman pod unpause --latest`, - } -) - -var ( - unpauseOptions entities.PodunpauseOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: unpauseCommand, - Parent: podCmd, - }) - flags := unpauseCommand.Flags() - flags.BoolVarP(&unpauseOptions.All, "all", "a", false, "Pause all running pods") - flags.BoolVarP(&unpauseOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } -} -func unpause(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - responses, err := registry.ContainerEngine().PodUnpause(context.Background(), args, unpauseOptions) - if err != nil { - return err - } - // in the cli, first we print out all the successful attempts - for _, r := range responses { - if len(r.Errs) == 0 { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Errs...) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/registry/config.go b/cmd/podmanV2/registry/config.go deleted file mode 100644 index 358f9172e..000000000 --- a/cmd/podmanV2/registry/config.go +++ /dev/null @@ -1,106 +0,0 @@ -package registry - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/containers/common/pkg/config" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/util" - "github.com/pkg/errors" -) - -const ( - ParentNSRequired = "ParentNSRequired" -) - -var ( - PodmanOptions entities.PodmanConfig -) - -// NewPodmanConfig creates a PodmanConfig from the environment -func NewPodmanConfig() entities.PodmanConfig { - if err := setXdgDirs(); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - var mode entities.EngineMode - switch runtime.GOOS { - case "darwin": - fallthrough - case "windows": - mode = entities.TunnelMode - case "linux": - mode = entities.ABIMode - default: - fmt.Fprintf(os.Stderr, "%s is not a supported OS", runtime.GOOS) - os.Exit(1) - } - - // cobra.Execute() may not be called yet, so we peek at os.Args. - for _, v := range os.Args { - // Prefix checking works because of how default EngineMode's - // have been defined. - if strings.HasPrefix(v, "--remote") { - mode = entities.TunnelMode - } - } - - // FIXME: for rootless, add flag to get the path to override configuration - cfg, err := config.NewConfig("") - if err != nil { - fmt.Fprint(os.Stderr, "Failed to obtain podman configuration: "+err.Error()) - os.Exit(1) - } - - cfg.Network.NetworkConfigDir = cfg.Network.CNIPluginDirs[0] - if rootless.IsRootless() { - cfg.Network.NetworkConfigDir = "" - } - - return entities.PodmanConfig{Config: cfg, EngineMode: mode} -} - -// SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set. -// containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is -// use for the libpod.conf configuration file. -func setXdgDirs() error { - if !rootless.IsRootless() { - return nil - } - - // Setup XDG_RUNTIME_DIR - if _, found := os.LookupEnv("XDG_RUNTIME_DIR"); !found { - dir, err := util.GetRuntimeDir() - if err != nil { - return err - } - if err := os.Setenv("XDG_RUNTIME_DIR", dir); err != nil { - return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR="+dir) - } - } - - if _, found := os.LookupEnv("DBUS_SESSION_BUS_ADDRESS"); !found { - sessionAddr := filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "bus") - if _, err := os.Stat(sessionAddr); err == nil { - os.Setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path="+sessionAddr) - } - } - - // Setup XDG_CONFIG_HOME - if _, found := os.LookupEnv("XDG_CONFIG_HOME"); !found { - cfgHomeDir, err := util.GetRootlessConfigHomeDir() - if err != nil { - return err - } - if err := os.Setenv("XDG_CONFIG_HOME", cfgHomeDir); err != nil { - return errors.Wrapf(err, "cannot set XDG_CONFIG_HOME="+cfgHomeDir) - } - } - return nil -} diff --git a/cmd/podmanV2/registry/registry.go b/cmd/podmanV2/registry/registry.go deleted file mode 100644 index 1c5e5d21b..000000000 --- a/cmd/podmanV2/registry/registry.go +++ /dev/null @@ -1,116 +0,0 @@ -package registry - -import ( - "context" - - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/domain/infra" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -// DefaultAPIAddress is the default address of the REST socket -const DefaultAPIAddress = "unix:/run/podman/podman.sock" - -// DefaultVarlinkAddress is the default address of the varlink socket -const DefaultVarlinkAddress = "unix:/run/podman/io.podman" - -type CliCommand struct { - Mode []entities.EngineMode - Command *cobra.Command - Parent *cobra.Command -} - -const ExecErrorCodeGeneric = 125 - -var ( - cliCtx context.Context - containerEngine entities.ContainerEngine - exitCode = ExecErrorCodeGeneric - imageEngine entities.ImageEngine - - // Commands holds the cobra.Commands to present to the user, including - // parent if not a child of "root" - Commands []CliCommand -) - -func SetExitCode(code int) { - exitCode = code -} - -func GetExitCode() int { - return exitCode -} - -func ImageEngine() entities.ImageEngine { - return imageEngine -} - -// NewImageEngine is a wrapper for building an ImageEngine to be used for PreRunE functions -func NewImageEngine(cmd *cobra.Command, args []string) (entities.ImageEngine, error) { - if imageEngine == nil { - PodmanOptions.FlagSet = cmd.Flags() - engine, err := infra.NewImageEngine(PodmanOptions) - if err != nil { - return nil, err - } - imageEngine = engine - } - return imageEngine, nil -} - -func ContainerEngine() entities.ContainerEngine { - return containerEngine -} - -// NewContainerEngine is a wrapper for building an ContainerEngine to be used for PreRunE functions -func NewContainerEngine(cmd *cobra.Command, args []string) (entities.ContainerEngine, error) { - if containerEngine == nil { - PodmanOptions.FlagSet = cmd.Flags() - engine, err := infra.NewContainerEngine(PodmanOptions) - if err != nil { - return nil, err - } - containerEngine = engine - } - return containerEngine, nil -} - -func SubCommandExists(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - return errors.Errorf("unrecognized command `%[1]s %[2]s`\nTry '%[1]s --help' for more information.", cmd.CommandPath(), args[0]) - } - return errors.Errorf("missing command '%[1]s COMMAND'\nTry '%[1]s --help' for more information.", cmd.CommandPath()) -} - -// IdOrLatestArgs used to validate a nameOrId was provided or the "--latest" flag -func IdOrLatestArgs(cmd *cobra.Command, args []string) error { - if len(args) > 1 || (len(args) == 0 && !cmd.Flag("latest").Changed) { - return errors.New(`command requires a name, id or the "--latest" flag`) - } - return nil -} - -type PodmanOptionsKey struct{} - -func Context() context.Context { - if cliCtx == nil { - cliCtx = ContextWithOptions(context.Background()) - } - return cliCtx -} - -func ContextWithOptions(ctx context.Context) context.Context { - cliCtx = context.WithValue(ctx, PodmanOptionsKey{}, PodmanOptions) - return cliCtx -} - -// GetContextWithOptions deprecated, use NewContextWithOptions() -func GetContextWithOptions() context.Context { - return ContextWithOptions(context.Background()) -} - -// GetContext deprecated, use Context() -func GetContext() context.Context { - return Context() -} diff --git a/cmd/podmanV2/registry/remote.go b/cmd/podmanV2/registry/remote.go deleted file mode 100644 index 5378701e7..000000000 --- a/cmd/podmanV2/registry/remote.go +++ /dev/null @@ -1,9 +0,0 @@ -package registry - -import ( - "github.com/containers/libpod/pkg/domain/entities" -) - -func IsRemote() bool { - return PodmanOptions.EngineMode == entities.TunnelMode -} diff --git a/cmd/podmanV2/report/diff.go b/cmd/podmanV2/report/diff.go deleted file mode 100644 index b36189d75..000000000 --- a/cmd/podmanV2/report/diff.go +++ /dev/null @@ -1,44 +0,0 @@ -package report - -import ( - "fmt" - "os" - - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/storage/pkg/archive" - jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" -) - -type ChangesReportJSON struct { - Changed []string `json:"changed,omitempty"` - Added []string `json:"added,omitempty"` - Deleted []string `json:"deleted,omitempty"` -} - -func ChangesToJSON(diffs *entities.DiffReport) error { - body := ChangesReportJSON{} - for _, row := range diffs.Changes { - switch row.Kind { - case archive.ChangeAdd: - body.Added = append(body.Added, row.Path) - case archive.ChangeDelete: - body.Deleted = append(body.Deleted, row.Path) - case archive.ChangeModify: - body.Changed = append(body.Changed, row.Path) - default: - return errors.Errorf("output kind %q not recognized", row.Kind) - } - } - - json := jsoniter.ConfigCompatibleWithStandardLibrary - enc := json.NewEncoder(os.Stdout) - return enc.Encode(body) -} - -func ChangesToTable(diffs *entities.DiffReport) error { - for _, row := range diffs.Changes { - fmt.Fprintln(os.Stdout, row.String()) - } - return nil -} diff --git a/cmd/podmanV2/root.go b/cmd/podmanV2/root.go deleted file mode 100644 index 801e728f0..000000000 --- a/cmd/podmanV2/root.go +++ /dev/null @@ -1,254 +0,0 @@ -package main - -import ( - "fmt" - "log/syslog" - "os" - "path" - "runtime/pprof" - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/tracing" - "github.com/containers/libpod/version" - "github.com/opentracing/opentracing-go" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - logrusSyslog "github.com/sirupsen/logrus/hooks/syslog" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// HelpTemplate is the help template for podman commands -// This uses the short and long options. -// command should not use this. -const helpTemplate = `{{.Short}} - -Description: - {{.Long}} - -{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` - -// UsageTemplate is the usage template for podman commands -// This blocks the displaying of the global options. The main podman -// command should not use this. -const usageTemplate = `Usage(v2):{{if (and .Runnable (not .HasAvailableSubCommands))}} - {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} - {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} - -Aliases: - {{.NameAndAliases}}{{end}}{{if .HasExample}} - -Examples: - {{.Example}}{{end}}{{if .HasAvailableSubCommands}} - -Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}} - {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} - -Flags: -{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} -{{end}} -` - -var ( - rootCmd = &cobra.Command{ - Use: path.Base(os.Args[0]), - Long: "Manage pods, containers and images", - SilenceUsage: true, - SilenceErrors: true, - TraverseChildren: true, - PersistentPreRunE: persistentPreRunE, - RunE: registry.SubCommandExists, - PersistentPostRunE: persistentPostRunE, - Version: version.Version, - } - - logLevels = []string{"debug", "info", "warn", "error", "fatal", "panic"} - logLevel = "error" - useSyslog bool -) - -func init() { - // Hooks are called before PersistentPreRunE() - cobra.OnInitialize( - loggingHook, - syslogHook, - ) - - rootFlags(registry.PodmanOptions, rootCmd.PersistentFlags()) -} - -func Execute() { - if err := rootCmd.ExecuteContext(registry.GetContextWithOptions()); err != nil { - logrus.Error(err) - } else if registry.GetExitCode() == registry.ExecErrorCodeGeneric { - // The exitCode modified from registry.ExecErrorCodeGeneric, - // indicates an application - // running inside of a container failed, as opposed to the - // podman command failed. Must exit with that exit code - // otherwise command exited correctly. - registry.SetExitCode(0) - } - os.Exit(registry.GetExitCode()) -} - -func persistentPreRunE(cmd *cobra.Command, args []string) error { - // TODO: Remove trace statement in podman V2.1 - logrus.Debugf("Called %s.PersistentPreRunE()", cmd.Name()) - - // Update PodmanOptions now that we "know" more - // TODO: pass in path overriding configuration file - registry.PodmanOptions = registry.NewPodmanConfig() - - // Prep the engines - if _, err := registry.NewImageEngine(cmd, args); err != nil { - return err - } - if _, err := registry.NewContainerEngine(cmd, args); err != nil { - return err - } - - if cmd.Flag("cpu-profile").Changed { - f, err := os.Create(registry.PodmanOptions.CpuProfile) - if err != nil { - return errors.Wrapf(err, "unable to create cpu profiling file %s", - registry.PodmanOptions.CpuProfile) - } - if err := pprof.StartCPUProfile(f); err != nil { - return err - } - } - - if cmd.Flag("trace").Changed { - tracer, closer := tracing.Init("podman") - opentracing.SetGlobalTracer(tracer) - registry.PodmanOptions.SpanCloser = closer - - registry.PodmanOptions.Span = tracer.StartSpan("before-context") - registry.PodmanOptions.SpanCtx = opentracing.ContextWithSpan(registry.Context(), registry.PodmanOptions.Span) - opentracing.StartSpanFromContext(registry.PodmanOptions.SpanCtx, cmd.Name()) - } - - // Setup Rootless environment, IFF: - // 1) in ABI mode - // 2) running as non-root - // 3) command doesn't require Parent Namespace - _, found := cmd.Annotations[registry.ParentNSRequired] - if !registry.IsRemote() && rootless.IsRootless() && !found { - err := registry.ContainerEngine().SetupRootless(registry.Context(), cmd) - if err != nil { - return err - } - } - return nil -} - -func persistentPostRunE(cmd *cobra.Command, args []string) error { - // TODO: Remove trace statement in podman V2.1 - logrus.Debugf("Called %s.PersistentPostRunE()", cmd.Name()) - - if cmd.Flag("cpu-profile").Changed { - pprof.StopCPUProfile() - } - if cmd.Flag("trace").Changed { - registry.PodmanOptions.Span.Finish() - registry.PodmanOptions.SpanCloser.Close() - } - return nil -} - -func loggingHook() { - var found bool - for _, l := range logLevels { - if l == logLevel { - found = true - break - } - } - if !found { - fmt.Fprintf(os.Stderr, "Log Level \"%s\" is not supported, choose from: %s\n", logLevel, strings.Join(logLevels, ", ")) - os.Exit(1) - } - - level, err := logrus.ParseLevel(logLevel) - if err != nil { - fmt.Fprint(os.Stderr, err.Error()) - os.Exit(1) - } - logrus.SetLevel(level) - - if logrus.IsLevelEnabled(logrus.InfoLevel) { - logrus.Infof("%s filtering at log level %s", os.Args[0], logrus.GetLevel()) - } -} - -func syslogHook() { - if !useSyslog { - return - } - - hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "") - if err != nil { - fmt.Fprint(os.Stderr, "Failed to initialize syslog hook: "+err.Error()) - os.Exit(1) - } - if err == nil { - logrus.AddHook(hook) - } -} - -func rootFlags(opts entities.PodmanConfig, flags *pflag.FlagSet) { - // V2 flags - flags.StringVarP(&opts.Uri, "remote", "r", "", "URL to access Podman service") - flags.StringSliceVar(&opts.Identities, "identity", []string{}, "path to SSH identity file") - - // Override default --help information of `--version` global flag - // TODO: restore -v option for version without breaking -v for volumes - var dummyVersion bool - flags.BoolVar(&dummyVersion, "version", false, "Version of Podman") - - cfg := opts.Config - flags.StringVar(&cfg.Engine.CgroupManager, "cgroup-manager", cfg.Engine.CgroupManager, opts.CGroupUsage) - flags.StringVar(&opts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results") - flags.StringVar(&opts.ConmonPath, "conmon", "", "Path of the conmon binary") - flags.StringVar(&cfg.Engine.NetworkCmdPath, "network-cmd-path", cfg.Engine.NetworkCmdPath, "Path to the command for configuring the network") - flags.StringVar(&cfg.Network.NetworkConfigDir, "cni-config-dir", cfg.Network.NetworkConfigDir, "Path of the configuration directory for CNI networks") - flags.StringVar(&cfg.Containers.DefaultMountsFile, "default-mounts-file", cfg.Containers.DefaultMountsFile, "Path to default mounts file") - flags.StringVar(&cfg.Engine.EventsLogger, "events-backend", cfg.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`) - flags.StringSliceVar(&cfg.Engine.HooksDir, "hooks-dir", cfg.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)") - flags.IntVar(&opts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations") - flags.StringVar(&cfg.Engine.Namespace, "namespace", cfg.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system") - flags.StringVar(&cfg.Engine.StaticDir, "root", "", "Path to the root directory in which data, including images, is stored") - flags.StringVar(&opts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") - flags.StringVar(&opts.RuntimePath, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc") - // -s is deprecated due to conflict with -s on subcommands - flags.StringVar(&opts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)") - flags.StringArrayVar(&opts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver") - - flags.StringVar(&opts.Engine.TmpDir, "tmpdir", "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n") - flags.BoolVar(&opts.Trace, "trace", false, "Enable opentracing output (default false)") - - // Override default --help information of `--help` global flag - var dummyHelp bool - flags.BoolVar(&dummyHelp, "help", false, "Help for podman") - flags.StringVar(&logLevel, "log-level", logLevel, fmt.Sprintf("Log messages above specified level (%s)", strings.Join(logLevels, ", "))) - - // Hide these flags for both ABI and Tunneling - for _, f := range []string{ - "cpu-profile", - "default-mounts-file", - "max-workers", - "trace", - } { - if err := flags.MarkHidden(f); err != nil { - logrus.Warnf("unable to mark %s flag as hidden: %s", f, err.Error()) - } - } - - // Only create these flags for ABI connections - if !registry.IsRemote() { - flags.BoolVar(&useSyslog, "syslog", false, "Output logging information to syslog as well as the console (default false)") - } -} diff --git a/cmd/podmanV2/system/events.go b/cmd/podmanV2/system/events.go deleted file mode 100644 index 95e6a5576..000000000 --- a/cmd/podmanV2/system/events.go +++ /dev/null @@ -1,103 +0,0 @@ -package system - -import ( - "bufio" - "context" - "html/template" - "os" - - "github.com/containers/buildah/pkg/formats" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/libpod/events" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - eventsDescription = "Monitor podman events" - eventsCommand = &cobra.Command{ - Use: "events", - Args: cobra.NoArgs, - Short: "Show podman events", - Long: eventsDescription, - RunE: eventsCmd, - Example: `podman events - podman events --filter event=create - podman events --since 1h30s`, - } -) - -var ( - eventOptions entities.EventsOptions - eventFormat string -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: eventsCommand, - }) - flags := eventsCommand.Flags() - flags.StringArrayVar(&eventOptions.Filter, "filter", []string{}, "filter output") - flags.StringVar(&eventFormat, "format", "", "format the output using a Go template") - flags.BoolVar(&eventOptions.Stream, "stream", true, "stream new events; for testing only") - flags.StringVar(&eventOptions.Since, "since", "", "show all events created since timestamp") - flags.StringVar(&eventOptions.Until, "until", "", "show all events until timestamp") - _ = flags.MarkHidden("stream") -} - -func eventsCmd(cmd *cobra.Command, args []string) error { - var ( - err error - eventsError error - tmpl *template.Template - ) - if eventFormat != formats.JSONString { - tmpl, err = template.New("events").Parse(eventFormat) - if err != nil { - return err - } - } - if len(eventOptions.Since) > 0 || len(eventOptions.Until) > 0 { - eventOptions.FromStart = true - } - eventChannel := make(chan *events.Event) - eventOptions.EventChan = eventChannel - - go func() { - eventsError = registry.ContainerEngine().Events(context.Background(), eventOptions) - }() - if eventsError != nil { - return eventsError - } - - w := bufio.NewWriter(os.Stdout) - for event := range eventChannel { - switch { - case eventFormat == formats.JSONString: - jsonStr, err := event.ToJSONString() - if err != nil { - return errors.Wrapf(err, "unable to format json") - } - if _, err := w.Write([]byte(jsonStr)); err != nil { - return err - } - case len(eventFormat) > 0: - if err := tmpl.Execute(w, event); err != nil { - return err - } - default: - if _, err := w.Write([]byte(event.ToHumanReadable())); err != nil { - return err - } - } - if _, err := w.Write([]byte("\n")); err != nil { - return err - } - if err := w.Flush(); err != nil { - return err - } - } - return nil -} diff --git a/cmd/podmanV2/system/info.go b/cmd/podmanV2/system/info.go deleted file mode 100644 index 6b0c6a13b..000000000 --- a/cmd/podmanV2/system/info.go +++ /dev/null @@ -1,73 +0,0 @@ -package system - -import ( - "encoding/json" - "fmt" - "os" - "text/template" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" - "gopkg.in/yaml.v2" -) - -var ( - infoDescription = `Display information pertaining to the host, current storage stats, and build of podman. - - Useful for the user and when reporting issues. -` - infoCommand = &cobra.Command{ - Use: "info", - Args: cobra.NoArgs, - Long: infoDescription, - Short: "Display podman system information", - RunE: info, - Example: `podman info`, - } -) - -var ( - inFormat string - debug bool -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: infoCommand, - }) - flags := infoCommand.Flags() - flags.BoolVarP(&debug, "debug", "D", false, "Display additional debug information") - flags.StringVarP(&inFormat, "format", "f", "", "Change the output format to JSON or a Go template") -} - -func info(cmd *cobra.Command, args []string) error { - info, err := registry.ContainerEngine().Info(registry.GetContext()) - if err != nil { - return err - } - - if inFormat == "json" { - b, err := json.MarshalIndent(info, "", " ") - if err != nil { - return err - } - fmt.Println(string(b)) - return nil - } - if !cmd.Flag("format").Changed { - b, err := yaml.Marshal(info) - if err != nil { - return err - } - fmt.Println(string(b)) - return nil - } - tmpl, err := template.New("info").Parse(inFormat) - if err != nil { - return err - } - err = tmpl.Execute(os.Stdout, info) - return err -} diff --git a/cmd/podmanV2/system/service.go b/cmd/podmanV2/system/service.go deleted file mode 100644 index 5573f7039..000000000 --- a/cmd/podmanV2/system/service.go +++ /dev/null @@ -1,124 +0,0 @@ -package system - -import ( - "fmt" - "os" - "path/filepath" - "time" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/systemd" - "github.com/containers/libpod/pkg/util" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var ( - srvDescription = `Run an API service - -Enable a listening service for API access to Podman commands. -` - - srvCmd = &cobra.Command{ - Use: "service [flags] [URI]", - Args: cobra.MaximumNArgs(1), - Short: "Run API service", - Long: srvDescription, - RunE: service, - Example: `podman system service --time=0 unix:///tmp/podman.sock - podman system service --varlink --time=0 unix:///tmp/podman.sock`, - } - - srvArgs = struct { - Timeout int64 - Varlink bool - }{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode}, - Command: srvCmd, - Parent: systemCmd, - }) - - flags := srvCmd.Flags() - flags.Int64VarP(&srvArgs.Timeout, "time", "t", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout") - flags.Int64Var(&srvArgs.Timeout, "timeout", 5, "Time until the service session expires in seconds. Use 0 to disable the timeout") - flags.BoolVar(&srvArgs.Varlink, "varlink", false, "Use legacy varlink service instead of REST") - - _ = flags.MarkDeprecated("varlink", "valink API is deprecated.") -} - -func service(cmd *cobra.Command, args []string) error { - apiURI, err := resolveApiURI(args) - if err != nil { - return err - } - logrus.Infof("using API endpoint: \"%s\"", apiURI) - - opts := entities.ServiceOptions{ - URI: apiURI, - Timeout: time.Duration(srvArgs.Timeout) * time.Second, - Command: cmd, - } - - if srvArgs.Varlink { - return registry.ContainerEngine().VarlinkService(registry.GetContext(), opts) - } - - logrus.Warn("This function is EXPERIMENTAL") - fmt.Fprintf(os.Stderr, "This function is EXPERIMENTAL.\n") - return registry.ContainerEngine().RestService(registry.GetContext(), opts) -} - -func resolveApiURI(_url []string) (string, error) { - - // When determining _*THE*_ listening endpoint -- - // 1) User input wins always - // 2) systemd socket activation - // 3) rootless honors XDG_RUNTIME_DIR - // 4) if varlink -- adapter.DefaultVarlinkAddress - // 5) lastly adapter.DefaultAPIAddress - - if _url == nil { - if v, found := os.LookupEnv("PODMAN_SOCKET"); found { - _url = []string{v} - } - } - - switch { - case len(_url) > 0: - return _url[0], nil - case systemd.SocketActivated(): - logrus.Info("using systemd socket activation to determine API endpoint") - return "", nil - case rootless.IsRootless(): - xdg, err := util.GetRuntimeDir() - if err != nil { - return "", err - } - - socketName := "podman.sock" - if srvArgs.Varlink { - socketName = "io.podman" - } - socketDir := filepath.Join(xdg, "podman", socketName) - if _, err := os.Stat(filepath.Dir(socketDir)); err != nil { - if os.IsNotExist(err) { - if err := os.Mkdir(filepath.Dir(socketDir), 0755); err != nil { - return "", err - } - } else { - return "", err - } - } - return "unix:" + socketDir, nil - case srvArgs.Varlink: - return registry.DefaultVarlinkAddress, nil - default: - return registry.DefaultAPIAddress, nil - } -} diff --git a/cmd/podmanV2/system/system.go b/cmd/podmanV2/system/system.go deleted file mode 100644 index e62a0c150..000000000 --- a/cmd/podmanV2/system/system.go +++ /dev/null @@ -1,25 +0,0 @@ -package system - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // Command: podman _system_ - systemCmd = &cobra.Command{ - Use: "system", - Short: "Manage podman", - Long: "Manage podman", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: systemCmd, - }) -} diff --git a/cmd/podmanV2/system/varlink.go b/cmd/podmanV2/system/varlink.go deleted file mode 100644 index 27dd0a7e9..000000000 --- a/cmd/podmanV2/system/varlink.go +++ /dev/null @@ -1,52 +0,0 @@ -package system - -import ( - "time" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - varlinkDescription = `Run varlink interface. Podman varlink listens on the specified unix domain socket for incoming connects. - - Tools speaking varlink protocol can remotely manage pods, containers and images. -` - varlinkCmd = &cobra.Command{ - Use: "varlink [flags] [URI]", - Args: cobra.MinimumNArgs(1), - Short: "Run varlink interface", - Long: varlinkDescription, - RunE: varlinkE, - Example: `podman varlink unix:/run/podman/io.podman - podman varlink --timeout 5000 unix:/run/podman/io.podman`, - } - varlinkArgs = struct { - Timeout int64 - }{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: varlinkCmd, - }) - flags := varlinkCmd.Flags() - flags.Int64VarP(&varlinkArgs.Timeout, "time", "t", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout") - flags.Int64Var(&varlinkArgs.Timeout, "timeout", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout") - -} - -func varlinkE(cmd *cobra.Command, args []string) error { - uri := registry.DefaultVarlinkAddress - if len(args) > 0 { - uri = args[0] - } - opts := entities.ServiceOptions{ - URI: uri, - Timeout: time.Duration(varlinkArgs.Timeout) * time.Second, - Command: cmd, - } - return registry.ContainerEngine().VarlinkService(registry.GetContext(), opts) -} diff --git a/cmd/podmanV2/system/version.go b/cmd/podmanV2/system/version.go deleted file mode 100644 index 7004c3109..000000000 --- a/cmd/podmanV2/system/version.go +++ /dev/null @@ -1,121 +0,0 @@ -package system - -import ( - "fmt" - "io" - "os" - "strings" - "text/tabwriter" - "time" - - "github.com/containers/buildah/pkg/formats" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - versionCommand = &cobra.Command{ - Use: "version", - Args: cobra.NoArgs, - Short: "Display the Podman Version Information", - RunE: version, - Annotations: map[string]string{ - registry.ParentNSRequired: "", - }, - } - versionFormat string -) - -type versionStruct struct { - Client define.Version - Server define.Version -} - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: versionCommand, - }) - flags := versionCommand.Flags() - flags.StringVarP(&versionFormat, "format", "f", "", "Change the output format to JSON or a Go template") -} - -func version(cmd *cobra.Command, args []string) error { - var ( - v versionStruct - err error - ) - v.Client, err = define.GetVersion() - if err != nil { - return errors.Wrapf(err, "unable to determine version") - } - // TODO we need to discuss how to implement - // this more. current endpoints dont have a - // version endpoint. maybe we use info? - //if remote { - // v.Server, err = getRemoteVersion(c) - // if err != nil { - // return err - // } - //} else { - v.Server = v.Client - //} - - versionOutputFormat := versionFormat - if versionOutputFormat != "" { - if strings.Join(strings.Fields(versionOutputFormat), "") == "{{json.}}" { - versionOutputFormat = formats.JSONString - } - var out formats.Writer - switch versionOutputFormat { - case formats.JSONString: - out = formats.JSONStruct{Output: v} - return out.Out() - default: - out = formats.StdoutTemplate{Output: v, Template: versionOutputFormat} - err := out.Out() - if err != nil { - // On Failure, assume user is using older version of podman version --format and check client - out = formats.StdoutTemplate{Output: v.Client, Template: versionOutputFormat} - if err1 := out.Out(); err1 != nil { - return err - } - } - } - return nil - } - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - defer w.Flush() - - if registry.IsRemote() { - if _, err := fmt.Fprintf(w, "Client:\n"); err != nil { - return err - } - formatVersion(w, v.Client) - if _, err := fmt.Fprintf(w, "\nServer:\n"); err != nil { - return err - } - formatVersion(w, v.Server) - } else { - formatVersion(w, v.Client) - } - return nil -} - -func formatVersion(writer io.Writer, version define.Version) { - fmt.Fprintf(writer, "Version:\t%s\n", version.Version) - fmt.Fprintf(writer, "RemoteAPI Version:\t%d\n", version.RemoteAPIVersion) - fmt.Fprintf(writer, "Go Version:\t%s\n", version.GoVersion) - if version.GitCommit != "" { - fmt.Fprintf(writer, "Git Commit:\t%s\n", version.GitCommit) - } - // Prints out the build time in readable format - if version.Built != 0 { - fmt.Fprintf(writer, "Built:\t%s\n", time.Unix(version.Built, 0).Format(time.ANSIC)) - } - - fmt.Fprintf(writer, "OS/Arch:\t%s\n", version.OsArch) -} diff --git a/cmd/podmanV2/utils/alias.go b/cmd/podmanV2/utils/alias.go deleted file mode 100644 index 54b3c5e89..000000000 --- a/cmd/podmanV2/utils/alias.go +++ /dev/null @@ -1,24 +0,0 @@ -package utils - -import "github.com/spf13/pflag" - -// AliasFlags is a function to handle backwards compatability with old flags -func AliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName { - switch name { - case "healthcheck-command": - name = "health-cmd" - case "healthcheck-interval": - name = "health-interval" - case "healthcheck-retries": - name = "health-retries" - case "healthcheck-start-period": - name = "health-start-period" - case "healthcheck-timeout": - name = "health-timeout" - case "net": - name = "network" - case "timeout": - name = "time" - } - return pflag.NormalizedName(name) -} diff --git a/cmd/podmanV2/utils/error.go b/cmd/podmanV2/utils/error.go deleted file mode 100644 index 3464f0779..000000000 --- a/cmd/podmanV2/utils/error.go +++ /dev/null @@ -1,16 +0,0 @@ -package utils - -import "fmt" - -type OutputErrors []error - -func (o OutputErrors) PrintErrors() (lastError error) { - if len(o) == 0 { - return - } - lastError = o[len(o)-1] - for e := 0; e < len(o)-1; e++ { - fmt.Println(o[e]) - } - return -} diff --git a/cmd/podmanV2/volumes/create.go b/cmd/podmanV2/volumes/create.go deleted file mode 100644 index 91181dd03..000000000 --- a/cmd/podmanV2/volumes/create.go +++ /dev/null @@ -1,72 +0,0 @@ -package volumes - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/parse" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - createDescription = `If using the default driver, "local", the volume will be created on the host in the volumes directory under container storage.` - - createCommand = &cobra.Command{ - Use: "create [flags] [NAME]", - Short: "Create a new volume", - Long: createDescription, - RunE: create, - Example: `podman volume create myvol - podman volume create - podman volume create --label foo=bar myvol`, - } -) - -var ( - createOpts = entities.VolumeCreateOptions{} - opts = struct { - Label []string - Opts []string - }{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: createCommand, - Parent: volumeCmd, - }) - flags := createCommand.Flags() - flags.StringVar(&createOpts.Driver, "driver", "", "Specify volume driver name (default local)") - flags.StringSliceVarP(&opts.Label, "label", "l", []string{}, "Set metadata for a volume (default [])") - flags.StringArrayVarP(&opts.Opts, "opt", "o", []string{}, "Set driver specific options (default [])") -} - -func create(cmd *cobra.Command, args []string) error { - var ( - err error - ) - if len(args) > 1 { - return errors.Errorf("too many arguments, create takes at most 1 argument") - } - if len(args) > 0 { - createOpts.Name = args[0] - } - createOpts.Label, err = parse.GetAllLabels([]string{}, opts.Label) - if err != nil { - return errors.Wrapf(err, "unable to process labels") - } - createOpts.Options, err = parse.GetAllLabels([]string{}, opts.Opts) - if err != nil { - return errors.Wrapf(err, "unable to process options") - } - response, err := registry.ContainerEngine().VolumeCreate(context.Background(), createOpts) - if err != nil { - return err - } - fmt.Println(response.IdOrName) - return nil -} diff --git a/cmd/podmanV2/volumes/inspect.go b/cmd/podmanV2/volumes/inspect.go deleted file mode 100644 index 4d9720432..000000000 --- a/cmd/podmanV2/volumes/inspect.go +++ /dev/null @@ -1,74 +0,0 @@ -package volumes - -import ( - "encoding/json" - "fmt" - "html/template" - "os" - - "github.com/containers/buildah/pkg/formats" - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -var ( - volumeInspectDescription = `Display detailed information on one or more volumes. - - Use a Go template to change the format from JSON.` - inspectCommand = &cobra.Command{ - Use: "inspect [flags] VOLUME [VOLUME...]", - Short: "Display detailed information on one or more volumes", - Long: volumeInspectDescription, - RunE: inspect, - Example: `podman volume inspect myvol - podman volume inspect --all - podman volume inspect --format "{{.Driver}} {{.Scope}}" myvol`, - } -) - -var ( - inspectOpts = entities.VolumeInspectOptions{} - inspectFormat string -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: inspectCommand, - Parent: volumeCmd, - }) - flags := inspectCommand.Flags() - flags.BoolVarP(&inspectOpts.All, "all", "a", false, "Inspect all volumes") - flags.StringVarP(&inspectFormat, "format", "f", "json", "Format volume output using Go template") -} - -func inspect(cmd *cobra.Command, args []string) error { - if (inspectOpts.All && len(args) > 0) || (!inspectOpts.All && len(args) < 1) { - return errors.New("provide one or more volume names or use --all") - } - responses, err := registry.ContainerEngine().VolumeInspect(context.Background(), args, inspectOpts) - if err != nil { - return err - } - switch inspectFormat { - case "", formats.JSONString: - jsonOut, err := json.MarshalIndent(responses, "", " ") - if err != nil { - return errors.Wrapf(err, "error marshalling inspect JSON") - } - fmt.Println(string(jsonOut)) - default: - tmpl, err := template.New("volumeInspect").Parse(inspectFormat) - if err != nil { - return err - } - if err := tmpl.Execute(os.Stdout, responses); err != nil { - return err - } - } - return nil - -} diff --git a/cmd/podmanV2/volumes/list.go b/cmd/podmanV2/volumes/list.go deleted file mode 100644 index c38f78c73..000000000 --- a/cmd/podmanV2/volumes/list.go +++ /dev/null @@ -1,98 +0,0 @@ -package volumes - -import ( - "context" - "html/template" - "io" - "os" - "strings" - "text/tabwriter" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - volumeLsDescription = ` -podman volume ls - -List all available volumes. The output of the volumes can be filtered -and the output format can be changed to JSON or a user specified Go template.` - lsCommand = &cobra.Command{ - Use: "ls", - Aliases: []string{"list"}, - Args: cobra.NoArgs, - Short: "List volumes", - Long: volumeLsDescription, - RunE: list, - } -) - -var ( - // Temporary struct to hold cli values. - cliOpts = struct { - Filter []string - Format string - Quiet bool - }{} - lsOpts = entities.VolumeListOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: lsCommand, - Parent: volumeCmd, - }) - flags := lsCommand.Flags() - flags.StringSliceVarP(&cliOpts.Filter, "filter", "f", []string{}, "Filter volume output") - flags.StringVar(&cliOpts.Format, "format", "{{.Driver}}\t{{.Name}}\n", "Format volume output using Go template") - flags.BoolVarP(&cliOpts.Quiet, "quiet", "q", false, "Print volume output in quiet mode") -} - -func list(cmd *cobra.Command, args []string) error { - var w io.Writer = os.Stdout - if cliOpts.Quiet && cmd.Flag("format").Changed { - return errors.New("quiet and format flags cannot be used together") - } - for _, f := range cliOpts.Filter { - filterSplit := strings.Split(f, "=") - if len(filterSplit) < 2 { - return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) - } - lsOpts.Filter[filterSplit[0]] = append(lsOpts.Filter[filterSplit[0]], filterSplit[1:]...) - } - responses, err := registry.ContainerEngine().VolumeList(context.Background(), lsOpts) - if err != nil { - return err - } - // "\t" from the command line is not being recognized as a tab - // replacing the string "\t" to a tab character if the user passes in "\t" - cliOpts.Format = strings.Replace(cliOpts.Format, `\t`, "\t", -1) - if cliOpts.Quiet { - cliOpts.Format = "{{.Name}}\n" - } - headers := "DRIVER\tVOLUME NAME\n" - row := cliOpts.Format - if !strings.HasSuffix(cliOpts.Format, "\n") { - row += "\n" - } - format := "{{range . }}" + row + "{{end}}" - if !cliOpts.Quiet && !cmd.Flag("format").Changed { - w = tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0) - format = headers + format - } - tmpl, err := template.New("listVolume").Parse(format) - if err != nil { - return err - } - if err := tmpl.Execute(w, responses); err != nil { - return err - } - if flusher, ok := w.(interface{ Flush() error }); ok { - return flusher.Flush() - } - return nil -} diff --git a/cmd/podmanV2/volumes/prune.go b/cmd/podmanV2/volumes/prune.go deleted file mode 100644 index 148065f56..000000000 --- a/cmd/podmanV2/volumes/prune.go +++ /dev/null @@ -1,74 +0,0 @@ -package volumes - -import ( - "bufio" - "context" - "fmt" - "os" - "strings" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - volumePruneDescription = `Volumes that are not currently owned by a container will be removed. - - The command prompts for confirmation which can be overridden with the --force flag. - Note all data will be destroyed.` - pruneCommand = &cobra.Command{ - Use: "prune", - Args: cobra.NoArgs, - Short: "Remove all unused volumes", - Long: volumePruneDescription, - RunE: prune, - } -) - -var ( - pruneOptions entities.VolumePruneOptions -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: pruneCommand, - Parent: volumeCmd, - }) - flags := pruneCommand.Flags() - flags.BoolVarP(&pruneOptions.Force, "force", "f", false, "Do not prompt for confirmation") -} - -func prune(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - // Prompt for confirmation if --force is not set - if !pruneOptions.Force { - reader := bufio.NewReader(os.Stdin) - fmt.Println("WARNING! This will remove all volumes not used by at least one container.") - fmt.Print("Are you sure you want to continue? [y/N] ") - answer, err := reader.ReadString('\n') - if err != nil { - return errors.Wrapf(err, "error reading input") - } - if strings.ToLower(answer)[0] != 'y' { - return nil - } - } - responses, err := registry.ContainerEngine().VolumePrune(context.Background(), pruneOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/volumes/rm.go b/cmd/podmanV2/volumes/rm.go deleted file mode 100644 index b019285d8..000000000 --- a/cmd/podmanV2/volumes/rm.go +++ /dev/null @@ -1,64 +0,0 @@ -package volumes - -import ( - "context" - "fmt" - - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -var ( - volumeRmDescription = `Remove one or more existing volumes. - - By default only volumes that are not being used by any containers will be removed. To remove the volumes anyways, use the --force flag.` - rmCommand = &cobra.Command{ - Use: "rm [flags] VOLUME [VOLUME...]", - Aliases: []string{"remove"}, - Short: "Remove one or more volumes", - Long: volumeRmDescription, - RunE: rm, - Example: `podman volume rm myvol1 myvol2 - podman volume rm --all - podman volume rm --force myvol`, - } -) - -var ( - rmOptions = entities.VolumeRmOptions{} -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: rmCommand, - Parent: volumeCmd, - }) - flags := rmCommand.Flags() - flags.BoolVarP(&rmOptions.All, "all", "a", false, "Remove all volumes") - flags.BoolVarP(&rmOptions.Force, "force", "f", false, "Remove a volume by force, even if it is being used by a container") -} - -func rm(cmd *cobra.Command, args []string) error { - var ( - errs utils.OutputErrors - ) - if (len(args) > 0 && rmOptions.All) || (len(args) < 1 && !rmOptions.All) { - return errors.New("choose either one or more volumes or all") - } - responses, err := registry.ContainerEngine().VolumeRm(context.Background(), args, rmOptions) - if err != nil { - return err - } - for _, r := range responses { - if r.Err == nil { - fmt.Println(r.Id) - } else { - errs = append(errs, r.Err) - } - } - return errs.PrintErrors() -} diff --git a/cmd/podmanV2/volumes/volume.go b/cmd/podmanV2/volumes/volume.go deleted file mode 100644 index d1135d1bf..000000000 --- a/cmd/podmanV2/volumes/volume.go +++ /dev/null @@ -1,25 +0,0 @@ -package volumes - -import ( - "github.com/containers/libpod/cmd/podmanV2/registry" - "github.com/containers/libpod/pkg/domain/entities" - "github.com/spf13/cobra" -) - -var ( - // Command: podman _volume_ - volumeCmd = &cobra.Command{ - Use: "volume", - Short: "Manage volumes", - Long: "Volumes are created in and can be shared between containers", - TraverseChildren: true, - RunE: registry.SubCommandExists, - } -) - -func init() { - registry.Commands = append(registry.Commands, registry.CliCommand{ - Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, - Command: volumeCmd, - }) -} |