diff options
34 files changed, 432 insertions, 208 deletions
@@ -93,11 +93,14 @@ LIBPOD := ${PROJECT}/v3/libpod GCFLAGS ?= all=-trimpath=$(CURDIR) ASMFLAGS ?= all=-trimpath=$(CURDIR) LDFLAGS_PODMAN ?= \ - -X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT) \ - -X $(LIBPOD)/define.buildInfo=$(BUILD_INFO) \ - -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ - -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ - $(EXTRA_LDFLAGS) + -X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT) \ + -X $(LIBPOD)/define.buildInfo=$(BUILD_INFO) \ + -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ + -X $(LIBPOD)/config._etcDir=$(ETCDIR) \ + $(EXTRA_LDFLAGS) +LDFLAGS_PODMAN_STATIC ?= \ + $(LDFLAGS_PODMAN) \ + -extldflags=-static #Update to LIBSECCOMP_COMMIT should reflect in Dockerfile too. LIBSECCOMP_COMMIT := v2.3.3 # Rarely if ever should integration tests take more than 50min, @@ -314,7 +317,7 @@ $(SRCBINDIR)/podman$(BINSFX): $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum -o $@ ./cmd/podman $(SRCBINDIR)/podman-remote-static: $(SRCBINDIR) .gopathok $(SOURCES) go.mod go.sum - CGO_ENABLED=$(CGO_ENABLED) \ + CGO_ENABLED=0 \ GOOS=$(GOOS) \ $(GO) build \ $(BUILDFLAGS) \ @@ -437,7 +440,7 @@ $(MANPAGES): %: %.md .install.md2man docdir -e 's/\[\(podman[^]]*\)\]/\1/g' \ -e 's/\[\([^]]*\)](http[^)]\+)/\1/g' \ -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \ - -e 's/\\$// /g' $< | \ + -e 's/\\$$/ /g' $< | \ $(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@) .PHONY: docdir @@ -748,11 +751,13 @@ install.systemd: install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${USERSYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/user/podman.socket ${DESTDIR}${USERSYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/user/podman.service ${DESTDIR}${USERSYSTEMDDIR}/podman.service + install ${SELINUXOPT} -m 644 contrib/systemd/user/podman-restart.service ${DESTDIR}${USERSYSTEMDDIR}/podman-restart.service # System services install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.service ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.service install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${SYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${SYSTEMDDIR}/podman.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${SYSTEMDDIR}/podman-restart.service else install.systemd: endif diff --git a/contrib/podmanimage/stable/Dockerfile b/contrib/podmanimage/stable/Dockerfile index 696268c85..2f86dd4ae 100644 --- a/contrib/podmanimage/stable/Dockerfile +++ b/contrib/podmanimage/stable/Dockerfile @@ -21,6 +21,7 @@ echo podman:10000:5000 > /etc/subgid; VOLUME /var/lib/containers VOLUME /home/podman/.local/share/containers +RUN mkdir -p /home/podman/.local/share/containers ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf diff --git a/contrib/podmanimage/testing/Dockerfile b/contrib/podmanimage/testing/Dockerfile index c20b26ac4..63b31252f 100644 --- a/contrib/podmanimage/testing/Dockerfile +++ b/contrib/podmanimage/testing/Dockerfile @@ -21,6 +21,7 @@ echo podman:10000:5000 > /etc/subgid; VOLUME /var/lib/containers VOLUME /home/podman/.local/share/containers +RUN mkdir -p /home/podman/.local/share/containers ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf diff --git a/contrib/podmanimage/upstream/Dockerfile b/contrib/podmanimage/upstream/Dockerfile index 1277f9ba8..922eee748 100644 --- a/contrib/podmanimage/upstream/Dockerfile +++ b/contrib/podmanimage/upstream/Dockerfile @@ -69,6 +69,7 @@ echo podman:10000:5000 > /etc/subgid; VOLUME /var/lib/containers VOLUME /home/podman/.local/share/containers +RUN mkdir -p /home/podman/.local/share/containers ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf ADD https://raw.githubusercontent.com/containers/libpod/master/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 6146a2c0e..ef8523f8c 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -531,10 +531,12 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath} %{_unitdir}/podman-auto-update.timer %{_unitdir}/podman.service %{_unitdir}/podman.socket +%{_unitdir}/podman-restart.service %{_usr}/lib/systemd/user/podman.service %{_usr}/lib/systemd/user/podman.socket %{_usr}/lib/systemd/user/podman-auto-update.service %{_usr}/lib/systemd/user/podman-auto-update.timer +%{_usr}/lib/systemd/user/podman-restart.service %{_usr}/lib/tmpfiles.d/podman.conf %if 0%{?with_devel} diff --git a/contrib/systemd/system/podman-restart.service b/contrib/systemd/system/podman-restart.service new file mode 100644 index 000000000..baf12b3ae --- /dev/null +++ b/contrib/systemd/system/podman-restart.service @@ -0,0 +1,12 @@ +[Unit] +Description=Podman Start All Containers With Restart Policy Set To Always +Documentation=man:podman-start(1) +StartLimitIntervalSec=0 + +[Service] +Type=oneshot +Environment=LOGGING="--log-level=info" +ExecStart=/usr/bin/podman $LOGGING start --all --filter restart-policy=always + +[Install] +WantedBy=multi-user.target diff --git a/contrib/systemd/system/podman.service b/contrib/systemd/system/podman.service index 7e5195e7a..cefb13ae3 100644 --- a/contrib/systemd/system/podman.service +++ b/contrib/systemd/system/podman.service @@ -10,3 +10,6 @@ Type=exec KillMode=process Environment=LOGGING="--log-level=info" ExecStart=/usr/bin/podman $LOGGING system service + +[Install] +WantedBy=multi-user.target diff --git a/docs/MANPAGE_SYNTAX.md b/docs/MANPAGE_SYNTAX.md index c9b677688..9794a0c3d 100644 --- a/docs/MANPAGE_SYNTAX.md +++ b/docs/MANPAGE_SYNTAX.md @@ -4,7 +4,7 @@ podman\-command - short description ## SYNOPSIS -(Shows the command structure.) +(Shows the command structure. If the command can be written in two different ways, both of them have to be shown.) **podman command** [*optional*] *mandatory value* @@ -16,7 +16,7 @@ podman\-command - short description **podman subcommand command** [*optional*] *value1* | *value2* -(If an optinal value follows a mandatory one.) +(If an optional value follows a mandatory one.) **podman command** [*optional*] *value1* | *value2* [*optional*] @@ -33,23 +33,23 @@ podman\-command - short description Example sentence: The command **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: You can 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. +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. Do not use pronouns in the man pages, especially the word `you`. +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. Do not use pronouns in the man pages, especially the word `you`. ## OPTIONS All flags are referred to as OPTIONS. The term flags should not be used. All OPTIONS are listed in this section. OPTIONS that appear in descriptions of other OPTIONS and sections retain their appearance, for example: **--exit**. OPTIONS that are quoted from other podman manpages or podman repositories have to be linked to those.\ -Example sentence: You can use **[podman-generate-systemd --new](podman-generate-systemd.1.md#--new)** for the problem. +Example sentence: Use **[podman-generate-systemd --new](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 the remote client, the sentence about the default argument should the second to last sentence. #### **--version**, **-v** -OPTIONS can be put after the command in two different ways. Eather the long version with **--option** or as the short version **-o**. If there are two ways to write an OPTION they are separated by a comma. If there are two versions of one command the long version is always shown in front.\ -Example: The default is **false**. *IMPORTANT: This option is not available with the remote Podman client*. +OPTIONS can be put after the command in two different ways. Either the long version with **--option** or as the short version **-o**. If there are two ways to write an OPTION they are separated by a comma. If there are two versions of one command the long version is always shown in front.\ +Example: The default is **false**. *IMPORTANT: This OPTION is not available with the remote Podman client*. #### **--exit** @@ -57,7 +57,7 @@ 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 default value is shown as **active**. +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 default value is shown as **active**. #### **--status**=**good** | *better* | *best* @@ -65,7 +65,7 @@ This is an example of three arguments following an OPTION. If the number of argu #### **--test**=**test** -OPTIONS that are followed by an equal sign include an argument after the equal sign in **bold**. If there is a default argument, that is used if the OPTION is not specified in the command, the argument after the eqaul 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**. 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 | | ------------------ | --------------------------------------------------------------------------- | @@ -102,6 +102,7 @@ All EXAMPLES are listed in this section. This section should be at the end of ea Description of the EXAMPLE ``` +### Example comment $ podman command $ podman command -o @@ -111,9 +112,16 @@ $ cat $HOME/Dockerfile | podman command --option Description of the EXAMPLE two ``` -$ podman command --redhat +# podman command --status=better +``` +## SEE ALSO +All commands, including commands with OPTIONS, and config-files mentioned in the manpage have to be listed here. Podman commands, including commands with OPTIONS, and config-files have to be linked. If a command is mentioned several times with different OPTIONS it just have to be linked once. All other commands, including commands with OPTIONS, and config-files just have to be mentioned. If a command is mentioned several times with different OPTIONS it just has to be linked once. -$ podman command --redhat better +Example: +**[podman(1)](podman.1.md)**, **[podman-run(1)](podman-run.1.md)**, **[podman-create(1)](podman-create.1.md)** -$ podman command --redhat=better -``` +## HISTORY +Normally, the dates of changes, the content of the changes and the person who provided them is listed here. Most manpages don't keep this record. + +Example:\ +December 2021, Originally compiled by Alexander Richter <example@redhat.com> diff --git a/docs/source/markdown/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md index 092772916..0a5948b4e 100644 --- a/docs/source/markdown/podman-attach.1.md +++ b/docs/source/markdown/podman-attach.1.md @@ -10,7 +10,7 @@ podman\-attach - Attach to a running container ## DESCRIPTION **podman attach** attaches to a running *container* using the *container's name* or *ID*, to either view its ongoing output or to control it interactively.\ -The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** option, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information. +The *container* can detached from (and leave it running) using a configurable key sequence. The default sequence is `ctrl-p,ctrl-q`. Configure the keys sequence using the **--detach-keys** OPTION, or specifying it in the `containers.conf` file: see **[containers.conf(5)](https://github.com/containers/common/blob/master/docs/containers.conf.5.md)** for more information. ## OPTIONS #### **--detach-keys**=**sequence** @@ -18,9 +18,8 @@ The *container* can detached from (and leave it running) using a configurable ke Specify the key **sequence** for detaching a *container*. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is `ctrl-p,ctrl-q`. #### **--latest**, **-l** - -Instead of providing the *container name* or *ID*, use the last created *container*. If you use methods other than Podman to run containers such as CRI-O, the last started *container* could be from either of those methods. The default is **false**.\ -*IMPORTANT: This option is not available with the remote Podman client* +Instead of providing the *container name* or *ID*, use the last created *container*. If other methods are used than Podman to run containers such as `CRI-O`, the last started *container* could be from either of those methods. The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client.* #### **--no-stdin** diff --git a/docs/source/markdown/podman-commit.1.md b/docs/source/markdown/podman-commit.1.md index 92574cdc5..bb7d3ce70 100644 --- a/docs/source/markdown/podman-commit.1.md +++ b/docs/source/markdown/podman-commit.1.md @@ -23,7 +23,17 @@ Set the author for the committed image. #### **--change**, **-c**=*instruction* Apply the following possible instructions to the created image: -**CMD** | **ENTRYPOINT** | **ENV** | **EXPOSE** | **LABEL** | **ONBUILD** | **STOPSIGNAL** | **USER** | **VOLUME** | **WORKDIR** + +- *CMD* +- *ENTRYPOINT* +- *ENV* +- *EXPOSE* +- *LABEL* +- *ONBUILD* +- *STOPSIGNAL* +- *USER* +- *VOLUME* +- *WORKDIR* Can be set multiple times. diff --git a/docs/source/markdown/podman-completion.1.md b/docs/source/markdown/podman-completion.1.md index 4ebe4e2e1..f8589ce68 100644 --- a/docs/source/markdown/podman-completion.1.md +++ b/docs/source/markdown/podman-completion.1.md @@ -4,60 +4,60 @@ podman\-completion - Generate shell completion scripts ## SYNOPSIS -**podman completion** [*options*] *bash*|*zsh*|*fish*|*powershell* +**podman completion** [*options*] *bash* | *zsh* | *fish* | *powershell* ## DESCRIPTION -The completion command generates shell completion scripts for a variety of shells. Supported shells are **bash**, **zsh**, **fish** and **powershell**. +**podman completion** generates shell completion scripts for a variety of shells. Supported shells are *bash*, *zsh*, *fish* and *powershell*. -These script are used by the shell to provide suggestions and complete commands when you are typing the command and press [TAB]. +These script are used by the shell to provide suggestions and complete commands when the command is typed and `[TAB]` is pressed. Usually these scripts are automatically installed via the package manager. ## OPTIONS -#### **--file**, **-f** +#### **--file**, **-f**=*file* -Write the generated output to file. +Write the generated output to a file. #### **--no-desc** -Do not provide description in the completions. +Do not provide description in the completions. The default is **false**. ## Installation ### BASH -Make sure you have `bash-completion` installed on the system. +`bash-completion` has to be installed on the system. -To load the completion script into the current session run: -`source <(podman completion bash)` +To load the completion script into the current session run:\ +**source <(podman completion bash)**. -To make it available for all bash sessions run: -`podman completion bash -f /etc/bash_completion.d/podman` +To make it available for all bash sessions run:\ +**podman completion -f /etc/bash_completion.d/podman bash**. ### ZSH -If shell completion is not already enabled in the environment you will need to enable it. You can execute the following once: -`echo "autoload -U compinit; compinit" >> ~/.zshrc` +Shell completion needs to be already enabled in the environment. The following can be executed:\ +**echo "autoload -U compinit; compinit" >> ~/.zshrc** -To make it available for all zsh sessions run: -`podman completion zsh -f "${fpath[1]}/_podman"` +To make it available for all zsh sessions run:\ +**podman completion -f "${fpath[1]}/_podman zsh"** -Once you reload the shell the auto-completion should be working. +Once the shell is reloaded the auto-completion should be working. ### FISH To load the completion script into the current session run: -`podman completion fish | source` +**podman completion fish | source** To make it available for all fish sessions run: -`podman completion fish -f ~/.config/fish/completions/podman.fish` +**podman completion -f ~/.config/fish/completions/podman.fish fish** ### POWERSHELL To load the completion script into the current session run: -`podman.exe completion powershell | Out-String | Invoke-Expression` +**podman.exe completion powershell | Out-String | Invoke-Expression** To make it available in all powershell sessions that a user has, write the completion output to a file and source that to the user's powershell profile. -More information about profiles is available with `Get-Help about_Profiles`. +More information about profiles is available with **Get-Help about_Profiles**. ## SEE ALSO -[podman(1)](podman.1.md) +**[podman(1)](podman.1.md)**, zsh(1), fish(1), powershell(1) diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index 271a44c9d..a86389f59 100644 --- a/docs/source/markdown/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md @@ -4,96 +4,102 @@ podman\-container\-checkpoint - Checkpoints one or more running containers ## SYNOPSIS -**podman container checkpoint** [*options*] *container* ... +**podman container checkpoint** [*options*] *container* [*container* ...] ## DESCRIPTION -Checkpoints all the processes in one or more containers. You may use container IDs or names as input. +**podman container checkpoint** checkpoints all the processes in one or more *containers*. A *container* can be restored from a checkpoint with **[podman-container-restore](podman-container-restore.1.md)**. The *container IDs* or *names* are used as input. ## OPTIONS #### **--all**, **-a** -Checkpoint all running containers. +Checkpoint all running *containers*. The default is **false**. -#### **--compress**, **-c** +#### **--compress**, **-c**=**zstd** | *none* | *gzip* Specify the compression algorithm used for the checkpoint archive created -with the **--export, -e** option. Possible algorithms are *gzip*, *none* -and *zstd*. If no compression algorithm is specified Podman will use -*zstd*. +with the **--export, -e** OPTION. Possible algorithms are **zstd**, *none* +and *gzip*. The default is **zstd**. One possible reason to use *none* is to enable faster creation of checkpoint archives. Not compressing the checkpoint archive can result in faster checkpoint archive creation. -``` -# podman container checkpoint -l --compress=none --export=dump.tar -# podman container checkpoint -l --compress=gzip --export=dump.tar.gz -``` - -#### **--export**, **-e** +#### **--export**, **-e**=*archive* Export the checkpoint to a tar.gz file. The exported checkpoint can be used -to import the container on another system and thus enabling container live -migration. This checkpoint archive also includes all changes to the container's -root file-system, if not explicitly disabled using **--ignore-rootfs** +to import the *container* on another system and thus enabling container live +migration. This checkpoint archive also includes all changes to the *container's* +root file-system, if not explicitly disabled using **--ignore-rootfs**. #### **--ignore-rootfs** This only works in combination with **--export, -e**. If a checkpoint is exported to a tar.gz file it is possible with the help of **--ignore-rootfs** to explicitly disable including changes to the root file-system into -the checkpoint archive file. +the checkpoint archive file. The default is **false**. #### **--ignore-volumes** -This option must be used in combination with the **--export, -e** option. -When this option is specified, the content of volumes associated with -the container will not be included into the checkpoint tar.gz file. +This OPTION must be used in combination with the **--export, -e** OPTION. +When this OPTION is specified, the content of volumes associated with +the *container* will not be included into the checkpoint tar.gz file. The default is **false**. #### **--keep**, **-k** -Keep all temporary log and statistics files created by CRIU during checkpointing. These files -are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these -files are theoretically not needed, but if these files are needed Podman can keep the files -for further analysis. +Keep all temporary log and statistics files created by CRIU during checkpointing. These files are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these files are theoretically not needed, but if these files are needed Podman can keep the files for further analysis. The default is **false**. #### **--latest**, **-l** -Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client) +Instead of providing the *container ID* or *name*, use the last created *container*. If you use methods other than Podman to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods. The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client.* #### **--leave-running**, **-R** -Leave the container running after checkpointing instead of stopping it. +Leave the *container* running after checkpointing instead of stopping it. The default is **false**. #### **--pre-checkpoint**, **-P** -Dump the container's memory information only, leaving the container running. Later -operations will supersede prior dumps. It only works on runc 1.0-rc3 or higher. +Dump the *container's* memory information only, leaving the *container* running. Later +operations will supersede prior dumps. It only works on `runc 1.0-rc3` or `higher`. The default is **false**. #### **--tcp-established** -Checkpoint a container with established TCP connections. If the checkpoint -image contains established TCP connections, this options is required during -restore. Defaults to not checkpointing containers with established TCP -connections. +Checkpoint a *container* with established TCP connections. If the checkpoint +image contains established TCP connections, this OPTION is required during +restore. Defaults to not checkpointing *containers* with established TCP +connections. The default is **false**. #### **--with-previous** -Check out the container with previous criu image files in pre-dump. It only works -without **--pre-checkpoint** or **-P**. It only works on runc 1.0-rc3 or higher. +Check out the *container* with previous criu image files in pre-dump. It only works on `runc 1.0-rc3` or `higher`. The default is **false**.\ +*IMPORTANT: This OPTION is not available with **--pre-checkpoint***. + -## EXAMPLE +## EXAMPLES -podman container checkpoint mywebserver +Make a checkpoint for the container "mywebserver". +``` +# podman container checkpoint mywebserver +``` -podman container checkpoint 860a4b23 +Dumps the container's memory information of the latest container into an archive. +``` +# podman container checkpoint -P -e pre-checkpoint.tar.gz -l +``` -podman container checkpoint -P -e pre-checkpoint.tar.gz -l +Keep the container's memory information from an older dump and add the new container's memory information. +``` +# podman container checkpoint --with-previous -e checkpoint.tar.gz -l +``` -podman container checkpoint --with-previous -e checkpoint.tar.gz -l +Dump the container's memory information of the latest container into an archive with the specified compress method. +``` +# podman container checkpoint -l --compress=none --export=dump.tar +# podman container checkpoint -l --compress=gzip --export=dump.tar.gz +``` ## SEE ALSO -podman(1), podman-container-restore(1) +**[podman(1)](podman.1.md)**, **[podman-container-restore(1)](podman-container-restore.1.md)** ## HISTORY September 2018, Originally compiled by Adrian Reber <areber@redhat.com> diff --git a/docs/source/markdown/podman-container-cleanup.1.md b/docs/source/markdown/podman-container-cleanup.1.md index 19d0b7818..f33b68a1c 100644 --- a/docs/source/markdown/podman-container-cleanup.1.md +++ b/docs/source/markdown/podman-container-cleanup.1.md @@ -4,51 +4,51 @@ podman\-container\-cleanup - Cleanup the container's network and mountpoints ## SYNOPSIS -**podman container cleanup** [*options*] *container* +**podman container cleanup** [*options*] *container* [*container* ...] ## DESCRIPTION -**podman container cleanup** cleans up exited containers by removing all mountpoints and network configuration from the host. The container name or ID can be used. The cleanup command does not remove the containers. Running containers will not be cleaned up. -Sometimes container's mount points and network stacks can remain if the podman command was killed or the container ran in daemon mode. This command is automatically executed when you run containers in daemon mode by the conmon process when the container exits. +**podman container cleanup** cleans up exited *containers* by removing all mountpoints and network configuration from the host. The *container name* or *ID* can be used. The cleanup command does not remove the *containers*. Running *containers* will not be cleaned up.\ +Sometimes container mount points and network stacks can remain if the podman command was killed or the *container* ran in daemon mode. This command is automatically executed when you run *containers* in daemon mode by the `conmon process` when the *container* exits. ## OPTIONS #### **--all**, **-a** -Cleanup all containers. +Cleanup all *containers*. The default is **false**. -#### **--exec**=_session_ +#### **--exec**=*session* -Clean up an exec session for a single container. -Can only be specified if a single container is being cleaned up (conflicts with **--all** as such). -If **--rm** is not specified, temporary files for the exec session will be cleaned up; if it is, the exec session will be removed from the container. -Conflicts with **--rmi** as the container is not being cleaned up so the image cannot be removed. +Clean up an exec session for a single *container*. +Can only be specified if a single *container* is being cleaned up (conflicts with **--all** as such). If **--rm** is not specified, temporary files for the exec session will be cleaned up; if it is, the exec session will be removed from the *container*.\ +*IMPORTANT: Conflicts with **--rmi** as the container is not being cleaned up so the image cannot be removed.* #### **--latest**, **-l** -Instead of providing the container name or ID, use the last created container. If you use methods other than Podman -to run containers such as CRI-O, the last started container could be from either of those methods. (This option is not available with the remote Podman client) + +Instead of providing the *container ID* or *name*, use the last created *container*. If you use methods other than Podman to run *containers* such as `CRI-O`, the last started *container* could be from either of those methods. The default is **false**.\ +*IMPORTANT: This OPTION is not available with the remote Podman client.* #### **--rm** -After cleanup, remove the container entirely. +After cleanup, remove the *container* entirely. The default is **false**. #### **--rmi** -After cleanup, remove the image entirely. - -## EXAMPLE - -`podman container cleanup mywebserver` - -`podman container cleanup mywebserver myflaskserver 860a4b23` +After cleanup, remove the image entirely. The default is **false**. -`podman container cleanup 860a4b23` +## EXAMPLES -`podman container cleanup -a` +Cleanup the container "mywebserver". +``` +$ podman container cleanup mywebserver +``` -`podman container cleanup --latest` +Cleanup the containers with the names "mywebserver", "myflaskserver", "860a4b23". +``` +$ podman container cleanup mywebserver myflaskserver 860a4b23 +``` ## SEE ALSO -**podman**(1), **podman-container**(1), **conmon**(8). +**[podman(1)](podman.1.md)**, **[podman-container(1)](podman-container.1.md)**, conmon(8) ## HISTORY Jun 2018, Originally compiled by Dan Walsh <dwalsh@redhat.com> diff --git a/docs/source/markdown/podman-container-exists.1.md b/docs/source/markdown/podman-container-exists.1.md index 381d968ab..e42489d63 100644 --- a/docs/source/markdown/podman-container-exists.1.md +++ b/docs/source/markdown/podman-container-exists.1.md @@ -1,42 +1,40 @@ % podman-container-exists(1) ## NAME -podman-container-exists - Check if a container exists in local storage +podman\-container\-exists - Check if a container exists in local storage ## SYNOPSIS **podman container exists** [*options*] *container* ## DESCRIPTION -**podman container exists** checks if a container exists in local storage. The **ID** or **Name** -of the container may be used as input. Podman will return an exit code -of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there -was an issue accessing the local storage. +**podman container exists** checks if a container exists in local storage. The *container ID* or *name* is used as input. Podman will return an exit code +of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there 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. +#### **--external** +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`. The default is **false**. **-h**, **--help** -Print usage statement +Prints usage statement. ## EXAMPLES -Check if an container called `webclient` exists in local storage (the container does actually exist). +Check if an container called "webclient" exists in local storage. Here, the container does exist. ``` $ podman container exists webclient $ echo $? 0 ``` -Check if an container called `webbackend` exists in local storage (the container does not actually exist). +Check if an container called "webbackend" exists in local storage. Here, the container does not exist. ``` $ 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). +Check if an container called "ubi8-working-container" created via Buildah exists in local storage. Here, the container does not exist. ``` $ podman container exists --external ubi8-working-container $ echo $? @@ -44,7 +42,7 @@ $ echo $? ``` ## SEE ALSO -podman(1) +**[podman(1)](podman.1.md)** ## HISTORY -November 2018, Originally compiled by Brent Baude (bbaude at redhat dot com) +November 2018, Originally compiled by Brent Baude <bbaude@redhat.com> diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index 734d00971..2510eaa81 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -336,9 +336,11 @@ Images are pulled under `XDG_DATA_HOME` when specified, otherwise in the home di Currently the slirp4netns package is required to be installed to create a network device, otherwise rootless containers need to run in the network namespace of the host. +In certain environments like HPC (High Performance Computing), users cannot take advantage of the additional UIDs and GIDs from the /etc/subuid and /etc/subgid systems. However, in this environment, rootless Podman can operate with a single UID. To make this work, set the `ignore_chown_errors` option in the /etc/containers/storage.conf or in ~/.config/containers/storage.conf files. This option tells Podman when pulling an image to ignore chown errors when attempting to change a file in a container image to match the non-root UID in the image. This means all files get saved as the user's UID. Note this could cause issues when running the container. + ### **NOTE:** Unsupported file systems in rootless mode -The Overlay file system (OverlayFS) is not supported in rootless mode. The fuse-overlayfs package is a tool that provides the functionality of OverlayFS in user namespace that allows mounting file systems in rootless environments. It is recommended to install the fuse-overlayfs package. In rootless mode Podman will automatically use the fuse-overlafs program as the mount_program if installed, as long as the $HOME/.config/containers/storage.conf file was not previously created. If storage.conf exists in the homedir, add `mount_program = "/usr/bin/fuse-overlayfs"` under `[storage.options.overlay]` to enable this feature. +The Overlay file system (OverlayFS) is not supported with kernels prior to 5.12.9 in rootless mode. The fuse-overlayfs package is a tool that provides the functionality of OverlayFS in user namespace that allows mounting file systems in rootless environments. It is recommended to install the fuse-overlayfs package. In rootless mode, Podman will automatically use the fuse-overlayfs program as the mount_program if installed, as long as the $HOME/.config/containers/storage.conf file was not previously created. If storage.conf exists in the homedir, add `mount_program = "/usr/bin/fuse-overlayfs"` under `[storage.options.overlay]` to enable this feature. The Network File System (NFS) and other distributed file systems (for example: Lustre, Spectrum Scale, the General Parallel File System (GPFS)) are not supported when running in rootless mode as these file systems do not understand user namespace. However, rootless Podman can make use of an NFS Homedir by modifying the `$HOME/.config/containers/storage.conf` to have the `graphroot` option point to a directory stored on local (Non NFS) storage. diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 69ba4671e..545b78976 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -428,7 +428,7 @@ func (c *Container) setupStorage(ctx context.Context) error { }, LabelOpts: c.config.LabelOpts, } - if c.restoreFromCheckpoint { + if c.restoreFromCheckpoint && !c.config.Privileged { // If restoring from a checkpoint, the root file-system // needs to be mounted with the same SELinux labels as // it was mounted previously. @@ -1062,7 +1062,7 @@ func (c *Container) init(ctx context.Context, retainRetries bool) error { } for _, v := range c.config.NamedVolumes { - if err := c.chownVolume(v.Name); err != nil { + if err := c.fixVolumePermissions(v); err != nil { return err } } @@ -1681,64 +1681,6 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string) return vol, nil } -// Chown the specified volume if necessary. -func (c *Container) chownVolume(volumeName string) error { - vol, err := c.runtime.state.Volume(volumeName) - if err != nil { - return errors.Wrapf(err, "error retrieving named volume %s for container %s", volumeName, c.ID()) - } - - vol.lock.Lock() - defer vol.lock.Unlock() - - // The volume may need a copy-up. Check the state. - if err := vol.update(); err != nil { - return err - } - - // TODO: For now, I've disabled chowning volumes owned by non-Podman - // drivers. This may be safe, but it's really going to be a case-by-case - // thing, I think - safest to leave disabled now and re-enable later if - // there is a demand. - if vol.state.NeedsChown && !vol.UsesVolumeDriver() { - vol.state.NeedsChown = false - - uid := int(c.config.Spec.Process.User.UID) - gid := int(c.config.Spec.Process.User.GID) - - if c.config.IDMappings.UIDMap != nil { - p := idtools.IDPair{ - UID: uid, - GID: gid, - } - mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) - newPair, err := mappings.ToHost(p) - if err != nil { - return errors.Wrapf(err, "error mapping user %d:%d", uid, gid) - } - uid = newPair.UID - gid = newPair.GID - } - - vol.state.UIDChowned = uid - vol.state.GIDChowned = gid - - if err := vol.save(); err != nil { - return err - } - - mountPoint, err := vol.MountPoint() - if err != nil { - return err - } - - if err := os.Lchown(mountPoint, uid, gid); err != nil { - return err - } - } - return nil -} - // cleanupStorage unmounts and cleans up the container's root filesystem func (c *Container) cleanupStorage() error { if !c.state.Mounted { diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index ddfccb999..ea52d7ba0 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -2426,3 +2426,77 @@ func (c *Container) createSecretMountDir() error { return err } + +// Fix ownership and permissions of the specified volume if necessary. +func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { + vol, err := c.runtime.state.Volume(v.Name) + if err != nil { + return errors.Wrapf(err, "error retrieving named volume %s for container %s", v.Name, c.ID()) + } + + vol.lock.Lock() + defer vol.lock.Unlock() + + // The volume may need a copy-up. Check the state. + if err := vol.update(); err != nil { + return err + } + + // TODO: For now, I've disabled chowning volumes owned by non-Podman + // drivers. This may be safe, but it's really going to be a case-by-case + // thing, I think - safest to leave disabled now and re-enable later if + // there is a demand. + if vol.state.NeedsChown && !vol.UsesVolumeDriver() { + vol.state.NeedsChown = false + + uid := int(c.config.Spec.Process.User.UID) + gid := int(c.config.Spec.Process.User.GID) + + if c.config.IDMappings.UIDMap != nil { + p := idtools.IDPair{ + UID: uid, + GID: gid, + } + mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) + newPair, err := mappings.ToHost(p) + if err != nil { + return errors.Wrapf(err, "error mapping user %d:%d", uid, gid) + } + uid = newPair.UID + gid = newPair.GID + } + + vol.state.UIDChowned = uid + vol.state.GIDChowned = gid + + if err := vol.save(); err != nil { + return err + } + + mountPoint, err := vol.MountPoint() + if err != nil { + return err + } + + if err := os.Lchown(mountPoint, uid, gid); err != nil { + return err + } + + // Make sure the new volume matches the permissions of the target directory. + // https://github.com/containers/podman/issues/10188 + st, err := os.Lstat(filepath.Join(c.state.Mountpoint, v.Dest)) + if err == nil { + if err := os.Chmod(mountPoint, st.Mode()|0111); err != nil { + return err + } + stat := st.Sys().(*syscall.Stat_t) + atime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) + if err := os.Chtimes(mountPoint, atime, st.ModTime()); err != nil { + return err + } + } else if !os.IsNotExist(err) { + return err + } + } + return nil +} diff --git a/libpod/container_internal_unsupported.go b/libpod/container_internal_unsupported.go index f979bcbde..125329ce5 100644 --- a/libpod/container_internal_unsupported.go +++ b/libpod/container_internal_unsupported.go @@ -57,3 +57,8 @@ func (c *Container) reloadNetwork() error { func (c *Container) getUserOverrides() *lookup.Overrides { return nil } + +// Fix ownership and permissions of the specified volume if necessary. +func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error { + return define.ErrNotImplemented +} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index c928e02a6..5446841f6 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -1090,7 +1090,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro } c.newNetworkEvent(events.NetworkDisconnect, netName) - if c.state.State != define.ContainerStateRunning { + if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) { return nil } @@ -1145,7 +1145,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e return err } c.newNetworkEvent(events.NetworkConnect, netName) - if c.state.State != define.ContainerStateRunning { + if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) { return nil } if c.state.NetNS == nil { diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index ac212474b..7baa1145a 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -166,10 +166,11 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { - FromSrc string `schema:"fromSrc"` - Changes []string `schema:"changes"` - Message string `schema:"message"` - Repo string `shchema:"repo"` + Changes []string `schema:"changes"` + FromSrc string `schema:"fromSrc"` + Message string `schema:"message"` + Platform string `schema:"platform"` + Repo string `shchema:"repo"` }{ // This is where you can override the golang default value for one of fields } @@ -192,9 +193,21 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) } } + + platformSpecs := strings.Split(query.Platform, "/") + opts := entities.ImageImportOptions{ + Source: source, + Changes: query.Changes, + Message: query.Message, + Reference: query.Repo, + OS: platformSpecs[0], + } + if len(platformSpecs) > 1 { + opts.Architecture = platformSpecs[1] + } + imageEngine := abi.ImageEngine{Libpod: runtime} - // TODO: add support for ImageImportOptions to take a platform parameter. Also import https://github.com/opencontainers/image-spec/tree/master/specs-go/v1 either here or within imageEngine.Import to get default platform - report, err := imageEngine.Import(r.Context(), entities.ImageImportOptions{Source: source, Changes: query.Changes, Message: query.Message, Reference: query.Repo}) + report, err := imageEngine.Import(r.Context(), opts) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball")) return diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 50423fb96..e933b9811 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -144,8 +144,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { if _, found := r.URL.Query()["dockerfile"]; found { var m = []string{} if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil { - utils.BadRequest(w, "dockerfile", query.Dockerfile, err) - return + // it's not json, assume just a string + m = append(m, query.Dockerfile) } containerFiles = m } else { @@ -189,8 +189,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { var devices = []string{} if _, found := r.URL.Query()["devices"]; found { var m = []string{} - if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil { - utils.BadRequest(w, "devices", query.DropCapabilities, err) + if err := json.Unmarshal([]byte(query.Devices), &m); err != nil { + utils.BadRequest(w, "devices", query.Devices, err) return } devices = m diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index c7d432b16..937d05330 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -299,6 +299,22 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO tarContent := []string{options.ContextDirectory} newContainerFiles := []string{} for _, c := range containerFiles { + if c == "/dev/stdin" { + content, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return nil, err + } + tmpFile, err := ioutil.TempFile("", "build") + if err != nil { + return nil, err + } + defer os.Remove(tmpFile.Name()) // clean up + defer tmpFile.Close() + if _, err := tmpFile.Write(content); err != nil { + return nil, err + } + c = tmpFile.Name() + } containerfile, err := filepath.Abs(c) if err != nil { logrus.Errorf("cannot find absolute path of %v: %v", c, err) diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index 911edeb5b..9cb32a364 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -165,14 +165,13 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) if _, found := exclude[name]; found { continue } - isSymLink := false fileInfo, err := os.Stat(cgroupRoot + "/" + name) if err != nil { - isSymLink = !fileInfo.IsDir() + continue } c := controller{ name: name, - symlink: isSymLink, + symlink: !fileInfo.IsDir(), } controllers = append(controllers, c) } diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index 3cc46ed0a..17b82037e 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -271,8 +271,10 @@ type ImageLoadReport struct { } type ImageImportOptions struct { + Architecture string Changes []string Message string + OS string Quiet bool Reference string SignaturePolicy string diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 5a953c047..e6dd19e63 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -702,7 +702,9 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric containersNamesOrIds := namesOrIds + all := options.All if len(options.Filters) > 0 { + all = false filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters)) if len(options.Filters) > 0 { for k, v := range options.Filters { @@ -719,6 +721,10 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } containersNamesOrIds = []string{} for _, candidate := range candidates { + if options.All { + containersNamesOrIds = append(containersNamesOrIds, candidate.ID()) + continue + } for _, nameOrID := range namesOrIds { if nameOrID == candidate.ID() || nameOrID == candidate.Name() { containersNamesOrIds = append(containersNamesOrIds, nameOrID) @@ -726,8 +732,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } } } - - ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, containersNamesOrIds, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(all, options.Latest, containersNamesOrIds, ic.Libpod) if err != nil { return nil, err } diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go index 083566201..5992181d3 100644 --- a/pkg/domain/infra/abi/images.go +++ b/pkg/domain/infra/abi/images.go @@ -388,6 +388,8 @@ func (ir *ImageEngine) Import(ctx context.Context, options entities.ImageImportO importOptions.CommitMessage = options.Message importOptions.Tag = options.Reference importOptions.SignaturePolicyPath = options.SignaturePolicy + importOptions.OS = options.OS + importOptions.Architecture = options.Architecture if !options.Quiet { importOptions.Writer = os.Stderr diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index 74ced300a..0047fc839 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -508,7 +508,9 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric containersNamesOrIds := namesOrIds + all := options.All if len(options.Filters) > 0 { + all = false containersNamesOrIds = []string{} opts := new(containers.ListOptions).WithFilters(options.Filters).WithAll(true) candidates, listErr := containers.List(ic.ClientCtx, opts) @@ -516,6 +518,10 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri return nil, listErr } for _, candidate := range candidates { + if options.All { + containersNamesOrIds = append(containersNamesOrIds, candidate.ID) + continue + } for _, nameOrID := range namesOrIds { if nameOrID == candidate.ID { containersNamesOrIds = append(containersNamesOrIds, nameOrID) @@ -530,7 +536,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri } } } - ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, containersNamesOrIds) + ctrs, err := getContainersByContext(ic.ClientCtx, all, false, containersNamesOrIds) if err != nil { return nil, err } diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index 037a4c01f..9e464dbc7 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -147,4 +147,39 @@ t GET "images/get?names=alpine&names=busybox" 200 '[POSIX tar archive]' img_cnt=$(tar xf "$WORKDIR/curl.result.out" manifest.json -O | jq "length") is "$img_cnt" 2 "number of images in tar archive" +# check build works when uploading container file as a tar, see issue #10660 +TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX) +function cleanBuildTest() { + podman rmi -a -f + rm -rf "${TMPD}" &> /dev/null +} +CONTAINERFILE_TAR="${TMPD}/containerfile.tar" +cat > $TMPD/containerfile << EOF +FROM quay.io/libpod/alpine_labels:latest +EOF +tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null + +curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ + -H "content-type: application/x-tar" \ + --dump-header "${TMPD}/headers.txt" \ + -o "${TMPD}/response.txt" \ + "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null + +BUILD_TEST_ERROR="" + +if ! grep -q '200 OK' "${TMPD}/headers.txt"; then + echo -e "${red}NOK: Image build from tar failed response was not 200 OK" + BUILD_TEST_ERROR="1" +fi + +if ! grep -q 'quay.io/libpod/alpine_labels' "${TMPD}/response.txt"; then + echo -e "${red}NOK: Image build from tar failed image name not in response" + BUILD_TEST_ERROR="1" +fi + +cleanBuildTest +if [[ "${BUILD_TEST_ERROR}" ]]; then + exit 1 +fi + # vim: filetype=sh diff --git a/test/apiv2/python/rest_api/test_v2_0_0_image.py b/test/apiv2/python/rest_api/test_v2_0_0_image.py index cea34e2e7..59dcea87f 100644 --- a/test/apiv2/python/rest_api/test_v2_0_0_image.py +++ b/test/apiv2/python/rest_api/test_v2_0_0_image.py @@ -89,14 +89,9 @@ class ImageTestCase(APITestCase): def test_create(self): r = requests.post( - self.podman_url + "/v1.40/images/create?fromImage=alpine&platform=linux/amd64/v8", - timeout=15, - ) + self.podman_url + "/v1.40/images/create?fromImage=alpine&platform=linux/amd64/v8", timeout=15) self.assertEqual(r.status_code, 200, r.text) - r = requests.post( - self.podman_url + "/v1.40/images/create?fromSrc=-&repo=fedora&message=testing123", - timeout=15, - ) + r = requests.post(self.podman_url + "/v1.40/images/create?fromSrc=-&repo=fedora&message=testing123&platform=linux/amd64", timeout=15) self.assertEqual(r.status_code, 200, r.text) def test_search_compat(self): diff --git a/test/compose/test-compose b/test/compose/test-compose index 981f78a79..70db6dd55 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -183,6 +183,8 @@ function test_port() { fi echo "# cat $WORKDIR/server.log:" cat $WORKDIR/server.log + echo "# cat $logfile:" + cat $logfile return fi diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index 6255690b1..abaacdd5e 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -604,4 +604,38 @@ RUN echo hello`, ALPINE) Expect(inspect.OutputToString()).To(Equal("windows")) }) + + It("podman build device test", func() { + if _, err := os.Lstat("/dev/fuse"); err != nil { + Skip(fmt.Sprintf("test requires stat /dev/fuse to work: %v", err)) + } + containerfile := fmt.Sprintf(`FROM %s +RUN ls /dev/fuse`, ALPINE) + containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") + err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755) + Expect(err).To(BeNil()) + session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + + session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/fuse", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + + It("podman build device rename test", func() { + SkipIfRootless("rootless builds do not currently support renaming devices") + containerfile := fmt.Sprintf(`FROM %s +RUN ls /dev/test1`, ALPINE) + containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile") + err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755) + Expect(err).To(BeNil()) + session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(125)) + + session = podmanTest.Podman([]string{"build", "--pull-never", "--device", "/dev/zero:/dev/test1", "-t", "test", "--file", containerfilePath, podmanTest.TempDir}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) }) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 58538b689..cae1b5aad 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -904,6 +904,18 @@ USER bin`, BB) Expect(session.ExitCode()).To(Equal(100)) }) + It("podman run with named volume", func() { + session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + perms := session.OutputToString() + + session = podmanTest.Podman([]string{"run", "--rm", "-v", "test:/var/tmp", ALPINE, "stat", "-c", "%a %Y", "/var/tmp"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal(perms)) + }) + It("podman run with built-in volume image", func() { session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"}) session.WaitWithDefaultTimeout() diff --git a/test/system/045-start.bats b/test/system/045-start.bats index 3e0118dba..7e4bbde8d 100644 --- a/test/system/045-start.bats +++ b/test/system/045-start.bats @@ -59,4 +59,15 @@ load helpers is "$output" "Error: fakepolicy invalid restart policy" } +@test "podman start --all --filter" { + run_podman run -d $IMAGE /bin/true + cid_exited_0="$output" + run_podman run -d $IMAGE /bin/false + cid_exited_1="$output" + + run_podman wait $cid_exited_0 $cid_exited_1 + run_podman start --all --filter exited=0 + is "$output" "$cid_exited_0" +} + # vim: filetype=sh diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 40622d6cc..6843e28a5 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -29,6 +29,29 @@ EOF run_podman rmi -f build_test } +@test "podman build test -f -" { + rand_filename=$(random_string 20) + rand_content=$(random_string 50) + + tmpdir=$PODMAN_TMPDIR/build-test + mkdir -p $tmpdir + containerfile=$PODMAN_TMPDIR/Containerfile + cat >$containerfile <<EOF +FROM $IMAGE +RUN apk add nginx +RUN echo $rand_content > /$rand_filename +EOF + + # The 'apk' command can take a long time to fetch files; bump timeout + PODMAN_TIMEOUT=240 run_podman build -t build_test -f - --format=docker $tmpdir < $containerfile + is "$output" ".*STEP 4: COMMIT" "COMMIT seen in log" + + run_podman run --rm build_test cat /$rand_filename + is "$output" "$rand_content" "reading generated file in image" + + run_podman rmi -f build_test +} + @test "podman build - global runtime flags test" { skip_if_remote "--runtime-flag flag not supported for remote" |