summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml57
-rwxr-xr-xAPI.md10
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--Makefile79
-rw-r--r--RELEASE_NOTES.md29
-rw-r--r--changelog.txt79
-rw-r--r--cmd/podman/cliconfig/config.go1
-rw-r--r--cmd/podman/commit.go6
-rw-r--r--cmd/podman/cp.go97
-rw-r--r--cmd/podman/main.go4
-rw-r--r--cmd/podman/main_local.go2
-rw-r--r--cmd/podman/main_remote.go39
-rw-r--r--cmd/podman/rm.go9
-rw-r--r--cmd/podman/shared/container.go2
-rw-r--r--cmd/podman/shared/container_inspect.go46
-rw-r--r--cmd/podman/system_df.go2
-rw-r--r--cmd/podman/varlink/io.podman.varlink10
-rw-r--r--completions/bash/podman1
-rwxr-xr-xcontrib/cirrus/logcollector.sh36
l---------[-rwxr-xr-x]contrib/cirrus/system_test.sh22
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--docs/podman-build.1.md2
-rw-r--r--docs/podman-commit.1.md8
-rw-r--r--docs/podman-create.1.md6
-rw-r--r--docs/podman-exec.1.md28
-rw-r--r--docs/podman-generate-kube.1.md2
-rw-r--r--docs/podman-rm.1.md7
-rw-r--r--docs/podman-run.1.md21
-rw-r--r--docs/podman.1.md17
-rw-r--r--libpod/container_api.go4
-rw-r--r--libpod/container_inspect.go114
-rw-r--r--libpod/container_internal_linux.go2
-rw-r--r--libpod/image/pull.go8
-rw-r--r--libpod/runtime.go19
-rw-r--r--libpod/runtime_cstorage.go118
-rw-r--r--libpod/runtime_ctr.go15
-rw-r--r--logo/podman-logo-source.svg993
-rw-r--r--logo/podman-logo.pngbin41734 -> 37056 bytes
-rw-r--r--pkg/adapter/containers.go14
-rw-r--r--pkg/apparmor/apparmor_linux.go9
-rw-r--r--pkg/hooks/docs/oci-hooks.5.md2
-rw-r--r--pkg/registries/registries.go16
-rw-r--r--pkg/spec/createconfig.go4
-rw-r--r--pkg/util/utils.go5
-rw-r--r--test/e2e/common_test.go27
-rw-r--r--test/e2e/cp_test.go21
-rw-r--r--test/e2e/logs_test.go17
-rw-r--r--test/e2e/port_test.go30
-rw-r--r--test/e2e/runlabel_test.go1
-rw-r--r--test/system/030-run.bats4
-rw-r--r--test/utils/utils.go2
-rw-r--r--vendor.conf4
-rw-r--r--vendor/github.com/containers/buildah/add.go18
-rw-r--r--vendor/github.com/containers/buildah/buildah.go2
-rw-r--r--vendor/github.com/containers/buildah/chroot/run.go20
-rw-r--r--vendor/github.com/containers/buildah/image.go2
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go101
-rw-r--r--vendor/github.com/containers/buildah/pkg/overlay/overlay.go31
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse.go20
-rw-r--r--vendor/github.com/containers/buildah/pkg/unshare/unshare.c13
-rw-r--r--vendor/github.com/containers/buildah/pkg/unshare/unshare.go20
-rw-r--r--vendor/github.com/containers/buildah/run_linux.go70
-rw-r--r--vendor/github.com/containers/buildah/util.go168
-rw-r--r--vendor/github.com/containers/buildah/util/util.go46
-rw-r--r--vendor/github.com/containers/buildah/vendor.conf4
-rw-r--r--vendor/github.com/containers/image/docker/docker_image_src.go61
-rw-r--r--vendor/github.com/containers/image/docker/reference/README.md2
-rw-r--r--vendor/github.com/containers/image/docker/reference/normalize.go29
-rw-r--r--vendor/github.com/containers/image/docker/reference/reference.go4
-rw-r--r--vendor/github.com/containers/image/docker/reference/regexp.go10
-rw-r--r--vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go224
-rw-r--r--vendor/github.com/containers/image/version/version.go6
-rw-r--r--version/version.go2
73 files changed, 1885 insertions, 1023 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 91caf7fe0..c1b05c1bf 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -21,12 +21,10 @@ env:
CIRRUS_SHELL: "/bin/bash"
# Save a little typing (path relative to $CIRRUS_WORKING_DIR)
SCRIPT_BASE: "./contrib/cirrus"
- # Command to prefix every output line with a timestamp
+ CIRRUS_CLONE_DEPTH: 50
+ # Command to prefix output lines with timing information
# (can't do inline awk script, Cirrus-CI or YAML mangles quoting)
TIMESTAMP: "awk --file ${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/timestamp.awk"
- # Command to log critical filesystems, types, and sizes.
- DFCMD: "df -lhTx tmpfs"
- CIRRUS_CLONE_DEPTH: 50
####
#### Cache-image names to test with
@@ -281,18 +279,16 @@ testing_task:
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
- ginkgo_node_logs_script: 'cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log || echo "Ginkgo node logs not found"'
- df_script: '${DFCMD}'
- audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
- journalctl_b_script: 'journalctl -b'
+ system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
on_failure:
failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
- # Job has already failed, don't fail again and miss collecting data
- failed_ginkgo_node_logs_script: 'cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log || echo "Ginkgo node logs not found"'
- failed_df_script: '${DFCMD}'
- failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
- failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
+
+ always: &standardlogs
+ ginkgo_node_logs_script: '$SCRIPT_BASE/logcollector.sh ginkgo'
+ df_script: '$SCRIPT_BASE/logcollector.sh df'
+ audit_log_script: '$SCRIPT_BASE/logcollector.sh audit'
+ journal_script: '$SCRIPT_BASE/logcollector.sh journal'
# This task executes tests under unique environments/conditions
@@ -317,16 +313,14 @@ special_testing_rootless_task:
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
- df_script: '${DFCMD}'
- audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
- journalctl_b_script: 'journalctl -b'
+ system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
on_failure:
failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
- # Job has already failed, don't fail again and miss collecting data
- failed_df_script: '${DFCMD}'
- failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
- failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
+
+ always:
+ <<: *standardlogs
+
special_testing_in_podman_task:
@@ -345,16 +339,12 @@ special_testing_in_podman_task:
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
- df_script: '${DFCMD}'
- audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
- journalctl_b_script: 'journalctl -b'
on_failure:
failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
- # Job has already failed, don't fail again and miss collecting data
- failed_df_script: '${DFCMD}'
- failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
- failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
+
+ always:
+ <<: *standardlogs
# Test building of new cache-images for future PR testing, in this PR.
@@ -423,16 +413,9 @@ verify_test_built_images_task:
environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
- ginkgo_node_logs_script: 'cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log || echo "Ginkgo node logs not found"'
- df_script: '${DFCMD}'
- audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
- journalctl_b_script: 'journalctl -b'
- on_failure:
- # Job has already failed, don't fail again and miss collecting data
- failed_ginkgo_node_logs_script: 'cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log || echo "Ginkgo node logs not found"'
- failed_df_script: '${DFCMD}'
- failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
- failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
+
+ always:
+ <<: *standardlogs
# Post message to IRC if everything passed
diff --git a/API.md b/API.md
index b6fdea695..cfe050343 100755
--- a/API.md
+++ b/API.md
@@ -286,7 +286,7 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method Attach(name: [string](https://godoc.org/builtin#string), detachKeys: [string](https://godoc.org/builtin#string), start: [bool](https://godoc.org/builtin#bool)) </div>
-Attach takes the name or ID of a container and sets up a the ability to remotely attach to its console. The start
+Attach takes the name or ID of a container and sets up the ability to remotely attach to its console. The start
bool is whether you wish to start the container in question first.
### <a name="AttachControl"></a>func AttachControl
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -459,7 +459,7 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.ExportContainer '{"name":
method ExportImage(name: [string](https://godoc.org/builtin#string), destination: [string](https://godoc.org/builtin#string), compress: [bool](https://godoc.org/builtin#bool), tags: [[]string](#[]string)) [string](https://godoc.org/builtin#string)</div>
ExportImage takes the name or ID of an image and exports it to a destination like a tarball. There is also
-a booleon option to force compression. It also takes in a string array of tags to be able to save multiple
+a boolean option to force compression. It also takes in a string array of tags to be able to save multiple
tags of the same image to a tarball (each tag should be of the form <image>:<tag>). Upon completion, the ID
of the image is returned. If the image cannot be found in local storage, an [ImageNotFound](#ImageNotFound)
error will be returned. See also [ImportImage](ImportImage).
@@ -729,14 +729,14 @@ error will be returned if the container cannot be found. See also [InspectImage]
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method InspectImage(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
-InspectImage takes the name or ID of an image and returns a string respresentation of data associated with the
+InspectImage takes the name or ID of an image and returns a string representation of data associated with the
mage. You must serialize the string into JSON to use it further. An [ImageNotFound](#ImageNotFound) error will
be returned if the image cannot be found.
### <a name="InspectPod"></a>func InspectPod
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
method InspectPod(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
-InspectPod takes the name or ID of an image and returns a string respresentation of data associated with the
+InspectPod takes the name or ID of an image and returns a string representation of data associated with the
pod. You must serialize the string into JSON to use it further. A [PodNotFound](#PodNotFound) error will
be returned if the pod cannot be found.
### <a name="KillContainer"></a>func KillContainer
@@ -1650,7 +1650,7 @@ name [string](https://godoc.org/builtin#string)
star_count [int](https://godoc.org/builtin#int)
### <a name="InfoDistribution"></a>type InfoDistribution
-InfoDistribution describes the the host's distribution
+InfoDistribution describes the host's distribution
distribution [string](https://godoc.org/builtin#string)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8b7544ba0..b86f3e345 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -315,7 +315,7 @@ branches, which you may occasionally see [red bars on the status graph
.](https://cirrus-ci.com/github/containers/libpod/master)
When the graph shows mostly green bars on the right, it's a good indication
-the master branch is currently stable. Alternating red/green bars is indicitave
+the master branch is currently stable. Alternating red/green bars is indicative
of a testing "flake", and should be examined (anybody can do this):
* *One or a small handful of tests, on a single task, (i.e. specific distro/version)
diff --git a/Makefile b/Makefile
index 9660ad78d..881236452 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
GO ?= go
-DESTDIR ?= /
-EPOCH_TEST_COMMIT ?= 1f31892a9fd8573d4b25274b208e6b9f860cdf81
+DESTDIR ?=
+EPOCH_TEST_COMMIT ?= 5df8178c995fe6422f0fed258cd65f6cbcf26f2e
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
@@ -10,12 +10,12 @@ GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
GIT_BRANCH_CLEAN ?= $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g")
LIBPOD_IMAGE ?= libpod_dev$(if $(GIT_BRANCH_CLEAN),:$(GIT_BRANCH_CLEAN))
LIBPOD_INSTANCE := libpod_dev
-PREFIX ?= ${DESTDIR}/usr/local
+PREFIX ?= /usr/local
BINDIR ?= ${PREFIX}/bin
LIBEXECDIR ?= ${PREFIX}/libexec
MANDIR ?= ${PREFIX}/share/man
SHAREDIR_CONTAINERS ?= ${PREFIX}/share/containers
-ETCDIR ?= ${DESTDIR}/etc
+ETCDIR ?= /etc
TMPFILESDIR ?= ${PREFIX}/lib/tmpfiles.d
SYSTEMDDIR ?= ${PREFIX}/lib/systemd/system
BUILDTAGS ?= \
@@ -51,7 +51,11 @@ COMMIT_NO ?= $(shell git rev-parse HEAD 2> /dev/null || true)
GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),${COMMIT_NO}-dirty,${COMMIT_NO})
BUILD_INFO ?= $(shell date +%s)
LIBPOD := ${PROJECT}/libpod
-LDFLAGS_PODMAN ?= $(LDFLAGS) -X $(LIBPOD).gitCommit=$(GIT_COMMIT) -X $(LIBPOD).buildInfo=$(BUILD_INFO)
+LDFLAGS_PODMAN ?= $(LDFLAGS) \
+ -X $(LIBPOD).gitCommit=$(GIT_COMMIT) \
+ -X $(LIBPOD).buildInfo=$(BUILD_INFO) \
+ -X $(LIBPOD).installPrefix=$(PREFIX) \
+ -X $(LIBPOD).etcDir=$(ETCDIR)
ISODATE ?= $(shell date --iso-8601)
#Update to LIBSECCOMP_COMMIT should reflect in Dockerfile too.
LIBSECCOMP_COMMIT := release-2.3
@@ -216,8 +220,11 @@ localintegration: varlink_generate test-binaries ginkgo
remoteintegration: varlink_generate test-binaries ginkgo-remote
-localsystem: .install.ginkgo
- ginkgo -v -noColor test/system/
+localsystem:
+ if timeout -v 1 true; then PODMAN=./bin/podman bats test/system/; else echo "Skipping localsystem: 'timeout -v' unavailable'"; fi
+
+remotesystem:
+ @echo "remotesystem - unimplemented"
system.test-binary: .install.ginkgo
$(GO) test -c ./test/system
@@ -262,54 +269,54 @@ changelog: ## Generate changelog
install: .gopathok install.bin install.remote install.man install.cni install.systemd ## Install binaries to system locations
install.remote:
- install ${SELINUXOPT} -d -m 755 $(BINDIR)
- install ${SELINUXOPT} -m 755 bin/podman-remote $(BINDIR)/podman-remote
- test -z "${SELINUXOPT}" || chcon --verbose --reference=$(BINDIR)/podman bin/podman-remote
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR)
+ install ${SELINUXOPT} -m 755 bin/podman-remote $(DESTDIR)$(BINDIR)/podman-remote
+ test -z "${SELINUXOPT}" || chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman bin/podman-remote
install.bin:
- install ${SELINUXOPT} -d -m 755 $(BINDIR)
- install ${SELINUXOPT} -m 755 bin/podman $(BINDIR)/podman
- test -z "${SELINUXOPT}" || chcon --verbose --reference=$(BINDIR)/podman bin/podman
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR)
+ install ${SELINUXOPT} -m 755 bin/podman $(DESTDIR)$(BINDIR)/podman
+ test -z "${SELINUXOPT}" || chcon --verbose --reference=$(DESTDIR)$(BINDIR)/podman bin/podman
install.man: docs
- install ${SELINUXOPT} -d -m 755 $(MANDIR)/man1
- install ${SELINUXOPT} -d -m 755 $(MANDIR)/man5
- install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES)) -t $(MANDIR)/man1
- install ${SELINUXOPT} -m 644 $(filter %.5,$(MANPAGES)) -t $(MANDIR)/man5
- install ${SELINUXOPT} -m 644 docs/links/*1 -t $(MANDIR)/man1
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man1
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man5
+ install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES)) -t $(DESTDIR)$(MANDIR)/man1
+ install ${SELINUXOPT} -m 644 $(filter %.5,$(MANPAGES)) -t $(DESTDIR)$(MANDIR)/man5
+ install ${SELINUXOPT} -m 644 docs/links/*1 -t $(DESTDIR)$(MANDIR)/man1
install.config:
- install ${SELINUXOPT} -d -m 755 $(SHAREDIR_CONTAINERS)
- install ${SELINUXOPT} -m 644 libpod.conf $(SHAREDIR_CONTAINERS)/libpod.conf
- install ${SELINUXOPT} -m 644 seccomp.json $(SHAREDIR_CONTAINERS)/seccomp.json
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(SHAREDIR_CONTAINERS)
+ install ${SELINUXOPT} -m 644 libpod.conf $(DESTDIR)$(SHAREDIR_CONTAINERS)/libpod.conf
+ install ${SELINUXOPT} -m 644 seccomp.json $(DESTDIR)$(SHAREDIR_CONTAINERS)/seccomp.json
install.completions:
- install ${SELINUXOPT} -d -m 755 ${BASHINSTALLDIR}
- install ${SELINUXOPT} -m 644 completions/bash/podman ${BASHINSTALLDIR}
- install ${SELINUXOPT} -d -m 755 ${ZSHINSTALLDIR}
- install ${SELINUXOPT} -m 644 completions/zsh/_podman ${ZSHINSTALLDIR}
+ install ${SELINUXOPT} -d -m 755 ${DESTDIR}${BASHINSTALLDIR}
+ install ${SELINUXOPT} -m 644 completions/bash/podman ${DESTDIR}${BASHINSTALLDIR}
+ install ${SELINUXOPT} -d -m 755 ${DESTDIR}${ZSHINSTALLDIR}
+ install ${SELINUXOPT} -m 644 completions/zsh/_podman ${DESTDIR}${ZSHINSTALLDIR}
install.cni:
- install ${SELINUXOPT} -d -m 755 ${ETCDIR}/cni/net.d/
- install ${SELINUXOPT} -m 644 cni/87-podman-bridge.conflist ${ETCDIR}/cni/net.d/87-podman-bridge.conflist
+ install ${SELINUXOPT} -d -m 755 ${DESTDIR}${ETCDIR}/cni/net.d/
+ install ${SELINUXOPT} -m 644 cni/87-podman-bridge.conflist ${DESTDIR}${ETCDIR}/cni/net.d/87-podman-bridge.conflist
install.docker: docker-docs
- install ${SELINUXOPT} -d -m 755 $(BINDIR) $(MANDIR)/man1
- install ${SELINUXOPT} -m 755 docker $(BINDIR)/docker
- install ${SELINUXOPT} -m 644 docs/docker*.1 -t $(MANDIR)/man1
+ install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man1
+ install ${SELINUXOPT} -m 755 docker $(DESTDIR)$(BINDIR)/docker
+ install ${SELINUXOPT} -m 644 docs/docker*.1 -t $(DESTDIR)$(MANDIR)/man1
install.systemd:
- install ${SELINUXOPT} -m 755 -d ${SYSTEMDDIR} ${TMPFILESDIR}
- install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.socket ${SYSTEMDDIR}/io.podman.socket
- install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.service ${SYSTEMDDIR}/io.podman.service
- install ${SELINUXOPT} -m 644 contrib/varlink/podman.conf ${TMPFILESDIR}/podman.conf
+ install ${SELINUXOPT} -m 755 -d ${DESTDIR}${SYSTEMDDIR} ${DESTDIR}${TMPFILESDIR}
+ install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.socket ${DESTDIR}${SYSTEMDDIR}/io.podman.socket
+ install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.service ${DESTDIR}${SYSTEMDDIR}/io.podman.service
+ install ${SELINUXOPT} -m 644 contrib/varlink/podman.conf ${DESTDIR}${TMPFILESDIR}/podman.conf
uninstall:
for i in $(filter %.1,$(MANPAGES)); do \
- rm -f $(MANDIR)/man1/$$(basename $${i}); \
+ rm -f $(DESTDIR)$(MANDIR)/man1/$$(basename $${i}); \
done; \
for i in $(filter %.5,$(MANPAGES)); do \
- rm -f $(MANDIR)/man5/$$(basename $${i}); \
+ rm -f $(DESTDIR)$(MANDIR)/man5/$$(basename $${i}); \
done
.PHONY: .gitvalidation
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index fbb6a78b0..2264dbaa9 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,34 @@
# Release Notes
+## 1.4.2
+### Bugfixes
+- Fixed a bug where Podman could not run containers using an older version of Systemd as init ([#3295](https://github.com/containers/libpod/issues/3295))
+
+### Misc
+- Updated vendored Buildah to v1.9.0 to resolve a critical bug with Dockerfile `RUN` instructions
+- The error message for running `podman kill` on containers that are not running has been improved
+- The Podman remote client can now log to a file if syslog is not available
+
+## 1.4.1
+### Features
+- The `podman exec` command now sets its error code differently based on whether the container does not exist, and the command in the container does not exist
+- The `podman inspect` command on containers now outputs Mounts JSON that matches that of `docker inspect`, only including user-specified volumes and differentiating bind mounts and named volumes
+- The `podman inspect` command now reports the path to a container's OCI spec with the `OCIConfigPath` key (only included when the container is initialized or running)
+- The `podman run --mount` command now supports the `bind-nonrecursive` option for bind mounts ([#3314](https://github.com/containers/libpod/issues/3314))
+
+### Bugfixes
+- Fixed a bug where `podman play kube` would fail to create containers due to an unspecified log driver
+- Fixed a bug where Podman would fail to build with [musl libc](https://www.musl-libc.org/) ([#3284](https://github.com/containers/libpod/issues/3284))
+- Fixed a bug where rootless Podman using `slirp4netns` networking in an environment with no nameservers on the host other than localhost would result in nonfunctional networking ([#3277](https://github.com/containers/libpod/issues/3277))
+- Fixed a bug where `podman import` would not properly set environment variables, discarding their values and retaining only keys
+- Fixed a bug where Podman would fail to run when built with Apparmor support but run on systems without the Apparmor kernel module loaded ([#3331](https://github.com/containers/libpod/issues/3331))
+
+### Misc
+- Remote Podman will now default the username it uses to log in to remote systems to the username of the current user
+- Podman now uses JSON logging with OCI runtimes that support it, allowing for better error reporting
+- Updated vendored Buildah to v1.8.4
+- Updated vendored containers/image to v2.0
+
## 1.4.0
### Features
- The `podman checkpoint` and `podman restore` commands can now be used to migrate containers between Podman installations on different systems ([#1618](https://github.com/containers/libpod/issues/1618))
diff --git a/changelog.txt b/changelog.txt
index ece82e15b..9e201ecb4 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,82 @@
+- Changelog for v1.4.2 (2019-06-18)
+ * Update release notes for Podman 1.4.2
+ * updating podman logo files
+ * fix port -l timing with healthchecks
+ * Bump Buildah to v1.9.0
+ * Swap to using the on-disk spec for inspect mounts
+ * Replace podman.svg; closes #3350
+ * cmd, docs, test: fix some typos
+ * run BATS tests in Cirrus
+ * Move the Config portion of Inspect into libpod
+ * Add remote client logging to a file
+ * Fix subgidname option in docs for podman run
+ * stop/kill: inproper state errors: s/in state/is in state/
+ * test: add test for logs -f
+ * kill: print ID and state for non-running containers
+ * API.md: fix few typos
+ * docs/podamn.1.md: fix typo: remove double the
+ * CONTRIBUTING.md: fix typo
+ * Remove unnecessary var type to fix lint warning
+ * Move installPrefix and etcDir into runtime.go
+ * Improve DESTDIR/PREFIX/ETCDIR handling
+ * Bump gitvalidation epoch
+ * Bump to v1.4.2-dev
+ * Change container command to contained
+ * Cirrus: Simplify log collection commands
+ * Accidently removed /run/lock from systemd mounts
+ * Add warning while untagging an image podman-load
+ * podman copy files to the volume with a container
+
+- Changelog for v1.4.1 (2019-06-14)
+ * Completely disable global options test
+ * Update release notes for 1.4.1
+ * Skip runlabel global options test for podman-in-podman
+ * pkg/apparmor: fix when AA is disabled
+ * Fix ENV parsing on `podman import`
+ * Fix storage-opts type in Cobra
+ * Use the logical registry location instead of the physical one in (podman info)
+ * Update containers/image to v2.0.0, and buildah to v1.8.4
+ * Document exit codes for podman exec
+ * Add --storage flag to 'podman rm' (local only)
+ * When creating exit command, pass storage options on
+ * Bump cirrus images
+ * Mention the new Podman mailing list in contributing.md
+ * Update 1.4.0 release notes with ID -> Id in inspect
+ * Bump conmon to 0.3.0
+ * Cirrus: Guarantee ssh is running for rootless
+ * Purge all use of easyjson and ffjson in libpod
+ * Split mount options in inspect further
+ * storage: support --mount type=bind,bind-nonrecursive
+ * oci: allow to specify what runtimes support JSON
+ * storage: fix typo
+ * oci: use json formatted errors from the runtime
+ * Make Inspect's mounts struct accurate to Docker
+ * Provide OCI spec path in `podman inspect` output
+ * If container is not in correct state podman exec should exit with 126
+ * rootless: use the slirp4netns builtin DNS first
+ * Add --filename option to generate kube
+ * Fix podman-remote to user default username
+ * Prohibit use of positional args with --import
+ * BATS tests - get working again
+ * Add a test for 'podman play kube' to prevent regression
+ * Cirrus: New images w/o buildah
+ * Remove source-built buildah from CI
+ * standardize documentation formatting
+ * Touchup upstream Dockerfile
+ * only set log driver if it isn't empty
+ * Fix cgo includes for musl
+ * When you change the storage driver we ignore the storage-options
+ * Update vendor on containers/storage to v1.12.10
+ * Bump gitvalidation epoch
+ * Bump to v1.4.1-dev
+ * Default 'pause' to false for 'podman cp'
+ * Update c/storage to 9b10041d7b2ef767ce9c42b5862b6c51eeb82214
+ * Fix spelling
+ * fix tutorial link to install.md
+ * Cirrus: Minor cleanup of dependencies and docs
+ * Begin to break up pkg/inspect
+ * docs: Add CI section and links
+
- Changelog for v1.4.0 (2019-06-07)
* Update release notes for v1.4.0
* Update release notes for v1.4.0
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 545166d05..4a4c839cc 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -439,6 +439,7 @@ type RmValues struct {
All bool
Force bool
Latest bool
+ Storage bool
Volumes bool
}
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 01e2ec701..db0b8241e 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -26,9 +26,9 @@ var (
commitCommand.Remote = remoteclient
return commitCmd(&commitCommand)
},
- Example: `podman commit -q --message "committing container to image" reverent_golick image-commited
- podman commit -q --author "firstName lastName" reverent_golick image-commited
- podman commit -q --pause=false containerID image-commited`,
+ Example: `podman commit -q --message "committing container to image" reverent_golick image-committed
+ podman commit -q --author "firstName lastName" reverent_golick image-committed
+ podman commit -q --pause=false containerID image-committed`,
}
)
diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go
index 7679ebcf1..a9418e6e0 100644
--- a/cmd/podman/cp.go
+++ b/cmd/podman/cp.go
@@ -145,7 +145,19 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
var glob []string
if isFromHostToCtr {
- if filepath.IsAbs(destPath) {
+ if isVol, volDestName, volName := isVolumeDestName(destPath, ctr); isVol {
+ path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, destPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting destination path from volume %s", volDestName)
+ }
+ destPath = path
+ } else if isBindMount, mount := isBindMountDestName(destPath, ctr); isBindMount {
+ path, err := pathWithBindMountSource(mount, destPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting destination path from bind mount %s", mount.Destination)
+ }
+ destPath = path
+ } else if filepath.IsAbs(destPath) {
cleanedPath, err := securejoin.SecureJoin(mountPoint, destPath)
if err != nil {
return err
@@ -166,7 +178,19 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
destPath = cleanedPath
}
} else {
- if filepath.IsAbs(srcPath) {
+ if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol {
+ path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, srcPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting source path from volume %s", volDestName)
+ }
+ srcPath = path
+ } else if isBindMount, mount := isBindMountDestName(srcPath, ctr); isBindMount {
+ path, err := pathWithBindMountSource(mount, srcPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting source path from bind moutn %s", mount.Destination)
+ }
+ srcPath = path
+ } else if filepath.IsAbs(srcPath) {
cleanedPath, err := securejoin.SecureJoin(mountPoint, srcPath)
if err != nil {
return err
@@ -407,3 +431,72 @@ func streamFileToStdout(srcPath string, srcfi os.FileInfo) error {
}
return nil
}
+
+func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string) {
+ separator := string(os.PathSeparator)
+ if filepath.IsAbs(path) {
+ path = strings.TrimPrefix(path, separator)
+ }
+ if path == "" {
+ return false, "", ""
+ }
+ for _, vol := range ctr.Config().NamedVolumes {
+ volNamePath := strings.TrimPrefix(vol.Dest, separator)
+ if matchVolumePath(path, volNamePath) {
+ return true, vol.Dest, vol.Name
+ }
+ }
+ return false, "", ""
+}
+
+// if SRCPATH or DESTPATH is from volume mount's destination -v or --mount type=volume, generates the path with volume mount point
+func pathWithVolumeMount(ctr *libpod.Container, runtime *libpod.Runtime, volDestName, volName, path string) (string, error) {
+ destVolume, err := runtime.GetVolume(volName)
+ if err != nil {
+ return "", errors.Wrapf(err, "error getting volume destination %s", volName)
+ }
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(string(os.PathSeparator), path)
+ }
+ path, err = securejoin.SecureJoin(destVolume.MountPoint(), strings.TrimPrefix(path, volDestName))
+ return path, err
+}
+
+func isBindMountDestName(path string, ctr *libpod.Container) (bool, specs.Mount) {
+ separator := string(os.PathSeparator)
+ if filepath.IsAbs(path) {
+ path = strings.TrimPrefix(path, string(os.PathSeparator))
+ }
+ if path == "" {
+ return false, specs.Mount{}
+ }
+ for _, m := range ctr.Config().Spec.Mounts {
+ if m.Type != "bind" {
+ continue
+ }
+ mDest := strings.TrimPrefix(m.Destination, separator)
+ if matchVolumePath(path, mDest) {
+ return true, m
+ }
+ }
+ return false, specs.Mount{}
+}
+
+func matchVolumePath(path, target string) bool {
+ pathStr := filepath.Clean(path)
+ target = filepath.Clean(target)
+ for len(pathStr) > len(target) && strings.Contains(pathStr, string(os.PathSeparator)) {
+ pathStr = pathStr[:strings.LastIndex(pathStr, string(os.PathSeparator))]
+ }
+ if pathStr == target {
+ return true
+ }
+ return false
+}
+
+func pathWithBindMountSource(m specs.Mount, path string) (string, error) {
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(string(os.PathSeparator), path)
+ }
+ return securejoin.SecureJoin(m.Source, strings.TrimPrefix(path, m.Destination))
+}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index a149a47f9..847cc0731 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -104,6 +104,7 @@ func before(cmd *cobra.Command, args []string) error {
logrus.Errorf(err.Error())
os.Exit(1)
}
+
if err := setupRootless(cmd, args); err != nil {
return err
}
@@ -118,6 +119,9 @@ func before(cmd *cobra.Command, args []string) error {
return err
}
logrus.SetLevel(level)
+ if err := setSyslog(); err != nil {
+ return err
+ }
if err := setRLimits(); err != nil {
return err
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index b4f21bd0c..132f35ab5 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -48,7 +48,7 @@ func init() {
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
// -s is depracated due to conflict with -s on subcommands
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
- rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
+ rootCmd.PersistentFlags().StringArrayVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go
index 1b9430e92..ecbb44d5a 100644
--- a/cmd/podman/main_remote.go
+++ b/cmd/podman/main_remote.go
@@ -3,8 +3,13 @@
package main
import (
+ "fmt"
+ "os"
"os/user"
+ "path/filepath"
+ "github.com/docker/docker/pkg/homedir"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -20,11 +25,41 @@ func init() {
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteUserName, "username", username, "username on the remote host")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteHost, "remote-host", "", "remote host")
// TODO maybe we allow the altering of this for bridge connections?
- //rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.VarlinkAddress, "varlink-address", adapter.DefaultAddress, "address of the varlink socket")
- rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error, fatal or panic")
+ // rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.VarlinkAddress, "varlink-address", adapter.DefaultAddress, "address of the varlink socket")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error, fatal or panic. Logged to ~/.config/containers/podman.log")
+ rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
}
func setSyslog() error {
+ // Log to file if not using syslog
+ homeDir := homedir.Get()
+ path := filepath.Join(homeDir, ".config", "containers")
+
+ if _, err := os.Stat(path); os.IsNotExist(err) {
+ if err := os.MkdirAll(path, 0750); err != nil {
+ fmt.Fprintf(os.Stderr, "%v", err)
+ return err
+ }
+ }
+
+ // Update path to include file name
+ path = filepath.Join(path, "podman.log")
+
+ // Create the log file if doesn't exist. And append to it if it already exists.
+ file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0640)
+ if err != nil {
+ // Cannot open log file. Logging to stderr
+ fmt.Fprintf(os.Stderr, "%v", err)
+ return err
+ } else {
+ formatter := new(logrus.TextFormatter)
+ formatter.FullTimestamp = true
+ logrus.SetFormatter(formatter)
+ logrus.SetOutput(file)
+ }
+
+ // Note this message is only logged if --log-level >= Info!
+ logrus.Infof("Logging level set to %s", logrus.GetLevel().String())
return nil
}
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index 1bf56b782..2710a8194 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -42,7 +42,9 @@ func init() {
flags.BoolVarP(&rmCommand.All, "all", "a", false, "Remove all containers")
flags.BoolVarP(&rmCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
flags.BoolVarP(&rmCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVar(&rmCommand.Storage, "storage", false, "Remove container from storage library")
flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove the volumes associated with the container")
+ markFlagHiddenForRemoteClient("storage", flags)
markFlagHiddenForRemoteClient("latest", flags)
}
@@ -54,6 +56,13 @@ func rmCmd(c *cliconfig.RmValues) error {
}
defer runtime.Shutdown(false)
+ // Storage conflicts with --all/--latest/--volumes
+ if c.Storage {
+ if c.All || c.Latest || c.Volumes {
+ return errors.Errorf("--storage conflicts with --volumes, --all, and --latest")
+ }
+ }
+
ok, failures, err := runtime.RemoveContainers(getContext(), c)
if err != nil {
if errors.Cause(err) == libpod.ErrNoSuchCtr {
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index c97eaa290..f24a2358f 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -710,7 +710,7 @@ func portsToString(ports []ocicni.PortMapping) string {
}
// GetRunlabel is a helper function for runlabel; it gets the image if needed and begins the
-// contruction of the runlabel output and environment variables
+// construction of the runlabel output and environment variables
func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtime *libpod.Runtime, pull bool, inputCreds string, dockerRegistryOptions image.DockerRegistryOptions, authfile string, signaturePolicyPath string, output io.Writer) (string, string, error) {
var (
newImage *image.Image
diff --git a/cmd/podman/shared/container_inspect.go b/cmd/podman/shared/container_inspect.go
index 97a1d0238..c89daf6bb 100644
--- a/cmd/podman/shared/container_inspect.go
+++ b/cmd/podman/shared/container_inspect.go
@@ -1,9 +1,6 @@
package shared
import (
- "strings"
-
- "github.com/containers/image/manifest"
"github.com/containers/libpod/libpod"
cc "github.com/containers/libpod/pkg/spec"
"github.com/docker/go-connections/nat"
@@ -17,7 +14,6 @@ import (
type InspectContainer struct {
*libpod.InspectContainerData
HostConfig *InspectContainerHostConfig `json:"HostConfig"`
- Config *InspectContainerConfig `json:"Config"`
}
// InspectContainerHostConfig holds Container configuration that is not specific
@@ -82,33 +78,8 @@ type InspectContainerHostConfig struct {
Tmpfs []string `json:"Tmpfs"`
}
-// InspectContainerConfig holds further data about a container, again mostly
-// not directly stored in Libpod. This struct is matched to the output of
-// `docker inspect`.
-type InspectContainerConfig struct {
- Hostname string `json:"Hostname"`
- DomainName string `json:"Domainname"` //TODO
- User specs.User `json:"User"`
- AttachStdin bool `json:"AttachStdin"` //TODO
- AttachStdout bool `json:"AttachStdout"` //TODO
- AttachStderr bool `json:"AttachStderr"` //TODO
- Tty bool `json:"Tty"`
- OpenStdin bool `json:"OpenStdin"`
- StdinOnce bool `json:"StdinOnce"` //TODO
- Env []string `json:"Env"`
- Cmd []string `json:"Cmd"`
- Image string `json:"Image"`
- Volumes map[string]struct{} `json:"Volumes"`
- WorkingDir string `json:"WorkingDir"`
- Entrypoint string `json:"Entrypoint"`
- Labels map[string]string `json:"Labels"`
- Annotations map[string]string `json:"Annotations"`
- StopSignal uint `json:"StopSignal"`
- Healthcheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"`
-}
-
// InspectLogConfig holds information about a container's configured log driver
-// and is presently unused. It is retained for Docker compatability.
+// and is presently unused. It is retained for Docker compatibility.
type InspectLogConfig struct {
Type string `json:"Type"`
Config map[string]string `json:"Config"` //idk type, TODO
@@ -181,21 +152,6 @@ func GetCtrInspectInfo(config *libpod.ContainerConfig, ctrInspectData *libpod.In
SecurityOpt: createArtifact.SecurityOpts,
Tmpfs: createArtifact.Tmpfs,
},
- &InspectContainerConfig{
- Hostname: spec.Hostname,
- User: spec.Process.User,
- Env: spec.Process.Env,
- Image: config.RootfsImageName,
- WorkingDir: spec.Process.Cwd,
- Labels: config.Labels,
- Annotations: spec.Annotations,
- Tty: spec.Process.Terminal,
- OpenStdin: config.Stdin,
- StopSignal: config.StopSignal,
- Cmd: config.Spec.Process.Args,
- Entrypoint: strings.Join(createArtifact.Entrypoint, " "),
- Healthcheck: config.HealthCheckConfig,
- },
}
return data, nil
}
diff --git a/cmd/podman/system_df.go b/cmd/podman/system_df.go
index 840916547..d2163d0d7 100644
--- a/cmd/podman/system_df.go
+++ b/cmd/podman/system_df.go
@@ -586,7 +586,7 @@ func volumesVerboseOutput(ctx context.Context, metaData dfMetaData) error {
}
volumesVerboseDiskUsage, err := getVolumeVerboseDiskUsage(metaData.volumes, metaData.volumeUsedByContainerMap)
if err != nil {
- return errors.Wrapf(err, "error getting verbose ouput of volumes")
+ return errors.Wrapf(err, "error getting verbose output of volumes")
}
os.Stderr.WriteString("\nLocal Volumes space usage:\n\n")
out := formats.StdoutTemplateArray{Output: systemDfVolumeVerboseDiskUsageToGeneric(volumesVerboseDiskUsage), Template: volumeVerboseFormat, Fields: volumeVerboseHeader}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 5b3d5ae4c..9410b9459 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -207,7 +207,7 @@ type ContainerNameSpace (
ipc: string
)
-# InfoDistribution describes the the host's distribution
+# InfoDistribution describes the host's distribution
type InfoDistribution (
distribution: string,
version: string
@@ -671,7 +671,7 @@ method PauseContainer(name: string) -> (container: string)
# See also [PauseContainer](#PauseContainer).
method UnpauseContainer(name: string) -> (container: string)
-# Attach takes the name or ID of a container and sets up a the ability to remotely attach to its console. The start
+# Attach takes the name or ID of a container and sets up the ability to remotely attach to its console. The start
# bool is whether you wish to start the container in question first.
method Attach(name: string, detachKeys: string, start: bool) -> ()
@@ -744,7 +744,7 @@ method BuildImage(build: BuildInfo) -> (image: MoreResponse)
# This function is not implemented yet.
# method CreateImage() -> (notimplemented: NotImplemented)
-# InspectImage takes the name or ID of an image and returns a string respresentation of data associated with the
+# InspectImage takes the name or ID of an image and returns a string representation of data associated with the
#image. You must serialize the string into JSON to use it further. An [ImageNotFound](#ImageNotFound) error will
# be returned if the image cannot be found.
method InspectImage(name: string) -> (image: string)
@@ -810,7 +810,7 @@ method Commit(name: string, image_name: string, changes: []string, author: strin
method ImportImage(source: string, reference: string, message: string, changes: []string, delete: bool) -> (image: string)
# ExportImage takes the name or ID of an image and exports it to a destination like a tarball. There is also
-# a booleon option to force compression. It also takes in a string array of tags to be able to save multiple
+# a boolean option to force compression. It also takes in a string array of tags to be able to save multiple
# tags of the same image to a tarball (each tag should be of the form <image>:<tag>). Upon completion, the ID
# of the image is returned. If the image cannot be found in local storage, an [ImageNotFound](#ImageNotFound)
# error will be returned. See also [ImportImage](ImportImage).
@@ -915,7 +915,7 @@ method ListPods() -> (pods: []ListPodData)
# ~~~
method GetPod(name: string) -> (pod: ListPodData)
-# InspectPod takes the name or ID of an image and returns a string respresentation of data associated with the
+# InspectPod takes the name or ID of an image and returns a string representation of data associated with the
# pod. You must serialize the string into JSON to use it further. A [PodNotFound](#PodNotFound) error will
# be returned if the pod cannot be found.
method InspectPod(name: string) -> (pod: string)
diff --git a/completions/bash/podman b/completions/bash/podman
index b049f309a..65c6308cc 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -2041,6 +2041,7 @@ _podman_rm() {
-h
--latest
-l
+ --storage
--volumes
-v
"
diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh
new file mode 100755
index 000000000..425a619b0
--- /dev/null
+++ b/contrib/cirrus/logcollector.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+set -e
+
+source $(dirname $0)/lib.sh
+
+req_env_var CIRRUS_WORKING_DIR OS_RELEASE_ID
+
+# Assume there are other log collection commands to follow - Don't
+# let one break another that may be useful, but also keep any
+# actual script-problems fatal so they are noticed right away.
+showrun() {
+ echo '+ '$(printf " %q" "$@")
+ set +e
+ echo '------------------------------------------------------------'
+ "$@"
+ local status=$?
+ [[ $status -eq 0 ]] || \
+ echo "[ rc = $status -- proceeding anyway ]"
+ echo '------------------------------------------------------------'
+ set -e
+}
+
+case $1 in
+ audit)
+ case $OS_RELEASE_ID in
+ ubuntu) showrun cat /var/log/kern.log ;;
+ fedora) showrun cat /var/log/audit/audit.log ;;
+ *) bad_os_id_ver ;;
+ esac
+ ;;
+ df) showrun df -lhTx tmpfs ;;
+ ginkgo) showrun cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log ;;
+ journal) showrun journalctl -b ;;
+ *) die 1 "Warning, $(basename $0) doesn't know how to handle the parameter '$1'"
+esac
diff --git a/contrib/cirrus/system_test.sh b/contrib/cirrus/system_test.sh
index a2cc1af05..cbc481d6b 100755..120000
--- a/contrib/cirrus/system_test.sh
+++ b/contrib/cirrus/system_test.sh
@@ -1,21 +1 @@
-#!/bin/bash
-
-set -e
-source $(dirname $0)/lib.sh
-
-req_env_var GOSRC OS_RELEASE_ID OS_RELEASE_VER
-
-set -x
-cd "$GOSRC"
-
-case "${OS_RELEASE_ID}" in
- ubuntu) ;& # Continue to the next item
- fedora)
- make install.tools
- make
- make test-binaries
- ;;
- *) bad_os_id_ver ;;
-esac
-
-make localsystem
+integration_test.sh \ No newline at end of file
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index d755fd1aa..68d02325a 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -39,7 +39,7 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
-Version: 1.4.1
+Version: 1.4.3
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md
index 12e8c3bf0..120573235 100644
--- a/docs/podman-build.1.md
+++ b/docs/podman-build.1.md
@@ -172,7 +172,7 @@ value can be entered. The password is entered without echo.
This is a Docker specific option to disable image verification to a Docker
registry and is not supported by Podman. This flag is a NOOP and provided
-soley for scripting compatibility.
+solely for scripting compatibility.
**--dns**=*dns*
diff --git a/docs/podman-commit.1.md b/docs/podman-commit.1.md
index bf0df0dda..a269d0fae 100644
--- a/docs/podman-commit.1.md
+++ b/docs/podman-commit.1.md
@@ -58,7 +58,7 @@ Suppress output
## EXAMPLES
```
-$ podman commit --change CMD=/bin/bash --change ENTRYPOINT=/bin/sh --change LABEL=blue=image reverent_golick image-commited
+$ podman commit --change CMD=/bin/bash --change ENTRYPOINT=/bin/sh --change LABEL=blue=image reverent_golick image-committed
Getting image source signatures
Copying blob sha256:b41deda5a2feb1f03a5c1bb38c598cbc12c9ccd675f438edc6acd815f7585b86
25.80 MB / 25.80 MB [======================================================] 0s
@@ -70,17 +70,17 @@ e3ce4d93051ceea088d1c242624d659be32cf1667ef62f1d16d6b60193e2c7a8
```
```
-$ podman commit -q --message "committing container to image" reverent_golick image-commited
+$ podman commit -q --message "committing container to image" reverent_golick image-committed
e3ce4d93051ceea088d1c242624d659be32cf1667ef62f1d16d6b60193e2c7a8
```
```
-$ podman commit -q --author "firstName lastName" reverent_golick image-commited
+$ podman commit -q --author "firstName lastName" reverent_golick image-committed
e3ce4d93051ceea088d1c242624d659be32cf1667ef62f1d16d6b60193e2c7a8
```
```
-$ podman commit -q --pause=false containerID image-commited
+$ podman commit -q --pause=false containerID image-committed
e3ce4d93051ceea088d1c242624d659be32cf1667ef62f1d16d6b60193e2c7a8
```
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index a4eebef4c..9ab7b201a 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -55,11 +55,11 @@ Block IO weight (relative weight) accepts a weight value between 10 and 1000.
Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`).
-**--cap-add**=*capabilitiy*
+**--cap-add**=*capability*
Add Linux capabilities
-**--cap-drop**=*capabilitiy*
+**--cap-drop**=*capability*
Drop Linux capabilities
@@ -382,7 +382,7 @@ Not implemented
**--log-driver**="*k8s-file*"
-Logging driver for the container. Currently not supported. This flag is a NOOP provided soley for scripting compatibility.
+Logging driver for the container. Currently not supported. This flag is a NOOP provided solely for scripting compatibility.
**--log-opt**=*path*
diff --git a/docs/podman-exec.1.md b/docs/podman-exec.1.md
index a6a58df01..07d24e295 100644
--- a/docs/podman-exec.1.md
+++ b/docs/podman-exec.1.md
@@ -52,6 +52,34 @@ The default working directory for running binaries within a container is the roo
The image developer can set a different default with the WORKDIR instruction, which can be overridden
when creating the container.
+## Exit Status
+
+The exit code from `podman exec` gives information about why the command within the container failed to run or why it exited. When `podman exec` exits with a
+non-zero code, the exit codes follow the `chroot` standard, see below:
+
+**_125_** if the error is with podman **_itself_**
+
+ $ podman exec --foo ctrID /bin/sh; echo $?
+ Error: unknown flag: --foo
+ 125
+
+**_126_** if the **_contained command_** cannot be invoked
+
+ $ podman exec ctrID /etc; echo $?
+ Error: container_linux.go:346: starting container process caused "exec: \"/etc\": permission denied": OCI runtime error
+ 126
+
+**_127_** if the **_contained command_** cannot be found
+
+ $ podman exec ctrID foo; echo $?
+ Error: container_linux.go:346: starting container process caused "exec: \"foo\": executable file not found in $PATH": OCI runtime error
+ 127
+
+**_Exit code_** of **_contained command_** otherwise
+
+ $ podman exec ctrID /bin/sh -c 'exit 3'
+ # 3
+
## EXAMPLES
$ podman exec -it ctrID ls
diff --git a/docs/podman-generate-kube.1.md b/docs/podman-generate-kube.1.md
index 88d8e9627..76baad83a 100644
--- a/docs/podman-generate-kube.1.md
+++ b/docs/podman-generate-kube.1.md
@@ -20,7 +20,7 @@ Output to the given file, instead of STDOUT. If the file already exists, `genera
**--service**, **-s**
-Generate a Kubernetes service object in addition to the Pods. Used to generate a Service specification for the corresponding Pod ouput. In particular, if the object has portmap bindings, the service specification will include a NodePort declaration to expose the service. A
+Generate a Kubernetes service object in addition to the Pods. Used to generate a Service specification for the corresponding Pod output. In particular, if the object has portmap bindings, the service specification will include a NodePort declaration to expose the service. A
random port is assigned by Podman in the specification.
## Examples
diff --git a/docs/podman-rm.1.md b/docs/podman-rm.1.md
index c7ff23bdf..32a8c2943 100644
--- a/docs/podman-rm.1.md
+++ b/docs/podman-rm.1.md
@@ -30,6 +30,13 @@ to run containers such as CRI-O, the last started container could be from either
The latest option is not supported on the remote client.
+**--storage**
+
+Remove the container from the storage library only.
+This is only possible with containers that are not present in libpod (cannot be seen by `podman ps`).
+It is used to remove containers from `podman build` and `buildah`, and orphan containers which were only partially removed by `podman rm`.
+The storage option conflicts with the **--all**, **--latest**, and **--volumes** options.
+
**--volumes**, **-v**
Remove the volumes associated with the container.
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index 8d7deb99f..c678d2a4c 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -395,7 +395,7 @@ Not implemented
**--log-driver**="*k8s-file*"
-Logging driver for the container. Currently not supported. This flag is a NOOP provided soley for scripting compatibility.
+Logging driver for the container. Currently not supported. This flag is a NOOP provided solely for scripting compatibility.
**--log-opt**=*path*
@@ -669,7 +669,7 @@ Signal to stop a container. Default is SIGTERM.
Timeout (in seconds) to stop a container. Default is 10.
-**--subuidname**=*name*
+**--subgidname**=*name*
Run the container in a new user namespace using the map with 'name' in the `/etc/subgid` file.
If calling podman run as an unprivileged user, the user needs to have the right to use the mapping. See `subgid(5)`.
@@ -903,28 +903,25 @@ the exit codes follow the `chroot` standard, see below:
**_125_** if the error is with podman **_itself_**
$ podman run --foo busybox; echo $?
- # flag provided but not defined: --foo
- See 'podman run --help'.
- 125
+ Error: unknown flag: --foo
+ 125
**_126_** if the **_contained command_** cannot be invoked
$ podman run busybox /etc; echo $?
- # exec: "/etc": permission denied
- podman: Error response from daemon: Contained command could not be invoked
- 126
+ Error: container_linux.go:346: starting container process caused "exec: \"/etc\": permission denied": OCI runtime error
+ 126
**_127_** if the **_contained command_** cannot be found
$ podman run busybox foo; echo $?
- # exec: "foo": executable file not found in $PATH
- podman: Error response from daemon: Contained command not found or does not exist
- 127
+ Error: container_linux.go:346: starting container process caused "exec: \"foo\": executable file not found in $PATH": OCI runtime error
+ 127
**_Exit code_** of **_contained command_** otherwise
$ podman run busybox /bin/sh -c 'exit 3'
- # 3
+ 3
## EXAMPLES
diff --git a/docs/podman.1.md b/docs/podman.1.md
index b6c0628ed..c23075718 100644
--- a/docs/podman.1.md
+++ b/docs/podman.1.md
@@ -90,6 +90,8 @@ Storage driver option, Default storage driver options are configured in /etc/con
output logging information to syslog as well as the console
+On remote clients, logging is directed to the file ~/.config/containers/podman.log
+
**--version**, **-v**
Print the version
@@ -103,24 +105,21 @@ the exit codes follow the `chroot` standard, see below:
**_125_** if the error is with podman **_itself_**
$ podman run --foo busybox; echo $?
- # flag provided but not defined: --foo
- See 'podman run --help'.
+ Error: unknown flag: --foo
125
-**_126_** if executing a **_container command_** and the the **_command_** cannot be invoked
+**_126_** if executing a **_contained command_** and the **_command_** cannot be invoked
$ podman run busybox /etc; echo $?
- # exec: "/etc": permission denied
- podman: Error response from daemon: Contained command could not be invoked
+ Error: container_linux.go:346: starting container process caused "exec: \"/etc\": permission denied": OCI runtime error
126
-**_127_** if executing a **_container command_** and the the **_command_** cannot be found
+**_127_** if executing a **_contained command_** and the **_command_** cannot be found
$ podman run busybox foo; echo $?
- # exec: "foo": executable file not found in $PATH
- podman: Error response from daemon: Contained command not found or does not exist
+ Error: container_linux.go:346: starting container process caused "exec: \"foo\": executable file not found in $PATH": OCI runtime error
127
-**_Exit code_** of **_container command_** otherwise
+**_Exit code_** of **_contained command_** otherwise
$ podman run busybox /bin/sh -c 'exit 3'
# 3
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 52d3afc0a..0e877d04e 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -180,7 +180,7 @@ func (c *Container) StopWithTimeout(timeout uint) error {
if c.state.State == ContainerStateConfigured ||
c.state.State == ContainerStateUnknown ||
c.state.State == ContainerStatePaused {
- return errors.Wrapf(ErrCtrStateInvalid, "can only stop created, running, or stopped containers. %s in state %s", c.ID(), c.state.State.String())
+ return errors.Wrapf(ErrCtrStateInvalid, "can only stop created, running, or stopped containers. %s is in state %s", c.ID(), c.state.State.String())
}
if c.state.State == ContainerStateStopped ||
@@ -203,7 +203,7 @@ func (c *Container) Kill(signal uint) error {
}
if c.state.State != ContainerStateRunning {
- return errors.Wrapf(ErrCtrStateInvalid, "can only kill running containers")
+ return errors.Wrapf(ErrCtrStateInvalid, "can only kill running containers. %s is in state %s", c.ID(), c.state.State.String())
}
defer c.newContainerEvent(events.Kill)
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 0a62ceb7c..752823634 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -1,8 +1,10 @@
package libpod
import (
+ "strings"
"time"
+ "github.com/containers/image/manifest"
"github.com/containers/libpod/libpod/driver"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -49,6 +51,53 @@ type InspectContainerData struct {
ExitCommand []string `json:"ExitCommand"`
Namespace string `json:"Namespace"`
IsInfra bool `json:"IsInfra"`
+ Config *InspectContainerConfig `json:"Config"`
+}
+
+// InspectContainerConfig holds further data about how a container was initially
+// configured.
+type InspectContainerConfig struct {
+ // Container hostname
+ Hostname string `json:"Hostname"`
+ // Container domain name - unused at present
+ DomainName string `json:"Domainname"`
+ // User the container was launched with
+ User string `json:"User"`
+ // Unused, at present
+ AttachStdin bool `json:"AttachStdin"`
+ // Unused, at present
+ AttachStdout bool `json:"AttachStdout"`
+ // Unused, at present
+ AttachStderr bool `json:"AttachStderr"`
+ // Whether the container creates a TTY
+ Tty bool `json:"Tty"`
+ // Whether the container leaves STDIN open
+ OpenStdin bool `json:"OpenStdin"`
+ // Whether STDIN is only left open once.
+ // Presently not supported by Podman, unused.
+ StdinOnce bool `json:"StdinOnce"`
+ // Container environment variables
+ Env []string `json:"Env"`
+ // Container command
+ Cmd []string `json:"Cmd"`
+ // Container image
+ Image string `json:"Image"`
+ // Unused, at present. I've never seen this field populated.
+ Volumes map[string]struct{} `json:"Volumes"`
+ // Container working directory
+ WorkingDir string `json:"WorkingDir"`
+ // Container entrypoint
+ Entrypoint string `json:"Entrypoint"`
+ // On-build arguments - presently unused. More of Buildah's domain.
+ OnBuild *string `json:"OnBuild"`
+ // Container labels
+ Labels map[string]string `json:"Labels"`
+ // Container annotations
+ Annotations map[string]string `json:"Annotations"`
+ // Container stop signal
+ StopSignal uint `json:"StopSignal"`
+ // Configured healthcheck for the container
+ Healthcheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"`
}
// InspectMount provides a record of a single mount in a container. It contains
@@ -192,7 +241,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
}
}
- mounts, err := c.getInspectMounts()
+ mounts, err := c.getInspectMounts(spec)
if err != nil {
return nil, err
}
@@ -284,6 +333,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
// Get information on the container's network namespace (if present)
data = c.getContainerNetworkInfo(data)
+ inspectConfig, err := c.generateInspectContainerConfig(spec)
+ if err != nil {
+ return nil, err
+ }
+ data.Config = inspectConfig
+
if size {
rootFsSize, err := c.rootFsSize()
if err != nil {
@@ -302,7 +357,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
// Get inspect-formatted mounts list.
// Only includes user-specified mounts. Only includes bind mounts and named
// volumes, not tmpfs volumes.
-func (c *Container) getInspectMounts() ([]*InspectMount, error) {
+func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]*InspectMount, error) {
inspectMounts := []*InspectMount{}
// No mounts, return early
@@ -319,7 +374,7 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) {
for _, namedVol := range c.config.NamedVolumes {
namedVolumes[namedVol.Dest] = namedVol
}
- for _, mount := range c.config.Spec.Mounts {
+ for _, mount := range ctrSpec.Mounts {
mounts[mount.Destination] = mount
}
@@ -401,3 +456,56 @@ func parseMountOptionsForInspect(options []string, mount *InspectMount) {
mount.Mode = zZ
mount.Options = otherOpts
}
+
+// Generate the InspectContainerConfig struct for the Config field of Inspect.
+func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectContainerConfig, error) {
+ ctrConfig := new(InspectContainerConfig)
+
+ ctrConfig.Hostname = c.Hostname()
+ ctrConfig.User = c.config.User
+ if spec.Process != nil {
+ ctrConfig.Tty = spec.Process.Terminal
+ ctrConfig.Env = []string{}
+ for _, val := range spec.Process.Env {
+ ctrConfig.Env = append(ctrConfig.Env, val)
+ }
+ ctrConfig.WorkingDir = spec.Process.Cwd
+ }
+
+ ctrConfig.OpenStdin = c.config.Stdin
+ ctrConfig.Image = c.config.RootfsImageName
+
+ // Leave empty is not explicitly overwritten by user
+ if len(c.config.Command) != 0 {
+ ctrConfig.Cmd = []string{}
+ for _, val := range c.config.Command {
+ ctrConfig.Cmd = append(ctrConfig.Cmd, val)
+ }
+ }
+
+ // Leave empty if not explicitly overwritten by user
+ if len(c.config.Entrypoint) != 0 {
+ ctrConfig.Entrypoint = strings.Join(c.config.Entrypoint, " ")
+ }
+
+ if len(c.config.Labels) != 0 {
+ ctrConfig.Labels = make(map[string]string)
+ for k, v := range c.config.Labels {
+ ctrConfig.Labels[k] = v
+ }
+ }
+
+ if len(spec.Annotations) != 0 {
+ ctrConfig.Annotations = make(map[string]string)
+ for k, v := range spec.Annotations {
+ ctrConfig.Annotations[k] = v
+ }
+ }
+
+ ctrConfig.StopSignal = c.config.StopSignal
+ // TODO: should JSON deep copy this to ensure internal pointers don't
+ // leak.
+ ctrConfig.Healthcheck = c.config.HealthCheckConfig
+
+ return ctrConfig, nil
+}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 0be5427d9..55cc5089b 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -424,7 +424,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// It also expects to be able to write to /sys/fs/cgroup/systemd and /var/log/journal
func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) error {
options := []string{"rw", "rprivate", "noexec", "nosuid", "nodev"}
- for _, dest := range []string{"/run"} {
+ for _, dest := range []string{"/run", "/run/lock"} {
if MountExists(mounts, dest) {
continue
}
diff --git a/libpod/image/pull.go b/libpod/image/pull.go
index cb7411ce5..644a9ae86 100644
--- a/libpod/image/pull.go
+++ b/libpod/image/pull.go
@@ -149,6 +149,13 @@ func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types.
// Need to load in all the repo tags from the manifest
res := []pullRefPair{}
for _, dst := range manifest[0].RepoTags {
+ //check if image exists and gives a warning of untagging
+ localImage, err := ir.NewFromLocal(dst)
+ imageID := strings.TrimSuffix(manifest[0].Config, ".json")
+ if err == nil && imageID != localImage.ID() {
+ logrus.Errorf("the image %s already exists, renaming the old one with ID %s to empty string", dst, localImage.ID())
+ }
+
pullInfo, err := ir.getPullRefPair(srcRef, dst)
if err != nil {
return nil, err
@@ -168,7 +175,6 @@ func (ir *Runtime) pullGoalFromImageReference(ctx context.Context, srcRef types.
if err != nil {
return nil, errors.Wrapf(err, "error loading manifest for %q", srcRef)
}
-
var dest string
if manifest.Annotations == nil || manifest.Annotations["org.opencontainers.image.ref.name"] == "" {
// If the input image has no image.ref.name, we need to feed it a dest anyways
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 24bb5f61c..2c50fce85 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -42,11 +42,20 @@ const (
SQLiteStateStore RuntimeStateStore = iota
// BoltDBStateStore is a state backed by a BoltDB database
BoltDBStateStore RuntimeStateStore = iota
+)
+
+var (
+ // InstallPrefix is the prefix where podman will be installed.
+ // It can be overridden at build time.
+ installPrefix = "/usr/local"
+ // EtcDir is the sysconfdir where podman should look for system config files.
+ // It can be overridden at build time.
+ etcDir = "/etc"
// SeccompDefaultPath defines the default seccomp path
- SeccompDefaultPath = "/usr/share/containers/seccomp.json"
+ SeccompDefaultPath = installPrefix + "/share/containers/seccomp.json"
// SeccompOverridePath if this exists it overrides the default seccomp path
- SeccompOverridePath = "/etc/crio/seccomp.json"
+ SeccompOverridePath = etcDir + "/crio/seccomp.json"
// ConfigPath is the path to the libpod configuration file
// This file is loaded to replace the builtin default config before
@@ -54,11 +63,11 @@ const (
// If it is not present, the builtin default config is used instead
// This path can be overridden when the runtime is created by using
// NewRuntimeFromConfig() instead of NewRuntime()
- ConfigPath = "/usr/share/containers/libpod.conf"
+ ConfigPath = installPrefix + "/share/containers/libpod.conf"
// OverrideConfigPath is the path to an override for the default libpod
// configuration file. If OverrideConfigPath exists, it will be used in
// place of the configuration file pointed to by ConfigPath.
- OverrideConfigPath = "/etc/containers/libpod.conf"
+ OverrideConfigPath = etcDir + "/containers/libpod.conf"
// DefaultInfraImage to use for infra container
DefaultInfraImage = "k8s.gcr.io/pause:3.1"
@@ -300,7 +309,7 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
TmpDir: "",
MaxLogSize: -1,
NoPivotRoot: false,
- CNIConfigDir: "/etc/cni/net.d/",
+ CNIConfigDir: etcDir + "/cni/net.d/",
CNIPluginDir: []string{"/usr/libexec/cni", "/usr/lib/cni", "/usr/local/lib/cni", "/opt/cni/bin"},
InfraCommand: DefaultInfraCommand,
InfraImage: DefaultInfraImage,
diff --git a/libpod/runtime_cstorage.go b/libpod/runtime_cstorage.go
new file mode 100644
index 000000000..569f63322
--- /dev/null
+++ b/libpod/runtime_cstorage.go
@@ -0,0 +1,118 @@
+package libpod
+
+import (
+ "github.com/containers/storage"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// StorageContainer represents a container present in c/storage but not in
+// libpod.
+type StorageContainer struct {
+ ID string
+ Names []string
+ PresentInLibpod bool
+}
+
+// ListStorageContainers lists all containers visible to c/storage.
+func (r *Runtime) ListStorageContainers() ([]*StorageContainer, error) {
+ r.lock.RLock()
+ defer r.lock.RUnlock()
+
+ finalCtrs := []*StorageContainer{}
+
+ ctrs, err := r.store.Containers()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, ctr := range ctrs {
+ storageCtr := new(StorageContainer)
+ storageCtr.ID = ctr.ID
+ storageCtr.Names = ctr.Names
+
+ // Look up if container is in state
+ hasCtr, err := r.state.HasContainer(ctr.ID)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error looking up container %s in state", ctr.ID)
+ }
+
+ storageCtr.PresentInLibpod = hasCtr
+
+ finalCtrs = append(finalCtrs, storageCtr)
+ }
+
+ return finalCtrs, nil
+}
+
+// RemoveStorageContainer removes a container from c/storage.
+// The container WILL NOT be removed if it exists in libpod.
+// Accepts ID or full name of container.
+// If force is set, the container will be unmounted first to ensure removal.
+func (r *Runtime) RemoveStorageContainer(idOrName string, force bool) error {
+ r.lock.Lock()
+ defer r.lock.Unlock()
+
+ targetID, err := r.store.Lookup(idOrName)
+ if err != nil {
+ if err == storage.ErrLayerUnknown {
+ return errors.Wrapf(ErrNoSuchCtr, "no container with ID or name %q found", idOrName)
+ }
+ return errors.Wrapf(err, "error looking up container %q", idOrName)
+ }
+
+ // Lookup returns an ID but it's not guaranteed to be a container ID.
+ // So we can still error here.
+ ctr, err := r.store.Container(targetID)
+ if err != nil {
+ if err == storage.ErrContainerUnknown {
+ return errors.Wrapf(ErrNoSuchCtr, "%q does not refer to a container", idOrName)
+ }
+ return errors.Wrapf(err, "error retrieving container %q", idOrName)
+ }
+
+ // Error out if the container exists in libpod
+ exists, err := r.state.HasContainer(ctr.ID)
+ if err != nil {
+ return err
+ }
+ if exists {
+ return errors.Wrapf(ErrCtrExists, "refusing to remove %q as it exists in libpod as container %s", idOrName, ctr.ID)
+ }
+
+ if !force {
+ timesMounted, err := r.store.Mounted(ctr.ID)
+ if err != nil {
+ if err == storage.ErrContainerUnknown {
+ // Container was removed from under us.
+ // It's gone, so don't bother erroring.
+ logrus.Warnf("Storage for container %s already removed", ctr.ID)
+ return nil
+ }
+ return errors.Wrapf(err, "error looking up container %q mounts", idOrName)
+ }
+ if timesMounted > 0 {
+ return errors.Wrapf(ErrCtrStateInvalid, "container %q is mounted and cannot be removed without using force", idOrName)
+ }
+ } else {
+ if _, err := r.store.Unmount(ctr.ID, true); err != nil {
+ if err == storage.ErrContainerUnknown {
+ // Container again gone, no error
+ logrus.Warnf("Storage for container %s already removed", ctr.ID)
+ return nil
+ }
+ return errors.Wrapf(err, "error unmounting container %q", idOrName)
+ }
+ }
+
+ if err := r.store.DeleteContainer(ctr.ID); err != nil {
+ if err == storage.ErrContainerUnknown {
+ // Container again gone, no error
+ logrus.Warnf("Storage for container %s already removed", ctr.ID)
+ return nil
+ }
+ return errors.Wrapf(err, "error removing storage for container %q", idOrName)
+ }
+
+ return nil
+}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index cf1f5701d..0871b83a7 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -9,9 +9,7 @@ import (
"time"
"github.com/containers/libpod/libpod/events"
- "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/rootless"
- "github.com/containers/storage"
"github.com/containers/storage/pkg/stringid"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
@@ -614,16 +612,3 @@ func (r *Runtime) GetLatestContainer() (*Container, error) {
}
return ctrs[lastCreatedIndex], nil
}
-
-// RemoveContainersFromStorage attempt to remove containers from storage that do not exist in libpod database
-func (r *Runtime) RemoveContainersFromStorage(ctrs []string) {
- for _, i := range ctrs {
- // if the container does not exist in database, attempt to remove it from storage
- if _, err := r.LookupContainer(i); err != nil && errors.Cause(err) == image.ErrNoSuchCtr {
- r.storageService.UnmountContainerImage(i, true)
- if err := r.storageService.DeleteContainer(i); err != nil && errors.Cause(err) != storage.ErrContainerUnknown {
- logrus.Errorf("Failed to remove container %q from storage: %s", i, err)
- }
- }
- }
-}
diff --git a/logo/podman-logo-source.svg b/logo/podman-logo-source.svg
index 7964b8326..9e5cc6625 100644
--- a/logo/podman-logo-source.svg
+++ b/logo/podman-logo-source.svg
@@ -1,73 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="864.88531"
- height="221.40775"
- viewBox="0 0 228.83423 58.580801"
+ id="svg8"
version="1.1"
- id="svg194630"
- inkscape:version="0.92.2 2405546, 2018-03-11"
- sodipodi:docname="podman-source.svg">
+ viewBox="0 0 228.25899 61.226642"
+ height="231.40778"
+ width="862.71112">
<defs
- id="defs194624">
- <inkscape:path-effect
- is_visible="true"
- id="path-effect10334-3"
- effect="spiro" />
- <inkscape:path-effect
- effect="spiro"
- id="path-effect10336-6"
- is_visible="true" />
- <inkscape:path-effect
- is_visible="true"
- id="path-effect9986-7"
- effect="spiro" />
- <inkscape:path-effect
- effect="spiro"
- id="path-effect9984-5"
- is_visible="true" />
- <inkscape:path-effect
- effect="spiro"
- id="path-effect10300-3"
- is_visible="true" />
- <inkscape:path-effect
- is_visible="true"
- id="path-effect10304-5"
- effect="spiro" />
+ id="defs2">
+ <marker
+ style="overflow:visible"
+ id="marker5584"
+ refX="0"
+ refY="0"
+ orient="auto">
+ <path
+ transform="scale(0.2)"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:#4d4d4d;stroke-width:1.00000003pt;stroke-opacity:1"
+ d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 Z"
+ id="path5582" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="DiamondS"
+ refX="0"
+ refY="0"
+ orient="auto">
+ <path
+ transform="scale(0.2)"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:#4d4d4d;stroke-width:1.00000003pt;stroke-opacity:1"
+ d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 Z"
+ id="path5359" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="DotL"
+ refX="0"
+ refY="0"
+ orient="auto">
+ <path
+ transform="matrix(0.8,0,0,0.8,5.92,0.8)"
+ style="fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:#4d4d4d;stroke-width:1.00000003pt;stroke-opacity:1"
+ d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
+ id="path5335" />
+ </marker>
+ <clipPath
+ id="clipPath81511"
+ clipPathUnits="userSpaceOnUse">
+ <rect
+ y="-1.4835175"
+ x="934.65692"
+ height="12.832292"
+ width="26.19375"
+ id="rect81513"
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:#a7a9ac;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1" />
+ </clipPath>
</defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="0.35"
- inkscape:cx="71.014106"
- inkscape:cy="693.56104"
- inkscape:document-units="mm"
- inkscape:current-layer="layer1"
- showgrid="false"
- units="px"
- fit-margin-top="20"
- fit-margin-left="20"
- fit-margin-right="20"
- fit-margin-bottom="20"
- inkscape:window-width="1712"
- inkscape:window-height="899"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1" />
<metadata
- id="metadata194627">
+ id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
@@ -79,529 +73,458 @@
</rdf:RDF>
</metadata>
<g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(90.226649,-273.75722)">
+ transform="translate(-1170.4453,517.6202)"
+ id="layer1">
<g
- transform="translate(997.58958,163.05706)"
- id="g194622">
- <text
- id="text194074"
- y="150.27197"
- x="-1022.7543"
+ id="g163426" />
+ <g
+ id="g10819"
+ transform="translate(0,-285.75012)">
+ <g
+ id="text10671"
style="font-style:normal;font-weight:normal;font-size:37.59195328px;line-height:22.55517006px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#892ca0;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- xml:space="preserve"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868"><tspan
+ aria-label="podman">
+ <path
+ id="path80700"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:Montserrat;fill:#892ca0;fill-opacity:1;stroke-width:0.26458332px"
- y="150.27197"
- x="-1022.7543"
- id="tspan194072"
- sodipodi:role="line">pod<tspan
- id="tspan194070"
- style="fill:#000000">man</tspan></tspan></text>
- <g
- id="g194220"
- transform="translate(-2257.9336,340.05556)">
+ d="m 1249.8778,-209.9329 c -3.1202,0 -5.526,1.27812 -6.9921,3.60883 v -3.45846 h -4.3231 v 27.29175 h 4.3231 v -10.75129 c 1.4661,2.3307 3.8719,3.60882 7.0673,3.60882 5.7139,0 9.4731,-4.09752 9.4731,-10.07464 0,-6.0899 -3.8719,-10.22501 -9.5483,-10.22501 z m -0.9022,16.61564 c -3.5713,0 -6.0899,-2.66903 -6.0899,-6.541 0,-3.75919 2.5186,-6.46581 6.0899,-6.46581 3.5712,0 6.0899,2.74421 6.0899,6.46581 0,3.83438 -2.5187,6.541 -6.0899,6.541 z" />
<path
- id="path194076"
- d="m 1200.0567,-176.59543 -19.2981,-9.23285 -4.8204,-20.8616 13.2871,-16.78059 21.3893,-0.0641 13.3849,16.70113 -4.699,20.88969 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#892ca0;stroke-width:1.0583334;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- inkscape:connector-curvature="0" />
+ id="path80702"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:Montserrat;fill:#892ca0;fill-opacity:1;stroke-width:0.26458332px"
+ d="m 1272.4964,-209.9329 c -6.2027,0 -10.4506,4.09752 -10.4506,10.14983 0,6.01471 4.2479,10.14982 10.4506,10.14982 6.1651,0 10.413,-4.13511 10.413,-10.14982 0,-6.05231 -4.2479,-10.14983 -10.413,-10.14983 z m 0,3.7216 c 3.5712,0 6.0899,2.63144 6.0899,6.46582 0,3.87197 -2.5187,6.50341 -6.0899,6.50341 -3.6088,0 -6.1275,-2.63144 -6.1275,-6.50341 0,-3.83438 2.5187,-6.46582 6.1275,-6.46582 z" />
<path
- style="fill:none;fill-rule:evenodd;stroke:#cccccc;stroke-width:0.79375005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.95294118"
- d="m 1189.7397,-221.65207 1.5045,2.52085"
- id="path194078"
- inkscape:connector-curvature="0" />
+ id="path80704"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Montserrat;-inkscape-font-specification:Montserrat;fill:#892ca0;fill-opacity:1;stroke-width:0.26458332px"
+ d="m 1302.1564,-217.67684 v 11.35277 c -1.466,-2.33071 -3.8719,-3.64642 -7.1048,-3.64642 -5.6388,0 -9.5108,4.09752 -9.5108,10.11223 0,6.0899 3.8344,10.2626 9.5859,10.2626 3.1954,0 5.6012,-1.27812 7.0297,-3.60882 v 3.42086 h 4.3231 v -27.89322 z m -6.1275,24.47236 c -3.6464,0 -6.1274,-2.70662 -6.165,-6.50341 0.038,-3.83438 2.5562,-6.57859 6.165,-6.57859 3.6089,0 6.1275,2.70662 6.1275,6.57859 0,3.79679 -2.5186,6.50341 -6.1275,6.50341 z" />
<path
- inkscape:connector-curvature="0"
- id="path194080"
- d="m 1209.7268,-221.94151 -1.4308,2.56335"
- style="fill:none;fill-rule:evenodd;stroke:#cccccc;stroke-width:0.79375005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.95294118" />
- <g
- id="g194084"
- inkscape:transform-center-x="-17.08132"
- inkscape:transform-center-y="5.3335262"
- transform="rotate(106.71323,1247.9186,-137.82522)">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#cccccc;stroke-width:0.79375005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.95294118"
- d="m 1189.7571,-94.267724 1.4678,2.542367"
- id="path194082"
- inkscape:connector-curvature="0" />
- </g>
- <g
- transform="matrix(0.28758168,0.95775612,0.95775612,-0.28758168,925.52985,-1372.6632)"
- inkscape:transform-center-y="5.3335446"
- inkscape:transform-center-x="17.08132"
- id="g194088">
- <path
- inkscape:connector-curvature="0"
- id="path194086"
- d="m 1189.7571,-94.267724 1.4678,2.542367"
- style="fill:none;fill-rule:evenodd;stroke:#cccccc;stroke-width:0.79375005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.95294118" />
- </g>
+ id="path80706"
+ style="fill:#60605b"
+ d="m 1339.1334,-209.9329 c -3.6464,0 -6.3154,1.46608 -7.5936,4.81177 -0.9398,-3.04495 -3.3832,-4.81177 -6.9545,-4.81177 -3.3081,0 -5.8643,1.20294 -7.2552,4.02234 v -3.87197 h -4.2855 v 19.99891 h 4.2855 v -9.88668 c 0,-3.49605 2.1051,-6.12749 5.5636,-6.24026 2.9322,0 4.699,1.842 4.699,4.88695 v 11.23999 h 4.3231 v -9.88668 c 0,-3.49605 2.0675,-6.12749 5.4884,-6.24026 2.9321,0 4.7366,1.842 4.7366,4.88695 v 11.23999 h 4.323 v -12.44293 c 0,-4.77418 -2.7442,-7.70635 -7.3304,-7.70635 z" />
+ <path
+ id="path80708"
+ style="fill:#60605b"
+ d="m 1368.4916,-189.78362 -0.038,-13.11959 c -0.038,-4.39826 -2.9322,-7.02969 -8.0823,-7.02969 -3.7968,0 -5.8268,0.86461 -8.6086,2.51866 l 1.7669,3.00736 c 1.9923,-1.35332 3.9847,-2.02997 5.9019,-2.02997 3.1577,0 4.7742,1.50368 4.7742,4.02234 v 0.60147 h -6.0523 c -4.8118,0.0376 -7.556,2.36829 -7.556,6.01471 0,3.53365 2.7066,6.20267 7.0297,6.20267 2.8946,0 5.1877,-0.86461 6.6162,-2.63143 v 2.44347 z m -9.9619,-3.2329 c -2.4059,0 -3.872,-1.16535 -3.872,-2.96977 0,-1.91719 1.3157,-2.66903 4.1351,-2.66903 h 5.4133 v 1.84201 c -0.2256,2.18033 -2.5939,3.79679 -5.6764,3.79679 z" />
+ <path
+ id="path80710"
+ style="fill:#60605b"
+ d="m 1385.9695,-209.9329 c -3.3833,0 -5.9396,1.20294 -7.3681,3.98474 v -3.83437 h -4.323 v 19.99891 h 4.323 v -10.63852 c 0.3008,-3.12013 2.3683,-5.41324 5.6764,-5.45083 3.0074,0 4.8118,1.842 4.8118,4.84936 v 11.23999 h 4.3231 v -12.44293 c 0,-4.77418 -2.7818,-7.70635 -7.4432,-7.70635 z" />
+ </g>
+ </g>
+ <g
+ id="g10987"
+ transform="translate(-4.0076941e-7,-285.75012)">
+ <g
+ id="g10985"
+ transform="translate(238.41304,-199.74894)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 963.98321,-1.2653795 h 12.72207"
+ id="path10821" />
<path
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1217.3928,-198.86664 c -1.6026,0.3763 -2.7924,0.4881 -4.4867,0.49355"
- id="path194090"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
+ id="path10823"
+ d="m 966.09989,1.3804536 h 12.72207"
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
- style="stroke-width:1.07322586"
- transform="matrix(0.93201038,0,0,0.93153044,84.668387,39.521136)"
- id="g194148">
+ style="stroke-width:0.86916679"
+ transform="matrix(1.1500458,0,0,1.1510087,-143.9252,0.43908228)"
+ id="g10875">
<path
- style="opacity:1;fill:#d7d8da;fill-opacity:1;stroke:#000000;stroke-width:0.85187292;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1196.4002,-277.28841 c -6.3145,0 -11.4334,5.11824 -11.4334,11.4319 0,5.60953 0.1555,10.87478 -3.8973,11.52796 2.2201,1.74955 31.1822,1.47773 31.1822,0.0657 -3.9446,-0.40986 -3.9311,-5.05055 -4.1745,-11.47895 -0.2435,-6.42839 -5.3624,-11.54663 -11.677,-11.54663 z"
- id="path194092"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="sccccs" />
+ id="path10825"
+ d="m 973.10356,3.3983398 c -2.30839,-3.74257021 -1.79145,-7.3525044 -2.88299,-12.510239 -0.59897,-3.1855248 -2.62142,-5.8149598 -5.25403,-6.7776908 -2.17189,-0.757647 -6.68263,-0.759955 -8.59472,0 -2.63261,0.962731 -4.65498,3.592166 -5.25395,6.7776908 -1.09155,5.1577346 -0.57458,8.76766879 -2.88297,12.510239"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.68990111;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <ellipse
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:none;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
+ id="ellipse10827"
+ cx="966.56354"
+ cy="-4.1070371"
+ rx="1.1158856"
+ ry="1.1746163" />
+ <ellipse
+ ry="1.1746163"
+ rx="1.1158856"
+ cy="-4.1070371"
+ cx="955.28723"
+ id="ellipse10829"
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:none;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1" />
+ <g
+ id="g10839"
+ style="stroke:#a7a9ac;stroke-width:0.51800275;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.88789899,0,0,0.88789899,108.02196,0.55783395)">
+ <path
+ id="path10831"
+ d="m 956.41893,-5.9814347 -4.67056,1.2514712"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10833"
+ d="m 956.9481,-5.2538306 -4.6966,2.711577"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10835"
+ d="m 957.34497,-4.3939348 -4.7625,4.76249998"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10837"
+ d="m 957.5434,-3.2694556 -2.434,4.21584432"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ transform="matrix(-0.88789899,0,0,0.88789899,1814.1581,0.55783389)"
+ style="stroke:#a7a9ac;stroke-width:0.51800275;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g10849">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 956.41893,-5.9814347 -4.67056,1.2514712"
+ id="path10841" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 956.9481,-5.2538306 -4.6966,2.711577"
+ id="path10843" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 957.34497,-4.3939348 -4.7625,4.76249998"
+ id="path10845" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.51800275;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 957.5434,-3.2694556 -2.434,4.21584432"
+ id="path10847" />
+ </g>
<ellipse
- ry="1.2784375"
- rx="1.2185711"
- cy="-221.69182"
- cx="1196.4897"
- id="ellipse194094"
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.85187298;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- transform="matrix(0.99938194,-0.03515294,0.03512104,0.99938307,0,0)" />
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#60605b;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
+ id="ellipse10851"
+ cx="961.04285"
+ cy="-4.9292688"
+ rx="3.5825801"
+ ry="3.4063873" />
<ellipse
- ry="3.3919933"
- rx="3.8366725"
- cy="-224.76184"
- cx="1205.7982"
- id="ellipse194096"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#60605b;stroke-width:0.85187823;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- transform="matrix(0.99946418,-0.03273147,0.0377188,0.99928839,0,0)" />
+ transform="scale(-1,1)"
+ style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="ellipse10853"
+ cx="-966.52734"
+ cy="-7.8406329"
+ rx="1.7252614"
+ ry="1.7690334" />
<path
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- sodipodi:nodetypes="csc"
- inkscape:original-d="m 1203.9748,-270.3367 c -0.4929,-0.18136 -0.8779,-0.48319 -1.375,-0.66415 -0.4972,-0.18083 -0.9228,0.4235 -1.3258,0.57498"
- inkscape:path-effect="#path-effect10334-3"
- inkscape:connector-curvature="0"
- id="path194098"
- d="m 1203.9748,-270.3367 c -0.3302,-0.40944 -0.849,-0.66007 -1.375,-0.66415 -0.4959,-0.004 -0.9897,0.21029 -1.3258,0.57498"
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.56791532;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.68990105;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 968.07427,-11.544209 c -0.34474,-0.448317 -0.89334,-0.733231 -1.45836,-0.757402 -0.53344,-0.02282 -1.07281,0.185834 -1.45201,0.561706"
+ id="path10855" />
<g
- transform="matrix(0.69366503,-0.00293008,0.00289825,0.69135666,529.16872,-257.19815)"
- style="stroke-width:0.82007539;stroke-miterlimit:4;stroke-dasharray:none"
- id="g194106">
+ id="g10863"
+ style="stroke-width:0.77700406;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.88789899,0,0,0.88789899,106.61242,0.08798743)">
<g
+ id="g10861"
transform="translate(0,-0.52916667)"
- id="g194104"
- style="stroke-width:0.82007539;stroke-miterlimit:4;stroke-dasharray:none">
+ style="stroke-width:0.77700406">
<path
- sodipodi:nodetypes="cccc"
- inkscape:connector-curvature="0"
- id="path194100"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.77700406;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 962.30591,-5.7829972 0.0993,1.9843749 c 0,0 1.58751,1.4221355 2.51355,-0.033073 0,0 -0.0993,-0.8268214 -0.16541,-1.0914047"
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.82007539;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ id="path10857" />
<path
- style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.82007539;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path10859"
d="m 962.28751,-5.7829972 -0.0993,1.9843749 c 0,0 -1.58751,1.4221355 -2.51355,-0.033073 0,0 0.0993,-0.8268214 0.16541,-1.0914047"
- id="path194102"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.77700406;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
<path
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- sodipodi:nodetypes="cszsccc"
- inkscape:connector-curvature="0"
- d="m 1197.9362,-265.07184 c -0.1012,-0.25799 -0.1029,-0.77483 -0.4026,-0.77357 -0.2995,0.002 -0.5774,-0.1914 -0.872,-0.19011 -0.2946,0.002 -0.571,0.19636 -0.8707,0.19765 -0.2993,0.002 -0.2975,0.51817 -0.396,0.77704 -0.1011,0.25897 1.275,1.09288 1.275,1.09288 0,0 1.3673,-0.84575 1.2663,-1.10389 z"
- style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:0.56791532;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path194108" />
+ id="path10865"
+ style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 962.57174,-5.5436767 c -0.1202,-0.3110186 -0.1202,-0.9330691 -0.48062,-0.9330691 -0.36047,0 -0.69372,-0.2332673 -1.04826,-0.2332673 -0.35456,0 -0.68781,0.2332673 -1.04828,0.2332673 -0.36046,0 -0.36046,0.6220505 -0.48061,0.9330691 -0.1202,0.3110253 1.52889,1.3218472 1.52889,1.3218472 0,0 1.64903,-1.0108219 1.52888,-1.3218472 z" />
+ <ellipse
+ ry="1.7690334"
+ rx="1.7252614"
+ cy="-7.8406329"
+ cx="955.36047"
+ id="ellipse10867"
+ style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <ellipse
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="ellipse10869"
+ cx="954.78467"
+ cy="-8.3384542"
+ rx="0.8483994"
+ ry="0.88143349" />
+ <path
+ id="path10871"
+ d="m 953.81353,-11.544209 c 0.34474,-0.448315 0.89333,-0.73323 1.45835,-0.757402 0.53344,-0.02282 1.07281,0.185833 1.45201,0.561706"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.68990105;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <ellipse
+ ry="0.88143349"
+ rx="0.8483994"
+ cy="-8.3384542"
+ cx="967.05286"
+ id="ellipse10873"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.68990111;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ </g>
+ <path
+ id="path10877"
+ d="m 948.21183,4.2931494 h 32.92765"
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ style="stroke-width:1.20411575"
+ transform="matrix(0.83048493,0,0,0.83048493,164.55035,-1.4237955)"
+ clip-path="url(#clipPath81511)"
+ id="g10929">
<path
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.56791532;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 1188.9919,-270.28459 c 0.3005,-0.43161 0.8005,-0.71808 1.3248,-0.75912 0.4944,-0.0387 1.002,0.14023 1.3629,0.48043"
- id="path194110"
- inkscape:connector-curvature="0"
- inkscape:path-effect="#path-effect10336-6"
- inkscape:original-d="m 1188.9919,-270.28459 c 0.479,-0.21554 0.8417,-0.54368 1.3248,-0.75912 0.4832,-0.21531 0.9505,0.35763 1.3629,0.48043"
- sodipodi:nodetypes="csc" />
+ id="path10879"
+ d="m 958.31594,13.737399 c -0.26199,-1.782196 -0.38924,-3.720848 -0.8727,-6.0017375 -0.53058,-2.8174518 -2.32212,-5.1430676 -4.65415,-5.9945597 -1.92393,-0.6701043 -5.91966,-0.6721461 -7.61343,0 -2.33204,0.8514921 -4.1235,3.1771079 -4.65409,5.9945597 -0.48346,2.2808895 -0.61071,4.2195415 -0.87269,6.0017375"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.95576686;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <ellipse
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:none;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
+ id="ellipse10881"
+ cx="954.20367"
+ cy="12.16224"
+ rx="0.98848081"
+ ry="1.0388949" />
+ <ellipse
+ ry="1.0388949"
+ rx="0.98848081"
+ cy="12.16224"
+ cx="944.21478"
+ id="ellipse10883"
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:none;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1" />
<g
- style="stroke-width:1.07322586"
- id="g194116"
- transform="translate(-0.1322934,-148.99351)">
- <ellipse
- transform="matrix(-0.99938215,0.03514721,0.03512674,0.99938287,0,0)"
- style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.8518728;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse194112"
- cx="-1206.3459"
- cy="-75.635956"
- rx="1.8695227"
- ry="1.9430941"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <ellipse
- transform="matrix(0.99938215,-0.03514721,0.03512674,0.99938287,0,0)"
- ry="0.96816051"
- rx="0.91933995"
- cy="-76.182663"
- cx="1206.9153"
- id="ellipse194114"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.8518728;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
+ id="g10893"
+ style="stroke:#a7a9ac;stroke-width:0.81074655;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.7865243,0,0,0.7853064,193.68501,16.288101)">
+ <path
+ id="path10885"
+ d="m 956.41893,-5.9814347 -4.67056,1.2514712"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10887"
+ d="m 956.9481,-5.2538306 -4.6966,2.711577"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10889"
+ d="m 957.34497,-4.3939348 -4.7625,4.76249998"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10891"
+ d="m 957.5434,-3.2694556 -2.434,4.21584432"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
- transform="matrix(-0.86763199,-0.04368486,-0.04400126,0.8648962,2029.5877,-215.68906)"
- style="stroke:#60605b;stroke-width:0.65475416;stroke-miterlimit:4;stroke-dasharray:none"
- id="g194126">
- <g
- id="g194124"
- style="stroke-width:0.65475416">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.65475416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 956.32834,-6.2874931 c -2.17461,0.00852 -3.90258,0.727992 -5.25392,1.62519"
- id="path194118"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.65475416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 957.00529,-5.3889116 c -2.45021,0.3102076 -3.99116,1.6666651 -5.21618,2.999397"
- id="path194120"
- inkscape:connector-curvature="0" />
- <path
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.65475416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 957.14608,-4.4502461 c -2.0377,0.8062397 -3.03766,2.4684328 -3.7999,4.05763317"
- id="path194122"
- inkscape:connector-curvature="0" />
- </g>
+ transform="matrix(-0.7865243,0,0,0.7853064,1705.0252,16.288101)"
+ style="stroke:#a7a9ac;stroke-width:0.81074655;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g10903">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 956.41893,-5.9814347 -4.67056,1.2514712"
+ id="path10895" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 956.9481,-5.2538306 -4.6966,2.711577"
+ id="path10897" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 957.34497,-4.3939348 -4.7625,4.76249998"
+ id="path10899" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.81074655;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 957.5434,-3.2694556 -2.434,4.21584432"
+ id="path10901" />
</g>
+ <ellipse
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#60605b;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
+ id="ellipse10905"
+ cx="949.31329"
+ cy="11.435012"
+ rx="3.1735437"
+ ry="3.0127952" />
+ <ellipse
+ transform="scale(-1,1)"
+ style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="ellipse10907"
+ cx="-954.17163"
+ cy="8.8600426"
+ rx="1.528282"
+ ry="1.5646298" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.9557668;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 955.54199,5.5843938 c -0.30575,-0.3965787 -0.79155,-0.6484892 -1.29185,-0.6698876 -0.4724,-0.020205 -0.95006,0.1642901 -1.28623,0.4968037"
+ id="path10909" />
<g
- id="g194136"
- style="stroke:#60605b;stroke-width:0.65475416;stroke-miterlimit:4;stroke-dasharray:none"
- transform="matrix(0.86340059,-0.09610492,0.09623303,0.86064955,368.1354,-165.50024)">
+ id="g10917"
+ style="stroke-width:1.21611977;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.7865243,0,0,0.7853064,192.4364,15.872544)">
<g
- style="stroke-width:0.65475416"
- id="g194134">
+ style="stroke-width:1.21611977"
+ id="g10915"
+ transform="translate(0,-0.52916667)">
<path
- inkscape:connector-curvature="0"
- id="path194128"
- d="m 956.32834,-6.2874931 c -2.17461,0.00852 -3.90258,0.727992 -5.25392,1.62519"
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.65475416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- inkscape:connector-curvature="0"
- id="path194130"
- d="m 957.00529,-5.3889116 c -2.45021,0.3102076 -3.99116,1.6666651 -5.21618,2.999397"
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.65475416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.21611977;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 962.30591,-5.7829972 0.0993,1.9843749 c 0,0 1.58751,1.4221355 2.51355,-0.033073 0,0 -0.0993,-0.8268214 -0.16541,-1.0914047"
+ id="path10911" />
<path
- inkscape:connector-curvature="0"
- id="path194132"
- d="m 956.99206,-4.4197862 c -2.0377,0.8062397 -3.03766,2.4684328 -3.7999,4.05763312"
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.65475416;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ id="path10913"
+ d="m 962.28751,-5.7829972 -0.0993,1.9843749 c 0,0 -1.58751,1.4221355 -2.51355,-0.033073 0,0 0.0993,-0.8268214 0.16541,-1.0914047"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.21611977;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
- <g
- style="stroke-width:1.07322586"
- id="g194142"
- transform="translate(-0.1322934,-149.16808)">
- <ellipse
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- ry="1.9430944"
- rx="1.8695223"
- cy="-87.545464"
- cx="1193.2991"
- id="ellipse194138"
- style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.8518728;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0.99967764,-0.0253894,0.02538424,0.99967777,0,0)" />
- <ellipse
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.8518728;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse194140"
- cx="-1192.7297"
- cy="-88.092163"
- rx="0.91933978"
- ry="0.96816063"
- transform="matrix(-0.99967764,0.0253894,0.02538424,0.99967777,0,0)" />
- </g>
+ <path
+ id="path10919"
+ style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 950.66771,10.891591 c -0.10648,-0.275082 -0.10648,-0.825257 -0.42575,-0.825257 -0.31931,0 -0.61451,-0.2063147 -0.92858,-0.2063147 -0.31407,0 -0.60928,0.2063147 -0.92858,0.2063147 -0.31932,0 -0.31932,0.550175 -0.42575,0.825257 -0.10647,0.275088 1.35433,1.169114 1.35433,1.169114 0,0 1.46076,-0.894026 1.35433,-1.169114 z" />
<ellipse
- transform="matrix(0.99938194,-0.03515294,0.03512104,0.99938307,0,0)"
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.85187298;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- id="ellipse194144"
- cx="1214.1729"
- cy="-221.06982"
- rx="1.2185711"
- ry="1.2784375" />
+ ry="1.5646298"
+ rx="1.528282"
+ cy="8.8600426"
+ cx="944.27972"
+ id="ellipse10921"
+ style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <ellipse
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="ellipse10923"
+ cx="943.76965"
+ cy="8.4197426"
+ rx="0.75153452"
+ ry="0.77958798" />
<path
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.85187304;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1196.6606,-258.19566 a 8.2351559,7.2429689 0 0 0 -7.6956,4.68912 c 4.7591,0.2089 10.6723,0.19768 15.4021,0.0114 a 8.2351559,7.2429689 0 0 0 -7.7065,-4.7005 z"
- id="path194146"
- inkscape:connector-curvature="0" />
+ id="path10925"
+ d="m 942.90945,5.5843938 c 0.30575,-0.3965787 0.79155,-0.6484892 1.29185,-0.6698876 0.4724,-0.020205 0.95006,0.1642901 1.28623,0.4968037"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.9557668;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <ellipse
+ ry="0.77958798"
+ rx="0.75153452"
+ cy="8.4197426"
+ cx="954.63715"
+ id="ellipse10927"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.95576686;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<path
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374999;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1219.0623,-197.2163 c -3.5719,1.43037 -11.1149,1.14699 -18.2221,1.17499 -7.1072,0.028 -15.5965,-0.27284 -17.0071,-1.69572"
- id="path194150"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="csc" />
- <path
- style="opacity:1;fill:#d7d8da;fill-opacity:1;stroke:#000000;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1198.4754,-191.15273 c 0,1.00704 0,1.99863 -0.017,2.94659 6.3077,1.15754 12.6043,1.18012 18.5208,0.0181 -0.042,-0.89578 -0.071,-1.85458 -0.1064,-2.86597 -0.1939,-5.53538 -4.2687,-9.41337 -9.2955,-9.41338 -5.0269,-1e-5 -9.1019,3.87807 -9.1019,9.31466 z"
- id="path194152"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="sccczs" />
- <ellipse
- ry="1.1909043"
- rx="1.1357201"
- cy="-148.3954"
- cx="1206.6315"
- id="ellipse194154"
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- transform="matrix(0.99938258,-0.03513486,0.03513911,0.99938243,0,0)" />
+ style="opacity:1;fill:none;fill-opacity:1;stroke:#892ca0;stroke-width:1.0583334;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 961.97165,23.28467 -19.29817,-9.23285 -4.82036,-20.8616002 13.2871,-16.7806158 21.38926,-0.06408 13.38485,16.7011458 -4.69887,20.8897002 z"
+ id="path10931" />
<path
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- sodipodi:nodetypes="csc"
- inkscape:original-d="m 1213.5138,-196.08059 c -0.3776,-0.13889 -0.6726,-0.37001 -1.0534,-0.5086 -0.3809,-0.13847 -0.7069,0.32432 -1.0158,0.4403"
- inkscape:path-effect="#path-effect9986-7"
- inkscape:connector-curvature="0"
- id="path194156"
- d="m 1213.5138,-196.08059 c -0.253,-0.31355 -0.6505,-0.50546 -1.0534,-0.5086 -0.3799,-0.003 -0.7582,0.161 -1.0158,0.4403"
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 943.44933,8.5264827 h 19.83144"
+ id="path10933" />
<path
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 1202.0344,-196.04037 c 0.2304,-0.33054 0.6134,-0.54988 1.0151,-0.5813 0.3788,-0.0296 0.7676,0.10738 1.0442,0.36791"
- id="path194158"
- inkscape:connector-curvature="0"
- inkscape:path-effect="#path-effect9984-5"
- inkscape:original-d="m 1202.0344,-196.04037 c 0.3671,-0.16505 0.645,-0.41631 1.0151,-0.5813 0.3701,-0.1649 0.7281,0.27386 1.0442,0.36791"
- sodipodi:nodetypes="csc" />
- <ellipse
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- ry="1.4879755"
- rx="1.432372"
- cy="-150.7608"
- cx="-1218.6735"
- id="ellipse194160"
- style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.79374987;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(-0.99938278,0.03512913,0.03514482,0.99938223,0,0)" />
- <ellipse
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79374987;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse194162"
- cx="1219.1096"
- cy="-151.17946"
- rx="0.70437056"
- ry="0.74139434"
- transform="matrix(0.99938278,-0.03512913,0.03514482,0.99938223,0,0)" />
- <path
- id="path194164"
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1218.7033,-188.67623 -1.6617,0.47913 c -5.9787,1.17108 -12.2753,1.1485 -18.583,-0.009 l -2.5256,-0.47009"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
+ id="path10935"
+ d="m 952.87074,12.492952 h 27.50208"
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<g
- transform="matrix(-0.54020821,-0.0266189,-0.02739623,0.52701539,1727.0536,-162.01736)"
- style="stroke:#60605b;stroke-width:0.99047768;stroke-miterlimit:4;stroke-dasharray:none"
- id="g194168">
+ transform="translate(0.78045403,0.88370984)"
+ id="g10979">
<path
- inkscape:connector-curvature="0"
- d="m 957.14608,-4.4502461 c -2.0377,0.8062397 -3.03766,2.4684328 -3.7999,4.05763317 m 3.65911,-4.99629867 c -2.45021,0.3102076 -3.99116,1.6666651 -5.21618,2.999397 m 4.53923,-3.8979785 c -2.17461,0.00852 -3.90258,0.727992 -5.25392,1.62519"
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.99047768;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path194166" />
- </g>
- <g
- transform="matrix(0.53757364,-0.05856052,0.05991696,0.52442773,691.53583,-131.42451)"
- id="g194176"
- style="stroke:#60605b;stroke-width:0.99047768;stroke-miterlimit:4;stroke-dasharray:none">
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 977.46866,11.110796 c -0.23262,-1.5824091 -0.34561,-3.3037374 -0.77487,-5.3289381 -0.4711,-2.5016132 -2.06181,-4.566525 -4.13242,-5.32256411 -1.70825,-0.59498494 -5.25606,-0.59679785 -6.75995,0 -2.07062,0.75603911 -3.66125,2.82095091 -4.13236,5.32256411 -0.42927,2.0252007 -0.54225,3.746529 -0.77486,5.3289381"
+ id="path10937" />
+ <ellipse
+ ry="0.92243373"
+ rx="0.87767112"
+ cy="9.7122078"
+ cx="973.81744"
+ id="ellipse10939"
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1" />
+ <ellipse
+ style="opacity:1;fill:#e7e8e9;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
+ id="ellipse10941"
+ cx="964.9483"
+ cy="9.7122078"
+ rx="0.87767112"
+ ry="0.92243373" />
+ <g
+ transform="matrix(0.69835413,0,0,0.69727276,299.02348,11.966021)"
+ style="stroke:#a7a9ac;stroke-width:0.7583214;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g10947">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.7583214;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 955.74614,-3.9599306 -4.67056,1.2514712"
+ id="path10943" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.7583214;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 956.27531,-3.2323265 -4.6966,2.71157695"
+ id="path10945" />
+ </g>
+ <g
+ id="g10953"
+ style="stroke:#a7a9ac;stroke-width:0.7583214;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(-0.69835413,0,0,0.69727276,1640.4712,13.375562)">
+ <path
+ id="path10949"
+ d="m 956.41893,-5.9814347 -4.67056,1.2514712"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.7583214;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path10951"
+ d="m 956.9481,-5.2538306 -4.6966,2.711577"
+ style="fill:none;fill-rule:evenodd;stroke:#a7a9ac;stroke-width:0.7583214;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <ellipse
+ ry="2.6750579"
+ rx="2.8177862"
+ cy="9.0665035"
+ cx="969.47528"
+ id="ellipse10955"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#60605b;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1" />
+ <ellipse
+ ry="1.3892332"
+ rx="1.3569601"
+ cy="6.7801905"
+ cx="-973.789"
+ id="ellipse10957"
+ style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ transform="scale(-1,1)" />
<path
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.99047768;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 956.32834,-6.2874931 c -2.17461,0.00852 -3.90258,0.727992 -5.25392,1.62519"
- id="path194170"
- inkscape:connector-curvature="0" />
+ id="path10959"
+ d="m 975.00567,3.8717489 c -0.27147,-0.3521218 -0.70281,-0.575793 -1.14703,-0.5947926 -0.41945,-0.01794 -0.84356,0.1458731 -1.14204,0.4411116"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.79374993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <g
+ transform="matrix(0.69835413,0,0,0.69727276,297.44499,13.006589)"
+ style="stroke-width:1.13748205;stroke-miterlimit:4;stroke-dasharray:none"
+ id="g10967">
+ <g
+ transform="translate(0,-0.52916667)"
+ id="g10965"
+ style="stroke-width:1.13748205">
+ <path
+ id="path10961"
+ d="m 962.30591,-5.7829972 0.0993,1.9843749 c 0,0 1.58751,1.4221355 2.51355,-0.033073 0,0 -0.0993,-0.8268214 -0.16541,-1.0914047"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.13748205;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.13748205;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 962.28751,-5.7829972 -0.0993,1.9843749 c 0,0 -1.58751,1.4221355 -2.51355,-0.033073 0,0 0.0993,-0.8268214 0.16541,-1.0914047"
+ id="path10963" />
+ </g>
+ </g>
<path
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.99047768;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 957.00529,-5.3889116 c -2.45021,0.3102076 -3.99116,1.6666651 -5.21618,2.999397"
- id="path194172"
- inkscape:connector-curvature="0" />
+ d="m 970.6778,8.5840058 c -0.0945,-0.2442451 -0.0945,-0.7327449 -0.37802,-0.7327449 -0.28351,0 -0.54562,-0.1831865 -0.82448,-0.1831865 -0.27887,0 -0.54098,0.1831865 -0.82449,0.1831865 -0.28352,0 -0.28352,0.4884998 -0.37802,0.7327449 -0.0945,0.2442506 1.20251,1.0380563 1.20251,1.0380563 0,0 1.297,-0.7938057 1.2025,-1.0380563 z"
+ style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path10969" />
+ <ellipse
+ style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="ellipse10971"
+ cx="965.00598"
+ cy="6.7801905"
+ rx="1.3569601"
+ ry="1.3892332" />
+ <ellipse
+ ry="0.69219536"
+ rx="0.66728675"
+ cy="6.3892479"
+ cx="964.5531"
+ id="ellipse10973"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
- style="fill:none;fill-rule:evenodd;stroke:#60605b;stroke-width:0.99047768;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 956.99206,-4.4197862 c -2.0377,0.8062397 -3.03766,2.4684328 -3.7999,4.05763312"
- id="path194174"
- inkscape:connector-curvature="0" />
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.79374993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 963.78925,3.8717489 c 0.27148,-0.3521208 0.70281,-0.5757916 1.14703,-0.5947926 0.41945,-0.017942 0.84357,0.1458717 1.14205,0.4411116"
+ id="path10975" />
+ <ellipse
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="ellipse10977"
+ cx="974.20233"
+ cy="6.3892479"
+ rx="0.66728675"
+ ry="0.69219536" />
</g>
- <ellipse
- transform="matrix(0.99967797,-0.02537634,0.02539731,0.99967744,0,0)"
- style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.79374987;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse194178"
- cx="1207.7616"
- cy="-162.88258"
- rx="1.4323721"
- ry="1.4879751"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <ellipse
- transform="matrix(-0.99967797,0.02537634,0.02539731,0.99967744,0,0)"
- ry="0.74139422"
- rx="0.70437062"
- cy="-163.30124"
- cx="-1207.3254"
- id="ellipse194180"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79374987;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <ellipse
- transform="matrix(0.99938258,-0.03513486,0.03513911,0.99938243,0,0)"
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- id="ellipse194182"
- cx="1221.1841"
- cy="-147.88377"
- rx="1.1357201"
- ry="1.1909043" />
- <ellipse
- ry="2.7544067"
- rx="2.9848497"
- cy="-149.08769"
- cx="1214.015"
- id="ellipse194184"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#60605b;stroke-width:0.79375076;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- transform="matrix(0.99941617,-0.03416617,0.0361353,0.99934691,0,0)" />
- <path
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- sodipodi:nodetypes="cscsccc"
- inkscape:connector-curvature="0"
- d="m 1209.0947,-191.32793 c -0.094,-0.24033 -0.1023,-0.66114 -0.3752,-0.72061 l -0.8127,-0.17709 -0.8115,0.18412 c -0.2721,0.0618 -0.2773,0.48269 -0.3691,0.72384 -0.094,0.24123 1.1883,1.01805 1.1883,1.01805 0,0 1.2743,-0.78785 1.1802,-1.02831 z"
- style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path194186" />
- <path
- style="opacity:1;fill:#ff8080;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1207.7699,-190.02101 c -0.07,0.11114 -0.1741,0.2003 -0.2946,0.25322 -0.1288,0.0562 -0.2743,0.0709 -0.4134,0.0495 -0.098,-0.0151 -0.1933,-0.0497 -0.2806,-0.0977 0,0.005 0,0.01 0,0.015 0,0.62103 0.5035,1.12448 1.1245,1.12448 0.621,0 1.1244,-0.50345 1.1244,-1.12448 10e-5,-0.005 10e-5,-0.008 0,-0.0129 -0.087,0.047 -0.1801,0.0808 -0.2774,0.0956 -0.1391,0.0212 -0.2847,0.007 -0.4135,-0.0495 -0.1204,-0.0529 -0.2242,-0.14208 -0.2945,-0.25322 -0.1839,-0.45256 -0.15,-0.33357 -0.2749,0 z"
- id="path194188"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccscccccc" />
- <path
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0"
- d="m 1208.9056,-185.61743 c -7.1727,0.14599 -10.811,-0.41013 -16.8091,-1.86816"
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="path194190" />
- <path
- id="path194192"
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374999;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1210.5635,-183.66873 c -3.2099,0.35365 -5.8695,0.42038 -8.7157,0.008"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
- <path
- sodipodi:nodetypes="sccczs"
- inkscape:connector-curvature="0"
- id="path194194"
- d="m 1182.9959,-193.76305 c 0,0.81341 0,1.61437 -0.013,2.38006 4.5482,0.93499 9.0885,0.95323 13.3546,0.0146 -0.029,-0.72355 -0.052,-1.49801 -0.077,-2.31495 -0.1398,-4.47113 -3.2525,-6.51948 -6.6971,-6.51948 -3.4446,0 -6.5675,2.04843 -6.5675,6.43977 z"
- style="opacity:1;fill:#d7d8da;fill-opacity:1;stroke:#000000;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <path
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 1193.6324,-197.30544 c -0.184,-0.21557 -0.4648,-0.34527 -0.7482,-0.34568 -0.2696,-3.9e-4 -0.5374,0.11563 -0.7215,0.31258"
- id="path194196"
- inkscape:connector-curvature="0"
- inkscape:path-effect="#path-effect10300-3"
- inkscape:original-d="m 1193.6324,-197.30544 c -0.2681,-0.0673 -0.4777,-0.27852 -0.7482,-0.34568 -0.2705,-0.0671 -0.5021,0.25638 -0.7215,0.31258"
- sodipodi:nodetypes="csc"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <path
- sodipodi:nodetypes="csc"
- inkscape:original-d="m 1185.4425,-197.28587 c 0.2607,-0.08 0.4581,-0.30096 0.721,-0.38091 0.2629,-0.0799 0.5172,0.23193 0.7416,0.27751"
- inkscape:path-effect="#path-effect10304-5"
- inkscape:connector-curvature="0"
- id="path194198"
- d="m 1185.4425,-197.28587 c 0.171,-0.22212 0.4411,-0.36483 0.721,-0.38091 0.2712,-0.0156 0.5472,0.0877 0.7416,0.27751"
- style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <ellipse
- transform="matrix(-0.99939588,0.03475453,0.03552362,0.99936884,0,0)"
- style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse194200"
- cx="-1199.4635"
- cy="-153.15971"
- rx="1.2560792"
- ry="1.2909421"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <ellipse
- transform="matrix(0.99939588,-0.03475453,0.03552362,0.99936884,0,0)"
- ry="0.64322108"
- rx="0.6176784"
- cy="-153.52293"
- cx="1199.8459"
- id="ellipse194202"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
- <ellipse
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- ry="1.2909336"
- rx="1.2560872"
- cy="-164.91208"
- cx="1190.6571"
- id="ellipse194204"
- style="fill:#000000;fill-opacity:1;stroke:#892ca0;stroke-width:0.79374993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0.99968481,-0.02510557,0.02567121,0.99967044,0,0)" />
- <path
- sodipodi:nodetypes="cccccc"
- inkscape:connector-curvature="0"
- id="path194206"
- transform="matrix(0.26458334,0,0,0.26458334,619.60435,-79.242757)"
- d="m 2154.0312,-434.57031 c -4.4701,0.15199 -7.9731,3.60605 -7.8242,7.71484 0.052,1.39375 0.5293,4.24714 1.377,5.40104 4.4988,0.24291 8.9701,0.26971 13.3222,0.0957 1.0211,-1.32719 1.5437,-4.42574 1.4883,-6.04752 -0.1491,-4.10861 -3.8934,-7.31601 -8.3633,-7.16406 z"
- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#60605b;stroke-width:2.99999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1" />
- <ellipse
- inkscape:export-ydpi="89.962868"
- inkscape:export-xdpi="89.962868"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79374993;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="ellipse194208"
- cx="-1190.2747"
- cy="-165.2753"
- rx="0.61768228"
- ry="0.64321685"
- transform="matrix(-0.99968481,0.02510557,0.02567121,0.99967044,0,0)" />
- <path
- id="path194210"
- style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 1190.4633,-192.29709 c -0.069,-0.17514 -0.076,-0.4818 -0.2773,-0.52514 l -0.6006,-0.12906 -0.5998,0.13418 c -0.2011,0.045 -0.2049,0.35176 -0.2728,0.52749 -0.069,0.1758 0.8783,0.7419 0.8783,0.7419 0,0 0.9418,-0.57414 0.8722,-0.74937 z"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cscsccc"
- inkscape:export-xdpi="89.962868"
- inkscape:export-ydpi="89.962868" />
<path
- sodipodi:nodetypes="cc"
- inkscape:connector-curvature="0"
- id="path194212"
- d="m 1181.9907,-189.53092 c 2.7637,0.72901 4.8155,0.94562 7.7375,0.95618"
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <ellipse
- transform="matrix(0.99938258,-0.03513486,0.03513911,0.99938243,0,0)"
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- id="ellipse194214"
- cx="1199.9076"
- cy="-149.77843"
- rx="0.93498713"
- ry="0.98041773" />
- <ellipse
- ry="0.98041773"
- rx="0.93498713"
- cy="-150.07587"
- cx="1191.4463"
- id="ellipse194216"
- style="opacity:1;fill:#f1f1f1;fill-opacity:1;stroke:none;stroke-width:0.79374999;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.99999952;stroke-opacity:1"
- transform="matrix(0.99938258,-0.03513486,0.03513911,0.99938243,0,0)" />
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 950.75405,15.138787 h 12.72207"
+ id="path10981" />
<path
- style="opacity:1;fill:none;fill-opacity:1;stroke:#3c6eb4;stroke-width:0.79374993;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1181.2324,-191.77986 c 5.5275,1.45801 11.8484,1.34886 16.4006,0.10007"
- id="path194218"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cc" />
+ id="path10983"
+ d="m 958.16237,17.784622 h 10.477"
+ style="fill:none;fill-rule:evenodd;stroke:#3c6eb4;stroke-width:1.05833328;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</g>
diff --git a/logo/podman-logo.png b/logo/podman-logo.png
index b0dcc75d2..70c8b1191 100644
--- a/logo/podman-logo.png
+++ b/logo/podman-logo.png
Binary files differ
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 29297fbd5..40b1e6b43 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -190,12 +190,18 @@ func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmVa
}
logrus.Debugf("Setting maximum rm workers to %d", maxWorkers)
+ if cli.Storage {
+ for _, ctr := range cli.InputArgs {
+ if err := r.RemoveStorageContainer(ctr, cli.Force); err != nil {
+ failures[ctr] = err
+ }
+ ok = append(ok, ctr)
+ }
+ return ok, failures, nil
+ }
+
ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime)
if err != nil {
- // Force may be used to remove containers no longer found in the database
- if cli.Force && len(cli.InputArgs) > 0 && errors.Cause(err) == libpod.ErrNoSuchCtr {
- r.RemoveContainersFromStorage(cli.InputArgs)
- }
return ok, failures, err
}
diff --git a/pkg/apparmor/apparmor_linux.go b/pkg/apparmor/apparmor_linux.go
index 2c5022c1f..0d01f41e9 100644
--- a/pkg/apparmor/apparmor_linux.go
+++ b/pkg/apparmor/apparmor_linux.go
@@ -225,8 +225,13 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
}
}
- if name != "" && !runcaa.IsEnabled() {
- return "", fmt.Errorf("profile %q specified but AppArmor is disabled on the host", name)
+ // Check if AppArmor is disabled and error out if a profile is to be set.
+ if !runcaa.IsEnabled() {
+ if name == "" {
+ return "", nil
+ } else {
+ return "", fmt.Errorf("profile %q specified but AppArmor is disabled on the host", name)
+ }
}
// If the specified name is not empty or is not a default libpod one,
diff --git a/pkg/hooks/docs/oci-hooks.5.md b/pkg/hooks/docs/oci-hooks.5.md
index c876dd2f8..fc0442283 100644
--- a/pkg/hooks/docs/oci-hooks.5.md
+++ b/pkg/hooks/docs/oci-hooks.5.md
@@ -90,7 +90,7 @@ $ cat /etc/containers/oci/hooks.d/oci-systemd-hook.json
"path": "/usr/libexec/oci/hooks.d/oci-systemd-hook"
}
"when": {
- "args": [".*/init$" , ".*/systemd$"],
+ "commands": [".*/init$" , ".*/systemd$"],
},
"stages": ["prestart", "poststop"]
}
diff --git a/pkg/registries/registries.go b/pkg/registries/registries.go
index 5c4ecd020..de63dcbf1 100644
--- a/pkg/registries/registries.go
+++ b/pkg/registries/registries.go
@@ -44,17 +44,7 @@ func getRegistries() ([]sysregistriesv2.Registry, error) {
// GetRegistries obtains the list of search registries defined in the global registries file.
func GetRegistries() ([]string, error) {
- var searchRegistries []string
- registries, err := getRegistries()
- if err != nil {
- return nil, err
- }
- for _, reg := range registries {
- if reg.Search {
- searchRegistries = append(searchRegistries, reg.Location)
- }
- }
- return searchRegistries, nil
+ return sysregistriesv2.UnqualifiedSearchRegistries(&types.SystemContext{SystemRegistriesConfPath: SystemRegistriesConfPath()})
}
// GetBlockedRegistries obtains the list of blocked registries defined in the global registries file.
@@ -66,7 +56,7 @@ func GetBlockedRegistries() ([]string, error) {
}
for _, reg := range registries {
if reg.Blocked {
- blockedRegistries = append(blockedRegistries, reg.Location)
+ blockedRegistries = append(blockedRegistries, reg.Prefix)
}
}
return blockedRegistries, nil
@@ -81,7 +71,7 @@ func GetInsecureRegistries() ([]string, error) {
}
for _, reg := range registries {
if reg.Insecure {
- insecureRegistries = append(insecureRegistries, reg.Location)
+ insecureRegistries = append(insecureRegistries, reg.Prefix)
}
}
return insecureRegistries, nil
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index ed8036a54..a8413d6c7 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -162,6 +162,10 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err
if config.StorageConfig.GraphDriverName != "" {
command = append(command, []string{"--storage-driver", config.StorageConfig.GraphDriverName}...)
}
+ for _, opt := range config.StorageConfig.GraphDriverOptions {
+ command = append(command, []string{"--storage-opt", opt}...)
+ }
+
if c.Syslog {
command = append(command, "--syslog", "true")
}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index a074f276c..61cdbbf38 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -99,7 +99,10 @@ func GetImageConfig(changes []string) (v1.ImageConfig, error) {
var st struct{}
exposedPorts[pair[1]] = st
case "ENV":
- env = append(env, pair[1])
+ if len(pair) < 3 {
+ return v1.ImageConfig{}, errors.Errorf("no value given for environment variable %q", pair[1])
+ }
+ env = append(env, strings.Join(pair[1:], "="))
case "ENTRYPOINT":
entrypoint = append(entrypoint, pair[1])
case "CMD":
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 9529346b4..8b6eab892 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -10,6 +10,7 @@ import (
"sort"
"strings"
"testing"
+ "time"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
@@ -22,6 +23,7 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
+ "github.com/pkg/errors"
)
var (
@@ -367,6 +369,18 @@ func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionInteg
return session, session.ExitCode(), session.OutputToString()
}
+// RunNginxWithHealthCheck runs the alpine nginx container with an optional name and adds a healthcheck into it
+func (p *PodmanTestIntegration) RunNginxWithHealthCheck(name string) (*PodmanSessionIntegration, string) {
+ var podmanArgs = []string{"run"}
+ if name != "" {
+ podmanArgs = append(podmanArgs, "--name", name)
+ }
+ podmanArgs = append(podmanArgs, "-dt", "-P", "--healthcheck-command", "CMD-SHELL curl http://localhost/", nginx)
+ session := p.Podman(podmanArgs)
+ session.WaitWithDefaultTimeout()
+ return session, session.OutputToString()
+}
+
func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) {
var podmanArgs = []string{"run", "--pod", pod}
if name != "" {
@@ -508,3 +522,16 @@ func (p *PodmanTestIntegration) ImageExistsInMainStore(idOrName string) bool {
results.WaitWithDefaultTimeout()
return Expect(results.ExitCode()).To(Equal(0))
}
+
+func (p *PodmanTestIntegration) RunHealthCheck(cid string) error {
+ for i := 0; i < 10; i++ {
+ hc := p.Podman([]string{"healthcheck", "run", cid})
+ hc.WaitWithDefaultTimeout()
+ if hc.ExitCode() == 0 {
+ return nil
+ }
+ fmt.Printf("Waiting for %s to pass healthcheck\n", cid)
+ time.Sleep(1 * time.Second)
+ }
+ return errors.Errorf("unable to detect %s as running", cid)
+}
diff --git a/test/e2e/cp_test.go b/test/e2e/cp_test.go
index 597d0aef7..f7596d77d 100644
--- a/test/e2e/cp_test.go
+++ b/test/e2e/cp_test.go
@@ -184,4 +184,25 @@ var _ = Describe("Podman cp", func() {
_, err = os.Stat("/tmp/cp_test.txt")
Expect(err).To(Not(BeNil()))
})
+ It("podman cp volume", func() {
+ session := podmanTest.Podman([]string{"volume", "create", "data"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"create", "-v", "data:/data", "--name", "container1", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ err = ioutil.WriteFile("cp_vol", []byte("copy to the volume"), 0644)
+ if err != nil {
+ os.Exit(1)
+ }
+ session = podmanTest.Podman([]string{"cp", "cp_vol", "container1" + ":/data/cp_vol1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"cp", "container1" + ":/data/cp_vol1", "cp_vol2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
})
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index cc50c4d95..d17f60a5d 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -218,4 +218,21 @@ var _ = Describe("Podman logs", func() {
Expect(results.ExitCode()).To(Equal(0))
Expect(len(results.OutputToStringArray())).To(Equal(3))
})
+
+ It("podman logs -f two lines", func() {
+ containerName := "logs-f-rm"
+
+ logc := podmanTest.Podman([]string{"run", "--rm", "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman; sleep 1; echo podman"})
+ logc.WaitWithDefaultTimeout()
+ Expect(logc.ExitCode()).To(Equal(0))
+
+ results := podmanTest.Podman([]string{"logs", "-f", containerName})
+ results.WaitWithDefaultTimeout()
+ Expect(results.ExitCode()).To(Equal(0))
+
+ // Verify that the cleanup process worked correctly and we can recreate a container with the same name
+ logc = podmanTest.Podman([]string{"run", "--rm", "--name", containerName, "-dt", ALPINE, "true"})
+ logc.WaitWithDefaultTimeout()
+ Expect(logc.ExitCode()).To(Equal(0))
+ })
})
diff --git a/test/e2e/port_test.go b/test/e2e/port_test.go
index e45118361..26c5fd7d0 100644
--- a/test/e2e/port_test.go
+++ b/test/e2e/port_test.go
@@ -48,11 +48,14 @@ var _ = Describe("Podman port", func() {
Expect(result.ExitCode()).ToNot(Equal(0))
})
- It("podman port -l nginx", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx})
- session.WaitWithDefaultTimeout()
+ It("podman port -l nginx", func() {
+ session, cid := podmanTest.RunNginxWithHealthCheck("")
Expect(session.ExitCode()).To(Equal(0))
+ if err := podmanTest.RunHealthCheck(cid); err != nil {
+ Fail(err.Error())
+ }
+
result := podmanTest.Podman([]string{"port", "-l"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
@@ -61,10 +64,13 @@ var _ = Describe("Podman port", func() {
})
It("podman container port -l nginx", func() {
- session := podmanTest.Podman([]string{"container", "run", "-dt", "-P", nginx})
- session.WaitWithDefaultTimeout()
+ session, cid := podmanTest.RunNginxWithHealthCheck("")
Expect(session.ExitCode()).To(Equal(0))
+ if err := podmanTest.RunHealthCheck(cid); err != nil {
+ Fail(err.Error())
+ }
+
result := podmanTest.Podman([]string{"container", "port", "-l"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
@@ -73,10 +79,13 @@ var _ = Describe("Podman port", func() {
})
It("podman port -l port nginx", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx})
- session.WaitWithDefaultTimeout()
+ session, cid := podmanTest.RunNginxWithHealthCheck("")
Expect(session.ExitCode()).To(Equal(0))
+ if err := podmanTest.RunHealthCheck(cid); err != nil {
+ Fail(err.Error())
+ }
+
result := podmanTest.Podman([]string{"port", "-l", "80"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
@@ -85,10 +94,13 @@ var _ = Describe("Podman port", func() {
})
It("podman port -a nginx", func() {
- session := podmanTest.Podman([]string{"run", "-dt", "-P", nginx})
- session.WaitWithDefaultTimeout()
+ session, cid := podmanTest.RunNginxWithHealthCheck("")
Expect(session.ExitCode()).To(Equal(0))
+ if err := podmanTest.RunHealthCheck(cid); err != nil {
+ Fail(err.Error())
+ }
+
result := podmanTest.Podman([]string{"port", "-a"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
diff --git a/test/e2e/runlabel_test.go b/test/e2e/runlabel_test.go
index 5ef68603e..4e2cb501e 100644
--- a/test/e2e/runlabel_test.go
+++ b/test/e2e/runlabel_test.go
@@ -85,6 +85,7 @@ var _ = Describe("podman container runlabel", func() {
})
It("podman container runlabel global options", func() {
+ Skip("Test nonfunctional for podman-in-podman testing")
image := "podman-global-test:ls"
podmanTest.BuildImage(GlobalDockerfile, image, "false")
result := podmanTest.Podman([]string{"--syslog", "--log-level", "debug", "container", "runlabel", "RUN", image})
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index a29b1adc3..cefff0e2c 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -9,8 +9,8 @@ true | 0 |
false | 1 |
sh -c 'exit 32' | 32 |
echo $rand | 0 | $rand
-/no/such/command | 127 | Error: container create failed:.*exec:.* no such file or dir
-/etc | 126 | Error: container create failed:.*exec:.* permission denied
+/no/such/command | 127 | Error: .*: starting container process caused .*exec:.*stat /no/such/command: no such file or directory
+/etc | 126 | Error: .*: starting container process caused .*exec:.* permission denied
"
while read cmd expected_rc expected_output; do
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 98031385d..43819350c 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -63,7 +63,7 @@ func (p *PodmanTest) MakeOptions(args []string) []string {
return p.PodmanMakeOptions(args)
}
-// PodmanAsUserBase exec podman as user. uid and gid is set for credentials useage. env is used
+// PodmanAsUserBase exec podman as user. uid and gid is set for credentials usage. env is used
// to record the env for debugging
func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, nocache bool) *PodmanSession {
var command *exec.Cmd
diff --git a/vendor.conf b/vendor.conf
index b7cb584f0..b8ac20a4e 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -15,7 +15,7 @@ github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-rc2
github.com/containernetworking/plugins v0.7.4
-github.com/containers/image 2c0349c99af7d90694b3faa0e9bde404d407b145
+github.com/containers/image v2.0.0
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1
@@ -93,7 +93,7 @@ k8s.io/api kubernetes-1.10.13-beta.0 https://github.com/kubernetes/api
k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apimachinery
k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
-github.com/containers/buildah v1.8.3
+github.com/containers/buildah v1.9.0
github.com/varlink/go 0f1d566d194b9d6d48e0d47c5e4d822628919066
# TODO: Gotty has not been updated since 2012. Can we find replacement?
github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
diff --git a/vendor/github.com/containers/buildah/add.go b/vendor/github.com/containers/buildah/add.go
index 11bfb6a12..b03aa65b2 100644
--- a/vendor/github.com/containers/buildah/add.go
+++ b/vendor/github.com/containers/buildah/add.go
@@ -34,10 +34,14 @@ type AddAndCopyOptions struct {
// If the sources include directory trees, Hasher will be passed
// tar-format archives of the directory trees.
Hasher io.Writer
- // Exludes contents in the .dockerignore file
+ // Excludes is the contents of the .dockerignore file
Excludes []string
- // current directory on host
+ // The base directory for Excludes and data to copy in
ContextDir string
+ // ID mapping options to use when contents to be copied are part of
+ // another container, and need ownerships to be mapped from the host to
+ // that container's values before copying them into the container.
+ IDMappingOptions *IDMappingOptions
}
// addURL copies the contents of the source URL to the destination. This is
@@ -116,6 +120,12 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
hostOwner := idtools.IDPair{UID: int(hostUID), GID: int(hostGID)}
dest := mountPoint
if destination != "" && filepath.IsAbs(destination) {
+ dir := filepath.Dir(destination)
+ if dir != "." && dir != "/" {
+ if err = idtools.MkdirAllAndChownNew(filepath.Join(dest, dir), 0755, hostOwner); err != nil {
+ return errors.Wrapf(err, "error creating directory %q", filepath.Join(dest, dir))
+ }
+ }
dest = filepath.Join(dest, destination)
} else {
if err = idtools.MkdirAllAndChownNew(filepath.Join(dest, b.WorkDir()), 0755, hostOwner); err != nil {
@@ -146,8 +156,8 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
if len(source) > 1 && (destfi == nil || !destfi.IsDir()) {
return errors.Errorf("destination %q is not a directory", dest)
}
- copyFileWithTar := b.copyFileWithTar(&containerOwner, options.Hasher)
- copyWithTar := b.copyWithTar(&containerOwner, options.Hasher)
+ copyFileWithTar := b.copyFileWithTar(options.IDMappingOptions, &containerOwner, options.Hasher)
+ copyWithTar := b.copyWithTar(options.IDMappingOptions, &containerOwner, options.Hasher)
untarPath := b.untarPath(nil, options.Hasher)
err = addHelper(excludes, extract, dest, destfi, hostOwner, options, copyFileWithTar, copyWithTar, untarPath, source...)
if err != nil {
diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go
index 56c8f088f..329835d7a 100644
--- a/vendor/github.com/containers/buildah/buildah.go
+++ b/vendor/github.com/containers/buildah/buildah.go
@@ -26,7 +26,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
- Version = "1.8.3"
+ Version = "1.9.0"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to
diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go
index d6e5a61ea..ae60d9bbe 100644
--- a/vendor/github.com/containers/buildah/chroot/run.go
+++ b/vendor/github.com/containers/buildah/chroot/run.go
@@ -220,7 +220,6 @@ func runUsingChrootMain() {
var stdout io.Writer
var stderr io.Writer
fdDesc := make(map[int]string)
- deferred := func() {}
if options.Spec.Process.Terminal {
// Create a pseudo-terminal -- open a copy of the master side.
ptyMasterFd, err := unix.Open("/dev/ptmx", os.O_RDWR, 0600)
@@ -370,12 +369,16 @@ func runUsingChrootMain() {
return
}
}
+ if err := unix.SetNonblock(relays[unix.Stdin], true); err != nil {
+ logrus.Errorf("error setting %d to nonblocking: %v", relays[unix.Stdin], err)
+ }
go func() {
buffers := make(map[int]*bytes.Buffer)
for _, writeFd := range relays {
buffers[writeFd] = new(bytes.Buffer)
}
pollTimeout := -1
+ stdinClose := false
for len(relays) > 0 {
fds := make([]unix.PollFd, 0, len(relays))
for fd := range relays {
@@ -395,6 +398,9 @@ func runUsingChrootMain() {
removeFds[int(rfd.Fd)] = struct{}{}
}
if rfd.Revents&unix.POLLIN == 0 {
+ if stdinClose && stdinCopy == nil {
+ continue
+ }
continue
}
b := make([]byte, 8192)
@@ -449,8 +455,19 @@ func runUsingChrootMain() {
if buffer.Len() > 0 {
pollTimeout = 100
}
+ if wfd == relays[unix.Stdin] && stdinClose && buffer.Len() == 0 {
+ stdinCopy.Close()
+ delete(relays, unix.Stdin)
+ }
}
for rfd := range removeFds {
+ if rfd == unix.Stdin {
+ buffer, found := buffers[relays[unix.Stdin]]
+ if found && buffer.Len() > 0 {
+ stdinClose = true
+ continue
+ }
+ }
if !options.Spec.Process.Terminal && rfd == unix.Stdin {
stdinCopy.Close()
}
@@ -461,7 +478,6 @@ func runUsingChrootMain() {
// Set up mounts and namespaces, and run the parent subprocess.
status, err := runUsingChroot(options.Spec, options.BundlePath, ctty, stdin, stdout, stderr, closeOnceRunning)
- deferred()
if err != nil {
fmt.Fprintf(os.Stderr, "error running subprocess: %v\n", err)
os.Exit(1)
diff --git a/vendor/github.com/containers/buildah/image.go b/vendor/github.com/containers/buildah/image.go
index 215920cc3..dc2d323d4 100644
--- a/vendor/github.com/containers/buildah/image.go
+++ b/vendor/github.com/containers/buildah/image.go
@@ -707,7 +707,7 @@ func (b *Builder) makeImageRef(options CommitOptions, exporting bool) (types.Ima
exporting: exporting,
squash: options.Squash,
emptyLayer: options.EmptyLayer,
- tarPath: b.tarPath(),
+ tarPath: b.tarPath(&b.IDMappingOptions),
parent: parent,
blobDirectory: options.BlobDirectory,
preEmptyLayers: b.PrependedEmptyLayers,
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index 3665251cd..20d6715f5 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -27,7 +27,7 @@ import (
"github.com/containers/image/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
- "github.com/cyphar/filepath-securejoin"
+ securejoin "github.com/cyphar/filepath-securejoin"
docker "github.com/fsouza/go-dockerclient"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
@@ -210,7 +210,6 @@ type Executor struct {
annotations []string
onbuild []string
layers bool
- topLayers []string
useCache bool
removeIntermediateCtrs bool
forceRmIntermediateCtrs bool
@@ -515,26 +514,55 @@ func (s *StageExecutor) Copy(excludes []string, copies ...imagebuilder.Copy) err
for _, src := range copy.Src {
contextDir := s.executor.contextDir
copyExcludes := excludes
+ var idMappingOptions *buildah.IDMappingOptions
if strings.HasPrefix(src, "http://") || strings.HasPrefix(src, "https://") {
sources = append(sources, src)
} else if len(copy.From) > 0 {
+ var srcRoot string
if other, ok := s.executor.stages[copy.From]; ok && other.index < s.index {
- sources = append(sources, filepath.Join(other.mountPoint, src))
+ srcRoot = other.mountPoint
contextDir = other.mountPoint
+ idMappingOptions = &other.builder.IDMappingOptions
} else if builder, ok := s.executor.containerMap[copy.From]; ok {
- sources = append(sources, filepath.Join(builder.MountPoint, src))
+ srcRoot = builder.MountPoint
contextDir = builder.MountPoint
+ idMappingOptions = &builder.IDMappingOptions
} else {
return errors.Errorf("the stage %q has not been built", copy.From)
}
+ srcSecure, err := securejoin.SecureJoin(srcRoot, src)
+ if err != nil {
+ return err
+ }
+ // If destination is a folder, we need to take extra care to
+ // ensure that files are copied with correct names (since
+ // resolving a symlink may result in a different name).
+ if hadFinalPathSeparator {
+ _, srcName := filepath.Split(src)
+ _, srcNameSecure := filepath.Split(srcSecure)
+ if srcName != srcNameSecure {
+ options := buildah.AddAndCopyOptions{
+ Chown: copy.Chown,
+ ContextDir: contextDir,
+ Excludes: copyExcludes,
+ }
+ if err := s.builder.Add(filepath.Join(copy.Dest, srcName), copy.Download, options, srcSecure); err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ sources = append(sources, srcSecure)
+
} else {
sources = append(sources, filepath.Join(s.executor.contextDir, src))
copyExcludes = append(s.executor.excludes, excludes...)
}
options := buildah.AddAndCopyOptions{
- Chown: copy.Chown,
- ContextDir: contextDir,
- Excludes: copyExcludes,
+ Chown: copy.Chown,
+ ContextDir: contextDir,
+ Excludes: copyExcludes,
+ IDMappingOptions: idMappingOptions,
}
if err := s.builder.Add(copy.Dest, copy.Download, options, sources...); err != nil {
return err
@@ -860,9 +888,6 @@ func (s *StageExecutor) prepare(ctx context.Context, stage imagebuilder.Stage, f
// Make this our "current" working container.
s.mountPoint = mountPoint
s.builder = builder
- // Add the top layer of this image to b.topLayers so we can
- // keep track of them when building with cached images.
- s.executor.topLayers = append(s.executor.topLayers, builder.TopLayer)
}
logrus.Debugln("Container ID:", builder.ContainerID)
return builder, nil
@@ -967,7 +992,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
logImageID := func(imgID string) {
if s.executor.iidfile == "" {
- fmt.Fprintf(s.executor.out, "--> %s\n", imgID)
+ fmt.Fprintf(s.executor.out, "%s\n", imgID)
}
}
@@ -985,7 +1010,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// We don't need to squash the base image, so just
// reuse the base image.
logCommit(s.output, -1)
- if imgID, ref, err = s.copyExistingImage(ctx, s.builder.FromImageID, s.output); err != nil {
+ if imgID, ref, err = s.tagExistingImage(ctx, s.builder.FromImageID, s.output); err != nil {
return "", nil, err
}
}
@@ -1110,7 +1135,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
imgID = cacheID
if commitName != "" {
logCommit(commitName, i)
- if imgID, ref, err = s.copyExistingImage(ctx, cacheID, commitName); err != nil {
+ if imgID, ref, err = s.tagExistingImage(ctx, cacheID, commitName); err != nil {
return "", nil, err
}
logImageID(imgID)
@@ -1179,8 +1204,8 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
return imgID, ref, nil
}
-// copyExistingImage creates a copy of an image already in the store
-func (s *StageExecutor) copyExistingImage(ctx context.Context, cacheID, output string) (string, reference.Canonical, error) {
+// tagExistingImage adds names to an image already in the store
+func (s *StageExecutor) tagExistingImage(ctx context.Context, cacheID, output string) (string, reference.Canonical, error) {
// If we don't need to attach a name to the image, just return the cache ID.
if output == "" {
return cacheID, nil, nil
@@ -1247,11 +1272,11 @@ func (s *StageExecutor) layerExists(ctx context.Context, currNode *parser.Node,
return "", errors.Wrapf(err, "error getting top layer info")
}
}
- // If the parent of the top layer of an image is equal to the last entry in b.topLayers
+ // If the parent of the top layer of an image is equal to the current build image's top layer,
// it means that this image is potentially a cached intermediate image from a previous
// build. Next we double check that the history of this image is equivalent to the previous
// lines in the Dockerfile up till the point we are at in the build.
- if imageTopLayer == nil || imageTopLayer.Parent == s.executor.topLayers[len(s.executor.topLayers)-1] || imageTopLayer.ID == s.executor.topLayers[len(s.executor.topLayers)-1] {
+ if imageTopLayer == nil || (s.builder.TopLayer != "" && (imageTopLayer.Parent == s.builder.TopLayer || imageTopLayer.ID == s.builder.TopLayer)) {
history, err := s.executor.getImageHistory(ctx, image.ID)
if err != nil {
return "", errors.Wrapf(err, "error getting history of %q", image.ID)
@@ -1340,26 +1365,8 @@ func (b *Executor) historyMatches(baseHistory []v1.History, child *parser.Node,
return false
}
}
- instruction := child.Original
- switch strings.ToUpper(child.Value) {
- case "RUN":
- instruction = instruction[4:]
- buildArgs := b.getBuildArgs()
- // If a previous image was built with some build-args but the new build process doesn't have any build-args
- // specified, the command might be expanded differently, so compare the lengths of the old instruction with
- // the current one. 11 is the length of "/bin/sh -c " that is used to run the run commands.
- if buildArgs == "" && len(history[len(baseHistory)].CreatedBy) > len(instruction)+11 {
- return false
- }
- // There are build-args, so check if anything with the build-args has changed
- if buildArgs != "" && !strings.Contains(history[len(baseHistory)].CreatedBy, buildArgs) {
- return false
- }
- fallthrough
- default:
- if !strings.Contains(history[len(baseHistory)].CreatedBy, instruction) {
- return false
- }
+ if history[len(baseHistory)].CreatedBy != b.getCreatedBy(child) {
+ return false
}
return true
}
@@ -1373,6 +1380,7 @@ func (b *Executor) getBuildArgs() string {
buildArgs = append(buildArgs, k+"="+v)
}
}
+ sort.Strings(buildArgs)
return strings.Join(buildArgs, " ")
}
@@ -1545,7 +1553,6 @@ func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, cr
options := buildah.CommitOptions{
Compression: s.executor.compression,
SignaturePolicyPath: s.executor.signaturePolicyPath,
- AdditionalTags: s.executor.additionalTags,
ReportWriter: writer,
PreferredManifestType: s.executor.outputFormat,
SystemContext: s.executor.systemContext,
@@ -1731,6 +1738,24 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
fmt.Fprintf(b.out, "[Warning] one or more build args were not consumed: %v\n", unusedList)
}
+ if len(b.additionalTags) > 0 {
+ if dest, err := b.resolveNameToImageRef(b.output); err == nil {
+ switch dest.Transport().Name() {
+ case is.Transport.Name():
+ img, err := is.Transport.GetStoreImage(b.store, dest)
+ if err != nil {
+ return imageID, ref, errors.Wrapf(err, "error locating just-written image %q", transports.ImageName(dest))
+ }
+ if err = util.AddImageNames(b.store, "", b.systemContext, img, b.additionalTags); err != nil {
+ return imageID, ref, errors.Wrapf(err, "error setting image names to %v", append(img.Names, b.additionalTags...))
+ }
+ logrus.Debugf("assigned names %v to image %q", img.Names, img.ID)
+ default:
+ logrus.Warnf("don't know how to add tags to images stored in %q transport", dest.Transport().Name())
+ }
+ }
+ }
+
if err := cleanup(); err != nil {
return "", nil, err
}
diff --git a/vendor/github.com/containers/buildah/pkg/overlay/overlay.go b/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
index 31f0c2cec..14d29a25b 100644
--- a/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
+++ b/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
@@ -2,6 +2,7 @@ package overlay
import (
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -15,13 +16,27 @@ import (
// MountTemp creates a subdir of the contentDir based on the source directory
// from the source system. It then mounds up the source directory on to the
// generated mount point and returns the mount point to the caller.
-func MountTemp(store storage.Store, containerId, source, dest string, rootUID, rootGID int) (specs.Mount, string, error) {
- mount := specs.Mount{}
+func MountTemp(store storage.Store, containerId, source, dest string, rootUID, rootGID int) (mount specs.Mount, contentDir string, Err error) {
- contentDir, err := store.ContainerDirectory(containerId)
+ containerDir, err := store.ContainerDirectory(containerId)
if err != nil {
return mount, "", err
}
+ contentDir = filepath.Join(containerDir, "overlay")
+ if err := idtools.MkdirAllAs(contentDir, 0700, rootUID, rootGID); err != nil {
+ return mount, "", errors.Wrapf(err, "failed to create the overlay %s directory", contentDir)
+ }
+
+ contentDir, err = ioutil.TempDir(contentDir, "")
+ if err != nil {
+ return mount, "", errors.Wrapf(err, "failed to create TempDir in the overlay %s directory", contentDir)
+ }
+ defer func() {
+ if Err != nil {
+ os.RemoveAll(contentDir)
+ }
+ }()
+
upperDir := filepath.Join(contentDir, "upper")
workDir := filepath.Join(contentDir, "work")
if err := idtools.MkdirAllAs(upperDir, 0700, rootUID, rootGID); err != nil {
@@ -44,3 +59,13 @@ func MountTemp(store storage.Store, containerId, source, dest string, rootUID, r
func RemoveTemp(contentDir string) error {
return os.RemoveAll(contentDir)
}
+
+// CleanupContent removes all temporary mountpoint and all content from
+// directory
+func CleanupContent(containerDir string) (Err error) {
+ contentDir := filepath.Join(containerDir, "overlay")
+ if err := os.RemoveAll(contentDir); err != nil && !os.IsNotExist(err) {
+ return errors.Wrapf(err, "failed to cleanup overlay %s directory", contentDir)
+ }
+ return nil
+}
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse.go b/vendor/github.com/containers/buildah/pkg/parse/parse.go
index 6c58f1194..61e70cdd3 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse.go
@@ -37,6 +37,7 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
var (
memoryLimit int64
memorySwap int64
+ noDNS bool
err error
)
@@ -67,9 +68,26 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
}
}
+ noDNS = false
dnsServers, _ := c.Flags().GetStringSlice("dns")
+ for _, server := range dnsServers {
+ if strings.ToLower(server) == "none" {
+ noDNS = true
+ }
+ }
+ if noDNS && len(dnsServers) > 1 {
+ return nil, errors.Errorf("invalid --dns, --dns=none may not be used with any other --dns options")
+ }
+
dnsSearch, _ := c.Flags().GetStringSlice("dns-search")
+ if noDNS && len(dnsSearch) > 0 {
+ return nil, errors.Errorf("invalid --dns-search, --dns-search may not be used with --dns=none")
+ }
+
dnsOptions, _ := c.Flags().GetStringSlice("dns-option")
+ if noDNS && len(dnsOptions) > 0 {
+ return nil, errors.Errorf("invalid --dns-option, --dns-option may not be used with --dns=none")
+ }
if _, err := units.FromHumanSize(c.Flag("shm-size").Value.String()); err != nil {
return nil, errors.Wrapf(err, "invalid --shm-size")
@@ -80,7 +98,7 @@ func CommonBuildOptions(c *cobra.Command) (*buildah.CommonBuildOptions, error) {
}
cpuPeriod, _ := c.Flags().GetUint64("cpu-period")
cpuQuota, _ := c.Flags().GetInt64("cpu-quota")
- cpuShares, _ := c.Flags().GetUint64("cpu-shared")
+ cpuShares, _ := c.Flags().GetUint64("cpu-shares")
httpProxy, _ := c.Flags().GetBool("http-proxy")
ulimit, _ := c.Flags().GetStringSlice("ulimit")
commonOpts := &buildah.CommonBuildOptions{
diff --git a/vendor/github.com/containers/buildah/pkg/unshare/unshare.c b/vendor/github.com/containers/buildah/pkg/unshare/unshare.c
index 67a3e0e4d..fd0d48d43 100644
--- a/vendor/github.com/containers/buildah/pkg/unshare/unshare.c
+++ b/vendor/github.com/containers/buildah/pkg/unshare/unshare.c
@@ -3,7 +3,7 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
-#include <linux/memfd.h>
+#include <sys/mman.h>
#include <fcntl.h>
#include <grp.h>
#include <sched.h>
@@ -14,6 +14,17 @@
#include <errno.h>
#include <unistd.h>
+/* Open Source projects like conda-forge, want to package podman and are based
+ off of centos:6, Conda-force has minimal libc requirements and is lacking
+ the memfd.h file, so we use mmam.h
+*/
+#ifndef MFD_ALLOW_SEALING
+#define MFD_ALLOW_SEALING 2U
+#endif
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 1U
+#endif
+
#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE 1024
#endif
diff --git a/vendor/github.com/containers/buildah/pkg/unshare/unshare.go b/vendor/github.com/containers/buildah/pkg/unshare/unshare.go
index 5a68d6b8d..21b102cf5 100644
--- a/vendor/github.com/containers/buildah/pkg/unshare/unshare.go
+++ b/vendor/github.com/containers/buildah/pkg/unshare/unshare.go
@@ -195,13 +195,25 @@ func (c *Cmd) Start() error {
if err == nil {
gidmapSet = true
} else {
- fmt.Fprintf(continueWrite, "error running newgidmap: %v: %s", err, g.String())
- fmt.Fprintf(continueWrite, "falling back to single mapping\n")
+ logrus.Warnf("error running newgidmap: %v: %s", err, g.String())
+ logrus.Warnf("falling back to single mapping")
g.Reset()
g.Write([]byte(fmt.Sprintf("0 %d 1\n", os.Getegid())))
}
}
if !gidmapSet {
+ if c.UseNewgidmap {
+ setgroups, err := os.OpenFile(fmt.Sprintf("/proc/%s/setgroups", pidString), os.O_TRUNC|os.O_WRONLY, 0)
+ if err != nil {
+ fmt.Fprintf(continueWrite, "error opening /proc/%s/setgroups: %v", pidString, err)
+ return errors.Wrapf(err, "error opening /proc/%s/setgroups", pidString)
+ }
+ defer setgroups.Close()
+ if _, err := fmt.Fprintf(setgroups, "deny"); err != nil {
+ fmt.Fprintf(continueWrite, "error writing 'deny' to /proc/%s/setgroups: %v", pidString, err)
+ return errors.Wrapf(err, "error writing 'deny' to /proc/%s/setgroups", pidString)
+ }
+ }
gidmap, err := os.OpenFile(fmt.Sprintf("/proc/%s/gid_map", pidString), os.O_TRUNC|os.O_WRONLY, 0)
if err != nil {
fmt.Fprintf(continueWrite, "error opening /proc/%s/gid_map: %v", pidString, err)
@@ -232,8 +244,8 @@ func (c *Cmd) Start() error {
if err == nil {
uidmapSet = true
} else {
- fmt.Fprintf(continueWrite, "error running newuidmap: %v: %s", err, u.String())
- fmt.Fprintf(continueWrite, "falling back to single mapping\n")
+ logrus.Warnf("error running newuidmap: %v: %s", err, u.String())
+ logrus.Warnf("falling back to single mapping")
u.Reset()
u.Write([]byte(fmt.Sprintf("0 %d 1\n", os.Geteuid())))
}
diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go
index 16c0550aa..0bf37da59 100644
--- a/vendor/github.com/containers/buildah/run_linux.go
+++ b/vendor/github.com/containers/buildah/run_linux.go
@@ -174,7 +174,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
bindFiles["/etc/hosts"] = hostFile
}
- if !contains(volumes, "/etc/resolv.conf") {
+ if !(contains(volumes, "/etc/resolv.conf") || (len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none")) {
resolvFile, err := b.addNetworkConfig(path, "/etc/resolv.conf", rootIDPair, b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions)
if err != nil {
return err
@@ -434,7 +434,7 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st
// Add temporary copies of the contents of volume locations at the
// volume locations, unless we already have something there.
- copyWithTar := b.copyWithTar(nil, nil)
+ copyWithTar := b.copyWithTar(nil, nil, nil)
builtins, err := runSetupBuiltinVolumes(b.MountLabel, mountPoint, cdir, copyWithTar, builtinVolumes, int(rootUID), int(rootGID))
if err != nil {
return err
@@ -1049,6 +1049,18 @@ func runConfigureNetwork(isolation Isolation, options RunOptions, configureNetwo
return teardown, nil
}
+func setNonblock(fd int, description string, nonblocking bool) error {
+ err := unix.SetNonblock(fd, nonblocking)
+ if err != nil {
+ if nonblocking {
+ logrus.Errorf("error setting %s to nonblocking: %v", description, err)
+ } else {
+ logrus.Errorf("error setting descriptor %s blocking: %v", description, err)
+ }
+ }
+ return err
+}
+
func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copyConsole bool, consoleListener *net.UnixListener, finishCopy []int, finishedCopy chan struct{}, spec *specs.Spec) {
defer func() {
unix.Close(finishCopy[0])
@@ -1116,14 +1128,22 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy
}
// Set our reading descriptors to non-blocking.
for rfd, wfd := range relayMap {
- if err := unix.SetNonblock(rfd, true); err != nil {
- logrus.Errorf("error setting %s to nonblocking: %v", readDesc[rfd], err)
+ if err := setNonblock(rfd, readDesc[rfd], true); err != nil {
return
}
- if err := unix.SetNonblock(wfd, false); err != nil {
- logrus.Errorf("error setting descriptor %d (%s) blocking: %v", wfd, writeDesc[wfd], err)
- }
+ setNonblock(wfd, writeDesc[wfd], false)
}
+
+ if copyPipes {
+ setNonblock(stdioPipe[unix.Stdin][1], writeDesc[stdioPipe[unix.Stdin][1]], true)
+ }
+
+ runCopyStdioPassData(stdio, copyPipes, stdioPipe, copyConsole, consoleListener, finishCopy, finishedCopy, spec, relayMap, relayBuffer, readDesc, writeDesc)
+}
+
+func runCopyStdioPassData(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copyConsole bool, consoleListener *net.UnixListener, finishCopy []int, finishedCopy chan struct{}, spec *specs.Spec, relayMap map[int]int, relayBuffer map[int]*bytes.Buffer, readDesc map[int]string, writeDesc map[int]string) {
+ closeStdin := false
+
// Pass data back and forth.
pollTimeout := -1
for len(relayMap) > 0 {
@@ -1155,12 +1175,6 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy
}
// If the POLLIN flag isn't set, then there's no data to be read from this descriptor.
if pollFd.Revents&unix.POLLIN == 0 {
- // If we're using pipes and it's our stdin and it's closed, close the writing
- // end of the corresponding pipe.
- if copyPipes && int(pollFd.Fd) == unix.Stdin && pollFd.Revents&unix.POLLHUP != 0 {
- unix.Close(stdioPipe[unix.Stdin][1])
- stdioPipe[unix.Stdin][1] = -1
- }
continue
}
// Read whatever there is to be read.
@@ -1175,10 +1189,8 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy
// using pipes, it's an EOF, so close the stdin
// pipe's writing end.
if n == 0 && copyPipes && int(pollFd.Fd) == unix.Stdin {
- unix.Close(stdioPipe[unix.Stdin][1])
- stdioPipe[unix.Stdin][1] = -1
- }
- if n > 0 {
+ removes[int(pollFd.Fd)] = struct{}{}
+ } else if n > 0 {
// Buffer the data in case we get blocked on where they need to go.
nwritten, err := relayBuffer[writeFD].Write(buf[:n])
if err != nil {
@@ -1222,6 +1234,11 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy
if n > 0 {
relayBuffer[writeFD].Next(n)
}
+ if closeStdin && writeFD == stdioPipe[unix.Stdin][1] && stdioPipe[unix.Stdin][1] >= 0 && relayBuffer[stdioPipe[unix.Stdin][1]].Len() == 0 {
+ logrus.Debugf("closing stdin")
+ unix.Close(stdioPipe[unix.Stdin][1])
+ stdioPipe[unix.Stdin][1] = -1
+ }
}
if relayBuffer[writeFD].Len() > 0 {
pollTimeout = 100
@@ -1229,6 +1246,14 @@ func runCopyStdio(stdio *sync.WaitGroup, copyPipes bool, stdioPipe [][]int, copy
}
// Remove any descriptors which we don't need to poll any more from the poll descriptor list.
for remove := range removes {
+ if copyPipes && remove == unix.Stdin {
+ closeStdin = true
+ if relayBuffer[stdioPipe[unix.Stdin][1]].Len() == 0 {
+ logrus.Debugf("closing stdin")
+ unix.Close(stdioPipe[unix.Stdin][1])
+ stdioPipe[unix.Stdin][1] = -1
+ }
+ }
delete(relayMap, remove)
}
// If the we-can-return pipe had anything for us, we're done.
@@ -1453,7 +1478,7 @@ func setupNamespaces(g *generate.Generator, namespaceOptions NamespaceOptions, i
}
}
}
- if configureNetwork {
+ if configureNetwork && !unshare.IsRootless() {
for name, val := range util.DefaultNetworkSysctl {
// Check that the sysctl we are adding is actually supported
// by the kernel
@@ -1564,6 +1589,15 @@ func (b *Builder) cleanupTempVolumes() {
func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string, optionMounts []specs.Mount, rootUID, rootGID int) (mounts []specs.Mount, Err error) {
+ // Make sure the overlay directory is clean before running
+ containerDir, err := b.store.ContainerDirectory(b.ContainerID)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error looking up container directory for %s", b.ContainerID)
+ }
+ if err := overlay.CleanupContent(containerDir); err != nil {
+ return nil, errors.Wrapf(err, "error cleaning up overlay content for %s", b.ContainerID)
+ }
+
parseMount := func(host, container string, options []string) (specs.Mount, error) {
var foundrw, foundro, foundz, foundZ, foundO bool
var rootProp string
diff --git a/vendor/github.com/containers/buildah/util.go b/vendor/github.com/containers/buildah/util.go
index 08fb99706..ce21d2651 100644
--- a/vendor/github.com/containers/buildah/util.go
+++ b/vendor/github.com/containers/buildah/util.go
@@ -1,9 +1,12 @@
package buildah
import (
+ "archive/tar"
"io"
"os"
+ "path/filepath"
+ "github.com/containers/buildah/util"
"github.com/containers/image/docker/reference"
"github.com/containers/image/pkg/sysregistries"
"github.com/containers/image/pkg/sysregistriesv2"
@@ -12,7 +15,9 @@ import (
"github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive"
"github.com/containers/storage/pkg/idtools"
+ "github.com/containers/storage/pkg/pools"
"github.com/containers/storage/pkg/reexec"
+ "github.com/containers/storage/pkg/system"
"github.com/opencontainers/image-spec/specs-go/v1"
rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
@@ -105,19 +110,108 @@ func convertRuntimeIDMaps(UIDMap, GIDMap []rspec.LinuxIDMapping) ([]idtools.IDMa
}
// copyFileWithTar returns a function which copies a single file from outside
-// of any container into our working container, mapping permissions using the
-// container's ID maps, possibly overridden using the passed-in chownOpts
-func (b *Builder) copyFileWithTar(chownOpts *idtools.IDPair, hasher io.Writer) func(src, dest string) error {
- convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
- return chrootarchive.CopyFileWithTarAndChown(chownOpts, hasher, convertedUIDMap, convertedGIDMap)
+// of any container, or another container, into our working container, mapping
+// read permissions using the passed-in ID maps, writing using the container's
+// ID mappings, possibly overridden using the passed-in chownOpts
+func (b *Builder) copyFileWithTar(tarIDMappingOptions *IDMappingOptions, chownOpts *idtools.IDPair, hasher io.Writer) func(src, dest string) error {
+ if tarIDMappingOptions == nil {
+ tarIDMappingOptions = &IDMappingOptions{
+ HostUIDMapping: true,
+ HostGIDMapping: true,
+ }
+ }
+ return func(src, dest string) error {
+ logrus.Debugf("copyFileWithTar(%s, %s)", src, dest)
+ f, err := os.Open(src)
+ if err != nil {
+ return errors.Wrapf(err, "error opening %q to copy its contents", src)
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ }
+ }()
+
+ sysfi, err := system.Lstat(src)
+ if err != nil {
+ return errors.Wrapf(err, "error reading attributes of %q", src)
+ }
+
+ hostUID := sysfi.UID()
+ hostGID := sysfi.GID()
+ containerUID, containerGID, err := util.GetContainerIDs(tarIDMappingOptions.UIDMap, tarIDMappingOptions.GIDMap, hostUID, hostGID)
+ if err != nil {
+ return errors.Wrapf(err, "error mapping owner IDs of %q: %d/%d", src, hostUID, hostGID)
+ }
+
+ fi, err := os.Lstat(src)
+ if err != nil {
+ return errors.Wrapf(err, "error reading attributes of %q", src)
+ }
+
+ hdr, err := tar.FileInfoHeader(fi, filepath.Base(src))
+ if err != nil {
+ return errors.Wrapf(err, "error generating tar header for: %q", src)
+ }
+ hdr.Name = filepath.Base(dest)
+ hdr.Uid = int(containerUID)
+ hdr.Gid = int(containerGID)
+
+ pipeReader, pipeWriter := io.Pipe()
+ writer := tar.NewWriter(pipeWriter)
+ var copyErr error
+ go func(srcFile *os.File) {
+ err := writer.WriteHeader(hdr)
+ if err != nil {
+ logrus.Debugf("error writing header for %s: %v", srcFile.Name(), err)
+ copyErr = err
+ }
+ n, err := pools.Copy(writer, srcFile)
+ if n != hdr.Size {
+ logrus.Debugf("expected to write %d bytes for %s, wrote %d instead", hdr.Size, srcFile.Name(), n)
+ }
+ if err != nil {
+ logrus.Debugf("error reading %s: %v", srcFile.Name(), err)
+ copyErr = err
+ }
+ if err = writer.Close(); err != nil {
+ logrus.Debugf("error closing write pipe for %s: %v", srcFile.Name(), err)
+ }
+ if err = srcFile.Close(); err != nil {
+ logrus.Debugf("error closing %s: %v", srcFile.Name(), err)
+ }
+ pipeWriter.Close()
+ pipeWriter = nil
+ return
+ }(f)
+
+ untar := b.untar(chownOpts, hasher)
+ err = untar(pipeReader, filepath.Dir(dest))
+ if err == nil {
+ err = copyErr
+ }
+ f = nil
+ if pipeWriter != nil {
+ pipeWriter.Close()
+ }
+ return err
+ }
}
// copyWithTar returns a function which copies a directory tree from outside of
-// any container into our working container, mapping permissions using the
-// container's ID maps, possibly overridden using the passed-in chownOpts
-func (b *Builder) copyWithTar(chownOpts *idtools.IDPair, hasher io.Writer) func(src, dest string) error {
- convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
- return chrootarchive.CopyWithTarAndChown(chownOpts, hasher, convertedUIDMap, convertedGIDMap)
+// our container or from another container, into our working container, mapping
+// permissions at read-time using the container's ID maps, with ownership at
+// write-time possibly overridden using the passed-in chownOpts
+func (b *Builder) copyWithTar(tarIDMappingOptions *IDMappingOptions, chownOpts *idtools.IDPair, hasher io.Writer) func(src, dest string) error {
+ tar := b.tarPath(tarIDMappingOptions)
+ untar := b.untar(chownOpts, hasher)
+ return func(src, dest string) error {
+ rc, err := tar(src)
+ if err != nil {
+ return errors.Wrapf(err, "error archiving %q for copy", src)
+ }
+ return untar(rc, dest)
+ }
}
// untarPath returns a function which extracts an archive in a specified
@@ -128,12 +222,58 @@ func (b *Builder) untarPath(chownOpts *idtools.IDPair, hasher io.Writer) func(sr
return chrootarchive.UntarPathAndChown(chownOpts, hasher, convertedUIDMap, convertedGIDMap)
}
-// tarPath returns a function which creates an archive of a specified
+// tarPath returns a function which creates an archive of a specified location,
+// which is often somewhere in the container's filesystem, mapping permissions
+// using the container's ID maps, or the passed-in maps if specified
+func (b *Builder) tarPath(idMappingOptions *IDMappingOptions) func(path string) (io.ReadCloser, error) {
+ var uidmap, gidmap []idtools.IDMap
+ if idMappingOptions == nil {
+ idMappingOptions = &IDMappingOptions{
+ HostUIDMapping: true,
+ HostGIDMapping: true,
+ }
+ }
+ convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(idMappingOptions.UIDMap, idMappingOptions.GIDMap)
+ tarMappings := idtools.NewIDMappingsFromMaps(convertedUIDMap, convertedGIDMap)
+ uidmap = tarMappings.UIDs()
+ gidmap = tarMappings.GIDs()
+ options := &archive.TarOptions{
+ Compression: archive.Uncompressed,
+ UIDMaps: uidmap,
+ GIDMaps: gidmap,
+ }
+ return func(path string) (io.ReadCloser, error) {
+ return archive.TarWithOptions(path, options)
+ }
+}
+
+// untar returns a function which extracts an archive stream to a specified
// location in the container's filesystem, mapping permissions using the
-// container's ID maps
-func (b *Builder) tarPath() func(path string) (io.ReadCloser, error) {
+// container's ID maps, possibly overridden using the passed-in chownOpts
+func (b *Builder) untar(chownOpts *idtools.IDPair, hasher io.Writer) func(tarArchive io.ReadCloser, dest string) error {
convertedUIDMap, convertedGIDMap := convertRuntimeIDMaps(b.IDMappingOptions.UIDMap, b.IDMappingOptions.GIDMap)
- return archive.TarPath(convertedUIDMap, convertedGIDMap)
+ untarMappings := idtools.NewIDMappingsFromMaps(convertedUIDMap, convertedGIDMap)
+ options := &archive.TarOptions{
+ UIDMaps: untarMappings.UIDs(),
+ GIDMaps: untarMappings.GIDs(),
+ ChownOpts: chownOpts,
+ }
+ untar := chrootarchive.Untar
+ if hasher != nil {
+ originalUntar := untar
+ untar = func(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
+ return originalUntar(io.TeeReader(tarArchive, hasher), dest, options)
+ }
+ }
+ return func(tarArchive io.ReadCloser, dest string) error {
+ err := untar(tarArchive, dest, options)
+ if err2 := tarArchive.Close(); err2 != nil {
+ if err == nil {
+ err = err2
+ }
+ }
+ return err
+ }
}
// isRegistryBlocked checks if the named registry is marked as blocked
diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go
index 30afe8313..4736d7b77 100644
--- a/vendor/github.com/containers/buildah/util/util.go
+++ b/vendor/github.com/containers/buildah/util/util.go
@@ -106,13 +106,19 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
// Figure out the list of registries.
var registries []string
- searchRegistries, err := sysregistriesv2.FindUnqualifiedSearchRegistries(sc)
+ searchRegistries, err := sysregistriesv2.UnqualifiedSearchRegistries(sc)
if err != nil {
logrus.Debugf("unable to read configured registries to complete %q: %v", name, err)
+ searchRegistries = nil
}
for _, registry := range searchRegistries {
- if !registry.Blocked {
- registries = append(registries, registry.Location)
+ reg, err := sysregistriesv2.FindRegistry(sc, registry)
+ if err != nil {
+ logrus.Debugf("unable to read registry configuraitno for %#v: %v", registry, err)
+ continue
+ }
+ if reg == nil || !reg.Blocked {
+ registries = append(registries, registry)
}
}
searchRegistriesAreEmpty := len(registries) == 0
@@ -257,6 +263,36 @@ func StringInSlice(s string, slice []string) bool {
return false
}
+// GetContainerIDs uses ID mappings to compute the container-level IDs that will
+// correspond to a UID/GID pair on the host.
+func GetContainerIDs(uidmap, gidmap []specs.LinuxIDMapping, uid, gid uint32) (uint32, uint32, error) {
+ uidMapped := true
+ for _, m := range uidmap {
+ uidMapped = false
+ if uid >= m.HostID && uid < m.HostID+m.Size {
+ uid = (uid - m.HostID) + m.ContainerID
+ uidMapped = true
+ break
+ }
+ }
+ if !uidMapped {
+ return 0, 0, errors.Errorf("container uses ID mappings (%#v), but doesn't map UID %d", uidmap, uid)
+ }
+ gidMapped := true
+ for _, m := range gidmap {
+ gidMapped = false
+ if gid >= m.HostID && gid < m.HostID+m.Size {
+ gid = (gid - m.HostID) + m.ContainerID
+ gidMapped = true
+ break
+ }
+ }
+ if !gidMapped {
+ return 0, 0, errors.Errorf("container uses ID mappings (%#v), but doesn't map GID %d", gidmap, gid)
+ }
+ return uid, gid, nil
+}
+
// GetHostIDs uses ID mappings to compute the host-level IDs that will
// correspond to a UID/GID pair in the container.
func GetHostIDs(uidmap, gidmap []specs.LinuxIDMapping, uid, gid uint32) (uint32, uint32, error) {
@@ -270,7 +306,7 @@ func GetHostIDs(uidmap, gidmap []specs.LinuxIDMapping, uid, gid uint32) (uint32,
}
}
if !uidMapped {
- return 0, 0, errors.Errorf("container uses ID mappings, but doesn't map UID %d", uid)
+ return 0, 0, errors.Errorf("container uses ID mappings (%#v), but doesn't map UID %d", uidmap, uid)
}
gidMapped := true
for _, m := range gidmap {
@@ -282,7 +318,7 @@ func GetHostIDs(uidmap, gidmap []specs.LinuxIDMapping, uid, gid uint32) (uint32,
}
}
if !gidMapped {
- return 0, 0, errors.Errorf("container uses ID mappings, but doesn't map GID %d", gid)
+ return 0, 0, errors.Errorf("container uses ID mappings (%#v), but doesn't map GID %d", gidmap, gid)
}
return uid, gid, nil
}
diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf
index 0c982626a..88148947a 100644
--- a/vendor/github.com/containers/buildah/vendor.conf
+++ b/vendor/github.com/containers/buildah/vendor.conf
@@ -3,12 +3,12 @@ github.com/blang/semver v3.5.0
github.com/BurntSushi/toml v0.2.0
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-rc2
-github.com/containers/image 9467ac9cfd92c545aa389f22f27e552de053c0f2
+github.com/containers/image v2.0.0
github.com/cyphar/filepath-securejoin v0.2.1
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1
-github.com/containers/storage v1.12.7
+github.com/containers/storage v1.12.10
github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716
github.com/docker/docker 54dddadc7d5d89fe0be88f76979f6f6ab0dede83
github.com/docker/docker-credential-helpers v0.6.1
diff --git a/vendor/github.com/containers/image/docker/docker_image_src.go b/vendor/github.com/containers/image/docker/docker_image_src.go
index c8fdb407c..c43e6e7ca 100644
--- a/vendor/github.com/containers/image/docker/docker_image_src.go
+++ b/vendor/github.com/containers/image/docker/docker_image_src.go
@@ -29,44 +29,16 @@ type dockerImageSource struct {
cachedManifestMIMEType string // Only valid if cachedManifest != nil
}
-// newImageSource creates a new `ImageSource` for the specified image reference
-// `ref`.
-//
-// The following steps will be done during the instance creation:
-//
-// - Lookup the registry within the configured location in
-// `sys.SystemRegistriesConfPath`. If there is no configured registry available,
-// we fallback to the provided docker reference `ref`.
-//
-// - References which contain a configured prefix will be automatically rewritten
-// to the correct target reference. For example, if the configured
-// `prefix = "example.com/foo"`, `location = "example.com"` and the image will be
-// pulled from the ref `example.com/foo/image`, then the resulting pull will
-// effectively point to `example.com/image`.
-//
-// - If the rewritten reference succeeds, it will be used as the `dockerRef`
-// in the client. If the rewrite fails, the function immediately returns an error.
-//
-// - Each mirror will be used (in the configured order) to test the
-// availability of the image manifest on the remote location. For example,
-// if the manifest is not reachable due to connectivity issues, then the next
-// mirror will be tested instead. If no mirror is configured or contains the
-// target manifest, then the initial `ref` will be tested as fallback. The
-// creation of the new `dockerImageSource` only succeeds if a remote
-// location with the available manifest was found.
-//
-// A cleanup call to `.Close()` is needed if the caller is done using the returned
-// `ImageSource`.
+// newImageSource creates a new ImageSource for the specified image reference.
+// The caller must call .Close() on the returned ImageSource.
func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerReference) (*dockerImageSource, error) {
registry, err := sysregistriesv2.FindRegistry(sys, ref.ref.Name())
if err != nil {
return nil, errors.Wrapf(err, "error loading registries configuration")
}
-
if registry == nil {
- // No configuration was found for the provided reference, so we create
- // a fallback registry by hand to make the client creation below work
- // as intended.
+ // No configuration was found for the provided reference, so use the
+ // equivalent of a default configuration.
registry = &sysregistriesv2.Registry{
Endpoint: sysregistriesv2.Endpoint{
Location: ref.ref.String(),
@@ -76,18 +48,19 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
}
primaryDomain := reference.Domain(ref.ref)
- // Found the registry within the sysregistriesv2 configuration. Now we test
- // all endpoints for the manifest availability. If a working image source
- // was found, it will be used for all future pull actions.
+ // Check all endpoints for the manifest availability. If we find one that does
+ // contain the image, it will be used for all future pull actions. Always try the
+ // non-mirror original location last; this both transparently handles the case
+ // of no mirrors configured, and ensures we return the error encountered when
+ // acessing the upstream location if all endpoints fail.
manifestLoadErr := errors.New("Internal error: newImageSource returned without trying any endpoint")
- for _, endpoint := range append(registry.Mirrors, registry.Endpoint) {
- logrus.Debugf("Trying to pull %q from endpoint %q", ref.ref, endpoint.Location)
-
- newRef, err := endpoint.RewriteReference(ref.ref, registry.Prefix)
- if err != nil {
- return nil, err
- }
- dockerRef, err := newReference(newRef)
+ pullSources, err := registry.PullSourcesFromReference(ref.ref)
+ if err != nil {
+ return nil, err
+ }
+ for _, pullSource := range pullSources {
+ logrus.Debugf("Trying to pull %q", pullSource.Reference)
+ dockerRef, err := newReference(pullSource.Reference)
if err != nil {
return nil, err
}
@@ -104,7 +77,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
if err != nil {
return nil, err
}
- client.tlsClientConfig.InsecureSkipVerify = endpoint.Insecure
+ client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
testImageSource := &dockerImageSource{
ref: dockerRef,
diff --git a/vendor/github.com/containers/image/docker/reference/README.md b/vendor/github.com/containers/image/docker/reference/README.md
index 53a88de82..3c4d74eb4 100644
--- a/vendor/github.com/containers/image/docker/reference/README.md
+++ b/vendor/github.com/containers/image/docker/reference/README.md
@@ -1,2 +1,2 @@
-This is a copy of github.com/docker/distribution/reference as of commit fb0bebc4b64e3881cc52a2478d749845ed76d2a8,
+This is a copy of github.com/docker/distribution/reference as of commit 3226863cbcba6dbc2f6c83a37b28126c934af3f8,
except that ParseAnyReferenceWithSet has been removed to drop the dependency on github.com/docker/distribution/digestset. \ No newline at end of file
diff --git a/vendor/github.com/containers/image/docker/reference/normalize.go b/vendor/github.com/containers/image/docker/reference/normalize.go
index fcc436a39..6a86ec64f 100644
--- a/vendor/github.com/containers/image/docker/reference/normalize.go
+++ b/vendor/github.com/containers/image/docker/reference/normalize.go
@@ -55,6 +55,35 @@ func ParseNormalizedNamed(s string) (Named, error) {
return named, nil
}
+// ParseDockerRef normalizes the image reference following the docker convention. This is added
+// mainly for backward compatibility.
+// The reference returned can only be either tagged or digested. For reference contains both tag
+// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
+// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
+// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
+func ParseDockerRef(ref string) (Named, error) {
+ named, err := ParseNormalizedNamed(ref)
+ if err != nil {
+ return nil, err
+ }
+ if _, ok := named.(NamedTagged); ok {
+ if canonical, ok := named.(Canonical); ok {
+ // The reference is both tagged and digested, only
+ // return digested.
+ newNamed, err := WithName(canonical.Name())
+ if err != nil {
+ return nil, err
+ }
+ newCanonical, err := WithDigest(newNamed, canonical.Digest())
+ if err != nil {
+ return nil, err
+ }
+ return newCanonical, nil
+ }
+ }
+ return TagNameOnly(named), nil
+}
+
// splitDockerDomain splits a repository name to domain and remotename string.
// If no valid domain is found, the default domain is used. Repository name
// needs to be already validated before.
diff --git a/vendor/github.com/containers/image/docker/reference/reference.go b/vendor/github.com/containers/image/docker/reference/reference.go
index fd3510e9e..8c0c23b2f 100644
--- a/vendor/github.com/containers/image/docker/reference/reference.go
+++ b/vendor/github.com/containers/image/docker/reference/reference.go
@@ -15,7 +15,7 @@
// tag := /[\w][\w.-]{0,127}/
//
// digest := digest-algorithm ":" digest-hex
-// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
+// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]*
// digest-algorithm-separator := /[+.-_]/
// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
@@ -205,7 +205,7 @@ func Parse(s string) (Reference, error) {
var repo repository
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
- if nameMatch != nil && len(nameMatch) == 3 {
+ if len(nameMatch) == 3 {
repo.domain = nameMatch[1]
repo.path = nameMatch[2]
} else {
diff --git a/vendor/github.com/containers/image/docker/reference/regexp.go b/vendor/github.com/containers/image/docker/reference/regexp.go
index 405e995db..786034932 100644
--- a/vendor/github.com/containers/image/docker/reference/regexp.go
+++ b/vendor/github.com/containers/image/docker/reference/regexp.go
@@ -20,15 +20,15 @@ var (
optional(repeated(separatorRegexp, alphaNumericRegexp)))
// domainComponentRegexp restricts the registry domain component of a
- // repository name to start with a component as defined by domainRegexp
+ // repository name to start with a component as defined by DomainRegexp
// and followed by an optional port.
domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
- // domainRegexp defines the structure of potential domain components
+ // DomainRegexp defines the structure of potential domain components
// that may be part of image names. This is purposely a subset of what is
// allowed by DNS to ensure backwards compatibility with Docker image
// names.
- domainRegexp = expression(
+ DomainRegexp = expression(
domainComponentRegexp,
optional(repeated(literal(`.`), domainComponentRegexp)),
optional(literal(`:`), match(`[0-9]+`)))
@@ -51,14 +51,14 @@ var (
// regexp has capturing groups for the domain and name part omitting
// the separating forward slash from either.
NameRegexp = expression(
- optional(domainRegexp, literal(`/`)),
+ optional(DomainRegexp, literal(`/`)),
nameComponentRegexp,
optional(repeated(literal(`/`), nameComponentRegexp)))
// anchoredNameRegexp is used to parse a name value, capturing the
// domain and trailing components.
anchoredNameRegexp = anchored(
- optional(capture(domainRegexp), literal(`/`)),
+ optional(capture(DomainRegexp), literal(`/`)),
capture(nameComponentRegexp,
optional(repeated(literal(`/`), nameComponentRegexp))))
diff --git a/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go b/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go
index 99ae65774..361e6fc60 100644
--- a/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go
+++ b/vendor/github.com/containers/image/pkg/sysregistriesv2/system_registries_v2.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "regexp"
"strings"
"sync"
@@ -35,10 +36,10 @@ type Endpoint struct {
Insecure bool `toml:"insecure"`
}
-// RewriteReference will substitute the provided reference `prefix` to the
+// rewriteReference will substitute the provided reference `prefix` to the
// endpoints `location` from the `ref` and creates a new named reference from it.
// The function errors if the newly created reference is not parsable.
-func (e *Endpoint) RewriteReference(ref reference.Named, prefix string) (reference.Named, error) {
+func (e *Endpoint) rewriteReference(ref reference.Named, prefix string) (reference.Named, error) {
refString := ref.String()
if !refMatchesPrefix(refString, prefix) {
return nil, fmt.Errorf("invalid prefix '%v' for reference '%v'", prefix, refString)
@@ -61,8 +62,10 @@ type Registry struct {
Mirrors []Endpoint `toml:"mirror"`
// If true, pulling from the registry will be blocked.
Blocked bool `toml:"blocked"`
- // If true, the registry can be used when pulling an unqualified image.
- Search bool `toml:"unqualified-search"`
+ // If true, mirrors will only be used for digest pulls. Pulling images by
+ // tag can potentially yield different images, depending on which endpoint
+ // we pull from. Forcing digest-pulls for mirrors avoids that issue.
+ MirrorByDigestOnly bool `toml:"mirror-by-digest-only"`
// Prefix is used for matching images, and to translate one namespace to
// another. If `Prefix="example.com/bar"`, `location="example.com/foo/bar"`
// and we pull from "example.com/bar/myimage:latest", the image will
@@ -71,6 +74,41 @@ type Registry struct {
Prefix string `toml:"prefix"`
}
+// PullSource consists of an Endpoint and a Reference. Note that the reference is
+// rewritten according to the registries prefix and the Endpoint's location.
+type PullSource struct {
+ Endpoint Endpoint
+ Reference reference.Named
+}
+
+// PullSourcesFromReference returns a slice of PullSource's based on the passed
+// reference.
+func (r *Registry) PullSourcesFromReference(ref reference.Named) ([]PullSource, error) {
+ var endpoints []Endpoint
+
+ if r.MirrorByDigestOnly {
+ // Only use mirrors when the reference is a digest one.
+ if _, isDigested := ref.(reference.Canonical); isDigested {
+ endpoints = append(r.Mirrors, r.Endpoint)
+ } else {
+ endpoints = []Endpoint{r.Endpoint}
+ }
+ } else {
+ endpoints = append(r.Mirrors, r.Endpoint)
+ }
+
+ sources := []PullSource{}
+ for _, ep := range endpoints {
+ rewritten, err := ep.rewriteReference(ref, r.Prefix)
+ if err != nil {
+ return nil, err
+ }
+ sources = append(sources, PullSource{Endpoint: ep, Reference: rewritten})
+ }
+
+ return sources, nil
+}
+
// V1TOMLregistries is for backwards compatibility to sysregistries v1
type V1TOMLregistries struct {
Registries []string `toml:"registries"`
@@ -83,11 +121,35 @@ type V1TOMLConfig struct {
Block V1TOMLregistries `toml:"block"`
}
+// V1RegistriesConf is the sysregistries v1 configuration format.
+type V1RegistriesConf struct {
+ V1TOMLConfig `toml:"registries"`
+}
+
+// Nonempty returns true if config contains at least one configuration entry.
+func (config *V1RegistriesConf) Nonempty() bool {
+ return (len(config.V1TOMLConfig.Search.Registries) != 0 ||
+ len(config.V1TOMLConfig.Insecure.Registries) != 0 ||
+ len(config.V1TOMLConfig.Block.Registries) != 0)
+}
+
+// V2RegistriesConf is the sysregistries v2 configuration format.
+type V2RegistriesConf struct {
+ Registries []Registry `toml:"registry"`
+ // An array of host[:port] (not prefix!) entries to use for resolving unqualified image references
+ UnqualifiedSearchRegistries []string `toml:"unqualified-search-registries"`
+}
+
+// Nonempty returns true if config contains at least one configuration entry.
+func (config *V2RegistriesConf) Nonempty() bool {
+ return (len(config.Registries) != 0 ||
+ len(config.UnqualifiedSearchRegistries) != 0)
+}
+
// tomlConfig is the data type used to unmarshal the toml config.
type tomlConfig struct {
- Registries []Registry `toml:"registry"`
- // backwards compatability to sysregistries v1
- V1TOMLConfig `toml:"registries"`
+ V2RegistriesConf
+ V1RegistriesConf // for backwards compatibility with sysregistries v1
}
// InvalidRegistries represents an invalid registry configurations. An example
@@ -120,12 +182,10 @@ func parseLocation(input string) (string, error) {
return trimmed, nil
}
-// getV1Registries transforms v1 registries in the config into an array of v2
-// registries of type Registry.
-func getV1Registries(config *tomlConfig) ([]Registry, error) {
+// ConvertToV2 returns a v2 config corresponding to a v1 one.
+func (config *V1RegistriesConf) ConvertToV2() (*V2RegistriesConf, error) {
regMap := make(map[string]*Registry)
- // We must preserve the order of config.V1Registries.Search.Registries at least. The order of the
- // other registries is not really important, but make it deterministic (the same for the same config file)
+ // The order of the registries is not really important, but make it deterministic (the same for the same config file)
// to minimize behavior inconsistency and not contribute to difficult-to-reproduce situations.
registryOrder := []string{}
@@ -148,15 +208,6 @@ func getV1Registries(config *tomlConfig) ([]Registry, error) {
return reg, nil
}
- // Note: config.V1Registries.Search needs to be processed first to ensure registryOrder is populated in the right order
- // if one of the search registries is also in one of the other lists.
- for _, search := range config.V1TOMLConfig.Search.Registries {
- reg, err := getRegistry(search)
- if err != nil {
- return nil, err
- }
- reg.Search = true
- }
for _, blocked := range config.V1TOMLConfig.Block.Registries {
reg, err := getRegistry(blocked)
if err != nil {
@@ -172,28 +223,31 @@ func getV1Registries(config *tomlConfig) ([]Registry, error) {
reg.Insecure = true
}
- registries := []Registry{}
+ res := &V2RegistriesConf{
+ UnqualifiedSearchRegistries: config.V1TOMLConfig.Search.Registries,
+ }
for _, location := range registryOrder {
reg := regMap[location]
- registries = append(registries, *reg)
+ res.Registries = append(res.Registries, *reg)
}
- return registries, nil
+ return res, nil
}
-// postProcessRegistries checks the consistency of all registries (e.g., set
-// the Prefix to Location if not set) and applies conflict checks. It returns an
-// array of cleaned registries and error in case of conflicts.
-func postProcessRegistries(regs []Registry) ([]Registry, error) {
- var registries []Registry
- regMap := make(map[string][]Registry)
+// anchoredDomainRegexp is an internal implementation detail of postProcess, defining the valid values of elements of UnqualifiedSearchRegistries.
+var anchoredDomainRegexp = regexp.MustCompile("^" + reference.DomainRegexp.String() + "$")
- for _, reg := range regs {
- var err error
+// postProcess checks the consistency of all the configuration, looks for conflicts,
+// and normalizes the configuration (e.g., sets the Prefix to Location if not set).
+func (config *V2RegistriesConf) postProcess() error {
+ regMap := make(map[string][]*Registry)
+ for i := range config.Registries {
+ reg := &config.Registries[i]
// make sure Location and Prefix are valid
+ var err error
reg.Location, err = parseLocation(reg.Location)
if err != nil {
- return nil, err
+ return err
}
if reg.Prefix == "" {
@@ -201,7 +255,7 @@ func postProcessRegistries(regs []Registry) ([]Registry, error) {
} else {
reg.Prefix, err = parseLocation(reg.Prefix)
if err != nil {
- return nil, err
+ return err
}
}
@@ -209,10 +263,9 @@ func postProcessRegistries(regs []Registry) ([]Registry, error) {
for _, mir := range reg.Mirrors {
mir.Location, err = parseLocation(mir.Location)
if err != nil {
- return nil, err
+ return err
}
}
- registries = append(registries, reg)
regMap[reg.Location] = append(regMap[reg.Location], reg)
}
@@ -222,22 +275,32 @@ func postProcessRegistries(regs []Registry) ([]Registry, error) {
//
// Note: we need to iterate over the registries array to ensure a
// deterministic behavior which is not guaranteed by maps.
- for _, reg := range registries {
+ for _, reg := range config.Registries {
others, _ := regMap[reg.Location]
for _, other := range others {
if reg.Insecure != other.Insecure {
msg := fmt.Sprintf("registry '%s' is defined multiple times with conflicting 'insecure' setting", reg.Location)
-
- return nil, &InvalidRegistries{s: msg}
+ return &InvalidRegistries{s: msg}
}
if reg.Blocked != other.Blocked {
msg := fmt.Sprintf("registry '%s' is defined multiple times with conflicting 'blocked' setting", reg.Location)
- return nil, &InvalidRegistries{s: msg}
+ return &InvalidRegistries{s: msg}
}
}
}
- return registries, nil
+ for i := range config.UnqualifiedSearchRegistries {
+ registry, err := parseLocation(config.UnqualifiedSearchRegistries[i])
+ if err != nil {
+ return err
+ }
+ if !anchoredDomainRegexp.MatchString(registry) {
+ return &InvalidRegistries{fmt.Sprintf("Invalid unqualified-search-registries entry %#v", registry)}
+ }
+ config.UnqualifiedSearchRegistries[i] = registry
+ }
+
+ return nil
}
// getConfigPath returns the system-registries config path if specified.
@@ -260,7 +323,7 @@ var configMutex = sync.Mutex{}
// configCache caches already loaded configs with config paths as keys and is
// used to avoid redudantly parsing configs. Concurrent accesses to the cache
// are synchronized via configMutex.
-var configCache = make(map[string][]Registry)
+var configCache = make(map[string]*V2RegistriesConf)
// InvalidateCache invalidates the registry cache. This function is meant to be
// used for long-running processes that need to reload potential changes made to
@@ -268,20 +331,18 @@ var configCache = make(map[string][]Registry)
func InvalidateCache() {
configMutex.Lock()
defer configMutex.Unlock()
- configCache = make(map[string][]Registry)
+ configCache = make(map[string]*V2RegistriesConf)
}
-// GetRegistries loads and returns the registries specified in the config.
-// Note the parsed content of registry config files is cached. For reloading,
-// use `InvalidateCache` and re-call `GetRegistries`.
-func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
+// getConfig returns the config object corresponding to ctx, loading it if it is not yet cached.
+func getConfig(ctx *types.SystemContext) (*V2RegistriesConf, error) {
configPath := getConfigPath(ctx)
configMutex.Lock()
defer configMutex.Unlock()
// if the config has already been loaded, return the cached registries
- if registries, inCache := configCache[configPath]; inCache {
- return registries, nil
+ if config, inCache := configCache[configPath]; inCache {
+ return config, nil
}
// load the config
@@ -292,51 +353,53 @@ func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
// isn't set. Note: if ctx.SystemRegistriesConfPath points to
// the default config, we will still return an error.
if os.IsNotExist(err) && (ctx == nil || ctx.SystemRegistriesConfPath == "") {
- return []Registry{}, nil
+ return &V2RegistriesConf{Registries: []Registry{}}, nil
}
return nil, err
}
- registries := config.Registries
+ v2Config := &config.V2RegistriesConf
// backwards compatibility for v1 configs
- v1Registries, err := getV1Registries(config)
- if err != nil {
- return nil, err
- }
- if len(v1Registries) > 0 {
- if len(registries) > 0 {
+ if config.V1RegistriesConf.Nonempty() {
+ if config.V2RegistriesConf.Nonempty() {
return nil, &InvalidRegistries{s: "mixing sysregistry v1/v2 is not supported"}
}
- registries = v1Registries
+ v2, err := config.V1RegistriesConf.ConvertToV2()
+ if err != nil {
+ return nil, err
+ }
+ v2Config = v2
}
- registries, err = postProcessRegistries(registries)
- if err != nil {
+ if err := v2Config.postProcess(); err != nil {
return nil, err
}
// populate the cache
- configCache[configPath] = registries
-
- return registries, err
+ configCache[configPath] = v2Config
+ return v2Config, nil
}
-// FindUnqualifiedSearchRegistries returns all registries that are configured
-// for unqualified image search (i.e., with Registry.Search == true).
-func FindUnqualifiedSearchRegistries(ctx *types.SystemContext) ([]Registry, error) {
- registries, err := GetRegistries(ctx)
+// GetRegistries loads and returns the registries specified in the config.
+// Note the parsed content of registry config files is cached. For reloading,
+// use `InvalidateCache` and re-call `GetRegistries`.
+func GetRegistries(ctx *types.SystemContext) ([]Registry, error) {
+ config, err := getConfig(ctx)
if err != nil {
return nil, err
}
+ return config.Registries, nil
+}
- unqualified := []Registry{}
- for _, reg := range registries {
- if reg.Search {
- unqualified = append(unqualified, reg)
- }
+// UnqualifiedSearchRegistries returns a list of host[:port] entries to try
+// for unqualified image search, in the returned order)
+func UnqualifiedSearchRegistries(ctx *types.SystemContext) ([]string, error) {
+ config, err := getConfig(ctx)
+ if err != nil {
+ return nil, err
}
- return unqualified, nil
+ return config.UnqualifiedSearchRegistries, nil
}
// refMatchesPrefix returns true iff ref,
@@ -371,14 +434,14 @@ func refMatchesPrefix(ref, prefix string) bool {
// — note that this requires the name to start with an explicit hostname!).
// If no Registry prefixes the image, nil is returned.
func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
- registries, err := GetRegistries(ctx)
+ config, err := getConfig(ctx)
if err != nil {
return nil, err
}
reg := Registry{}
prefixLen := 0
- for _, r := range registries {
+ for _, r := range config.Registries {
if refMatchesPrefix(ref, r.Prefix) {
length := len(r.Prefix)
if length > prefixLen {
@@ -393,21 +456,12 @@ func FindRegistry(ctx *types.SystemContext, ref string) (*Registry, error) {
return nil, nil
}
-// Reads the global registry file from the filesystem. Returns a byte array.
-func readRegistryConf(configPath string) ([]byte, error) {
- configBytes, err := ioutil.ReadFile(configPath)
- return configBytes, err
-}
-
-// Used in unittests to parse custom configs without a types.SystemContext.
-var readConf = readRegistryConf
-
// Loads the registry configuration file from the filesystem and then unmarshals
// it. Returns the unmarshalled object.
func loadRegistryConf(configPath string) (*tomlConfig, error) {
config := &tomlConfig{}
- configBytes, err := readConf(configPath)
+ configBytes, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/version/version.go b/vendor/github.com/containers/image/version/version.go
index 184274736..62b2c8bc5 100644
--- a/vendor/github.com/containers/image/version/version.go
+++ b/vendor/github.com/containers/image/version/version.go
@@ -4,14 +4,14 @@ import "fmt"
const (
// VersionMajor is for an API incompatible changes
- VersionMajor = 1
+ VersionMajor = 2
// VersionMinor is for functionality in a backwards-compatible manner
- VersionMinor = 7
+ VersionMinor = 0
// VersionPatch is for backwards-compatible bug fixes
VersionPatch = 0
// VersionDev indicates development branch. Releases will be empty string.
- VersionDev = "-dev"
+ VersionDev = ""
)
// Version is the specification version that the package types support.
diff --git a/version/version.go b/version/version.go
index c3917c016..3dbf4768d 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.4.1-dev"
+const Version = "1.4.3-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility