summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml28
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md36
-rw-r--r--Makefile18
-rw-r--r--cmd/podman/generate/generate.go2
-rw-r--r--cmd/podman/images/prune.go1
-rw-r--r--cmd/podman/machine/init.go8
-rw-r--r--cmd/podman/play/play.go2
-rw-r--r--cmd/podman/root.go5
-rwxr-xr-xcontrib/cirrus/runner.sh17
-rwxr-xr-xcontrib/cirrus/setup_environment.sh38
-rw-r--r--contrib/msi/podman.wxs8
-rwxr-xr-xdocs/dckrman.sh1
-rw-r--r--docs/source/markdown/podman-image-prune.1.md4
-rw-r--r--go.mod3
-rw-r--r--go.sum4
-rw-r--r--libpod/boltdb_state.go17
-rw-r--r--libpod/container.go19
-rw-r--r--libpod/container_copy_linux.go2
-rw-r--r--libpod/container_exec.go2
-rw-r--r--libpod/container_internal.go11
-rw-r--r--libpod/container_internal_linux.go2
-rw-r--r--libpod/container_path_resolution.go8
-rw-r--r--libpod/kube.go8
-rw-r--r--libpod/network/cni/config.go6
-rw-r--r--libpod/network/cni/config_test.go21
-rw-r--r--libpod/network/cni/run.go3
-rw-r--r--libpod/network/cni/run_test.go41
-rw-r--r--libpod/network/types/network.go4
-rw-r--r--libpod/networking_linux.go55
-rw-r--r--libpod/networking_slirp4netns.go2
-rw-r--r--libpod/oci_conmon_linux.go2
-rw-r--r--libpod/pod.go6
-rw-r--r--libpod/pod_api.go46
-rw-r--r--libpod/runtime.go19
-rw-r--r--libpod/runtime_ctr.go27
-rw-r--r--libpod/runtime_img.go21
-rw-r--r--pkg/api/handlers/libpod/images.go8
-rw-r--r--pkg/api/server/register_images.go6
-rw-r--r--pkg/bindings/connection.go4
-rw-r--r--pkg/bindings/images/build.go3
-rw-r--r--pkg/bindings/images/types.go2
-rw-r--r--pkg/bindings/images/types_prune_options.go15
-rw-r--r--pkg/domain/entities/images.go5
-rw-r--r--pkg/domain/infra/abi/containers.go4
-rw-r--r--pkg/domain/infra/abi/images.go12
-rw-r--r--pkg/domain/infra/abi/secrets.go2
-rw-r--r--pkg/domain/infra/tunnel/images.go2
-rw-r--r--pkg/machine/ignition.go88
-rw-r--r--pkg/specgen/generate/container.go2
-rw-r--r--pkg/specgen/generate/container_create.go3
-rwxr-xr-xtest/compose/test-compose1
-rw-r--r--test/e2e/network_connect_disconnect_test.go18
-rw-r--r--test/e2e/network_test.go52
-rw-r--r--test/e2e/rename_test.go25
-rw-r--r--test/e2e/stop_test.go11
-rw-r--r--test/system/035-logs.bats31
-rw-r--r--test/system/040-ps.bats32
-rw-r--r--test/system/060-mount.bats2
-rw-r--r--test/system/065-cp.bats43
-rw-r--r--test/system/070-build.bats9
-rw-r--r--test/system/080-pause.bats2
-rw-r--r--test/system/120-load.bats4
-rw-r--r--test/system/220-healthcheck.bats1
-rw-r--r--test/system/270-socket-activation.bats24
-rw-r--r--test/system/330-corrupt-images.bats2
-rw-r--r--test/system/500-networking.bats8
-rw-r--r--test/system/700-play.bats17
-rw-r--r--vendor/github.com/containers/common/libimage/copier.go2
-rw-r--r--vendor/github.com/containers/common/libimage/filters.go38
-rw-r--r--vendor/github.com/containers/common/libimage/image.go50
-rw-r--r--vendor/github.com/containers/common/libimage/load.go59
-rw-r--r--vendor/github.com/containers/common/libimage/manifests/manifests.go10
-rw-r--r--vendor/github.com/containers/common/libimage/runtime.go35
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go12
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go17
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf25
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go19
-rw-r--r--vendor/github.com/containers/common/pkg/retry/retry.go2
-rw-r--r--vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go10
-rw-r--r--vendor/github.com/containers/common/pkg/supplemented/supplemented.go4
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go2
-rw-r--r--vendor/github.com/containers/common/version/version.go2
-rw-r--r--vendor/modules.txt2
83 files changed, 916 insertions, 308 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 968854771..9897a9f7f 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -637,6 +637,33 @@ rootless_system_test_task:
main_script: *main
always: *logs_artifacts
+rootless_gitlab_test_task:
+ name: *std_name_fmt
+ alias: rootless_gitlab_test
+ skip: *tags
+ only_if: *not_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.
+ # allow_failures: $CI == $CI
+ depends_on:
+ - rootless_integration_test
+ gce_instance: *standardvm
+ env:
+ <<: *ubuntu_envvars
+ TEST_FLAVOR: 'gitlab'
+ PRIV_NAME: rootless
+ clone_script: *noop # Comes from cache
+ gopath_cache: *ro_gopath_cache
+ setup_script: *setup
+ main_script: *main
+ always:
+ <<: *logs_artifacts
+ junit_artifacts:
+ path: gitlab-runner-podman.xml
+ type: text/xml
+ format: junit
+
upgrade_test_task:
name: "Upgrade test: from $PODMAN_UPGRADE_FROM"
alias: upgrade_test
@@ -720,6 +747,7 @@ success_task:
- local_system_test
- remote_system_test
- rootless_system_test
+ - rootless_gitlab_test
- upgrade_test
- buildah_bud_test
- meta
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 568cf7240..f5f0b21be 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,7 +1,41 @@
<!--
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/master/CONTRIBUTING.md#submitting-pull-requests).
+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.
+
+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`.
-->
+
+#### What this PR does / why we need it:
+
+<!---
+Please put your overall PR description here
+-->
+
+#### How to verify it
+
+<!---
+Please specify the precise conditions and/or the specific test(s) which must pass.
+-->
+
+#### Which issue(s) this PR fixes:
+
+<!--
+Please uncomment this block and include only one of the following on a
+line by itself:
+
+None
+
+-OR-
+
+Fixes #<issue number>
+
+*** Please also put 'Fixes #' in the commit and PR description***
+
+-->
+
+#### Special notes for your reviewer:
diff --git a/Makefile b/Makefile
index 3116958c6..590675d25 100644
--- a/Makefile
+++ b/Makefile
@@ -412,9 +412,9 @@ completions: podman podman-remote
declare -A outfiles=([bash]=%s [zsh]=_%s [fish]=%s.fish [powershell]=%s.ps1);\
for shell in $${!outfiles[*]}; do \
for remote in "" "-remote"; do \
- podman="podman$$remote"; \
- outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $$podman); \
- ./bin/$$podman completion $$shell >| $$outfile; \
+ podman="podman$$remote"; \
+ outfile=$$(printf "completions/$$shell/$${outfiles[$$shell]}" $$podman); \
+ ./bin/$$podman completion $$shell >| $$outfile; \
done;\
done
@@ -432,10 +432,10 @@ $(MANPAGES): %: %.md .install.md2man docdir
### this ensures that manpages are renderd correctly
@sed -e 's/\((podman[^)]*\.md\(#.*\)\?)\)//g' \
- -e 's/\[\(podman[^]]*\)\]/\1/g' \
+ -e 's/\[\(podman[^]]*\)\]/\1/g' \
-e 's/\[\([^]]*\)](http[^)]\+)/\1/g' \
- -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \
- -e 's/\\$$/ /g' $< | \
+ -e 's;<\(/\)\?\(a\|a\s\+[^>]*\|sup\)>;;g' \
+ -e 's/\\$$/ /g' $< | \
$(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@)
.PHONY: docdir
@@ -672,7 +672,7 @@ podman-v$(RELEASE_NUMBER).msi: podman-remote-windows podman-remote-windows-docs
--directory-ref INSTALLDIR --prefix $(DOCFILE)/ > \
$(DOCFILE)/pages.wsx
wixl -D VERSION=$(call err_if_empty,RELEASE_VERSION) -D ManSourceDir=$(DOCFILE) \
- -o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx
+ -o $@ contrib/msi/podman.wxs $(DOCFILE)/pages.wsx --arch x64
.PHONY: package
package: ## Build rpm packages
@@ -759,6 +759,8 @@ install.docker:
install.docker-docs-nobuild:
install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man1
install ${SELINUXOPT} -m 644 docs/build/man/docker*.1 -t $(DESTDIR)$(MANDIR)/man1
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man5
+ install ${SELINUXOPT} -m 644 docs/build/man/docker*.5 -t $(DESTDIR)$(MANDIR)/man5
.PHONY: install.docker-docs
install.docker-docs: docker-docs install.docker-docs-nobuild
@@ -809,7 +811,7 @@ install.tools: .install.goimports .install.gitvalidation .install.md2man .instal
.PHONY: .install.golangci-lint
.install.golangci-lint: .gopathok
- VERSION=1.36.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
+ VERSION=1.36.0 GOBIN=$(GOBIN) ./hack/install_golangci.sh
.PHONY: .install.bats
.install.bats: .gopathok
diff --git a/cmd/podman/generate/generate.go b/cmd/podman/generate/generate.go
index 6b48a342e..a42aa9f21 100644
--- a/cmd/podman/generate/generate.go
+++ b/cmd/podman/generate/generate.go
@@ -11,7 +11,7 @@ var (
// Command: podman _generate_
generateCmd = &cobra.Command{
Use: "generate",
- Short: "Generate structured data based on containers, pods or volumes.",
+ Short: "Generate structured data based on containers, pods or volumes",
Long: "Generate structured data (e.g., Kubernetes YAML or systemd units) based on containers, pods or volumes.",
RunE: validate.SubCommandExists,
}
diff --git a/cmd/podman/images/prune.go b/cmd/podman/images/prune.go
index 7e6a29d94..6c39e5c69 100644
--- a/cmd/podman/images/prune.go
+++ b/cmd/podman/images/prune.go
@@ -41,6 +41,7 @@ func init() {
flags := pruneCmd.Flags()
flags.BoolVarP(&pruneOpts.All, "all", "a", false, "Remove all images not in use by containers, not just dangling ones")
+ flags.BoolVarP(&pruneOpts.External, "external", "", false, "Remove images even when they are used by external containers (e.g., by build containers)")
flags.BoolVarP(&force, "force", "f", false, "Do not prompt for confirmation")
filterFlagName := "filter"
diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go
index 19f31d1a6..adde887f7 100644
--- a/cmd/podman/machine/init.go
+++ b/cmd/podman/machine/init.go
@@ -42,7 +42,7 @@ func init() {
cpusFlagName := "cpus"
flags.Uint64Var(
&initOpts.CPUS,
- cpusFlagName, 1,
+ cpusFlagName, cfg.Machine.CPUs,
"Number of CPUs",
)
_ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
@@ -50,7 +50,7 @@ func init() {
diskSizeFlagName := "disk-size"
flags.Uint64Var(
&initOpts.DiskSize,
- diskSizeFlagName, 10,
+ diskSizeFlagName, cfg.Machine.DiskSize,
"Disk size in GB",
)
@@ -59,7 +59,7 @@ func init() {
memoryFlagName := "memory"
flags.Uint64VarP(
&initOpts.Memory,
- memoryFlagName, "m", 2048,
+ memoryFlagName, "m", cfg.Machine.Memory,
"Memory in MB",
)
_ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
@@ -71,7 +71,7 @@ func init() {
)
ImagePathFlagName := "image-path"
- flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Engine.MachineImage, "Path to qcow image")
+ flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "Path to qcow image")
_ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault)
IgnitionPathFlagName := "ignition-path"
diff --git a/cmd/podman/play/play.go b/cmd/podman/play/play.go
index f121d6a2d..d676bd701 100644
--- a/cmd/podman/play/play.go
+++ b/cmd/podman/play/play.go
@@ -10,7 +10,7 @@ var (
// Command: podman _play_
playCmd = &cobra.Command{
Use: "play",
- Short: "Play containers, pods or volumes from a structured file.",
+ Short: "Play containers, pods or volumes from a structured file",
Long: "Play structured data (e.g., Kubernetes YAML) based on containers, pods or volumes.",
RunE: validate.SubCommandExists,
}
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 58cab0268..eb30f1ef6 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -92,6 +92,11 @@ func Execute() {
if registry.GetExitCode() == 0 {
registry.SetExitCode(define.ExecErrorCodeGeneric)
}
+ if registry.IsRemote() {
+ if strings.Contains(err.Error(), "unable to connect to Podman") {
+ fmt.Fprintln(os.Stderr, "Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM")
+ }
+ }
fmt.Fprintln(os.Stderr, formatError(err))
}
os.Exit(registry.GetExitCode())
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index 128398c38..22a66dd08 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -286,6 +286,23 @@ function _run_release() {
msg "All OK"
}
+
+function _run_gitlab() {
+ rootless_uid=$(id -u)
+ systemctl enable --now --user podman.socket
+ export DOCKER_HOST=unix:///run/user/${rootless_uid}/podman/podman.sock
+ export CONTAINER_HOST=$DOCKER_HOST
+ cd $GOPATH/src/gitlab.com/gitlab-org/gitlab-runner
+ set +e
+ go test -v ./executors/docker |& tee $GOSRC/gitlab-runner-podman.log
+ ret=$?
+ set -e
+ # This file is collected and parsed by Cirrus-CI so must be in $GOSRC
+ cat $GOSRC/gitlab-runner-podman.log | \
+ go-junit-report > $GOSRC/gitlab-runner-podman.xml
+ return $ret
+}
+
logformatter() {
if [[ "$CI" == "true" ]]; then
# Use similar format as human-friendly task name from .cirrus.yml
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 41b155943..ef1f83024 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -243,6 +243,44 @@ case "$TEST_FLAVOR" in
install_test_configs
;;
+ gitlab)
+ # This only runs on Ubuntu for now
+ if [[ "$OS_RELEASE_ID" != "ubuntu" ]]; then
+ die "This test only runs on Ubuntu due to sheer laziness"
+ fi
+
+ # Ref: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27270#note_499585550
+
+ remove_packaged_podman_files
+ make install PREFIX=/usr ETCDIR=/etc
+
+ # Need to re-build lists (removed during image production)
+ ooe.sh apt-get -qq -y update
+ msg "Installing previously downloaded/cached packages"
+ # N/B: Tests check/expect `docker info` output, and this `!= podman info`
+ ooe.sh apt-get install --yes --no-download --ignore-missing containerd.io docker-ce docker-ce-cli
+
+ msg "Disabling docker service and socket activation"
+ systemctl stop docker.service docker.socket
+ systemctl disable docker.service docker.socket
+ rm -rf /run/docker*
+ # Guarantee the docker daemon can't be started, even by accident
+ rm -vf $(type -P dockerd)
+
+ msg "Obtaining necessary gitlab-runner testing bits"
+ slug="gitlab.com/gitlab-org/gitlab-runner"
+ helper_fqin="registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-latest-pwsh"
+ ssh="ssh $ROOTLESS_USER@localhost -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no env GOPATH=$GOPATH"
+ showrun $ssh go get -u github.com/jstemmer/go-junit-report
+ showrun $ssh git clone https://$slug $GOPATH/src/$slug
+ showrun $ssh make -C $GOPATH/src/$slug development_setup
+ showrun $ssh bash -c "'cd $GOPATH/src/$slug && GOPATH=$GOPATH go get .'"
+
+ showrun $ssh podman pull $helper_fqin
+ # Tests expect image with this exact name
+ showrun $ssh podman tag $helper_fqin \
+ docker.io/gitlab/gitlab-runner-helper:x86_64-latest-pwsh
+ ;;
swagger) ;& # use next item
consistency) make clean ;;
release) ;;
diff --git a/contrib/msi/podman.wxs b/contrib/msi/podman.wxs
index 451dd565d..4136e2cc4 100644
--- a/contrib/msi/podman.wxs
+++ b/contrib/msi/podman.wxs
@@ -11,19 +11,19 @@
<Product Name="Podman $(var.VERSION)" Id="*" UpgradeCode="696BAB5D-CA1F-4B05-B123-320F245B8D6D" Version="$(var.VERSION)" Language="1033" Manufacturer="Red Hat Inc.">
- <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="100" Compressed="yes"/>
+ <Package Id="*" Keywords="Installer" Description="Red Hat's Podman $(var.VERSION) Installer" Comments="Apache 2.0 License" Manufacturer="Red Hat Inc." InstallScope="perMachine" InstallerVersion="200" Compressed="yes"/>
<Media Id="1" Cabinet="Podman.cab" EmbedCab="yes"/>
<Property Id="DiskPrompt" Value="Red Hat's Podman $(var.VERSION) Installation"/>
<Directory Id="TARGETDIR" Name="SourceDir">
- <Directory Id="ProgramFilesFolder" Name="PFiles">
+ <Directory Id="ProgramFiles64Folder" Name="PFiles">
<Directory Id="RedHatPFiles" Name="RedHat">
<Directory Id="INSTALLDIR" Name="Podman">
- <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82">
+ <Component Id="INSTALLDIR_Component" Guid="14B310C4-9B5D-4DA5-ADF9-B9D008E4CD82" Win64="Yes">
<CreateFolder/>
</Component>
- <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714">
+ <Component Id="MainExecutable" Guid="73752F94-6589-4C7B-ABED-39D655A19714" Win64="Yes">
<File Id="520C6E17-77A2-4F41-9611-30FA763A0702" Name="podman.exe" Source="bin/windows/podman.exe" KeyPath="yes"/>
</Component>
</Directory>
diff --git a/docs/dckrman.sh b/docs/dckrman.sh
index c69524a7e..18fb364bf 100755
--- a/docs/dckrman.sh
+++ b/docs/dckrman.sh
@@ -4,3 +4,4 @@ for i in $@; do
filename=$(echo $i | sed 's/podman/docker/g')
echo .so man1/$b > $filename
done
+echo .so man5/containerfile.5 > $(dirname $1)/dockerfile.5
diff --git a/docs/source/markdown/podman-image-prune.1.md b/docs/source/markdown/podman-image-prune.1.md
index bd08d18fc..493332ec0 100644
--- a/docs/source/markdown/podman-image-prune.1.md
+++ b/docs/source/markdown/podman-image-prune.1.md
@@ -17,6 +17,10 @@ The image prune command does not prune cache images that only use layers that ar
Remove dangling images and images that have no associated containers.
+#### **--external**
+
+Remove images even when they are used by external containers (e.g., build containers).
+
#### **--filter**=*filters*
Provide filter values.
diff --git a/go.mod b/go.mod
index 4c473891b..973b149a3 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v1.0.1
github.com/containernetworking/plugins v1.0.1
github.com/containers/buildah v1.23.0
- github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73
+ github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.16.0
github.com/containers/ocicrypt v1.1.2
@@ -62,7 +62,6 @@ require (
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/vbauerster/mpb/v6 v6.0.4
- github.com/vbauerster/mpb/v7 v7.1.4 // indirect
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
diff --git a/go.sum b/go.sum
index aa3c0f0d6..e25bb592a 100644
--- a/go.sum
+++ b/go.sum
@@ -250,8 +250,8 @@ github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNB
github.com/containers/buildah v1.23.0 h1:qGIeSNOczUHzvnaaOS29HSMiYAjw6JgIXYksAyvqnLs=
github.com/containers/buildah v1.23.0/go.mod h1:K0iMKgy/MffkkgELBXhSXwTy2HTT6hM0X8qruDR1FwU=
github.com/containers/common v0.44.0/go.mod h1:7sdP4vmI5Bm6FPFxb3lvAh1Iktb6tiO1MzjUzhxdoGo=
-github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73 h1:+qKOyTHbuFo3GPsrUksphfHxYMIJQmPgwpDdQnARGAI=
-github.com/containers/common v0.44.1-0.20210921143342-f2f10e650c73/go.mod h1:zxv7KjdYddSGoWuLUVp6eSb++Ow1zmSMB2jwxuNB4cU=
+github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6 h1:DojkCc4a9f3WB25Fk0GDap1/OkKU9UmDLvPJyqw3TBc=
+github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6/go.mod h1:L4+sJlqi+R7frlbiWBW0baPra/cH8u5ZYwbxkukw3Lk=
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.16.0 h1:WQcNSzb7+ngS2cfynx0vUwhk+scpgiKlldVcsF8GPbI=
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 612908ac2..1242a8d6b 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -1756,6 +1756,23 @@ func (s *BoltState) SafeRewriteContainerConfig(ctr *Container, oldName, newName
if err := allCtrsBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
return errors.Wrapf(err, "error renaming container %s in all containers bucket in DB", ctr.ID())
}
+ if ctr.config.Pod != "" {
+ podsBkt, err := getPodBucket(tx)
+ if err != nil {
+ return err
+ }
+ podBkt := podsBkt.Bucket([]byte(ctr.config.Pod))
+ if podBkt == nil {
+ return errors.Wrapf(define.ErrInternal, "bucket for pod %s does not exist", ctr.config.Pod)
+ }
+ podCtrBkt := podBkt.Bucket(containersBkt)
+ if podCtrBkt == nil {
+ return errors.Wrapf(define.ErrInternal, "pod %s does not have a containers bucket", ctr.config.Pod)
+ }
+ if err := podCtrBkt.Put([]byte(ctr.ID()), []byte(newName)); err != nil {
+ return errors.Wrapf(err, "error renaming container %s in pod %s members bucket", ctr.ID(), ctr.config.Pod)
+ }
+ }
}
}
diff --git a/libpod/container.go b/libpod/container.go
index 5c56ff036..4d15c04c5 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -774,9 +774,9 @@ func (c *Container) ExecSessions() ([]string, error) {
return ids, nil
}
-// ExecSession retrieves detailed information on a single active exec session in
-// a container
-func (c *Container) ExecSession(id string) (*ExecSession, error) {
+// execSessionNoCopy returns the associated exec session to id.
+// Note that the session is not a deep copy.
+func (c *Container) execSessionNoCopy(id string) (*ExecSession, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
@@ -791,6 +791,17 @@ func (c *Container) ExecSession(id string) (*ExecSession, error) {
return nil, errors.Wrapf(define.ErrNoSuchExecSession, "no exec session with ID %s found in container %s", id, c.ID())
}
+ return session, nil
+}
+
+// ExecSession retrieves detailed information on a single active exec session in
+// a container
+func (c *Container) ExecSession(id string) (*ExecSession, error) {
+ session, err := c.execSessionNoCopy(id)
+ if err != nil {
+ return nil, err
+ }
+
returnSession := new(ExecSession)
if err := JSONDeepCopy(session, returnSession); err != nil {
return nil, errors.Wrapf(err, "error copying contents of container %s exec session %s", c.ID(), session.ID())
@@ -1095,7 +1106,7 @@ func (c *Container) AutoRemove() bool {
if spec.Annotations == nil {
return false
}
- return c.Spec().Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue
+ return spec.Annotations[define.InspectAnnotationAutoremove] == define.InspectResponseTrue
}
// Timezone returns the timezone configured inside the container.
diff --git a/libpod/container_copy_linux.go b/libpod/container_copy_linux.go
index a35824289..7d4dd0d46 100644
--- a/libpod/container_copy_linux.go
+++ b/libpod/container_copy_linux.go
@@ -174,7 +174,7 @@ func (c *Container) copyToArchive(ctx context.Context, path string, writer io.Wr
// getContainerUser returns the specs.User and ID mappings of the container.
func getContainerUser(container *Container, mountPoint string) (specs.User, error) {
- userspec := container.Config().User
+ userspec := container.config.User
uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec)
u := specs.User{
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 1cb45a118..f99fb7d3f 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -747,7 +747,7 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
return -1, err
}
- session, err := c.ExecSession(sessionID)
+ session, err := c.execSessionNoCopy(sessionID)
if err != nil {
if errors.Cause(err) == define.ErrNoSuchExecSession {
// TODO: If a proper Context is ever plumbed in here, we
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index cb691dfd8..3f9738411 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -923,12 +923,11 @@ func (c *Container) checkDependenciesRunning() ([]string, error) {
}
// Check the status
- conf := depCtr.Config()
state, err := depCtr.State()
if err != nil {
return nil, errors.Wrapf(err, "error retrieving state of dependency %s of container %s", dep, c.ID())
}
- if state != define.ContainerStateRunning && !conf.IsInfra {
+ if state != define.ContainerStateRunning && !depCtr.config.IsInfra {
notRunning = append(notRunning, dep)
}
depCtrs[dep] = depCtr
@@ -1003,7 +1002,7 @@ func (c *Container) cniHosts() string {
for _, status := range c.getNetworkStatus() {
for _, netInt := range status.Interfaces {
for _, netAddress := range netInt.Networks {
- hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.Config().Name)
+ hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.config.Name)
}
}
}
@@ -2005,7 +2004,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s
}
return nil, err
}
- ociHooks, err := manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0)
+ ociHooks, err := manager.Hooks(config, c.config.Spec.Annotations, len(c.config.UserVolumes) > 0)
if err != nil {
return nil, err
}
@@ -2022,7 +2021,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (map[s
return nil, err
}
- allHooks, err = manager.Hooks(config, c.Spec().Annotations, len(c.config.UserVolumes) > 0)
+ allHooks, err = manager.Hooks(config, c.config.Spec.Annotations, len(c.config.UserVolumes) > 0)
if err != nil {
return nil, err
}
@@ -2106,7 +2105,7 @@ func (c *Container) canWithPrevious() error {
// JSON files for later export
func (c *Container) prepareCheckpointExport() error {
// save live config
- if _, err := metadata.WriteJSONFile(c.Config(), c.bundlePath(), metadata.ConfigDumpFile); err != nil {
+ if _, err := metadata.WriteJSONFile(c.config, c.bundlePath(), metadata.ConfigDumpFile); err != nil {
return err
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index dd6f3878a..867ecc2ad 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1310,7 +1310,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if err == nil && options.Name == "" && (!options.IgnoreStaticIP || !options.IgnoreStaticMAC) {
// The file with the network.status does exist. Let's restore the
// container with the same networks settings as during checkpointing.
- aliases, err := c.runtime.state.GetAllNetworkAliases(c)
+ aliases, err := c.GetAllNetworkAliases()
if err != nil {
return err
}
diff --git a/libpod/container_path_resolution.go b/libpod/container_path_resolution.go
index ec7306ca1..bb2ef1a73 100644
--- a/libpod/container_path_resolution.go
+++ b/libpod/container_path_resolution.go
@@ -112,7 +112,7 @@ func (c *Container) resolvePath(mountPoint string, containerPath string) (string
func findVolume(c *Container, containerPath string) (*Volume, error) {
runtime := c.Runtime()
cleanedContainerPath := filepath.Clean(containerPath)
- for _, vol := range c.Config().NamedVolumes {
+ for _, vol := range c.config.NamedVolumes {
if cleanedContainerPath == filepath.Clean(vol.Dest) {
return runtime.GetVolume(vol.Name)
}
@@ -124,7 +124,7 @@ func findVolume(c *Container, containerPath string) (*Volume, error) {
// Volume's destination.
func isPathOnVolume(c *Container, containerPath string) bool {
cleanedContainerPath := filepath.Clean(containerPath)
- for _, vol := range c.Config().NamedVolumes {
+ for _, vol := range c.config.NamedVolumes {
if cleanedContainerPath == filepath.Clean(vol.Dest) {
return true
}
@@ -141,7 +141,7 @@ func isPathOnVolume(c *Container, containerPath string) bool {
// path of a Mount. Returns a matching Mount or nil.
func findBindMount(c *Container, containerPath string) *specs.Mount {
cleanedPath := filepath.Clean(containerPath)
- for _, m := range c.Config().Spec.Mounts {
+ for _, m := range c.config.Spec.Mounts {
if m.Type != "bind" {
continue
}
@@ -157,7 +157,7 @@ func findBindMount(c *Container, containerPath string) *specs.Mount {
// Mount's destination.
func isPathOnBindMount(c *Container, containerPath string) bool {
cleanedContainerPath := filepath.Clean(containerPath)
- for _, m := range c.Config().Spec.Mounts {
+ for _, m := range c.config.Spec.Mounts {
if cleanedContainerPath == filepath.Clean(m.Destination) {
return true
}
diff --git a/libpod/kube.go b/libpod/kube.go
index d94108cf2..57d99f3ef 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -90,7 +90,7 @@ func (p *Pod) GenerateForKube(ctx context.Context) (*v1.Pod, []v1.ServicePort, e
// so set it at here
for _, ctr := range allContainers {
if !ctr.IsInfra() {
- switch ctr.Config().RestartPolicy {
+ switch ctr.config.RestartPolicy {
case define.RestartPolicyAlways:
pod.Spec.RestartPolicy = v1.RestartPolicyAlways
case define.RestartPolicyOnFailure:
@@ -253,7 +253,9 @@ func (p *Pod) podWithContainers(ctx context.Context, containers []*Container, po
// We add the original port declarations from the libpod infra container
// to the first kubernetes container description because otherwise we loose
// the original container/port bindings.
- if first && len(ports) > 0 {
+ // Add the port configuration to the first regular container or the first
+ // init container if only init containers have been created in the pod.
+ if first && len(ports) > 0 && (!isInit || len(containers) == 2) {
ctr.Ports = ports
first = false
}
@@ -424,7 +426,7 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
// NOTE: a privileged container mounts all of /dev/*.
if !c.Privileged() && len(c.config.Spec.Linux.Devices) > 0 {
// TODO Enable when we can support devices and their names
- kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.Spec().Linux.Devices)
+ kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.config.Spec.Linux.Devices)
return kubeContainer, kubeVolumes, nil, errors.Wrapf(define.ErrNotImplemented, "linux devices")
}
diff --git a/libpod/network/cni/config.go b/libpod/network/cni/config.go
index 670ee0c65..3df155637 100644
--- a/libpod/network/cni/config.go
+++ b/libpod/network/cni/config.go
@@ -170,7 +170,11 @@ func (n *cniNetwork) NetworkRemove(nameOrID string) error {
file := network.filename
delete(n.networks, network.libpodNet.Name)
- return os.Remove(file)
+ // make sure to not error for ErrNotExist
+ if err := os.Remove(file); err != nil && !errors.Is(err, os.ErrNotExist) {
+ return err
+ }
+ return nil
}
// NetworkList will return all known Networks. Optionally you can
diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go
index a0a0ea1af..288cf4626 100644
--- a/libpod/network/cni/config_test.go
+++ b/libpod/network/cni/config_test.go
@@ -1021,6 +1021,27 @@ var _ = Describe("Config", func() {
Expect(err.Error()).To(ContainSubstring("subnet 10.10.0.0/24 is already used on the host or by another config"))
})
+ It("remove network should not error when config file does not exists on disk", func() {
+ name := "mynet"
+ network := types.Network{Name: name}
+ _, err := libpodNet.NetworkCreate(network)
+ Expect(err).To(BeNil())
+
+ path := filepath.Join(cniConfDir, name+".conflist")
+ Expect(path).To(BeARegularFile())
+
+ err = os.Remove(path)
+ Expect(err).To(BeNil())
+ Expect(path).ToNot(BeARegularFile())
+
+ err = libpodNet.NetworkRemove(name)
+ Expect(err).To(BeNil())
+
+ nets, err := libpodNet.NetworkList()
+ Expect(err).To(BeNil())
+ Expect(nets).To(HaveLen(1))
+ Expect(nets).ToNot(ContainElement(HaveNetworkName(name)))
+ })
})
Context("network load valid existing ones", func() {
diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go
index 0f91a407c..bd873f89b 100644
--- a/libpod/network/cni/run.go
+++ b/libpod/network/cni/run.go
@@ -186,9 +186,6 @@ outer:
}
return errors.Errorf("requested static ip %s not in any subnet on network %s", ip.String(), network.libpodNet.Name)
}
- if len(netOpts.Aliases) > 0 && !network.libpodNet.DNSEnabled {
- return errors.New("cannot set aliases on a network without dns enabled")
- }
return nil
}
diff --git a/libpod/network/cni/run_test.go b/libpod/network/cni/run_test.go
index 0a2c090e1..965203c2a 100644
--- a/libpod/network/cni/run_test.go
+++ b/libpod/network/cni/run_test.go
@@ -966,6 +966,26 @@ var _ = Describe("run CNI", func() {
})
})
+ It("setup with aliases but dns disabled should work", func() {
+ runTest(func() {
+ defNet := types.DefaultNetworkName
+ intName := "eth0"
+ setupOpts := types.SetupOptions{
+ NetworkOptions: types.NetworkOptions{
+ ContainerID: stringid.GenerateNonCryptoID(),
+ Networks: map[string]types.PerNetworkOptions{
+ defNet: {
+ InterfaceName: intName,
+ Aliases: []string{"somealias"},
+ },
+ },
+ },
+ }
+ _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
+ Expect(err).ToNot(HaveOccurred())
+ })
+ })
+
})
Context("invalid network setup test", func() {
@@ -1052,27 +1072,6 @@ var _ = Describe("run CNI", func() {
})
})
- It("setup with aliases but dns disabled", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- Aliases: []string{"somealias"},
- },
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("cannot set aliases on a network without dns enabled"))
- })
- })
-
It("setup without networks", func() {
runTest(func() {
setupOpts := types.SetupOptions{
diff --git a/libpod/network/types/network.go b/libpod/network/types/network.go
index 68a32d499..2fe4f3da2 100644
--- a/libpod/network/types/network.go
+++ b/libpod/network/types/network.go
@@ -151,7 +151,9 @@ type PerNetworkOptions struct {
// StaticIPv4 for this container. Optional.
StaticIPs []net.IP `json:"static_ips,omitempty"`
// Aliases contains a list of names which the dns server should resolve
- // to this container. Can only be set when DNSEnabled is true on the Network.
+ // to this container. Should only be set when DNSEnabled is true on the Network.
+ // If aliases are set but there is no dns support for this network the
+ // network interface implementation should ignore this and NOT error.
// Optional.
Aliases []string `json:"aliases,omitempty"`
// StaticMac for this container. Optional.
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index ec9d98b56..e792a410c 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -48,6 +48,41 @@ const (
persistentCNIDir = "/var/lib/cni"
)
+// GetAllNetworkAliases returns all configured aliases for this container.
+// It also adds the container short ID as alias to match docker.
+func (c *Container) GetAllNetworkAliases() (map[string][]string, error) {
+ allAliases, err := c.runtime.state.GetAllNetworkAliases(c)
+ if err != nil {
+ return nil, err
+ }
+
+ // get the all attached networks, we cannot use GetAllNetworkAliases()
+ // since it returns nil if there are no aliases
+ nets, _, err := c.networks()
+ if err != nil {
+ return nil, err
+ }
+
+ // add container short ID as alias to match docker
+ for _, net := range nets {
+ allAliases[net] = append(allAliases[net], c.config.ID[:12])
+ }
+ return allAliases, nil
+}
+
+// GetNetworkAliases returns configured aliases for this network.
+// It also adds the container short ID as alias to match docker.
+func (c *Container) GetNetworkAliases(netName string) ([]string, error) {
+ aliases, err := c.runtime.state.GetNetworkAliases(c, netName)
+ if err != nil {
+ return nil, err
+ }
+
+ // add container short ID as alias to match docker
+ aliases = append(aliases, c.config.ID[:12])
+ return aliases, nil
+}
+
func (c *Container) getNetworkOptions() (types.NetworkOptions, error) {
opts := types.NetworkOptions{
ContainerID: c.config.ID,
@@ -61,7 +96,7 @@ func (c *Container) getNetworkOptions() (types.NetworkOptions, error) {
if err != nil {
return opts, err
}
- aliases, err := c.runtime.state.GetAllNetworkAliases(c)
+ aliases, err := c.GetAllNetworkAliases()
if err != nil {
return opts, err
}
@@ -872,7 +907,7 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu
}
}
- aliases, err := ctr.runtime.state.GetAllNetworkAliases(ctr)
+ aliases, err := ctr.GetAllNetworkAliases()
if err != nil {
return nil, err
}
@@ -975,6 +1010,11 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
for _, net := range networks {
cniNet := new(define.InspectAdditionalNetwork)
cniNet.NetworkID = net
+ aliases, err := c.GetNetworkAliases(net)
+ if err != nil {
+ return nil, err
+ }
+ cniNet.Aliases = aliases
settings.Networks[net] = cniNet
}
}
@@ -1009,7 +1049,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
return nil, err
}
- aliases, err := c.runtime.state.GetNetworkAliases(c, name)
+ aliases, err := c.GetNetworkAliases(name)
if err != nil {
return nil, err
}
@@ -1222,6 +1262,14 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
// get network status before we connect
networkStatus := c.getNetworkStatus()
+ network, err := c.runtime.network.NetworkInspect(netName)
+ if err != nil {
+ return err
+ }
+ if !network.DNSEnabled && len(aliases) > 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName)
+ }
+
if err := c.runtime.state.NetworkConnect(c, netName, aliases); err != nil {
return err
}
@@ -1253,6 +1301,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e
if !exists {
return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName)
}
+ aliases = append(aliases, c.config.ID[:12])
opts.Networks = map[string]types.PerNetworkOptions{
netName: {
Aliases: aliases,
diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go
index cca55cb9b..46cda89a9 100644
--- a/libpod/networking_slirp4netns.go
+++ b/libpod/networking_slirp4netns.go
@@ -222,7 +222,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
defer errorhandling.CloseQuiet(syncR)
defer errorhandling.CloseQuiet(syncW)
- havePortMapping := len(ctr.Config().PortMappings) > 0
+ havePortMapping := len(ctr.config.PortMappings) > 0
logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID))
ctrNetworkSlipOpts := []string{}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index b7b5d09cd..71a7b29fa 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1150,7 +1150,7 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
if ctr.config.NetMode.IsSlirp4netns() || rootless.IsRootless() {
if ctr.config.PostConfigureNetNS {
- havePortMapping := len(ctr.Config().PortMappings) > 0
+ havePortMapping := len(ctr.config.PortMappings) > 0
if havePortMapping {
ctr.rootlessPortSyncR, ctr.rootlessPortSyncW, err = os.Pipe()
if err != nil {
diff --git a/libpod/pod.go b/libpod/pod.go
index e4516b354..c0b0a974b 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -164,8 +164,7 @@ func (p *Pod) PidMode() string {
if err != nil {
return ""
}
- conf := infra.Config()
- ctrSpec := conf.Spec
+ ctrSpec := infra.config.Spec
if ctrSpec != nil && ctrSpec.Linux != nil {
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == specs.PIDNamespace {
@@ -186,8 +185,7 @@ func (p *Pod) UserNSMode() string {
if err != nil {
return ""
}
- conf := infra.Config()
- ctrSpec := conf.Spec
+ ctrSpec := infra.config.Spec
if ctrSpec != nil && ctrSpec.Linux != nil {
for _, ns := range ctrSpec.Linux.Namespaces {
if ns.Type == specs.UserNamespace {
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index 3ee4cd839..971309f77 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -34,7 +34,7 @@ func (p *Pod) startInitContainers(ctx context.Context) error {
}
// If the container is a once init container, we need to remove it
// after it runs
- if initCon.Config().InitContainerType == define.OneShotInitContainer {
+ if initCon.config.InitContainerType == define.OneShotInitContainer {
icLock := initCon.lock
icLock.Lock()
if err := p.runtime.removeContainer(ctx, initCon, false, false, true); err != nil {
@@ -590,16 +590,16 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
return nil, err
}
infraConfig = new(define.InspectPodInfraConfig)
- infraConfig.HostNetwork = !infra.Config().ContainerNetworkConfig.UseImageHosts
- infraConfig.StaticIP = infra.Config().ContainerNetworkConfig.StaticIP
- infraConfig.NoManageResolvConf = infra.Config().UseImageResolvConf
- infraConfig.NoManageHosts = infra.Config().UseImageHosts
+ infraConfig.HostNetwork = !infra.config.ContainerNetworkConfig.UseImageHosts
+ infraConfig.StaticIP = infra.config.ContainerNetworkConfig.StaticIP
+ infraConfig.NoManageResolvConf = infra.config.UseImageResolvConf
+ infraConfig.NoManageHosts = infra.config.UseImageHosts
infraConfig.CPUPeriod = p.CPUPeriod()
infraConfig.CPUQuota = p.CPUQuota()
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
infraConfig.PidNS = p.PidMode()
infraConfig.UserNS = p.UserNSMode()
- namedVolumes, mounts := infra.sortUserVolumes(infra.Config().Spec)
+ namedVolumes, mounts := infra.sortUserVolumes(infra.config.Spec)
inspectMounts, err = infra.GetInspectMounts(namedVolumes, infra.config.ImageVolumes, mounts)
if err != nil {
return nil, err
@@ -611,30 +611,30 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
return nil, err
}
- if len(infra.Config().ContainerNetworkConfig.DNSServer) > 0 {
- infraConfig.DNSServer = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSServer))
- for _, entry := range infra.Config().ContainerNetworkConfig.DNSServer {
+ if len(infra.config.ContainerNetworkConfig.DNSServer) > 0 {
+ infraConfig.DNSServer = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSServer))
+ for _, entry := range infra.config.ContainerNetworkConfig.DNSServer {
infraConfig.DNSServer = append(infraConfig.DNSServer, entry.String())
}
}
- if len(infra.Config().ContainerNetworkConfig.DNSSearch) > 0 {
- infraConfig.DNSSearch = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSSearch))
- infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.Config().ContainerNetworkConfig.DNSSearch...)
+ if len(infra.config.ContainerNetworkConfig.DNSSearch) > 0 {
+ infraConfig.DNSSearch = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSSearch))
+ infraConfig.DNSSearch = append(infraConfig.DNSSearch, infra.config.ContainerNetworkConfig.DNSSearch...)
}
- if len(infra.Config().ContainerNetworkConfig.DNSOption) > 0 {
- infraConfig.DNSOption = make([]string, 0, len(infra.Config().ContainerNetworkConfig.DNSOption))
- infraConfig.DNSOption = append(infraConfig.DNSOption, infra.Config().ContainerNetworkConfig.DNSOption...)
+ if len(infra.config.ContainerNetworkConfig.DNSOption) > 0 {
+ infraConfig.DNSOption = make([]string, 0, len(infra.config.ContainerNetworkConfig.DNSOption))
+ infraConfig.DNSOption = append(infraConfig.DNSOption, infra.config.ContainerNetworkConfig.DNSOption...)
}
- if len(infra.Config().HostAdd) > 0 {
- infraConfig.HostAdd = make([]string, 0, len(infra.Config().HostAdd))
- infraConfig.HostAdd = append(infraConfig.HostAdd, infra.Config().HostAdd...)
+ if len(infra.config.HostAdd) > 0 {
+ infraConfig.HostAdd = make([]string, 0, len(infra.config.HostAdd))
+ infraConfig.HostAdd = append(infraConfig.HostAdd, infra.config.HostAdd...)
}
- if len(infra.Config().ContainerNetworkConfig.Networks) > 0 {
- infraConfig.Networks = make([]string, 0, len(infra.Config().ContainerNetworkConfig.Networks))
- infraConfig.Networks = append(infraConfig.Networks, infra.Config().ContainerNetworkConfig.Networks...)
+ if len(infra.config.ContainerNetworkConfig.Networks) > 0 {
+ infraConfig.Networks = make([]string, 0, len(infra.config.ContainerNetworkConfig.Networks))
+ infraConfig.Networks = append(infraConfig.Networks, infra.config.ContainerNetworkConfig.Networks...)
}
- infraConfig.NetworkOptions = infra.Config().ContainerNetworkConfig.NetworkOptions
- infraConfig.PortBindings = makeInspectPortBindings(infra.Config().ContainerNetworkConfig.PortMappings, nil)
+ infraConfig.NetworkOptions = infra.config.ContainerNetworkConfig.NetworkOptions
+ infraConfig.PortBindings = makeInspectPortBindings(infra.config.ContainerNetworkConfig.PortMappings, nil)
}
inspectData := define.InspectPodData{
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 161d5a533..27885bf5c 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -706,19 +706,32 @@ func (r *Runtime) TmpDir() (string, error) {
return r.config.Engine.TmpDir, nil
}
-// GetConfig returns a copy of the configuration used by the runtime
-func (r *Runtime) GetConfig() (*config.Config, error) {
+// GetConfig returns the configuration used by the runtime.
+// Note that the returned value is not a copy and must hence
+// only be used in a reading fashion.
+func (r *Runtime) GetConfigNoCopy() (*config.Config, error) {
r.lock.RLock()
defer r.lock.RUnlock()
if !r.valid {
return nil, define.ErrRuntimeStopped
}
+ return r.config, nil
+}
+
+// GetConfig returns a copy of the configuration used by the runtime.
+// Please use GetConfigNoCopy() in case you only want to read from
+// but not write to the returned config.
+func (r *Runtime) GetConfig() (*config.Config, error) {
+ rtConfig, err := r.GetConfigNoCopy()
+ if err != nil {
+ return nil, err
+ }
config := new(config.Config)
// Copy so the caller won't be able to modify the actual config
- if err := JSONDeepCopy(r.config, config); err != nil {
+ if err := JSONDeepCopy(rtConfig, config); err != nil {
return nil, errors.Wrapf(err, "error copying config")
}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 3494fa8f2..00979a500 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -193,10 +193,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf
ctr.config.LogPath = ""
}
- ctr.config.Spec = new(spec.Spec)
- if err := JSONDeepCopy(rSpec, ctr.config.Spec); err != nil {
- return nil, errors.Wrapf(err, "error copying runtime spec while creating container")
- }
+ ctr.config.Spec = rSpec
ctr.config.CreatedTime = time.Now()
ctr.state.BindMounts = make(map[string]string)
@@ -234,13 +231,6 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options ..
}
func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Container, retErr error) {
- // Validate the container
- if err := ctr.validate(); err != nil {
- return nil, err
- }
- if ctr.config.IsInfra {
- ctr.config.StopTimeout = 10
- }
// normalize the networks to names
// ocicni only knows about cni names so we have to make
// sure we do not use ids internally
@@ -265,11 +255,26 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
if err != nil {
return nil, err
}
+ network, err := r.network.NetworkInspect(netName)
+ if err != nil {
+ return nil, err
+ }
+ if !network.DNSEnabled {
+ return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set network aliases for network %q because dns is disabled", netName)
+ }
netAliases[netName] = aliases
}
ctr.config.NetworkAliases = netAliases
}
+ // Validate the container
+ if err := ctr.validate(); err != nil {
+ return nil, err
+ }
+ if ctr.config.IsInfra {
+ ctr.config.StopTimeout = 10
+ }
+
// Inhibit shutdown until creation succeeds
shutdown.Inhibit()
defer shutdown.Uninhibit()
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 66cf7a4d5..1915a5c4d 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -48,6 +48,27 @@ func (r *Runtime) RemoveContainersForImageCallback(ctx context.Context) libimage
}
}
+// IsExternalContainerCallback returns a callback that be used in `libimage` to
+// figure out whether a given container is an external one. A container is
+// considered external if it is not present in libpod's database.
+func (r *Runtime) IsExternalContainerCallback(_ context.Context) libimage.IsExternalContainerFunc {
+ // NOTE: pruning external containers is subject to race conditions
+ // (e.g., when a container gets removed). To address this and similar
+ // races, pruning had to happen inside c/storage. Containers has to be
+ // labelled with "podman/libpod" along with callbacks similar to
+ // libimage.
+ return func(idOrName string) (bool, error) {
+ _, err := r.LookupContainer(idOrName)
+ if err == nil {
+ return false, nil
+ }
+ if errors.Is(err, define.ErrNoSuchCtr) {
+ return true, nil
+ }
+ return false, nil
+ }
+}
+
// newBuildEvent creates a new event based on completion of a built image
func (r *Runtime) newImageBuildCompleteEvent(idOrName string) {
e := events.NewEvent(events.Build)
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 0023479ea..1c6cc917c 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -150,7 +150,8 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- All bool `schema:"all"`
+ All bool `schema:"all"`
+ External bool `schema:"external"`
}{
// override any golang type defaults
}
@@ -190,8 +191,9 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
pruneOptions := entities.ImagePruneOptions{
- All: query.All,
- Filter: libpodFilters,
+ All: query.All,
+ External: query.External,
+ Filter: libpodFilters,
}
imagePruneReports, err := imageEngine.Prune(r.Context(), pruneOptions)
if err != nil {
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 5e0de7def..aa573eaa6 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -1050,6 +1050,12 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: |
// Remove all images not in use by containers, not just dangling ones
// - in: query
+ // name: external
+ // default: false
+ // type: boolean
+ // description: |
+ // Remove images even when they are used by external containers (e.g, by build containers)
+ // - in: query
// name: filters
// type: string
// description: |
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 4127ad2f0..e2c46e481 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -112,12 +112,12 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string)
return nil, errors.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme)
}
if err != nil {
- return nil, errors.Wrapf(err, "failed to create %sClient", _url.Scheme)
+ return nil, errors.Wrapf(err, "unable to connect to Podman. failed to create %sClient", _url.Scheme)
}
ctx = context.WithValue(ctx, clientKey, &connection)
if err := pingNewConnection(ctx); err != nil {
- return nil, errors.Wrap(err, "cannot connect to the Podman socket, please verify the connection to the Linux system, or use `podman machine` to create/start a Linux VM.")
+ return nil, errors.Wrap(err, "unable to connect to Podman socket")
}
return ctx, nil
}
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index ded97d8d6..8cf4532d0 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -230,6 +230,9 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
params.Add("platform", platform)
}
}
+ if contextDir, err := filepath.EvalSymlinks(options.ContextDirectory); err == nil {
+ options.ContextDirectory = contextDir
+ }
params.Set("pullpolicy", options.PullPolicy.String())
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 6ff9f18ec..dc6bd91c3 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -74,6 +74,8 @@ type ExportOptions struct {
type PruneOptions struct {
// Prune all images
All *bool
+ // Prune images even when they're used by external containers
+ External *bool
// Filters to apply when pruning images
Filters map[string][]string
}
diff --git a/pkg/bindings/images/types_prune_options.go b/pkg/bindings/images/types_prune_options.go
index 77bef32e3..c9772045e 100644
--- a/pkg/bindings/images/types_prune_options.go
+++ b/pkg/bindings/images/types_prune_options.go
@@ -32,6 +32,21 @@ func (o *PruneOptions) GetAll() bool {
return *o.All
}
+// WithExternal set field External to given value
+func (o *PruneOptions) WithExternal(value bool) *PruneOptions {
+ o.External = &value
+ return o
+}
+
+// GetExternal returns value of field External
+func (o *PruneOptions) GetExternal() bool {
+ if o.External == nil {
+ var z bool
+ return z
+ }
+ return *o.External
+}
+
// WithFilters set field Filters to given value
func (o *PruneOptions) WithFilters(value map[string][]string) *PruneOptions {
o.Filters = value
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 80d570764..2822b1ad7 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -251,8 +251,9 @@ type ImageListOptions struct {
}
type ImagePruneOptions struct {
- All bool `json:"all" schema:"all"`
- Filter []string `json:"filter" schema:"filter"`
+ All bool `json:"all" schema:"all"`
+ External bool `json:"external" schema:"external"`
+ Filter []string `json:"filter" schema:"filter"`
}
type ImageTagOptions struct{}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 02af214a6..8e7e2d411 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -169,6 +169,10 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
logrus.Debugf("Container %s is already stopped", c.ID())
case options.All && errors.Cause(err) == define.ErrCtrStateInvalid:
logrus.Debugf("Container %s is not running, could not stop", c.ID())
+ // container never created in OCI runtime
+ // docker parity: do nothing just return container id
+ case errors.Cause(err) == define.ErrCtrStateInvalid:
+ logrus.Debugf("Container %s is either not created on runtime or is in a invalid state", c.ID())
default:
return err
}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 98d668434..c06059205 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -41,13 +41,21 @@ func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.Boo
func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOptions) ([]*reports.PruneReport, error) {
pruneOptions := &libimage.RemoveImagesOptions{
- Filters: append(opts.Filter, "containers=false", "readonly=false"),
- WithSize: true,
+ RemoveContainerFunc: ir.Libpod.RemoveContainersForImageCallback(ctx),
+ IsExternalContainerFunc: ir.Libpod.IsExternalContainerCallback(ctx),
+ ExternalContainers: opts.External,
+ Filters: append(opts.Filter, "readonly=false"),
+ WithSize: true,
}
if !opts.All {
pruneOptions.Filters = append(pruneOptions.Filters, "dangling=true")
}
+ if opts.External {
+ pruneOptions.Filters = append(pruneOptions.Filters, "containers=external")
+ } else {
+ pruneOptions.Filters = append(pruneOptions.Filters, "containers=false")
+ }
var pruneReports []*reports.PruneReport
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index 2bf8eaae3..34c230e75 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -21,7 +21,7 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
// set defaults from config for the case they are not set by an upper layer
// (-> i.e. tests that talk directly to the api)
- cfg, err := ic.Libpod.GetConfig()
+ cfg, err := ic.Libpod.GetConfigNoCopy()
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 282770613..d41a20348 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -95,7 +95,7 @@ func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOption
f := strings.Split(filter, "=")
filters[f[0]] = f[1:]
}
- options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters)
+ options := new(images.PruneOptions).WithAll(opts.All).WithFilters(filters).WithExternal(opts.External)
reports, err := images.Prune(ir.ClientCtx, options)
if err != nil {
return nil, err
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index 89b556b14..e211f5ea6 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
+ "net/url"
)
/*
@@ -80,6 +81,7 @@ func NewIgnitionFile(ign DynamicIgnition) error {
// so a listening host knows it can being interacting with it
ready := `[Unit]
Requires=dev-virtio\\x2dports-%s.device
+After=remove-moby.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
@@ -89,6 +91,23 @@ ExecStart=/bin/sh -c '/usr/bin/echo Ready >/dev/%s'
[Install]
RequiredBy=multi-user.target
`
+ deMoby := `[Unit]
+Description=Remove moby-engine
+# Run once for the machine
+After=systemd-machine-id-commit.service
+Before=zincati.service
+ConditionPathExists=!/var/lib/%N.stamp
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/bin/rpm-ostree override remove moby-engine
+ExecStart=/usr/bin/rpm-ostree ex apply-live --allow-replacement
+ExecStartPost=/bin/touch /var/lib/%N.stamp
+
+[Install]
+WantedBy=multi-user.target
+ `
_ = ready
ignSystemd := Systemd{
Units: []Unit{
@@ -101,6 +120,21 @@ RequiredBy=multi-user.target
Name: "ready.service",
Contents: strToPtr(fmt.Sprintf(ready, "vport1p1", "vport1p1")),
},
+ {
+ Enabled: boolToPtr(false),
+ Name: "docker.service",
+ Mask: boolToPtr(true),
+ },
+ {
+ Enabled: boolToPtr(false),
+ Name: "docker.socket",
+ Mask: boolToPtr(true),
+ },
+ {
+ Enabled: boolToPtr(true),
+ Name: "remove-moby.service",
+ Contents: &deMoby,
+ },
}}
ignConfig := Config{
Ignition: ignVersion,
@@ -161,6 +195,22 @@ func getFiles(usrName string) []File {
var (
files []File
)
+
+ lingerExample := `[Unit]
+Description=A systemd user unit demo
+After=network-online.target
+Wants=network-online.target podman.socket
+[Service]
+ExecStart=/usr/bin/sleep infinity
+`
+ containers := `[containers]
+netns="bridge"
+rootless_networking="cni"
+`
+ rootContainers := `[engine]
+machine_enabled=true
+`
+
// Add a fake systemd service to get the user socket rolling
files = append(files, File{
Node: Node{
@@ -171,7 +221,7 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,%5BUnit%5D%0ADescription%3DA%20systemd%20user%20unit%20demo%0AAfter%3Dnetwork-online.target%0AWants%3Dnetwork-online.target%20podman.socket%0A%5BService%5D%0AExecStart%3D%2Fusr%2Fbin%2Fsleep%20infinity%0A"),
+ Source: encodeDataURLPtr(lingerExample),
},
Mode: intToPtr(0744),
},
@@ -188,7 +238,7 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"),
+ Source: encodeDataURLPtr(containers),
},
Mode: intToPtr(0744),
},
@@ -213,7 +263,7 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,%5Bengine%5D%0Amachine_enabled%3Dtrue%0A"),
+ Source: encodeDataURLPtr(rootContainers),
},
Mode: intToPtr(0644),
},
@@ -233,7 +283,22 @@ func getFiles(usrName string) []File {
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
- Source: strToPtr("data:,unqualified-search-registries%3D%5B%22docker.io%22%5D"),
+ Source: encodeDataURLPtr("unqualified-search-registries=[\"docker.io\"]\n"),
+ },
+ Mode: intToPtr(0644),
+ },
+ })
+
+ files = append(files, File{
+ Node: Node{
+ Path: "/etc/tmpfiles.d/podman-docker.conf",
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ // Create a symlink from the docker socket to the podman socket.
+ // Taken from https://github.com/containers/podman/blob/main/contrib/systemd/system/podman-docker.conf
+ Contents: Resource{
+ Source: encodeDataURLPtr("L+ /run/docker.sock - - - - /run/podman/podman.sock\n"),
},
Mode: intToPtr(0644),
},
@@ -253,5 +318,20 @@ func getLinks(usrName string) []Link {
Hard: boolToPtr(false),
Target: "/home/" + usrName + "/.config/systemd/user/linger-example.service",
},
+ }, {
+ Node: Node{
+ Group: getNodeGrp("root"),
+ Path: "/usr/local/bin/docker",
+ Overwrite: boolToPtr(true),
+ User: getNodeUsr("root"),
+ },
+ LinkEmbedded1: LinkEmbedded1{
+ Hard: boolToPtr(false),
+ Target: "/usr/bin/podman",
+ },
}}
}
+
+func encodeDataURLPtr(contents string) *string {
+ return strToPtr(fmt.Sprintf("data:,%s", url.PathEscape(contents)))
+}
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index ae26807a9..71b882510 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -54,7 +54,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
}
}
- rtc, err := r.GetConfig()
+ rtc, err := r.GetConfigNoCopy()
if err != nil {
return nil, err
}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index fefa9b4a9..6100e7a5b 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -23,7 +23,7 @@ import (
// Returns the created, container and any warnings resulting from creating the
// container, or an error.
func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator) (*spec.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) {
- rtc, err := rt.GetConfig()
+ rtc, err := rt.GetConfigNoCopy()
if err != nil {
return nil, nil, nil, err
}
@@ -498,6 +498,7 @@ func CreateExitCommandArgs(storageConfig types.StoreOptions, config *config.Conf
"--log-level", logrus.GetLevel().String(),
"--cgroup-manager", config.Engine.CgroupManager,
"--tmpdir", config.Engine.TmpDir,
+ "--cni-config-dir", config.Network.NetworkConfigDir,
}
if config.Engine.OCIRuntime != "" {
command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...)
diff --git a/test/compose/test-compose b/test/compose/test-compose
index 70db6dd55..beaf276fd 100755
--- a/test/compose/test-compose
+++ b/test/compose/test-compose
@@ -247,6 +247,7 @@ function podman() {
--storage-driver=vfs \
--root $WORKDIR/root \
--runroot $WORKDIR/runroot \
+ --cni-config-dir $WORKDIR/cni \
"$@")
echo -n "$output" >>$WORKDIR/output.log
}
diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go
index 217efdeec..5f7c55d3f 100644
--- a/test/e2e/network_connect_disconnect_test.go
+++ b/test/e2e/network_connect_disconnect_test.go
@@ -52,7 +52,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("network disconnect with net mode slirp4netns should result in error", func() {
- SkipIfRootless("network connect and disconnect are only rootful")
netName := "slirp" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
@@ -118,7 +117,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("network connect with net mode slirp4netns should result in error", func() {
- SkipIfRootless("network connect and disconnect are only rootful")
netName := "slirp" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
@@ -146,6 +144,13 @@ var _ = Describe("Podman network connect and disconnect", func() {
ctr := podmanTest.Podman([]string{"create", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
Expect(ctr).Should(Exit(0))
+ cid := ctr.OutputToString()
+
+ // network alias container short id is always added and shown in inspect
+ inspect := podmanTest.Podman([]string{"container", "inspect", "test", "--format", "{{(index .NetworkSettings.Networks \"" + netName + "\").Aliases}}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(Equal("[" + cid[0:12] + "]"))
con := podmanTest.Podman([]string{"network", "connect", netName, "test"})
con.WaitWithDefaultTimeout()
@@ -153,7 +158,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("podman network connect", func() {
- SkipIfRemote("This requires a pending PR to be merged before it will work")
netName := "aliasTest" + stringid.GenerateNonCryptoID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
@@ -163,6 +167,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
ctr := podmanTest.Podman([]string{"run", "-dt", "--name", "test", "--network", netName, ALPINE, "top"})
ctr.WaitWithDefaultTimeout()
Expect(ctr).Should(Exit(0))
+ cid := ctr.OutputToString()
exec := podmanTest.Podman([]string{"exec", "-it", "test", "ip", "addr", "show", "eth0"})
exec.WaitWithDefaultTimeout()
@@ -184,6 +189,12 @@ var _ = Describe("Podman network connect and disconnect", func() {
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(Equal("2"))
+ // network alias container short id is always added and shown in inspect
+ inspect = podmanTest.Podman([]string{"container", "inspect", "test", "--format", "{{(index .NetworkSettings.Networks \"" + newNetName + "\").Aliases}}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(Equal("[" + cid[0:12] + "]"))
+
exec = podmanTest.Podman([]string{"exec", "-it", "test", "ip", "addr", "show", "eth1"})
exec.WaitWithDefaultTimeout()
Expect(exec).Should(Exit(0))
@@ -193,7 +204,6 @@ var _ = Describe("Podman network connect and disconnect", func() {
rm.WaitWithDefaultTimeout()
Expect(rm).Should(Exit(0))
Expect(rm.ErrorToString()).To(Equal(""))
-
})
It("podman network connect when not running", func() {
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index 7e56b8a25..8e47fac75 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -603,6 +603,11 @@ var _ = Describe("Podman network", func() {
})
It("podman network prune --filter", func() {
+ // set custom cni directory to prevent flakes
+ podmanTest.CNIConfigDir = tempdir
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ }
net1 := "macvlan" + stringid.GenerateNonCryptoID() + "net1"
nc := podmanTest.Podman([]string{"network", "create", net1})
@@ -613,11 +618,10 @@ var _ = Describe("Podman network", func() {
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).Should(HaveLen(2))
- Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(list.OutputToStringArray()).Should(ContainElement(net1))
+ Expect(list.OutputToStringArray()).Should(ContainElement("podman"))
// -f needed only to skip y/n question
prune := podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=50"})
@@ -627,11 +631,10 @@ var _ = Describe("Podman network", func() {
listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
listAgain.WaitWithDefaultTimeout()
Expect(listAgain).Should(Exit(0))
+ Expect(listAgain.OutputToStringArray()).Should(HaveLen(2))
- Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeTrue())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement(net1))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
// -f needed only to skip y/n question
prune = podmanTest.Podman([]string{"network", "prune", "-f", "--filter", "until=5000000000000"})
@@ -641,14 +644,18 @@ var _ = Describe("Podman network", func() {
listAgain = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
listAgain.WaitWithDefaultTimeout()
Expect(listAgain).Should(Exit(0))
+ Expect(listAgain.OutputToStringArray()).Should(HaveLen(1))
- Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
})
It("podman network prune", func() {
+ // set custom cni directory to prevent flakes
+ podmanTest.CNIConfigDir = tempdir
+ if IsRemote() {
+ podmanTest.RestartRemoteService()
+ }
// Create two networks
// Check they are there
// Run a container on one of them
@@ -669,13 +676,11 @@ var _ = Describe("Podman network", func() {
list := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
list.WaitWithDefaultTimeout()
- Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).Should(HaveLen(3))
- Expect(StringInSlice(net1, list.OutputToStringArray())).To(BeTrue())
- Expect(StringInSlice(net2, list.OutputToStringArray())).To(BeTrue())
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
+ Expect(list.OutputToStringArray()).Should(ContainElement(net1))
+ Expect(list.OutputToStringArray()).Should(ContainElement(net2))
+ Expect(list.OutputToStringArray()).Should(ContainElement("podman"))
session := podmanTest.Podman([]string{"run", "-dt", "--net", net2, ALPINE, "top"})
session.WaitWithDefaultTimeout()
@@ -688,13 +693,10 @@ var _ = Describe("Podman network", func() {
listAgain := podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}}"})
listAgain.WaitWithDefaultTimeout()
Expect(listAgain).Should(Exit(0))
+ Expect(listAgain.OutputToStringArray()).Should(HaveLen(2))
- Expect(StringInSlice(net1, listAgain.OutputToStringArray())).To(BeFalse())
- Expect(StringInSlice(net2, listAgain.OutputToStringArray())).To(BeTrue())
- // Make sure default network 'podman' still exists
- if !isRootless() {
- Expect(StringInSlice("podman", list.OutputToStringArray())).To(BeTrue())
- }
-
+ Expect(listAgain.OutputToStringArray()).ShouldNot(ContainElement(net1))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement(net2))
+ Expect(listAgain.OutputToStringArray()).Should(ContainElement("podman"))
})
})
diff --git a/test/e2e/rename_test.go b/test/e2e/rename_test.go
index 0bd1792c9..e5e69c25c 100644
--- a/test/e2e/rename_test.go
+++ b/test/e2e/rename_test.go
@@ -111,4 +111,29 @@ var _ = Describe("podman rename", func() {
Expect(ps).Should(Exit(0))
Expect(ps.OutputToString()).To(ContainSubstring(newName))
})
+
+ It("Rename a container that is part of a pod", func() {
+ podName := "testPod"
+ infraName := "infra1"
+ pod := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--infra-name", infraName})
+ pod.WaitWithDefaultTimeout()
+ Expect(pod).Should(Exit(0))
+
+ infraName2 := "infra2"
+ rename := podmanTest.Podman([]string{"rename", infraName, infraName2})
+ rename.WaitWithDefaultTimeout()
+ Expect(rename).Should(Exit(0))
+
+ remove := podmanTest.Podman([]string{"pod", "rm", "-f", podName})
+ remove.WaitWithDefaultTimeout()
+ Expect(remove).Should(Exit(0))
+
+ create := podmanTest.Podman([]string{"create", "--name", infraName2, ALPINE, "top"})
+ create.WaitWithDefaultTimeout()
+ Expect(create).Should(Exit(0))
+
+ create2 := podmanTest.Podman([]string{"create", "--name", infraName, ALPINE, "top"})
+ create2.WaitWithDefaultTimeout()
+ Expect(create2).Should(Exit(0))
+ })
})
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index a984bf6d0..7f178d719 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -234,6 +234,17 @@ var _ = Describe("Podman stop", func() {
Expect(strings.TrimSpace(finalCtrs.OutputToString())).To(Equal(""))
})
+ It("podman stop should return silent success on stopping configured containers", func() {
+ // following container is not created on OCI runtime
+ // so we return success and assume that is is stopped
+ session2 := podmanTest.Podman([]string{"create", "--name", "stopctr", ALPINE, "/bin/sh"})
+ session2.WaitWithDefaultTimeout()
+ Expect(session2).Should(Exit(0))
+ session3 := podmanTest.Podman([]string{"stop", "stopctr"})
+ session3.WaitWithDefaultTimeout()
+ Expect(session3).Should(Exit(0))
+ })
+
It("podman stop --cidfile", func() {
tmpDir, err := ioutil.TempDir("", "")
diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats
index a04d2ac74..76ce12b81 100644
--- a/test/system/035-logs.bats
+++ b/test/system/035-logs.bats
@@ -135,31 +135,38 @@ function _log_test_until() {
s_after="after_$(random_string)_${driver}"
before=$(date --iso-8601=seconds)
- sleep 5
+ sleep 1
run_podman run --log-driver=$driver -d --name test $IMAGE sh -c \
"echo $s_before; trap 'echo $s_after; exit' SIGTERM; while :; do sleep 1; done"
# sleep a second to make sure the date is after the first echo
sleep 1
run_podman stop test
- # sleep for 20 seconds to get the proper after time
- sleep 20
+ run_podman wait test
- run_podman logs test
- is "$output" \
- "$s_before
+ # Sigh. Stupid journald has a lag. Wait a few seconds for it to catch up.
+ retries=20
+ s_both="$s_before
$s_after"
+ while [[ $retries -gt 0 ]]; do
+ run_podman logs test
+ if [[ "$output" = "$s_both" ]]; then
+ break
+ fi
+ retries=$((retries - 1))
+ sleep 0.1
+ done
+ if [[ $retries -eq 0 ]]; then
+ die "Timed out waiting for before&after in podman logs: $output"
+ fi
run_podman logs --until $before test
- is "$output" \
- ""
+ is "$output" "" "podman logs --until before"
- after=$(date --iso-8601=seconds)
+ after=$(date --date='+1 second' --iso-8601=seconds)
run_podman logs --until $after test
- is "$output" \
- "$s_before
-$s_after"
+ is "$output" "$s_both" "podman logs --until after"
run_podman rm -f test
}
diff --git a/test/system/040-ps.bats b/test/system/040-ps.bats
index 182d75547..63f57efdc 100644
--- a/test/system/040-ps.bats
+++ b/test/system/040-ps.bats
@@ -90,26 +90,48 @@ load helpers
is "${#lines[@]}" "1" "setup check: no storage containers at start of test"
# Force a buildah timeout; this leaves a buildah container behind
+ local t0=$SECONDS
PODMAN_TIMEOUT=5 run_podman 124 build -t thiswillneverexist - <<EOF
FROM $IMAGE
+RUN touch /intermediate.image.to.be.pruned
RUN sleep 30
EOF
+ local t1=$SECONDS
+ local delta_t=$((t1 - t0))
+ if [[ $delta_t -gt 10 ]]; then
+ # FIXME FIXME FIXME: when buildah issue 3544 gets fixed and vendored,
+ # change 'echo' to 'die'
+ echo "podman build did not get killed within 10 seconds (actual time: $delta_t seconds)"
+ fi
run_podman ps -a
- is "${#lines[@]}" "1" "podman ps -a does not see buildah container"
+ is "${#lines[@]}" "1" "podman ps -a does not see buildah containers"
run_podman ps --external -a
- is "${#lines[@]}" "2" "podman ps -a --external sees buildah container"
+ is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers"
is "${lines[1]}" \
"[0-9a-f]\{12\} \+$IMAGE *buildah .* seconds ago .* storage .* ${PODMAN_TEST_IMAGE_NAME}-working-container" \
"podman ps --external"
- cid="${lines[1]:0:12}"
-
# 'rm -a' should be a NOP
run_podman rm -a
run_podman ps --external -a
- is "${#lines[@]}" "2" "podman ps -a --external sees buildah container"
+ is "${#lines[@]}" "3" "podman ps -a --external sees buildah containers"
+
+ # Cannot prune intermediate image as it's being used by a buildah
+ # container.
+ run_podman image prune -f
+ is "$output" "" "No image is pruned"
+
+ # --external for removing buildah containers.
+ run_podman image prune -f --external
+ is "${#lines[@]}" "1" "Image used by build container is pruned"
+
+ # One buildah container has been removed.
+ run_podman ps --external -a
+ is "${#lines[@]}" "2" "podman ps -a --external sees buildah containers"
+
+ cid="${lines[1]:0:12}"
# We can't rm it without -f, but podman should issue a helpful message
run_podman 2 rm "$cid"
diff --git a/test/system/060-mount.bats b/test/system/060-mount.bats
index 63a93e13b..ba37ea5e1 100644
--- a/test/system/060-mount.bats
+++ b/test/system/060-mount.bats
@@ -125,6 +125,7 @@ load helpers
run_podman exec $cid find /image-mount/etc/
# Clean up
+ run_podman stop -t 0 $cid
run_podman rm -f $cid
}
@@ -147,6 +148,7 @@ load helpers
run_podman inspect --format "{{(index .Mounts 0).RW}}" $cid
is "$output" "true" "inspect data includes image mount source"
+ run_podman stop -t 0 $cid
run_podman rm -f $cid
}
diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats
index 39f439e7b..38c38d671 100644
--- a/test/system/065-cp.bats
+++ b/test/system/065-cp.bats
@@ -256,6 +256,7 @@ load helpers
"
# From RUNNING container
+ local -a destcontainers=()
while read id src dest dest_fullname description; do
# dest may be "''" for empty table cells
if [[ $dest == "''" ]];then
@@ -265,26 +266,25 @@ load helpers
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman start $destcontainer
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman kill cpcontainer
- run_podman rm -f cpcontainer
+ run_podman kill cpcontainer ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
# From CREATED container
+ destcontainers=()
run_podman create --name cpcontainer --workdir=/srv $cpimage
while read id src dest dest_fullname description; do
# dest may be "''" for empty table cells
@@ -295,23 +295,21 @@ load helpers
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
-
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman start $destcontainer
run_podman exec $destcontainer cat "/$dest_fullname"
is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman rm -f cpcontainer
+ run_podman kill ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
run_podman rmi -f $cpimage
}
@@ -496,6 +494,7 @@ load helpers
"
# From RUNNING container
+ local -a destcontainers=()
while read src dest dest_fullname description; do
if [[ $src == "''" ]];then
unset src
@@ -510,28 +509,27 @@ load helpers
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman start $destcontainer
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman kill cpcontainer
- run_podman rm -f cpcontainer
+ run_podman kill cpcontainer ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
# From CREATED container
+ destcontainers=()
run_podman create --name cpcontainer --workdir=/srv $cpimage
while read src dest dest_fullname description; do
if [[ $src == "''" ]];then
@@ -547,26 +545,25 @@ ${randomcontent[1]}" "$description"
# To RUNNING container
run_podman run -d $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
# To CREATED container
run_podman create $IMAGE sleep infinity
destcontainer="$output"
+ destcontainers+=($destcontainer)
run_podman start $destcontainer
run_podman cp cpcontainer:$src $destcontainer:"/$dest"
run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
- run_podman kill $destcontainer
- run_podman rm -f $destcontainer
done < <(parse_table "$tests")
- run_podman rm -f cpcontainer
+ run_podman kill ${destcontainers[@]}
+ run_podman rm -f cpcontainer ${destcontainers[@]}
run_podman rmi -f $cpimage
}
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index 0e1396fc6..4e89e299a 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -956,6 +956,15 @@ EOF
run_podman build -t build_test $tmpdir
}
+@test "podman build build context is a symlink to a directory" {
+ tmpdir=$PODMAN_TMPDIR/build-test
+ mkdir -p $tmpdir/target
+ ln -s target $tmpdir/link
+ echo FROM $IMAGE > $tmpdir/link/Dockerfile
+ echo RUN echo hello >> $tmpdir/link/Dockerfile
+ run_podman build -t build_test $tmpdir/link
+}
+
function teardown() {
# A timeout or other error in 'build' can leave behind stale images
# that podman can't even see and which will cascade into subsequent
diff --git a/test/system/080-pause.bats b/test/system/080-pause.bats
index 1eb47dcfb..2314324a9 100644
--- a/test/system/080-pause.bats
+++ b/test/system/080-pause.bats
@@ -48,6 +48,7 @@ load helpers
# would imply that the container never paused.
is "$max_delta" "[3456]" "delta t between paused and restarted"
+ run_podman stop -t 0 $cname
run_podman rm -f $cname
# Pause/unpause on nonexistent name or id - these should all fail
@@ -73,6 +74,7 @@ load helpers
is "$output" "$cid" "podman unpause output"
run_podman ps --format '{{.ID}} {{.Names}} {{.Status}}'
is "$output" "${cid:0:12} $cname Up.*" "podman ps on resumed container"
+ run_podman stop -t 0 $cname
run_podman rm -f $cname
run_podman rm -f notrunning
}
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index f2f9bf4d4..8be9ed5c5 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -32,7 +32,7 @@ verify_iid_and_name() {
echo "I am an invalid file and should cause a podman-load error" > $invalid
run_podman 125 load -i $invalid
# podman and podman-remote emit different messages; this is a common string
- is "$output" ".*payload does not match any of the supported image formats .*" \
+ is "$output" ".*payload does not match any of the supported image formats:.*" \
"load -i INVALID fails with expected diagnostic"
}
@@ -129,7 +129,7 @@ verify_iid_and_name() {
@test "podman load - redirect corrupt payload" {
run_podman 125 load <<< "Danger, Will Robinson!! This is a corrupt tarball!"
is "$output" \
- ".*payload does not match any of the supported image formats .*" \
+ ".*payload does not match any of the supported image formats:.*" \
"Diagnostic from 'podman load' unknown/corrupt payload"
}
diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats
index e5a0e7e88..28fe8eb92 100644
--- a/test/system/220-healthcheck.bats
+++ b/test/system/220-healthcheck.bats
@@ -108,6 +108,7 @@ Log[-1].Output |
is "$output" "unhealthy" "output from 'podman healthcheck run'"
# Clean up
+ run_podman stop -t 0 healthcheck_c
run_podman rm -f healthcheck_c
run_podman rmi healthcheck_i
}
diff --git a/test/system/270-socket-activation.bats b/test/system/270-socket-activation.bats
index 031ba161b..dd439d3ae 100644
--- a/test/system/270-socket-activation.bats
+++ b/test/system/270-socket-activation.bats
@@ -69,26 +69,36 @@ function teardown() {
@test "podman system service - socket activation - no container" {
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
- is "$output" "OK" "podman service responses normally"
+ is "$output" "OK" "podman service responds normally"
}
-@test "podman system service - socket activation - exist container " {
- run_podman run $IMAGE sleep 90
+@test "podman system service - socket activation - existing container" {
+ run_podman run -d $IMAGE sleep 90
+ cid="$output"
+
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
- is "$output" "OK" "podman service responses normally"
+ is "$output" "OK" "podman service responds normally"
+
+ run_podman stop -t 0 $cid
+ run_podman rm -f $cid
}
-@test "podman system service - socket activation - kill rootless pause " {
+@test "podman system service - socket activation - kill rootless pause" {
if ! is_rootless; then
skip "root podman no need pause process"
fi
- run_podman run $IMAGE sleep 90
+ run_podman run -d $IMAGE sleep 90
+ cid="$output"
+
local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
if [ -f $pause_pid ]; then
kill -9 $(cat $pause_pid) 2> /dev/null
fi
run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
- is "$output" "OK" "podman service responses normally"
+ is "$output" "OK" "podman service responds normally"
+
+ run_podman stop -t 0 $cid
+ run_podman rm -f $cid
}
# vim: filetype=sh
diff --git a/test/system/330-corrupt-images.bats b/test/system/330-corrupt-images.bats
index eeffff3ec..86da06cb0 100644
--- a/test/system/330-corrupt-images.bats
+++ b/test/system/330-corrupt-images.bats
@@ -78,7 +78,7 @@ function _corrupt_image_test() {
# Run the requested command. Confirm it succeeds, with suitable warnings
run_podman $*
- is "$output" ".*error determining parent of image.*ignoring the error" \
+ is "$output" ".*Failed to determine parent of image.*ignoring the error" \
"$* with missing $what_to_rm"
run_podman images -a --noheading
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index ef00d0366..548f2d764 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -415,6 +415,10 @@ load helpers
run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").MacAddress}}"
mac="$output"
+ # check network alias for container short id
+ run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname\").Aliases}}"
+ is "$output" "\[${cid:0:12}\]" "short container id in network aliases"
+
run_podman network disconnect $netname $cid
# check that we cannot curl (timeout after 3 sec)
@@ -443,6 +447,10 @@ load helpers
# connect a second network
run_podman network connect $netname2 $cid
+ # check network2 alias for container short id
+ run_podman inspect $cid --format "{{(index .NetworkSettings.Networks \"$netname2\").Aliases}}"
+ is "$output" "\[${cid:0:12}\]" "short container id in network aliases"
+
# curl should work
run curl --max-time 3 -s $SERVER/index.txt
is "$output" "$random_1" "curl 127.0.0.1:/index.txt should work"
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index 2b05cdd84..0785bffdf 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -69,11 +69,15 @@ RELABEL="system_u:object_r:container_file_t:s0"
TESTDIR=$PODMAN_TMPDIR/testdir
mkdir -p $TESTDIR
echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
+
run_podman play kube - < $PODMAN_TMPDIR/test.yaml
if [ -e /usr/sbin/selinuxenabled -a /usr/sbin/selinuxenabled ]; then
run ls -Zd $TESTDIR
is "$output" ${RELABEL} "selinux relabel should have happened"
fi
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
}
@@ -86,6 +90,9 @@ RELABEL="system_u:object_r:container_file_t:s0"
run ls -Zd $TESTDIR
is "$output" ${RELABEL} "selinux relabel should have happened"
fi
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
}
@@ -102,12 +109,19 @@ RELABEL="system_u:object_r:container_file_t:s0"
infraID="$output"
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "slirp4netns" "network mode slirp4netns is set for the container"
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
+
run_podman play kube --network none $PODMAN_TMPDIR/test.yaml
run_podman pod inspect --format {{.InfraContainerID}} "${lines[1]}"
infraID="$output"
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "none" "network mode none is set for the container"
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
}
@@ -149,6 +163,9 @@ _EOF
run_podman play kube --start=false $PODMAN_TMPDIR/test.yaml
run_podman inspect --format "{{ .Config.User }}" test_pod-test
is "$output" bin "expect container within pod to run as the bin user"
+
+ run_podman stop -a -t 0
+ run_podman pod stop test_pod
run_podman pod rm -f test_pod
run_podman rmi -f userimage:latest
}
diff --git a/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go
index 42d3690b9..636b97bfd 100644
--- a/vendor/github.com/containers/common/libimage/copier.go
+++ b/vendor/github.com/containers/common/libimage/copier.go
@@ -304,7 +304,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) {
defaultContainerConfig, err := config.Default()
if err != nil {
- logrus.Warnf("failed to get container config for copy options: %v", err)
+ logrus.Warnf("Failed to get container config for copy options: %v", err)
} else {
c.imageCopyOptions.MaxParallelDownloads = defaultContainerConfig.Engine.ImageParallelCopies
}
diff --git a/vendor/github.com/containers/common/libimage/filters.go b/vendor/github.com/containers/common/libimage/filters.go
index 0cc5cc311..833f940cc 100644
--- a/vendor/github.com/containers/common/libimage/filters.go
+++ b/vendor/github.com/containers/common/libimage/filters.go
@@ -47,11 +47,11 @@ func filterImages(images []*Image, filters []filterFunc) ([]*Image, error) {
// compileImageFilters creates `filterFunc`s for the specified filters. The
// required format is `key=value` with the following supported keys:
// after, since, before, containers, dangling, id, label, readonly, reference, intermediate
-func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([]filterFunc, error) {
- logrus.Tracef("Parsing image filters %s", filters)
+func (r *Runtime) compileImageFilters(ctx context.Context, options *ListImagesOptions) ([]filterFunc, error) {
+ logrus.Tracef("Parsing image filters %s", options.Filters)
filterFuncs := []filterFunc{}
- for _, filter := range filters {
+ for _, filter := range options.Filters {
var key, value string
split := strings.SplitN(filter, "=", 2)
if len(split) != 2 {
@@ -77,11 +77,16 @@ func (r *Runtime) compileImageFilters(ctx context.Context, filters []string) ([]
filterFuncs = append(filterFuncs, filterBefore(img.Created()))
case "containers":
- containers, err := strconv.ParseBool(value)
- if err != nil {
- return nil, errors.Wrapf(err, "non-boolean value %q for dangling filter", value)
+ switch value {
+ case "false", "true":
+ case "external":
+ if options.IsExternalContainerFunc == nil {
+ return nil, fmt.Errorf("libimage error: external containers filter without callback")
+ }
+ default:
+ return nil, fmt.Errorf("unsupported value %q for containers filter", value)
}
- filterFuncs = append(filterFuncs, filterContainers(containers))
+ filterFuncs = append(filterFuncs, filterContainers(value, options.IsExternalContainerFunc))
case "dangling":
dangling, err := strconv.ParseBool(value)
@@ -190,13 +195,28 @@ func filterReadOnly(value bool) filterFunc {
}
// filterContainers creates a container filter for matching the specified value.
-func filterContainers(value bool) filterFunc {
+func filterContainers(value string, fn IsExternalContainerFunc) filterFunc {
return func(img *Image) (bool, error) {
ctrs, err := img.Containers()
if err != nil {
return false, err
}
- return (len(ctrs) > 0) == value, nil
+ if value != "external" {
+ boolValue := value == "true"
+ return (len(ctrs) > 0) == boolValue, nil
+ }
+
+ // Check whether all associated containers are external ones.
+ for _, c := range ctrs {
+ isExternal, err := fn(c)
+ if err != nil {
+ return false, fmt.Errorf("checking if %s is an external container in filter: %w", c, err)
+ }
+ if !isExternal {
+ return isExternal, nil
+ }
+ }
+ return true, nil
}
}
diff --git a/vendor/github.com/containers/common/libimage/image.go b/vendor/github.com/containers/common/libimage/image.go
index 8456d5280..00a2d620e 100644
--- a/vendor/github.com/containers/common/libimage/image.go
+++ b/vendor/github.com/containers/common/libimage/image.go
@@ -2,6 +2,7 @@ package libimage
import (
"context"
+ "fmt"
"path/filepath"
"sort"
"strings"
@@ -51,7 +52,7 @@ func (i *Image) reload() error {
logrus.Tracef("Reloading image %s", i.ID())
img, err := i.runtime.store.Image(i.ID())
if err != nil {
- return errors.Wrap(err, "error reloading image")
+ return errors.Wrap(err, "reloading image")
}
i.storageImage = img
i.cached.imageSource = nil
@@ -232,11 +233,15 @@ func (i *Image) Containers() ([]string, error) {
}
// removeContainers removes all containers using the image.
-func (i *Image) removeContainers(fn RemoveContainerFunc) error {
- // Execute the custom removal func if specified.
- if fn != nil {
+func (i *Image) removeContainers(options *RemoveImagesOptions) error {
+ if !options.Force && !options.ExternalContainers {
+ // Nothing to do.
+ return nil
+ }
+
+ if options.Force && options.RemoveContainerFunc != nil {
logrus.Debugf("Removing containers of image %s with custom removal function", i.ID())
- if err := fn(i.ID()); err != nil {
+ if err := options.RemoveContainerFunc(i.ID()); err != nil {
return err
}
}
@@ -246,6 +251,19 @@ func (i *Image) removeContainers(fn RemoveContainerFunc) error {
return err
}
+ if !options.Force && options.ExternalContainers {
+ // All containers must be external ones.
+ for _, cID := range containers {
+ isExternal, err := options.IsExternalContainerFunc(cID)
+ if err != nil {
+ return fmt.Errorf("checking if %s is an external container: %w", cID, err)
+ }
+ if !isExternal {
+ return fmt.Errorf("cannot remove container %s: not an external container", cID)
+ }
+ }
+ }
+
logrus.Debugf("Removing containers of image %s from the local containers storage", i.ID())
var multiE error
for _, cID := range containers {
@@ -392,11 +410,9 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
return processedIDs, nil
}
- // Perform the actual removal. First, remove containers if needed.
- if options.Force {
- if err := i.removeContainers(options.RemoveContainerFunc); err != nil {
- return processedIDs, err
- }
+ // Perform the container removal, if needed.
+ if err := i.removeContainers(options); err != nil {
+ return processedIDs, err
}
// Podman/Docker compat: we only report an image as removed if it has
@@ -406,7 +422,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
if err != nil {
// We must be tolerant toward corrupted images.
// See containers/podman commit fd9dd7065d44.
- logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine if an image is a parent: %v, ignoring the error", err)
hasChildren = false
}
@@ -416,7 +432,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
if err != nil {
// We must be tolerant toward corrupted images.
// See containers/podman commit fd9dd7065d44.
- logrus.Warnf("error determining parent of image: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine parent of image: %v, ignoring the error", err)
parent = nil
}
@@ -440,7 +456,7 @@ func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveIma
if err != nil {
// See Podman commit fd9dd7065d44: we need to
// be tolerant toward corrupted images.
- logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine if an image is a parent: %v, ignoring the error", err)
danglingParent = false
}
if !danglingParent {
@@ -462,7 +478,7 @@ func (i *Image) Tag(name string) error {
ref, err := NormalizeName(name)
if err != nil {
- return errors.Wrapf(err, "error normalizing name %q", name)
+ return errors.Wrapf(err, "normalizing name %q", name)
}
if _, isDigested := ref.(reference.Digested); isDigested {
@@ -499,7 +515,7 @@ func (i *Image) Untag(name string) error {
ref, err := NormalizeName(name)
if err != nil {
- return errors.Wrapf(err, "error normalizing name %q", name)
+ return errors.Wrapf(err, "normalizing name %q", name)
}
// FIXME: this is breaking Podman CI but must be re-enabled once
@@ -885,12 +901,12 @@ func getImageID(ctx context.Context, src types.ImageReference, sys *types.System
}
defer func() {
if err := newImg.Close(); err != nil {
- logrus.Errorf("failed to close image: %q", err)
+ logrus.Errorf("Failed to close image: %q", err)
}
}()
imageDigest := newImg.ConfigInfo().Digest
if err = imageDigest.Validate(); err != nil {
- return "", errors.Wrapf(err, "error getting config info")
+ return "", errors.Wrapf(err, "getting config info")
}
return "@" + imageDigest.Encoded(), nil
}
diff --git a/vendor/github.com/containers/common/libimage/load.go b/vendor/github.com/containers/common/libimage/load.go
index 33dc1a22f..f2b57c43a 100644
--- a/vendor/github.com/containers/common/libimage/load.go
+++ b/vendor/github.com/containers/common/libimage/load.go
@@ -2,7 +2,7 @@ package libimage
import (
"context"
- "errors"
+ "fmt"
"os"
"time"
@@ -28,66 +28,69 @@ func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) (
defer r.writeEvent(&Event{ID: "", Name: path, Time: time.Now(), Type: EventTypeImageLoad})
}
- var (
- loadedImages []string
- loadError error
- )
-
if options == nil {
options = &LoadOptions{}
}
- for _, f := range []func() ([]string, error){
+ var loadErrors []error
+
+ for _, f := range []func() ([]string, string, error){
// OCI
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as an OCI directory", path)
ref, err := ociTransport.NewReference(path, "")
if err != nil {
- return nil, err
+ return nil, ociTransport.Transport.Name(), err
}
- return r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ return images, ociTransport.Transport.Name(), err
},
// OCI-ARCHIVE
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as an OCI archive", path)
ref, err := ociArchiveTransport.NewReference(path, "")
if err != nil {
- return nil, err
+ return nil, ociArchiveTransport.Transport.Name(), err
}
- return r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ return images, ociArchiveTransport.Transport.Name(), err
},
// DIR
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as a Docker dir", path)
ref, err := dirTransport.NewReference(path)
if err != nil {
- return nil, err
+ return nil, dirTransport.Transport.Name(), err
}
- return r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
+ return images, dirTransport.Transport.Name(), err
},
// DOCKER-ARCHIVE
- func() ([]string, error) {
+ func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as a Docker archive", path)
ref, err := dockerArchiveTransport.ParseReference(path)
if err != nil {
- return nil, err
+ return nil, dockerArchiveTransport.Transport.Name(), err
}
- return r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions)
- },
-
- // Give a decent error message if nothing above worked.
- func() ([]string, error) {
- return nil, errors.New("payload does not match any of the supported image formats (oci, oci-archive, dir, docker-archive)")
+ images, err := r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions)
+ return images, dockerArchiveTransport.Transport.Name(), err
},
} {
- loadedImages, loadError = f()
- if loadError == nil {
- return loadedImages, loadError
+ loadedImages, transportName, err := f()
+ if err == nil {
+ return loadedImages, nil
}
- logrus.Debugf("Error loading %s: %v", path, loadError)
+ logrus.Debugf("Error loading %s (%s): %v", path, transportName, err)
+ loadErrors = append(loadErrors, fmt.Errorf("%s: %v", transportName, err))
+ }
+
+ // Give a decent error message if nothing above worked.
+ loadError := fmt.Errorf("payload does not match any of the supported image formats:")
+ for _, err := range loadErrors {
+ loadError = fmt.Errorf("%v\n * %v", loadError, err)
}
return nil, loadError
diff --git a/vendor/github.com/containers/common/libimage/manifests/manifests.go b/vendor/github.com/containers/common/libimage/manifests/manifests.go
index 81b5343c0..8d1abfba9 100644
--- a/vendor/github.com/containers/common/libimage/manifests/manifests.go
+++ b/vendor/github.com/containers/common/libimage/manifests/manifests.go
@@ -125,19 +125,19 @@ func (l *list) SaveToImage(store storage.Store, imageID string, names []string,
if err != nil {
if created {
if _, err2 := store.DeleteImage(img.ID, true); err2 != nil {
- logrus.Errorf("error deleting image %q after failing to save manifest for it", img.ID)
+ logrus.Errorf("Deleting image %q after failing to save manifest for it", img.ID)
}
}
- return "", errors.Wrapf(err, "error saving manifest list to image %q", imageID)
+ return "", errors.Wrapf(err, "saving manifest list to image %q", imageID)
}
err = store.SetImageBigData(imageID, instancesData, instancesBytes, nil)
if err != nil {
if created {
if _, err2 := store.DeleteImage(img.ID, true); err2 != nil {
- logrus.Errorf("error deleting image %q after failing to save instance locations for it", img.ID)
+ logrus.Errorf("Deleting image %q after failing to save instance locations for it", img.ID)
}
}
- return "", errors.Wrapf(err, "error saving instance list to image %q", imageID)
+ return "", errors.Wrapf(err, "saving instance list to image %q", imageID)
}
return imageID, nil
}
@@ -200,7 +200,7 @@ func (l *list) Push(ctx context.Context, dest types.ImageReference, options Push
}
defer func() {
if err2 := policyContext.Destroy(); err2 != nil {
- logrus.Errorf("error destroying signature policy context: %v", err2)
+ logrus.Errorf("Destroying signature policy context: %v", err2)
}
}()
diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go
index 42461014d..dabadbec0 100644
--- a/vendor/github.com/containers/common/libimage/runtime.go
+++ b/vendor/github.com/containers/common/libimage/runtime.go
@@ -2,6 +2,7 @@ package libimage
import (
"context"
+ "fmt"
"os"
"strings"
@@ -306,7 +307,7 @@ func (r *Runtime) lookupImageInLocalStorage(name, candidate string, options *Loo
if errors.Cause(err) == os.ErrNotExist {
// We must be tolerant toward corrupted images.
// See containers/podman commit fd9dd7065d44.
- logrus.Warnf("error determining if an image is a manifest list: %v, ignoring the error", err)
+ logrus.Warnf("Failed to determine if an image is a manifest list: %v, ignoring the error", err)
return image, nil
}
return nil, err
@@ -484,10 +485,16 @@ func (r *Runtime) imageReferenceMatchesContext(ref types.ImageReference, options
return true, nil
}
+// IsExternalContainerFunc allows for checking whether the specified container
+// is an external one. The definition of an external container can be set by
+// callers.
+type IsExternalContainerFunc func(containerID string) (bool, error)
+
// ListImagesOptions allow for customizing listing images.
type ListImagesOptions struct {
// Filters to filter the listed images. Supported filters are
// * after,before,since=image
+ // * containers=true,false,external
// * dangling=true,false
// * intermediate=true,false (useful for pruning images)
// * id=id
@@ -495,6 +502,11 @@ type ListImagesOptions struct {
// * readonly=true,false
// * reference=name[:tag] (wildcards allowed)
Filters []string
+ // IsExternalContainerFunc allows for checking whether the specified
+ // container is an external one (when containers=external filter is
+ // used). The definition of an external container can be set by
+ // callers.
+ IsExternalContainerFunc IsExternalContainerFunc
}
// ListImages lists images in the local container storage. If names are
@@ -525,7 +537,7 @@ func (r *Runtime) ListImages(ctx context.Context, names []string, options *ListI
var filters []filterFunc
if len(options.Filters) > 0 {
- compiledFilters, err := r.compileImageFilters(ctx, options.Filters)
+ compiledFilters, err := r.compileImageFilters(ctx, options)
if err != nil {
return nil, err
}
@@ -550,8 +562,17 @@ type RemoveImagesOptions struct {
// containers using a specific image. By default, all containers in
// the local containers storage will be removed (if Force is set).
RemoveContainerFunc RemoveContainerFunc
+ // IsExternalContainerFunc allows for checking whether the specified
+ // container is an external one (when containers=external filter is
+ // used). The definition of an external container can be set by
+ // callers.
+ IsExternalContainerFunc IsExternalContainerFunc
+ // Remove external containers even when Force is false. Requires
+ // IsExternalContainerFunc to be specified.
+ ExternalContainers bool
// Filters to filter the removed images. Supported filters are
// * after,before,since=image
+ // * containers=true,false,external
// * dangling=true,false
// * intermediate=true,false (useful for pruning images)
// * id=id
@@ -581,6 +602,10 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem
options = &RemoveImagesOptions{}
}
+ if options.ExternalContainers && options.IsExternalContainerFunc == nil {
+ return nil, []error{fmt.Errorf("libimage error: cannot remove external containers without callback")}
+ }
+
// The logic here may require some explanation. Image removal is
// surprisingly complex since it is recursive (intermediate parents are
// removed) and since multiple items in `names` may resolve to the
@@ -635,7 +660,11 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem
}
default:
- filteredImages, err := r.ListImages(ctx, nil, &ListImagesOptions{Filters: options.Filters})
+ options := &ListImagesOptions{
+ IsExternalContainerFunc: options.IsExternalContainerFunc,
+ Filters: options.Filters,
+ }
+ filteredImages, err := r.ListImages(ctx, nil, options)
if err != nil {
appendError(err)
return nil, rmErrors
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
index 4f11e4ed2..735d19493 100644
--- a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
@@ -97,22 +97,22 @@ func InstallDefault(name string) error {
}
if err := cmd.Start(); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil {
- logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
+ logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr)
}
return errors.Wrapf(err, "start %s command", apparmorParserPath)
}
if err := p.generateDefault(apparmorParserPath, pipe); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil {
- logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
+ logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr)
}
if cmdErr := cmd.Wait(); cmdErr != nil {
- logrus.Errorf("unable to wait for AppArmor command: %q", cmdErr)
+ logrus.Errorf("Unable to wait for AppArmor command: %q", cmdErr)
}
return errors.Wrap(err, "generate default profile into pipe")
}
if pipeErr := pipe.Close(); pipeErr != nil {
- logrus.Errorf("unable to close AppArmor pipe: %q", pipeErr)
+ logrus.Errorf("Unable to close AppArmor pipe: %q", pipeErr)
}
return errors.Wrap(cmd.Wait(), "wait for AppArmor command")
@@ -252,7 +252,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
if name != "" {
return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
} else {
- logrus.Debug("skipping loading default AppArmor profile (rootless mode)")
+ logrus.Debug("Skipping loading default AppArmor profile (rootless mode)")
return "", nil
}
}
@@ -292,7 +292,7 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
if err != nil {
return "", errors.Wrapf(err, "install profile %s", name)
}
- logrus.Infof("successfully loaded AppAmor profile %q", name)
+ logrus.Infof("Successfully loaded AppAmor profile %q", name)
} else {
logrus.Infof("AppAmor profile %q is already loaded", name)
}
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index c1f63577a..3b4c7fa04 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -54,6 +54,8 @@ type Config struct {
Containers ContainersConfig `toml:"containers"`
// Engine specifies how the container engine based on Engine will run
Engine EngineConfig `toml:"engine"`
+ // Machine specifies configurations of podman machine VMs
+ Machine MachineConfig `toml:"machine"`
// Network section defines the configuration of CNI Plugins
Network NetworkConfig `toml:"network"`
// Secret section defines configurations for the secret management
@@ -281,9 +283,6 @@ type EngineConfig struct {
// MachineEnabled indicates if Podman is running in a podman-machine VM
MachineEnabled bool `toml:"machine_enabled,omitempty"`
- // MachineImage is the image used when creating a podman-machine VM
- MachineImage string `toml:"machine_image,omitempty"`
-
// MultiImageArchive - if true, the container engine allows for storing
// archives (e.g., of the docker-archive transport) with multiple
// images. By default, Podman creates single-image archives.
@@ -490,6 +489,18 @@ type SecretConfig struct {
Opts map[string]string `toml:"opts,omitempty"`
}
+// MachineConfig represents the "machine" TOML config table
+type MachineConfig struct {
+ // Number of CPU's a machine is created with.
+ CPUs uint64 `toml:"cpus,omitempty"`
+ // DiskSize is the size of the disk in GB created when init-ing a podman-machine VM
+ DiskSize uint64 `toml:"disk_size,omitempty"`
+ // MachineImage is the image used when init-ing a podman-machine VM
+ Image string `toml:"image,omitempty"`
+ // Memory in MB a machine is created with.
+ Memory uint64 `toml:"memory,omitempty"`
+}
+
// Destination represents destination for remote service
type Destination struct {
// URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index 7c72ec79f..1d3c003e3 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -396,10 +396,6 @@ default_sysctls = [
#
#machine_enabled = false
-# The image used when creating a podman-machine VM.
-#
-#machine_image = "testing"
-
# MultiImageArchive - if true, the container engine allows for storing archives
# (e.g., of the docker-archive transport) with multiple images. By default,
# Podman creates single-image archives.
@@ -559,8 +555,25 @@ default_sysctls = [
[engine.volume_plugins]
#testplugin = "/run/podman/plugins/test.sock"
-# The [engine.volume_plugins] table MUST be the last entry in this file.
+[machine]
+# Number of CPU's a machine is created with.
+#
+#cpus=1
+
+# The size of the disk in GB created when init-ing a podman-machine VM.
+#
+#disk_size=10
+
+# The image used when creating a podman-machine VM.
+#
+#image = "testing"
+
+# Memory in MB a machine is created with.
+#
+#memory=2048
+
+# The [machine] table MUST be the last entry in this file.
# (Unless another table is added)
# TOML does not provide a way to end a table other than a further table being
-# defined, so every key hereafter will be part of [volume_plugins] and not the
+# defined, so every key hereafter will be part of [machine] and not the
# main config.
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 34d17d72c..e72e1b3e4 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -208,6 +208,7 @@ func DefaultConfig() (*Config, error) {
},
Engine: *defaultEngineConfig,
Secrets: defaultSecretConfig(),
+ Machine: defaultMachineConfig(),
}, nil
}
@@ -219,6 +220,16 @@ func defaultSecretConfig() SecretConfig {
}
}
+// defaultMachineConfig returns the default machine configuration.
+func defaultMachineConfig() MachineConfig {
+ return MachineConfig{
+ CPUs: 1,
+ DiskSize: 10,
+ Image: "testing",
+ Memory: 2048,
+ }
+}
+
// defaultConfigFromMemory returns a default engine configuration. Note that the
// config is different for root and rootless. It also parses the storage.conf.
func defaultConfigFromMemory() (*EngineConfig, error) {
@@ -345,8 +356,6 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
// constants.
c.LockType = "shm"
c.MachineEnabled = false
- c.MachineImage = "testing"
-
c.ChownCopiedFiles = true
return c, nil
@@ -566,9 +575,3 @@ func (c *Config) MachineEnabled() bool {
func (c *Config) RootlessNetworking() string {
return c.Containers.RootlessNetworking
}
-
-// MachineImage returns the image to be
-// used when creating a podman-machine VM
-func (c *Config) MachineImage() string {
- return c.Engine.MachineImage
-}
diff --git a/vendor/github.com/containers/common/pkg/retry/retry.go b/vendor/github.com/containers/common/pkg/retry/retry.go
index 8eb2da975..43e3a6688 100644
--- a/vendor/github.com/containers/common/pkg/retry/retry.go
+++ b/vendor/github.com/containers/common/pkg/retry/retry.go
@@ -30,7 +30,7 @@ func RetryIfNecessary(ctx context.Context, operation func() error, retryOptions
if retryOptions.Delay != 0 {
delay = retryOptions.Delay
}
- logrus.Warnf("failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
+ logrus.Warnf("Failed, retrying in %s ... (%d/%d). Error: %v", delay, attempt+1, retryOptions.MaxRetry, err)
select {
case <-time.After(delay):
break
diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
index 4b7253b31..6c9321e73 100644
--- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
+++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
@@ -114,13 +114,13 @@ func getMounts(filePath string) []string {
file, err := os.Open(filePath)
if err != nil {
// This is expected on most systems
- logrus.Debugf("file %q not found, skipping...", filePath)
+ logrus.Debugf("File %q not found, skipping...", filePath)
return nil
}
defer file.Close()
scanner := bufio.NewScanner(file)
if err = scanner.Err(); err != nil {
- logrus.Errorf("error reading file %q, %v skipping...", filePath, err)
+ logrus.Errorf("Reading file %q, %v skipping...", filePath, err)
return nil
}
var mounts []string
@@ -128,7 +128,7 @@ func getMounts(filePath string) []string {
if strings.HasPrefix(strings.TrimSpace(scanner.Text()), "/") {
mounts = append(mounts, scanner.Text())
} else {
- logrus.Debugf("skipping unrecognized mount in %v: %q",
+ logrus.Debugf("Skipping unrecognized mount in %v: %q",
filePath, scanner.Text())
}
}
@@ -176,7 +176,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str
if _, err := os.Stat(file); err == nil {
mounts, err := addSubscriptionsFromMountsFile(file, mountLabel, containerWorkingDir, uid, gid)
if err != nil {
- logrus.Warnf("error mounting subscriptions, skipping entry in %s: %v", file, err)
+ logrus.Warnf("Failed to mount subscriptions, skipping entry in %s: %v", file, err)
}
subscriptionMounts = mounts
break
@@ -192,7 +192,7 @@ func MountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPoint str
switch {
case err == nil:
if err := addFIPSModeSubscription(&subscriptionMounts, containerWorkingDir, mountPoint, mountLabel, uid, gid); err != nil {
- logrus.Errorf("error adding FIPS mode subscription to container: %v", err)
+ logrus.Errorf("Adding FIPS mode subscription to container: %v", err)
}
case os.IsNotExist(err):
logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode subscription")
diff --git a/vendor/github.com/containers/common/pkg/supplemented/supplemented.go b/vendor/github.com/containers/common/pkg/supplemented/supplemented.go
index a36c3eda4..196176a1c 100644
--- a/vendor/github.com/containers/common/pkg/supplemented/supplemented.go
+++ b/vendor/github.com/containers/common/pkg/supplemented/supplemented.go
@@ -83,12 +83,12 @@ func (s *supplementedImageReference) NewImageSource(ctx context.Context, sys *ty
if iss != nil {
// The composite source has been created. Use its Close method.
if err2 := iss.Close(); err2 != nil {
- logrus.Errorf("error opening image: %v", err2)
+ logrus.Errorf("Opening image: %v", err2)
}
} else if top != nil {
// The composite source has not been created, but the top was already opened. Close it.
if err2 := top.Close(); err2 != nil {
- logrus.Errorf("error opening image: %v", err2)
+ logrus.Errorf("Closing image: %v", err2)
}
}
}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
index 1935d71f1..6420ba274 100644
--- a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
@@ -237,7 +237,7 @@ func checkCgroupPids(cgMounts map[string]string, quiet bool) cgroupPids {
_, ok := cgMounts["pids"]
if !ok {
if !quiet {
- logrus.Warn("unable to find pids cgroup in mounts")
+ logrus.Warn("Unable to find pids cgroup in mounts")
}
return cgroupPids{}
}
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index ba4dda5e6..b6ceabce5 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the version of the build.
-const Version = "0.44.1-dev"
+const Version = "0.46.1-dev"
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 661619f98..1fb03d302 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -97,7 +97,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.44.1-0.20210921143342-f2f10e650c73
+# github.com/containers/common v0.46.1-0.20210928081721-32e20295f1c6
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests
github.com/containers/common/pkg/apparmor