diff options
80 files changed, 1633 insertions, 135 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 1bbd41b22..41e3d8078 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -7,6 +7,10 @@ env: #### # Name of the ultimate destination branch for this CI run, PR or post-merge. DEST_BRANCH: "main" + # Netavark branch to use when TEST_ENVIRON=host-netavark + NETAVARK_BRANCH: "main" + # Aardvark branch to use + AARDVARK_BRANCH: "main" # Overrides default location (/tmp/cirrus) for repo clone GOPATH: &gopath "/var/tmp/go" GOBIN: "${GOPATH}/bin" @@ -44,7 +48,7 @@ env: #### N/B: Required ALL of these are set for every single task. #### TEST_FLAVOR: # int, sys, ext_svc, validate, automation, etc. - TEST_ENVIRON: host # 'host' or 'container' + TEST_ENVIRON: host # 'host', 'host-netavark', or 'container' PODBIN_NAME: podman # 'podman' or 'remote' PRIV_NAME: root # 'root' or 'rootless' DISTRO_NV: # any {PRIOR_,}{FEDORA,UBUNTU}_NAME value @@ -218,7 +222,8 @@ validate_task: bindings_task: name: "Test Bindings" alias: bindings - only_if: ¬_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' + # Don't run for [CI:DOCS] or [CI:BUILD] + only_if: ¬_build $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' && $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*' skip: *branches_and_tags depends_on: - build @@ -298,7 +303,8 @@ consistency_task: alt_build_task: name: "$ALT_NAME" alias: alt_build - only_if: *not_docs + # Don't run for [CI:DOCS]; DO run for [CI:BUILD] + only_if: ¬_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' depends_on: - build env: @@ -327,6 +333,7 @@ alt_build_task: osx_alt_build_task: name: "OSX Cross" alias: osx_alt_build + only_if: *not_docs depends_on: - build env: @@ -352,7 +359,7 @@ docker-py_test_task: name: Docker-py Compat. alias: docker-py_test skip: *tags - only_if: *not_docs + only_if: *not_build depends_on: - build gce_instance: *standardvm @@ -373,7 +380,7 @@ unit_test_task: name: "Unit tests on $DISTRO_NV" alias: unit_test skip: *tags - only_if: *not_docs + only_if: *not_build depends_on: - validate matrix: @@ -398,7 +405,7 @@ unit_test_task: apiv2_test_task: name: "APIv2 test on $DISTRO_NV" alias: apiv2_test - only_if: *not_docs + only_if: *not_build skip: *tags depends_on: - validate @@ -419,7 +426,7 @@ apiv2_test_task: compose_test_task: name: "compose test on $DISTRO_NV ($PRIV_NAME)" alias: compose_test - only_if: *not_docs + only_if: *not_build skip: *tags depends_on: - validate @@ -446,7 +453,7 @@ local_integration_test_task: &local_integration_test_task # <int.|sys.> <podman|remote> <Distro NV> <root|rootless> name: &std_name_fmt "$TEST_FLAVOR $PODBIN_NAME $DISTRO_NV $PRIV_NAME $TEST_ENVIRON" alias: local_integration_test - only_if: *not_docs + only_if: *not_build skip: *branches_and_tags depends_on: - unit_test @@ -482,7 +489,7 @@ remote_integration_test_task: container_integration_test_task: name: *std_name_fmt alias: container_integration_test - only_if: *not_docs + only_if: *not_build skip: *branches_and_tags depends_on: - unit_test @@ -508,12 +515,38 @@ container_integration_test_task: main_script: *main always: *int_logs_artifacts +# Run the integration tests using the latest upstream build of netavark. +netavark_integration_test_task: + name: "Netavark integration" # using *std_name_fmt here is unreadable + alias: netavark_integration_test + only_if: *not_build + skip: *branches_and_tags + depends_on: + - unit_test + gce_instance: *standardvm + env: + DISTRO_NV: ${FEDORA_NAME} + _BUILD_CACHE_HANDLE: ${FEDORA_NAME}-build-${CIRRUS_BUILD_ID} + VM_IMAGE_NAME: ${FEDORA_CACHE_IMAGE_NAME} + CTR_FQIN: ${FEDORA_CONTAINER_FQIN} + TEST_FLAVOR: int + TEST_ENVIRON: host-netavark + NETAVARK_URL: "https://api.cirrus-ci.com/v1/artifact/github/containers/netavark/success/binary.zip?branch=${NETAVARK_BRANCH}" + NETAVARK_DEBUG: 0 # set non-zero to use the debug-mode binary + AARDVARK_URL: "https://api.cirrus-ci.com/v1/artifact/github/containers/aardvark-dns/success/binary.zip?branch=${AARDVARK_BRANCH}" + AARDVARK_DEBUG: 0 # set non-zero to use the debug-mode binary + clone_script: *noop # Comes from cache + gopath_cache: *ro_gopath_cache + setup_script: *setup + main_script: *main + always: *int_logs_artifacts + # Execute most integration tests as a regular (non-root) user. rootless_integration_test_task: name: *std_name_fmt alias: rootless_integration_test - only_if: *not_docs + only_if: *not_build skip: *branches_and_tags depends_on: - unit_test @@ -538,7 +571,7 @@ local_system_test_task: &local_system_test_task name: *std_name_fmt alias: local_system_test skip: *tags - only_if: *not_docs + only_if: *not_build depends_on: - local_integration_test matrix: *platform_axis @@ -585,7 +618,7 @@ buildah_bud_test_task: name: *std_name_fmt alias: buildah_bud_test skip: *tags - only_if: *not_docs + only_if: *not_build depends_on: - local_integration_test env: @@ -613,7 +646,7 @@ rootless_system_test_task: name: *std_name_fmt alias: rootless_system_test skip: *tags - only_if: *not_docs + only_if: *not_build depends_on: - rootless_integration_test matrix: *platform_axis @@ -631,7 +664,7 @@ rootless_gitlab_test_task: name: *std_name_fmt alias: rootless_gitlab_test skip: *tags - only_if: *not_docs + only_if: *not_build # Community-maintained downstream test may fail unexpectedly. # Ref. repository: https://gitlab.com/gitlab-org/gitlab-runner # If necessary, uncomment the next line and file issue(s) with details. @@ -658,7 +691,7 @@ upgrade_test_task: name: "Upgrade test: from $PODMAN_UPGRADE_FROM" alias: upgrade_test skip: *tags - only_if: $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' || $CIRRUS_CRON != '' + only_if: *not_build depends_on: - local_system_test matrix: @@ -733,6 +766,7 @@ success_task: - remote_integration_test - rootless_integration_test - container_integration_test + - netavark_integration_test - local_system_test - remote_system_test - rootless_system_test @@ -777,7 +811,10 @@ release_task: release_test_task: name: "Optional Release Test" alias: release_test - only_if: $CIRRUS_PR != '' + # Release-PRs are never ever marked with [CI:DOCS] or [CI:BUILD] + only_if: *not_build + # Allow running manually as part of release PR preperation + # see RELEASE_PROCESS.md trigger_type: manual depends_on: - success diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index f0223f9eb..6376bafa2 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -12,7 +12,7 @@ set -eo pipefail # most notably: # # PODBIN_NAME : "podman" (i.e. local) or "remote" -# TEST_ENVIRON : 'host' or 'container'; desired environment in which to run +# TEST_ENVIRON : 'host', 'host-netavark', or 'container'; desired environment in which to run # CONTAINER : 1 if *currently* running inside a container, 0 if host # diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 6a3597402..72afcf9bf 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -130,7 +130,7 @@ esac # Required to be defined by caller: The environment where primary testing happens # shellcheck disable=SC2154 case "$TEST_ENVIRON" in - host) + host*) # The e2e tests wrongly guess `--cgroup-manager` option # shellcheck disable=SC2154 if [[ "$CG_FS_TYPE" == "cgroup2fs" ]] || [[ "$PRIV_NAME" == "root" ]] @@ -141,6 +141,41 @@ case "$TEST_ENVIRON" in warn "Forcing CGROUP_MANAGER=cgroupfs" echo "CGROUP_MANAGER=cgroupfs" >> /etc/ci_environment fi + # TODO: For the foreseeable future, need to support running tests + # with and without the latest netavark/aardvark. Once they're more + # stable and widely supported in Fedora, they can be pre-installed + # from its RPM at VM image build-time. + if [[ "$TEST_ENVIRON" =~ netavark ]]; then + for info in "netavark $NETAVARK_BRANCH $NETAVARK_URL $NETAVARK_DEBUG" \ + "aardvark-dns $AARDVARK_BRANCH $AARDVARK_URL $AARDVARK_DEBUG"; do + + read _name _branch _url _debug <<<"$info" + req_env_vars _name _branch _url _debug + msg "Downloading latest $_name from upstream branch '$_branch'" + # Use identifiable archive filename in of a get_ci_env.sh environment + curl --fail --location -o /tmp/$_name.zip "$_url" + + # Needs to be in a specific location + # ref: https://github.com/containers/common/blob/main/pkg/config/config_linux.go#L39 + _pdir=/usr/local/libexec/podman + mkdir -p $_pdir + cd $_pdir + msg "$PWD" + unzip /tmp/$_name.zip + if ((_debug)); then + warn "Using debug $_name binary" + mv $_name.debug $_name + else + rm $_name.debug + fi + chmod 0755 $_pdir/$_name + cd - + done + + restorecon -F -v $_nvdir + msg "Forcing NETWORK_BACKEND=netavark in all subsequent environments." + echo "NETWORK_BACKEND=netavark" >> /etc/ci_environment + fi ;; container) if ((CONTAINER==0)); then # not yet inside a container @@ -247,7 +282,7 @@ case "$TEST_FLAVOR" in # Use existing host bits when testing is to happen inside a container # since this script will run again in that environment. # shellcheck disable=SC2154 - if [[ "$TEST_ENVIRON" == "host" ]]; then + if [[ "$TEST_ENVIRON" =~ host ]]; then if ((CONTAINER)); then die "Refusing to config. host-test in container"; fi @@ -259,7 +294,7 @@ case "$TEST_FLAVOR" in make && make install PREFIX=/usr ETCDIR=/etc fi else - die "Invalid value for $$TEST_ENVIRON=$TEST_ENVIRON" + die "Invalid value for \$TEST_ENVIRON=$TEST_ENVIRON" fi install_test_configs diff --git a/contrib/helloimage/Containerfile b/contrib/helloimage/Containerfile new file mode 100644 index 000000000..bea71cae0 --- /dev/null +++ b/contrib/helloimage/Containerfile @@ -0,0 +1,8 @@ +FROM registry.access.redhat.com/ubi8-micro:latest + +LABEL maintainer="Podman Maintainers" +LABEL artist="MáirÃn Nà ḊuḃṫaiÄ¡, Twitter:@mairin" +WORKDIR /tmp + +COPY podman_hello_world.bash . +ENTRYPOINT ./podman_hello_world.bash diff --git a/contrib/helloimage/README.md b/contrib/helloimage/README.md new file mode 100644 index 000000000..93edcc527 --- /dev/null +++ b/contrib/helloimage/README.md @@ -0,0 +1,55 @@ +![PODMAN logo](../../logo/podman-logo-source.svg) + +# Podman Hello World image + +## Overview + +This directory contains the Containerfile and bash script necessary to create the +"hello" podman image housed on quay.io under the Podman account in a public +repository. The image is public and can be pulled without credentials. + +Using this image is helpful to: + + * Prove that basic Podman operations are working on the host. + * Shows that the image was pulled from the quay.io container registry. + * Container creation was successfuly accomplished. (`podman ps -a`) + * The created container was able to stream output to your terminal. + +## Directory Contents + +The contents of this directory contain: + * ./Containerfile + * ./podman_hello_world.bash + +## Sample Usage + +To simply run the image: + +``` +podman run quay.io/podman/hello + +! ... Hello Podman World ...! + + .--"--. + / - - \ + / (O) (O) \ + ~~~| -=(,Y,)=- | + .---. /` \ |~~ + ~/ o o \~~~~.----. ~~ + | =(X)= |~ / (O (O) \ + ~~~~~~~ ~| =(Y_)=- | + ~~~~ ~~~| U |~~ + +Project: https://github.com/containers/podman +Website: https://podman.io +Documents: https://docs.podman.io +Twitter: @Podman_io +``` +To build the image yourself, copy the files from this directory into +a local directory and issue these commands: + +``` +chmod 755 ./podman_hello_world.bash +podman build -t myhello . +podman run myhello +``` diff --git a/contrib/helloimage/podman_hello_world.bash b/contrib/helloimage/podman_hello_world.bash new file mode 100755 index 000000000..c28141174 --- /dev/null +++ b/contrib/helloimage/podman_hello_world.bash @@ -0,0 +1,23 @@ +#!/bin/sh +### +# ASCII art by the incomparable MáirÃn Duffy, +# duffy@redhat.com, Twitter: @mairin +# January 2022 +### +echo " " +echo "! ... Hello Podman World ...!" +echo " " +echo " .--\"--. " +echo " / - - \\ " +echo " / (O) (O) \\ " +echo " ~~~| -=(,Y,)=- | " +echo " .---. /\` \\ |~~ " +echo " ~/ o o \\~~~~.----. ~~ " +echo " | =(X)= |~ / (O (O) \\ " +echo " ~~~~~~~ ~| =(Y_)=- | " +echo " ~~~~ ~~~| U |~~ " +echo "" +echo "Project: https://github.com/containers/podman" +echo "Website: https://podman.io" +echo "Documents: https://docs.podman.io" +echo "Twitter: @Podman_io" diff --git a/docs/source/markdown/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md index 6340a9360..985cfa0e8 100644 --- a/docs/source/markdown/podman-attach.1.md +++ b/docs/source/markdown/podman-attach.1.md @@ -22,7 +22,7 @@ The default is `ctrl-p,ctrl-q`. 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.\ 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.* +*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.* #### **--no-stdin** diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md index 9d03174c7..2c8f4005c 100644 --- a/docs/source/markdown/podman-build.1.md +++ b/docs/source/markdown/podman-build.1.md @@ -94,7 +94,7 @@ resulting image's configuration. #### **--cache-from** Images to utilize as potential cache sources. Podman does not currently support -caching so this is a NOOP. (This option is not available with the remote Podman client) +caching so this is a NOOP. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--cap-add**=*CAP\_xxx* @@ -119,7 +119,7 @@ given. #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--cgroup-parent**=*path* @@ -138,7 +138,7 @@ that the cgroup namespace in which `buildah` itself is being run should be reuse This option is added to be aligned with other containers CLIs. Podman doesn't communicate with a daemon or a remote server. -Thus, compressing the data before sending it is irrelevant to Podman. (This option is not available with the remote Podman client) +Thus, compressing the data before sending it is irrelevant to Podman. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--cpu-period**=*limit* @@ -257,7 +257,7 @@ specifying **--disable-compression=false**. This is a Docker specific option to disable image verification to a container registry and is not supported by Podman. This option is a NOOP and provided -solely for scripting compatibility. (This option is not available with the remote Podman client) +solely for scripting compatibility. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--dns**=*dns* @@ -546,7 +546,7 @@ size entirely, the system uses `64m`. #### **--sign-by**=*fingerprint* -Sign the image using a GPG key with the specified FINGERPRINT. (This option is not available with the remote Podman client) +Sign the image using a GPG key with the specified FINGERPRINT. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines,) #### **--squash** @@ -600,7 +600,7 @@ timestamp. #### **--tls-verify** Require HTTPS and verify certificates when talking to container registries -(defaults to true). (This option is not available with the remote Podman client) +(defaults to true). (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--ulimit**=*type*=*soft-limit*[:*hard-limit*] @@ -727,7 +727,7 @@ using the architecture variant of the build host. Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman - container. (This option is not available with the remote Podman client) + container. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> diff --git a/docs/source/markdown/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index 00d8f7095..fcb3cfd0c 100644 --- a/docs/source/markdown/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md @@ -57,7 +57,7 @@ The default is **false**. 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.\ 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.* +*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.* #### **--leave-running**, **-R** diff --git a/docs/source/markdown/podman-container-cleanup.1.md b/docs/source/markdown/podman-container-cleanup.1.md index e58519ac3..0f182eded 100644 --- a/docs/source/markdown/podman-container-cleanup.1.md +++ b/docs/source/markdown/podman-container-cleanup.1.md @@ -27,7 +27,7 @@ Can only be specified if a single *container* is being cleaned up (conflicts wit 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.\ 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.* +*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.* #### **--rm** diff --git a/docs/source/markdown/podman-container-diff.1.md b/docs/source/markdown/podman-container-diff.1.md index 89a749fbd..f09bc4896 100644 --- a/docs/source/markdown/podman-container-diff.1.md +++ b/docs/source/markdown/podman-container-diff.1.md @@ -26,7 +26,7 @@ Alter the output into a different format. The only valid format for **podman con #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-container-inspect.1.md b/docs/source/markdown/podman-container-inspect.1.md index dfed294fc..9945fca7c 100644 --- a/docs/source/markdown/podman-container-inspect.1.md +++ b/docs/source/markdown/podman-container-inspect.1.md @@ -23,7 +23,7 @@ The keys of the returned JSON can be used as the values for the --format flag (s 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.) +(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines.) #### **--size**, **-s** diff --git a/docs/source/markdown/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md index 3dfa063b8..4016eb1cb 100644 --- a/docs/source/markdown/podman-container-restore.1.md +++ b/docs/source/markdown/podman-container-restore.1.md @@ -33,7 +33,7 @@ The default is **false**. 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.* +*IMPORTANT: This OPTION is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines. This OPTION does not need a container name or ID as input argument.* #### **--ignore-rootfs** @@ -87,7 +87,7 @@ not much the container runtime used for container creation. Import a pre-checkpoint tar.gz file which was exported by Podman. This option must be used with **-i** or **--import**. It only works on `runc 1.0-rc3` or `higher`. -*IMPORTANT: This OPTION is not supported on the remote client.* +*IMPORTANT: This OPTION is not supported on the remote client, including Mac and Windows (excluding WSL2) machines.* #### **--name**, **-n**=*name* diff --git a/docs/source/markdown/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md index 2457265dd..ac34b232c 100644 --- a/docs/source/markdown/podman-container-runlabel.1.md +++ b/docs/source/markdown/podman-container-runlabel.1.md @@ -42,7 +42,7 @@ Display the label's value of the image having populated its environment variable #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--creds**=*[username[:password]]* diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 16b358745..2a0f3b738 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -25,7 +25,7 @@ man pages. ## IMAGE The image is specified using transport:path format. If no transport is specified, the `docker` (container registry) -transport will be used by default. For remote Podman, `docker` is the only allowed transport. +transport will be used by default. For remote Podman, including Mac and Windows (excluding WSL2) machines, `docker` is the only allowed transport. **dir:**_path_ An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This @@ -149,7 +149,7 @@ Write the container ID to the file #### **--conmon-pidfile**=*path* Write the pid of the `conmon` process to a file. `conmon` runs in a separate process than Podman, so this is necessary when using systemd to restart Podman containers. -(This option is not available with the remote Podman client) +(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--cpu-period**=*limit* @@ -348,7 +348,7 @@ See [**Environment**](#environment) note below for precedence and examples. #### **--env-host** -Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client) +Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--env-file**=*file* @@ -377,7 +377,7 @@ Allows container to use the user's supplementary group access. If file systems o devices are only accessible by the rootless user's group, this flag tells the OCI runtime to pass the group access into the container. Currently only available with the `crun` OCI runtime. Note: `keep-groups` is exclusive, you cannot add any other groups -with this flag. (Not available for remote commands) +with this flag. (Not available for remote commands, including Mac and Windows (excluding WSL2) machines) #### **--health-cmd**=*"command"* | *'["command", "arg1", ...]'* @@ -432,7 +432,7 @@ the container should not use any proxy. Proxy environment variables specified for the container in any other way will override the values that would have been passed through from the host. (Other ways to specify the proxy for the container include passing the values with the `--env` flag, or hard coding the -proxy environment at container build time.) (This option is not available with the remote Podman client) +proxy environment at container build time.) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) For example, to disable passing these environment variables from host to container: @@ -524,7 +524,7 @@ $ podman info --format '{{ .Host.LogDriver }}' journald ``` The *passthrough* driver passes down the standard streams (stdin, stdout, stderr) to the -container. It is not allowed with the remote Podman client and on a tty, since it is +container. It is not allowed with the remote Podman client, including Mac and Windows (excluding WSL2) machines, and on a tty, since it is vulnerable to attacks via TIOCSTI. #### **--log-opt**=*name*=*value* @@ -1237,7 +1237,7 @@ Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman container. Similarly, `-v SOURCE-VOLUME:/CONTAINER-DIR` will mount the volume in the host to the container. If no such named volume exists, Podman will -create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarily the client machine.) +create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, including Mac and Windows (excluding WSL2) machines, the volumes will be mounted from the remote server, not necessarily the client machine.) The _options_ is a comma-separated list and can be: @@ -1445,7 +1445,7 @@ can override the working directory by using the **-w** option. #### **--pidfile**=*path* -When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client) +When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile. After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command: diff --git a/docs/source/markdown/podman-diff.1.md b/docs/source/markdown/podman-diff.1.md index fd574abb1..66675de93 100644 --- a/docs/source/markdown/podman-diff.1.md +++ b/docs/source/markdown/podman-diff.1.md @@ -26,7 +26,7 @@ Alter the output into a different format. The only valid format for **podman di #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md index c539e987b..5fb4ceace 100644 --- a/docs/source/markdown/podman-exec.1.md +++ b/docs/source/markdown/podman-exec.1.md @@ -37,7 +37,7 @@ When set to true, keep stdin open even if not attached. The default is *false*. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--preserve-fds**=*N* diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index d051092f8..fdc9c21a5 100644 --- a/docs/source/markdown/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md @@ -10,7 +10,7 @@ podman\-generate\-systemd - Generate systemd unit file(s) for a container or pod **podman generate systemd** will create a systemd unit file that can be used to control a container or pod. By default, the command will print the content of the unit files to stdout. -_Note: If you use this command with the remote client, you would still have to place the generated units on the remote system. Moreover, please make sure that the XDG_RUNTIME_DIR environment variable is set. If unset, you may set it via `export XDG_RUNTIME_DIR=/run/user/$(id -u)`._ +_Note: If you use this command with the remote client, including Mac and Windows (excluding WSL2) machines, you would still have to place the generated units on the remote system. Moreover, please make sure that the XDG_RUNTIME_DIR environment variable is set. If unset, you may set it via `export XDG_RUNTIME_DIR=/run/user/$(id -u)`._ ## OPTIONS diff --git a/docs/source/markdown/podman-image-scp.1.md b/docs/source/markdown/podman-image-scp.1.md index d39882417..e08d5b465 100644 --- a/docs/source/markdown/podman-image-scp.1.md +++ b/docs/source/markdown/podman-image-scp.1.md @@ -8,7 +8,7 @@ podman-image-scp - Securely copy an image from one host to another ## DESCRIPTION **podman image scp** copies container images between hosts on a network. You can load to the remote host or from the remote host as well as in between two remote hosts. -Note: `::` is used to specify the image name depending on if you are saving or loading. Images can also be transferred from rootful to rootless storage on the same machine without using sshd. This feature is not supported on the remote client. +Note: `::` is used to specify the image name depending on if you are saving or loading. Images can also be transferred from rootful to rootless storage on the same machine without using sshd. This feature is not supported on the remote client, including Mac and Windows (excluding WSL2) machines. **podman image scp [GLOBAL OPTIONS]** diff --git a/docs/source/markdown/podman-image-sign.1.md b/docs/source/markdown/podman-image-sign.1.md index 42ddd7eb2..7e483a3b2 100644 --- a/docs/source/markdown/podman-image-sign.1.md +++ b/docs/source/markdown/podman-image-sign.1.md @@ -33,7 +33,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path` #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--directory**, **-d**=*dir* diff --git a/docs/source/markdown/podman-image-trust.1.md b/docs/source/markdown/podman-image-trust.1.md index 61b8966a7..ba8d7fc2f 100644 --- a/docs/source/markdown/podman-image-trust.1.md +++ b/docs/source/markdown/podman-image-trust.1.md @@ -8,7 +8,7 @@ podman\-image\-trust - Manage container registry image trust policy **podman image trust** set|show [*options*] *registry[/repository]* ## DESCRIPTION -Manages which registries you trust as a source of container images based on its location. (This option is not available with the remote Podman client) +Manages which registries you trust as a source of container images based on its location. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) The location is determined by the transport and the registry host of the image. Using this container image `docker://docker.io/library/busybox` diff --git a/docs/source/markdown/podman-init.1.md b/docs/source/markdown/podman-init.1.md index 6d1d92e04..d771c92f3 100644 --- a/docs/source/markdown/podman-init.1.md +++ b/docs/source/markdown/podman-init.1.md @@ -25,7 +25,7 @@ Initialize all containers. Containers that have already initialized (including c #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md index 259a6c992..9eafb7460 100644 --- a/docs/source/markdown/podman-inspect.1.md +++ b/docs/source/markdown/podman-inspect.1.md @@ -37,7 +37,7 @@ The keys of the returned JSON can be used as the values for the --format flag (s 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 can be used to inspect the latest pod created when used with --type pod. (This option is not available with the remote Podman client or when invoked as *podman image inspect*.) +This option can be used to inspect the latest pod created when used with --type pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines, or when invoked as *podman image inspect*.) #### **--size**, **-s** diff --git a/docs/source/markdown/podman-kill.1.md b/docs/source/markdown/podman-kill.1.md index dc79a44dc..79d93bc4e 100644 --- a/docs/source/markdown/podman-kill.1.md +++ b/docs/source/markdown/podman-kill.1.md @@ -23,7 +23,7 @@ Read container ID from the specified file and remove the container. Can be spec #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--signal**, **-s** diff --git a/docs/source/markdown/podman-load.1.md b/docs/source/markdown/podman-load.1.md index d1735750f..30e8e82ea 100644 --- a/docs/source/markdown/podman-load.1.md +++ b/docs/source/markdown/podman-load.1.md @@ -30,7 +30,7 @@ Note: `:` is a restricted character and cannot be part of the file name. Load the specified input file instead of from stdin. The file can be on the local file system or on a server (e.g., https://server.com/archive.tar) -The remote client requires the use of this option. +The remote client, including Mac and Windows (excluding WSL2) machines, requires the use of this option. NOTE: Use the environment variable `TMPDIR` to change the temporary storage location of container images. Podman defaults to use `/var/tmp`. diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md index ae1eeeafa..c84b0cc99 100644 --- a/docs/source/markdown/podman-login.1.md +++ b/docs/source/markdown/podman-login.1.md @@ -38,7 +38,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path` #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--get-login** diff --git a/docs/source/markdown/podman-logs.1.md b/docs/source/markdown/podman-logs.1.md index b8b0b44ba..f62a66c81 100644 --- a/docs/source/markdown/podman-logs.1.md +++ b/docs/source/markdown/podman-logs.1.md @@ -26,7 +26,7 @@ file will be removed before `podman logs` reads the final content. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--names**, **-n** diff --git a/docs/source/markdown/podman-manifest-add.1.md b/docs/source/markdown/podman-manifest-add.1.md index 8e3f56797..40f841bf8 100644 --- a/docs/source/markdown/podman-manifest-add.1.md +++ b/docs/source/markdown/podman-manifest-add.1.md @@ -44,7 +44,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path` #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--creds**=*creds* diff --git a/docs/source/markdown/podman-manifest-push.1.md b/docs/source/markdown/podman-manifest-push.1.md index 3a68f6228..a0011cea8 100644 --- a/docs/source/markdown/podman-manifest-push.1.md +++ b/docs/source/markdown/podman-manifest-push.1.md @@ -30,7 +30,7 @@ environment variable. `export REGISTRY_AUTH_FILE=path` #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--creds**=*creds* diff --git a/docs/source/markdown/podman-mount.1.md b/docs/source/markdown/podman-mount.1.md index 33524029c..82c7fe804 100644 --- a/docs/source/markdown/podman-mount.1.md +++ b/docs/source/markdown/podman-mount.1.md @@ -38,7 +38,7 @@ Print the mounted containers in specified format (json). 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) +started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--no-trunc** diff --git a/docs/source/markdown/podman-network-reload.1.md b/docs/source/markdown/podman-network-reload.1.md index f091c34dc..5cbe9b9bf 100644 --- a/docs/source/markdown/podman-network-reload.1.md +++ b/docs/source/markdown/podman-network-reload.1.md @@ -21,7 +21,7 @@ Reload network configuration of all containers. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index a056640e7..6d02af80d 100644 --- a/docs/source/markdown/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md @@ -40,7 +40,7 @@ A Kubernetes PersistentVolumeClaim represents a Podman named volume. Only the Pe - volume.podman.io/mount-options Play kube is capable of building images on the fly given the correct directory layout and Containerfiles. This -option is not available for remote clients yet. Consider the following excerpt from a YAML file: +option is not available for remote clients, including Mac and Windows (excluding WSL2) machines, yet. Consider the following excerpt from a YAML file: ``` apiVersion: v1 kind: Pod @@ -120,7 +120,7 @@ Build images even if they are found in the local storage. #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--configmap**=*path* @@ -215,7 +215,7 @@ Tears down the pods created by a previous run of `play kube` and recreates the p #### **--seccomp-profile-root**=*path* -Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (This option is not available with the remote Podman client) +Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--start** diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index e7eae2aa2..58d3b9d44 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -317,7 +317,7 @@ Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman container. Similarly, `-v SOURCE-VOLUME:/CONTAINER-DIR` will mount the volume in the host to the container. If no such named volume exists, Podman will -create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarily the client machine.) +create one. The `OPTIONS` are a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, including Mac and Windows (excluding WSL2) machines, the volumes will be mounted from the remote server, not necessarily the client machine.) The _options_ is a comma-separated list and can be: diff --git a/docs/source/markdown/podman-pod-inspect.1.md b/docs/source/markdown/podman-pod-inspect.1.md index 5147a2559..75b422306 100644 --- a/docs/source/markdown/podman-pod-inspect.1.md +++ b/docs/source/markdown/podman-pod-inspect.1.md @@ -14,7 +14,7 @@ that belong to the pod. #### **--latest**, **-l** Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman -to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client) +to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--format**=*format*, **-f** diff --git a/docs/source/markdown/podman-pod-kill.1.md b/docs/source/markdown/podman-pod-kill.1.md index 973d8da88..45b61c620 100644 --- a/docs/source/markdown/podman-pod-kill.1.md +++ b/docs/source/markdown/podman-pod-kill.1.md @@ -17,7 +17,7 @@ Sends signal to all containers associated with a pod. #### **--latest**, **-l** Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman -to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client) +to run pods such as CRI-O, the last started pod could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--signal**, **-s** diff --git a/docs/source/markdown/podman-pod-logs.1.md b/docs/source/markdown/podman-pod-logs.1.md index bc38c33fd..53aa5d58b 100644 --- a/docs/source/markdown/podman-pod-logs.1.md +++ b/docs/source/markdown/podman-pod-logs.1.md @@ -26,7 +26,7 @@ chance that the log file will be removed before `podman pod logs` reads the fina #### **--latest**, **-l** -Instead of providing the pod name or id, get logs of the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or id, get logs of the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--since**=*TIMESTAMP* diff --git a/docs/source/markdown/podman-pod-pause.1.md b/docs/source/markdown/podman-pod-pause.1.md index 0e53b52be..1f29cb2ed 100644 --- a/docs/source/markdown/podman-pod-pause.1.md +++ b/docs/source/markdown/podman-pod-pause.1.md @@ -17,7 +17,7 @@ Pause all pods. #### **--latest**, **-l** -Instead of providing the pod name or ID, pause the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, pause the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md index b61f12e90..a0581df50 100644 --- a/docs/source/markdown/podman-pod-ps.1.md +++ b/docs/source/markdown/podman-pod-ps.1.md @@ -42,7 +42,7 @@ Display the container statuses #### **--latest**, **-l** -Show the latest pod created (all states) (This option is not available with the remote Podman client) +Show the latest pod created (all states) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--noheading** diff --git a/docs/source/markdown/podman-pod-restart.1.md b/docs/source/markdown/podman-pod-restart.1.md index c63daa419..677eca3a3 100644 --- a/docs/source/markdown/podman-pod-restart.1.md +++ b/docs/source/markdown/podman-pod-restart.1.md @@ -20,7 +20,7 @@ Restarts all pods #### **--latest**, **-l** -Instead of providing the pod name or ID, restart the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, restart the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-pod-rm.1.md b/docs/source/markdown/podman-pod-rm.1.md index 00c82a8f7..ed33c5e57 100644 --- a/docs/source/markdown/podman-pod-rm.1.md +++ b/docs/source/markdown/podman-pod-rm.1.md @@ -23,7 +23,7 @@ ExecStop directive of a systemd service referencing that pod. #### **--latest**, **-l** -Instead of providing the pod name or ID, remove the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, remove the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--force**, **-f** diff --git a/docs/source/markdown/podman-pod-start.1.md b/docs/source/markdown/podman-pod-start.1.md index 7f3adc8ff..bab109212 100644 --- a/docs/source/markdown/podman-pod-start.1.md +++ b/docs/source/markdown/podman-pod-start.1.md @@ -18,7 +18,7 @@ Starts all pods #### **--latest**, **-l** -Instead of providing the pod name or ID, start the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, start the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--pod-id-file** diff --git a/docs/source/markdown/podman-pod-stats.1.md b/docs/source/markdown/podman-pod-stats.1.md index 47d95983a..460571add 100644 --- a/docs/source/markdown/podman-pod-stats.1.md +++ b/docs/source/markdown/podman-pod-stats.1.md @@ -17,7 +17,7 @@ Show all containers. Only running containers are shown by default #### **--latest**, **-l** -Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--no-reset** diff --git a/docs/source/markdown/podman-pod-stop.1.md b/docs/source/markdown/podman-pod-stop.1.md index f2887b5a5..13d86d1db 100644 --- a/docs/source/markdown/podman-pod-stop.1.md +++ b/docs/source/markdown/podman-pod-stop.1.md @@ -23,7 +23,7 @@ ExecStop directive of a systemd service referencing that pod. #### **--latest**, **-l** -Instead of providing the pod name or ID, stop the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, stop the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--time**, **-t**=*seconds* diff --git a/docs/source/markdown/podman-pod-top.1.md b/docs/source/markdown/podman-pod-top.1.md index 42198c7fa..3f4c24117 100644 --- a/docs/source/markdown/podman-pod-top.1.md +++ b/docs/source/markdown/podman-pod-top.1.md @@ -17,7 +17,7 @@ Display the running processes of containers in a pod. The *format-descriptors* a #### **--latest**, **-l** -Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, use the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) ## FORMAT DESCRIPTORS diff --git a/docs/source/markdown/podman-pod-unpause.1.md b/docs/source/markdown/podman-pod-unpause.1.md index cd91a661b..ce883af69 100644 --- a/docs/source/markdown/podman-pod-unpause.1.md +++ b/docs/source/markdown/podman-pod-unpause.1.md @@ -17,7 +17,7 @@ Unpause all pods. #### **--latest**, **-l** -Instead of providing the pod name or ID, unpause the last created pod. (This option is not available with the remote Podman client) +Instead of providing the pod name or ID, unpause the last created pod. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-port.1.md b/docs/source/markdown/podman-port.1.md index 2881cbb7b..a72fc12bf 100644 --- a/docs/source/markdown/podman-port.1.md +++ b/docs/source/markdown/podman-port.1.md @@ -21,7 +21,7 @@ or private ports/protocols as filters. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md index 827fb2b2f..5b142d283 100644 --- a/docs/source/markdown/podman-ps.1.md +++ b/docs/source/markdown/podman-ps.1.md @@ -94,7 +94,7 @@ Print the n last created containers (all states) #### **--latest**, **-l** -Show the latest container created (all states) (This option is not available with the remote Podman client) +Show the latest container created (all states) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--namespace**, **--ns** diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md index fe4af44d3..00a86aa71 100644 --- a/docs/source/markdown/podman-pull.1.md +++ b/docs/source/markdown/podman-pull.1.md @@ -17,7 +17,7 @@ podman pull copies an image from a registry onto the local machine. The command *IMPORTANT: Images are stored in local image storage.* ## SOURCE -SOURCE is the location from which the container image is pulled from. It supports all transports from **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport. +SOURCE is the location from which the container image is pulled from. It supports all transports from **[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md)**. If no transport is specified, the input is subject to short-name resolution and the `docker` (i.e., container registry) transport is used. For remote clients, including Mac and Windows (excluding WSL2) machines, `docker` is the only supported transport. ``` # Pull from a container registry @@ -63,7 +63,7 @@ Default is `${XDG\_RUNTIME\_DIR}/containers/auth.json`, which is set using `podm #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)** for details. (This option is not available with the remote Podman client) +Please refer to **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)** for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--creds**=*[username[:password]]* diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md index 19c64a7e3..c71eecfd2 100644 --- a/docs/source/markdown/podman-push.1.md +++ b/docs/source/markdown/podman-push.1.md @@ -20,7 +20,7 @@ Images are pushed from those stored in local image storage. ## DESTINATION - DESTINATION is the location the container image is pushed to. It supports all transports from `containers-transports(5)`. If no transport is specified, the `docker` (i.e., container registry) transport is used. For remote clients, `docker` is the only supported transport. + DESTINATION is the location the container image is pushed to. It supports all transports from `containers-transports(5)`. If no transport is specified, the `docker` (i.e., container registry) transport is used. For remote clients, including Mac and Windows (excluding WSL2) machines, `docker` is the only supported transport. ``` # Push to a container registry @@ -64,7 +64,7 @@ value can be entered. The password is entered without echo. #### **--cert-dir**=*path* Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry. (Default: /etc/containers/certs.d) -Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client) +Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--compress** @@ -77,7 +77,7 @@ Specifies the compression format to use. Supported values are: `gzip`, `zstd` a #### **--digestfile** *Digestfile* -After copying the image, write the digest of the resulting image to the file. (This option is not available with the remote Podman client) +After copying the image, write the digest of the resulting image to the file. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--disable-content-trust** @@ -95,11 +95,11 @@ When writing the output image, suppress progress output #### **--remove-signatures** -Discard any pre-existing signatures in the image. (This option is not available with the remote Podman client) +Discard any pre-existing signatures in the image. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--sign-by**=*key* -Add a signature at the destination using the specified key. (This option is not available with the remote Podman client) +Add a signature at the destination using the specified key. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--tls-verify** diff --git a/docs/source/markdown/podman-restart.1.md b/docs/source/markdown/podman-restart.1.md index bb8f13a92..323087069 100644 --- a/docs/source/markdown/podman-restart.1.md +++ b/docs/source/markdown/podman-restart.1.md @@ -19,7 +19,7 @@ Restart all containers regardless of their current state. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--running** Restart all containers that are already in the *running* state. diff --git a/docs/source/markdown/podman-rm.1.md b/docs/source/markdown/podman-rm.1.md index f3807d2f7..23944270c 100644 --- a/docs/source/markdown/podman-rm.1.md +++ b/docs/source/markdown/podman-rm.1.md @@ -43,7 +43,7 @@ during the ExecStop directive of a systemd service referencing that container. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--time**, **-t**=*seconds* diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 014b50c6c..239cf3b83 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -43,7 +43,7 @@ pages. ## IMAGE The image is specified using transport:path format. If no transport is specified, the `docker` (container registry) -transport will be used by default. For remote Podman, `docker` is the only allowed transport. +transport will be used by default. For remote Podman, including Mac and Windows (excluding WSL2) machines, `docker` is the only allowed transport. **dir:**_path_ An existing local directory _path_ storing the manifest, layer tarballs and signatures as individual files. This @@ -167,7 +167,7 @@ Write the container ID to *file*. #### **--conmon-pidfile**=*file* Write the pid of the **conmon** process to a file. As **conmon** runs in a separate process than Podman, this is necessary when using systemd to restart Podman containers. -(This option is not available with the remote Podman client) +(This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--cpu-period**=*limit* @@ -383,7 +383,7 @@ See [**Environment**](#environment) note below for precedence and examples. #### **--env-host** -Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client) +Use host environment inside of the container. See **Environment** note below for precedence. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--env-file**=*file* @@ -419,7 +419,7 @@ Allows container to use the user's supplementary group access. If file systems o devices are only accessible by the rootless user's group, this flag tells the OCI runtime to pass the group access into the container. Currently only available with the `crun` OCI runtime. Note: `keep-groups` is exclusive, you cannot add any other groups -with this flag. (Not available for remote commands) +with this flag. (Not available for remote commands, including Mac and Windows (excluding WSL2) machines) #### **--health-cmd**=*"command"* | *'["command", "arg1", ...]'* @@ -474,7 +474,7 @@ the container should not use any proxy. Proxy environment variables specified for the container in any other way will override the values that would have been passed through from the host. (Other ways to specify the proxy for the container include passing the values with the **--env** flag, or hard coding the -proxy environment at container build time.) (This option is not available with the remote Podman client) +proxy environment at container build time.) (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) Defaults to **true**. @@ -548,7 +548,7 @@ $ podman info --format '{{ .Host.LogDriver }}' journald ``` The **passthrough** driver passes down the standard streams (stdin, stdout, stderr) to the -container. It is not allowed with the remote Podman client and on a tty, since it is +container. It is not allowed with the remote Podman client, including Mac and Windows (excluding WSL2) machines, and on a tty, since it is vulnerable to attacks via TIOCSTI. @@ -818,7 +818,7 @@ If a container is run within a pod, and the pod has an infra-container, the infr #### **--preserve-fds**=*N* Pass down to the process N additional file descriptors (in addition to 0, 1, 2). -The total FDs will be 3+N. (This option is not available with the remote Podman client) +The total FDs will be 3+N. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) #### **--privileged** @@ -1309,7 +1309,7 @@ Create a bind mount. If you specify _/HOST-DIR_:_/CONTAINER-DIR_, Podman bind mounts _host-dir_ in the host to _CONTAINER-DIR_ in the Podman container. Similarly, _SOURCE-VOLUME_:_/CONTAINER-DIR_ will mount the volume in the host to the container. If no such named volume exists, Podman will -create one. (Note when using the remote client, the volumes will be mounted from the remote server, not necessarily the client machine.) +create one. (Note when using the remote client, including Mac and Windows (excluding WSL2) machines, the volumes will be mounted from the remote server, not necessarily the client machine.) The _options_ is a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup> @@ -1521,7 +1521,7 @@ can override the working directory by using the **-w** option. #### **--pidfile**=*path* -When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client) +When the pidfile location is specified, the container process' PID will be written to the pidfile. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) If the pidfile option is not specified, the container process' PID will be written to /run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile. After the container is started, the location for the pidfile can be discovered with the following `podman inspect` command: diff --git a/docs/source/markdown/podman-start.1.md b/docs/source/markdown/podman-start.1.md index b8ed181e0..793f27aa4 100644 --- a/docs/source/markdown/podman-start.1.md +++ b/docs/source/markdown/podman-start.1.md @@ -32,7 +32,7 @@ Attach container's STDIN. The default is false. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--sig-proxy** diff --git a/docs/source/markdown/podman-stats.1.md b/docs/source/markdown/podman-stats.1.md index 1b04c371e..a1a156b10 100644 --- a/docs/source/markdown/podman-stats.1.md +++ b/docs/source/markdown/podman-stats.1.md @@ -27,7 +27,7 @@ Show all containers. Only running containers are shown by default #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--no-reset** diff --git a/docs/source/markdown/podman-stop.1.md b/docs/source/markdown/podman-stop.1.md index 9a852cbae..e35ab9182 100644 --- a/docs/source/markdown/podman-stop.1.md +++ b/docs/source/markdown/podman-stop.1.md @@ -34,7 +34,7 @@ during the ExecStop directive of a systemd service referencing that container. #### **--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) +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, including Mac and Windows (excluding WSL2) machines) #### **--time**, **-t**=*seconds* diff --git a/docs/source/markdown/podman-top.1.md b/docs/source/markdown/podman-top.1.md index d385cde28..6b9433b89 100644 --- a/docs/source/markdown/podman-top.1.md +++ b/docs/source/markdown/podman-top.1.md @@ -20,7 +20,7 @@ Print usage statement #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## FORMAT DESCRIPTORS diff --git a/docs/source/markdown/podman-unmount.1.md b/docs/source/markdown/podman-unmount.1.md index 045ea5456..692b1e495 100644 --- a/docs/source/markdown/podman-unmount.1.md +++ b/docs/source/markdown/podman-unmount.1.md @@ -43,7 +43,7 @@ as the mount point could be removed without their knowledge. 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) +started container could be from either of those methods. (This option is not available with the remote Podman client, including Mac and Windows (excluding WSL2) machines) ## EXAMPLE diff --git a/docs/source/markdown/podman-wait.1.md b/docs/source/markdown/podman-wait.1.md index 7ee53c57e..e307e4528 100644 --- a/docs/source/markdown/podman-wait.1.md +++ b/docs/source/markdown/podman-wait.1.md @@ -29,7 +29,7 @@ Condition to wait on (default "stopped") #### **--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) +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, including Mac and Windows (excluding WSL2) machines) ## EXAMPLES diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index 0fe30bf0f..ee2783054 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -41,7 +41,7 @@ For the netavark backend "/etc/containers/networks" is used as root and "$graphroot/networks" as rootless. #### **--connection**, **-c** -Connection to use for remote podman (Default connection is configured in `containers.conf`) +Connection to use for remote podman, including Mac and Windows (excluding WSL2) machines, (Default connection is configured in `containers.conf`) Remote connections use local containers.conf for default. #### **--conmon** @@ -167,7 +167,7 @@ Storage driver option, Default storage driver options are configured in /etc/con Output logging information to syslog as well as the console (default *false*). -On remote clients, logging is directed to the file $HOME/.config/containers/podman.log. +On remote clients, including Mac and Windows (excluding WSL2) machines, logging is directed to the file $HOME/.config/containers/podman.log. #### **--tmpdir** diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 5cc2a78fc..86d8586d0 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -510,6 +510,9 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { if c.IsReadOnly() && dstPath != "/dev/shm" { newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev") } + if dstPath == "/dev/shm" && c.state.BindMounts["/dev/shm"] == c.config.ShmDir { + newMount.Options = append(newMount.Options, "nosuid", "noexec", "nodev") + } if !MountExists(g.Mounts(), dstPath) { g.AddMount(newMount) } else { @@ -1570,6 +1573,9 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if c.IsReadOnly() && dstPath != "/dev/shm" { newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev") } + if dstPath == "/dev/shm" && c.state.BindMounts["/dev/shm"] == c.config.ShmDir { + newMount.Options = append(newMount.Options, "nosuid", "noexec", "nodev") + } if !MountExists(g.Mounts(), dstPath) { g.AddMount(newMount) } diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 86a60e92d..cad8c4609 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -365,6 +365,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY if err != nil { return nil, err } + + for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels + labels[k] = v + } + specgenOpts := kube.CtrSpecGenOptions{ Annotations: annotations, Container: initCtr, @@ -405,7 +410,12 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY return nil, err } + for k, v := range podSpec.PodSpecGen.Labels { // add podYAML labels + labels[k] = v + } + specgenOpts := kube.CtrSpecGenOptions{ + Annotations: annotations, Container: container, Image: pulledImage, Volumes: volumes, diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 2fd149b49..beaec1135 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net" + "regexp" "strings" "time" @@ -291,9 +292,9 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener return nil, err } - // Only set the env if the value is not "" - if value != "" { - envs[env.Name] = value + // Only set the env if the value is not nil + if value != nil { + envs[env.Name] = *value } } for _, envFrom := range opts.Container.EnvFrom { @@ -609,7 +610,7 @@ func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) (map[string] // envVarValue returns the environment variable value configured within the container's env setting. // It gets the value from a configMap or secret if specified, otherwise returns env.Value -func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) { +func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) { if env.ValueFrom != nil { if env.ValueFrom.ConfigMapKeyRef != nil { cmKeyRef := env.ValueFrom.ConfigMapKeyRef @@ -618,16 +619,16 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) { for _, c := range opts.ConfigMaps { if cmKeyRef.Name == c.Name { if value, ok := c.Data[cmKeyRef.Key]; ok { - return value, nil + return &value, nil } err = errors.Errorf("Cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name) break } } if cmKeyRef.Optional == nil || !*cmKeyRef.Optional { - return "", err + return nil, err } - return "", nil + return nil, nil } if env.ValueFrom.SecretKeyRef != nil { @@ -635,18 +636,56 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (string, error) { secret, err := k8sSecretFromSecretManager(secKeyRef.Name, opts.SecretsManager) if err == nil { if val, ok := secret[secKeyRef.Key]; ok { - return string(val), nil + value := string(val) + return &value, nil } err = errors.Errorf("Secret %v has not %v key", secKeyRef.Name, secKeyRef.Key) } if secKeyRef.Optional == nil || !*secKeyRef.Optional { - return "", errors.Errorf("Cannot set env %v: %v", env.Name, err) + return nil, errors.Errorf("Cannot set env %v: %v", env.Name, err) } - return "", nil + return nil, nil + } + + if env.ValueFrom.FieldRef != nil { + return envVarValueFieldRef(env, opts) } } - return env.Value, nil + return &env.Value, nil +} + +func envVarValueFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) { + fieldRef := env.ValueFrom.FieldRef + + fieldPathLabelPattern := `^metadata.labels\['(.+)'\]$` + fieldPathLabelRegex := regexp.MustCompile(fieldPathLabelPattern) + fieldPathAnnotationPattern := `^metadata.annotations\['(.+)'\]$` + fieldPathAnnotationRegex := regexp.MustCompile(fieldPathAnnotationPattern) + + fieldPath := fieldRef.FieldPath + + if fieldPath == "metadata.name" { + return &opts.PodName, nil + } + if fieldPath == "metadata.uid" { + return &opts.PodID, nil + } + fieldPathMatches := fieldPathLabelRegex.FindStringSubmatch(fieldPath) + if len(fieldPathMatches) == 2 { // 1 for entire regex and 1 for subexp + labelValue := opts.Labels[fieldPathMatches[1]] // not existent label is OK + return &labelValue, nil + } + fieldPathMatches = fieldPathAnnotationRegex.FindStringSubmatch(fieldPath) + if len(fieldPathMatches) == 2 { // 1 for entire regex and 1 for subexp + annotationValue := opts.Annotations[fieldPathMatches[1]] // not existent annotation is OK + return &annotationValue, nil + } + + return nil, errors.Errorf( + "Can not set env %v. Reason: fieldPath %v is either not valid or not supported", + env.Name, fieldPath, + ) } // getPodPorts converts a slice of kube container descriptions to an diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go index f714826f0..2ac268c79 100644 --- a/pkg/specgen/generate/kube/play_test.go +++ b/pkg/specgen/generate/kube/play_test.go @@ -189,13 +189,15 @@ func TestEnvVarValue(t *testing.T) { assert.NoError(t, err) defer os.RemoveAll(d) secretsManager := createSecrets(t, d) + value := "foo" + emptyValue := "" tests := []struct { name string envVar v1.EnvVar options CtrSpecGenOptions succeed bool - expected string + expected *string }{ { "ConfigMapExists", @@ -214,7 +216,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: configMapList, }, true, - "foo", + &value, }, { "ContainerKeyDoesNotExistInConfigMap", @@ -233,7 +235,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: configMapList, }, false, - "", + nil, }, { "OptionalContainerKeyDoesNotExistInConfigMap", @@ -253,7 +255,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: configMapList, }, true, - "", + nil, }, { "ConfigMapDoesNotExist", @@ -272,7 +274,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: configMapList, }, false, - "", + nil, }, { "OptionalConfigMapDoesNotExist", @@ -292,7 +294,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: configMapList, }, true, - "", + nil, }, { "EmptyConfigMapList", @@ -311,7 +313,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: []v1.ConfigMap{}, }, false, - "", + nil, }, { "OptionalEmptyConfigMapList", @@ -331,7 +333,7 @@ func TestEnvVarValue(t *testing.T) { ConfigMaps: []v1.ConfigMap{}, }, true, - "", + nil, }, { "SecretExists", @@ -350,7 +352,7 @@ func TestEnvVarValue(t *testing.T) { SecretsManager: secretsManager, }, true, - "foo", + &value, }, { "ContainerKeyDoesNotExistInSecret", @@ -369,7 +371,7 @@ func TestEnvVarValue(t *testing.T) { SecretsManager: secretsManager, }, false, - "", + nil, }, { "OptionalContainerKeyDoesNotExistInSecret", @@ -389,7 +391,7 @@ func TestEnvVarValue(t *testing.T) { SecretsManager: secretsManager, }, true, - "", + nil, }, { "SecretDoesNotExist", @@ -408,7 +410,7 @@ func TestEnvVarValue(t *testing.T) { SecretsManager: secretsManager, }, false, - "", + nil, }, { "OptionalSecretDoesNotExist", @@ -428,7 +430,173 @@ func TestEnvVarValue(t *testing.T) { SecretsManager: secretsManager, }, true, - "", + nil, + }, + { + "FieldRefMetadataName", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.name", + }, + }, + }, + CtrSpecGenOptions{ + PodName: value, + }, + true, + &value, + }, + { + "FieldRefMetadataUID", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.uid", + }, + }, + }, + CtrSpecGenOptions{ + PodID: value, + }, + true, + &value, + }, + { + "FieldRefMetadataLabelsExist", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.labels['label']", + }, + }, + }, + CtrSpecGenOptions{ + Labels: map[string]string{"label": value}, + }, + true, + &value, + }, + { + "FieldRefMetadataLabelsEmpty", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.labels['label']", + }, + }, + }, + CtrSpecGenOptions{ + Labels: map[string]string{"label": ""}, + }, + true, + &emptyValue, + }, + { + "FieldRefMetadataLabelsNotExist", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.labels['label']", + }, + }, + }, + CtrSpecGenOptions{}, + true, + &emptyValue, + }, + { + "FieldRefMetadataAnnotationsExist", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.annotations['annotation']", + }, + }, + }, + CtrSpecGenOptions{ + Annotations: map[string]string{"annotation": value}, + }, + true, + &value, + }, + { + "FieldRefMetadataAnnotationsEmpty", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.annotations['annotation']", + }, + }, + }, + CtrSpecGenOptions{ + Annotations: map[string]string{"annotation": ""}, + }, + true, + &emptyValue, + }, + { + "FieldRefMetadataAnnotationsNotExist", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.annotations['annotation']", + }, + }, + }, + CtrSpecGenOptions{}, + true, + &emptyValue, + }, + { + "FieldRefInvalid1", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.annotations['annotation]", + }, + }, + }, + CtrSpecGenOptions{}, + false, + nil, + }, + { + "FieldRefInvalid2", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.dummy['annotation']", + }, + }, + }, + CtrSpecGenOptions{}, + false, + nil, + }, + { + "FieldRefNotSupported", + v1.EnvVar{ + Name: "FOO", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }, + CtrSpecGenOptions{}, + false, + nil, }, } diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 8ca7ce4e6..17699a038 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -19,6 +19,7 @@ import ( "github.com/containers/podman/v4/pkg/specgen" systemdDefine "github.com/containers/podman/v4/pkg/systemd/define" "github.com/containers/podman/v4/pkg/util" + "github.com/docker/docker/opts" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -422,11 +423,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions // SHM Size if c.ShmSize != "" { - shmSize, err := units.FromHumanSize(c.ShmSize) - if err != nil { + var m opts.MemBytes + if err := m.Set(c.ShmSize); err != nil { return errors.Wrapf(err, "unable to translate --shm-size") } - s.ShmSize = &shmSize + val := m.Value() + s.ShmSize = &val } if c.Net != nil { diff --git a/podman.spec.rpkg b/podman.spec.rpkg index 4068b3a81..d02b7ea99 100644 --- a/podman.spec.rpkg +++ b/podman.spec.rpkg @@ -77,12 +77,15 @@ BuildRequires: ostree-devel BuildRequires: systemd BuildRequires: systemd-devel Requires: conmon >= 2:2.0.30-2 -Requires: containers-common >= 4:1-30 -Requires: containernetworking-plugins >= 1.0.0-15.1 +# containers-common pulled from podman-next copr for f34, +# from the distro repos for f35+ +%if 0%{?fedora} <= 35 +Requires: containers-common >= 4:1-39 +%else +Requires: containers-common >= 4:1-46 +%endif Requires: iptables Requires: nftables -Requires: netavark -Recommends: %{name}-plugins = %{epoch}:%{version}-%{release} Recommends: catatonit Suggests: qemu-user-static diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go index a23983623..bfed01854 100644 --- a/test/e2e/containers_conf_test.go +++ b/test/e2e/containers_conf_test.go @@ -84,6 +84,11 @@ var _ = Describe("Verify podman containers.conf usage", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("size=200k")) + + session = podmanTest.Podman([]string{"run", "--shm-size", "1g", ALPINE, "grep", "shm", "/proc/self/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("size=1048576k")) }) It("add capabilities", func() { diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index cbaa8d6a4..b5e64fcbc 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -2984,7 +2984,7 @@ invalid kube kind inspect = podmanTest.Podman([]string{"inspect", podName + "-" + ctr02Name, "--format", "'{{.Config.Labels}}'"}) inspect.WaitWithDefaultTimeout() Expect(inspect).Should(Exit(0)) - Expect(inspect.OutputToString()).To(ContainSubstring(`map[]`)) + Expect(inspect.OutputToString()).NotTo(ContainSubstring(autoUpdateRegistry + ":" + autoUpdateRegistryValue)) }) It("podman play kube teardown", func() { diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 62a454e29..91a2eddad 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1926,4 +1926,14 @@ WORKDIR /madethis`, BB) Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("i686")) }) + + It("podman run /dev/shm has nosuid,noexec,nodev", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "grep", "/dev/shm", "/proc/self/mountinfo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + output := session.OutputToString() + Expect(output).To(ContainSubstring("nosuid")) + Expect(output).To(ContainSubstring("noexec")) + Expect(output).To(ContainSubstring("nodev")) + }) }) diff --git a/vendor/github.com/docker/docker/opts/address_pools.go b/vendor/github.com/docker/docker/opts/address_pools.go new file mode 100644 index 000000000..fa15c24b9 --- /dev/null +++ b/vendor/github.com/docker/docker/opts/address_pools.go @@ -0,0 +1,84 @@ +package opts + +import ( + "encoding/csv" + "encoding/json" + "fmt" + "strconv" + "strings" + + types "github.com/docker/libnetwork/ipamutils" +) + +// PoolsOpt is a Value type for parsing the default address pools definitions +type PoolsOpt struct { + Values []*types.NetworkToSplit +} + +// UnmarshalJSON fills values structure info from JSON input +func (p *PoolsOpt) UnmarshalJSON(raw []byte) error { + return json.Unmarshal(raw, &(p.Values)) +} + +// Set predefined pools +func (p *PoolsOpt) Set(value string) error { + csvReader := csv.NewReader(strings.NewReader(value)) + fields, err := csvReader.Read() + if err != nil { + return err + } + + poolsDef := types.NetworkToSplit{} + + for _, field := range fields { + parts := strings.SplitN(field, "=", 2) + if len(parts) != 2 { + return fmt.Errorf("invalid field '%s' must be a key=value pair", field) + } + + key := strings.ToLower(parts[0]) + value := strings.ToLower(parts[1]) + + switch key { + case "base": + poolsDef.Base = value + case "size": + size, err := strconv.Atoi(value) + if err != nil { + return fmt.Errorf("invalid size value: %q (must be integer): %v", value, err) + } + poolsDef.Size = size + default: + return fmt.Errorf("unexpected key '%s' in '%s'", key, field) + } + } + + p.Values = append(p.Values, &poolsDef) + + return nil +} + +// Type returns the type of this option +func (p *PoolsOpt) Type() string { + return "pool-options" +} + +// String returns a string repr of this option +func (p *PoolsOpt) String() string { + var pools []string + for _, pool := range p.Values { + repr := fmt.Sprintf("%s %d", pool.Base, pool.Size) + pools = append(pools, repr) + } + return strings.Join(pools, ", ") +} + +// Value returns the mounts +func (p *PoolsOpt) Value() []*types.NetworkToSplit { + return p.Values +} + +// Name returns the flag name of this option +func (p *PoolsOpt) Name() string { + return "default-address-pools" +} diff --git a/vendor/github.com/docker/docker/opts/env.go b/vendor/github.com/docker/docker/opts/env.go new file mode 100644 index 000000000..97e1a8c8a --- /dev/null +++ b/vendor/github.com/docker/docker/opts/env.go @@ -0,0 +1,30 @@ +package opts // import "github.com/docker/docker/opts" + +import ( + "os" + "strings" + + "github.com/pkg/errors" +) + +// ValidateEnv validates an environment variable and returns it. +// If no value is specified, it obtains its value from the current environment +// +// As on ParseEnvFile and related to #16585, environment variable names +// are not validate whatsoever, it's up to application inside docker +// to validate them or not. +// +// The only validation here is to check if name is empty, per #25099 +func ValidateEnv(val string) (string, error) { + arr := strings.SplitN(val, "=", 2) + if arr[0] == "" { + return "", errors.New("invalid environment variable: " + val) + } + if len(arr) > 1 { + return val, nil + } + if envVal, ok := os.LookupEnv(arr[0]); ok { + return arr[0] + "=" + envVal, nil + } + return val, nil +} diff --git a/vendor/github.com/docker/docker/opts/hosts.go b/vendor/github.com/docker/docker/opts/hosts.go new file mode 100644 index 000000000..a3123adef --- /dev/null +++ b/vendor/github.com/docker/docker/opts/hosts.go @@ -0,0 +1,183 @@ +package opts // import "github.com/docker/docker/opts" + +import ( + "fmt" + "net" + "net/url" + "path/filepath" + "strconv" + "strings" + + "github.com/docker/docker/pkg/homedir" +) + +const ( + // DefaultHTTPPort Default HTTP Port used if only the protocol is provided to -H flag e.g. dockerd -H tcp:// + // These are the IANA registered port numbers for use with Docker + // see http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=docker + DefaultHTTPPort = 2375 // Default HTTP Port + // DefaultTLSHTTPPort Default HTTP Port used when TLS enabled + DefaultTLSHTTPPort = 2376 // Default TLS encrypted HTTP Port + // DefaultUnixSocket Path for the unix socket. + // Docker daemon by default always listens on the default unix socket + DefaultUnixSocket = "/var/run/docker.sock" + // DefaultTCPHost constant defines the default host string used by docker on Windows + DefaultTCPHost = "tcp://" + DefaultHTTPHost + ":2375" + // DefaultTLSHost constant defines the default host string used by docker for TLS sockets + DefaultTLSHost = "tcp://" + DefaultHTTPHost + ":2376" + // DefaultNamedPipe defines the default named pipe used by docker on Windows + DefaultNamedPipe = `//./pipe/docker_engine` + // HostGatewayName is the string value that can be passed + // to the IPAddr section in --add-host that is replaced by + // the value of HostGatewayIP daemon config value + HostGatewayName = "host-gateway" +) + +// ValidateHost validates that the specified string is a valid host and returns it. +func ValidateHost(val string) (string, error) { + host := strings.TrimSpace(val) + // The empty string means default and is not handled by parseDaemonHost + if host != "" { + _, err := parseDaemonHost(host) + if err != nil { + return val, err + } + } + // Note: unlike most flag validators, we don't return the mutated value here + // we need to know what the user entered later (using ParseHost) to adjust for TLS + return val, nil +} + +// ParseHost and set defaults for a Daemon host string. +// defaultToTLS is preferred over defaultToUnixXDG. +func ParseHost(defaultToTLS, defaultToUnixXDG bool, val string) (string, error) { + host := strings.TrimSpace(val) + if host == "" { + if defaultToTLS { + host = DefaultTLSHost + } else if defaultToUnixXDG { + runtimeDir, err := homedir.GetRuntimeDir() + if err != nil { + return "", err + } + socket := filepath.Join(runtimeDir, "docker.sock") + host = "unix://" + socket + } else { + host = DefaultHost + } + } else { + var err error + host, err = parseDaemonHost(host) + if err != nil { + return val, err + } + } + return host, nil +} + +// parseDaemonHost parses the specified address and returns an address that will be used as the host. +// Depending of the address specified, this may return one of the global Default* strings defined in hosts.go. +func parseDaemonHost(addr string) (string, error) { + addrParts := strings.SplitN(addr, "://", 2) + if len(addrParts) == 1 && addrParts[0] != "" { + addrParts = []string{"tcp", addrParts[0]} + } + + switch addrParts[0] { + case "tcp": + return ParseTCPAddr(addrParts[1], DefaultTCPHost) + case "unix": + return parseSimpleProtoAddr("unix", addrParts[1], DefaultUnixSocket) + case "npipe": + return parseSimpleProtoAddr("npipe", addrParts[1], DefaultNamedPipe) + case "fd": + return addr, nil + default: + return "", fmt.Errorf("Invalid bind address format: %s", addr) + } +} + +// parseSimpleProtoAddr parses and validates that the specified address is a valid +// socket address for simple protocols like unix and npipe. It returns a formatted +// socket address, either using the address parsed from addr, or the contents of +// defaultAddr if addr is a blank string. +func parseSimpleProtoAddr(proto, addr, defaultAddr string) (string, error) { + addr = strings.TrimPrefix(addr, proto+"://") + if strings.Contains(addr, "://") { + return "", fmt.Errorf("Invalid proto, expected %s: %s", proto, addr) + } + if addr == "" { + addr = defaultAddr + } + return fmt.Sprintf("%s://%s", proto, addr), nil +} + +// ParseTCPAddr parses and validates that the specified address is a valid TCP +// address. It returns a formatted TCP address, either using the address parsed +// from tryAddr, or the contents of defaultAddr if tryAddr is a blank string. +// tryAddr is expected to have already been Trim()'d +// defaultAddr must be in the full `tcp://host:port` form +func ParseTCPAddr(tryAddr string, defaultAddr string) (string, error) { + if tryAddr == "" || tryAddr == "tcp://" { + return defaultAddr, nil + } + addr := strings.TrimPrefix(tryAddr, "tcp://") + if strings.Contains(addr, "://") || addr == "" { + return "", fmt.Errorf("Invalid proto, expected tcp: %s", tryAddr) + } + + defaultAddr = strings.TrimPrefix(defaultAddr, "tcp://") + defaultHost, defaultPort, err := net.SplitHostPort(defaultAddr) + if err != nil { + return "", err + } + // url.Parse fails for trailing colon on IPv6 brackets on Go 1.5, but + // not 1.4. See https://github.com/golang/go/issues/12200 and + // https://github.com/golang/go/issues/6530. + if strings.HasSuffix(addr, "]:") { + addr += defaultPort + } + + u, err := url.Parse("tcp://" + addr) + if err != nil { + return "", err + } + host, port, err := net.SplitHostPort(u.Host) + if err != nil { + // try port addition once + host, port, err = net.SplitHostPort(net.JoinHostPort(u.Host, defaultPort)) + } + if err != nil { + return "", fmt.Errorf("Invalid bind address format: %s", tryAddr) + } + + if host == "" { + host = defaultHost + } + if port == "" { + port = defaultPort + } + p, err := strconv.Atoi(port) + if err != nil && p == 0 { + return "", fmt.Errorf("Invalid bind address format: %s", tryAddr) + } + + return fmt.Sprintf("tcp://%s%s", net.JoinHostPort(host, port), u.Path), nil +} + +// ValidateExtraHost validates that the specified string is a valid extrahost and returns it. +// ExtraHost is in the form of name:ip where the ip has to be a valid ip (IPv4 or IPv6). +func ValidateExtraHost(val string) (string, error) { + // allow for IPv6 addresses in extra hosts by only splitting on first ":" + arr := strings.SplitN(val, ":", 2) + if len(arr) != 2 || len(arr[0]) == 0 { + return "", fmt.Errorf("bad format for add-host: %q", val) + } + // Skip IPaddr validation for special "host-gateway" string + if arr[1] != HostGatewayName { + if _, err := ValidateIPAddress(arr[1]); err != nil { + return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1]) + } + } + return val, nil +} diff --git a/vendor/github.com/docker/docker/opts/hosts_unix.go b/vendor/github.com/docker/docker/opts/hosts_unix.go new file mode 100644 index 000000000..29864194a --- /dev/null +++ b/vendor/github.com/docker/docker/opts/hosts_unix.go @@ -0,0 +1,11 @@ +// +build !windows + +package opts // import "github.com/docker/docker/opts" + +const ( + // DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 + DefaultHTTPHost = "localhost" + + // DefaultHost constant defines the default host string used by docker on other hosts than Windows + DefaultHost = "unix://" + DefaultUnixSocket +) diff --git a/vendor/github.com/docker/docker/opts/hosts_windows.go b/vendor/github.com/docker/docker/opts/hosts_windows.go new file mode 100644 index 000000000..576236ba4 --- /dev/null +++ b/vendor/github.com/docker/docker/opts/hosts_windows.go @@ -0,0 +1,60 @@ +package opts // import "github.com/docker/docker/opts" + +const ( + // TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5. + // + // On Windows, this mitigates a problem with the default options of running + // a docker client against a local docker daemon on TP5. + // + // What was found that if the default host is "localhost", even if the client + // (and daemon as this is local) is not physically on a network, and the DNS + // cache is flushed (ipconfig /flushdns), then the client will pause for + // exactly one second when connecting to the daemon for calls. For example + // using docker run windowsservercore cmd, the CLI will send a create followed + // by an attach. You see the delay between the attach finishing and the attach + // being seen by the daemon. + // + // Here's some daemon debug logs with additional debug spew put in. The + // AfterWriteJSON log is the very last thing the daemon does as part of the + // create call. The POST /attach is the second CLI call. Notice the second + // time gap. + // + // time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs" + // time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig" + // time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...." + // time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking.... + // time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...." + // time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...." + // time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func" + // time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create" + // time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2" + // time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate" + // time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON" + // ... 1 second gap here.... + // time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach" + // time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1" + // + // We suspect this is either a bug introduced in GOLang 1.5.1, or that a change + // in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory, + // the Windows networking stack is supposed to resolve "localhost" internally, + // without hitting DNS, or even reading the hosts file (which is why localhost + // is commented out in the hosts file on Windows). + // + // We have validated that working around this using the actual IPv4 localhost + // address does not cause the delay. + // + // This does not occur with the docker client built with 1.4.3 on the same + // Windows build, regardless of whether the daemon is built using 1.5.1 + // or 1.4.3. It does not occur on Linux. We also verified we see the same thing + // on a cross-compiled Windows binary (from Linux). + // + // Final note: This is a mitigation, not a 'real' fix. It is still susceptible + // to the delay if a user were to do 'docker run -H=tcp://localhost:2375...' + // explicitly. + + // DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. dockerd -H tcp://:8080 + DefaultHTTPHost = "127.0.0.1" + + // DefaultHost constant defines the default host string used by docker on Windows + DefaultHost = "npipe://" + DefaultNamedPipe +) diff --git a/vendor/github.com/docker/docker/opts/ip.go b/vendor/github.com/docker/docker/opts/ip.go new file mode 100644 index 000000000..cfbff3a9f --- /dev/null +++ b/vendor/github.com/docker/docker/opts/ip.go @@ -0,0 +1,47 @@ +package opts // import "github.com/docker/docker/opts" + +import ( + "fmt" + "net" +) + +// IPOpt holds an IP. It is used to store values from CLI flags. +type IPOpt struct { + *net.IP +} + +// NewIPOpt creates a new IPOpt from a reference net.IP and a +// string representation of an IP. If the string is not a valid +// IP it will fallback to the specified reference. +func NewIPOpt(ref *net.IP, defaultVal string) *IPOpt { + o := &IPOpt{ + IP: ref, + } + o.Set(defaultVal) + return o +} + +// Set sets an IPv4 or IPv6 address from a given string. If the given +// string is not parsable as an IP address it returns an error. +func (o *IPOpt) Set(val string) error { + ip := net.ParseIP(val) + if ip == nil { + return fmt.Errorf("%s is not an ip address", val) + } + *o.IP = ip + return nil +} + +// String returns the IP address stored in the IPOpt. If stored IP is a +// nil pointer, it returns an empty string. +func (o *IPOpt) String() string { + if *o.IP == nil { + return "" + } + return o.IP.String() +} + +// Type returns the type of the option +func (o *IPOpt) Type() string { + return "ip" +} diff --git a/vendor/github.com/docker/docker/opts/opts.go b/vendor/github.com/docker/docker/opts/opts.go new file mode 100644 index 000000000..60a093f28 --- /dev/null +++ b/vendor/github.com/docker/docker/opts/opts.go @@ -0,0 +1,348 @@ +package opts // import "github.com/docker/docker/opts" + +import ( + "fmt" + "net" + "path" + "regexp" + "strings" + + units "github.com/docker/go-units" +) + +var ( + alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) + domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`) +) + +// ListOpts holds a list of values and a validation function. +type ListOpts struct { + values *[]string + validator ValidatorFctType +} + +// NewListOpts creates a new ListOpts with the specified validator. +func NewListOpts(validator ValidatorFctType) ListOpts { + var values []string + return *NewListOptsRef(&values, validator) +} + +// NewListOptsRef creates a new ListOpts with the specified values and validator. +func NewListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts { + return &ListOpts{ + values: values, + validator: validator, + } +} + +func (opts *ListOpts) String() string { + if len(*opts.values) == 0 { + return "" + } + return fmt.Sprintf("%v", *opts.values) +} + +// Set validates if needed the input value and adds it to the +// internal slice. +func (opts *ListOpts) Set(value string) error { + if opts.validator != nil { + v, err := opts.validator(value) + if err != nil { + return err + } + value = v + } + *opts.values = append(*opts.values, value) + return nil +} + +// Delete removes the specified element from the slice. +func (opts *ListOpts) Delete(key string) { + for i, k := range *opts.values { + if k == key { + *opts.values = append((*opts.values)[:i], (*opts.values)[i+1:]...) + return + } + } +} + +// GetMap returns the content of values in a map in order to avoid +// duplicates. +func (opts *ListOpts) GetMap() map[string]struct{} { + ret := make(map[string]struct{}) + for _, k := range *opts.values { + ret[k] = struct{}{} + } + return ret +} + +// GetAll returns the values of slice. +func (opts *ListOpts) GetAll() []string { + return *opts.values +} + +// GetAllOrEmpty returns the values of the slice +// or an empty slice when there are no values. +func (opts *ListOpts) GetAllOrEmpty() []string { + v := *opts.values + if v == nil { + return make([]string, 0) + } + return v +} + +// Get checks the existence of the specified key. +func (opts *ListOpts) Get(key string) bool { + for _, k := range *opts.values { + if k == key { + return true + } + } + return false +} + +// Len returns the amount of element in the slice. +func (opts *ListOpts) Len() int { + return len(*opts.values) +} + +// Type returns a string name for this Option type +func (opts *ListOpts) Type() string { + return "list" +} + +// WithValidator returns the ListOpts with validator set. +func (opts *ListOpts) WithValidator(validator ValidatorFctType) *ListOpts { + opts.validator = validator + return opts +} + +// NamedOption is an interface that list and map options +// with names implement. +type NamedOption interface { + Name() string +} + +// NamedListOpts is a ListOpts with a configuration name. +// This struct is useful to keep reference to the assigned +// field name in the internal configuration struct. +type NamedListOpts struct { + name string + ListOpts +} + +var _ NamedOption = &NamedListOpts{} + +// NewNamedListOptsRef creates a reference to a new NamedListOpts struct. +func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts { + return &NamedListOpts{ + name: name, + ListOpts: *NewListOptsRef(values, validator), + } +} + +// Name returns the name of the NamedListOpts in the configuration. +func (o *NamedListOpts) Name() string { + return o.name +} + +// MapOpts holds a map of values and a validation function. +type MapOpts struct { + values map[string]string + validator ValidatorFctType +} + +// Set validates if needed the input value and add it to the +// internal map, by splitting on '='. +func (opts *MapOpts) Set(value string) error { + if opts.validator != nil { + v, err := opts.validator(value) + if err != nil { + return err + } + value = v + } + vals := strings.SplitN(value, "=", 2) + if len(vals) == 1 { + (opts.values)[vals[0]] = "" + } else { + (opts.values)[vals[0]] = vals[1] + } + return nil +} + +// GetAll returns the values of MapOpts as a map. +func (opts *MapOpts) GetAll() map[string]string { + return opts.values +} + +func (opts *MapOpts) String() string { + return fmt.Sprintf("%v", opts.values) +} + +// Type returns a string name for this Option type +func (opts *MapOpts) Type() string { + return "map" +} + +// NewMapOpts creates a new MapOpts with the specified map of values and a validator. +func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts { + if values == nil { + values = make(map[string]string) + } + return &MapOpts{ + values: values, + validator: validator, + } +} + +// NamedMapOpts is a MapOpts struct with a configuration name. +// This struct is useful to keep reference to the assigned +// field name in the internal configuration struct. +type NamedMapOpts struct { + name string + MapOpts +} + +var _ NamedOption = &NamedMapOpts{} + +// NewNamedMapOpts creates a reference to a new NamedMapOpts struct. +func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts { + return &NamedMapOpts{ + name: name, + MapOpts: *NewMapOpts(values, validator), + } +} + +// Name returns the name of the NamedMapOpts in the configuration. +func (o *NamedMapOpts) Name() string { + return o.name +} + +// ValidatorFctType defines a validator function that returns a validated string and/or an error. +type ValidatorFctType func(val string) (string, error) + +// ValidatorFctListType defines a validator function that returns a validated list of string and/or an error +type ValidatorFctListType func(val string) ([]string, error) + +// ValidateIPAddress validates an Ip address. +func ValidateIPAddress(val string) (string, error) { + var ip = net.ParseIP(strings.TrimSpace(val)) + if ip != nil { + return ip.String(), nil + } + return "", fmt.Errorf("%s is not an ip address", val) +} + +// ValidateDNSSearch validates domain for resolvconf search configuration. +// A zero length domain is represented by a dot (.). +func ValidateDNSSearch(val string) (string, error) { + if val = strings.Trim(val, " "); val == "." { + return val, nil + } + return validateDomain(val) +} + +func validateDomain(val string) (string, error) { + if alphaRegexp.FindString(val) == "" { + return "", fmt.Errorf("%s is not a valid domain", val) + } + ns := domainRegexp.FindSubmatch([]byte(val)) + if len(ns) > 0 && len(ns[1]) < 255 { + return string(ns[1]), nil + } + return "", fmt.Errorf("%s is not a valid domain", val) +} + +// ValidateLabel validates that the specified string is a valid label, +// it does not use the reserved namespaces com.docker.*, io.docker.*, org.dockerproject.* +// and returns it. +// Labels are in the form on key=value. +func ValidateLabel(val string) (string, error) { + if strings.Count(val, "=") < 1 { + return "", fmt.Errorf("bad attribute format: %s", val) + } + + lowered := strings.ToLower(val) + if strings.HasPrefix(lowered, "com.docker.") || strings.HasPrefix(lowered, "io.docker.") || + strings.HasPrefix(lowered, "org.dockerproject.") { + return "", fmt.Errorf( + "label %s is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use", + val) + } + + return val, nil +} + +// ValidateSingleGenericResource validates that a single entry in the +// generic resource list is valid. +// i.e 'GPU=UID1' is valid however 'GPU:UID1' or 'UID1' isn't +func ValidateSingleGenericResource(val string) (string, error) { + if strings.Count(val, "=") < 1 { + return "", fmt.Errorf("invalid node-generic-resource format `%s` expected `name=value`", val) + } + return val, nil +} + +// ParseLink parses and validates the specified string as a link format (name:alias) +func ParseLink(val string) (string, string, error) { + if val == "" { + return "", "", fmt.Errorf("empty string specified for links") + } + arr := strings.Split(val, ":") + if len(arr) > 2 { + return "", "", fmt.Errorf("bad format for links: %s", val) + } + if len(arr) == 1 { + return val, val, nil + } + // This is kept because we can actually get a HostConfig with links + // from an already created container and the format is not `foo:bar` + // but `/foo:/c1/bar` + if strings.HasPrefix(arr[0], "/") { + _, alias := path.Split(arr[1]) + return arr[0][1:], alias, nil + } + return arr[0], arr[1], nil +} + +// MemBytes is a type for human readable memory bytes (like 128M, 2g, etc) +type MemBytes int64 + +// String returns the string format of the human readable memory bytes +func (m *MemBytes) String() string { + // NOTE: In spf13/pflag/flag.go, "0" is considered as "zero value" while "0 B" is not. + // We return "0" in case value is 0 here so that the default value is hidden. + // (Sometimes "default 0 B" is actually misleading) + if m.Value() != 0 { + return units.BytesSize(float64(m.Value())) + } + return "0" +} + +// Set sets the value of the MemBytes by passing a string +func (m *MemBytes) Set(value string) error { + val, err := units.RAMInBytes(value) + *m = MemBytes(val) + return err +} + +// Type returns the type +func (m *MemBytes) Type() string { + return "bytes" +} + +// Value returns the value in int64 +func (m *MemBytes) Value() int64 { + return int64(*m) +} + +// UnmarshalJSON is the customized unmarshaler for MemBytes +func (m *MemBytes) UnmarshalJSON(s []byte) error { + if len(s) <= 2 || s[0] != '"' || s[len(s)-1] != '"' { + return fmt.Errorf("invalid size: %q", s) + } + val, err := units.RAMInBytes(string(s[1 : len(s)-1])) + *m = MemBytes(val) + return err +} diff --git a/vendor/github.com/docker/docker/opts/quotedstring.go b/vendor/github.com/docker/docker/opts/quotedstring.go new file mode 100644 index 000000000..6c889070e --- /dev/null +++ b/vendor/github.com/docker/docker/opts/quotedstring.go @@ -0,0 +1,37 @@ +package opts // import "github.com/docker/docker/opts" + +// QuotedString is a string that may have extra quotes around the value. The +// quotes are stripped from the value. +type QuotedString struct { + value *string +} + +// Set sets a new value +func (s *QuotedString) Set(val string) error { + *s.value = trimQuotes(val) + return nil +} + +// Type returns the type of the value +func (s *QuotedString) Type() string { + return "string" +} + +func (s *QuotedString) String() string { + return *s.value +} + +func trimQuotes(value string) string { + lastIndex := len(value) - 1 + for _, char := range []byte{'\'', '"'} { + if value[0] == char && value[lastIndex] == char { + return value[1:lastIndex] + } + } + return value +} + +// NewQuotedString returns a new quoted string option +func NewQuotedString(value *string) *QuotedString { + return &QuotedString{value: value} +} diff --git a/vendor/github.com/docker/docker/opts/runtime.go b/vendor/github.com/docker/docker/opts/runtime.go new file mode 100644 index 000000000..4b9babf0a --- /dev/null +++ b/vendor/github.com/docker/docker/opts/runtime.go @@ -0,0 +1,79 @@ +package opts // import "github.com/docker/docker/opts" + +import ( + "fmt" + "strings" + + "github.com/docker/docker/api/types" +) + +// RuntimeOpt defines a map of Runtimes +type RuntimeOpt struct { + name string + stockRuntimeName string + values *map[string]types.Runtime +} + +// NewNamedRuntimeOpt creates a new RuntimeOpt +func NewNamedRuntimeOpt(name string, ref *map[string]types.Runtime, stockRuntime string) *RuntimeOpt { + if ref == nil { + ref = &map[string]types.Runtime{} + } + return &RuntimeOpt{name: name, values: ref, stockRuntimeName: stockRuntime} +} + +// Name returns the name of the NamedListOpts in the configuration. +func (o *RuntimeOpt) Name() string { + return o.name +} + +// Set validates and updates the list of Runtimes +func (o *RuntimeOpt) Set(val string) error { + parts := strings.SplitN(val, "=", 2) + if len(parts) != 2 { + return fmt.Errorf("invalid runtime argument: %s", val) + } + + parts[0] = strings.TrimSpace(parts[0]) + parts[1] = strings.TrimSpace(parts[1]) + if parts[0] == "" || parts[1] == "" { + return fmt.Errorf("invalid runtime argument: %s", val) + } + + parts[0] = strings.ToLower(parts[0]) + if parts[0] == o.stockRuntimeName { + return fmt.Errorf("runtime name '%s' is reserved", o.stockRuntimeName) + } + + if _, ok := (*o.values)[parts[0]]; ok { + return fmt.Errorf("runtime '%s' was already defined", parts[0]) + } + + (*o.values)[parts[0]] = types.Runtime{Path: parts[1]} + + return nil +} + +// String returns Runtime values as a string. +func (o *RuntimeOpt) String() string { + var out []string + for k := range *o.values { + out = append(out, k) + } + + return fmt.Sprintf("%v", out) +} + +// GetMap returns a map of Runtimes (name: path) +func (o *RuntimeOpt) GetMap() map[string]types.Runtime { + if o.values != nil { + return *o.values + } + + return map[string]types.Runtime{} +} + +// Type returns the type of the option +func (o *RuntimeOpt) Type() string { + return "runtime" +} diff --git a/vendor/github.com/docker/docker/opts/ulimit.go b/vendor/github.com/docker/docker/opts/ulimit.go new file mode 100644 index 000000000..61cc58d4d --- /dev/null +++ b/vendor/github.com/docker/docker/opts/ulimit.go @@ -0,0 +1,81 @@ +package opts // import "github.com/docker/docker/opts" + +import ( + "fmt" + + units "github.com/docker/go-units" +) + +// UlimitOpt defines a map of Ulimits +type UlimitOpt struct { + values *map[string]*units.Ulimit +} + +// NewUlimitOpt creates a new UlimitOpt +func NewUlimitOpt(ref *map[string]*units.Ulimit) *UlimitOpt { + if ref == nil { + ref = &map[string]*units.Ulimit{} + } + return &UlimitOpt{ref} +} + +// Set validates a Ulimit and sets its name as a key in UlimitOpt +func (o *UlimitOpt) Set(val string) error { + l, err := units.ParseUlimit(val) + if err != nil { + return err + } + + (*o.values)[l.Name] = l + + return nil +} + +// String returns Ulimit values as a string. +func (o *UlimitOpt) String() string { + var out []string + for _, v := range *o.values { + out = append(out, v.String()) + } + + return fmt.Sprintf("%v", out) +} + +// GetList returns a slice of pointers to Ulimits. +func (o *UlimitOpt) GetList() []*units.Ulimit { + var ulimits []*units.Ulimit + for _, v := range *o.values { + ulimits = append(ulimits, v) + } + + return ulimits +} + +// Type returns the option type +func (o *UlimitOpt) Type() string { + return "ulimit" +} + +// NamedUlimitOpt defines a named map of Ulimits +type NamedUlimitOpt struct { + name string + UlimitOpt +} + +var _ NamedOption = &NamedUlimitOpt{} + +// NewNamedUlimitOpt creates a new NamedUlimitOpt +func NewNamedUlimitOpt(name string, ref *map[string]*units.Ulimit) *NamedUlimitOpt { + if ref == nil { + ref = &map[string]*units.Ulimit{} + } + return &NamedUlimitOpt{ + name: name, + UlimitOpt: *NewUlimitOpt(ref), + } +} + +// Name returns the option name +func (o *NamedUlimitOpt) Name() string { + return o.name +} diff --git a/vendor/github.com/docker/libnetwork/ipamutils/utils.go b/vendor/github.com/docker/libnetwork/ipamutils/utils.go new file mode 100644 index 000000000..3fd37cd88 --- /dev/null +++ b/vendor/github.com/docker/libnetwork/ipamutils/utils.go @@ -0,0 +1,135 @@ +// Package ipamutils provides utility functions for ipam management +package ipamutils + +import ( + "fmt" + "net" + "sync" +) + +var ( + // PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12 + // (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks` + PredefinedLocalScopeDefaultNetworks []*net.IPNet + // PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8 + // (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks` + PredefinedGlobalScopeDefaultNetworks []*net.IPNet + mutex sync.Mutex + localScopeDefaultNetworks = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16}, + {"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16}, + {"192.168.0.0/16", 20}} + globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}} +) + +// NetworkToSplit represent a network that has to be split in chunks with mask length Size. +// Each subnet in the set is derived from the Base pool. Base is to be passed +// in CIDR format. +// Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256 +// 10.10.[0-255].0/24 address pools +type NetworkToSplit struct { + Base string `json:"base"` + Size int `json:"size"` +} + +func init() { + var err error + if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil { + //we are going to panic in case of error as we should never get into this state + panic("InitAddressPools failed to initialize the global scope default address pool") + } + + if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil { + //we are going to panic in case of error as we should never get into this state + panic("InitAddressPools failed to initialize the local scope default address pool") + } +} + +// configDefaultNetworks configures local as well global default pool based on input +func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error { + mutex.Lock() + defer mutex.Unlock() + defaultNetworks, err := splitNetworks(defaultAddressPool) + if err != nil { + return err + } + *result = defaultNetworks + return nil +} + +// GetGlobalScopeDefaultNetworks returns PredefinedGlobalScopeDefaultNetworks +func GetGlobalScopeDefaultNetworks() []*net.IPNet { + mutex.Lock() + defer mutex.Unlock() + return PredefinedGlobalScopeDefaultNetworks +} + +// GetLocalScopeDefaultNetworks returns PredefinedLocalScopeDefaultNetworks +func GetLocalScopeDefaultNetworks() []*net.IPNet { + mutex.Lock() + defer mutex.Unlock() + return PredefinedLocalScopeDefaultNetworks +} + +// ConfigGlobalScopeDefaultNetworks configures global default pool. +// Ideally this will be called from SwarmKit as part of swarm init +func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { + if defaultAddressPool == nil { + defaultAddressPool = globalScopeDefaultNetworks + } + return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks) +} + +// ConfigLocalScopeDefaultNetworks configures local default pool. +// Ideally this will be called during libnetwork init +func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error { + if defaultAddressPool == nil { + return nil + } + return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks) +} + +// splitNetworks takes a slice of networks, split them accordingly and returns them +func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) { + localPools := make([]*net.IPNet, 0, len(list)) + + for _, p := range list { + _, b, err := net.ParseCIDR(p.Base) + if err != nil { + return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err) + } + ones, _ := b.Mask.Size() + if p.Size <= 0 || p.Size < ones { + return nil, fmt.Errorf("invalid pools size: %d", p.Size) + } + localPools = append(localPools, splitNetwork(p.Size, b)...) + } + return localPools, nil +} + +func splitNetwork(size int, base *net.IPNet) []*net.IPNet { + one, bits := base.Mask.Size() + mask := net.CIDRMask(size, bits) + n := 1 << uint(size-one) + s := uint(bits - size) + list := make([]*net.IPNet, 0, n) + + for i := 0; i < n; i++ { + ip := copyIP(base.IP) + addIntToIP(ip, uint(i<<s)) + list = append(list, &net.IPNet{IP: ip, Mask: mask}) + } + return list +} + +func copyIP(from net.IP) net.IP { + ip := make([]byte, len(from)) + copy(ip, from) + return ip +} + +func addIntToIP(array net.IP, ordinal uint) { + for i := len(array) - 1; i >= 0; i-- { + array[i] |= (byte)(ordinal & 0xff) + ordinal >>= 8 + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index aa6fc2753..31c11bd55 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -342,6 +342,7 @@ github.com/docker/docker/api/types/versions github.com/docker/docker/api/types/volume github.com/docker/docker/client github.com/docker/docker/errdefs +github.com/docker/docker/opts github.com/docker/docker/pkg/archive github.com/docker/docker/pkg/fileutils github.com/docker/docker/pkg/homedir @@ -372,6 +373,7 @@ github.com/docker/go-plugins-helpers/volume ## explicit github.com/docker/go-units # github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 +github.com/docker/libnetwork/ipamutils github.com/docker/libnetwork/resolvconf github.com/docker/libnetwork/resolvconf/dns github.com/docker/libnetwork/types |