diff options
-rw-r--r-- | OWNERS | 2 | ||||
-rw-r--r-- | cmd/podman/containers/cp.go | 8 | ||||
-rw-r--r-- | cmd/podman/validate/args.go | 7 | ||||
-rw-r--r-- | docs/MANPAGE_SYNTAX.md | 20 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-prune.1.md | 3 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-restore.1.md | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-save.1.md | 5 | ||||
-rw-r--r-- | libpod/container_internal.go | 2 | ||||
-rw-r--r-- | pkg/specgen/generate/container.go | 13 | ||||
-rw-r--r-- | test/e2e/config/containers-journald.conf | 4 | ||||
-rw-r--r-- | test/e2e/containers_conf_test.go | 30 | ||||
-rw-r--r-- | test/system/065-cp.bats | 9 |
12 files changed, 83 insertions, 22 deletions
@@ -5,6 +5,7 @@ approvers: - jwhonce - Luap99 - mheon + - mtrmac - rhatdan - saschagrunert - TomSweeneyRedHat @@ -19,6 +20,7 @@ reviewers: - jwhonce - Luap99 - mheon + - mtrmac - QiWang19 - rhatdan - saschagrunert diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index 2c7d72b20..0ad258824 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -177,6 +177,10 @@ func copyFromContainer(container string, containerPath string, hostPath string) containerTarget = filepath.Dir(containerTarget) } + if !isStdout && containerInfo.IsDir && !hostInfo.IsDir { + return errors.New("destination must be a directory when copying a directory") + } + reader, writer := io.Pipe() hostCopy := func() error { defer reader.Close() @@ -334,6 +338,10 @@ func copyToContainer(container string, containerPath string, hostPath string) er stdinFile = tmpFile.Name() } + if hostInfo.IsDir && !containerInfo.IsDir { + return errors.New("destination must be a directory when copying a directory") + } + reader, writer := io.Pipe() hostCopy := func() error { defer writer.Close() diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go index c00813369..fc07a6acc 100644 --- a/cmd/podman/validate/args.go +++ b/cmd/podman/validate/args.go @@ -3,6 +3,7 @@ package validate import ( "fmt" "strconv" + "strings" "github.com/containers/podman/v3/cmd/podman/registry" "github.com/pkg/errors" @@ -20,7 +21,11 @@ func NoArgs(cmd *cobra.Command, args []string) error { // SubCommandExists returns an error if no sub command is provided 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]) + suggestions := cmd.SuggestionsFor(args[0]) + if len(suggestions) == 0 { + return errors.Errorf("unrecognized command `%[1]s %[2]s`\nTry '%[1]s --help' for more information.", cmd.CommandPath(), args[0]) + } + return errors.Errorf("unrecognized command `%[1]s %[2]s`\n\nDid you mean this?\n\t%[3]s\n\nTry '%[1]s --help' for more information.", cmd.CommandPath(), args[0], strings.Join(suggestions, "\n\t")) } return errors.Errorf("missing command '%[1]s COMMAND'\nTry '%[1]s --help' for more information.", cmd.CommandPath()) } diff --git a/docs/MANPAGE_SYNTAX.md b/docs/MANPAGE_SYNTAX.md index 553f5d977..7fff167ba 100644 --- a/docs/MANPAGE_SYNTAX.md +++ b/docs/MANPAGE_SYNTAX.md @@ -5,7 +5,7 @@ podman\-command - short description ## SYNOPSIS (Shows the command structure. If the command can be written in two different ways, both of them have to be shown.\ -Many manpages include the OPTIONS **--all**, **-a** and/or **--latest**, **-l**. In this case there is no `container name` or `ID` needed after the initial command. Because most of the other OPTIONS still need the `container name` or ` ID`, it is defined that the *container* argument in the command should **not** be put in brackets. It should also be noted in the *IMPORTANT* section in the description of the OPTION with the following sentence: *IMPORTANT: This OPTION does not need a container name or ID as input argument.*.) +Many manpages include the OPTIONS **--all**, **-a** and/or **--latest**, **-l**. In this case, there is no `container name` or `ID` needed after the initial command. Because most of the other OPTIONS still need the `container name` or ` ID`, it is defined that the *container* argument in the command should **not** be put in brackets. It should also be noted in the *IMPORTANT* section in the description of the OPTION with the following sentence: *IMPORTANT: This OPTION does not need a container name or ID as input argument.*.) **podman command** [*optional*] *mandatory value* @@ -36,7 +36,9 @@ Example for the first sentence: **podman command** is an example command. Commands or files that are quoted from other podman manpages or podman repositories have to be linked to those. Non-podman commands are not to be linked.\ Example sentence: Use **[podman-run](podman-run.1.md)** or **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for the problem. -It should also be specified if the command can only be run as root. In addition, it should be described when a command, OPTION, or other content cannot be executed with the remote client or in combination with other commands, OPTIONS, or content. In this case, the following sentence is put at the end of a command, OPTION, or content: *IMPORTANT: This OPTION/command/other is not available with the command/OPTION/content/remote Podman client*. For a command, this should be done in the DESCRIPTION section. For the OPTIONS, it should be done in the DESCRIPTION of the specified OPTION. +It should also be specified if the command can only be run as root. In addition, it should be described when a command, OPTION, or other content cannot be executed with the remote client or in combination with other commands, OPTIONS, or content. In this case, the following sentence is put at the end of a command, OPTION, or content:\ +*IMPORTANT: This command/OPTION/content is not available with the command/OPTION/content/on the remote Podman client.*\ +For a command, this should be done in the DESCRIPTION section. For the OPTIONS, it should be done in the DESCRIPTION of the specified OPTION. Do not use pronouns in the man pages, especially the word `you`. @@ -48,11 +50,11 @@ All flags are referred to as OPTIONS. The term flags should not be used. All OPT OPTIONS that are quoted from other podman manpages or podman repositories have to be linked to those.\ Example sentence: Use **[podman-generate-systemd --new](./source/markdown/podman-generate-systemd.1.md#--new)** for the problem. - Each OPTION should be explained to the fullest extent below the OPTION itself. Each OPTION is behind an H4-header (`####`). If the OPTION has a default argument, it has to be explained in the description of the OPTION. If the OPTION is also not available with a command/OPTION/content/remote Podman client, the sentence about the default argument should the second to last sentence. The sentence about the default argument should be in a new line as well as the *IMPORTANT* sentence. + Each OPTION should be explained to the fullest extent below the OPTION itself. Each OPTION is behind an H4-header (`####`). If the OPTION has a default argument, it has to be explained in the description of the OPTION. If the OPTION is also not available with a command/OPTION/content/ on the remote Podman client, the sentence about the default argument should the second to last sentence. The sentence about the default argument should be in a new line as well as the *IMPORTANT* sentence. All OPTIONS are to be sorted in alphabetical order. - Tables should be used when there is a different definition for different arguments and these have to be explained. This is shown with the OPTION **--test**.\ + Tables should be used when there is a different definition for multiple arguments, and these have to be explained. This is shown with the OPTION **--test**.\ Lists should be used when arguments are used that do not need a definition for each argument and a single description explains them. An example is shown with **[podman-commit --change](./source/markdown/podman-commit.1.md#--change--cinstruction)** @@ -68,17 +70,17 @@ An example of an OPTION that has only one possible structure. Thus, it cannot be #### **--answer**=, **-a**=**active** | *disable* -The **--answer** OPTION above is an example of an OPTION that accepts two possible arguments as inputs. If there is a default argument that is selected when the OPTION is not used in the command, it is shown in **bold**. If the OPTION is used it must include an argument afterwards. It must always be ensured that the standard argument is in the first position after the OPTION. In this example, there are two different ways to execute the command. Both possible OPTIONS have to be shown with the arguments following them.\ +The **--answer** OPTION above is an example of an OPTION that accepts two possible arguments as inputs. If a default argument is selected when the OPTION is not used in the command, it is shown in **bold**. If the OPTION is used, it must include an argument afterward. It must always be ensured that the standard argument is in the first position after the OPTION. In this example, there are two different ways to execute the command. Both possible OPTIONS have to be shown with the arguments following them.\ The default value is shown as **active**. #### **--status**=**good** | *better* | *best* -This is an example of three arguments following an OPTION. If the number of arguments is greater than three, the arguments are **not** listed after the equal sign. The arguments have to be shown in a table like in **--test**=**_test_**. This form should also be used if the understanding of the content is in danger of becoming incomprehensible. An example for this is **[podman-container-prune --filters](./source/markdown/podman-container-prune.1.md#--filterfilters)**.\ +This is an example of three arguments following an OPTION. If the number of arguments is greater than three, the arguments are **not** listed after the equal sign. The arguments must be shown in a table like in **--test**=**_test_**. This form should also be used if the understanding of the content is in danger of becoming incomprehensible. An example for this is **[podman-container-prune --filters](./source/markdown/podman-container-prune.1.md#--filterfilters)**.\ The default value is shown as **good**. #### **--test**=**test** -OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold** or *italic*. If there is a default argument, that is used if the OPTION is not specified in the command, the argument after the equal sign is displayed in **bold**. All arguments must be listed and explained in the text below the OPTION. +OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold** or *italic*. If there is a default argument that is used if the OPTION is not specified in the command, the argument after the equal sign is displayed in **bold**. All arguments must be listed and explained in the text below the OPTION. | Argument | Description | | ------------------ | --------------------------------------------------------------------------- | @@ -88,7 +90,7 @@ OPTIONS that are followed by an equal sign include an argument after the equal s | *example four* | Example: Can be combined with **--exit**. | | *example five* | The fifth description | -The table shows an example for a listing of arguments. The contents in the table should be aligned left. If the content in the table conflicts with this, it can be aligned in a way that supports the understanding of the content. If there is a default argument, it **must** listed as the first entry in the table.\ +The table shows an example for a listing of arguments. The contents in the table should be aligned left. If the content in the table conflicts with this, it can be aligned to support the understanding of the content. If there is a default argument, it **must** be listed as the first entry in the table.\ The default value is shown as **example one**. If the number of arguments is smaller than four they have to be listed behind the OPTION as seen in the OPTION **--status**. @@ -137,4 +139,4 @@ Normally, the dates of changes, the content of the changes and the person who pr Example:\ December 2021, Originally compiled by Alexander Richter <example@redhat.com> -`A new line is needed of the end of every manpage.` +`Every manpage should end with an empty line.` diff --git a/docs/source/markdown/podman-container-prune.1.md b/docs/source/markdown/podman-container-prune.1.md index 06014897f..0f679ceff 100644 --- a/docs/source/markdown/podman-container-prune.1.md +++ b/docs/source/markdown/podman-container-prune.1.md @@ -21,7 +21,7 @@ Supported filters: | Filter | Description | | :----------------: | --------------------------------------------------------------------------- | | *until* | Only remove containers and images created before given timestamp. | -| *label* | Only remove containers and images, with (or without, in case label!=[...] is used) the specified labels. | +| *label* | Only remove containers and images, with (or without, in the case of label!=[...] is used) the specified labels. | The `until` *filter* can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the machine’s time. @@ -60,7 +60,6 @@ ed0c6468b8e1cb641b4621d1fe30cb477e1fefc5c0bceb66feaf2f7cb50e5962 6ac6c8f0067b7a4682e6b8e18902665b57d1a0e07e885d9abcd382232a543ccd fff1c5b6c3631746055ec40598ce8ecaa4b82aef122f9e3a85b03b55c0d06c23 602d343cd47e7cb3dfc808282a9900a3e4555747787ec6723bb68cedab8384d5 - ``` Remove all stopped containers from local storage created within last 10 minutes diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md index 21021b952..36eb650e5 100644 --- a/docs/source/markdown/podman-container-restore.1.md +++ b/docs/source/markdown/podman-container-restore.1.md @@ -31,7 +31,7 @@ The default is **false**. #### **--latest**, **-l** -Instead of providing the *container ID* or *name*, use the last created *container*. If other methods than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods.\ +Instead of providing the *container ID* or *name*, use the last created *container*. If other tools than Podman are used to run *containers* such as `CRI-O`, the last started *container* could be from either tool.\ The default is **false**.\ *IMPORTANT: This OPTION is not available with the remote Podman client. This OPTION does not need a container name or ID as input argument.* diff --git a/docs/source/markdown/podman-save.1.md b/docs/source/markdown/podman-save.1.md index ab21d2bc6..1f1f60b22 100644 --- a/docs/source/markdown/podman-save.1.md +++ b/docs/source/markdown/podman-save.1.md @@ -35,8 +35,9 @@ Write to a file, default is STDOUT #### **--format**=*format* -Save image to **oci-archive, oci-dir** (directory with oci manifest type), or **docker-dir** (directory with v2s2 manifest type) +Save image to **docker-archive**, **oci-archive** (see `containers-transports(5)`), **oci-dir** (`oci` transport), or **docker-dir** (`dir` transport with v2s2 manifest type). ``` +--format docker-archive --format oci-archive --format oci-dir --format docker-dir @@ -100,7 +101,7 @@ Storing signatures ``` ## SEE ALSO -podman(1), podman-load(1), containers.conf(5) +podman(1), podman-load(1), containers.conf(5), containers-transports(5) ## HISTORY July 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com> diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 545b78976..2555f15ec 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1535,7 +1535,7 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { // If /etc/mtab does not exist in container image, then we need to // create it, so that mount command within the container will work. mtab := filepath.Join(mountPoint, "/etc/mtab") - if err := os.MkdirAll(filepath.Dir(mtab), 0755); err != nil { + if err := idtools.MkdirAllAs(filepath.Dir(mtab), 0755, c.RootUID(), c.RootGID()); err != nil { return "", errors.Wrap(err, "error creating mtab directory") } if err = os.Symlink("/proc/mounts", mtab); err != nil && !os.IsExist(err) { diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index e7276892d..ca92f558d 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -7,12 +7,14 @@ import ( "github.com/containers/common/libimage" "github.com/containers/podman/v3/libpod" + "github.com/containers/podman/v3/libpod/define" ann "github.com/containers/podman/v3/pkg/annotations" envLib "github.com/containers/podman/v3/pkg/env" "github.com/containers/podman/v3/pkg/signal" "github.com/containers/podman/v3/pkg/specgen" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -204,6 +206,17 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat if len(s.LogConfiguration.Driver) < 1 { s.LogConfiguration.Driver = rtc.Containers.LogDriver } + if len(rtc.Containers.LogTag) > 0 { + if s.LogConfiguration.Driver != define.JSONLogging { + if s.LogConfiguration.Options == nil { + s.LogConfiguration.Options = make(map[string]string) + } + + s.LogConfiguration.Options["tag"] = rtc.Containers.LogTag + } else { + logrus.Warnf("log_tag %q is not allowed with %q log_driver", rtc.Containers.LogTag, define.JSONLogging) + } + } warnings, err := verifyContainerResources(s) if err != nil { diff --git a/test/e2e/config/containers-journald.conf b/test/e2e/config/containers-journald.conf new file mode 100644 index 000000000..463f9a9fa --- /dev/null +++ b/test/e2e/config/containers-journald.conf @@ -0,0 +1,4 @@ +[containers] + +log_driver="journald" +log_tag="{{.ImageName}}" diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index a354de3b2..054454798 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -167,16 +167,34 @@ var _ = Describe("Podman run", func() { verifyNSHandling("/proc/self/ns/cgroup", "--cgroupns") }) + It("using journald for container with container log_tag", func() { + SkipIfInContainer("journalctl inside a container doesn't work correctly") + os.Setenv("CONTAINERS_CONF", "config/containers-journald.conf") + if IsRemote() { + podmanTest.RestartRemoteService() + } + logc := podmanTest.Podman([]string{"run", "-d", ALPINE, "sh", "-c", "echo podman; sleep 0.1; echo podman; sleep 0.1; echo podman"}) + logc.WaitWithDefaultTimeout() + Expect(logc.ExitCode()).To(Equal(0)) + cid := logc.OutputToString() + + wait := podmanTest.Podman([]string{"wait", cid}) + wait.WaitWithDefaultTimeout() + Expect(wait.ExitCode()).To(Equal(0)) + + cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_TAG", fmt.Sprintf("CONTAINER_ID_FULL=%s", cid)) + out, err := cmd.CombinedOutput() + Expect(err).To(BeNil()) + Expect(string(out)).To(ContainSubstring("alpine")) + }) + It("podman containers.conf additionalvolumes", func() { conffile := filepath.Join(podmanTest.TempDir, "container.conf") tempdir, err = CreateTempDirInTempDir() - if err != nil { - os.Exit(1) - } + Expect(err).To(BeNil()) + err := ioutil.WriteFile(conffile, []byte(fmt.Sprintf("[containers]\nvolumes=[\"%s:%s:Z\",]\n", tempdir, tempdir)), 0755) - if err != nil { - os.Exit(1) - } + Expect(err).To(BeNil()) os.Setenv("CONTAINERS_CONF", conffile) if IsRemote() { diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats index 24ac8118e..eda04611f 100644 --- a/test/system/065-cp.bats +++ b/test/system/065-cp.bats @@ -272,6 +272,11 @@ load helpers run_podman rm -f cpcontainer done < <(parse_table "$tests") + run_podman create --name cpcontainer --workdir=/srv $cpimage sleep infinity + run_podman 125 cp $srcdir cpcontainer:/etc/os-release + is "$output" "Error: destination must be a directory when copying a directory" "cannot copy directory to file" + run_podman rm -f cpcontainer + run_podman rmi -f $cpimage } @@ -343,6 +348,10 @@ load helpers is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description" rm -rf $destdir/* done < <(parse_table "$tests") + + touch $destdir/testfile + run_podman 125 cp cpcontainer:/etc/ $destdir/testfile + is "$output" "Error: destination must be a directory when copying a directory" "cannot copy directory to file" run_podman rm -f cpcontainer run_podman rmi -f $cpimage |