diff options
26 files changed, 348 insertions, 76 deletions
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 64271031d..ebb6ed98f 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -109,6 +109,7 @@ func jsonOut(responses []entities.ListContainer) error { r := make([]entities.ListContainer, 0) for _, con := range responses { con.CreatedAt = units.HumanDuration(time.Since(time.Unix(con.Created, 0))) + " ago" + con.Status = psReporter{con}.Status() r = append(r, con) } b, err := json.MarshalIndent(r, "", " ") diff --git a/commands-demo.md b/commands-demo.md index 555f83af9..74879842f 100644 --- a/commands-demo.md +++ b/commands-demo.md @@ -27,11 +27,11 @@ | [podman-generate-systemd(1)](https://podman.readthedocs.io/en/latest/markdown/podman-generate-systemd.1.html) | Generate systemd unit file(s) for a container or pod. Not supported for the remote client | | [podman-history(1)](https://podman.readthedocs.io/en/latest/markdown/podman-history.1.html) | Shows the history of an image | | [podman-image(1)](https://podman.readthedocs.io/en/latest/image.html) | Manage Images | -| [podman-image-exists(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-exists.1.html) | Check if an image exists in local storage | | [podman-image-diff(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-diff.html) | Inspect changes on an image's filesystem. | +| [podman-image-exists(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-exists.1.html) | Check if an image exists in local storage | | [podman-image-prune(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-prune.1.html) | Remove all unused images from the local store | -| [podman-image-sign(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-sign.1.html) | Create a signature for an image | | [podman-image-search(1)](https://podman.readthedocs.io/en/latest/markdown/podman-search.1.html) | Search a registry for an image. | +| [podman-image-sign(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-sign.1.html) | Create a signature for an image | | [podman-image-tree(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-tree.1.html) | Prints layer hierarchy of an image in a tree format | | [podman-image-trust(1)](https://podman.readthedocs.io/en/latest/markdown/podman-image-trust.1.html) | Manage container registry image trust policy | | [podman-images(1)](https://podman.readthedocs.io/en/latest/markdown/podman-images.1.html) | List images in local storage | [![...](/docs/source/markdown/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh) | @@ -58,9 +58,9 @@ | [podman-pod-exists(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-exists.1.html) | Check if a pod exists in local storage | | [podman-pod-inspect(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-inspect.1.html) | Displays information describing a pod | | [podman-pod-kill(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-kill.1.html) | Kill the main process of each container in one or more pods | -| [podman-pod-ps(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-ps.1.html) | Prints out information about pods | | [podman-pod-pause(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pause.1.html) | Pause one or more containers | | [podman-pod-prune(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-prune.1.html) | Remove all stopped pods and their containers | +| [podman-pod-ps(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-ps.1.html) | Prints out information about pods | | [podman-pod-restart](https://podman.readthedocs.io/en/latest/markdown/podman-pod-restart.1.html) | Restart one or more pods | | [podman-pod-rm(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-rm.1.html) | Remove one or more stopped pods and containers | | [podman-pod-start(1)](https://podman.readthedocs.io/en/latest/markdown/podman-pod-start.1.html) | Start one or more pods | diff --git a/docs/source/Commands.rst b/docs/source/Commands.rst index aba29bd82..096bdbedf 100644 --- a/docs/source/Commands.rst +++ b/docs/source/Commands.rst @@ -6,11 +6,13 @@ Commands :doc:`attach <markdown/podman-attach.1>` Attach to a running container +:doc:`auto-update <markdown/podman-auto-update.1>` Auto update containers according to their auto-update policy + :doc:`build <markdown/podman-build.1>` Build an image using instructions from Containerfiles :doc:`commit <markdown/podman-commit.1>` Create new image based on the changed container -:doc:`containers <managecontainers>` Manage Containers +:doc:`container <managecontainers>` Manage Containers :doc:`cp <markdown/podman-cp.1>` Copy files/folders between a container and the local filesystem @@ -52,6 +54,8 @@ Commands :doc:`logs <markdown/podman-logs.1>` Fetch the logs of a container +:doc:`manifest <manifest>` Create and manipulate manifest lists and image indexes + :doc:`mount <markdown/podman-mount.1>` Mount a working container's root filesystem :doc:`network <network>` Manage Networks @@ -94,12 +98,14 @@ Commands :doc:`top <markdown/podman-top.1>` Display the running processes of a container -:doc:`umount <markdown/podman-umount.1>` Unmounts working container's root filesystem +:doc:`unmount <markdown/podman-unmount.1>` Unmounts working container's root filesystem :doc:`unpause <markdown/podman-unpause.1>` Unpause the processes in one or more containers :doc:`unshare <markdown/podman-unshare.1>` Run a command in a modified user namespace +:doc:`untag <markdown/podman-untag.1>` Removes one or more names from a locally-stored image + :doc:`version <markdown/podman-version.1>` Display the Podman Version Information :doc:`volume <volume>` Manage volumes diff --git a/docs/source/connection.rst b/docs/source/connection.rst new file mode 100644 index 000000000..64eb18c57 --- /dev/null +++ b/docs/source/connection.rst @@ -0,0 +1,12 @@ +Manage the destination(s) for Podman service(s) +================= + +:doc:`add <markdown/podman-system-connection-add.1>` Record destination for the Podman service + +:doc:`default <markdown/podman-system-connection-default.1>` Set named destination as default for the Podman service + +:doc:`list <markdown/podman-system-connection-list.1>` List the destination for the Podman service(s) + +:doc:`remove <markdown/podman-system-connection-remove.1>` Delete named destination + +:doc:`rename <markdown/podman-system-connection-rename.1>` Rename the destination for Podman service diff --git a/docs/source/image.rst b/docs/source/image.rst index a8c6171e1..2b0ef3d43 100644 --- a/docs/source/image.rst +++ b/docs/source/image.rst @@ -4,6 +4,8 @@ Image :doc:`build <markdown/podman-build.1>` Build an image using instructions from Containerfiles +:doc:`diff <markdown/podman-image-diff.1>` Inspect changes on an image's filesystem + :doc:`exists <markdown/podman-image-exists.1>` Check if an image exists in local storage :doc:`history <markdown/podman-history.1>` Show history of a specified image @@ -16,6 +18,8 @@ Image :doc:`load <markdown/podman-load.1>` Load an image from container archive +:doc:`mount <markdown/podman-image-mount.1>` Mount an image's root filesystem. + :doc:`prune <markdown/podman-image-prune.1>` Remove unused images :doc:`pull <markdown/podman-pull.1>` Pull an image from a registry @@ -26,6 +30,8 @@ Image :doc:`save <markdown/podman-save.1>` Save image to an archive +:doc:`search <markdown/podman-search.1>` Search a registry for an image + :doc:`sign <markdown/podman-image-sign.1>` Sign an image :doc:`tag <markdown/podman-tag.1>` Add an additional name to a local image @@ -33,3 +39,7 @@ Image :doc:`tree <markdown/podman-image-tree.1>` Prints layer hierarchy of an image in a tree format :doc:`trust <markdown/podman-image-trust.1>` Manage container image trust policy + +:doc:`unmount <markdown/podman-unmount.1>` Unmount an image's root filesystem + +:doc:`untag <markdown/podman-untag.1>` Removes one or more names from a locally-stored image diff --git a/docs/source/index.rst b/docs/source/index.rst index 715ca2744..9a1381080 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -15,6 +15,7 @@ If you are completely new to containers, we recommend that you check out the :do :caption: Contents: Introduction + :doc:`<markdown/podman.1>` Simple management tool for pods, containers and images Commands Reference Tutorials diff --git a/docs/source/managecontainers.rst b/docs/source/managecontainers.rst index 5c5a83a82..849fd1d25 100644 --- a/docs/source/managecontainers.rst +++ b/docs/source/managecontainers.rst @@ -37,10 +37,10 @@ Manage Containers :doc:`port <markdown/podman-port.1>` List port mappings or a specific mapping for the container -:doc:`restart <markdown/podman-restart.1>` Restart one or more containers - :doc:`prune <markdown/podman-container-prune.1>` Remove all stopped containers +:doc:`restart <markdown/podman-restart.1>` Restart one or more containers + :doc:`restore <markdown/podman-container-restore.1>` Restores one or more containers from a checkpoint :doc:`rm <markdown/podman-rm.1>` Remove one or more containers @@ -57,7 +57,7 @@ Manage Containers :doc:`top <markdown/podman-top.1>` Display the running processes of a container -:doc:`umount <markdown/podman-umount.1>` Unmounts working container's root filesystem +:doc:`unmount <markdown/podman-unmount.1>` Unmounts working container's root filesystem :doc:`unpause <markdown/podman-unpause.1>` Unpause the processes in one or more containers diff --git a/docs/source/manifest.rst b/docs/source/manifest.rst new file mode 100644 index 000000000..c63c28502 --- /dev/null +++ b/docs/source/manifest.rst @@ -0,0 +1,14 @@ +Create and manipulate manifest lists and image indexes +================= + +:doc:`add <markdown/podman-manifest-add.1>` Add an image to a manifest list or image index + +:doc:`annotate <markdown/podman-manifest-annotate.1>` Add or update information about an entry in a manifest list or image index + +:doc:`create <markdown/podman-manifest-create.1>` Create a manifest list or image index + +:doc:`inspect <markdown/podman-manifest-inspect.1>` Display a manifest list or image index + +:doc:`push <markdown/podman-manifest-push.1>` Push a manifest list or image index to a registry + +:doc:`remove <markdown/podman-manifest-remove.1>` Remove an image from a manifest list or image index diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 5c58d59fc..f65c52e29 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -801,8 +801,8 @@ Run container in systemd mode. The default is *true*. The value *always* enforces the systemd mode is enforced without looking at the executable name. Otherwise, if set to true and the -command you are running inside the container is systemd, /usr/sbin/init -or /sbin/init. +command you are running inside the container is systemd, /usr/sbin/init, +/sbin/init or /usr/local/sbin/init. If the command you are running inside of the container is systemd, Podman will setup tmpfs mount points in the following directories: diff --git a/docs/source/markdown/podman-image.1.md b/docs/source/markdown/podman-image.1.md index 55e95d032..bbf5f6d84 100644 --- a/docs/source/markdown/podman-image.1.md +++ b/docs/source/markdown/podman-image.1.md @@ -20,8 +20,8 @@ The image command allows you to manage images | import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | | inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a image or image's configuration. | | list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) | -| mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. | | load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. | +| mount | [podman-image-mount(1)](podman-image-mount.1.md) | Mount an image's root filesystem. | | prune | [podman-image-prune(1)](podman-image-prune.1.md) | Remove all unused images from the local store. | | pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | | push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. | @@ -30,10 +30,10 @@ The image command allows you to manage images | search | [podman-search(1)](podman-search.1.md) | Search a registry for an image. | | sign | [podman-image-sign(1)](podman-image-sign.1.md) | Create a signature for an image. | | tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | -| untag | [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. | -| unmount | [podman-image-unmount(1)](podman-image-unmount.1.md) | Unmount an image's root filesystem. | | tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. | | trust | [podman-image-trust(1)](podman-image-trust.1.md) | Manage container registry image trust policy. | +| unmount | [podman-image-unmount(1)](podman-image-unmount.1.md) | Unmount an image's root filesystem. | +| untag | [podman-untag(1)](podman-untag.1.md) | Removes one or more names from a locally-stored image. | ## SEE ALSO podman diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index db742e429..976cdd88b 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -831,8 +831,8 @@ Run container in systemd mode. The default is **true**. The value *always* enforces the systemd mode is enforced without looking at the executable name. Otherwise, if set to **true** and the -command you are running inside the container is systemd, _/usr/sbin/init_ -or _/sbin/init_. +command you are running inside the container is systemd, _/usr/sbin/init_, +_/sbin/init_ or _/usr/local/sbin/init_. If the command you are running inside of the container is systemd Podman will setup tmpfs mount points in the following directories: diff --git a/docs/source/markdown/podman-system-connection.1.md b/docs/source/markdown/podman-system-connection.1.md index 86199c6b9..0673aaee1 100644 --- a/docs/source/markdown/podman-system-connection.1.md +++ b/docs/source/markdown/podman-system-connection.1.md @@ -13,13 +13,13 @@ The user will be prompted for the ssh login password or key file pass phrase as ## COMMANDS -| Command | Man Page | Description | -| ------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------- | -| add | [podman-system-connection-add(1)](podman-system-connection-add.1.md) | Record destination for the Podman service | -| default | [podman-system-connection-default(1)](podman-system-connection-default.1.md) | Set named destination as default for the Podman service | -| list | [podman-system-connection-list(1)](podman-system-connection-list.1.md) | List the destination for the Podman service(s) | -| remove | [podman-system-connection-remove(1)](podman-system-connection-remove.1.md) | Delete named destination | -| rename | [podman-system-connection-rename(1)](podman-system-connection-rename.1.md) | Rename the destination for Podman service | +| Command | Man Page | Description | +| -------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------- | +| add | [podman-system-connection\-add(1)](podman-system-connection-add.1.md) | Record destination for the Podman service | +| default | [podman-system-connection\-default(1)](podman-system-connection-default.1.md) | Set named destination as default for the Podman service | +| list | [podman-system-connection\-list(1)](podman-system-connection-list.1.md) | List the destination for the Podman service(s) | +| remove | [podman-system-connection\-remove(1)](podman-system-connection-remove.1.md) | Delete named destination | +| rename | [podman-system-connection\-rename(1)](podman-system-connection-rename.1.md) | Rename the destination for Podman service | ## EXAMPLE ``` diff --git a/docs/source/system.rst b/docs/source/system.rst index 2d93a1d6d..566fd1a95 100644 --- a/docs/source/system.rst +++ b/docs/source/system.rst @@ -1,6 +1,8 @@ System ====== +:doc:`connection <connection>` Manage the destination(s) for Podman service(s) + :doc:`df <markdown/podman-system-df.1>` Show podman disk usage :doc:`info <markdown/podman-info.1>` Display podman system information @@ -12,3 +14,5 @@ System :doc:`renumber <markdown/podman-system-renumber.1>` Migrate lock numbers :doc:`reset <markdown/podman-system-reset.1>` Reset podman storage + +:doc:`service <markdown/podman-system-service.1>` Run an API service diff --git a/hack/xref-helpmsgs-manpages b/hack/xref-helpmsgs-manpages index 16b596589..7b617eed7 100755 --- a/hack/xref-helpmsgs-manpages +++ b/hack/xref-helpmsgs-manpages @@ -26,8 +26,14 @@ $| = 1; my $Default_Podman = './bin/podman'; my $PODMAN = $ENV{PODMAN} || $Default_Podman; +# Path to all doc files, including .rst and (down one level) markdown +my $Docs_Path = 'docs/source'; + # Path to podman markdown source files (of the form podman-*.1.md) -my $Markdown_Path = 'docs/source/markdown'; +my $Markdown_Path = "$Docs_Path/markdown"; + +# Global error count +my $Errs = 0; # END user-customizable section ############################################################################### @@ -96,35 +102,38 @@ sub main { my $help = podman_help(); my $man = podman_man('podman'); + my $rst = podman_rst(); + + xref_by_help($help, $man); + xref_by_man($help, $man); - my $retval = xref_by_help($help, $man) - + xref_by_man($help, $man); + xref_rst($help, $rst); - exit !!$retval; + exit !!$Errs; } +############################################################################### +# BEGIN cross-referencing + ################## # xref_by_help # Find keys in '--help' but not in man ################## sub xref_by_help { my ($help, $man, @subcommand) = @_; - my $errs = 0; for my $k (sort keys %$help) { if (exists $man->{$k}) { if (ref $help->{$k}) { - $errs += xref_by_help($help->{$k}, $man->{$k}, @subcommand, $k); + xref_by_help($help->{$k}, $man->{$k}, @subcommand, $k); } # Otherwise, non-ref is leaf node such as a --option } else { my $man = $man->{_path} || 'man'; warn "$ME: podman @subcommand --help lists $k, but $k not in $man\n"; - ++$errs; + ++$Errs; } } - - return $errs; } ################# @@ -137,13 +146,11 @@ sub xref_by_help { sub xref_by_man { my ($help, $man, @subcommand) = @_; - my $errs = 0; - # FIXME: this generates way too much output for my $k (grep { $_ ne '_path' } sort keys %$man) { if (exists $help->{$k}) { if (ref $man->{$k}) { - $errs += xref_by_man($help->{$k}, $man->{$k}, @subcommand, $k); + xref_by_man($help->{$k}, $man->{$k}, @subcommand, $k); } } elsif ($k ne '--help' && $k ne '-h') { @@ -175,13 +182,38 @@ sub xref_by_man { next if "@subcommand" eq 'system' && $k eq 'service'; warn "$ME: podman @subcommand: $k in $man, but not --help\n"; - ++$errs; + ++$Errs; } } +} - return $errs; +############## +# xref_rst # Cross-check *.rst files against help +############## +sub xref_rst { + my ($help, $rst, @subcommand) = @_; + + # Cross-check against rst (but only subcommands, not options). + # We key on $help because that is Absolute Truth: anything in podman --help + # must be referenced in an rst (the converse is not true). + for my $k (sort grep { $_ !~ /^-/ } keys %$help) { + # Check for subcommands, if any (eg podman system -> connection -> add) + if (ref $help->{$k}) { + xref_rst($help->{$k}, $rst->{$k}, @subcommand, $k); + } + + # Check that command is mentioned in at least one .rst file + if (! exists $rst->{$k}{_desc}) { + my @podman = ("podman", @subcommand, $k); + warn "$ME: no link in *.rst for @podman\n"; + ++$Errs; + } + } } +# END cross-referencing +############################################################################### +# BEGIN data gathering ################# # podman_help # Parse output of 'podman [subcommand] --help' @@ -249,6 +281,7 @@ sub podman_man { or die "$ME: Cannot read $manpath: $!\n"; my $section = ''; my @most_recent_flags; + my $previous_subcmd = ''; while (my $line = <$fh>) { chomp $line; next unless $line; # skip empty lines @@ -278,6 +311,11 @@ sub podman_man { elsif ($line =~ /^\|\s+(\S+)\s+\|\s+\[\S+\]\((\S+)\.1\.md\)/) { # $1 will be changed by recursion _*BEFORE*_ left-hand assignment my $subcmd = $1; + if ($previous_subcmd gt $subcmd) { + warn "$ME: $subpath: '$previous_subcmd' and '$subcmd' are out of order\n"; + ++$Errs; + } + $previous_subcmd = $subcmd; $man{$subcmd} = podman_man($2); } } @@ -315,4 +353,76 @@ sub podman_man { } +################ +# podman_rst # Parse contents of docs/source/*.rst +################ +sub podman_rst { + my %rst; + + # Read all .rst files, looking for ":doc:`subcmd <target>` description" + for my $rst (glob "$Docs_Path/*.rst") { + open my $fh, '<', $rst + or die "$ME: Cannot read $rst: $!\n"; + + # The basename of foo.rst is usually, but not always, the name of + # a podman subcommand. There are a few special cases: + (my $command = $rst) =~ s!^.*/(.*)\.rst!$1!; + + my $subcommand_href = \%rst; + if ($command eq 'Commands') { + ; + } + elsif ($command eq 'managecontainers') { + $subcommand_href = $rst{container} //= { }; + } + elsif ($command eq 'connection') { + $subcommand_href = $rst{system}{connection} //= { }; + } + else { + $subcommand_href = $rst{$command} //= { }; + } + + my $previous_subcommand = ''; + while (my $line = <$fh>) { + if ($line =~ /^:doc:`(\S+)\s+<(.*?)>`\s+(.*)/) { + my ($subcommand, $target, $desc) = ($1, $2, $3); + + # Check that entries are in alphabetical order + if ($subcommand lt $previous_subcommand) { + warn "$ME: $rst:$.: '$previous_subcommand' and '$subcommand' are out of order\n"; + ++$Errs; + } + $previous_subcommand = $subcommand; + + # Mark this subcommand as documented. + $subcommand_href->{$subcommand}{_desc} = $desc; + + # Check for invalid links. These will be one of two forms: + # <markdown/foo.1> -> markdown/foo.1.md + # <foo> -> foo.rst + if ($target =~ m!^markdown/!) { + if (! -e "$Docs_Path/$target.md") { + warn "$ME: $rst:$.: '$subcommand' links to nonexistent $target\n"; + ++$Errs; + } + } + else { + if (! -e "$Docs_Path/$target.rst") { + warn "$ME: $rst:$.: '$subcommand' links to nonexistent $target.rst\n"; + } + } + } + } + close $fh; + } + + # Special case: 'image trust set/show' are documented in image-trust.1 + $rst{image}{trust}{$_} = { _desc => 'ok' } for (qw(set show)); + + return \%rst; +} + +# END data gathering +############################################################################### + 1; diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 9fb9738dc..e2bc4e50f 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -626,7 +626,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro Destination: "/sys/fs/cgroup/systemd", Type: "bind", Source: "/sys/fs/cgroup/systemd", - Options: []string{"bind", "nodev", "noexec", "nosuid"}, + Options: []string{"bind", "nodev", "noexec", "nosuid", "rslave"}, } g.AddMount(systemdMnt) g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent") diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go index 50dd4933b..ed40a37ab 100644 --- a/pkg/domain/entities/container_ps.go +++ b/pkg/domain/entities/container_ps.go @@ -56,6 +56,8 @@ type ListContainer struct { StartedAt int64 // State of container State string + // Status is a human-readable approximation of a duration for json output + Status string } // ListContainer Namespaces contains the identifiers of the container's Linux namespaces diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 35675e1f3..70d740bb5 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -226,7 +226,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti if err != nil { imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, rawImage)) if err != nil { - return nil, errors.Errorf("invalid image reference %q", rawImage) + return nil, errors.Wrapf(err, "invalid image reference %q", rawImage) } } diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 1a1bb4526..8289e2089 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -142,11 +142,6 @@ func (s *SpecGenerator) Validate() error { return err } - // The following are defaults as needed by container creation - if len(s.WorkDir) < 1 { - s.WorkDir = "/" - } - // Set defaults if network info is not provided if s.NetNS.NSMode == "" { s.NetNS.NSMode = Bridge diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 65f8197bc..53d160442 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -135,15 +135,18 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat s.Annotations = annotations // workdir - if newImage != nil { - workingDir, err := newImage.WorkingDir(ctx) - if err != nil { - return nil, err - } - if len(s.WorkDir) < 1 && len(workingDir) > 1 { + if s.WorkDir == "" { + if newImage != nil { + workingDir, err := newImage.WorkingDir(ctx) + if err != nil { + return nil, err + } s.WorkDir = workingDir } } + if s.WorkDir == "" { + s.WorkDir = "/" + } if len(s.SeccompProfilePath) < 1 { p, err := libpod.DefaultSeccompPath() diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index b61ac2c30..fda4c098c 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -164,13 +164,19 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. } if len(command) > 0 { - if command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd") { + useSystemdCommands := map[string]bool{ + "/sbin/init": true, + "/usr/sbin/init": true, + "/usr/local/sbin/init": true, + } + if useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd") { useSystemd = true } } default: return nil, errors.Wrapf(err, "invalid value %q systemd option requires 'true, false, always'", s.Systemd) } + logrus.Debugf("using systemd mode: %t", useSystemd) if useSystemd { // is StopSignal was not set by the user then set it to systemd // expected StopSigal @@ -241,13 +247,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. // If the user did not set an workdir but the image did, ensure it is // created. if s.WorkDir == "" && img != nil { - newWD, err := img.WorkingDir(ctx) - if err != nil { - return nil, err - } - if newWD != "" { - options = append(options, libpod.WithCreateWorkingDir()) - } + options = append(options, libpod.WithCreateWorkingDir()) } if s.StopSignal != nil { options = append(options, libpod.WithStopSignal(*s.StopSignal)) diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go index 4352ef718..5e4cc3399 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -158,8 +158,9 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, configSpec.Linux.Seccomp = seccompConfig } - // Clear default Seccomp profile from Generator for privileged containers - if s.SeccompProfilePath == "unconfined" || s.Privileged { + // Clear default Seccomp profile from Generator for unconfined containers + // and privileged containers which do not specify a seccomp profile. + if s.SeccompProfilePath == "unconfined" || (s.Privileged && (s.SeccompProfilePath == config.SeccompOverridePath || s.SeccompProfilePath == config.SeccompDefaultPath)) { configSpec.Linux.Seccomp = nil } diff --git a/pkg/varlinkapi/create.go b/pkg/varlinkapi/create.go index 2d3e20f67..e9309a2d4 100644 --- a/pkg/varlinkapi/create.go +++ b/pkg/varlinkapi/create.go @@ -704,7 +704,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. if err != nil { return nil, errors.Wrapf(err, "cannot parse bool %s", c.String("systemd")) } - if x && (command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd")) { + useSystemdCommands := map[string]bool{ + "/sbin/init": true, + "/usr/sbin/init": true, + "/usr/local/sbin/init": true, + } + if x && (useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd")) { systemd = true } } diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go index f10ef5c99..a734d399d 100644 --- a/test/e2e/ps_test.go +++ b/test/e2e/ps_test.go @@ -188,6 +188,21 @@ var _ = Describe("Podman ps", func() { Expect(result.IsJSONOutputValid()).To(BeTrue()) }) + It("podman ps print a human-readable `Status` with json format", func() { + _, ec, _ := podmanTest.RunLsContainer("test1") + Expect(ec).To(Equal(0)) + + result := podmanTest.Podman([]string{"ps", "-a", "--format", "json"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(result.IsJSONOutputValid()).To(BeTrue()) + // must contain "Status" + match, StatusLine := result.GrepString(`Status`) + Expect(match).To(BeTrue()) + // container is running or exit, so it must contain `ago` + Expect(StatusLine[0]).To(ContainSubstring("ago")) + }) + It("podman ps namespace flag with go template format", func() { Skip(v2fail) _, ec, _ := podmanTest.RunLsContainer("test1") diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index dc44d3b3f..30e565894 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -193,22 +193,46 @@ var _ = Describe("Podman run", func() { Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("FALSE")) }) - It("podman run seccomp test", func() { - + forbidGetCWDSeccompProfile := func() string { in := []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`) jsonFile, err := podmanTest.CreateSeccompJson(in) if err != nil { fmt.Println(err) Skip("Failed to prepare seccomp.json for test.") } + return jsonFile + } + + It("podman run seccomp test", func() { + session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"}) + session.WaitWithDefaultTimeout() + Expect(session).To(ExitWithError()) + match, _ := session.GrepString("Operation not permitted") + Expect(match).Should(BeTrue()) + }) - session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", jsonFile}, ""), ALPINE, "pwd"}) + It("podman run seccomp test --privileged", func() { + session := podmanTest.Podman([]string{"run", "-it", "--privileged", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"}) session.WaitWithDefaultTimeout() Expect(session).To(ExitWithError()) match, _ := session.GrepString("Operation not permitted") Expect(match).Should(BeTrue()) }) + It("podman run seccomp test --privileged no profile should be unconfined", func() { + session := podmanTest.Podman([]string{"run", "-it", "--privileged", ALPINE, "grep", "Seccomp", "/proc/self/status"}) + session.WaitWithDefaultTimeout() + Expect(session.OutputToString()).To(ContainSubstring("0")) + Expect(session.ExitCode()).To(Equal(0)) + }) + + It("podman run seccomp test no profile should be default", func() { + session := podmanTest.Podman([]string{"run", "-it", ALPINE, "grep", "Seccomp", "/proc/self/status"}) + session.WaitWithDefaultTimeout() + Expect(session.OutputToString()).To(ContainSubstring("2")) + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman run capabilities test", func() { session := podmanTest.Podman([]string{"run", "--rm", "--cap-add", "all", ALPINE, "cat", "/proc/self/status"}) session.WaitWithDefaultTimeout() diff --git a/test/e2e/run_working_dir.go b/test/e2e/run_working_dir.go new file mode 100644 index 000000000..93330deba --- /dev/null +++ b/test/e2e/run_working_dir.go @@ -0,0 +1,69 @@ +package integration + +import ( + "os" + "strings" + + . "github.com/containers/podman/v2/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman run", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() + podmanTest.SeedImages() + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + processTestResult(f) + + }) + + It("podman run a container without workdir", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "pwd"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal("/")) + }) + + It("podman run a container using non existing --workdir", func() { + if !strings.Contains(podmanTest.OCIRuntime, "crun") { + Skip("Test only works on crun") + } + session := podmanTest.Podman([]string{"run", "--workdir", "/home/foobar", ALPINE, "pwd"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(127)) + }) + + It("podman run a container on an image with a workdir", func() { + SkipIfRemote() + dockerfile := `FROM alpine +RUN mkdir -p /home/foobar +WORKDIR /etc/foobar` + podmanTest.BuildImage(dockerfile, "test", "false") + + session := podmanTest.Podman([]string{"run", "test", "pwd"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal("/etc/foobar")) + + session = podmanTest.Podman([]string{"run", "--workdir", "/home/foobar", "test", "pwd"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal("/home/foobar")) + }) +}) diff --git a/transfer.md b/transfer.md index 9aa271c37..49ff687e6 100644 --- a/transfer.md +++ b/transfer.md @@ -38,10 +38,10 @@ There are other equivalents for these tools | Existing Step | `Podman` (and friends) | | :--- | :--- | | `docker attach` | [`podman attach`](./docs/source/markdown/podman-attach.1.md) | -| `docker cp` | [`podman cp`](./docs/source/markdown/podman-cp.1.md) | | `docker build` | [`podman build`](./docs/source/markdown/podman-build.1.md) | | `docker commit` | [`podman commit`](./docs/source/markdown/podman-commit.1.md) | | `docker container`|[`podman container`](./docs/source/markdown/podman-container.1.md) | +| `docker cp` | [`podman cp`](./docs/source/markdown/podman-cp.1.md) | | `docker create` | [`podman create`](./docs/source/markdown/podman-create.1.md) | | `docker diff` | [`podman diff`](./docs/source/markdown/podman-diff.1.md) | | `docker events` | [`podman events`](./docs/source/markdown/podman-events.1.md) | @@ -59,10 +59,10 @@ There are other equivalents for these tools | `docker network ls` | [`podman network ls`](./docs/source/markdown/podman-network-ls.1.md) | | `docker network rm` | [`podman network rm`](./docs.source/markdown/podman-network-rm.1.md) | | `docker pause` | [`podman pause`](./docs/source/markdown/podman-pause.1.md) | +| `docker port` | [`podman port`](./docs/source/markdown/podman-port.1.md) | | `docker ps` | [`podman ps`](./docs/source/markdown/podman-ps.1.md) | | `docker pull` | [`podman pull`](./docs/source/markdown/podman-pull.1.md) | | `docker push` | [`podman push`](./docs/source/markdown/podman-push.1.md) | -| `docker port` | [`podman port`](./docs/source/markdown/podman-port.1.md) | | `docker restart` | [`podman restart`](./docs/source/markdown/podman-restart.1.md) | | `docker rm` | [`podman rm`](./docs/source/markdown/podman-rm.1.md) | | `docker rmi` | [`podman rmi`](./docs/source/markdown/podman-rmi.1.md) | @@ -71,20 +71,20 @@ There are other equivalents for these tools | `docker search` | [`podman search`](./docs/source/markdown/podman-search.1.md) | | `docker start` | [`podman start`](./docs/source/markdown/podman-start.1.md) | | `docker stop` | [`podman stop`](./docs/source/markdown/podman-stop.1.md) | +| `docker system df` | [`podman system df`](./docs/source/markdown/podman-system-df.1.md) | +| `docker system info` | [`podman system info`](./docs/source/markdown/podman-system-info.1.md) | +| `docker system prune` | [`podman system prune`](./docs/source/markdown/podman-system-prune.1.md) | +| `docker system` | [`podman system`](./docs/source/markdown/podman-system.1.md) | | `docker tag` | [`podman tag`](./docs/source/markdown/podman-tag.1.md) | | `docker top` | [`podman top`](./docs/source/markdown/podman-top.1.md) | | `docker unpause` | [`podman unpause`](./docs/source/markdown/podman-unpause.1.md) | | `docker version` | [`podman version`](./docs/source/markdown/podman-version.1.md) | -| `docker volume` | [`podman volume`](./docs/source/markdown/podman-volume.1.md) | | `docker volume create` | [`podman volume create`](./docs/source/markdown/podman-volume-create.1.md) | | `docker volume inspect`| [`podman volume inspect`](./docs/source/markdown/podman-volume-inspect.1.md)| | `docker volume ls` | [`podman volume ls`](./docs/source/markdown/podman-volume-ls.1.md) | | `docker volume prune` | [`podman volume prune`](./docs/source/markdown/podman-volume-prune.1.md) | | `docker volume rm` | [`podman volume rm`](./docs/source/markdown/podman-volume-rm.1.md) | -| `docker system` | [`podman system`](./docs/source/markdown/podman-system.1.md) | -| `docker system df` | [`podman system df`](./docs/source/markdown/podman-system-df.1.md) | -| `docker system prune` | [`podman system prune`](./docs/source/markdown/podman-system-prune.1.md) | -| `docker system info` | [`podman system info`](./docs/source/markdown/podman-system-info.1.md) | +| `docker volume` | [`podman volume`](./docs/source/markdown/podman-volume.1.md) | | `docker wait` | [`podman wait`](./docs/source/markdown/podman-wait.1.md) | **** Use mount to take advantage of the entire linux tool chain rather then just cp. Read [`here`](./docs/podman-cp.1.md) for more information. @@ -95,8 +95,8 @@ Those Docker commands currently do not have equivalents in `podman`: | Missing command | Description| | :--- | :--- | -| `docker container update` | podman does not support altering running containers. We recommend recreating containers with the correct arguments.| | `docker container rename` | podman does not support `container rename` - or the `rename` shorthand. We recommend using `podman rm` and `podman create` to create a container with a specific name.| +| `docker container update` | podman does not support altering running containers. We recommend recreating containers with the correct arguments.| | `docker node` || | `docker plugin` | podman does not support plugins. We recommend you use alternative OCI Runtimes or OCI Runtime Hooks to alter behavior of podman.| | `docker secret` || @@ -108,22 +108,21 @@ Those Docker commands currently do not have equivalents in `podman`: The following podman commands do not have a Docker equivalent: -* [`podman generate`](./docs/source/markdown/podman-generate.1.md) -* [`podman generate kube`](./docs/source/markdown/podman-generate-kube.1.md) * [`podman container checkpoint`](/docs/source/markdown/podman-container-checkpoint.1.md) * [`podman container cleanup`](/docs/source/markdown/podman-container-cleanup.1.md) * [`podman container exists`](/docs/source/markdown/podman-container-exists.1.md) * [`podman container refresh`](/docs/source/markdown/podman-container-refresh.1.md) -* [`podman container runlabel`](/docs/source/markdown/podman-container-runlabel.1.md) * [`podman container restore`](/docs/source/markdown/podman-container-restore.1.md) +* [`podman container runlabel`](/docs/source/markdown/podman-container-runlabel.1.md) +* [`podman generate kube`](./docs/source/markdown/podman-generate-kube.1.md) +* [`podman generate`](./docs/source/markdown/podman-generate.1.md) * [`podman healthcheck run`](/docs/source/markdown/podman-healthcheck-run.1.md) * [`podman image exists`](./docs/source/markdown/podman-image-exists.1.md) * [`podman image sign`](./docs/source/markdown/podman-image-sign.1.md) * [`podman image trust`](./docs/source/markdown/podman-image-trust.1.md) * [`podman mount`](./docs/source/markdown/podman-mount.1.md) -* [`podman play`](./docs/source/markdown/podman-play.1.md) * [`podman play kube`](./docs/source/markdown/podman-play-kube.1.md) -* [`podman pod`](./docs/source/markdown/podman-pod.1.md) +* [`podman play`](./docs/source/markdown/podman-play.1.md) * [`podman pod create`](./docs/source/markdown/podman-pod-create.1.md) * [`podman pod exists`](./docs/source/markdown/podman-pod-exists.1.md) * [`podman pod inspect`](./docs/source/markdown/podman-pod-inspect.1.md) @@ -136,4 +135,5 @@ The following podman commands do not have a Docker equivalent: * [`podman pod stop`](./docs/source/markdown/podman-pod-stop.1.md) * [`podman pod top`](./docs/source/markdown/podman-pod-top.1.md) * [`podman pod unpause`](./docs/source/markdown/podman-pod-unpause.1.md) +* [`podman pod`](./docs/source/markdown/podman-pod.1.md) * [`podman umount`](./docs/source/markdown/podman-umount.1.md) |