diff options
-rw-r--r-- | cmd/podman/containers/exists.go | 15 | ||||
-rw-r--r-- | cmd/podman/containers/ps.go | 2 | ||||
-rw-r--r-- | cmd/podman/diff.go | 5 | ||||
-rw-r--r-- | cmd/podman/utils/alias.go | 2 | ||||
-rw-r--r-- | completions/bash/podman | 558 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-exists.1.md | 14 | ||||
-rw-r--r-- | docs/source/markdown/podman-ps.1.md | 78 | ||||
-rw-r--r-- | libpod/diff.go | 20 | ||||
-rw-r--r-- | libpod/runtime_cstorage.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/containers.go | 30 | ||||
-rw-r--r-- | pkg/bindings/containers/containers.go | 6 | ||||
-rw-r--r-- | pkg/bindings/test/containers_test.go | 12 | ||||
-rw-r--r-- | pkg/domain/entities/containers.go | 5 | ||||
-rw-r--r-- | pkg/domain/entities/engine_container.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 16 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 4 | ||||
-rw-r--r-- | test/system/030-run.bats | 20 | ||||
-rw-r--r-- | test/system/140-diff.bats | 22 |
18 files changed, 384 insertions, 431 deletions
diff --git a/cmd/podman/containers/exists.go b/cmd/podman/containers/exists.go index 283f6df18..1d79b684d 100644 --- a/cmd/podman/containers/exists.go +++ b/cmd/podman/containers/exists.go @@ -12,10 +12,10 @@ 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", + Use: "exists [flags] CONTAINER", Short: "Check if a container exists in local storage", Long: containerExistsDescription, - Example: `podman container exists containerID + Example: `podman container exists --external containerID podman container exists myctr || podman run --name myctr [etc...]`, RunE: exists, Args: cobra.ExactArgs(1), @@ -29,10 +29,19 @@ func init() { Command: existsCommand, Parent: containerCmd, }) + flags := existsCommand.Flags() + flags.Bool("external", false, "Check external storage containers as well as Podman containers") } func exists(cmd *cobra.Command, args []string) error { - response, err := registry.ContainerEngine().ContainerExists(context.Background(), args[0]) + external, err := cmd.Flags().GetBool("external") + if err != nil { + return err + } + options := entities.ContainerExistsOptions{ + External: external, + } + response, err := registry.ContainerEngine().ContainerExists(context.Background(), args[0], options) if err != nil { return err } diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 65bfc97da..41d309f51 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -58,7 +58,7 @@ func init() { func listFlagSet(flags *pflag.FlagSet) { 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.BoolVar(&listOpts.Storage, "storage", false, "Show containers in storage not controlled by Podman") + flags.BoolVar(&listOpts.Storage, "external", false, "Show containers in storage not controlled by Podman") 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.BoolVar(&listOpts.Namespace, "ns", false, "Display namespace information") diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go index 51a04bf46..9d2236abe 100644 --- a/cmd/podman/diff.go +++ b/cmd/podman/diff.go @@ -48,7 +48,10 @@ func diff(cmd *cobra.Command, args []string) error { return containers.Diff(cmd, args, diffOpts) } - if found, err := registry.ContainerEngine().ContainerExists(registry.GetContext(), args[0]); err != nil { + options := entities.ContainerExistsOptions{ + External: true, + } + if found, err := registry.ContainerEngine().ContainerExists(registry.GetContext(), args[0], options); err != nil { return err } else if found.Value { return containers.Diff(cmd, args, diffOpts) diff --git a/cmd/podman/utils/alias.go b/cmd/podman/utils/alias.go index ff31e82ea..10b96fa98 100644 --- a/cmd/podman/utils/alias.go +++ b/cmd/podman/utils/alias.go @@ -21,6 +21,8 @@ func AliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName { name = "time" case "namespace": name = "ns" + case "storage": + name = "external" } return pflag.NormalizedName(name) } diff --git a/completions/bash/podman b/completions/bash/podman index 564d35f67..c08bb3352 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -755,10 +755,8 @@ _podman_attach() { --detach-keys " local boolean_options=" - --help - -h - --latest - -l + --help -h + --latest -l --no-stdin --sig-proxy " @@ -782,18 +780,13 @@ _podman_container_checkpoint() { --export " local boolean_options=" - -a - --all - -h - --help - -k - --keep - -l - --latest - -R - --leave-running - --tcp-established + --all -a + --help -h --ignore-rootfs + --keep -k + --latest -l + --leave-running -R + --tcp-established " case "$prev" in -e|--export) @@ -897,18 +890,14 @@ _podman_container_restore() { --name " local boolean_options=" - -a - --all - -h - --help - -k - --keep - -l - --latest - --tcp-established + --all -a + --help -h --ignore-rootfs --ignore-static-ip --ignore-static-mac + --keep -k + --latest -l + --tcp-established " case "$prev" in -i|--import) @@ -1015,9 +1004,8 @@ _podman_network_create() { --subnet " local boolean_options=" - --disable-dns - --help - -h + --disable-dns + --help -h --internal " _complete_ "$options_with_args" "$boolean_options" @@ -1049,9 +1037,8 @@ _podman_network_inspect() { _podman_network_ls() { local options_with_args=" - --format - -f --filter + --format -f " local boolean_options=" --help @@ -1072,10 +1059,8 @@ _podman_network_rm() { local options_with_args=" " local boolean_options=" - --force - -f - --help - -h + --force -f + --help -h " _complete_ "$options_with_args" "$boolean_options" @@ -1222,12 +1207,9 @@ _podman_system_prune() { " local boolean_options=" - -a - --all - -f - --force - -h - --help + --all -a + --force -f + --help -h --volumes " case "$cur" in @@ -1287,12 +1269,9 @@ _podman_commit() { --iidfile " local boolean_options=" - --help - -h - --pause - -p - --quiet - -q + --help -h + --pause -p + --quiet -q " _complete_ "$options_with_args" "$boolean_options" @@ -1309,15 +1288,13 @@ _podman_commit() { _podman_build() { local boolean_options=" --force-rm - --help - -h + --help -h --layers --no-cache --pull --pull-always --pull-never - --quiet - -q + --quiet -q --rm --squash --squash-all @@ -1340,33 +1317,29 @@ _podman_build() { --cpuset-cpus --cpuset-mems --creds - -f - --file + --file -f --format --iidfile --ipc --label - -m - --memory + --memory -m --memory-swap + --mount --net --network --pid --runtime-flag --security-opt --shm-size - -t - --tag + --tag -t --ulimit --userns - --userns-uid-map --userns-gid-map - --userns-uid-map-user --userns-gid-map-group + --userns-uid-map + --userns-uid-map-user --uts - --mount - --volume - -v + --volume -v " case "$prev" in @@ -1414,13 +1387,10 @@ _podman_exec() { -w " local boolean_options=" - --help - -h - --latest - -l + --help -h + --latest -l --privileged - --tty - -t + --tty -t " case "$cur" in -*) @@ -1456,8 +1426,7 @@ _podman_history() { --format " local boolean_options=" - --help - -h + --help -h --human -H --no-trunc --quiet -q @@ -1540,12 +1509,9 @@ _podman_image_umount() { _podman_image_unmount() { local boolean_options=" - --all - -a - --help - -h - --force - -f + --all -a + --help -h + --force -f " local options_with_args=" " @@ -1563,10 +1529,8 @@ _podman_image_unmount() { _podman_image_mount() { local boolean_options=" - --all - -a - --help - -h + --all -a + --help -h " local options_with_args=" @@ -1680,21 +1644,15 @@ _podman_image() { _podman_images() { local boolean_options=" - -a - --all + --all -a --digests - --digests - -f - --filter - -h - --help + --filter -f + --help -h --history --no-trunc - --notruncate - -n --noheading - -q - --quiet + --notruncate -n + --quiet -q " local options_with_args=" --format @@ -1715,10 +1673,8 @@ _podman_images() { _podman_inspect() { local boolean_options=" - --help - -h - --latest - -l + --help -h + --latest -l " local options_with_args=" --format @@ -1785,12 +1741,9 @@ _podman_kill() { --signal -s " local boolean_options=" - --all - -a - --help - -h - --latest - -l + --all -a + --help -h + --latest -l " case "$cur" in -*) @@ -1808,14 +1761,10 @@ _podman_logs() { --tail " local boolean_options=" - --follow - -f - --help - -h - --latest - -l - --timestamps - -t + --follow -f + --help -h + --latest -l + --timestamps -t " _complete_ "$options_with_args" "$boolean_options" @@ -1856,10 +1805,10 @@ _podman_manifest() { _podman_manifest_add() { local options_with_args=" --annotation + --arch --authfile --cert-dir --creds - --arch --features --os --os-version @@ -1946,20 +1895,18 @@ _podman_manifest_push() { --cert-dir --creds --digestfile - --format - -f + --format -f --sign-by --signature-policy, " local boolean_options=" --all + --help -h --purge - --help - -h + --quiet --remove-signatures --tls-verify - --quiet " _complete_ "$options_with_args" "$boolean_options" @@ -2001,13 +1948,10 @@ _podman_pull() { --override-variant " local boolean_options=" - --all-tags - -a + --all-tags -a --disable-content-trust - --help - -h - --quiet - -q + --help -h + --quiet -q --tls-verify " _complete_ "$options_with_args" "$boolean_options" @@ -2035,14 +1979,10 @@ _podman_unmount() { _podman_umount() { local boolean_options=" - --all - -a - --help - -h - --force - -f - --latest - -l + --all -a + --help -h + --force -f + --latest -l " local options_with_args=" " @@ -2060,12 +2000,9 @@ _podman_umount() { _podman_mount() { local boolean_options=" - --all - -a - --help - -h - -l - --latest + --all -a + --help -h + --latest -l --notruncate " @@ -2088,19 +2025,17 @@ _podman_push() { local boolean_options=" --compress --digestflag - --help - -h - --quiet - -q + --help -h + --quiet -q --tls-verify " local options_with_args=" - --authfile - --format - --cert-dir - --creds - --sign-by + --authfile + --cert-dir + --creds + --format + --sign-by " local all_options="$options_with_args $boolean_options" @@ -2125,18 +2060,18 @@ _podman_container_run() { --builtin-volume --cap-add --cap-drop - --cgroup-parent --cgroup-conf + --cgroup-parent --cidfile --conmon-pidfile --cpu-period --cpu-quota --cpu-rt-period --cpu-rt-runtime - --cpuset-cpus + --cpu-shares -c --cpus + --cpuset-cpus --cpuset-mems - --cpu-shares -c --device --device-cgroup-rule --device-read-bps @@ -2148,8 +2083,8 @@ _podman_container_run() { --dns-search --entrypoint --env -e - --env-host --env-file + --env-host --expose --gidmap --group-add @@ -2165,15 +2100,15 @@ _podman_container_run() { --ip --ipc --kernel-memory - --label-file --label -l + --label-file --log-driver --log-opt --mac-address --memory -m + --memory-reservation --memory-swap --memory-swappiness - --memory-reservation --name --network --no-healthcheck @@ -2190,8 +2125,8 @@ _podman_container_run() { --publish -p --pull --restart - --runtime --rootfs + --runtime --security-opt --shm-size --stop-signal @@ -2202,21 +2137,20 @@ _podman_container_run() { --systemd --tmpfs --tz - --umask --uidmap --ulimit + --umask --user -u --userns --uts - --volumes-from --volume -v + --volumes-from --workdir -w " local boolean_options=" --disable-content-trust=false - --help - -h + --help -h --init --interactive -i --oom-kill-disable @@ -2234,8 +2168,8 @@ _podman_container_run() { --health-cmd --health-interval --health-retries - --health-timeout --health-start-period + --health-timeout " boolean_options="$boolean_options --detach -d @@ -2437,12 +2371,9 @@ _podman_restart() { --time -t " local boolean_options=" - --all - -a - --help - -h - --latest - -l + --all -a + --help -h + --latest -l --running " case "$cur" in @@ -2457,20 +2388,13 @@ _podman_restart() { _podman_rm() { local boolean_options=" - --all - -a + --all -a --cidfile - --force - -f - --help - -h - --ignore - -i - --latest - -l - --storage - --volumes - -v + --force -f + --help -h + --ignore -i + --latest -l + --volumes -v " local options_with_args=" @@ -2490,12 +2414,9 @@ _podman_rm() { _podman_rmi() { local boolean_options=" - --all - -a - --force - -f - --help - -h + --all -a + --force -f + --help -h " case "$cur" in @@ -2510,13 +2431,11 @@ _podman_rmi() { _podman_stats() { local boolean_options=" - --all - -a - --help - -h - --no-stream + --all -a --format + --help -h --no-reset + --no-stream " case "$cur" in @@ -2619,10 +2538,8 @@ _podman_save() { " local boolean_options=" --compress - --help - -h - -q - --quiet + --help -h + --quiet -q " case "$cur" in @@ -2659,12 +2576,9 @@ _podman_port() { local options_with_args=" " local boolean_options=" - --all - -a - --help - -h - -l - --latest + --all -a + --help -h + --latest -l " case "$cur" in -*) @@ -2690,14 +2604,14 @@ _podman_ps() { " local boolean_options=" --all -a + --external --help -h --latest -l + --namespace --ns --no-trunc --pod -p --quiet -q --size -s - --storage - --namespace --ns --sync " _complete_ "$options_with_args" "$boolean_options" @@ -2730,14 +2644,10 @@ _podman_start() { " local boolean_options=" - --attach - -a - -h - --help - -i - --interactive - --latest - -l + --attach -a + --help -h + --interactive -i + --latest -l --sig-proxy " case "$cur" in @@ -2754,15 +2664,11 @@ _podman_stop() { --time -t " local boolean_options=" - --all - -a + --all -a --cidfile - -h - --help - --ignore - -i - --latest - -l + --help -h + --ignore -i + --latest -l " case "$cur" in -*) @@ -2807,12 +2713,9 @@ _podman_varlink() { _podman_wait() { local options_with_args="" local boolean_options=" - --help - -h - -i - -l - --interval - --latest + --help -h + --interval -i + --latest -l " case "$cur" in -*) @@ -2846,19 +2749,16 @@ _podman_load() { --input -i " local boolean_options=" - --help - -h - --quiet - -q + --help -h + --quiet -q " _complete_ "$options_with_args" "$boolean_options" } _podman_cp() { local boolean_options=" - --help - -h --extract + --help -h --pause " _complete_ "$boolean_options" @@ -2866,12 +2766,10 @@ _podman_cp() { _podman_login() { local options_with_args=" - --username - -u - --password - -p --authfile --get-login + --password -p + --username -u " local boolean_options=" --help @@ -2979,12 +2877,10 @@ _podman_play_kube() { " local boolean_options=" - -h - --help - --quiet - -q - --tls-verify + --help -h + --quiet -q --seccomp-profile-root + --tls-verify " case "$cur" in @@ -2999,10 +2895,9 @@ _podman_play_kube() { _podman_events() { local options_with_args=" - --help - --h --filter --format + --help -h --since --until " @@ -3023,10 +2918,8 @@ _podman_container_runlabel() { local boolean_options=" --display - --help - -h - -q - --quiet + --help -h + --quiet -q --replace --tls-verify " @@ -3044,8 +2937,7 @@ _podman_container_runlabel() { _podman_image_sign() { local options_with_args=" --cert-dir - -d - --directory + --directory -d --sign-by " local boolean_options=" @@ -3065,9 +2957,8 @@ _podman_image_sign() { _podman_image_trust_set() { echo hello local options_with_args=" - -f - --type - --pubkeysfile + --pubkeysfile -f + --type -t " local boolean_options=" --help @@ -3087,10 +2978,8 @@ _podman_image_trust_show() { local options_with_args=" " local boolean_options=" - --help - -h - -j - --json + --help -h + --json -j --raw " case "$cur" in @@ -3133,10 +3022,8 @@ _podman_images_prune() { " local boolean_options=" - -a - --all - -h - --help + --all -a + --help -h " case "$cur" in -*) @@ -3151,10 +3038,8 @@ _podman_container_prune() { " local boolean_options=" - -f - --force - -h - --help + --force -f + --help -h " case "$cur" in -*) @@ -3168,7 +3053,10 @@ _podman_container_exists() { " local boolean_options=" - " + --external + --help -h + " + case "$cur" in -*) COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur")) @@ -3221,8 +3109,7 @@ _podman_pod_create() { " local boolean_options=" - --help - -h + --help -h --infra --replace " @@ -3234,14 +3121,10 @@ _podman_pod_kill() { " local boolean_options=" - --all - -a - --help - -h - --signal - -s - --latest - -l + --all -a + --help -h + --latest -l + --signal -s " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3256,8 +3139,7 @@ _podman_pod_kill() { __podman_pod_ps() { local options_with_args=" - -f - --filter + --filter -f --format --sort " @@ -3267,14 +3149,11 @@ __podman_pod_ps() { --ctr-ids --ctr-names --ctr-status - --help - -h - -q - --quiet - --no-trunc + --help -h --labels - -l - --latest + --latest -l + --no-trunc + --quiet -q " _complete_ "$options_with_args" "$boolean_options" } @@ -3312,12 +3191,9 @@ _podman_pod_restart() { " local boolean_options=" - --all - -a - --help - -h - --latest - -l + --all -a + --help -h + --latest -l " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3336,16 +3212,11 @@ _podman_pod_rm() { " local boolean_options=" - -a - --all - --help - -h - --ignore - -i - -f - --force - --latest - -l + --all -a + --force -f + --help -h + --ignore -i + --latest -l " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3364,12 +3235,9 @@ _podman_pod_start() { " local boolean_options=" - --all - -a - --help - -h - --latest - -l + --all -a + --help -h + --latest -l " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3384,21 +3252,16 @@ _podman_pod_start() { _podman_pod_stop() { local options_with_args=" - -t - --time --pod-id-file + --time -t " local boolean_options=" - --all - -a + --all -a --cleanup - --help - --ignore - -i - -h - --latest - -l + --help -h + --ignore -i + --latest -l " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3416,12 +3279,9 @@ _podman_pod_pause() { " local boolean_options=" - --all - -a - --help - -h - --latest - -l + --all -a + --help -h + --latest -l " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3439,12 +3299,9 @@ _podman_pod_unpause() { " local boolean_options=" - --all - -a - --help - -h - --latest - -l + --all -a + --help -h + --latest -l " _complete_ "$options_with_args" "$boolean_options" case "$cur" in @@ -3459,10 +3316,8 @@ _podman_pod_unpause() { _podman_pod_inspect() { local options_with_args=" - --format - -f - --latest - -l + --format -f + --latest -l " _complete_ "$options_with_args" @@ -3476,6 +3331,7 @@ _podman_pod() { " subcommands=" create + inspect kill pause ps @@ -3486,7 +3342,6 @@ _podman_pod() { stop top unpause - inspect " local aliases=" list @@ -3507,10 +3362,8 @@ _podman_pod() { _podman_volume_create() { local options_with_args=" --driver - --label - -l - --opt - -o + --label -l + --opt -o " local boolean_options=" @@ -3524,15 +3377,12 @@ _podman_volume_create() { _podman_volume_ls() { local options_with_args=" --filter - --format - -f + --format -f " local boolean_options=" - --help - -h - --quiet - -q + --help -h + --quiet -q " _complete_ "$options_with_args" "$boolean_options" @@ -3545,10 +3395,8 @@ _podman_volume_inspect() { " local boolean_options=" - --all - -a - --help - -h + --all -a + --help -h " _complete_ "$options_with_args" "$boolean_options" @@ -3566,12 +3414,9 @@ _podman_volume_rm() { local options_with_args="" local boolean_options=" - --all - -a - --force - -f - --help - -h + --all -a + --force -f + --help -h " _complete_ "$options_with_args" "$boolean_options" @@ -3589,10 +3434,8 @@ _podman_volume_prune() { local options_with_args="" local boolean_options=" - --force - -f - --help - -h + --force -f + --help -h " _complete_ "$options_with_args" "$boolean_options" @@ -3600,15 +3443,14 @@ _podman_volume_prune() { _podman_volume() { local boolean_options=" - --help - -h + --help -h " subcommands=" create inspect ls - rm prune + rm " local aliases=" list @@ -3639,19 +3481,17 @@ _podman_podman() { --network-cmd-path --root --runroot + --runtime --storage-driver --storage-opt --tmpdir - --runtime --url " local boolean_options=" - --help + --help -h + --remote -r --syslog - --version - -h - -r, --remote - -v + --version -v " commands=" attach @@ -3682,12 +3522,12 @@ _podman_podman() { mount network pause + play pod port ps pull push - play restart rm rmi diff --git a/docs/source/markdown/podman-container-exists.1.md b/docs/source/markdown/podman-container-exists.1.md index 3cc13e73a..d81a38515 100644 --- a/docs/source/markdown/podman-container-exists.1.md +++ b/docs/source/markdown/podman-container-exists.1.md @@ -4,7 +4,7 @@ podman-container-exists - Check if a container exists in local storage ## SYNOPSIS -**podman container exists** *container* +**podman container exists** [*options*] *container* ## DESCRIPTION **podman container exists** checks if a container exists in local storage. The **ID** or **Name** @@ -14,6 +14,9 @@ was an issue accessing the local storage. ## OPTIONS +**--external**=*true|false* +Check for external containers as well as Podman containers. These external containers are generally created via other container technology such as Buildah or CRI-O. + **-h**, **--help** Print usage statement @@ -24,7 +27,6 @@ Check if an container called `webclient` exists in local storage (the container $ podman container exists webclient $ echo $? 0 -$ ``` Check if an container called `webbackend` exists in local storage (the container does not actually exist). @@ -32,7 +34,13 @@ Check if an container called `webbackend` exists in local storage (the container $ podman container exists webbackend $ echo $? 1 -$ +``` + +Check if an container called `ubi8-working-container` created via Buildah exists in local storage (the container does not actually exist). +``` +$ podman container exists --external ubi8-working-container +$ echo $? +1 ``` ## SEE ALSO diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md index 58d3358e5..90f147222 100644 --- a/docs/source/markdown/podman-ps.1.md +++ b/docs/source/markdown/podman-ps.1.md @@ -34,23 +34,33 @@ all the containers information. By default it lists: Show all the containers created by Podman, default is only running containers. -Note: Podman shares containers storage with other tools such as Buildah and CRI-O. In some cases these `external` containers might also exist in the same storage. Use the `--storage` option to see these external containers. External containers show the 'storage' status. +Note: Podman shares containers storage with other tools such as Buildah and CRI-O. In some cases these `external` containers might also exist in the same storage. Use the `--external` option to see these external containers. External containers show the 'storage' status. -**--pod**, **-p** - -Display the pods the containers are associated with - -**--storage** +**--external** Display external containers that are not controlled by Podman but are stored in containers storage. These external containers are generally created via other container technology such as Buildah or CRI-O and may depend on the same container images that Podman is also using. External containers are denoted with either a 'buildah' or 'storage' in the COMMAND and STATUS column of the ps output. Only used with the --all option. -**--no-trunc** +**--filter**, **-f** -Display the extended information +Filter what containers are shown in the output. +Multiple filters can be given with multiple uses of the --filter flag. +If multiple filters are given, only containers which match all of the given filters will be shown. +Results will be drawn from all containers, regardless of whether --all was given. -**--quiet**, **-q** +Valid filters are listed below: -Print the numeric IDs of the containers only +| **Filter** | **Description** | +| --------------- | -------------------------------------------------------------------------------- | +| id | [ID] Container's ID | +| name | [Name] Container's name | +| label | [Key] or [Key=Value] Label assigned to a container | +| exited | [Int] Container's exit code | +| status | [Status] Container's status: 'created', 'exited', 'paused', 'running', 'unknown' | +| ancestor | [ImageName] Image or descendant used to create container | +| before | [ID] or [Name] Containers created before this container | +| since | [ID] or [Name] Containers created since this container | +| volume | [VolumeName] or [MountpointDestination] Volume mounted in container | +| health | [Status] healthy or unhealthy | **--format**=*format* @@ -74,15 +84,9 @@ Valid placeholders for the Go template are listed below: | .Labels | All the labels assigned to the container | | .Mounts | Volumes mounted in the container | -**--sort** - -Sort by command, created, id, image, names, runningfor, size, or status", -Note: Choosing size will sort by size of rootFs, not alphabetically like the rest of the options -Default: created - -**--size**, **-s** +**--help**, **-h** -Display the total file size +Print usage statement **--last**, **-n** @@ -98,31 +102,27 @@ The latest option is not supported on the remote client. Display namespace information -**--filter**, **-f** +**--no-trunc** -Filter what containers are shown in the output. -Multiple filters can be given with multiple uses of the --filter flag. -If multiple filters are given, only containers which match all of the given filters will be shown. -Results will be drawn from all containers, regardless of whether --all was given. +Display the extended information -Valid filters are listed below: +**--pod**, **-p** -| **Filter** | **Description** | -| --------------- | -------------------------------------------------------------------------------- | -| id | [ID] Container's ID | -| name | [Name] Container's name | -| label | [Key] or [Key=Value] Label assigned to a container | -| exited | [Int] Container's exit code | -| status | [Status] Container's status: 'created', 'exited', 'paused', 'running', 'unknown' | -| ancestor | [ImageName] Image or descendant used to create container | -| before | [ID] or [Name] Containers created before this container | -| since | [ID] or [Name] Containers created since this container | -| volume | [VolumeName] or [MountpointDestination] Volume mounted in container | -| health | [Status] healthy or unhealthy | +Display the pods the containers are associated with -**--help**, **-h** +**--quiet**, **-q** -Print usage statement +Print the numeric IDs of the containers only + +**--sort** + +Sort by command, created, id, image, names, runningfor, size, or status", +Note: Choosing size will sort by size of rootFs, not alphabetically like the rest of the options +Default: created + +**--size**, **-s** + +Display the total file size **--sync** @@ -181,7 +181,7 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS ``` ``` -$ podman ps --storage -a +$ podman ps --external -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 69ed779d8ef9f redis:alpine "redis-server" 25 hours ago Created 6379/tcp k8s_container1_podsandbox1_redhat.test.crio_redhat-test-crio_1 38a8a78596f9 docker.io/library/busybox:latest buildah 2 hours ago storage busybox-working-container diff --git a/libpod/diff.go b/libpod/diff.go index 5335d701c..43f4d2e96 100644 --- a/libpod/diff.go +++ b/libpod/diff.go @@ -62,18 +62,22 @@ func (r *Runtime) ApplyDiffTarStream(to string, diff io.Reader) error { func (r *Runtime) getLayerID(id string) (string, error) { var toLayer string toImage, err := r.imageRuntime.NewFromLocal(id) + if err == nil { + return toImage.TopLayer(), nil + } + + targetID, err := r.store.Lookup(id) if err != nil { - toCtr, err := r.store.Container(id) + targetID = id + } + toCtr, err := r.store.Container(targetID) + if err != nil { + toLayer, err = layers.FullID(r.store, targetID) if err != nil { - toLayer, err = layers.FullID(r.store, id) - if err != nil { - return "", errors.Errorf("layer, image, or container %s does not exist", id) - } - } else { - toLayer = toCtr.LayerID + return "", errors.Errorf("layer, image, or container %s does not exist", id) } } else { - toLayer = toImage.TopLayer() + toLayer = toCtr.LayerID } return toLayer, nil } diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go index 03eebeefc..61fdd42d3 100644 --- a/libpod/runtime_cstorage.go +++ b/libpod/runtime_cstorage.go @@ -52,6 +52,10 @@ func (r *Runtime) ListStorageContainers() ([]*StorageContainer, error) { return finalCtrs, nil } +func (r *Runtime) StorageContainer(idOrName string) (*storage.Container, error) { + return r.store.Container(idOrName) +} + // RemoveStorageContainer removes a container from c/storage. // The container WILL NOT be removed if it exists in libpod. // Accepts ID or full name of container. diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 7dde51102..7e6481321 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -11,6 +11,7 @@ import ( "github.com/containers/podman/v2/pkg/api/handlers/compat" "github.com/containers/podman/v2/pkg/api/handlers/utils" "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" "github.com/containers/podman/v2/pkg/ps" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -18,9 +19,30 @@ import ( ) func ContainerExists(w http.ResponseWriter, r *http.Request) { + decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) + // Now use the ABI implementation to prevent us from having duplicate + // code. + containerEngine := abi.ContainerEngine{Libpod: runtime} + name := utils.GetName(r) - _, err := runtime.LookupContainer(name) + query := struct { + External bool `schema:"external"` + }{ + // override any golang type defaults + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + return + } + + options := entities.ContainerExistsOptions{ + External: query.External, + } + + report, err := containerEngine.ContainerExists(r.Context(), name, options) if err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { utils.ContainerNotFound(w, name, err) @@ -30,7 +52,11 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) { return } - utils.WriteResponse(w, http.StatusNoContent, "") + if report.Value { + utils.WriteResponse(w, http.StatusNoContent, "") + } else { + utils.ContainerNotFound(w, name, define.ErrNoSuchCtr) + } } func ListContainers(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go index 708ad06cb..b5cd2128b 100644 --- a/pkg/bindings/containers/containers.go +++ b/pkg/bindings/containers/containers.go @@ -322,12 +322,14 @@ func Wait(ctx context.Context, nameOrID string, condition *define.ContainerStatu // Exists is a quick, light-weight way to determine if a given container // exists in local storage. The nameOrID can be a container name // or a partial/full ID. -func Exists(ctx context.Context, nameOrID string) (bool, error) { +func Exists(ctx context.Context, nameOrID string, external bool) (bool, error) { conn, err := bindings.GetClient(ctx) if err != nil { return false, err } - response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/exists", nil, nil, nameOrID) + params := url.Values{} + params.Set("external", strconv.FormatBool(external)) + response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/exists", params, nil, nameOrID) if err != nil { return false, err } diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go index 408b4769d..0fb677768 100644 --- a/pkg/bindings/test/containers_test.go +++ b/pkg/bindings/test/containers_test.go @@ -405,7 +405,7 @@ var _ = Describe("Podman containers ", func() { It("podman bogus container does not exist in local storage", func() { // Bogus container existence check should fail - containerExists, err := containers.Exists(bt.conn, "foobar") + containerExists, err := containers.Exists(bt.conn, "foobar", false) Expect(err).To(BeNil()) Expect(containerExists).To(BeFalse()) }) @@ -415,7 +415,7 @@ var _ = Describe("Podman containers ", func() { var name = "top" _, err := bt.RunTopContainer(&name, bindings.PFalse, nil) Expect(err).To(BeNil()) - containerExists, err := containers.Exists(bt.conn, name) + containerExists, err := containers.Exists(bt.conn, name, false) Expect(err).To(BeNil()) Expect(containerExists).To(BeTrue()) }) @@ -425,7 +425,7 @@ var _ = Describe("Podman containers ", func() { var name = "top" cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil) Expect(err).To(BeNil()) - containerExists, err := containers.Exists(bt.conn, cid) + containerExists, err := containers.Exists(bt.conn, cid, false) Expect(err).To(BeNil()) Expect(containerExists).To(BeTrue()) }) @@ -435,7 +435,7 @@ var _ = Describe("Podman containers ", func() { var name = "top" cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil) Expect(err).To(BeNil()) - containerExists, err := containers.Exists(bt.conn, cid[0:12]) + containerExists, err := containers.Exists(bt.conn, cid[0:12], false) Expect(err).To(BeNil()) Expect(containerExists).To(BeTrue()) }) @@ -455,7 +455,7 @@ var _ = Describe("Podman containers ", func() { Expect(err).To(BeNil()) err = containers.Kill(bt.conn, name, "SIGINT") Expect(err).To(BeNil()) - _, err = containers.Exists(bt.conn, name) + _, err = containers.Exists(bt.conn, name, false) Expect(err).To(BeNil()) }) @@ -466,7 +466,7 @@ var _ = Describe("Podman containers ", func() { Expect(err).To(BeNil()) err = containers.Kill(bt.conn, cid, "SIGTERM") Expect(err).To(BeNil()) - _, err = containers.Exists(bt.conn, cid) + _, err = containers.Exists(bt.conn, cid, false) Expect(err).To(BeNil()) }) diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 3b6dd106f..46b169284 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -246,6 +246,11 @@ type ExecOptions struct { WorkDir string } +// ContainerExistsOptions describes the cli values to check if a container exists +type ContainerExistsOptions struct { + External bool +} + // ContainerStartOptions describes the val from the // CLI needed to start a container type ContainerStartOptions struct { diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 803a59932..a20d3b404 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -21,7 +21,7 @@ type ContainerEngine interface { ContainerDiff(ctx context.Context, nameOrID string, options DiffOptions) (*DiffReport, error) ContainerExec(ctx context.Context, nameOrID string, options ExecOptions, streams define.AttachStreams) (int, error) ContainerExecDetached(ctx context.Context, nameOrID string, options ExecOptions) (string, error) - ContainerExists(ctx context.Context, nameOrID string) (*BoolReport, error) + ContainerExists(ctx context.Context, nameOrID string, options ContainerExistsOptions) (*BoolReport, error) ContainerExport(ctx context.Context, nameOrID string, options ContainerExportOptions) error ContainerInit(ctx context.Context, namesOrIds []string, options ContainerInitOptions) ([]*ContainerInitReport, error) ContainerInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]*ContainerInspectReport, []error, error) diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 614fd5fe0..60dbbce6c 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -74,11 +74,19 @@ func getContainersByContext(all, latest bool, names []string, runtime *libpod.Ru return } -// TODO: Should return *entities.ContainerExistsReport, error -func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) { +// ContainerExists returns whether the container exists in container storage +func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string, options entities.ContainerExistsOptions) (*entities.BoolReport, error) { _, err := ic.Libpod.LookupContainer(nameOrID) - if err != nil && errors.Cause(err) != define.ErrNoSuchCtr { - return nil, err + if err != nil { + if errors.Cause(err) != define.ErrNoSuchCtr { + return nil, err + } + if options.External { + // Check if container exists in storage + if _, storageErr := ic.Libpod.StorageContainer(nameOrID); storageErr == nil { + err = nil + } + } } return &entities.BoolReport{Value: err == nil}, nil } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index eb591d23d..7913d79cd 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -29,8 +29,8 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string, return errors.New("not implemented") } -func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) { - exists, err := containers.Exists(ic.ClientCxt, nameOrID) +func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string, options entities.ContainerExistsOptions) (*entities.BoolReport, error) { + exists, err := containers.Exists(ic.ClientCxt, nameOrID, options.External) return &entities.BoolReport{Value: exists}, err } diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 28dc7c7a7..f7c48da8d 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -460,4 +460,24 @@ json-file | f is "$output" "$expect" "podman run with --tz=local, matches host" } +@test "podman container exists" { + rand=$(random_string 30) + run_podman 1 container exists myctr + + run_podman create --name myctr $IMAGE /bin/true + run_podman container exists myctr + + # Create a container that podman does not know about + run buildah from $IMAGE + cid="$output" + + # exists should fail + run_podman 1 container exists $cid + + # exists should succeed + run_podman container exists --external $cid + + run buildah rm $cid +} + # vim: filetype=sh diff --git a/test/system/140-diff.bats b/test/system/140-diff.bats index 01ec5430e..d0f33e438 100644 --- a/test/system/140-diff.bats +++ b/test/system/140-diff.bats @@ -32,4 +32,26 @@ load helpers run_podman rm $n } +@test "podman diff with buildah container " { + rand_file=$(random_string 10) + run buildah from --name buildahctr $IMAGE + run buildah run buildahctr sh -c "touch /$rand_file;rm /etc/services" + + run_podman diff --format json buildahctr + + # Expected results for each type of diff + declare -A expect=( + [added]="/$rand_file" + [changed]="/etc" + [deleted]="/etc/services" + ) + + for field in ${!expect[@]}; do + result=$(jq -r -c ".${field}[]" <<<"$output") + is "$result" "${expect[$field]}" "$field" + done + + run buildah rm buildahctr +} + # vim: filetype=sh |