summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml147
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md6
-rw-r--r--README.md12
-rw-r--r--cmd/podman/system/reset.go14
-rw-r--r--contrib/cirrus/CIModes.md129
-rw-r--r--contrib/podmanimage/README.md10
-rw-r--r--contrib/podmanimage/stable/Containerfile55
-rw-r--r--contrib/podmanimage/stable/Dockerfile36
-rw-r--r--contrib/podmanimage/testing/Containerfile60
-rw-r--r--contrib/podmanimage/testing/Dockerfile36
-rw-r--r--contrib/podmanimage/upstream/Containerfile61
-rw-r--r--contrib/podmanimage/upstream/Dockerfile85
-rw-r--r--docs/source/markdown/podman-build.1.md2
-rw-r--r--docs/source/markdown/podman-create.1.md4
-rw-r--r--docs/source/markdown/podman-play-kube.1.md4
-rw-r--r--docs/source/markdown/podman-pod-create.1.md4
-rw-r--r--docs/source/markdown/podman-run.1.md4
-rw-r--r--docs/tutorials/basic_networking.md16
-rw-r--r--go.mod7
-rw-r--r--go.sum10
-rw-r--r--libpod/container_config.go3
-rw-r--r--libpod/container_internal.go26
-rw-r--r--libpod/container_internal_linux.go239
-rw-r--r--libpod/container_log.go8
-rw-r--r--libpod/networking_linux.go30
-rw-r--r--libpod/options.go29
-rw-r--r--libpod/reset.go72
-rw-r--r--libpod/runtime.go62
-rw-r--r--pkg/api/handlers/compat/images_build.go146
-rw-r--r--pkg/api/handlers/libpod/play.go4
-rw-r--r--pkg/bindings/images/build.go7
-rw-r--r--pkg/domain/infra/abi/system.go2
-rw-r--r--pkg/domain/infra/runtime_abi.go2
-rw-r--r--pkg/domain/infra/runtime_libpod.go21
-rw-r--r--pkg/resolvconf/dns/resolvconf.go28
-rw-r--r--pkg/specgen/generate/config_linux.go139
-rw-r--r--pkg/specgen/generate/container_create.go14
-rw-r--r--pkg/specgen/generate/oci.go10
-rw-r--r--pkg/specgen/volumes.go14
-rw-r--r--pkg/util/utils_linux.go142
-rwxr-xr-xtest/buildah-bud/apply-podman-deltas13
-rw-r--r--test/e2e/build_test.go2
-rw-r--r--test/e2e/logs_test.go21
-rw-r--r--test/e2e/network_connect_disconnect_test.go9
-rw-r--r--test/e2e/play_kube_test.go8
-rw-r--r--test/e2e/pod_create_test.go22
-rw-r--r--test/e2e/run_privileged_test.go24
-rw-r--r--test/e2e/run_volume_test.go45
-rw-r--r--test/system/170-run-userns.bats35
-rw-r--r--test/system/500-networking.bats4
-rw-r--r--vendor/github.com/containers/common/libimage/inspect.go2
-rw-r--r--vendor/github.com/containers/common/libimage/pull.go3
-rw-r--r--vendor/github.com/containers/common/libnetwork/resolvconf/resolv.go182
-rw-r--r--vendor/github.com/containers/common/libnetwork/resolvconf/resolvconf.go (renamed from pkg/resolvconf/resolvconf.go)158
-rw-r--r--vendor/github.com/docker/docker/api/swagger.yaml2
-rw-r--r--vendor/github.com/docker/docker/pkg/system/mknod.go6
-rw-r--r--vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go14
-rw-r--r--vendor/github.com/docker/docker/pkg/system/mknod_unix.go14
-rw-r--r--vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go2
-rw-r--r--vendor/modules.txt8
60 files changed, 1402 insertions, 872 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index fe00974b3..21100388f 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -59,6 +59,7 @@ env:
curl --fail --location -O
--url https://api.cirrus-ci.com/v1/artifact/build/${CIRRUS_BUILD_ID}
+
# Default timeout for each task
timeout_in: 60m
@@ -71,7 +72,9 @@ gcp_credentials: ENCRYPTED[a28959877b2c9c36f151781b0a05407218cda646c7d047fc556e4
ext_svc_check_task:
alias: 'ext_svc_check' # int. ref. name - required for depends_on reference
name: "Ext. services" # Displayed Title - has no other significance
- skip: &tags "$CIRRUS_TAG != ''" # Don't run on tags
+ # Don't create this task for new tags so release process is more reliable
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: $CIRRUS_TAG == ''
# Default/small container image to execute tasks with
container: &smallcontainer
image: ${CTR_FQIN}
@@ -117,7 +120,9 @@ ext_svc_check_task:
automation_task:
alias: 'automation'
name: "Check Automation"
- skip: &branches_and_tags "$CIRRUS_PR == '' || $CIRRUS_TAG != ''" # Don't run on branches/tags
+ # This task is not needed for branches, tags, or cron runs.
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: &is_pr "$CIRRUS_PR != ''"
container: *smallcontainer
env:
TEST_FLAVOR: automation
@@ -138,6 +143,9 @@ automation_task:
build_task:
alias: 'build'
name: 'Build for $DISTRO_NV'
+ # Multiarch doesn't depend on buildability in this automation context
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: "$CIRRUS_CRON != 'multiarch'"
gce_instance: &standardvm
image_project: libpod-218412
zone: "us-central1-a"
@@ -189,7 +197,8 @@ validate_task:
# automation reliability/speed in those contexts. Any missed errors due
# to nonsequential PR merging practices, will be caught on a future PR,
# build or test task failures.
- skip: *branches_and_tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *is_pr
depends_on:
- ext_svc_check
- automation
@@ -218,9 +227,12 @@ validate_task:
bindings_task:
name: "Test Bindings"
alias: bindings
- # Don't run for [CI:DOCS] or [CI:BUILD]
- only_if: &not_build $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' && $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*'
- skip: *branches_and_tags
+ # Don't create task for PRs using [CI:DOCS] or [CI:BUILD]
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: >-
+ $CIRRUS_PR != '' &&
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' &&
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*'
depends_on:
- build
gce_instance: *standardvm
@@ -249,6 +261,11 @@ bindings_task:
swagger_task:
name: "Test Swagger"
alias: swagger
+ # Don't create task for [CI:BUILD] or multiarch builds
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: >-
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*' &&
+ $CIRRUS_CRON != 'multiarch'
depends_on:
- build
gce_instance: *standardvm
@@ -276,7 +293,8 @@ swagger_task:
consistency_task:
name: "Test Code Consistency"
alias: consistency
- skip: *tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *is_pr
depends_on:
- build
container: *smallcontainer
@@ -297,8 +315,11 @@ consistency_task:
alt_build_task:
name: "$ALT_NAME"
alias: alt_build
- # Don't run for [CI:DOCS]; DO run for [CI:BUILD]
- only_if: &not_docs $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*'
+ # Don't create task for [CI:DOCS] or multiarch builds
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: &not_docs_multiarch >-
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' &&
+ $CIRRUS_CRON != 'multiarch'
depends_on:
- build
env:
@@ -330,7 +351,8 @@ alt_build_task:
osx_alt_build_task:
name: "OSX Cross"
alias: osx_alt_build
- only_if: *not_docs
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_docs_multiarch
depends_on:
- build
env:
@@ -359,8 +381,14 @@ osx_alt_build_task:
docker-py_test_task:
name: Docker-py Compat.
alias: docker-py_test
- skip: *tags
- only_if: *not_build
+ # Don't create task for tags, branches, or PRs w/ [CI:DOCS] or [CI:BUILD]
+ # N/B: for PRs $CIRRUS_BRANCH == 'pull/<number>'
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: &not_tag_branch_build_docs >-
+ $CIRRUS_PR != '' &&
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' &&
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*'
+
depends_on:
- build
gce_instance: *standardvm
@@ -379,8 +407,8 @@ docker-py_test_task:
unit_test_task:
name: "Unit tests on $DISTRO_NV"
alias: unit_test
- skip: *tags
- only_if: *not_build
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- validate
matrix:
@@ -404,8 +432,8 @@ unit_test_task:
apiv2_test_task:
name: "APIv2 test on $DISTRO_NV"
alias: apiv2_test
- only_if: *not_build
- skip: *tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- validate
gce_instance: *standardvm
@@ -424,8 +452,8 @@ apiv2_test_task:
compose_test_task:
name: "$TEST_FLAVOR test on $DISTRO_NV ($PRIV_NAME)"
alias: compose_test
- only_if: *not_build
- skip: *tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- validate
gce_instance: *standardvm
@@ -457,8 +485,8 @@ 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_build
- skip: *branches_and_tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- unit_test
matrix: *platform_axis
@@ -492,8 +520,8 @@ remote_integration_test_task:
container_integration_test_task:
name: *std_name_fmt
alias: container_integration_test
- only_if: *not_build
- skip: *branches_and_tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- unit_test
matrix: &fedora_vm_axis
@@ -522,8 +550,8 @@ container_integration_test_task:
rootless_integration_test_task:
name: *std_name_fmt
alias: rootless_integration_test
- only_if: *not_build
- skip: *branches_and_tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- unit_test
matrix: *platform_axis
@@ -545,8 +573,13 @@ rootless_integration_test_task:
local_system_test_task: &local_system_test_task
name: *std_name_fmt
alias: local_system_test
- skip: *tags
- only_if: *not_build
+ # Don't create task for tags, or if using [CI:DOCS], [CI:BUILD], multiarch
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: &not_tag_build_docs_multiarch >-
+ $CIRRUS_TAG == '' &&
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:DOCS.*' &&
+ $CIRRUS_CHANGE_TITLE !=~ '.*CI:BUILD.*' &&
+ $CIRRUS_CRON != 'multiarch'
depends_on:
- local_integration_test
matrix: *platform_axis
@@ -590,11 +623,29 @@ rootless_remote_system_test_task:
PRIV_NAME: rootless
+rootless_system_test_task:
+ name: *std_name_fmt
+ alias: rootless_system_test
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_build_docs_multiarch
+ depends_on:
+ - rootless_integration_test
+ matrix: *platform_axis
+ gce_instance: *standardvm
+ env:
+ TEST_FLAVOR: sys
+ PRIV_NAME: rootless
+ clone_script: *get_gosrc
+ setup_script: *setup
+ main_script: *main
+ always: *logs_artifacts
+
+
buildah_bud_test_task:
name: *std_name_fmt
alias: buildah_bud_test
- skip: *tags
- only_if: *not_build
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- local_integration_test
env:
@@ -618,29 +669,11 @@ buildah_bud_test_task:
always: *int_logs_artifacts
-rootless_system_test_task:
- name: *std_name_fmt
- alias: rootless_system_test
- skip: *tags
- only_if: *not_build
- depends_on:
- - rootless_integration_test
- matrix: *platform_axis
- gce_instance: *standardvm
- env:
- TEST_FLAVOR: sys
- PRIV_NAME: rootless
- clone_script: *get_gosrc
- setup_script: *setup
- main_script: *main
- always: *logs_artifacts
-
-
rootless_gitlab_test_task:
name: *std_name_fmt
alias: rootless_gitlab_test
- skip: *tags
- only_if: *not_build
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
# 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.
@@ -666,8 +699,8 @@ rootless_gitlab_test_task:
upgrade_test_task:
name: "Upgrade test: from $PODMAN_UPGRADE_FROM"
alias: upgrade_test
- skip: *tags
- only_if: *not_build
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_tag_branch_build_docs
depends_on:
- local_system_test
matrix:
@@ -695,9 +728,10 @@ image_build_task: &image-build
alias: image_build
# Some of these container images take > 1h to build, limit
# this task to a specific Cirrus-Cron entry with this name.
+ # Docs: ./contrib/cirrus/CIModes.md
only_if: $CIRRUS_CRON == 'multiarch'
depends_on:
- - build
+ - ext_svc_check
timeout_in: 120m # emulation is sssllllooooowwww
gce_instance:
<<: *standardvm
@@ -728,6 +762,7 @@ test_image_build_task:
<<: *image-build
alias: test_image_build
# Allow this to run inside a PR w/ [CI:BUILD] only.
+ # Docs: ./contrib/cirrus/CIModes.md
only_if: $CIRRUS_PR != '' && $CIRRUS_CHANGE_TITLE =~ '.*CI:BUILD.*'
# This takes a LONG time, only run when requested. N/B: Any task
# made to depend on this one will block FOREVER unless triggered.
@@ -793,9 +828,9 @@ success_task:
- remote_system_test
- rootless_system_test
- rootless_remote_system_test
+ - buildah_bud_test
- rootless_gitlab_test
- upgrade_test
- - buildah_bud_test
- image_build
- meta
container: *smallcontainer
@@ -809,7 +844,8 @@ success_task:
artifacts_task:
name: "Artifacts"
alias: artifacts
- only_if: *not_docs
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: *not_docs_multiarch
depends_on:
- success
# This task is a secondary/convenience for downstream consumers, don't
@@ -862,7 +898,9 @@ artifacts_task:
release_task:
name: "Verify Release"
alias: release
- only_if: *tags
+ # This should _only_ run for new tags
+ # Docs: ./contrib/cirrus/CIModes.md
+ only_if: $CIRRUS_TAG != ''
depends_on:
- success
gce_instance: *standardvm
@@ -884,6 +922,7 @@ release_test_task:
name: "Optional Release Test"
alias: release_test
# Release-PRs always include "release" or "Bump" in the title
+ # Docs: ./contrib/cirrus/CIModes.md
only_if: $CIRRUS_CHANGE_TITLE =~ '.*((release)|(bump)).*'
# Allow running manually only as part of release-related builds
# see RELEASE_PROCESS.md
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 9a4563308..cc8b618f4 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -3,9 +3,9 @@ Thanks for sending a pull request!
Please make sure you've read our contributing guidelines and how to submit a pull request (https://github.com/containers/podman/blob/main/CONTRIBUTING.md#submitting-pull-requests).
-In case you're only changing docs, make sure to prefix the pull-request title with "[CI:DOCS]". That will prevent functional tests from running and save time and energy.
+In case you're only changing docs, make sure to prefix the pull-request title with "[CI:DOCS]". That will prevent functional tests from running and save time and energy.
-Finally, be sure to sign commits with your real name. Since by opening
+Finally, be sure to sign commits with your real name. Since by opening
a PR you already have commits, you can add signatures if needed with
something like `git commit -s --amend`.
-->
@@ -18,7 +18,7 @@ is required: Enter your extended release note in the block below. If the PR
requires additional action from users switching to the new release, include the
string "action required".
-For more information on release notes please follow the kubernetes model:
+For more information on release notes, please follow the Kubernetes model:
https://git.k8s.io/community/contributors/guide/release-notes.md
-->
diff --git a/README.md b/README.md
index 1a1e21fe3..5e86b336e 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
# Podman: A tool for managing OCI containers and pods
Podman (the POD MANager) is a tool for managing containers and images, volumes mounted into those containers, and pods made from groups of containers.
+Podman runs containers on Linux, but can also be used on Mac and Windows systems using a Podman-managed virtual machine.
Podman is based on libpod, a library for container lifecycle management that is also contained in this repository. The libpod library provides APIs for managing containers, pods, container images, and volumes.
* [Latest Version: 4.1.0](https://github.com/containers/podman/releases/tag/v4.1.0)
@@ -24,16 +25,15 @@ At a high level, the scope of Podman and libpod is the following:
* Support for pods, groups of containers that share resources and are managed together.
* Support for running containers and pods without root or other elevated privileges.
* Resource isolation of containers and pods.
-* Support for a Docker-compatible CLI interface.
+* Support for a Docker-compatible CLI interface, which can both run containers locally and on remote systems.
* No manager daemon, for improved security and lower resource utilization at idle.
* Support for a REST API providing both a Docker-compatible interface and an improved interface exposing advanced Podman functionality.
-
-Podman presently only supports running containers on Linux. However, we are building a remote client which can run on Windows and macOS and manage Podman containers on a Linux system via the REST API using SSH tunneling.
+* Support for running on Windows and Mac via virtual machines run by `podman machine`.
## Roadmap
-1. Further improvements to the REST API, with a focus on bugfixes and implementing missing functionality
-1. Improvements on rootless containers, with a focus on improving the user experience and exposing presently-unavailable features when possible
+1. A fully-featured GUI frontend for `podman machine`
+1. Further improvements to `podman generate kube` and `podman play kube`
1. Improvements to Pods, including the addition of pod-level resource limits
## Communications
@@ -111,7 +111,7 @@ includes tables showing Docker commands and their Podman equivalent commands.
Tutorials on using Podman.
**[Remote Client](https://github.com/containers/podman/blob/main/docs/tutorials/remote_client.md)**
-A brief how-to on using the Podman remote-client.
+A brief how-to on using the Podman remote client.
**[Basic Setup and Use of Podman in a Rootless environment](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md)**
A tutorial showing the setup and configuration necessary to run Rootless Podman.
diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go
index 176573bf6..20f15a34f 100644
--- a/cmd/podman/system/reset.go
+++ b/cmd/podman/system/reset.go
@@ -91,18 +91,10 @@ func reset(cmd *cobra.Command, args []string) {
registry.ContainerEngine().Shutdown(registry.Context())
registry.ImageEngine().Shutdown(registry.Context())
- engine, err := infra.NewSystemEngine(entities.ResetMode, registry.PodmanConfig())
- if err != nil {
- logrus.Error(err)
- os.Exit(define.ExecErrorCodeGeneric)
- }
- defer engine.Shutdown(registry.Context())
-
- if err := engine.Reset(registry.Context()); err != nil {
+ // Do not try to shut the engine down, as a Reset engine is not valid
+ // after its creation.
+ if _, err := infra.NewSystemEngine(entities.ResetMode, registry.PodmanConfig()); err != nil {
logrus.Error(err)
- // FIXME change this to return the error like other commands
- // defer will never run on os.Exit()
- //nolint:gocritic
os.Exit(define.ExecErrorCodeGeneric)
}
diff --git a/contrib/cirrus/CIModes.md b/contrib/cirrus/CIModes.md
new file mode 100644
index 000000000..8b1e33bb1
--- /dev/null
+++ b/contrib/cirrus/CIModes.md
@@ -0,0 +1,129 @@
+The following is a list (incomplete) of the primary contexts and runtime
+"modes" supported by podman CI. Note that there may be additional checks
+done regarding "skipping work" in the `runner.sh` script. This document
+only details the controls at the `.cirrus.yml` level.
+
+## Visualization
+
+The relationship between tasks can be incredibly hard to understand by
+staring at the YAML.
+[A tool exists](https://github.com/containers/automation/tree/main/cirrus-task-map)
+for producing a graph (flow-chart) of the `.cirrus.yml` file. A (possibly
+outdated) example of it's output can be seen below:
+
+![cirrus-task-map output](https://github.com/containers/podman/wiki/cirrus-map.svg)
+
+## Implementation notes
+
++ The `skip` conditional should never be used for tasks.
+ While it's arguably easier to read that `only_if`, it leads to a cluttered
+ status output that's harder to page through when reviewing PRs. As opposed
+ to `only_if` which will bypass creation of the task (at runtime) completely.
+ Also, by sticking to one conditional style, it's easer to re-use the YAML
+ statements across multiple tasks.
+
++ The only variables which can be used as part of conditions are defined by
+ Cirrus-CI.
+ [The list is documented](https://cirrus-ci.org/guide/writing-tasks/#environment-variables). Reference to any variables defined in YAML will **not** behave how
+ you expect, don't use them!
+
+* Somme Cirrus-CI defined variables contain non-empty values outside their
+ obvious context. For example, when running for a PR a task will have
+ `$CIRRUS_BRANCH` set to `pull/<number>`.
+
+* Conditions which use positive or negative regular-expressions have several
+ "flags" set: "Multi-line" and "Case-insensitive".
+
+## Testing
+
+Executing most of the modes can be mocked by forcing values for (otherwise)
+Cirrus-CI defined variables. For example `$CIRRUS_TAG`. As of the publishing
+of this document, it's not possible to override the behavior of `$CIRRUS_PR`.
+
+## Cirrus Task contexts and runtime modes
+
+### Intended general PR Tasks (*italic*: matrix)
++ ext_svc_check
++ automation
++ *build*
++ validate
++ bindings
++ swagger
++ consistency
++ *alt_build*
++ osx_alt_build
++ docker-py_test
++ *unit_test*
++ apiv2_test
++ *compose_test*
++ *local_integration_test*
++ *remote_integration_test*
++ *container_integration_test*
++ *rootless_integration_test*
++ *local_system_test*
++ *remote_system_test*
++ *rootless_remote_system_test*
++ *buildah_bud_test*
++ *rootless_system_test*
++ rootless_gitlab_test
++ *upgrade_test*
++ meta
++ success
++ artifacts
+
+### Intended for PR w/ "release" or "bump" in title:
++ (All the general PR tasks above)
++ release_test
+
+### Intended `[CI:DOCS]` PR Tasks:
++ ext_svc_check
++ automation
++ *build*
++ validate
++ swagger
++ consistency
++ meta
++ success
+
+### Intend `[CI:BUILD]` PR Tasks:
++ ext_svc_check
++ automation
++ *build*
++ validate
++ consistency
++ *alt_build*
++ osx_alt_build
++ test_image_build
++ meta
++ success
++ artifacts
+
+### Intended Branch tasks (and Cirrus-cron jobs, except "multiarch"):
++ ext_svc_check
++ *build*
++ swagger
++ *alt_build*
++ osx_alt_build
++ *local_system_test*
++ *remote_system_test*
++ *rootless_remote_system_test*
++ *rootless_system_test*
++ meta
++ success
++ artifacts
+
+### Intended for "multiarch" Cirrus-Cron (always a branch):
++ ext_svc_check
++ image_build
++ meta
++ success
+
+### Intended for new Tag tasks:
++ *build*
++ swagger
++ *alt_build*
++ osx_alt_build
++ meta
++ success
++ artifacts
++ release
diff --git a/contrib/podmanimage/README.md b/contrib/podmanimage/README.md
index 4f184ca28..b4ef81d84 100644
--- a/contrib/podmanimage/README.md
+++ b/contrib/podmanimage/README.md
@@ -4,7 +4,7 @@
## Overview
-This directory contains the Dockerfiles necessary to create the podmanimage container
+This directory contains the Containerfiles necessary to create the podmanimage container
images that are housed on quay.io under the Podman account. All repositories where
the images live are public and can be pulled without credentials. These container images are secured and the
resulting containers can run safely with privileges within the container.
@@ -21,18 +21,18 @@ The container images are:
and stable version of podman. For the most recent `<version>` tags (`vX`,
`vX.Y`, and `vX.Y.Z`) the image contents will be updated daily to incorporate
(especially) security upgrades. For build details, please [see the
- configuration file](stable/Dockerfile).
+ configuration file](stable/Containerfile).
* `quay.io/containers/podman:latest` and `quay.io/podman/stable:latest` -
- Built daily using the same Dockerfile as above. The Podman version
+ Built daily using the same Containerfile as above. The Podman version
will remain the "latest" available in Fedora, however the other image
contents may vary compared to the version-tagged images.
* `quay.io/podman/testing:latest` - This image is built daily, using the
latest version of Podman that was in the Fedora `updates-testing` repository.
- The image is Built with [the testing Dockerfile](testing/Dockerfile).
+ The image is Built with [the testing Containerfile](testing/Containerfile).
* `quay.io/podman/upstream:latest` - This image is built daily using the latest
code found in this GitHub repository. Due to the image changing frequently,
it's not guaranteed to be stable or even executable. The image is built with
- [the upstream Dockerfile](upstream/Dockerfile).
+ [the upstream Containerfile](upstream/Containerfile).
## Sample Usage
diff --git a/contrib/podmanimage/stable/Containerfile b/contrib/podmanimage/stable/Containerfile
new file mode 100644
index 000000000..9121c5cde
--- /dev/null
+++ b/contrib/podmanimage/stable/Containerfile
@@ -0,0 +1,55 @@
+# stable/Containerfile
+#
+# Build a Podman container image from the latest
+# stable version of Podman on the Fedoras Updates System.
+# https://bodhi.fedoraproject.org/updates/?search=podman
+# This image can be used to create a secured container
+# that runs safely with privileges within the container.
+#
+FROM registry.fedoraproject.org/fedora:latest
+
+# Don't include container-selinux and remove
+# directories used by dnf that are just taking
+# up space.
+RUN dnf -y update && \
+ rpm --setcaps shadow-utils 2>/dev/null && \
+ dnf -y install podman fuse-overlayfs \
+ --exclude container-selinux && \
+ dnf clean all && \
+ rm -rf /var/cache /var/log/dnf* /var/log/yum.*
+
+RUN useradd podman; \
+echo -e "podman:1:999\npodman:1001:64535" > /etc/subuid; \
+echo -e "podman:1:999\npodman:1001:64535" > /etc/subgid;
+
+ARG _REPO_URL="https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable"
+ADD $_REPO_URL/containers.conf /etc/containers/containers.conf
+ADD $_REPO_URL/podman-containers.conf /home/podman/.config/containers/containers.conf
+
+RUN mkdir -p /home/podman/.local/share/containers && \
+ chown podman:podman -R /home/podman && \
+ chmod 644 /etc/containers/containers.conf
+
+# Copy & modify the defaults to provide reference if runtime changes needed.
+# Changes here are required for running with fuse-overlay storage inside container.
+RUN sed -e 's|^#mount_program|mount_program|g' \
+ -e '/additionalimage.*/a "/var/lib/shared",' \
+ -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' \
+ /usr/share/containers/storage.conf \
+ > /etc/containers/storage.conf
+
+# Note VOLUME options must always happen after the chown call above
+# RUN commands can not modify existing volumes
+VOLUME /var/lib/containers
+VOLUME /home/podman/.local/share/containers
+
+RUN mkdir -p /var/lib/shared/overlay-images \
+ /var/lib/shared/overlay-layers \
+ /var/lib/shared/vfs-images \
+ /var/lib/shared/vfs-layers && \
+ touch /var/lib/shared/overlay-images/images.lock && \
+ touch /var/lib/shared/overlay-layers/layers.lock && \
+ touch /var/lib/shared/vfs-images/images.lock && \
+ touch /var/lib/shared/vfs-layers/layers.lock
+
+ENV _CONTAINERS_USERNS_CONFIGURED=""
diff --git a/contrib/podmanimage/stable/Dockerfile b/contrib/podmanimage/stable/Dockerfile
deleted file mode 100644
index 78d820458..000000000
--- a/contrib/podmanimage/stable/Dockerfile
+++ /dev/null
@@ -1,36 +0,0 @@
-# stable/Dockerfile
-#
-# Build a Podman container image from the latest
-# stable version of Podman on the Fedoras Updates System.
-# https://bodhi.fedoraproject.org/updates/?search=podman
-# This image can be used to create a secured container
-# that runs safely with privileges within the container.
-#
-FROM registry.fedoraproject.org/fedora:latest
-
-# Don't include container-selinux and remove
-# directories used by yum that are just taking
-# up space.
-RUN dnf -y update; rpm --restore shadow-utils 2>/dev/null; \
-yum -y install podman fuse-overlayfs --exclude container-selinux; \
-rm -rf /var/cache /var/log/dnf* /var/log/yum.*
-
-RUN useradd podman; \
-echo -e "podman:1:999\npodman:1001:64535" > /etc/subuid; \
-echo -e "podman:1:999\npodman:1001:64535" > /etc/subgid;
-
-ADD https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
-ADD https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf
-
-RUN mkdir -p /home/podman/.local/share/containers; chown podman:podman -R /home/podman
-
-# Note VOLUME options must always happen after the chown call above
-# RUN commands can not modify existing volumes
-VOLUME /var/lib/containers
-VOLUME /home/podman/.local/share/containers
-
-# chmod containers.conf and adjust storage.conf to enable Fuse storage.
-RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
-RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock
-
-ENV _CONTAINERS_USERNS_CONFIGURED=""
diff --git a/contrib/podmanimage/testing/Containerfile b/contrib/podmanimage/testing/Containerfile
new file mode 100644
index 000000000..16314a633
--- /dev/null
+++ b/contrib/podmanimage/testing/Containerfile
@@ -0,0 +1,60 @@
+# testing/Containerfile
+#
+# Build a Podman container image from the latest
+# stable version of Podman on the Fedoras Updates System.
+# https://bodhi.fedoraproject.org/updates/?search=podman
+# This image can be used to create a secured container
+# that runs safely with privileges within the container.
+#
+FROM registry.fedoraproject.org/fedora:latest
+
+# Don't include container-selinux and remove
+# directories used by dnf that are just taking
+# up space.
+RUN dnf -y update && \
+ rpm --setcaps shadow-utils 2>/dev/null && \
+ dnf -y install podman fuse-overlayfs \
+ --exclude container-selinux --enablerepo updates-testing && \
+ dnf clean all && \
+ rm -rf /var/cache /var/log/dnf* /var/log/yum.*
+
+RUN useradd podman; \
+echo -e "podman:1:999\npodman:1001:64535" > /etc/subuid; \
+echo -e "podman:1:999\npodman:1001:64535" > /etc/subgid;
+
+ARG _REPO_URL="https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable"
+ADD $_REPO_URL/containers.conf /etc/containers/containers.conf
+ADD $_REPO_URL/podman-containers.conf /home/podman/.config/containers/containers.conf
+
+RUN mkdir -p /home/podman/.local/share/containers && \
+ chown podman:podman -R /home/podman
+
+# Copy & modify the defaults to provide reference if runtime changes needed.
+# Changes here are required for running with fuse-overlay storage inside container.
+RUN sed -e 's|^#mount_program|mount_program|g' \
+ -e '/additionalimage.*/a "/var/lib/shared",' \
+ -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' \
+ /usr/share/containers/storage.conf \
+ > /etc/containers/storage.conf
+
+# Note VOLUME options must always happen after the chown call above
+# RUN commands can not modify existing volumes
+VOLUME /var/lib/containers
+VOLUME /home/podman/.local/share/containers
+
+# chmod containers.conf and adjust storage.conf to enable Fuse storage.
+RUN chmod 644 /etc/containers/containers.conf && \
+ sed -i -e 's|^#mount_program|mount_program|g' \
+ -e '/additionalimage.*/a "/var/lib/shared",' \
+ -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' \
+ /etc/containers/storage.conf
+RUN mkdir -p /var/lib/shared/overlay-images \
+ /var/lib/shared/overlay-layers \
+ /var/lib/shared/vfs-images \
+ /var/lib/shared/vfs-layers && \
+ touch /var/lib/shared/overlay-images/images.lock && \
+ touch /var/lib/shared/overlay-layers/layers.lock && \
+ touch /var/lib/shared/vfs-images/images.lock && \
+ touch /var/lib/shared/vfs-layers/layers.lock
+
+ENV _CONTAINERS_USERNS_CONFIGURED=""
diff --git a/contrib/podmanimage/testing/Dockerfile b/contrib/podmanimage/testing/Dockerfile
deleted file mode 100644
index 41af1c849..000000000
--- a/contrib/podmanimage/testing/Dockerfile
+++ /dev/null
@@ -1,36 +0,0 @@
-# testing/Dockerfile
-#
-# Build a Podman image using the latest
-# version of Podman that is in updates-testing
-# on the Fedoras Updates System. At times this
-# may be the same the latest stable version.
-# https://bodhi.fedoraproject.org/updates/?search=podman
-# This image can be used to create a secured container
-# that runs safely with privileges within the container.
-#
-FROM registry.fedoraproject.org/fedora:latest
-
-# Don't include container-selinux and remove
-# directories used by yum that are just taking
-# up space.
-RUN yum -y update; rpm --restore shadow-utils 2>/dev/null; yum -y install podman fuse-overlayfs --exclude container-selinux --enablerepo updates-testing; rm -rf /var/cache /var/log/dnf* /var/log/yum.*
-
-RUN useradd podman; \
-echo -e "podman:1:999\npodman:1001:64535" > /etc/subuid; \
-echo -e "podman:1:999\npodman:1001:64535" > /etc/subgid;
-
-ADD https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
-ADD https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf
-
-RUN mkdir -p /home/podman/.local/share/containers; chown podman:podman -R /home/podman
-
-# Note VOLUME options must always happen after the chown call above
-# RUN commands can not modify existing volumes
-VOLUME /var/lib/containers
-VOLUME /home/podman/.local/share/containers
-
-# chmod containers.conf and adjust storage.conf to enable Fuse storage.
-RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
-RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock
-
-ENV _CONTAINERS_USERNS_CONFIGURED=""
diff --git a/contrib/podmanimage/upstream/Containerfile b/contrib/podmanimage/upstream/Containerfile
new file mode 100644
index 000000000..c3a07a8d6
--- /dev/null
+++ b/contrib/podmanimage/upstream/Containerfile
@@ -0,0 +1,61 @@
+# upstream/Containerfile
+#
+# Build a Podman container image from the latest
+# upstream version of Podman on GitHub.
+# https://github.com/containers/podman
+# This image can be used to create a secured container
+# that runs safely with privileges within the container.
+# The containers created by this image also come with a
+# Podman development environment in /root/podman.
+#
+FROM registry.fedoraproject.org/fedora:latest
+
+# Don't include container-selinux and remove
+# directories used by dnf that are just taking
+# up space. The latest podman + deps. come from
+# https://copr.fedorainfracloud.org/coprs/rhcontainerbot/podman-next/
+RUN dnf -y update && \
+ rpm --setcaps shadow-utils 2>/dev/null && \
+ dnf -y install 'dnf-command(copr)' --enablerepo=updates-testing && \
+ dnf -y copr enable rhcontainerbot/podman-next && \
+ dnf -y install podman fuse-overlayfs \
+ --exclude container-selinux \
+ --enablerepo=updates-testing && \
+ dnf clean all && \
+ rm -rf /var/cache /var/log/dnf* /var/log/yum.*
+
+RUN useradd podman; \
+echo -e "podman:1:999\npodman:1001:64535" > /etc/subuid; \
+echo -e "podman:1:999\npodman:1001:64535" > /etc/subgid;
+
+ARG _REPO_URL="https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable"
+ADD $_REPO_URL/containers.conf /etc/containers/containers.conf
+ADD $_REPO_URL/podman-containers.conf /home/podman/.config/containers/containers.conf
+
+RUN mkdir -p /home/podman/.local/share/containers && \
+ chown podman:podman -R /home/podman && \
+ chmod 644 /etc/containers/containers.conf
+
+# Copy & modify the defaults to provide reference if runtime changes needed.
+# Changes here are required for running with fuse-overlay storage inside container.
+RUN sed -e 's|^#mount_program|mount_program|g' \
+ -e '/additionalimage.*/a "/var/lib/shared",' \
+ -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' \
+ /usr/share/containers/storage.conf \
+ > /etc/containers/storage.conf
+
+# Note VOLUME options must always happen after the chown call above
+# RUN commands can not modify existing volumes
+VOLUME /var/lib/containers
+VOLUME /home/podman/.local/share/containers
+
+RUN mkdir -p /var/lib/shared/overlay-images \
+ /var/lib/shared/overlay-layers \
+ /var/lib/shared/vfs-images \
+ /var/lib/shared/vfs-layers && \
+ touch /var/lib/shared/overlay-images/images.lock && \
+ touch /var/lib/shared/overlay-layers/layers.lock && \
+ touch /var/lib/shared/vfs-images/images.lock && \
+ touch /var/lib/shared/vfs-layers/layers.lock
+
+ENV _CONTAINERS_USERNS_CONFIGURED=""
diff --git a/contrib/podmanimage/upstream/Dockerfile b/contrib/podmanimage/upstream/Dockerfile
deleted file mode 100644
index 0769a7612..000000000
--- a/contrib/podmanimage/upstream/Dockerfile
+++ /dev/null
@@ -1,85 +0,0 @@
-# git/Dockerfile
-#
-# Build a Podman container image from the latest
-# upstream version of Podman on GitHub.
-# https://github.com/containers/podman
-# This image can be used to create a secured container
-# that runs safely with privileges within the container.
-# The containers created by this image also come with a
-# Podman development environment in /root/podman.
-#
-FROM registry.fedoraproject.org/fedora:latest
-ENV GOPATH=/root/podman
-
-# Install the software required to build Podman.
-# Then create a directory and clone from the Podman
-# GitHub repository, make and install Podman
-# to the container.
-# Finally remove the podman directory and a few other packages
-# that are needed for building but not running Podman
-RUN yum -y update; rpm --restore shadow-utils 2>/dev/null; yum -y install --exclude container-selinux \
- --enablerepo=updates-testing \
- btrfs-progs-devel \
- containernetworking-cni \
- conmon \
- device-mapper-devel \
- git \
- glib2-devel \
- glibc-devel \
- glibc-static \
- go \
- golang-github-cpuguy83-md2man \
- gpgme-devel \
- iptables \
- libassuan-devel \
- libgpg-error-devel \
- libseccomp-devel \
- libselinux-devel \
- make \
- pkgconfig \
- crun \
- fuse-overlayfs \
- fuse3 \
- containers-common \
- podman-plugins; \
- mkdir /root/podman; \
- git clone https://github.com/containers/podman /root/podman/src/github.com/containers/podman; \
- cd /root/podman/src/github.com/containers/podman; \
- make BUILDTAGS="selinux seccomp"; \
- make install PREFIX=/usr; \
- cd /root/podman; \
- git clone https://github.com/containers/conmon /root/podman/conmon; \
- cd conmon; \
- make; \
- install -D -m 755 bin/conmon /usr/libexec/podman/conmon; \
- git clone https://github.com/containernetworking/plugins.git $GOPATH/src/github.com/containernetworking/plugins; \
- cd $GOPATH/src/github.com/containernetworking/plugins; \
- ./build_linux.sh; \
- mkdir -p /usr/libexec/cni; \
- \cp -fR bin/* /usr/libexec/cni; \
- mkdir -p /etc/cni/net.d; \
- curl -qsSL https://raw.githubusercontent.com/containers/podman/main/cni/87-podman-bridge.conflist | tee /etc/cni/net.d/99-loopback.conf; \
- mkdir -p /usr/share/containers; \
- rm -rf /root/podman/*; \
- yum -y remove git golang go-md2man make; \
- yum clean all;
-
-RUN useradd podman; \
-echo -e "podman:1:999\npodman:1001:64535" > /etc/subuid; \
-echo -e "podman:1:999\npodman:1001:64535" > /etc/subgid;
-
-ADD https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable/containers.conf /etc/containers/containers.conf
-ADD https://raw.githubusercontent.com/containers/podman/main/contrib/podmanimage/stable/podman-containers.conf /home/podman/.config/containers/containers.conf
-
-RUN mkdir -p /home/podman/.local/share/containers; chown podman:podman -R /home/podman
-
-# Note VOLUME options must always happen after the chown call above
-# RUN commands can not modify existing volumes
-VOLUME /var/lib/containers
-VOLUME /home/podman/.local/share/containers
-
-# chmod containers.conf and adjust storage.conf to enable Fuse storage.
-RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/storage.conf
-RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock
-
-ENV _CONTAINERS_USERNS_CONFIGURED=""
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index a59dcea89..4d6a74a1f 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -99,7 +99,7 @@ different stages in COPY instruction.
Valid values could be:
-* Local directory – e.g. --build-context project2=../path/to/project2/src
+* Local directory – e.g. --build-context project2=../path/to/project2/src (This option is not available with the remote Podman client. On Podman machine setup (i.e macOS and Winows) path must exists on the machine VM)
* HTTP URL to a tarball – e.g. --build-context src=https://example.org/releases/src.tar
* Container image – specified with a container-image:// prefix, e.g. --build-context alpine=container-image://alpine:3.15, (also accepts docker://, docker-image://)
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 913183869..d5e96168d 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -1261,9 +1261,9 @@ Podman allocates unique ranges of UIDs and GIDs from the `containers` subordinat
**host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
-**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user.
+**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user.
-**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is ignored for containers created by the root user.
+**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user.
**ns:**_namespace_: run the container in the given existing user namespace.
diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md
index 08bb2a5bc..1c7fc99a2 100644
--- a/docs/source/markdown/podman-play-kube.1.md
+++ b/docs/source/markdown/podman-play-kube.1.md
@@ -276,9 +276,9 @@ Podman allocates unique ranges of UIDs and GIDs from the `containers` subordinat
**host**: create a new namespace for the container.
-**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user.
+**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user.
-**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is ignored for containers created by the root user.
+**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user.
**ns:**_namespace_: run the pod in the given existing user namespace.
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index 1a98528bb..d5b8232cf 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -360,9 +360,9 @@ Valid _mode_ values are:
- *host*: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
- - *keep-id*: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user.
+ - *keep-id*: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user.
- - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is ignored for containers created by the root user.
+ - *nomap*: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user.
#### **--volume**, **-v**[=*[[SOURCE-VOLUME|HOST-DIR:]CONTAINER-DIR[:OPTIONS]]*]
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index b9d87b5bd..6acbec7d5 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -1329,9 +1329,9 @@ The rootless option `--userns=keep-id` uses all the subuids and subgids of the u
**host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
-**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user.
+**keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is not allowed for containers created by the root user.
-**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is ignored for containers created by the root user.
+**nomap**: creates a user namespace where the current rootless user's UID:GID are not mapped into the container. This option is not allowed for containers created by the root user.
**ns:**_namespace_: run the container in the given existing user namespace.
diff --git a/docs/tutorials/basic_networking.md b/docs/tutorials/basic_networking.md
index 396994596..b6f53175b 100644
--- a/docs/tutorials/basic_networking.md
+++ b/docs/tutorials/basic_networking.md
@@ -93,6 +93,22 @@ When rootless containers are run, network operations
will be executed inside an extra network namespace. To join this namespace, use
`podman unshare --rootless-netns`.
+#### Default Network
+
+The default network `podman` with netavark is memory-only. It does not support dns resolution because of backwards compatibility with Docker. To change settings, export the in-memory network and change the file.
+
+For the default rootful network use
+```
+podman network inspect podman | jq .[] > /etc/containers/networks/podman.json
+```
+
+And for the rootless network use
+
+```
+podman network inspect podman | jq .[] > ~/.local/share/containers/storage/networks/podman.json
+```
+
+
#### Example
By default, rootful containers use the netavark for its default network if
diff --git a/go.mod b/go.mod
index fc0bbcc73..8c2c0f87a 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v1.1.1
github.com/containernetworking/plugins v1.1.1
github.com/containers/buildah v1.26.1-0.20220524184833-5500333c2e06
- github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824
+ github.com/containers/common v0.48.1-0.20220528105338-54c8092c69a1
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.21.2-0.20220520105616-e594853d6471
github.com/containers/ocicrypt v1.1.4-0.20220428134531-566b808bdf6f
@@ -24,7 +24,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
github.com/docker/distribution v2.8.1+incompatible
- github.com/docker/docker v20.10.16+incompatible
+ github.com/docker/docker v20.10.17+incompatible
github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
github.com/docker/go-units v0.4.0
@@ -57,7 +57,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
- github.com/stretchr/testify v1.7.1
+ github.com/stretchr/testify v1.7.2
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/ulikunitz/xz v0.5.10
@@ -72,5 +72,4 @@ require (
google.golang.org/protobuf v1.28.0
gopkg.in/inf.v0 v0.9.1
gopkg.in/yaml.v2 v2.4.0
- gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index aa2e07376..000167d52 100644
--- a/go.sum
+++ b/go.sum
@@ -339,8 +339,8 @@ github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19
github.com/containers/buildah v1.26.1-0.20220524184833-5500333c2e06 h1:Tx1IfKch/SnsCk1YrdyR4B2AcS1TKLYxbSMXzmQXafU=
github.com/containers/buildah v1.26.1-0.20220524184833-5500333c2e06/go.mod h1:oB0PwsW+rhePNsBimCnEz4YMLx8QxZBjHi/DPnXhUCg=
github.com/containers/common v0.48.1-0.20220519181648-280c6f69fa82/go.mod h1:Ru/JjL1CTHzlxghVMhchzcFUwHLvlIeR5/SUMw8VUOI=
-github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824 h1:5gMIUUpIK9DvHrrlj1Tik8GfCh5DEuVqm0JnYHWYUDw=
-github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824/go.mod h1:Ru/JjL1CTHzlxghVMhchzcFUwHLvlIeR5/SUMw8VUOI=
+github.com/containers/common v0.48.1-0.20220528105338-54c8092c69a1 h1:oq9ol4U/HEJfDYCp9aKBFDBaE16Y1RZN0GJ4eIkrJoo=
+github.com/containers/common v0.48.1-0.20220528105338-54c8092c69a1/go.mod h1:Ru/JjL1CTHzlxghVMhchzcFUwHLvlIeR5/SUMw8VUOI=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.21.2-0.20220511203756-fe4fd4ed8be4/go.mod h1:OsX9sFexyGF0FCNAjfcVFv3IwMqDyLyV/WQY/roLPcE=
@@ -429,8 +429,9 @@ github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r
github.com/docker/docker v20.10.3-0.20220208084023-a5c757555091+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.15+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ=
github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
+github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
@@ -1262,8 +1263,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/sylabs/sif/v2 v2.7.0 h1:VFzN8alnJ/3n1JA0K9DyUtfSzezWgWrzLDcYGhgBskk=
github.com/sylabs/sif/v2 v2.7.0/go.mod h1:TiyBWsgWeh5yBeQFNuQnvROwswqK7YJT8JA1L53bsXQ=
diff --git a/libpod/container_config.go b/libpod/container_config.go
index 30b84adcf..6558f3c89 100644
--- a/libpod/container_config.go
+++ b/libpod/container_config.go
@@ -412,6 +412,9 @@ type ContainerMiscConfig struct {
InitContainerType string `json:"init_container_type,omitempty"`
// PasswdEntry specifies arbitrary data to append to a file.
PasswdEntry string `json:"passwd_entry,omitempty"`
+ // MountAllDevices is an option to indicate whether a privileged container
+ // will mount all the host's devices
+ MountAllDevices bool `json:"mountAllDevices"`
}
// InfraInherit contains the compatible options inheritable from the infra container
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 7494eb3ec..fd451f9ef 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/buildah/pkg/overlay"
butil "github.com/containers/buildah/util"
"github.com/containers/common/libnetwork/etchosts"
+ "github.com/containers/common/libnetwork/resolvconf"
"github.com/containers/common/pkg/cgroups"
"github.com/containers/common/pkg/chown"
"github.com/containers/common/pkg/config"
@@ -986,7 +987,7 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
}
func (c *Container) completeNetworkSetup() error {
- var outResolvConf []string
+ var nameservers []string
netDisabled, err := c.NetworkDisabled()
if err != nil {
return err
@@ -1000,11 +1001,14 @@ func (c *Container) completeNetworkSetup() error {
if err := c.runtime.setupNetNS(c); err != nil {
return err
}
+ if err := c.save(); err != nil {
+ return err
+ }
state := c.state
// collect any dns servers that cni tells us to use (dnsname)
for _, status := range c.getNetworkStatus() {
for _, server := range status.DNSServerIPs {
- outResolvConf = append(outResolvConf, fmt.Sprintf("nameserver %s", server))
+ nameservers = append(nameservers, server.String())
}
}
// check if we have a bindmount for /etc/hosts
@@ -1020,24 +1024,12 @@ func (c *Container) completeNetworkSetup() error {
}
// check if we have a bindmount for resolv.conf
- resolvBindMount := state.BindMounts["/etc/resolv.conf"]
- if len(outResolvConf) < 1 || resolvBindMount == "" || len(c.config.NetNsCtr) > 0 {
+ resolvBindMount := state.BindMounts[resolvconf.DefaultResolvConf]
+ if len(nameservers) < 1 || resolvBindMount == "" || len(c.config.NetNsCtr) > 0 {
return nil
}
- // read the existing resolv.conf
- b, err := ioutil.ReadFile(resolvBindMount)
- if err != nil {
- return err
- }
- for _, line := range strings.Split(string(b), "\n") {
- // only keep things that don't start with nameserver from the old
- // resolv.conf file
- if !strings.HasPrefix(line, "nameserver") {
- outResolvConf = append([]string{line}, outResolvConf...)
- }
- }
// write and return
- return ioutil.WriteFile(resolvBindMount, []byte(strings.Join(outResolvConf, "\n")), 0644)
+ return resolvconf.Add(resolvBindMount, nameservers)
}
// Initialize a container, creating it in the runtime
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index e19d75deb..41c0ac595 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -9,7 +9,6 @@ import (
"io"
"io/ioutil"
"math"
- "net"
"os"
"os/user"
"path"
@@ -29,6 +28,7 @@ import (
"github.com/containers/buildah/pkg/overlay"
butil "github.com/containers/buildah/util"
"github.com/containers/common/libnetwork/etchosts"
+ "github.com/containers/common/libnetwork/resolvconf"
"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/apparmor"
"github.com/containers/common/pkg/cgroups"
@@ -44,7 +44,6 @@ import (
"github.com/containers/podman/v4/pkg/checkpoint/crutils"
"github.com/containers/podman/v4/pkg/criu"
"github.com/containers/podman/v4/pkg/lookup"
- "github.com/containers/podman/v4/pkg/resolvconf"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/podman/v4/utils"
@@ -388,6 +387,37 @@ func lookupHostUser(name string) (*runcuser.ExecUser, error) {
return &execUser, nil
}
+// Internal only function which returns upper and work dir from
+// overlay options.
+func getOverlayUpperAndWorkDir(options []string) (string, string, error) {
+ upperDir := ""
+ workDir := ""
+ for _, o := range options {
+ if strings.HasPrefix(o, "upperdir") {
+ splitOpt := strings.SplitN(o, "=", 2)
+ if len(splitOpt) > 1 {
+ upperDir = splitOpt[1]
+ if upperDir == "" {
+ return "", "", errors.New("cannot accept empty value for upperdir")
+ }
+ }
+ }
+ if strings.HasPrefix(o, "workdir") {
+ splitOpt := strings.SplitN(o, "=", 2)
+ if len(splitOpt) > 1 {
+ workDir = splitOpt[1]
+ if workDir == "" {
+ return "", "", errors.New("cannot accept empty value for workdir")
+ }
+ }
+ }
+ }
+ if (upperDir != "" && workDir == "") || (upperDir == "" && workDir != "") {
+ return "", "", errors.New("must specify both upperdir and workdir")
+ }
+ return upperDir, workDir, nil
+}
+
// Generate spec for a container
// Accepts a map of the container's dependencies
func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
@@ -407,6 +437,14 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
//nolint:staticcheck
g := generate.NewFromSpec(c.config.Spec)
+ // If the flag to mount all devices is set for a privileged container, add
+ // all the devices from the host's machine into the container
+ if c.config.MountAllDevices {
+ if err := util.AddPrivilegedDevices(&g); err != nil {
+ return nil, err
+ }
+ }
+
// If network namespace was requested, add it now
if c.config.CreateNetNS {
if c.config.PostConfigureNetNS {
@@ -460,23 +498,9 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
for _, o := range namedVol.Options {
if o == "O" {
overlayFlag = true
- }
- if overlayFlag && strings.Contains(o, "upperdir") {
- splitOpt := strings.SplitN(o, "=", 2)
- if len(splitOpt) > 1 {
- upperDir = splitOpt[1]
- if upperDir == "" {
- return nil, errors.New("cannot accept empty value for upperdir")
- }
- }
- }
- if overlayFlag && strings.Contains(o, "workdir") {
- splitOpt := strings.SplitN(o, "=", 2)
- if len(splitOpt) > 1 {
- workDir = splitOpt[1]
- if workDir == "" {
- return nil, errors.New("cannot accept empty value for workdir")
- }
+ upperDir, workDir, err = getOverlayUpperAndWorkDir(namedVol.Options)
+ if err != nil {
+ return nil, err
}
}
}
@@ -489,10 +513,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return nil, err
}
- if (upperDir != "" && workDir == "") || (upperDir == "" && workDir != "") {
- return nil, errors.Wrapf(err, "must specify both upperdir and workdir")
- }
-
overlayOpts = &overlay.Options{RootUID: c.RootUID(),
RootGID: c.RootGID(),
UpperDirOptionFragment: upperDir,
@@ -585,11 +605,22 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// Add overlay volumes
for _, overlayVol := range c.config.OverlayVolumes {
+ upperDir, workDir, err := getOverlayUpperAndWorkDir(overlayVol.Options)
+ if err != nil {
+ return nil, err
+ }
contentDir, err := overlay.TempDir(c.config.StaticDir, c.RootUID(), c.RootGID())
if err != nil {
return nil, err
}
- overlayMount, err := overlay.Mount(contentDir, overlayVol.Source, overlayVol.Dest, c.RootUID(), c.RootGID(), c.runtime.store.GraphOptions())
+ overlayOpts := &overlay.Options{RootUID: c.RootUID(),
+ RootGID: c.RootGID(),
+ UpperDirOptionFragment: upperDir,
+ WorkDirOptionFragment: workDir,
+ GraphOpts: c.runtime.store.GraphOptions(),
+ }
+
+ overlayMount, err := overlay.MountWithOptions(contentDir, overlayVol.Source, overlayVol.Dest, overlayOpts)
if err != nil {
return nil, errors.Wrapf(err, "mounting overlay failed %q", overlayVol.Source)
}
@@ -2284,49 +2315,10 @@ rootless=%d
// generateResolvConf generates a containers resolv.conf
func (c *Container) generateResolvConf() error {
var (
- nameservers []string
networkNameServers []string
networkSearchDomains []string
)
- hostns := true
- resolvConf := "/etc/resolv.conf"
- for _, namespace := range c.config.Spec.Linux.Namespaces {
- if namespace.Type == spec.NetworkNamespace {
- hostns = false
- if namespace.Path != "" && !strings.HasPrefix(namespace.Path, "/proc/") {
- definedPath := filepath.Join("/etc/netns", filepath.Base(namespace.Path), "resolv.conf")
- _, err := os.Stat(definedPath)
- if err == nil {
- resolvConf = definedPath
- } else if !os.IsNotExist(err) {
- return err
- }
- }
- break
- }
- }
-
- contents, err := ioutil.ReadFile(resolvConf)
- // resolv.conf doesn't have to exists
- if err != nil && !os.IsNotExist(err) {
- return err
- }
-
- ns := resolvconf.GetNameservers(contents)
- // check if systemd-resolved is used, assume it is used when 127.0.0.53 is the only nameserver
- if !hostns && len(ns) == 1 && ns[0] == "127.0.0.53" {
- // read the actual resolv.conf file for systemd-resolved
- resolvedContents, err := ioutil.ReadFile("/run/systemd/resolve/resolv.conf")
- if err != nil {
- if !os.IsNotExist(err) {
- return errors.Wrapf(err, "detected that systemd-resolved is in use, but could not locate real resolv.conf")
- }
- } else {
- contents = resolvedContents
- }
- }
-
netStatus := c.getNetworkStatus()
for _, status := range netStatus {
if status.DNSServerIPs != nil {
@@ -2346,34 +2338,18 @@ func (c *Container) generateResolvConf() error {
return err
}
- // Ensure that the container's /etc/resolv.conf is compatible with its
- // network configuration.
- resolv, err := resolvconf.FilterResolvDNS(contents, ipv6, !hostns)
- if err != nil {
- return errors.Wrapf(err, "error parsing host resolv.conf")
+ nameservers := make([]string, 0, len(c.runtime.config.Containers.DNSServers)+len(c.config.DNSServer))
+ nameservers = append(nameservers, c.runtime.config.Containers.DNSServers...)
+ for _, ip := range c.config.DNSServer {
+ nameservers = append(nameservers, ip.String())
}
-
- dns := make([]net.IP, 0, len(c.runtime.config.Containers.DNSServers)+len(c.config.DNSServer))
- for _, i := range c.runtime.config.Containers.DNSServers {
- result := net.ParseIP(i)
- if result == nil {
- return errors.Wrapf(define.ErrInvalidArg, "invalid IP address %s", i)
- }
- dns = append(dns, result)
- }
- dns = append(dns, c.config.DNSServer...)
// If the user provided dns, it trumps all; then dns masq; then resolv.conf
var search []string
- switch {
- case len(dns) > 0:
- // We store DNS servers as net.IP, so need to convert to string
- for _, server := range dns {
- nameservers = append(nameservers, server.String())
- }
- default:
- // Make a new resolv.conf
+ keepHostServers := false
+ if len(nameservers) == 0 {
+ keepHostServers = true
// first add the nameservers from the networks status
- nameservers = append(nameservers, networkNameServers...)
+ nameservers = networkNameServers
// when we add network dns server we also have to add the search domains
search = networkSearchDomains
// slirp4netns has a built in DNS forwarder.
@@ -2385,38 +2361,34 @@ func (c *Container) generateResolvConf() error {
nameservers = append(nameservers, slirp4netnsDNS.String())
}
}
- nameservers = append(nameservers, resolvconf.GetNameservers(resolv.Content)...)
}
if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 {
- if !cutil.StringInSlice(".", c.config.DNSSearch) {
- search = append(search, c.runtime.config.Containers.DNSSearches...)
- search = append(search, c.config.DNSSearch...)
- }
- } else {
- search = append(search, resolvconf.GetSearchDomains(resolv.Content)...)
+ customSearch := make([]string, 0, len(c.config.DNSSearch)+len(c.runtime.config.Containers.DNSSearches))
+ customSearch = append(customSearch, c.runtime.config.Containers.DNSSearches...)
+ customSearch = append(customSearch, c.config.DNSSearch...)
+ search = customSearch
}
- var options []string
- if len(c.config.DNSOption) > 0 || len(c.runtime.config.Containers.DNSOptions) > 0 {
- options = c.runtime.config.Containers.DNSOptions
- options = append(options, c.config.DNSOption...)
- } else {
- options = resolvconf.GetOptions(resolv.Content)
- }
+ options := make([]string, 0, len(c.config.DNSOption)+len(c.runtime.config.Containers.DNSOptions))
+ options = append(options, c.runtime.config.Containers.DNSOptions...)
+ options = append(options, c.config.DNSOption...)
destPath := filepath.Join(c.state.RunDir, "resolv.conf")
- if err := os.Remove(destPath); err != nil && !os.IsNotExist(err) {
- return errors.Wrapf(err, "container %s", c.ID())
- }
-
- // Build resolv.conf
- if _, err = resolvconf.Build(destPath, nameservers, search, options); err != nil {
+ if err := resolvconf.New(&resolvconf.Params{
+ IPv6Enabled: ipv6,
+ KeepHostServers: keepHostServers,
+ Nameservers: nameservers,
+ Namespaces: c.config.Spec.Linux.Namespaces,
+ Options: options,
+ Path: destPath,
+ Searches: search,
+ }); err != nil {
return errors.Wrapf(err, "error building resolv.conf for container %s", c.ID())
}
- return c.bindMountRootFile(destPath, "/etc/resolv.conf")
+ return c.bindMountRootFile(destPath, resolvconf.DefaultResolvConf)
}
// Check if a container uses IPv6.
@@ -2457,31 +2429,13 @@ func (c *Container) addNameserver(ips []string) error {
}
// Do we have a resolv.conf at all?
- path, ok := c.state.BindMounts["/etc/resolv.conf"]
+ path, ok := c.state.BindMounts[resolvconf.DefaultResolvConf]
if !ok {
return nil
}
- // Read in full contents, parse out existing nameservers
- contents, err := ioutil.ReadFile(path)
- if err != nil {
- return err
- }
- ns := resolvconf.GetNameservers(contents)
- options := resolvconf.GetOptions(contents)
- search := resolvconf.GetSearchDomains(contents)
-
- // We could verify that it doesn't already exist
- // but extra nameservers shouldn't harm anything.
- // Ensure we are the first entry in resolv.conf though, otherwise we
- // might be after user-added servers.
- ns = append(ips, ns...)
-
- // We're rewriting the container's resolv.conf as part of this, but we
- // hold the container lock, so there should be no risk of parallel
- // modification.
- if _, err := resolvconf.Build(path, ns, search, options); err != nil {
- return errors.Wrapf(err, "error adding new nameserver to container %s resolv.conf", c.ID())
+ if err := resolvconf.Add(path, ips); err != nil {
+ return fmt.Errorf("adding new nameserver to container %s resolv.conf: %w", c.ID(), err)
}
return nil
@@ -2496,34 +2450,13 @@ func (c *Container) removeNameserver(ips []string) error {
}
// Do we have a resolv.conf at all?
- path, ok := c.state.BindMounts["/etc/resolv.conf"]
+ path, ok := c.state.BindMounts[resolvconf.DefaultResolvConf]
if !ok {
return nil
}
- // Read in full contents, parse out existing nameservers
- contents, err := ioutil.ReadFile(path)
- if err != nil {
- return err
- }
- ns := resolvconf.GetNameservers(contents)
- options := resolvconf.GetOptions(contents)
- search := resolvconf.GetSearchDomains(contents)
-
- toRemove := make(map[string]bool)
- for _, ip := range ips {
- toRemove[ip] = true
- }
-
- newNS := make([]string, 0, len(ns))
- for _, server := range ns {
- if !toRemove[server] {
- newNS = append(newNS, server)
- }
- }
-
- if _, err := resolvconf.Build(path, newNS, search, options); err != nil {
- return errors.Wrapf(err, "error removing nameservers from container %s resolv.conf", c.ID())
+ if err := resolvconf.Remove(path, ips); err != nil {
+ return fmt.Errorf("removing nameservers from container %s resolv.conf: %w", c.ID(), err)
}
return nil
diff --git a/libpod/container_log.go b/libpod/container_log.go
index 7a9eb2dbf..da6d51670 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -75,7 +75,6 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
go func() {
defer options.WaitGroup.Done()
- var partial string
for line := range t.Lines {
select {
case <-ctx.Done():
@@ -89,13 +88,6 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
logrus.Errorf("Getting new log line: %v", err)
continue
}
- if nll.Partial() {
- partial += nll.Msg
- continue
- } else if !nll.Partial() && len(partial) > 0 {
- nll.Msg = partial + nll.Msg
- partial = ""
- }
nll.CID = c.ID()
nll.CName = c.Name()
nll.ColorID = colorID
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 37fa9b5f5..ee80b00fe 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -21,6 +21,7 @@ import (
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/common/libnetwork/etchosts"
+ "github.com/containers/common/libnetwork/resolvconf"
"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/machine"
@@ -30,11 +31,10 @@ import (
"github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/errorhandling"
"github.com/containers/podman/v4/pkg/namespaces"
- "github.com/containers/podman/v4/pkg/resolvconf"
"github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/lockfile"
- spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -526,23 +526,19 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
return nil, errors.Wrapf(err, "failed to determine slirp4netns DNS address from cidr: %s", cidr.String())
}
}
- conf, err := resolvconf.Get()
- if err != nil {
- return nil, err
- }
- conf, err = resolvconf.FilterResolvDNS(conf.Content, netOptions.enableIPv6, true)
- if err != nil {
- return nil, err
- }
- searchDomains := resolvconf.GetSearchDomains(conf.Content)
- dnsOptions := resolvconf.GetOptions(conf.Content)
- nameServers := resolvconf.GetNameservers(conf.Content)
- _, err = resolvconf.Build(filepath.Join(rootlessNetNsDir, "resolv.conf"), append([]string{resolveIP.String()}, nameServers...), searchDomains, dnsOptions)
- if err != nil {
+ if err := resolvconf.New(&resolvconf.Params{
+ Path: filepath.Join(rootlessNetNsDir, "resolv.conf"),
+ // fake the netns since we want to filter localhost
+ Namespaces: []specs.LinuxNamespace{
+ {Type: specs.NetworkNamespace},
+ },
+ IPv6Enabled: netOptions.enableIPv6,
+ KeepHostServers: true,
+ Nameservers: []string{resolveIP.String()},
+ }); err != nil {
return nil, errors.Wrap(err, "failed to create rootless netns resolv.conf")
}
-
// create cni directories to store files
// they will be bind mounted to the correct location in a extra mount ns
err = os.MkdirAll(filepath.Join(rootlessNetNsDir, persistentCNIDir), 0700)
@@ -1089,7 +1085,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
func (c *Container) joinedNetworkNSPath() string {
for _, namespace := range c.config.Spec.Linux.Namespaces {
- if namespace.Type == spec.NetworkNamespace {
+ if namespace.Type == specs.NetworkNamespace {
return namespace.Path
}
}
diff --git a/libpod/options.go b/libpod/options.go
index a02c05537..8b3b07efa 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -435,6 +435,21 @@ func WithDefaultInfraCommand(cmd string) RuntimeOption {
}
}
+// WithReset instructs libpod to reset all storage to factory defaults.
+// All containers, pods, volumes, images, and networks will be removed.
+// All directories created by Libpod will be removed.
+func WithReset() RuntimeOption {
+ return func(rt *Runtime) error {
+ if rt.valid {
+ return define.ErrRuntimeFinalized
+ }
+
+ rt.doReset = true
+
+ return nil
+ }
+}
+
// WithRenumber instructs libpod to perform a lock renumbering while
// initializing. This will handle migrations from early versions of libpod with
// file locks to newer versions with SHM locking, as well as changes in the
@@ -2159,3 +2174,17 @@ func WithPasswdEntry(passwdEntry string) CtrCreateOption {
return nil
}
}
+
+// WithMountAllDevices sets the option to mount all of a privileged container's
+// host devices
+func WithMountAllDevices() CtrCreateOption {
+ return func(ctr *Container) error {
+ if ctr.valid {
+ return define.ErrCtrFinalized
+ }
+
+ ctr.config.MountAllDevices = true
+
+ return nil
+ }
+}
diff --git a/libpod/reset.go b/libpod/reset.go
index 28d0ee3f6..30eab50fb 100644
--- a/libpod/reset.go
+++ b/libpod/reset.go
@@ -17,8 +17,78 @@ import (
"github.com/sirupsen/logrus"
)
+// removeAllDirs removes all Podman storage directories. It is intended to be
+// used as a backup for reset() when that function cannot be used due to
+// failures in initializing libpod.
+// It does not expect that all the directories match what is in use by Podman,
+// as this is a common failure point for `system reset`. As such, our ability to
+// interface with containers and pods is somewhat limited.
+// This function assumes that we do not have a working c/storage store.
+func (r *Runtime) removeAllDirs() error {
+ var lastErr error
+
+ // Grab the runtime alive lock.
+ // This ensures that no other Podman process can run while we are doing
+ // a reset, so no race conditions with containers/pods/etc being created
+ // while we are resetting storage.
+ // TODO: maybe want a helper for getting the path? This is duped from
+ // runtime.go
+ runtimeAliveLock := filepath.Join(r.config.Engine.TmpDir, "alive.lck")
+ aliveLock, err := storage.GetLockfile(runtimeAliveLock)
+ if err != nil {
+ logrus.Errorf("Lock runtime alive lock %s: %v", runtimeAliveLock, err)
+ } else {
+ aliveLock.Lock()
+ defer aliveLock.Unlock()
+ }
+
+ // We do not have a store - so we can't really try and remove containers
+ // or pods or volumes...
+ // Try and remove the directories, in hopes that they are unmounted.
+ // This is likely to fail but it's the best we can do.
+
+ // Volume path
+ if err := os.RemoveAll(r.config.Engine.VolumePath); err != nil {
+ lastErr = errors.Wrapf(err, "removing volume path")
+ }
+
+ // Tmpdir
+ if err := os.RemoveAll(r.config.Engine.TmpDir); err != nil {
+ if lastErr != nil {
+ logrus.Errorf("Reset: %v", lastErr)
+ }
+ lastErr = errors.Wrapf(err, "removing tmp dir")
+ }
+
+ // Runroot
+ if err := os.RemoveAll(r.storageConfig.RunRoot); err != nil {
+ if lastErr != nil {
+ logrus.Errorf("Reset: %v", lastErr)
+ }
+ lastErr = errors.Wrapf(err, "removing run root")
+ }
+
+ // Static dir
+ if err := os.RemoveAll(r.config.Engine.StaticDir); err != nil {
+ if lastErr != nil {
+ logrus.Errorf("Reset: %v", lastErr)
+ }
+ lastErr = errors.Wrapf(err, "removing static dir")
+ }
+
+ // Graph root
+ if err := os.RemoveAll(r.storageConfig.GraphRoot); err != nil {
+ if lastErr != nil {
+ logrus.Errorf("Reset: %v", lastErr)
+ }
+ lastErr = errors.Wrapf(err, "removing graph root")
+ }
+
+ return lastErr
+}
+
// Reset removes all storage
-func (r *Runtime) Reset(ctx context.Context) error {
+func (r *Runtime) reset(ctx context.Context) error {
var timeout *uint
pods, err := r.GetAllPods()
if err != nil {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index e268c2d17..6c8a99846 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -96,6 +96,10 @@ type Runtime struct {
// This bool is just needed so that we can set it for netavark interface.
syslog bool
+ // doReset indicates that the runtime should perform a system reset.
+ // All Podman files will be removed.
+ doReset bool
+
// doRenumber indicates that the runtime should perform a lock renumber
// during initialization.
// Once the runtime has been initialized and returned, this variable is
@@ -235,6 +239,11 @@ func newRuntimeFromConfig(conf *config.Config, options ...RuntimeOption) (*Runti
runtime.config.CheckCgroupsAndAdjustConfig()
+ // If resetting storage, do *not* return a runtime.
+ if runtime.doReset {
+ return nil, nil
+ }
+
return runtime, nil
}
@@ -305,6 +314,13 @@ func makeRuntime(runtime *Runtime) (retErr error) {
}
runtime.conmonPath = cPath
+ if runtime.noStore && runtime.doReset {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot perform system reset if runtime is not creating a store")
+ }
+ if runtime.doReset && runtime.doRenumber {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot perform system reset while renumbering locks")
+ }
+
// Make the static files directory if it does not exist
if err := os.MkdirAll(runtime.config.Engine.StaticDir, 0700); err != nil {
// The directory is allowed to exist
@@ -339,6 +355,20 @@ func makeRuntime(runtime *Runtime) (retErr error) {
// Grab config from the database so we can reset some defaults
dbConfig, err := runtime.state.GetDBConfig()
if err != nil {
+ if runtime.doReset {
+ // We can at least delete the DB and the static files
+ // directory.
+ // Can't safely touch anything else because we aren't
+ // sure of other directories.
+ if err := runtime.state.Close(); err != nil {
+ logrus.Errorf("Closing database connection: %v", err)
+ } else {
+ if err := os.RemoveAll(runtime.config.Engine.StaticDir); err != nil {
+ logrus.Errorf("Removing static files directory %v: %v", runtime.config.Engine.StaticDir, err)
+ }
+ }
+ }
+
return errors.Wrapf(err, "error retrieving runtime configuration from database")
}
@@ -372,7 +402,13 @@ func makeRuntime(runtime *Runtime) (retErr error) {
// Validate our config against the database, now that we've set our
// final storage configuration
if err := runtime.state.ValidateDBConfig(runtime); err != nil {
- return err
+ // If we are performing a storage reset: continue on with a
+ // warning. Otherwise we can't `system reset` after a change to
+ // the core paths.
+ if !runtime.doReset {
+ return err
+ }
+ logrus.Errorf("Runtime paths differ from those stored in database, storage reset may not remove all files")
}
if err := runtime.state.SetNamespace(runtime.config.Engine.Namespace); err != nil {
@@ -394,6 +430,14 @@ func makeRuntime(runtime *Runtime) (retErr error) {
} else if runtime.noStore {
logrus.Debug("No store required. Not opening container store.")
} else if err := runtime.configureStore(); err != nil {
+ // Make a best-effort attempt to clean up if performing a
+ // storage reset.
+ if runtime.doReset {
+ if err := runtime.removeAllDirs(); err != nil {
+ logrus.Errorf("Removing libpod directories: %v", err)
+ }
+ }
+
return err
}
defer func() {
@@ -575,6 +619,18 @@ func makeRuntime(runtime *Runtime) (retErr error) {
return err
}
+ // If we're resetting storage, do it now.
+ // We will not return a valid runtime.
+ // TODO: Plumb this context out so it can be set.
+ if runtime.doReset {
+ // Mark the runtime as valid, so normal functionality "mostly"
+ // works and we can use regular functions to remove
+ // ctrs/pods/etc
+ runtime.valid = true
+
+ return runtime.reset(context.Background())
+ }
+
// If we're renumbering locks, do it now.
// It breaks out of normal runtime init, and will not return a valid
// runtime.
@@ -818,7 +874,7 @@ func (r *Runtime) DeferredShutdown(force bool) {
// still containers running or mounted
func (r *Runtime) Shutdown(force bool) error {
if !r.valid {
- return define.ErrRuntimeStopped
+ return nil
}
if r.workerChannel != nil {
@@ -1067,7 +1123,7 @@ func (r *Runtime) mergeDBConfig(dbConfig *DBConfig) {
if !r.storageSet.GraphDriverNameSet && dbConfig.GraphDriver != "" {
if r.storageConfig.GraphDriverName != dbConfig.GraphDriver &&
r.storageConfig.GraphDriverName != "" {
- logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve",
+ logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve. May prevent use of images created by other tools",
r.storageConfig.GraphDriverName, dbConfig.GraphDriver)
}
r.storageConfig.GraphDriverName = dbConfig.GraphDriver
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index f47aa523e..fe17aa1d4 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -70,68 +70,69 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}()
query := struct {
- AddHosts string `schema:"extrahosts"`
- AdditionalCapabilities string `schema:"addcaps"`
- AllPlatforms bool `schema:"allplatforms"`
- Annotations string `schema:"annotations"`
- AppArmor string `schema:"apparmor"`
- BuildArgs string `schema:"buildargs"`
- CacheFrom string `schema:"cachefrom"`
- CgroupParent string `schema:"cgroupparent"` // nolint
- Compression uint64 `schema:"compression"`
- ConfigureNetwork string `schema:"networkmode"`
- CPPFlags string `schema:"cppflags"`
- CpuPeriod uint64 `schema:"cpuperiod"` // nolint
- CpuQuota int64 `schema:"cpuquota"` // nolint
- CpuSetCpus string `schema:"cpusetcpus"` // nolint
- CpuSetMems string `schema:"cpusetmems"` // nolint
- CpuShares uint64 `schema:"cpushares"` // nolint
- DNSOptions string `schema:"dnsoptions"`
- DNSSearch string `schema:"dnssearch"`
- DNSServers string `schema:"dnsservers"`
- Devices string `schema:"devices"`
- Dockerfile string `schema:"dockerfile"`
- DropCapabilities string `schema:"dropcaps"`
- Envs []string `schema:"setenv"`
- Excludes string `schema:"excludes"`
- ForceRm bool `schema:"forcerm"`
- From string `schema:"from"`
- HTTPProxy bool `schema:"httpproxy"`
- IdentityLabel bool `schema:"identitylabel"`
- Ignore bool `schema:"ignore"`
- Isolation string `schema:"isolation"`
- Jobs int `schema:"jobs"` // nolint
- LabelOpts string `schema:"labelopts"`
- Labels string `schema:"labels"`
- Layers bool `schema:"layers"`
- LogRusage bool `schema:"rusage"`
- Manifest string `schema:"manifest"`
- MemSwap int64 `schema:"memswap"`
- Memory int64 `schema:"memory"`
- NamespaceOptions string `schema:"nsoptions"`
- NoCache bool `schema:"nocache"`
- OSFeatures []string `schema:"osfeature"`
- OSVersion string `schema:"osversion"`
- OutputFormat string `schema:"outputformat"`
- Platform []string `schema:"platform"`
- Pull bool `schema:"pull"`
- PullPolicy string `schema:"pullpolicy"`
- Quiet bool `schema:"q"`
- Registry string `schema:"registry"`
- Rm bool `schema:"rm"`
- RusageLogFile string `schema:"rusagelogfile"`
- Remote string `schema:"remote"`
- Seccomp string `schema:"seccomp"`
- Secrets string `schema:"secrets"`
- SecurityOpt string `schema:"securityopt"`
- ShmSize int `schema:"shmsize"`
- Squash bool `schema:"squash"`
- TLSVerify bool `schema:"tlsVerify"`
- Tags []string `schema:"t"`
- Target string `schema:"target"`
- Timestamp int64 `schema:"timestamp"`
- Ulimits string `schema:"ulimits"`
- UnsetEnvs []string `schema:"unsetenv"`
+ AddHosts string `schema:"extrahosts"`
+ AdditionalCapabilities string `schema:"addcaps"`
+ AdditionalBuildContexts string `schema:"additionalbuildcontexts"`
+ AllPlatforms bool `schema:"allplatforms"`
+ Annotations string `schema:"annotations"`
+ AppArmor string `schema:"apparmor"`
+ BuildArgs string `schema:"buildargs"`
+ CacheFrom string `schema:"cachefrom"`
+ CgroupParent string `schema:"cgroupparent"` // nolint
+ Compression uint64 `schema:"compression"`
+ ConfigureNetwork string `schema:"networkmode"`
+ CPPFlags string `schema:"cppflags"`
+ CpuPeriod uint64 `schema:"cpuperiod"` // nolint
+ CpuQuota int64 `schema:"cpuquota"` // nolint
+ CpuSetCpus string `schema:"cpusetcpus"` // nolint
+ CpuSetMems string `schema:"cpusetmems"` // nolint
+ CpuShares uint64 `schema:"cpushares"` // nolint
+ DNSOptions string `schema:"dnsoptions"`
+ DNSSearch string `schema:"dnssearch"`
+ DNSServers string `schema:"dnsservers"`
+ Devices string `schema:"devices"`
+ Dockerfile string `schema:"dockerfile"`
+ DropCapabilities string `schema:"dropcaps"`
+ Envs []string `schema:"setenv"`
+ Excludes string `schema:"excludes"`
+ ForceRm bool `schema:"forcerm"`
+ From string `schema:"from"`
+ HTTPProxy bool `schema:"httpproxy"`
+ IdentityLabel bool `schema:"identitylabel"`
+ Ignore bool `schema:"ignore"`
+ Isolation string `schema:"isolation"`
+ Jobs int `schema:"jobs"` // nolint
+ LabelOpts string `schema:"labelopts"`
+ Labels string `schema:"labels"`
+ Layers bool `schema:"layers"`
+ LogRusage bool `schema:"rusage"`
+ Manifest string `schema:"manifest"`
+ MemSwap int64 `schema:"memswap"`
+ Memory int64 `schema:"memory"`
+ NamespaceOptions string `schema:"nsoptions"`
+ NoCache bool `schema:"nocache"`
+ OSFeatures []string `schema:"osfeature"`
+ OSVersion string `schema:"osversion"`
+ OutputFormat string `schema:"outputformat"`
+ Platform []string `schema:"platform"`
+ Pull bool `schema:"pull"`
+ PullPolicy string `schema:"pullpolicy"`
+ Quiet bool `schema:"q"`
+ Registry string `schema:"registry"`
+ Rm bool `schema:"rm"`
+ RusageLogFile string `schema:"rusagelogfile"`
+ Remote string `schema:"remote"`
+ Seccomp string `schema:"seccomp"`
+ Secrets string `schema:"secrets"`
+ SecurityOpt string `schema:"securityopt"`
+ ShmSize int `schema:"shmsize"`
+ Squash bool `schema:"squash"`
+ TLSVerify bool `schema:"tlsVerify"`
+ Tags []string `schema:"t"`
+ Target string `schema:"target"`
+ Timestamp int64 `schema:"timestamp"`
+ Ulimits string `schema:"ulimits"`
+ UnsetEnvs []string `schema:"unsetenv"`
}{
Dockerfile: "Dockerfile",
IdentityLabel: true,
@@ -375,6 +376,14 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
additionalTags = append(additionalTags, possiblyNormalizedTag)
}
+ var additionalBuildContexts = map[string]*buildahDefine.AdditionalBuildContext{}
+ if _, found := r.URL.Query()["additionalbuildcontexts"]; found {
+ if err := json.Unmarshal([]byte(query.AdditionalBuildContexts), &additionalBuildContexts); err != nil {
+ utils.BadRequest(w, "additionalbuildcontexts", query.AdditionalBuildContexts, err)
+ return
+ }
+ }
+
var buildArgs = map[string]string{}
if _, found := r.URL.Query()["buildargs"]; found {
if err := json.Unmarshal([]byte(query.BuildArgs), &buildArgs); err != nil {
@@ -562,12 +571,13 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
buildOptions := buildahDefine.BuildOptions{
- AddCapabilities: addCaps,
- AdditionalTags: additionalTags,
- Annotations: annotations,
- CPPFlags: cppflags,
- Args: buildArgs,
- AllPlatforms: query.AllPlatforms,
+ AddCapabilities: addCaps,
+ AdditionalBuildContexts: additionalBuildContexts,
+ AdditionalTags: additionalTags,
+ Annotations: annotations,
+ CPPFlags: cppflags,
+ Args: buildArgs,
+ AllPlatforms: query.AllPlatforms,
CommonBuildOpts: &buildah.CommonBuildOptions{
AddHost: addhosts,
ApparmorProfile: apparmor,
diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go
index b71afc28c..36e61c986 100644
--- a/pkg/api/handlers/libpod/play.go
+++ b/pkg/api/handlers/libpod/play.go
@@ -77,7 +77,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
utils.Error(w, http.StatusInternalServerError, err)
return
}
- query.LogDriver = config.Containers.LogDriver
+ logDriver = config.Containers.LogDriver
}
containerEngine := abi.ContainerEngine{Libpod: runtime}
@@ -89,7 +89,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) {
Networks: query.Network,
NoHosts: query.NoHosts,
Quiet: true,
- LogDriver: query.LogDriver,
+ LogDriver: logDriver,
LogOptions: query.LogOptions,
StaticIPs: staticIPs,
StaticMACs: staticMACs,
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index b4b7c36f6..fe81dc662 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -81,6 +81,13 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
for _, tag := range options.AdditionalTags {
params.Add("t", tag)
}
+ if additionalBuildContexts := options.AdditionalBuildContexts; len(additionalBuildContexts) > 0 {
+ additionalBuildContextMap, err := jsoniter.Marshal(additionalBuildContexts)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("additionalbuildcontexts", string(additionalBuildContextMap))
+ }
if buildArgs := options.Args; len(buildArgs) > 0 {
bArgs, err := jsoniter.MarshalToString(buildArgs)
if err != nil {
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 2ce190464..762f0d79a 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -328,7 +328,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
}
func (se *SystemEngine) Reset(ctx context.Context) error {
- return se.Libpod.Reset(ctx)
+ return nil
}
func (se *SystemEngine) Renumber(ctx context.Context, flags *pflag.FlagSet, config *entities.PodmanConfig) error {
diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go
index 39989c96b..7b5198d2f 100644
--- a/pkg/domain/infra/runtime_abi.go
+++ b/pkg/domain/infra/runtime_abi.go
@@ -53,7 +53,7 @@ func NewSystemEngine(setup entities.EngineSetup, facts *entities.PodmanConfig) (
case entities.RenumberMode:
r, err = GetRuntimeRenumber(context.Background(), facts.FlagSet, facts)
case entities.ResetMode:
- r, err = GetRuntimeRenumber(context.Background(), facts.FlagSet, facts)
+ r, err = GetRuntimeReset(context.Background(), facts.FlagSet, facts)
case entities.MigrateMode:
name, flagErr := facts.FlagSet.GetString("new-runtime")
if flagErr != nil {
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index daa6f0cbf..03e7ffb5d 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -37,6 +37,7 @@ type engineOpts struct {
migrate bool
noStore bool
withFDS bool
+ reset bool
config *entities.PodmanConfig
}
@@ -48,6 +49,7 @@ func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, cfg *entities.Podm
migrate: true,
noStore: false,
withFDS: true,
+ reset: false,
config: cfg,
})
}
@@ -59,6 +61,7 @@ func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, cfg *entities.P
migrate: false,
noStore: false,
withFDS: false,
+ reset: false,
config: cfg,
})
}
@@ -70,6 +73,7 @@ func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, cfg *entities.Pod
migrate: false,
noStore: false,
withFDS: true,
+ reset: false,
config: cfg,
})
}
@@ -82,6 +86,7 @@ func GetRuntime(ctx context.Context, flags *flag.FlagSet, cfg *entities.PodmanCo
migrate: false,
noStore: false,
withFDS: true,
+ reset: false,
config: cfg,
})
})
@@ -95,6 +100,18 @@ func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, cfg *entities.Podm
migrate: false,
noStore: true,
withFDS: true,
+ reset: false,
+ config: cfg,
+ })
+}
+
+func GetRuntimeReset(ctx context.Context, fs *flag.FlagSet, cfg *entities.PodmanConfig) (*libpod.Runtime, error) {
+ return getRuntime(ctx, fs, &engineOpts{
+ renumber: false,
+ migrate: false,
+ noStore: false,
+ withFDS: true,
+ reset: true,
config: cfg,
})
}
@@ -161,6 +178,10 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
}
}
+ if opts.reset {
+ options = append(options, libpod.WithReset())
+ }
+
if opts.renumber {
options = append(options, libpod.WithRenumber())
}
diff --git a/pkg/resolvconf/dns/resolvconf.go b/pkg/resolvconf/dns/resolvconf.go
deleted file mode 100644
index cb4bd1033..000000000
--- a/pkg/resolvconf/dns/resolvconf.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Originally from github.com/docker/libnetwork/resolvconf/dns
-
-package dns
-
-import (
- "regexp"
-)
-
-// IPLocalhost is a regex pattern for IPv4 or IPv6 loopback range.
-const IPLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1)$)`
-
-// IPv4Localhost is a regex pattern for IPv4 localhost address range.
-const IPv4Localhost = `(127\.([0-9]{1,3}\.){2}[0-9]{1,3})`
-
-var localhostIPRegexp = regexp.MustCompile(IPLocalhost)
-var localhostIPv4Regexp = regexp.MustCompile(IPv4Localhost)
-
-// IsLocalhost returns true if ip matches the localhost IP regular expression.
-// Used for determining if nameserver settings are being passed which are
-// localhost addresses
-func IsLocalhost(ip string) bool {
- return localhostIPRegexp.MatchString(ip)
-}
-
-// IsIPv4Localhost returns true if ip matches the IPv4 localhost regular expression.
-func IsIPv4Localhost(ip string) bool {
- return localhostIPv4Regexp.MatchString(ip)
-}
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index ed2e5408d..4c3748e67 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -3,7 +3,6 @@ package generate
import (
"fmt"
"io/fs"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -11,6 +10,7 @@ import (
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/rootless"
+ "github.com/containers/podman/v4/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
@@ -18,56 +18,6 @@ import (
"golang.org/x/sys/unix"
)
-var (
- errNotADevice = errors.New("not a device node")
-)
-
-func addPrivilegedDevices(g *generate.Generator) error {
- hostDevices, err := getDevices("/dev")
- if err != nil {
- return err
- }
- g.ClearLinuxDevices()
-
- if rootless.IsRootless() {
- mounts := make(map[string]interface{})
- for _, m := range g.Mounts() {
- mounts[m.Destination] = true
- }
- newMounts := []spec.Mount{}
- for _, d := range hostDevices {
- devMnt := spec.Mount{
- Destination: d.Path,
- Type: define.TypeBind,
- Source: d.Path,
- Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"},
- }
- if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") {
- continue
- }
- if _, found := mounts[d.Path]; found {
- continue
- }
- newMounts = append(newMounts, devMnt)
- }
- g.Config.Mounts = append(newMounts, g.Config.Mounts...)
- if g.Config.Linux.Resources != nil {
- g.Config.Linux.Resources.Devices = nil
- }
- } else {
- for _, d := range hostDevices {
- g.AddDevice(d)
- }
- // Add resources device - need to clear the existing one first.
- if g.Config.Linux.Resources != nil {
- g.Config.Linux.Resources.Devices = nil
- }
- g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm")
- }
-
- return nil
-}
-
// DevicesFromPath computes a list of devices
func DevicesFromPath(g *generate.Generator, devicePath string) error {
devs := strings.Split(devicePath, ":")
@@ -174,60 +124,12 @@ func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, mask, unmask
}
}
-// based on getDevices from runc (libcontainer/devices/devices.go)
-func getDevices(path string) ([]spec.LinuxDevice, error) {
- files, err := ioutil.ReadDir(path)
- if err != nil {
- if rootless.IsRootless() && os.IsPermission(err) {
- return nil, nil
- }
- return nil, err
- }
- out := []spec.LinuxDevice{}
- for _, f := range files {
- switch {
- case f.IsDir():
- switch f.Name() {
- // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
- case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
- continue
- default:
- sub, err := getDevices(filepath.Join(path, f.Name()))
- if err != nil {
- return nil, err
- }
- if sub != nil {
- out = append(out, sub...)
- }
- continue
- }
- case f.Name() == "console":
- continue
- case f.Mode()&os.ModeSymlink != 0:
- continue
- }
-
- device, err := deviceFromPath(filepath.Join(path, f.Name()))
- if err != nil {
- if err == errNotADevice {
- continue
- }
- if os.IsNotExist(err) {
- continue
- }
- return nil, err
- }
- out = append(out, *device)
- }
- return out, nil
-}
-
func addDevice(g *generate.Generator, device string) error {
src, dst, permissions, err := ParseDevice(device)
if err != nil {
return err
}
- dev, err := deviceFromPath(src)
+ dev, err := util.DeviceFromPath(src)
if err != nil {
return errors.Wrapf(err, "%s is not a valid device", src)
}
@@ -316,43 +218,6 @@ func IsValidDeviceMode(mode string) bool {
return true
}
-// Copied from github.com/opencontainers/runc/libcontainer/devices
-// Given the path to a device look up the information about a linux device
-func deviceFromPath(path string) (*spec.LinuxDevice, error) {
- var stat unix.Stat_t
- err := unix.Lstat(path, &stat)
- if err != nil {
- return nil, err
- }
- var (
- devType string
- mode = stat.Mode
- devNumber = uint64(stat.Rdev) // nolint: unconvert
- m = os.FileMode(mode)
- )
-
- switch {
- case mode&unix.S_IFBLK == unix.S_IFBLK:
- devType = "b"
- case mode&unix.S_IFCHR == unix.S_IFCHR:
- devType = "c"
- case mode&unix.S_IFIFO == unix.S_IFIFO:
- devType = "p"
- default:
- return nil, errNotADevice
- }
-
- return &spec.LinuxDevice{
- Type: devType,
- Path: path,
- FileMode: &m,
- UID: &stat.Uid,
- GID: &stat.Gid,
- Major: int64(unix.Major(devNumber)),
- Minor: int64(unix.Minor(devNumber)),
- }, nil
-}
-
func supportAmbientCapabilities() bool {
err := unix.Prctl(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, 0, 0, 0)
return err == nil
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 04e24d625..7faf13465 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -278,6 +278,10 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
options = append(options, libpod.WithPasswdEntry(s.PasswdEntry))
}
+ if s.Privileged {
+ options = append(options, libpod.WithMountAllDevices())
+ }
+
useSystemd := false
switch s.Systemd {
case "always":
@@ -542,6 +546,16 @@ func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtim
infraConf := infra.Config()
infraSpec := infraConf.Spec
+ // need to set compatOptions to the currently filled specgenOptions so we do not overwrite
+ compatibleOptions.CapAdd = append(compatibleOptions.CapAdd, s.CapAdd...)
+ compatibleOptions.CapDrop = append(compatibleOptions.CapDrop, s.CapDrop...)
+ compatibleOptions.HostDeviceList = append(compatibleOptions.HostDeviceList, s.HostDeviceList...)
+ compatibleOptions.ImageVolumes = append(compatibleOptions.ImageVolumes, s.ImageVolumes...)
+ compatibleOptions.Mounts = append(compatibleOptions.Mounts, s.Mounts...)
+ compatibleOptions.OverlayVolumes = append(compatibleOptions.OverlayVolumes, s.OverlayVolumes...)
+ compatibleOptions.SelinuxOpts = append(compatibleOptions.SelinuxOpts, s.SelinuxOpts...)
+ compatibleOptions.Volumes = append(compatibleOptions.Volumes, s.Volumes...)
+
compatByte, err := json.Marshal(compatibleOptions)
if err != nil {
return nil, nil, nil, err
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index dda2de6e4..716960024 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -337,14 +337,8 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
}
var userDevices []spec.LinuxDevice
- if s.Privileged {
- // If privileged, we need to add all the host devices to the
- // spec. We do not add the user provided ones because we are
- // already adding them all.
- if err := addPrivilegedDevices(&g); err != nil {
- return nil, err
- }
- } else {
+
+ if !s.Privileged {
// add default devices from containers.conf
for _, device := range rtc.Containers.Devices {
if err = DevicesFromPath(&g, device); err != nil {
diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go
index b26666df3..a7a1022b0 100644
--- a/pkg/specgen/volumes.go
+++ b/pkg/specgen/volumes.go
@@ -97,6 +97,8 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
// This is not a named volume
overlayFlag := false
chownFlag := false
+ upperDirFlag := false
+ workDirFlag := false
for _, o := range options {
if o == "O" {
overlayFlag = true
@@ -105,8 +107,16 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
if strings.Contains(joinedOpts, "U") {
chownFlag = true
}
-
- if len(options) > 2 || (len(options) == 2 && !chownFlag) {
+ if strings.Contains(joinedOpts, "upperdir") {
+ upperDirFlag = true
+ }
+ if strings.Contains(joinedOpts, "workdir") {
+ workDirFlag = true
+ }
+ if (workDirFlag && !upperDirFlag) || (!workDirFlag && upperDirFlag) {
+ return nil, nil, nil, errors.New("must set both `upperdir` and `workdir`")
+ }
+ if len(options) > 2 && !(len(options) == 3 && upperDirFlag && workDirFlag) || (len(options) == 2 && !chownFlag) {
return nil, nil, nil, errors.New("can't use 'O' with other options")
}
}
diff --git a/pkg/util/utils_linux.go b/pkg/util/utils_linux.go
index 0b21bf3c5..871303f64 100644
--- a/pkg/util/utils_linux.go
+++ b/pkg/util/utils_linux.go
@@ -3,13 +3,24 @@ package util
import (
"fmt"
"io/fs"
+ "io/ioutil"
"os"
"path/filepath"
+ "strings"
"syscall"
+ "github.com/containers/podman/v4/libpod/define"
+ "github.com/containers/podman/v4/pkg/rootless"
"github.com/containers/psgo"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
+)
+
+var (
+ errNotADevice = errors.New("not a device node")
)
// GetContainerPidInformationDescriptors returns a string slice of all supported
@@ -59,3 +70,134 @@ func FindDeviceNodes() (map[string]string, error) {
return nodes, nil
}
+
+func AddPrivilegedDevices(g *generate.Generator) error {
+ hostDevices, err := getDevices("/dev")
+ if err != nil {
+ return err
+ }
+ g.ClearLinuxDevices()
+
+ if rootless.IsRootless() {
+ mounts := make(map[string]interface{})
+ for _, m := range g.Mounts() {
+ mounts[m.Destination] = true
+ }
+ newMounts := []spec.Mount{}
+ for _, d := range hostDevices {
+ devMnt := spec.Mount{
+ Destination: d.Path,
+ Type: define.TypeBind,
+ Source: d.Path,
+ Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"},
+ }
+ if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") {
+ continue
+ }
+ if _, found := mounts[d.Path]; found {
+ continue
+ }
+ newMounts = append(newMounts, devMnt)
+ }
+ g.Config.Mounts = append(newMounts, g.Config.Mounts...)
+ if g.Config.Linux.Resources != nil {
+ g.Config.Linux.Resources.Devices = nil
+ }
+ } else {
+ for _, d := range hostDevices {
+ g.AddDevice(d)
+ }
+ // Add resources device - need to clear the existing one first.
+ if g.Config.Linux.Resources != nil {
+ g.Config.Linux.Resources.Devices = nil
+ }
+ g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm")
+ }
+
+ return nil
+}
+
+// based on getDevices from runc (libcontainer/devices/devices.go)
+func getDevices(path string) ([]spec.LinuxDevice, error) {
+ files, err := ioutil.ReadDir(path)
+ if err != nil {
+ if rootless.IsRootless() && os.IsPermission(err) {
+ return nil, nil
+ }
+ return nil, err
+ }
+ out := []spec.LinuxDevice{}
+ for _, f := range files {
+ switch {
+ case f.IsDir():
+ switch f.Name() {
+ // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
+ case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
+ continue
+ default:
+ sub, err := getDevices(filepath.Join(path, f.Name()))
+ if err != nil {
+ return nil, err
+ }
+ if sub != nil {
+ out = append(out, sub...)
+ }
+ continue
+ }
+ case f.Name() == "console":
+ continue
+ case f.Mode()&os.ModeSymlink != 0:
+ continue
+ }
+
+ device, err := DeviceFromPath(filepath.Join(path, f.Name()))
+ if err != nil {
+ if err == errNotADevice {
+ continue
+ }
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+ out = append(out, *device)
+ }
+ return out, nil
+}
+
+// Copied from github.com/opencontainers/runc/libcontainer/devices
+// Given the path to a device look up the information about a linux device
+func DeviceFromPath(path string) (*spec.LinuxDevice, error) {
+ var stat unix.Stat_t
+ err := unix.Lstat(path, &stat)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ devType string
+ mode = stat.Mode
+ devNumber = uint64(stat.Rdev) // nolint: unconvert
+ m = os.FileMode(mode)
+ )
+
+ switch {
+ case mode&unix.S_IFBLK == unix.S_IFBLK:
+ devType = "b"
+ case mode&unix.S_IFCHR == unix.S_IFCHR:
+ devType = "c"
+ case mode&unix.S_IFIFO == unix.S_IFIFO:
+ devType = "p"
+ default:
+ return nil, errNotADevice
+ }
+
+ return &spec.LinuxDevice{
+ Type: devType,
+ Path: path,
+ FileMode: &m,
+ UID: &stat.Uid,
+ GID: &stat.Gid,
+ Major: int64(unix.Major(devNumber)),
+ Minor: int64(unix.Minor(devNumber)),
+ }, nil
+}
diff --git a/test/buildah-bud/apply-podman-deltas b/test/buildah-bud/apply-podman-deltas
index e2ca45728..6ff564aaa 100755
--- a/test/buildah-bud/apply-podman-deltas
+++ b/test/buildah-bud/apply-podman-deltas
@@ -193,21 +193,12 @@ skip_if_remote "volumes don't work with podman-remote" \
"buildah bud --volume" \
"buildah-bud-policy"
-# Most of this should work in podman remote after API implementation other than where context is host.
skip_if_remote "--build-context option not implemented in podman-remote" \
- "build-with-additional-build-context and COPY, test pinning image" \
- "build-with-additional-build-context and COPY, stagename and additional-context conflict" \
- "build-with-additional-build-context and COPY, additionalContext and numeric value of stage" \
- "build-with-additional-build-context and COPY, additionalContext and numeric value of stage" \
"build-with-additional-build-context and COPY, additional context from host" \
- "build-with-additional-build-context and COPY, additional context from external URL" \
- "build-with-additional-build-context and RUN --mount=from=, additional-context is URL and mounted from subdir" \
"build-with-additional-build-context and RUN --mount=from=, additional-context not image and also test conflict with stagename" \
- "build-with-additional-build-context and RUN --mount=from=, additional-context and also test conflict with stagename" \
- "bud-multiple-platform for --all-platform with additional-build-context" \
- "build-with-additional-build-context and FROM, stagename and additional-context conflict" \
+
+skip_if_remote "env-variable for Containerfile.in pre-processing is not propogated on remote" \
"bud with Containerfile.in, via envariable" \
- "build-with-additional-build-context and FROM, pin busybox to alpine"
# Requires a local file outside context dir
skip_if_remote "local keyfile not sent to podman-remote" \
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 86dc76116..0b766dcc8 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -85,7 +85,7 @@ var _ = Describe("Podman build", func() {
})
It("podman build with a secret from file and verify if secret file is not leaked into image", func() {
- session := podmanTest.Podman([]string{"build", "-f", "build/secret-verify-leak/Containerfile.with-secret-verify-leak", "-t", "secret-test-leak", "--secret", "id=mysecret,src=build/secret.txt", "build/"})
+ session := podmanTest.Podman([]string{"build", "-f", "build/secret-verify-leak/Containerfile.with-secret-verify-leak", "-t", "secret-test-leak", "--secret", "id=mysecret,src=build/secret.txt", "build/secret-verify-leak"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 0d24a7e17..14dd6b6b8 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -8,6 +8,7 @@ import (
"time"
. "github.com/containers/podman/v4/test/utils"
+ "github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
@@ -370,6 +371,26 @@ var _ = Describe("Podman logs", func() {
Expect(results.OutputToString()).To(Equal("stdout"))
Expect(results.ErrorToString()).To(Equal("stderr"))
})
+
+ It("podman logs partial log lines: "+log, func() {
+ skipIfJournaldInContainer()
+
+ cname := "log-test"
+ content := stringid.GenerateNonCryptoID()
+ // use printf to print no extra newline
+ logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", cname, ALPINE, "printf", content})
+ logc.WaitWithDefaultTimeout()
+ Expect(logc).To(Exit(0))
+ // Important: do not use OutputToString(), this will remove the trailing newline from the output.
+ // However this test must make sure that there is no such extra newline.
+ Expect(string(logc.Out.Contents())).To(Equal(content))
+
+ logs := podmanTest.Podman([]string{"logs", cname})
+ logs.WaitWithDefaultTimeout()
+ Expect(logs).To(Exit(0))
+ // see comment above
+ Expect(string(logs.Out.Contents())).To(Equal(content))
+ })
}
It("using journald for container with container tag", func() {
diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go
index 019bb4617..c9ffe6a8d 100644
--- a/test/e2e/network_connect_disconnect_test.go
+++ b/test/e2e/network_connect_disconnect_test.go
@@ -2,7 +2,6 @@ package integration
import (
"os"
- "strings"
. "github.com/containers/podman/v4/test/utils"
"github.com/containers/storage/pkg/stringid"
@@ -94,7 +93,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec2 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec2.WaitWithDefaultTimeout()
Expect(exec2).Should(Exit(0))
- Expect(strings.Contains(exec2.OutputToString(), ns)).To(BeTrue())
+ Expect(exec2.OutputToString()).To(ContainSubstring(ns))
dis := podmanTest.Podman([]string{"network", "disconnect", netName, "test"})
dis.WaitWithDefaultTimeout()
@@ -113,7 +112,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec3 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec3.WaitWithDefaultTimeout()
Expect(exec3).Should(Exit(0))
- Expect(strings.Contains(exec3.OutputToString(), ns)).To(BeFalse())
+ Expect(exec3.OutputToString()).ToNot(ContainSubstring(ns))
// make sure stats still works https://github.com/containers/podman/issues/13824
stats := podmanTest.Podman([]string{"stats", "test", "--no-stream"})
@@ -211,7 +210,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec2 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec2.WaitWithDefaultTimeout()
Expect(exec2).Should(Exit(0))
- Expect(strings.Contains(exec2.OutputToString(), ns)).To(BeFalse())
+ Expect(exec2.OutputToString()).ToNot(ContainSubstring(ns))
ip := "10.11.100.99"
mac := "44:11:44:11:44:11"
@@ -240,7 +239,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec3 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec3.WaitWithDefaultTimeout()
Expect(exec3).Should(Exit(0))
- Expect(strings.Contains(exec3.OutputToString(), ns)).To(BeTrue())
+ Expect(exec3.OutputToString()).To(ContainSubstring(ns))
// make sure stats works https://github.com/containers/podman/issues/13824
stats := podmanTest.Podman([]string{"stats", "test", "--no-stream"})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 31044f68b..61f2b3a1c 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -3688,7 +3688,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
})
// Check the block devices are exposed inside container
- It("ddpodman play kube expose block device inside container", func() {
+ It("podman play kube expose block device inside container", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
@@ -3727,7 +3727,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
})
// Check the char devices are exposed inside container
- It("ddpodman play kube expose character device inside container", func() {
+ It("podman play kube expose character device inside container", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
@@ -3781,7 +3781,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
Expect(kube).Should(Exit(125))
})
- It("ddpodman play kube reports error when we try to expose char device as block device", func() {
+ It("podman play kube reports error when we try to expose char device as block device", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
@@ -3807,7 +3807,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
Expect(kube).Should(Exit(125))
})
- It("ddpodman play kube reports error when we try to expose block device as char device", func() {
+ It("podman play kube reports error when we try to expose block device as char device", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index dedb1caeb..4919cc670 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -1112,4 +1112,26 @@ ENTRYPOINT ["sleep","99999"]
})
+ It("podman pod create infra inheritance test", func() {
+ volName := "testVol1"
+ volCreate := podmanTest.Podman([]string{"volume", "create", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"pod", "create", "-v", volName + ":/vol1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ volName2 := "testVol2"
+ volCreate = podmanTest.Podman([]string{"volume", "create", volName2})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--pod", session.OutputToString(), "-v", volName2 + ":/vol2", ALPINE, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("/vol1"))
+ Expect(session.OutputToString()).Should(ContainSubstring("/vol2"))
+ })
+
})
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index 4f0b512c6..dfaff7e67 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -131,6 +131,30 @@ var _ = Describe("Podman privileged container tests", func() {
Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 20))
})
+ It("podman privileged should restart after host devices change", func() {
+ containerName := "privileged-restart-test"
+ SkipIfRootless("Cannot create devices in /dev in rootless mode")
+ Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
+
+ mknod := SystemExec("mknod", []string{"/dev/foodevdir/null", "c", "1", "3"})
+ mknod.WaitWithDefaultTimeout()
+ Expect(mknod).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"run", "--name=" + containerName, "--privileged", "-it", fedoraMinimal, "ls", "/dev"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ deviceFiles := session.OutputToStringArray()
+
+ os.RemoveAll("/dev/foodevdir")
+ session = podmanTest.Podman([]string{"start", "--attach", containerName})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ deviceFilesAfterRemoval := session.OutputToStringArray()
+ Expect(deviceFiles).To(Not(Equal(deviceFilesAfterRemoval)))
+ })
+
It("run no-new-privileges test", func() {
// Check if our kernel is new enough
k, err := IsKernelNewerThan("4.14")
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 3bef889b7..1c0480407 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -325,6 +325,51 @@ var _ = Describe("Podman run with volumes", func() {
})
+ It("podman support overlay volume with custom upperdir and workdir", func() {
+ SkipIfRemote("Overlay volumes only work locally")
+ if os.Getenv("container") != "" {
+ Skip("Overlay mounts not supported when running in a container")
+ }
+ if rootless.IsRootless() {
+ if _, err := exec.LookPath("fuse-overlayfs"); err != nil {
+ Skip("Fuse-Overlayfs required for rootless overlay mount test")
+ }
+ }
+
+ // Use bindsource instead of named volume
+ bindSource := filepath.Join(tempdir, "bindsource")
+ err := os.Mkdir(bindSource, 0755)
+ Expect(err).To(BeNil(), "mkdir "+bindSource)
+
+ // create persistent upperdir on host
+ upperDir := filepath.Join(tempdir, "upper")
+ err = os.Mkdir(upperDir, 0755)
+ Expect(err).To(BeNil(), "mkdir "+upperDir)
+
+ // create persistent workdir on host
+ workDir := filepath.Join(tempdir, "work")
+ err = os.Mkdir(workDir, 0755)
+ Expect(err).To(BeNil(), "mkdir "+workDir)
+
+ overlayOpts := fmt.Sprintf("upperdir=%s,workdir=%s", upperDir, workDir)
+
+ // create file on overlay volume
+ session := podmanTest.Podman([]string{"run", "--volume", bindSource + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "echo hello >> " + "/data/overlay"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--volume", bindSource + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ // must contain `overlay` file since it should be persistent on specified upper and workdir
+ Expect(session.OutputToString()).To(ContainSubstring("overlay"))
+
+ session = podmanTest.Podman([]string{"run", "--volume", bindSource + ":/data:O", ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ // must not contain `overlay` file which was on custom upper and workdir since we have not specified any upper or workdir
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlay")))
+
+ })
+
It("podman run with noexec can't exec", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
session.WaitWithDefaultTimeout()
diff --git a/test/system/170-run-userns.bats b/test/system/170-run-userns.bats
index 46cb37b9d..84788a7f4 100644
--- a/test/system/170-run-userns.bats
+++ b/test/system/170-run-userns.bats
@@ -111,15 +111,30 @@ EOF
}
@test "podman userns=nomap" {
- skip_if_not_rootless "--userns=nomap only works in rootless mode"
- ns_user=$(id -un)
- baseuid=$(egrep "${ns_user}:" /etc/subuid | cut -f2 -d:)
- test ! -z ${baseuid} || skip "no IDs allocated for user ${ns_user}"
+ if is_rootless; then
+ ns_user=$(id -un)
+ baseuid=$(egrep "${ns_user}:" /etc/subuid | cut -f2 -d:)
+ test ! -z ${baseuid} || skip "no IDs allocated for user ${ns_user}"
+
+ test_name="test_$(random_string 12)"
+ run_podman run -d --userns=nomap $IMAGE sleep 100
+ cid=${output}
+ run_podman top ${cid} huser
+ is "${output}" "HUSER.*${baseuid}" "Container should start with baseuid from /etc/subuid not user UID"
+ run_podman rm -t 0 --force ${cid}
+ else
+ run_podman 125 run -d --userns=nomap $IMAGE sleep 100
+ is "${output}" "Error: nomap is only supported in rootless mode" "Container should fail to start since nomap is not suppored in rootful mode"
+ fi
+}
- test_name="test_$(random_string 12)"
- run_podman run -d --userns=nomap $IMAGE sleep 100
- cid=${output}
- run_podman top ${cid} huser
- is "${output}" "HUSER.*${baseuid}" "Container should start with baseuid from /etc/subuid not user UID"
- run_podman rm -t 0 --force ${cid}
+@test "podman userns=keep-id" {
+ if is_rootless; then
+ user=$(id -u)
+ run_podman run --rm --userns=keep-id $IMAGE id -u
+ is "${output}" "$user" "Container should run as the current user"
+ else
+ run_podman 125 run --rm --userns=keep-id $IMAGE id -u
+ is "${output}" "Error: keep-id is only supported in rootless mode" "Container should fail to start since keep-id is not suppored in rootful mode"
+ fi
}
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 3db0804d1..92aabae32 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -111,6 +111,10 @@ load helpers
$IMAGE nc -l -n -v -p $myport
cid="$output"
+ # check that podman stores the network info correctly when a userns is used (#14465)
+ run_podman container inspect --format "{{.NetworkSettings.SandboxKey}}" $cid
+ assert "$output" =~ ".*/netns/netns-.*" "Netns path should be set"
+
wait_for_output "listening on .*:$myport .*" $cid
# emit random string, and check it
diff --git a/vendor/github.com/containers/common/libimage/inspect.go b/vendor/github.com/containers/common/libimage/inspect.go
index 05d60edfc..ae06acd2c 100644
--- a/vendor/github.com/containers/common/libimage/inspect.go
+++ b/vendor/github.com/containers/common/libimage/inspect.go
@@ -128,7 +128,7 @@ func (i *Image) Inspect(ctx context.Context, options *InspectOptions) (*ImageDat
Config: &ociImage.Config,
Version: info.DockerVersion,
Size: size,
- VirtualSize: size, // TODO: they should be different (inherited from Podman)
+ VirtualSize: size, // NOTE: same as size. Inherited from Docker where it's scheduled for deprecation.
Digest: i.Digest(),
Labels: info.Labels,
RootFS: &RootFS{
diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go
index 771756160..d204ef1c4 100644
--- a/vendor/github.com/containers/common/libimage/pull.go
+++ b/vendor/github.com/containers/common/libimage/pull.go
@@ -533,9 +533,6 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
sys := r.systemContextCopy()
resolved, err := shortnames.Resolve(sys, imageName)
if err != nil {
- // TODO: that is a too big of a hammer since we should only
- // ignore errors that indicate that there's no alias and no
- // USRs. Must be addressed in c/image first.
if localImage != nil && pullPolicy == config.PullPolicyNewer {
return []string{resolvedImageName}, nil
}
diff --git a/vendor/github.com/containers/common/libnetwork/resolvconf/resolv.go b/vendor/github.com/containers/common/libnetwork/resolvconf/resolv.go
new file mode 100644
index 000000000..c451d3b49
--- /dev/null
+++ b/vendor/github.com/containers/common/libnetwork/resolvconf/resolv.go
@@ -0,0 +1,182 @@
+package resolvconf
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/containers/common/pkg/util"
+ "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ localhost = "127.0.0.1"
+ systemdResolvedIP = "127.0.0.53"
+)
+
+// Params for the New() function.
+type Params struct {
+ // Path is the path to new resolv.conf file which should be created.
+ Path string
+ // Namespaces is the list of container namespaces.
+ // This is required to fist check for a resolv.conf under /etc/netns,
+ // created by "ip netns". Also used to check if the container has a
+ // netns in which case localhost nameserver must be filtered.
+ Namespaces []specs.LinuxNamespace
+ // IPv6Enabled will filter ipv6 nameservers when not set to true.
+ IPv6Enabled bool
+ // KeepHostServers can be set when it is required to still keep the
+ // original resolv.conf content even when custom Nameserver/Searches/Options
+ // are set. In this case they will be appended to the given values.
+ KeepHostServers bool
+ // Nameservers is a list of nameservers the container should use,
+ // instead of the default ones from the host.
+ Nameservers []string
+ // Searches is a list of dns search domains the container should use,
+ // instead of the default ones from the host.
+ Searches []string
+ // Options is a list of dns options the container should use,
+ // instead of the default ones from the host.
+ Options []string
+
+ // resolvConfPath is the path which should be used as base to get the dns
+ // options. This should only be used for testing purposes. For all other
+ // callers this defaults to /etc/resolv.conf.
+ resolvConfPath string
+}
+
+func getDefaultResolvConf(params *Params) ([]byte, bool, error) {
+ resolveConf := DefaultResolvConf
+ // this is only used by testing
+ if params.resolvConfPath != "" {
+ resolveConf = params.resolvConfPath
+ }
+ hostNS := true
+ for _, ns := range params.Namespaces {
+ if ns.Type == specs.NetworkNamespace {
+ hostNS = false
+ if ns.Path != "" && !strings.HasPrefix(ns.Path, "/proc/") {
+ // check for netns created by "ip netns"
+ path := filepath.Join("/etc/netns", filepath.Base(ns.Path), "resolv.conf")
+ _, err := os.Stat(path)
+ if err == nil {
+ resolveConf = path
+ }
+ }
+ break
+ }
+ }
+
+ contents, err := os.ReadFile(resolveConf)
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
+ return nil, false, err
+ }
+ if hostNS {
+ return contents, hostNS, nil
+ }
+
+ ns := getNameservers(contents)
+ // Check for local only resolver, in this case we want to get the real nameservers
+ // since localhost is not reachable from the netns.
+ if len(ns) == 1 {
+ var path string
+ switch ns[0] {
+ case systemdResolvedIP:
+ // used by systemd-resolved
+ path = "/run/systemd/resolve/resolv.conf"
+ case localhost:
+ // used by NetworkManager https://github.com/containers/podman/issues/13599
+ path = "/run/NetworkManager/no-stub-resolv.conf"
+ }
+ if path != "" {
+ // read the actual resolv.conf file for
+ resolvedContents, err := os.ReadFile(path)
+ if err != nil {
+ // do not error when the file does not exists, the detection logic is not perfect
+ if !errors.Is(err, os.ErrNotExist) {
+ return nil, false, fmt.Errorf("local resolver detected, but could not read real resolv.conf at %q: %w", path, err)
+ }
+ } else {
+ logrus.Debugf("found local resolver, using %q to get the nameservers", path)
+ contents = resolvedContents
+ }
+ }
+ }
+
+ return contents, hostNS, nil
+}
+
+// unsetSearchDomainsIfNeeded removes the search domain when they contain a single dot as element.
+func unsetSearchDomainsIfNeeded(searches []string) []string {
+ if util.StringInSlice(".", searches) {
+ return nil
+ }
+ return searches
+}
+
+// New creates a new resolv.conf file with the given params.
+func New(params *Params) error {
+ // short path, if everything is given there is no need to actually read the hosts /etc/resolv.conf
+ if len(params.Nameservers) > 0 && len(params.Options) > 0 && len(params.Searches) > 0 && !params.KeepHostServers {
+ return build(params.Path, params.Nameservers, unsetSearchDomainsIfNeeded(params.Searches), params.Options)
+ }
+
+ content, hostNS, err := getDefaultResolvConf(params)
+ if err != nil {
+ return fmt.Errorf("failed to get the default /etc/resolv.conf content: %w", err)
+ }
+
+ content = filterResolvDNS(content, params.IPv6Enabled, !hostNS)
+
+ nameservers := params.Nameservers
+ if len(nameservers) == 0 || params.KeepHostServers {
+ nameservers = append(nameservers, getNameservers(content)...)
+ }
+
+ searches := unsetSearchDomainsIfNeeded(params.Searches)
+ // if no params.Searches then use host ones
+ // otherwise make sure that they were no explicitly unset before adding host ones
+ if len(params.Searches) == 0 || (params.KeepHostServers && len(searches) > 0) {
+ searches = append(searches, getSearchDomains(content)...)
+ }
+
+ options := params.Options
+ if len(options) == 0 || params.KeepHostServers {
+ options = append(options, getOptions(content)...)
+ }
+
+ return build(params.Path, nameservers, searches, options)
+}
+
+// Add will add the given nameservers to the given resolv.conf file.
+// It will add the nameserver in front of the existing ones.
+func Add(path string, nameservers []string) error {
+ contents, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+
+ nameservers = append(nameservers, getNameservers(contents)...)
+ return build(path, nameservers, getSearchDomains(contents), getOptions(contents))
+}
+
+// Remove the given nameserver from the given resolv.conf file.
+func Remove(path string, nameservers []string) error {
+ contents, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+
+ oldNameservers := getNameservers(contents)
+ newNameserver := make([]string, 0, len(oldNameservers))
+ for _, ns := range oldNameservers {
+ if !util.StringInSlice(ns, nameservers) {
+ newNameserver = append(newNameserver, ns)
+ }
+ }
+
+ return build(path, newNameserver, getSearchDomains(contents), getOptions(contents))
+}
diff --git a/pkg/resolvconf/resolvconf.go b/vendor/github.com/containers/common/libnetwork/resolvconf/resolvconf.go
index f23cd61b0..54b8c3227 100644
--- a/pkg/resolvconf/resolvconf.go
+++ b/vendor/github.com/containers/common/libnetwork/resolvconf/resolvconf.go
@@ -1,26 +1,23 @@
// Package resolvconf provides utility code to query and update DNS configuration in /etc/resolv.conf.
-// Originally from github.com/docker/libnetwork/resolvconf.
+// Originally from github.com/docker/libnetwork/resolvconf but heavily modified to better work with podman.
package resolvconf
import (
"bytes"
- "io/ioutil"
+ "os"
"regexp"
"strings"
- "sync"
- "github.com/containers/podman/v4/pkg/resolvconf/dns"
- "github.com/containers/storage/pkg/ioutils"
"github.com/sirupsen/logrus"
)
const (
- // DefaultResolvConf points to the default file used for dns configuration on a linux machine
+ // DefaultResolvConf points to the default file used for dns configuration on a linux machine.
DefaultResolvConf = "/etc/resolv.conf"
)
var (
- // Note: the default IPv4 & IPv6 resolvers are set to Google's Public DNS
+ // Note: the default IPv4 & IPv6 resolvers are set to Google's Public DNS.
defaultIPv4Dns = []string{"nameserver 8.8.8.8", "nameserver 8.8.4.4"}
defaultIPv6Dns = []string{"nameserver 2001:4860:4860::8888", "nameserver 2001:4860:4860::8844"}
ipv4NumBlock = `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)`
@@ -29,94 +26,30 @@ var (
// will *not match* IPv4-Embedded IPv6 Addresses (RFC6052), but that and other variants
// -- e.g. other link-local types -- either won't work in containers or are unnecessary.
// For readability and sufficiency for Docker purposes this seemed more reasonable than a
- // 1000+ character regexp with exact and complete IPv6 validation
+ // 1000+ character regexp with exact and complete IPv6 validation.
ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})(%\w+)?`
- localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`)
+ // ipLocalhost is a regex pattern for IPv4 or IPv6 loopback range.
+ ipLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1)$)`
+
+ localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipLocalhost + `\s*\n*`)
nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`)
nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
optionsRegexp = regexp.MustCompile(`^\s*options\s*(([^\s]+\s*)*)$`)
)
-var lastModified struct {
- sync.Mutex
- sha256 string
- contents []byte
-}
-
-// File contains the resolv.conf content and its hash
-type File struct {
- Content []byte
- Hash string
-}
-
-// Get returns the contents of /etc/resolv.conf and its hash
-func Get() (*File, error) {
- return GetSpecific(DefaultResolvConf)
-}
-
-// GetSpecific returns the contents of the user specified resolv.conf file and its hash
-func GetSpecific(path string) (*File, error) {
- resolv, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
- hash, err := ioutils.HashData(bytes.NewReader(resolv))
- if err != nil {
- return nil, err
- }
- return &File{Content: resolv, Hash: hash}, nil
-}
-
-// GetIfChanged retrieves the host /etc/resolv.conf file, checks against the last hash
-// and, if modified since last check, returns the bytes and new hash.
-// This feature is used by the resolv.conf updater for containers
-func GetIfChanged() (*File, error) {
- lastModified.Lock()
- defer lastModified.Unlock()
-
- resolv, err := ioutil.ReadFile("/etc/resolv.conf")
- if err != nil {
- return nil, err
- }
- newHash, err := ioutils.HashData(bytes.NewReader(resolv))
- if err != nil {
- return nil, err
- }
- if lastModified.sha256 != newHash {
- lastModified.sha256 = newHash
- lastModified.contents = resolv
- return &File{Content: resolv, Hash: newHash}, nil
- }
- // nothing changed, so return no data
- return nil, nil
-}
-
-// GetLastModified retrieves the last used contents and hash of the host resolv.conf.
-// Used by containers updating on restart
-func GetLastModified() *File {
- lastModified.Lock()
- defer lastModified.Unlock()
-
- return &File{Content: lastModified.contents, Hash: lastModified.sha256}
-}
-
-// FilterResolvDNS cleans up the config in resolvConf. It has two main jobs:
+// filterResolvDNS cleans up the config in resolvConf. It has two main jobs:
// 1. If a netns is enabled, it looks for localhost (127.*|::1) entries in the provided
// resolv.conf, removing local nameserver entries, and, if the resulting
// cleaned config has no defined nameservers left, adds default DNS entries
// 2. Given the caller provides the enable/disable state of IPv6, the filter
// code will remove all IPv6 nameservers if it is not enabled for containers
//
-func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) (*File, error) {
+func filterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) []byte {
// If we're using the host netns, we have nothing to do besides hash the file.
if !netnsEnabled {
- hash, err := ioutils.HashData(bytes.NewReader(resolvConf))
- if err != nil {
- return nil, err
- }
- return &File{Content: resolvConf, Hash: hash}, nil
+ return resolvConf
}
cleanedResolvConf := localhostNSRegexp.ReplaceAll(resolvConf, []byte{})
// if IPv6 is not enabled, also clean out any IPv6 address nameserver
@@ -125,7 +58,7 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) (*F
}
// if the resulting resolvConf has no more nameservers defined, add appropriate
// default DNS servers for IPv4 and (optionally) IPv6
- if len(GetNameservers(cleanedResolvConf)) == 0 {
+ if len(getNameservers(cleanedResolvConf)) == 0 {
logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: %v", defaultIPv4Dns)
dns := defaultIPv4Dns
if ipv6Enabled {
@@ -134,19 +67,15 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool, netnsEnabled bool) (*F
}
cleanedResolvConf = append(cleanedResolvConf, []byte("\n"+strings.Join(dns, "\n"))...)
}
- hash, err := ioutils.HashData(bytes.NewReader(cleanedResolvConf))
- if err != nil {
- return nil, err
- }
- return &File{Content: cleanedResolvConf, Hash: hash}, nil
+ return cleanedResolvConf
}
// getLines parses input into lines and strips away comments.
-func getLines(input []byte, commentMarker []byte) [][]byte {
+func getLines(input []byte) [][]byte {
lines := bytes.Split(input, []byte("\n"))
var output [][]byte
for _, currentLine := range lines {
- var commentIndex = bytes.Index(currentLine, commentMarker)
+ commentIndex := bytes.Index(currentLine, []byte("#"))
if commentIndex == -1 {
output = append(output, currentLine)
} else {
@@ -156,10 +85,10 @@ func getLines(input []byte, commentMarker []byte) [][]byte {
return output
}
-// GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
-func GetNameservers(resolvConf []byte) []string {
+// getNameservers returns nameservers (if any) listed in /etc/resolv.conf.
+func getNameservers(resolvConf []byte) []string {
nameservers := []string{}
- for _, line := range getLines(resolvConf, []byte("#")) {
+ for _, line := range getLines(resolvConf) {
ns := nsRegexp.FindSubmatch(line)
if len(ns) > 0 {
nameservers = append(nameservers, string(ns[1]))
@@ -168,30 +97,12 @@ func GetNameservers(resolvConf []byte) []string {
return nameservers
}
-// GetNameserversAsCIDR returns nameservers (if any) listed in
-// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
-// This function's output is intended for net.ParseCIDR
-func GetNameserversAsCIDR(resolvConf []byte) []string {
- nameservers := []string{}
- for _, nameserver := range GetNameservers(resolvConf) {
- var address string
- // If IPv6, strip zone if present
- if strings.Contains(nameserver, ":") {
- address = strings.Split(nameserver, "%")[0] + "/128"
- } else {
- address = nameserver + "/32"
- }
- nameservers = append(nameservers, address)
- }
- return nameservers
-}
-
-// GetSearchDomains returns search domains (if any) listed in /etc/resolv.conf
+// getSearchDomains returns search domains (if any) listed in /etc/resolv.conf
// If more than one search line is encountered, only the contents of the last
// one is returned.
-func GetSearchDomains(resolvConf []byte) []string {
+func getSearchDomains(resolvConf []byte) []string {
domains := []string{}
- for _, line := range getLines(resolvConf, []byte("#")) {
+ for _, line := range getLines(resolvConf) {
match := searchRegexp.FindSubmatch(line)
if match == nil {
continue
@@ -201,12 +112,12 @@ func GetSearchDomains(resolvConf []byte) []string {
return domains
}
-// GetOptions returns options (if any) listed in /etc/resolv.conf
+// getOptions returns options (if any) listed in /etc/resolv.conf
// If more than one options line is encountered, only the contents of the last
// one is returned.
-func GetOptions(resolvConf []byte) []string {
+func getOptions(resolvConf []byte) []string {
options := []string{}
- for _, line := range getLines(resolvConf, []byte("#")) {
+ for _, line := range getLines(resolvConf) {
match := optionsRegexp.FindSubmatch(line)
if match == nil {
continue
@@ -216,35 +127,30 @@ func GetOptions(resolvConf []byte) []string {
return options
}
-// Build writes a configuration file to path containing a "nameserver" entry
+// build writes a configuration file to path containing a "nameserver" entry
// for every element in dns, a "search" entry for every element in
// dnsSearch, and an "options" entry for every element in dnsOptions.
-func Build(path string, dns, dnsSearch, dnsOptions []string) (*File, error) {
- content := bytes.NewBuffer(nil)
+func build(path string, dns, dnsSearch, dnsOptions []string) error {
+ content := new(bytes.Buffer)
if len(dnsSearch) > 0 {
if searchString := strings.Join(dnsSearch, " "); strings.Trim(searchString, " ") != "." {
if _, err := content.WriteString("search " + searchString + "\n"); err != nil {
- return nil, err
+ return err
}
}
}
for _, dns := range dns {
if _, err := content.WriteString("nameserver " + dns + "\n"); err != nil {
- return nil, err
+ return err
}
}
if len(dnsOptions) > 0 {
if optsString := strings.Join(dnsOptions, " "); strings.Trim(optsString, " ") != "" {
if _, err := content.WriteString("options " + optsString + "\n"); err != nil {
- return nil, err
+ return err
}
}
}
- hash, err := ioutils.HashData(bytes.NewReader(content.Bytes()))
- if err != nil {
- return nil, err
- }
-
- return &File{Content: content.Bytes(), Hash: hash}, ioutil.WriteFile(path, content.Bytes(), 0644)
+ return os.WriteFile(path, content.Bytes(), 0o644)
}
diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml
index b6bca4cef..0bbe74700 100644
--- a/vendor/github.com/docker/docker/api/swagger.yaml
+++ b/vendor/github.com/docker/docker/api/swagger.yaml
@@ -3347,7 +3347,7 @@ definitions:
Limits:
description: "Define resources limits."
$ref: "#/definitions/Limit"
- Reservation:
+ Reservations:
description: "Define resources reservation."
$ref: "#/definitions/ResourceObject"
RestartPolicy:
diff --git a/vendor/github.com/docker/docker/pkg/system/mknod.go b/vendor/github.com/docker/docker/pkg/system/mknod.go
index 5734d47d4..d27152c0f 100644
--- a/vendor/github.com/docker/docker/pkg/system/mknod.go
+++ b/vendor/github.com/docker/docker/pkg/system/mknod.go
@@ -7,12 +7,6 @@ import (
"golang.org/x/sys/unix"
)
-// Mknod creates a filesystem node (file, device special file or named pipe) named path
-// with attributes specified by mode and dev.
-func Mknod(path string, mode uint32, dev int) error {
- return unix.Mknod(path, mode, dev)
-}
-
// Mkdev is used to build the value of linux devices (in /dev/) which specifies major
// and minor number of the newly created device special file.
// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes.
diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go b/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go
new file mode 100644
index 000000000..c890be116
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go
@@ -0,0 +1,14 @@
+//go:build freebsd
+// +build freebsd
+
+package system // import "github.com/docker/docker/pkg/system"
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+// Mknod creates a filesystem node (file, device special file or named pipe) named path
+// with attributes specified by mode and dev.
+func Mknod(path string, mode uint32, dev int) error {
+ return unix.Mknod(path, mode, uint64(dev))
+}
diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_unix.go b/vendor/github.com/docker/docker/pkg/system/mknod_unix.go
new file mode 100644
index 000000000..4586aad19
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/system/mknod_unix.go
@@ -0,0 +1,14 @@
+//go:build !freebsd && !windows
+// +build !freebsd,!windows
+
+package system // import "github.com/docker/docker/pkg/system"
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+// Mknod creates a filesystem node (file, device special file or named pipe) named path
+// with attributes specified by mode and dev.
+func Mknod(path string, mode uint32, dev int) error {
+ return unix.Mknod(path, mode, dev)
+}
diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
index df22c47fc..da867903e 100644
--- a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
+++ b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go
@@ -9,7 +9,7 @@ package assert
import "reflect"
-// Wrapper around reflect.Value.CanConvert, for compatability
+// Wrapper around reflect.Value.CanConvert, for compatibility
// reasons.
func canConvert(value reflect.Value, to reflect.Type) bool {
return value.CanConvert(to)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e5de2d8d4..d21045c0d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -109,7 +109,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/util
-# github.com/containers/common v0.48.1-0.20220523155016-2fd37da97824
+# github.com/containers/common v0.48.1-0.20220528105338-54c8092c69a1
## explicit
github.com/containers/common/libimage
github.com/containers/common/libimage/define
@@ -119,6 +119,7 @@ github.com/containers/common/libnetwork/etchosts
github.com/containers/common/libnetwork/internal/util
github.com/containers/common/libnetwork/netavark
github.com/containers/common/libnetwork/network
+github.com/containers/common/libnetwork/resolvconf
github.com/containers/common/libnetwork/types
github.com/containers/common/libnetwork/util
github.com/containers/common/pkg/apparmor
@@ -329,7 +330,7 @@ github.com/docker/distribution/registry/client/auth/challenge
github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory
-# github.com/docker/docker v20.10.16+incompatible
+# github.com/docker/docker v20.10.17+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types
@@ -641,7 +642,7 @@ github.com/spf13/cobra
github.com/spf13/pflag
# github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980
github.com/stefanberger/go-pkcs11uri
-# github.com/stretchr/testify v1.7.1
+# github.com/stretchr/testify v1.7.2
## explicit
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
@@ -865,7 +866,6 @@ gopkg.in/tomb.v1
## explicit
gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.1
-## explicit
gopkg.in/yaml.v3
# sigs.k8s.io/yaml v1.3.0
sigs.k8s.io/yaml