summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml70
-rw-r--r--.gitignore3
-rw-r--r--Makefile106
-rw-r--r--README.md3
-rw-r--r--cmd/podman/cliconfig/config.go1
-rw-r--r--cmd/podman/sign.go19
-rw-r--r--completions/bash/podman1
-rw-r--r--contrib/cirrus/99-do-not-use-google-subnets.conflist21
-rwxr-xr-xcontrib/cirrus/build_release.sh30
-rwxr-xr-xcontrib/cirrus/cache_release_archive.sh140
-rwxr-xr-xcontrib/cirrus/cirrus_yaml_test.py43
-rwxr-xr-xcontrib/cirrus/integration_test.sh4
-rw-r--r--contrib/cirrus/lib.sh20
-rwxr-xr-xcontrib/cirrus/setup_environment.sh16
l---------contrib/cirrus/uncache_release_archives.sh1
-rwxr-xr-xcontrib/cirrus/unit_test.sh4
-rwxr-xr-xcontrib/cirrus/upload_release_archive.sh52
-rw-r--r--contrib/imgts/lib_entrypoint.sh15
-rw-r--r--contrib/upldrel/Dockerfile9
-rw-r--r--contrib/upldrel/README.md9
-rwxr-xr-xcontrib/upldrel/entrypoint.sh62
-rw-r--r--docs/podman-image-sign.1.md15
-rwxr-xr-xhack/get_release_info.sh54
-rw-r--r--libpod/boltdb_state.go46
-rw-r--r--libpod/boltdb_state_internal.go7
-rw-r--r--libpod/in_memory_state.go20
-rw-r--r--libpod/runtime.go4
-rw-r--r--libpod/runtime_ctr.go15
-rw-r--r--libpod/runtime_renumber.go17
-rw-r--r--libpod/runtime_volume.go4
-rw-r--r--libpod/runtime_volume_linux.go37
-rw-r--r--libpod/state.go10
-rw-r--r--libpod/volume.go36
-rw-r--r--test/e2e/run_volume_test.go8
-rw-r--r--test/e2e/systemd_test.go48
35 files changed, 626 insertions, 324 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index f49b1d312..8d915fbfe 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -62,6 +62,10 @@ env:
GCE_SSH_USERNAME: cirrus-ci
# Name where this repositories cloud resources are located
GCP_PROJECT_ID: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
+ RELEASE_GCPJSON: ENCRYPTED[789d8f7e9a5972ce350fd8e60f1032ccbf4a35c3938b604774b711aad280e12c21faf10e25af1e0ba33597ffb9e39e46]
+ RELEASE_GCPNAME: ENCRYPTED[417d50488a4bd197bcc925ba6574de5823b97e68db1a17e3a5fde4bcf26576987345e75f8d9ea1c15a156b4612c072a1]
+ RELEASE_GCPROJECT: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
+
# Default VM to use unless set or modified by task
@@ -339,9 +343,8 @@ testing_task:
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
- cache_release_archive_script: >-
- [[ "$TEST_REMOTE_CLIENT" == "false" ]] || \
- $SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}
+ build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
+ upload_release_archive_script: '$SCRIPT_BASE/upload_release_archive.sh |& ${TIMESTAMP}'
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
@@ -379,9 +382,6 @@ testing_crun_task:
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
- cache_release_archive_script: >-
- [[ "$TEST_REMOTE_CLIENT" == "false" ]] || \
- $SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
@@ -462,14 +462,15 @@ special_testing_cross_task:
env:
matrix:
- SPECIALMODE: 'windows' # See docs
- SPECIALMODE: 'darwin'
+ CROSS_PLATFORM: 'windows'
+ CROSS_PLATFORM: 'darwin'
timeout_in: 20m
networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
- cache_release_archive_script: '$SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}'
+ build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
+ upload_release_archive_script: '$SCRIPT_BASE/upload_release_archive.sh |& ${TIMESTAMP}'
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
@@ -618,6 +619,9 @@ verify_test_built_images_task:
integration_test_script: >-
[[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}
+ build_release_script: >-
+ [[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
+ '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
system_test_script: >-
[[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}
@@ -632,7 +636,7 @@ success_task:
# it blocks PRs from merging if a depends_on task fails
only_if: $CIRRUS_BRANCH != $DEST_BRANCH
- # ignores any dependent task conditions, include everything except 'release'
+ # ignores any dependent task conditions
depends_on:
- "gating"
- "vendor"
@@ -663,49 +667,3 @@ success_task:
memory: 1
success_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/success.sh |& ${TIMESTAMP}'
-
-
-release_task:
-
- # Never do this when building images
- only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\*\*\*\s*CIRRUS:\s*TEST\s*IMAGES\s*\*\*\*.*'
-
- # TODO: Uncomment both to not affect pass/fail status of entire job?
- # allow_failures: $CI == "true"
- # skip_notifications: $CI == "true"
-
- # Must include everything (YAML anchor/alias cannot be used here)
- depends_on:
- - "gating"
- - "vendor"
- - "varlink_api"
- - "build_each_commit"
- - "build_without_cgo"
- - "meta"
- - "image_prune"
- - "testing"
- - "testing_crun"
- - "special_testing_rootless"
- - "special_testing_in_podman"
- - "special_testing_cgroupv2"
- - "special_testing_cross"
- - "special_testing_endpoint"
- - "test_build_cache_images"
- - "test_building_snap"
- - "verify_test_built_images"
- - "success"
-
- gce_instance:
- image_name: "${IMAGE_BUILDER_CACHE_IMAGE_NAME}"
-
- timeout_in: 30m
-
- env:
- GCPJSON: ENCRYPTED[789d8f7e9a5972ce350fd8e60f1032ccbf4a35c3938b604774b711aad280e12c21faf10e25af1e0ba33597ffb9e39e46]
- GCPNAME: ENCRYPTED[417d50488a4bd197bcc925ba6574de5823b97e68db1a17e3a5fde4bcf26576987345e75f8d9ea1c15a156b4612c072a1]
- GCPROJECT: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
-
- uncache_release_archives_script: '$SCRIPT_BASE/uncache_release_archives.sh |& ${TIMESTAMP}'
-
- on_failure:
- failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
diff --git a/.gitignore b/.gitignore
index 2d984cb5a..d3e56ecdf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ __pycache__
/cmd/podman/varlink/iopodman.go
.gopathok
test/e2e/e2e.coverprofile
-/podman*zip
+release.txt
+podman-remote*.zip
podman*.tar.gz
.idea*
diff --git a/Makefile b/Makefile
index 82a24306d..1a3d03f8a 100644
--- a/Makefile
+++ b/Makefile
@@ -81,13 +81,12 @@ LIBSECCOMP_COMMIT := release-2.3
# caller may override in special circumstances if needed.
GINKGOTIMEOUT ?= -timeout=90m
-RELEASE_VERSION ?= $(shell git fetch --tags && git describe HEAD 2> /dev/null)
-RELEASE_NUMBER ?= $(shell echo $(RELEASE_VERSION) | sed 's/-.*//')
-RELEASE_DIST ?= $(shell ( source /etc/os-release; echo $$ID ))
-RELEASE_DIST_VER ?= $(shell ( source /etc/os-release; echo $$VERSION_ID | cut -d '.' -f 1))
-RELEASE_ARCH ?= $(shell go env GOARCH 2> /dev/null)
-RELEASE_BASENAME := $(shell basename $(PROJECT))
-
+RELEASE_VERSION ?= $(shell hack/get_release_info.sh VERSION)
+RELEASE_NUMBER ?= $(shell hack/get_release_info.sh NUMBER)
+RELEASE_DIST ?= $(shell hack/get_release_info.sh DIST)
+RELEASE_DIST_VER ?= $(shell hack/get_release_info.sh DIST_VER)
+RELEASE_ARCH ?= $(shell hack/get_release_info.sh ARCH)
+RELEASE_BASENAME := $(shell hack/get_release_info.sh BASENAME)
# If GOPATH not specified, use one in the local directory
ifeq ($(GOPATH),)
@@ -164,11 +163,9 @@ podman: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman
podman-remote: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on remote environment
$(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS) remoteclient" -o bin/$@ $(PROJECT)/cmd/podman
-podman-remote-darwin: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on remote OSX environment
- CGO_ENABLED=0 GOOS=darwin $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@ $(PROJECT)/cmd/podman
-
-podman-remote-windows: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman for a remote windows environment
- CGO_ENABLED=0 GOOS=windows $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@.exe $(PROJECT)/cmd/podman
+podman-remote-%: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build podman for a specific GOOS
+ $(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe"))
+ CGO_ENABLED=0 GOOS=$* $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@$(BINSFX) $(PROJECT)/cmd/podman
local-cross: $(CROSS_BUILD_TARGETS) ## Cross local compilation
@@ -182,8 +179,9 @@ clean: ## Clean artifacts
rm -rf \
.gopathok \
_output \
- podman*.zip \
- podman*.tar.gz \
+ release.txt
+ $(wildcard podman-remote*.zip) \
+ $(wildcard podman*.tar.gz) \
bin \
build \
docs/remote \
@@ -300,23 +298,6 @@ vagrant-check:
binaries: varlink_generate podman podman-remote ## Build podman
-# Zip archives are supported on all platforms + allows embedding metadata
-podman.zip: binaries docs
- $(eval TMPDIR := $(shell mktemp -d -p '' $@_XXXX))
- test -n "$(TMPDIR)"
- $(MAKE) install "DESTDIR=$(TMPDIR)" "PREFIX=$(TMPDIR)/usr"
- # Encoded RELEASE_INFO format depended upon by CI tooling
- # X-RELEASE-INFO format depended upon by CI tooling
- cd "$(TMPDIR)" && echo \
- "X-RELEASE-INFO: $(RELEASE_BASENAME) $(RELEASE_VERSION) $(RELEASE_DIST) $(RELEASE_DIST_VER) $(RELEASE_ARCH)" | \
- zip --recurse-paths --archive-comment "$(CURDIR)/$@" "./"
- -rm -rf "$(TMPDIR)"
-
-podman-remote-%.zip: podman-remote-%
- # Don't label darwin/windows cros-compiles with local distribution & version
- echo "X-RELEASE-INFO: podman-remote $(RELEASE_VERSION) $* cc $(RELEASE_ARCH)" | \
- zip --archive-comment "$(CURDIR)/$@" ./bin/$<*
-
install.catatonit:
./hack/install_catatonit.sh
@@ -333,19 +314,58 @@ docs: $(MANPAGES) ## Generate documentation
install-podman-remote-docs: docs
@(cd docs; ./podman-remote.sh ./remote)
+# When publishing releases include critical build-time details
+.PHONY: release.txt
+release.txt:
+ # X-RELEASE-INFO format depended upon by automated tooling
+ echo -n "X-RELEASE-INFO:" > "$@"
+ for field in "$(RELEASE_BASENAME)" "$(RELEASE_VERSION)" \
+ "$(RELEASE_DIST)" "$(RELEASE_DIST_VER)" "$(RELEASE_ARCH)"; do \
+ echo -n " $$field"; done >> "$@"
+ echo "" >> "$@"
+
+podman-$(RELEASE_NUMBER).tar.gz: binaries docs release.txt
+ $(eval TMPDIR := $(shell mktemp -d -p '' podman_XXXX))
+ $(eval SUBDIR := podman-$(RELEASE_NUMBER))
+ mkdir -p "$(TMPDIR)/$(SUBDIR)"
+ $(MAKE) install.bin install.man install.cni install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr"
+ # release.txt location and content depended upon by automated tooling
+ cp release.txt "$(TMPDIR)/"
+ tar -czvf $@ --xattrs -C "$(TMPDIR)" "./release.txt" "./$(SUBDIR)"
+ -rm -rf "$(TMPDIR)"
+
+# Must call make in-line: Dependency-spec. w/ wild-card also consumes variable value.
+podman-remote-$(RELEASE_NUMBER)-%.zip:
+ $(MAKE) podman-remote-$* install-podman-remote-docs release.txt \
+ RELEASE_BASENAME=$(shell hack/get_release_info.sh REMOTENAME) \
+ RELEASE_DIST=$* RELEASE_DIST_VER="-"
+ $(eval TMPDIR := $(shell mktemp -d -p '' $podman_remote_XXXX))
+ $(eval SUBDIR := podman-$(RELEASE_VERSION))
+ $(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe"))
+ mkdir -p "$(TMPDIR)/$(SUBDIR)"
+ # release.txt location and content depended upon by automated tooling
+ cp release.txt "$(TMPDIR)/"
+ cp ./bin/podman-remote-$*$(BINSFX) "$(TMPDIR)/$(SUBDIR)/podman$(BINSFX)"
+ cp -r ./docs/remote "$(TMPDIR)/$(SUBDIR)/docs/"
+ $(eval DOCFILE := $(TMPDIR)/$(SUBDIR)/docs/podman.1)
+ cp docs/podman-remote.1 "$(DOCFILE)"
+ sed -i 's/podman\\*-remote/podman/g' "$(DOCFILE)"
+ sed -i 's/Podman\\*-remote/Podman\ for\ $*/g' "$(DOCFILE)"
+ sed -i 's/podman\.conf/podman\-remote\.conf/g' "$(DOCFILE)"
+ sed -i 's/A\ remote\ CLI\ for\ Podman\:\ //g' "$(DOCFILE)"
+ cd "$(TMPDIR)" && \
+ zip --recurse-paths "$(CURDIR)/$@" "./release.txt" "./"
+ -rm -rf "$(TMPDIR)"
+
+.PHONY: podman-release
+podman-release:
+ rm -f release.txt
+ $(MAKE) podman-$(RELEASE_NUMBER).tar.gz
-brew-pkg: install-podman-remote-docs podman-remote-darwin
- @mkdir -p ./brew
- @cp ./bin/podman-remote-darwin ./brew/podman
- @cp -r ./docs/remote ./brew/docs/
- @cp docs/podman-remote.1 ./brew/docs/podman.1
- @cp docs/podman-remote.conf.5 ./brew/docs/podman-remote.conf.5
- @sed -i 's/podman\\*-remote/podman/g' ./brew/docs/podman.1
- @sed -i 's/Podman\\*-remote/Podman\ for\ Mac/g' ./brew/docs/podman.1
- @sed -i 's/podman\.conf/podman\-remote\.conf/g' ./brew/docs/podman.1
- @sed -i 's/A\ remote\ CLI\ for\ Podman\:\ //g' ./brew/docs/podman.1
- tar -czvf podman-${RELEASE_NUMBER}.tar.gz ./brew
- @rm -rf ./brew
+.PHONY: podman-remote-%-release
+podman-remote-%-release:
+ rm -f release.txt
+ $(MAKE) podman-remote-$(RELEASE_NUMBER)-$*.zip
docker-docs: docs
(cd docs; ./dckrman.sh *.1)
diff --git a/README.md b/README.md
index f7c592671..34ed6d9e1 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,9 @@ popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`
* [Latest Version: 1.4.4](https://github.com/containers/libpod/releases/latest)
* [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master)
* [GoDoc: ![GoDoc](https://godoc.org/github.com/containers/libpod/libpod?status.svg)](https://godoc.org/github.com/containers/libpod/libpod)
+* Automated continuous release downloads (including remote-client):
+ * Master Branch: [https://storage.cloud.google.com/libpod-master-releases/](https://storage.cloud.google.com/libpod-master-releases/)
+ * Pull-requests: [https://storage.cloud.google.com/libpod-pr-releases/](https://storage.cloud.google.com/libpod-pr-releases/)
## Overview and scope
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 9bc47333d..98e7aed4b 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -509,6 +509,7 @@ type SignValues struct {
PodmanCommand
Directory string
SignBy string
+ CertDir string
}
type StartValues struct {
diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go
index de289047a..63ba9b904 100644
--- a/cmd/podman/sign.go
+++ b/cmd/podman/sign.go
@@ -46,7 +46,7 @@ func init() {
flags := signCommand.Flags()
flags.StringVarP(&signCommand.Directory, "directory", "d", "", "Define an alternate directory to store signatures")
flags.StringVar(&signCommand.SignBy, "sign-by", "", "Name of the signing key")
-
+ flags.StringVar(&signCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
}
// SignatureStoreDir defines default directory to store signatures
@@ -76,6 +76,13 @@ func signCmd(c *cliconfig.SignValues) error {
}
}
+ sc := runtime.SystemContext()
+ sc.DockerCertPath = c.CertDir
+
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerCertPath: c.CertDir,
+ }
+
mech, err := signature.NewGPGSigningMechanism()
if err != nil {
return errors.Wrap(err, "error initializing GPG")
@@ -85,7 +92,7 @@ func signCmd(c *cliconfig.SignValues) error {
return errors.Wrap(err, "signing is not supported")
}
- systemRegistriesDirPath := trust.RegistriesDirPath(runtime.SystemContext())
+ systemRegistriesDirPath := trust.RegistriesDirPath(sc)
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
return errors.Wrapf(err, "error reading registry configuration")
@@ -96,10 +103,14 @@ func signCmd(c *cliconfig.SignValues) error {
if err != nil {
return errors.Wrapf(err, "error parsing image name")
}
- rawSource, err := srcRef.NewImageSource(getContext(), runtime.SystemContext())
+ rawSource, err := srcRef.NewImageSource(getContext(), sc)
if err != nil {
return errors.Wrapf(err, "error getting image source")
}
+ err = rawSource.Close()
+ if err != nil {
+ logrus.Errorf("unable to close new image source %q", err)
+ }
manifest, _, err := rawSource.GetManifest(getContext(), nil)
if err != nil {
return errors.Wrapf(err, "error getting manifest")
@@ -114,7 +125,7 @@ func signCmd(c *cliconfig.SignValues) error {
if err != nil {
return err
}
- newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing)
+ newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing)
if err != nil {
return errors.Wrapf(err, "error pulling image %s", signimage)
}
diff --git a/completions/bash/podman b/completions/bash/podman
index 7280f4040..e6ffb135f 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -2669,6 +2669,7 @@ _podman_container_runlabel() {
_podman_image_sign() {
local options_with_args="
+ --cert-dir
-d
--directory
--sign-by
diff --git a/contrib/cirrus/99-do-not-use-google-subnets.conflist b/contrib/cirrus/99-do-not-use-google-subnets.conflist
new file mode 100644
index 000000000..e9ab638ed
--- /dev/null
+++ b/contrib/cirrus/99-do-not-use-google-subnets.conflist
@@ -0,0 +1,21 @@
+{
+ "cniVersion": "0.4.0",
+ "name": "do-not-use-google-subnets",
+ "plugins": [
+ {
+ "type": "bridge",
+ "name": "do-not-use-google-subnets",
+ "bridge": "do-not-use-google-subnets",
+ "ipam": {
+ "type": "host-local",
+ "ranges": [
+ [
+ {
+ "subnet": "10.128.0.0/9"
+ }
+ ]
+ ]
+ }
+ }
+ ]
+}
diff --git a/contrib/cirrus/build_release.sh b/contrib/cirrus/build_release.sh
new file mode 100755
index 000000000..287643f47
--- /dev/null
+++ b/contrib/cirrus/build_release.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+source $(dirname $0)/lib.sh
+
+req_env_var TEST_REMOTE_CLIENT OS_RELEASE_ID GOSRC
+
+cd $GOSRC
+
+if [[ "$TEST_REMOTE_CLIENT" == "true" ]] && [[ -z "$CROSS_PLATFORM" ]]
+then
+ CROSS_PLATFORM=linux
+fi
+
+if [[ -n "$CROSS_PLATFORM" ]]
+then
+ echo "Compiling podman-remote release archive for ${CROSS_PLATFORM}"
+ case "$CROSS_PLATFORM" in
+ linux) ;&
+ windows) ;&
+ darwin)
+ make podman-remote-${CROSS_PLATFORM}-release
+ ;;
+ *)
+ die 1 "Unknown/unsupported cross-compile platform '$CROSS_PLATFORM'"
+ ;;
+ esac
+else
+ echo "Compiling release archive for $OS_RELEASE_ID"
+ make podman-release
+fi
diff --git a/contrib/cirrus/cache_release_archive.sh b/contrib/cirrus/cache_release_archive.sh
deleted file mode 100755
index 2365f7593..000000000
--- a/contrib/cirrus/cache_release_archive.sh
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/bin/bash
-
-set -eo pipefail
-
-source $(dirname $0)/lib.sh
-
-req_env_var GOSRC
-
-RELEASE_ARCHIVE_NAMES=""
-
-handle_archive() { # Assumed to be called with set +e
- TASK_NUMBER=$1
- PR_OR_BRANCH=$2
- CACHE_URL=$3
- ARCHIVE_NAME="$(basename $CACHE_URL)"
- req_env_var TASK_NUMBER PR_OR_BRANCH CACHE_URL ARCHIVE_NAME
-
- cd /tmp
- curl -sO "$CACHE_URL" || return $(warn 0 "Couldn't download file, skipping.")
- [[ -r "/tmp/$ARCHIVE_NAME" ]] || return $(warn 0 "Unreadable archive '/tmp/$ARCHIVE_NAME', skipping.")
-
- ZIPCOMMENT=$(unzip -qqz "$ARCHIVE_NAME" 2>/dev/null) # noisy bugger
- if [[ "$?" -ne "0" ]] || [[ -z "$ZIPCOMMENT" ]]
- then
- return $(warn 0 "Could not unzip metadata from downloaded '/tmp/$ARCHIVE_NAME', skipping.")
- fi
-
- RELEASE_INFO=$(echo "$ZIPCOMMENT" | grep -m 1 'X-RELEASE-INFO:' | sed -r -e 's/X-RELEASE-INFO:\s*(.+)/\1/')
- if [[ "$?" -ne "0" ]] || [[ -z "$RELEASE_INFO" ]]
- then
- return $(warn 0 "Metadata empty or invalid: '$ZIPCOMMENT', skipping.")
- fi
-
- # e.g. libpod v1.3.1-166-g60df124e fedora 29 amd64
- # or libpod v1.3.1-166-g60df124e amd64
- FIELDS="RELEASE_BASENAME RELEASE_VERSION RELEASE_DIST RELEASE_DIST_VER RELEASE_ARCH"
- read $FIELDS <<< $RELEASE_INFO
- for f in $FIELDS
- do
- [[ -n "${!f}" ]] || return $(warn 0 "Expecting $f to be non-empty in metadata: '$RELEASE_INFO', skipping.")
- done
-
- echo -n "Preparing $RELEASE_BASENAME archive: "
- # Drop version number to enable "latest" representation
- # (version available w/in zip-file comment)
- RELEASE_ARCHIVE_NAME="${RELEASE_BASENAME}-${PR_OR_BRANCH}-${RELEASE_DIST}-${RELEASE_DIST_VER}-${RELEASE_ARCH}.zip"
- # Allow uploading all gathered files in parallel, later with gsutil.
- mv -v "$ARCHIVE_NAME" "/$RELEASE_ARCHIVE_NAME"
- RELEASE_ARCHIVE_NAMES="$RELEASE_ARCHIVE_NAMES $RELEASE_ARCHIVE_NAME"
-}
-
-make_release() {
- ARCHIVE_NAME="$1"
- req_env_var ARCHIVE_NAME
-
- # There's no actual testing of windows/darwin targets yet
- # but we still want to cross-compile and publish binaries
- if [[ "$SPECIALMODE" == "windows" ]] || [[ "$SPECIALMODE" == "darwin" ]]
- then
- RELFILE="podman-remote-${SPECIALMODE}.zip"
- elif [[ "$SPECIALMODE" == "none" ]]
- then
- RELFILE="podman.zip"
- else
- die 55 "$(basename $0) unable to handle \$SPECIALMODE=$SPECIALMODE for $ARCHIVE_NAME"
- fi
- echo "Calling make $RELFILE"
- cd $GOSRC
- make "$RELFILE"
- echo "Renaming archive so it can be identified/downloaded for publishing"
- mv -v "$RELFILE" "$ARCHIVE_NAME"
- echo "Success!"
-}
-
-[[ "$CI" == "true" ]] || \
- die 56 "$0 requires a Cirrus-CI cross-task cache to function"
-
-cd $GOSRC
-# Same script re-used for both uploading and downloading to avoid duplication
-if [[ "$(basename $0)" == "cache_release_archive.sh" ]]
-then
- # ref: https://cirrus-ci.org/guide/writing-tasks/#environment-variables
- req_env_var CI_NODE_INDEX CIRRUS_BUILD_ID
- # Use unique names for uncache_release_archives.sh to find/download them all
- ARCHIVE_NAME="build-${CIRRUS_BUILD_ID}-task-${CI_NODE_INDEX}.zip"
- make_release "$ARCHIVE_NAME"
-
- # ref: https://cirrus-ci.org/guide/writing-tasks/#http-cache
- URL="http://$CIRRUS_HTTP_CACHE_HOST/${ARCHIVE_NAME}"
- echo "Uploading $ARCHIVE_NAME to Cirrus-CI cache at $URL"
- curl -s -X POST --data-binary "@$ARCHIVE_NAME" "$URL"
-elif [[ "$(basename $0)" == "uncache_release_archives.sh" ]]
-then
- req_env_var CIRRUS_BUILD_ID CI_NODE_TOTAL GCPJSON GCPNAME GCPROJECT
- [[ "${CI_NODE_INDEX}" -eq "$[CI_NODE_TOTAL-1]" ]] || \
- die 0 "WARNING: This task depends on cache data from other tasks, otherwise it is a no-op."
-
- if [[ -n "$CIRRUS_PR" ]]
- then
- PR_OR_BRANCH="pr$CIRRUS_PR"
- BUCKET="libpod-pr-releases"
- elif [[ -n "$CIRRUS_BRANCH" ]]
- then
- PR_OR_BRANCH="$CIRRUS_BRANCH"
- BUCKET="libpod-$CIRRUS_BRANCH-releases"
- else
- die 10 "Expecting either \$CIRRUS_PR or \$CIRRUS_BRANCH to be non-empty."
- fi
-
- echo "Blindly downloading Cirrus-CI cache files for task (some will fail)."
- set +e # Don't stop looping until all task's cache is attempted
- for (( task_number = 0 ; task_number < $CI_NODE_TOTAL ; task_number++ ))
- do
- ARCHIVE_NAME="build-${CIRRUS_BUILD_ID}-task-${task_number}.zip"
- URL="http://$CIRRUS_HTTP_CACHE_HOST/${ARCHIVE_NAME}"
- echo "Attempting to download cached archive from $URL"
- handle_archive "$task_number" "$PR_OR_BRANCH" "$URL"
- echo "----------------------------------------"
- done
- set -e
-
- [[ -n "$RELEASE_ARCHIVE_NAMES" ]] || \
- die 67 "Error: No release archives found in CI cache, expecting at least one."
-
- echo "Preparing to upload release archives."
- gcloud config set project "$GCPROJECT"
- echo "$GCPJSON" > /tmp/gcp.json
- gcloud auth activate-service-account --key-file=/tmp/gcp.json
- rm /tmp/gcp.json
- # handle_archive() placed all uploadable files under /
- gsutil -m cp /*.zip "gs://$BUCKET" # Upload in parallel
- echo "Successfully uploaded archives:"
- for ARCHIVE_NAME in $RELEASE_ARCHIVE_NAMES
- do
- echo " https://storage.cloud.google.com/$BUCKET/$ARCHIVE_NAME"
- done
- echo "These will remain available until automatic pruning by bucket policy."
-else
- die 9 "I don't know what to do when called $0"
-fi
diff --git a/contrib/cirrus/cirrus_yaml_test.py b/contrib/cirrus/cirrus_yaml_test.py
index c8faee65f..c2ff8e69e 100755
--- a/contrib/cirrus/cirrus_yaml_test.py
+++ b/contrib/cirrus/cirrus_yaml_test.py
@@ -26,7 +26,6 @@ class TestCaseBase(unittest.TestCase):
class TestDependsOn(TestCaseBase):
ALL_TASK_NAMES = None
- SUCCESS_RELEASE = set(['success', 'release'])
def setUp(self):
super().setUp()
@@ -34,34 +33,22 @@ class TestDependsOn(TestCaseBase):
for key, _ in self.CIRRUS_YAML.items()
if key.endswith('_task')])
- def test_dicts(self):
+ def test_00_dicts(self):
"""Expected dictionaries are present and non-empty"""
- for name in ('success_task', 'release_task'):
- # tests all names then show specific failures
- with self.subTest(name=name):
- self.assertIn(name, self.CIRRUS_YAML)
- self.assertIn(name.replace('_task', ''), self.ALL_TASK_NAMES)
- self.assertIn('depends_on', self.CIRRUS_YAML[name])
- self.assertGreater(len(self.CIRRUS_YAML[name]['depends_on']), 0)
-
- def _check_dep(self, name, task_name, deps):
- # name includes '_task' suffix, task_name does not
- msg=('Please add "{0}" to the "depends_on" list in "{1}"'
- "".format(task_name, name))
- self.assertIn(task_name, deps, msg=msg)
-
- def test_depends(self):
- """Success and Release tasks depend on all other tasks"""
- for name in ('success_task', 'release_task'):
- deps = set(self.CIRRUS_YAML[name]['depends_on'])
- for task_name in self.ALL_TASK_NAMES - self.SUCCESS_RELEASE:
- with self.subTest(name=name, task_name=task_name):
- self._check_dep(name, task_name, deps)
-
- def test_release(self):
- """Release task must always execute last"""
- deps = set(self.CIRRUS_YAML['release_task']['depends_on'])
- self._check_dep('release_task', 'success', deps)
+ self.assertIn('success_task', self.CIRRUS_YAML)
+ self.assertIn('success_task'.replace('_task', ''), self.ALL_TASK_NAMES)
+ self.assertIn('depends_on', self.CIRRUS_YAML['success_task'])
+ self.assertGreater(len(self.CIRRUS_YAML['success_task']['depends_on']), 0)
+
+ def test_01_depends(self):
+ """Success task depends on all other tasks"""
+ success_deps = set(self.CIRRUS_YAML['success_task']['depends_on'])
+ for task_name in self.ALL_TASK_NAMES - set(['success']):
+ with self.subTest(task_name=task_name):
+ msg=('Please add "{0}" to the "depends_on" list in "success_task"'
+ "".format(task_name))
+ self.assertIn(task_name, success_deps, msg=msg)
+
if __name__ == "__main__":
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index a3d18d440..552f2ba73 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -65,10 +65,6 @@ case "$SPECIALMODE" in
make local${TESTSUITE}
fi
;;
- windows) ;& # for podman-remote building only
- darwin)
- warn '' "No $SPECIALMODE remote client integration tests configured"
- ;;
*)
die 110 "Unsupported \$SPECIALMODE: $SPECIALMODE"
esac
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index a20ee5a62..f66e63140 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -64,6 +64,8 @@ export PRIOR_FEDORA_BASE_IMAGE="fedora-cloud-base-29-1-2-1559164849"
export BUILT_IMAGE_SUFFIX="${BUILT_IMAGE_SUFFIX:--$CIRRUS_REPO_NAME-${CIRRUS_BUILD_ID}}"
# IN_PODMAN container image
IN_PODMAN_IMAGE="quay.io/libpod/in_podman:latest"
+# Image for uploading releases
+UPLDREL_IMAGE="quay.io/libpod/upldrel:latest"
# Avoid getting stuck waiting for user input
export DEBIAN_FRONTEND="noninteractive"
@@ -76,7 +78,7 @@ BIGTO="timeout_attempt_delay_command 300s 5 30s"
# Safe env. vars. to transfer from root -> $ROOTLESS_USER (go env handled separetly)
ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(TEST_REMOTE.*)'
# Unsafe env. vars for display
-SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(^GC[EP]..+)|(SSH)'
+SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(GC[EP]..+)|(SSH)'
# Names of systemd units which should never be running
EVIL_UNITS="cron crond atd apt-daily-upgrade apt-daily fstrim motd-news systemd-tmpfiles-clean"
@@ -321,13 +323,15 @@ EOF
install_test_configs(){
echo "Installing cni config, policy and registry config"
- req_env_var GOSRC
- sudo install -D -m 755 $GOSRC/cni/87-podman-bridge.conflist \
- /etc/cni/net.d/87-podman-bridge.conflist
- sudo install -D -m 755 $GOSRC/test/policy.json \
- /etc/containers/policy.json
- sudo install -D -m 755 $GOSRC/test/registries.conf \
- /etc/containers/registries.conf
+ req_env_var GOSRC SCRIPT_BASE
+ cd $GOSRC
+ install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/
+ # This config must always sort last in the list of networks (podman picks first one
+ # as the default). This config prevents allocation of network address space used
+ # by default in google cloud. https://cloud.google.com/vpc/docs/vpc#ip-ranges
+ install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist /etc/cni/net.d/
+ install -v -D -m 644 ./test/policy.json /etc/containers/
+ install -v -D -m 644 ./test/registries.conf /etc/containers/
}
# Remove all files (except conmon, for now) provided by the distro version of podman.
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 2579229a5..7c7659169 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -44,11 +44,15 @@ case "${OS_REL_VER}" in
;;
fedora-30) ;& # continue to next item
fedora-29)
+ # All SELinux distros need this for systemd-in-a-container
+ setsebool container_manage_cgroup true
if [[ "$ADD_SECOND_PARTITION" == "true" ]]; then
bash "$SCRIPT_BASE/add_second_partition.sh"; fi
;;
centos-7) # Current VM is an image-builder-image no local podman/testing
- echo "No further setup required for VM image building"
+ echo "No further setup required for VM image building"
+ # All SELinux distros need this for systemd-in-a-container
+ setsebool container_manage_cgroup true
exit 0
;;
*) bad_os_id_ver ;;
@@ -57,8 +61,7 @@ esac
# Reload to incorporate any changes from above
source "$SCRIPT_BASE/lib.sh"
-install_test_configs
-
+# Must execute before possible setup_rootless()
make install.tools
case "$SPECIALMODE" in
@@ -66,7 +69,8 @@ case "$SPECIALMODE" in
remove_packaged_podman_files # we're building from source
;;
none)
- remove_packaged_podman_files
+ [[ -n "$CROSS_PLATFORM" ]] || \
+ remove_packaged_podman_files
;;
endpoint)
remove_packaged_podman_files
@@ -88,8 +92,8 @@ case "$SPECIALMODE" in
in_podman) # Assumed to be Fedora
$SCRIPT_BASE/setup_container_environment.sh
;;
- windows) ;& # for podman-remote building only
- darwin) ;;
*)
die 111 "Unsupported \$SPECIALMODE: $SPECIALMODE"
esac
+
+install_test_configs
diff --git a/contrib/cirrus/uncache_release_archives.sh b/contrib/cirrus/uncache_release_archives.sh
deleted file mode 120000
index e9fc6edff..000000000
--- a/contrib/cirrus/uncache_release_archives.sh
+++ /dev/null
@@ -1 +0,0 @@
-cache_release_archive.sh \ No newline at end of file
diff --git a/contrib/cirrus/unit_test.sh b/contrib/cirrus/unit_test.sh
index 004839f17..c6c77d17e 100755
--- a/contrib/cirrus/unit_test.sh
+++ b/contrib/cirrus/unit_test.sh
@@ -16,10 +16,6 @@ case "$SPECIALMODE" in
none)
make
;;
- windows) ;&
- darwin)
- make podman-remote-$SPECIALMODE
- ;;
*)
die 109 "Unsupported \$SPECIAL_MODE: $SPECIALMODE"
esac
diff --git a/contrib/cirrus/upload_release_archive.sh b/contrib/cirrus/upload_release_archive.sh
new file mode 100755
index 000000000..942255821
--- /dev/null
+++ b/contrib/cirrus/upload_release_archive.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+set -eo pipefail
+
+source $(dirname $0)/lib.sh
+
+req_env_var CI UPLDREL_IMAGE CIRRUS_BUILD_ID GOSRC RELEASE_GCPJSON RELEASE_GCPNAME RELEASE_GCPROJECT
+
+[[ "$CI" == "true" ]] || \
+ die 56 "$0 must be run under Cirrus-CI to function"
+
+unset PR_OR_BRANCH BUCKET
+if [[ -n "$CIRRUS_PR" ]]
+then
+ PR_OR_BRANCH="pr$CIRRUS_PR"
+ BUCKET="libpod-pr-releases"
+elif [[ -n "$CIRRUS_BRANCH" ]]
+then
+ PR_OR_BRANCH="$CIRRUS_BRANCH"
+ BUCKET="libpod-$CIRRUS_BRANCH-releases"
+else
+ die 1 "Expecting either \$CIRRUS_PR or \$CIRRUS_BRANCH to be non-empty."
+fi
+
+# Functional local podman required for uploading a release
+cd $GOSRC
+[[ -n "$(type -P podman)" ]] || \
+ make install || \
+ die 57 "$0 requires working podman binary on path to function"
+
+TMPF=$(mktemp -p '' $(basename $0)_XXXX.json)
+trap "rm -f $TMPF" EXIT
+set +x
+echo "$RELEASE_GCPJSON" > "$TMPF"
+unset RELEASE_GCPJSON
+
+cd $GOSRC
+for filename in $(ls -1 *.tar.gz *.zip)
+do
+ echo "Running podman ... $UPLDREL_IMAGE $filename"
+ podman run -i --rm \
+ -e "GCPNAME=$RELEASE_GCPNAME" \
+ -e "GCPPROJECT=$RELEASE_GCPROJECT" \
+ -e "GCPJSON_FILEPATH=$TMPF" \
+ -e "REL_ARC_FILEPATH=/tmp/$filename" \
+ -e "PR_OR_BRANCH=$PR_OR_BRANCH" \
+ -e "BUCKET=$BUCKET" \
+ --security-opt label=disable \
+ -v "$TMPF:$TMPF:ro" \
+ -v "$GOSRC/$filename:/tmp/$filename:ro" \
+ $UPLDREL_IMAGE
+done
diff --git a/contrib/imgts/lib_entrypoint.sh b/contrib/imgts/lib_entrypoint.sh
index 7b76c823f..3f6b11128 100644
--- a/contrib/imgts/lib_entrypoint.sh
+++ b/contrib/imgts/lib_entrypoint.sh
@@ -35,10 +35,15 @@ req_env_var() {
gcloud_init() {
set +xe
- TMPF=$(mktemp -p '' .$(uuidgen)XXXX)
- trap "rm -f $TMPF" EXIT
- echo "$GCPJSON" > $TMPF && \
- $GCLOUD auth activate-service-account --project "$GCPPROJECT" --key-file=$TMPF || \
+ if [[ -n "$1" ]] && [[ -r "$1" ]]
+ then
+ TMPF="$1"
+ else
+ TMPF=$(mktemp -p '' .$(uuidgen)_XXXX.json)
+ trap "rm -f $TMPF &> /dev/null" EXIT
+ echo "$GCPJSON" > $TMPF
+ fi
+ $GCLOUD auth activate-service-account --project="$GCPPROJECT" --key-file="$TMPF" || \
die 5 FATAL auth
- rm -f $TMPF
+ rm -f $TMPF &> /dev/null || true # ignore any read-only error
}
diff --git a/contrib/upldrel/Dockerfile b/contrib/upldrel/Dockerfile
new file mode 100644
index 000000000..54a58c521
--- /dev/null
+++ b/contrib/upldrel/Dockerfile
@@ -0,0 +1,9 @@
+FROM quay.io/libpod/imgts:latest
+
+RUN yum -y update && \
+ yum -y install unzip && \
+ rpm -V unzip && \
+ yum clean all
+
+COPY /contrib/upldrel/entrypoint.sh /usr/local/bin/entrypoint.sh
+RUN chmod 755 /usr/local/bin/entrypoint.sh
diff --git a/contrib/upldrel/README.md b/contrib/upldrel/README.md
new file mode 100644
index 000000000..41f5ffef0
--- /dev/null
+++ b/contrib/upldrel/README.md
@@ -0,0 +1,9 @@
+![PODMAN logo](../../logo/podman-logo-source.svg)
+
+A container image for canonical-naming and uploading of
+libpod and remote-client archives. Only intended to ever
+be used by CI/CD, and depends heavily on an embedded
+`release.txt` file produced by `make`.
+
+Build script: [../cirrus/build_release.sh](../cirrus/build_release.sh)
+Upload script: [../cirrus/upload_release_archive.sh](../cirrus/upload_release_archive.sh)
diff --git a/contrib/upldrel/entrypoint.sh b/contrib/upldrel/entrypoint.sh
new file mode 100755
index 000000000..985b828a0
--- /dev/null
+++ b/contrib/upldrel/entrypoint.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+set -e
+
+source /usr/local/bin/lib_entrypoint.sh
+
+req_env_var GCPJSON_FILEPATH GCPNAME GCPPROJECT REL_ARC_FILEPATH PR_OR_BRANCH BUCKET
+
+[[ -r "$REL_ARC_FILEPATH" ]] || \
+ die 2 ERROR Cannot read release archive file: "$REL_ARC_FILEPATH"
+
+[[ -r "$GCPJSON_FILEPATH" ]] || \
+ die 3 ERROR Cannot read GCP credentials file: "$GCPJSON_FILEPATH"
+
+cd $TMPDIR
+echo "Attempting to extract release.txt from tar or zip $REL_ARC_FILEPATH"
+unset SFX
+if tar xzf "$REL_ARC_FILEPATH" "./release.txt"
+then
+ echo "It's a tarball"
+ SFX="tar.gz"
+elif unzip "$REL_ARC_FILEPATH" release.txt
+then
+ echo "It's a zip"
+ SFX="zip"
+else
+ die 5 ERROR Could not extract release.txt from $REL_ARC_FILEPATH
+fi
+
+echo "Parsing release.txt contents"
+RELEASETXT=$(<release.txt)
+cd -
+[[ -n "$RELEASETXT" ]] || \
+ die 3 ERROR Could not obtain metadata from release.txt in $REL_ARC_FILEPATH
+
+RELEASE_INFO=$(echo "$RELEASETXT" | grep -m 1 'X-RELEASE-INFO:' | sed -r -e 's/X-RELEASE-INFO:\s*(.+)/\1/')
+if [[ "$?" -ne "0" ]] || [[ -z "$RELEASE_INFO" ]]
+then
+ die 4 ERROR Metadata is empty or invalid: '$RELEASETXT'
+fi
+
+# e.g. libpod v1.3.1-166-g60df124e fedora 29 amd64
+# or libpod v1.3.1-166-g60df124e amd64
+FIELDS="RELEASE_BASENAME RELEASE_VERSION RELEASE_DIST RELEASE_DIST_VER RELEASE_ARCH"
+read $FIELDS <<< $RELEASE_INFO
+for f in $FIELDS
+do
+ [[ -n "${!f}" ]] || \
+ die 5 ERROR Expecting $f to be non-empty in metadata: '$RELEASE_INFO'
+done
+
+gcloud_init "$GCPJSON_FILEPATH"
+
+# Drop version number to enable "latest" representation
+# (version available w/in zip-file comment)
+RELEASE_ARCHIVE_NAME="${RELEASE_BASENAME}-${PR_OR_BRANCH}-${RELEASE_DIST}-${RELEASE_DIST_VER}-${RELEASE_ARCH}.${SFX}"
+
+echo "Uploading archive as $RELEASE_ARCHIVE_NAME"
+gsutil cp "$REL_ARC_FILEPATH" "gs://$BUCKET/$RELEASE_ARCHIVE_NAME"
+
+echo "Release now available at:"
+echo " https://storage.cloud.google.com/$BUCKET/$RELEASE_ARCHIVE_NAME"
diff --git a/docs/podman-image-sign.1.md b/docs/podman-image-sign.1.md
index 61df3b3bd..ca438b438 100644
--- a/docs/podman-image-sign.1.md
+++ b/docs/podman-image-sign.1.md
@@ -12,14 +12,23 @@ been pulled from a registry. The signature will be written to a directory
derived from the registry configuration files in /etc/containers/registries.d. By default, the signature will be written into /var/lib/containers/sigstore directory.
## OPTIONS
+
**--help**, **-h**
- Print usage statement.
+
+Print usage statement.
+
+**--cert-dir**=*path*
+
+Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
+Default certificates directory is _/etc/containers/certs.d_. (Not available for remote commands)
**--directory**, **-d**=*dir*
- Store the signatures in the specified directory. Default: /var/lib/containers/sigstore
+
+Store the signatures in the specified directory. Default: /var/lib/containers/sigstore
**--sign-by**=*identity*
- Override the default identity of the signature.
+
+Override the default identity of the signature.
## EXAMPLES
Sign the busybox image with the identify of foo@bar.com with a user's keyring and save the signature in /tmp/signatures/.
diff --git a/hack/get_release_info.sh b/hack/get_release_info.sh
new file mode 100755
index 000000000..29b4237b4
--- /dev/null
+++ b/hack/get_release_info.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# This script produces various bits of metadata needed by Makefile. Using
+# a script allows uniform behavior across multiple environments and
+# distributions. The script expects a single argument, as reflected below.
+
+set -e
+
+cd "${GOSRC:-$(dirname $0)/../}"
+
+valid_args() {
+ REGEX='^\s+[[:upper:]]+\*[)]'
+ egrep --text --no-filename --group-separator=' ' --only-matching "$REGEX" "$0" | \
+ cut -d '*' -f 1
+}
+
+unset OUTPUT
+case "$1" in
+ # Wild-card suffix needed by valid_args() e.g. possible bad grep of "$(echo $FOO)"
+ VERSION*)
+ OUTPUT="${CIRRUS_TAG:-$(git fetch --tags && git describe HEAD 2> /dev/null)}"
+ ;;
+ NUMBER*)
+ OUTPUT="$($0 VERSION | sed 's/-.*//')"
+ ;;
+ DIST_VER*)
+ OUTPUT="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
+ ;;
+ DIST*)
+ OUTPUT="$(source /etc/os-release; echo $ID)"
+ ;;
+ ARCH*)
+ OUTPUT="${GOARCH:-$(go env GOARCH 2> /dev/null)}"
+ ;;
+ BASENAME*)
+ OUTPUT="${CIRRUS_REPO_NAME:-$(basename $(git rev-parse --show-toplevel))}"
+ ;;
+ REMOTENAME*)
+ OUTPUT="$($0 BASENAME)-remote"
+ ;;
+ *)
+ echo "Error, unknown/unsupported argument '$1', valid arguments:"
+ valid_args
+ exit 1
+ ;;
+esac
+
+if [[ -n "$OUTPUT" ]]
+then
+ echo -n "$OUTPUT"
+else
+ echo "Error, empty output for info: '$1'" > /dev/stderr
+ exit 2
+fi
diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go
index 176781f07..1de8d80c9 100644
--- a/libpod/boltdb_state.go
+++ b/libpod/boltdb_state.go
@@ -870,7 +870,7 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
newCfgJSON, err := json.Marshal(newCfg)
if err != nil {
- return errors.Wrapf(err, "error marshalling new configuration JSON for container %s", pod.ID())
+ return errors.Wrapf(err, "error marshalling new configuration JSON for pod %s", pod.ID())
}
db, err := s.getDBCon()
@@ -900,6 +900,50 @@ func (s *BoltState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
return err
}
+// RewriteVolumeConfig rewrites a volume's configuration.
+// WARNING: This function is DANGEROUS. Do not use without reading the full
+// comment on this function in state.go.
+func (s *BoltState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) error {
+ if !s.valid {
+ return define.ErrDBClosed
+ }
+
+ if !volume.valid {
+ return define.ErrVolumeRemoved
+ }
+
+ newCfgJSON, err := json.Marshal(newCfg)
+ if err != nil {
+ return errors.Wrapf(err, "error marshalling new configuration JSON for volume %q", volume.Name())
+ }
+
+ db, err := s.getDBCon()
+ if err != nil {
+ return err
+ }
+ defer s.deferredCloseDBCon(db)
+
+ err = db.Update(func(tx *bolt.Tx) error {
+ volBkt, err := getVolBucket(tx)
+ if err != nil {
+ return err
+ }
+
+ volDB := volBkt.Bucket([]byte(volume.Name()))
+ if volDB == nil {
+ volume.valid = false
+ return errors.Wrapf(define.ErrNoSuchVolume, "no volume with name %q found in DB", volume.Name())
+ }
+
+ if err := volDB.Put(configKey, newCfgJSON); err != nil {
+ return errors.Wrapf(err, "error updating volume %q config JSON", volume.Name())
+ }
+
+ return nil
+ })
+ return err
+}
+
// Pod retrieves a pod given its full ID
func (s *BoltState) Pod(id string) (*Pod, error) {
if id == "" {
diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go
index 408ef7224..6e4179835 100644
--- a/libpod/boltdb_state_internal.go
+++ b/libpod/boltdb_state_internal.go
@@ -449,6 +449,13 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu
return errors.Wrapf(err, "error unmarshalling volume %s config from DB", string(name))
}
+ // Get the lock
+ lock, err := s.runtime.lockManager.RetrieveLock(volume.config.LockID)
+ if err != nil {
+ return errors.Wrapf(err, "error retrieving lock for volume %q", string(name))
+ }
+ volume.lock = lock
+
volume.runtime = s.runtime
volume.valid = true
diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go
index 7c4abd25d..a9b735327 100644
--- a/libpod/in_memory_state.go
+++ b/libpod/in_memory_state.go
@@ -425,6 +425,26 @@ func (s *InMemoryState) RewritePodConfig(pod *Pod, newCfg *PodConfig) error {
return nil
}
+// RewriteVolumeConfig rewrites a volume's configuration.
+// This function is DANGEROUS, even with in-memory state.
+// Please read the full comment in state.go before using it.
+func (s *InMemoryState) RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) error {
+ if !volume.valid {
+ return define.ErrVolumeRemoved
+ }
+
+ // If the volume does not exist, return error
+ stateVol, ok := s.volumes[volume.Name()]
+ if !ok {
+ volume.valid = false
+ return errors.Wrapf(define.ErrNoSuchVolume, "volume with name %q not found in state", volume.Name())
+ }
+
+ stateVol.config = newCfg
+
+ return nil
+}
+
// Volume retrieves a volume from its full name
func (s *InMemoryState) Volume(name string) (*Volume, error) {
if name == "" {
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 4d6a80d0b..28774773e 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -76,10 +76,6 @@ var (
// place of the configuration file pointed to by ConfigPath.
OverrideConfigPath = etcDir + "/containers/libpod.conf"
- // DefaultInfraImage to use for infra container
-
- // DefaultInfraCommand to be run in an infra container
-
// DefaultSHMLockPath is the default path for SHM locks
DefaultSHMLockPath = "/libpod_lock"
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 92b2faefb..acd317d20 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -253,10 +253,13 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai
// Go through named volumes and add them.
// If they don't exist they will be created using basic options.
+ // Maintain an array of them - we need to lock them later.
+ ctrNamedVolumes := make([]*Volume, 0, len(ctr.config.NamedVolumes))
for _, vol := range ctr.config.NamedVolumes {
// Check if it exists already
- _, err := r.state.Volume(vol.Name)
+ dbVol, err := r.state.Volume(vol.Name)
if err == nil {
+ ctrNamedVolumes = append(ctrNamedVolumes, dbVol)
// The volume exists, we're good
continue
} else if errors.Cause(err) != config2.ErrNoSuchVolume {
@@ -275,6 +278,8 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai
if err := ctr.copyWithTarFromImage(vol.Dest, newVol.MountPoint()); err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "Failed to copy content into new volume mount %q", vol.Name)
}
+
+ ctrNamedVolumes = append(ctrNamedVolumes, newVol)
}
if ctr.config.LogPath == "" && ctr.config.LogDriver != JournaldLogging {
@@ -291,6 +296,14 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai
ctr.config.Mounts = append(ctr.config.Mounts, ctr.config.ShmDir)
}
+ // Lock all named volumes we are adding ourself to, to ensure we can't
+ // use a volume being removed.
+ for _, namedVol := range ctrNamedVolumes {
+ toLock := namedVol
+ toLock.lock.Lock()
+ defer toLock.lock.Unlock()
+ }
+
// Add the container to the state
// TODO: May be worth looking into recovering from name/ID collisions here
if ctr.config.Pod != "" {
diff --git a/libpod/runtime_renumber.go b/libpod/runtime_renumber.go
index 735ffba34..9de2556b2 100644
--- a/libpod/runtime_renumber.go
+++ b/libpod/runtime_renumber.go
@@ -53,6 +53,23 @@ func (r *Runtime) renumberLocks() error {
return err
}
}
+ allVols, err := r.state.AllVolumes()
+ if err != nil {
+ return err
+ }
+ for _, vol := range allVols {
+ lock, err := r.lockManager.AllocateLock()
+ if err != nil {
+ return errors.Wrapf(err, "error allocating lock for volume %s", vol.Name())
+ }
+
+ vol.config.LockID = lock.ID()
+
+ // Write the new lock ID
+ if err := r.state.RewriteVolumeConfig(vol, vol.config); err != nil {
+ return err
+ }
+ }
r.newSystemEvent(events.Renumber)
diff --git a/libpod/runtime_volume.go b/libpod/runtime_volume.go
index d05db936b..512e778a1 100644
--- a/libpod/runtime_volume.go
+++ b/libpod/runtime_volume.go
@@ -36,6 +36,10 @@ func (r *Runtime) RemoveVolume(ctx context.Context, v *Volume, force bool) error
return nil
}
}
+
+ v.lock.Lock()
+ defer v.lock.Unlock()
+
return r.removeVolume(ctx, v, force)
}
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index 84703787d..70296248c 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -28,7 +28,7 @@ func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption)
}
// newVolume creates a new empty volume
-func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) {
+func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (_ *Volume, Err error) {
volume, err := newVolume(r)
if err != nil {
return nil, errors.Wrapf(err, "error creating volume")
@@ -68,6 +68,21 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
}
volume.config.MountPoint = fullVolPath
+ lock, err := r.lockManager.AllocateLock()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error allocating lock for new volume")
+ }
+ volume.lock = lock
+ volume.config.LockID = volume.lock.ID()
+
+ defer func() {
+ if Err != nil {
+ if err := volume.lock.Free(); err != nil {
+ logrus.Errorf("Error freeing volume lock after failed creation: %v", err)
+ }
+ }
+ }()
+
volume.valid = true
// Add the volume to state
@@ -110,6 +125,8 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
return errors.Wrapf(err, "error removing container %s that depends on volume %s", dep, v.Name())
}
+ logrus.Debugf("Removing container %s (depends on volume %q)", ctr.ID(), v.Name())
+
// TODO: do we want to set force here when removing
// containers?
// I'm inclined to say no, in case someone accidentally
@@ -128,12 +145,24 @@ func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force bool) error
return errors.Wrapf(err, "error removing volume %s", v.Name())
}
- // Delete the mountpoint path of the volume, that is delete the volume from /var/lib/containers/storage/volumes
+ var removalErr error
+
+ // Free the volume's lock
+ if err := v.lock.Free(); err != nil {
+ removalErr = errors.Wrapf(err, "error freeing lock for volume %s", v.Name())
+ }
+
+ // Delete the mountpoint path of the volume, that is delete the volume
+ // from /var/lib/containers/storage/volumes
if err := v.teardownStorage(); err != nil {
- return errors.Wrapf(err, "error cleaning up volume storage for %q", v.Name())
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error cleaning up volume storage for %q", v.Name())
+ } else {
+ logrus.Errorf("error cleaning up volume storage for volume %q: %v", v.Name(), err)
+ }
}
defer v.newVolumeEvent(events.Remove)
logrus.Debugf("Removed volume %s", v.Name())
- return nil
+ return removalErr
}
diff --git a/libpod/state.go b/libpod/state.go
index d0ad1a1f8..5d704e69a 100644
--- a/libpod/state.go
+++ b/libpod/state.go
@@ -115,12 +115,20 @@ type State interface {
// answer is this: use this only very sparingly, and only if you really
// know what you're doing.
RewriteContainerConfig(ctr *Container, newCfg *ContainerConfig) error
- // PLEASE READ THE ABOVE DESCRIPTION BEFORE USING.
+ // PLEASE READ THE DESCRIPTION FOR RewriteContainerConfig BEFORE USING.
// This function is identical to RewriteContainerConfig, save for the
// fact that it is used with pods instead.
// It is subject to the same conditions as RewriteContainerConfig.
// Please do not use this unless you know what you're doing.
RewritePodConfig(pod *Pod, newCfg *PodConfig) error
+ // PLEASE READ THE DESCRIPTION FOR RewriteContainerConfig BEFORE USING.
+ // This function is identical to RewriteContainerConfig, save for the
+ // fact that it is used with volumes instead.
+ // It is subject to the same conditions as RewriteContainerConfig.
+ // The exception is that volumes do not have IDs, so only volume name
+ // cannot be altered.
+ // Please do not use this unless you know what you're doing.
+ RewriteVolumeConfig(volume *Volume, newCfg *VolumeConfig) error
// Accepts full ID of pod.
// If the pod given is not in the set namespace, an error will be
diff --git a/libpod/volume.go b/libpod/volume.go
index 74126b49b..abfa7b3f4 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -2,6 +2,8 @@ package libpod
import (
"time"
+
+ "github.com/containers/libpod/libpod/lock"
)
// Volume is the type used to create named volumes
@@ -11,21 +13,35 @@ type Volume struct {
valid bool
runtime *Runtime
+ lock lock.Locker
}
// VolumeConfig holds the volume's config information
type VolumeConfig struct {
- // Name of the volume
+ // Name of the volume.
Name string `json:"name"`
-
- Labels map[string]string `json:"labels"`
- Driver string `json:"driver"`
- MountPoint string `json:"mountPoint"`
- CreatedTime time.Time `json:"createdAt,omitempty"`
- Options map[string]string `json:"options"`
- IsCtrSpecific bool `json:"ctrSpecific"`
- UID int `json:"uid"`
- GID int `json:"gid"`
+ // ID of the volume's lock.
+ LockID uint32 `json:"lockID"`
+ // Labels for the volume.
+ Labels map[string]string `json:"labels"`
+ // The volume driver. Empty string or local does not activate a volume
+ // driver, all other volumes will.
+ Driver string `json:"driver"`
+ // The location the volume is mounted at.
+ MountPoint string `json:"mountPoint"`
+ // Time the volume was created.
+ CreatedTime time.Time `json:"createdAt,omitempty"`
+ // Options to pass to the volume driver. For the local driver, this is
+ // a list of mount options. For other drivers, they are passed to the
+ // volume driver handling the volume.
+ Options map[string]string `json:"options"`
+ // Whether this volume was created for a specific container and will be
+ // removed with it.
+ IsCtrSpecific bool `json:"ctrSpecific"`
+ // UID the volume will be created as.
+ UID int `json:"uid"`
+ // GID the volume will be created as.
+ GID int `json:"gid"`
}
// Name retrieves the volume's name
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 1e0b84310..abb93a149 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -154,4 +154,12 @@ var _ = Describe("Podman run with volumes", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
})
+
+ It("podman run with volume flag and multiple named volumes", func() {
+ session := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol1:/testvol1", "-v", "testvol2:/testvol2", ALPINE, "grep", "/testvol", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/testvol1"))
+ Expect(session.OutputToString()).To(ContainSubstring("/testvol2"))
+ })
})
diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go
index 91604867d..02778d493 100644
--- a/test/e2e/systemd_test.go
+++ b/test/e2e/systemd_test.go
@@ -5,7 +5,10 @@ package integration
import (
"io/ioutil"
"os"
+ "strings"
+ "time"
+ "github.com/containers/libpod/pkg/cgroups"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -77,4 +80,49 @@ WantedBy=multi-user.target
status := SystemExec("bash", []string{"-c", "systemctl status redis"})
Expect(status.OutputToString()).To(ContainSubstring("active (running)"))
})
+
+ It("podman run container with systemd PID1", func() {
+ cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
+ Expect(err).To(BeNil())
+ if cgroupsv2 {
+ Skip("systemd test does not work in cgroups V2 mode yet")
+ }
+
+ systemdImage := "fedora"
+ pull := podmanTest.Podman([]string{"pull", systemdImage})
+ pull.WaitWithDefaultTimeout()
+ Expect(pull.ExitCode()).To(Equal(0))
+
+ ctrName := "testSystemd"
+ run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", systemdImage, "init"})
+ run.WaitWithDefaultTimeout()
+ Expect(run.ExitCode()).To(Equal(0))
+ ctrID := run.OutputToString()
+
+ logs := podmanTest.Podman([]string{"logs", ctrName})
+ logs.WaitWithDefaultTimeout()
+ Expect(logs.ExitCode()).To(Equal(0))
+
+ // Give container 10 seconds to start
+ started := false
+ for i := 0; i < 10; i++ {
+ runningCtrs := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
+ runningCtrs.WaitWithDefaultTimeout()
+ Expect(runningCtrs.ExitCode()).To(Equal(0))
+
+ if strings.Contains(runningCtrs.OutputToString(), ctrID) {
+ started = true
+ break
+ }
+
+ time.Sleep(1 * time.Second)
+ }
+
+ Expect(started).To(BeTrue())
+
+ systemctl := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "systemctl", "status", "--no-pager"})
+ systemctl.WaitWithDefaultTimeout()
+ Expect(systemctl.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(systemctl.OutputToString(), "State:")).To(BeTrue())
+ })
})