summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml32
-rw-r--r--CODE-OF-CONDUCT.md3
-rw-r--r--Makefile2
-rw-r--r--README.md6
-rw-r--r--RELEASE_NOTES.md11
-rw-r--r--changelog.txt32
-rw-r--r--cmd/podman/commands.go11
-rw-r--r--cmd/podman/commit.go12
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/images.go59
-rw-r--r--cmd/podman/libpodruntime/runtime.go58
-rw-r--r--cmd/podman/ps.go10
-rw-r--r--cmd/podman/pull.go111
-rw-r--r--cmd/podman/shared/container.go5
-rw-r--r--cmd/podman/shared/create.go24
-rw-r--r--cmd/podman/shared/intermediate.go1
-rw-r--r--code-of-conduct.md55
-rw-r--r--completions/bash/podman42
-rw-r--r--contrib/fedora-minimal/Dockerfile1
-rw-r--r--contrib/fedora-minimal/README.md4
-rw-r--r--contrib/spec/podman.spec.in11
-rw-r--r--contrib/spec/python-podman.spec.in2
-rw-r--r--contrib/systemd/README.md78
-rw-r--r--contrib/systemd/system/podman.service2
-rw-r--r--contrib/systemd/user/podman.service2
-rw-r--r--docs/source/markdown/podman-build.1.md2
-rw-r--r--docs/source/markdown/podman-create.1.md9
-rw-r--r--docs/source/markdown/podman-images.1.md12
-rw-r--r--docs/source/markdown/podman-run.1.md2
-rw-r--r--docs/source/markdown/podman-system-service.1.md (renamed from docs/source/markdown/podman-service.1.md)10
-rw-r--r--docs/source/markdown/podman-system.1.md2
-rw-r--r--docs/source/markdown/podman.1.md1
-rw-r--r--go.mod10
-rw-r--r--go.sum155
-rw-r--r--install.md529
-rw-r--r--libpod/container_internal.go34
-rw-r--r--libpod/image/image.go104
-rw-r--r--libpod/image/image_test.go2
-rw-r--r--libpod/options.go153
-rw-r--r--libpod/pod.go14
-rw-r--r--libpod/runtime_pod_infra_linux.go28
-rw-r--r--libpod/runtime_pod_linux.go12
-rw-r--r--libpod/stats.go2
-rw-r--r--libpod/stats_config.go28
-rw-r--r--pkg/adapter/pods.go22
-rw-r--r--pkg/api/Makefile2
-rw-r--r--pkg/api/handlers/containers.go8
-rw-r--r--pkg/api/handlers/events.go44
-rw-r--r--pkg/api/handlers/generic/containers_stats.go18
-rw-r--r--pkg/api/handlers/libpod/containers.go174
-rw-r--r--pkg/api/handlers/libpod/images.go209
-rw-r--r--pkg/api/handlers/libpod/pods.go14
-rw-r--r--pkg/api/handlers/libpod/swagger.go8
-rw-r--r--pkg/api/handlers/libpod/types.go82
-rw-r--r--pkg/api/handlers/swagger.go8
-rw-r--r--pkg/api/handlers/types.go27
-rw-r--r--pkg/api/handlers/utils/handler.go8
-rw-r--r--pkg/api/server/register_containers.go2
-rw-r--r--pkg/api/server/register_events.go2
-rw-r--r--pkg/api/server/register_images.go122
-rw-r--r--pkg/api/server/register_pods.go2
-rw-r--r--pkg/api/server/server.go1
-rw-r--r--pkg/bindings/connection.go12
-rw-r--r--pkg/bindings/containers/containers.go17
-rw-r--r--pkg/bindings/images/images.go4
-rw-r--r--pkg/bindings/images/search.go2
-rw-r--r--pkg/bindings/pods/pods.go2
-rw-r--r--pkg/bindings/test/common_test.go32
-rw-r--r--pkg/bindings/test/images_test.go104
-rw-r--r--pkg/cgroups/cgroups.go15
-rw-r--r--pkg/cgroups/cpu.go39
-rw-r--r--pkg/rootlessport/rootlessport_linux.go29
-rw-r--r--pkg/seccomp/seccomp.go54
-rw-r--r--pkg/spec/config_linux.go37
-rw-r--r--pkg/spec/config_linux_cgo.go11
-rw-r--r--pkg/spec/config_unsupported.go4
-rw-r--r--pkg/spec/createconfig.go47
-rw-r--r--pkg/spec/parse.go18
-rw-r--r--pkg/spec/spec.go6
-rw-r--r--pkg/varlinkapi/images.go10
-rw-r--r--test/apiv2/01-basic.at3
-rw-r--r--test/apiv2/10-images.at6
-rw-r--r--test/apiv2/20-containers.at16
-rw-r--r--test/apiv2/40-pods.at20
-rwxr-xr-xtest/apiv2/test-apiv283
-rw-r--r--test/e2e/build_test.go37
-rw-r--r--test/e2e/commit_test.go19
-rw-r--r--test/e2e/config.go2
-rw-r--r--test/e2e/images_test.go5
-rw-r--r--test/e2e/load_test.go2
-rw-r--r--test/e2e/play_kube_test.go43
-rw-r--r--test/e2e/ps_test.go13
-rw-r--r--test/e2e/run_test.go12
-rw-r--r--test/e2e/run_volume_test.go24
-rw-r--r--test/endpoint/endpoint.go2
-rw-r--r--vendor/github.com/acarl005/stripansi/LICENSE21
-rw-r--r--vendor/github.com/acarl005/stripansi/README.md30
-rw-r--r--vendor/github.com/acarl005/stripansi/stripansi.go13
-rw-r--r--vendor/github.com/containers/image/v5/copy/copy.go33
-rw-r--r--vendor/github.com/containers/image/v5/copy/manifest.go14
-rw-r--r--vendor/github.com/containers/image/v5/directory/directory_dest.go21
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_client.go124
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_image.go2
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_image_dest.go11
-rw-r--r--vendor/github.com/containers/image/v5/docker/docker_image_src.go99
-rw-r--r--vendor/github.com/containers/image/v5/docker/errors.go11
-rw-r--r--vendor/github.com/containers/image/v5/docker/tarfile/dest.go3
-rw-r--r--vendor/github.com/containers/image/v5/docker/tarfile/src.go9
-rw-r--r--vendor/github.com/containers/image/v5/image/docker_schema2.go4
-rw-r--r--vendor/github.com/containers/image/v5/image/oci.go4
-rw-r--r--vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go60
-rw-r--r--vendor/github.com/containers/image/v5/openshift/openshift.go4
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go4
-rw-r--r--vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go2
-rw-r--r--vendor/github.com/containers/image/v5/types/types.go2
-rw-r--r--vendor/github.com/containers/image/v5/version/version.go4
-rw-r--r--vendor/github.com/gorilla/mux/README.md91
-rw-r--r--vendor/github.com/gorilla/mux/context.go18
-rw-r--r--vendor/github.com/gorilla/mux/go.mod2
-rw-r--r--vendor/github.com/gorilla/mux/middleware.go25
-rw-r--r--vendor/github.com/gorilla/mux/mux.go28
-rw-r--r--vendor/github.com/gorilla/mux/regexp.go65
-rw-r--r--vendor/github.com/gorilla/mux/route.go38
-rw-r--r--vendor/github.com/gorilla/mux/test_helpers.go2
-rw-r--r--vendor/github.com/mtrmac/gpgme/.appveyor.yml40
-rw-r--r--vendor/github.com/mtrmac/gpgme/.travis.yml32
-rw-r--r--vendor/github.com/mtrmac/gpgme/data.go18
-rw-r--r--vendor/github.com/mtrmac/gpgme/go.mod3
-rw-r--r--vendor/github.com/mtrmac/gpgme/go_gpgme.c22
-rw-r--r--vendor/github.com/mtrmac/gpgme/go_gpgme.h12
-rw-r--r--vendor/github.com/mtrmac/gpgme/gpgme.go346
-rw-r--r--vendor/github.com/mtrmac/gpgme/unset_agent_info.go18
-rw-r--r--vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go14
-rw-r--r--vendor/github.com/onsi/ginkgo/.travis.yml18
-rw-r--r--vendor/github.com/onsi/ginkgo/CHANGELOG.md5
-rw-r--r--vendor/github.com/onsi/ginkgo/config/config.go2
-rw-r--r--vendor/github.com/onsi/ginkgo/go.mod9
-rw-r--r--vendor/github.com/onsi/ginkgo/go.sum26
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/bar_option.go7
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/decor/decorator.go27
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/decor/merge.go45
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/go.mod1
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/go.sum2
-rw-r--r--vendor/github.com/vbauerster/mpb/v4/proxyreader.go8
-rw-r--r--vendor/modules.txt17
-rw-r--r--version/version.go2
146 files changed, 2881 insertions, 1707 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 8f355b3ba..5c4cf470c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -143,6 +143,27 @@ gating_task:
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
+# This task checks to make sure that we can still build an rpm from the
+# source code using contrib/rpm/podman.spec.in
+rpmbuild_task:
+
+ only_if: $CIRRUS_BRANCH != $DEST_BRANCH
+ depends_on:
+ - "gating"
+ env:
+ CIRRUS_WORKING_DIR: "/usr/src/libpod"
+
+ container:
+ image: quay.io/libpod/rpmbuild:$DEST_BRANCH
+ cpu: 2
+ memory: 4
+
+ rpmbuild_script:
+ - 'make -C ${CIRRUS_WORKING_DIR} -f ${CIRRUS_WORKING_DIR}/.copr/Makefile'
+ - 'rpmbuild --rebuild ${CIRRUS_WORKING_DIR}/podman-*.src.rpm'
+
+ on_failure:
+ failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh |& ${TIMESTAMP}'
# This task runs `make vendor` followed by ./hack/tree_status.sh to check
# whether the git tree is clean. The reasoning for that is to make sure
@@ -316,8 +337,10 @@ meta_task:
# Remove old and disused images based on labels set by meta_task
image_prune_task:
- # Do not run this frequently
- only_if: $CIRRUS_BRANCH == $DEST_BRANCH
+ # This should ONLY ever run from the master branch, and never
+ # anywhere else so it's behavior is always consistent, even
+ # as new branches are created.
+ only_if: $CIRRUS_BRANCH == "master"
depends_on:
- "meta"
@@ -683,9 +706,7 @@ docs_task:
# Only run this for PRs on mention, and after merge
only_if: >-
- $CIRRUS_BRANCH == $DEST_BRANCH &&
- $CIRRUS_CHANGE_MESSAGE !=~ '.*CI:IMG.*' &&
- $CIRRUS_CHANGE_MESSAGE =~ '.*CI:DOCS.*'
+ $CIRRUS_BRANCH != $DEST_BRANCH
depends_on:
- "gating"
@@ -712,6 +733,7 @@ success_task:
- "meta"
- "image_prune"
- "testing"
+ - "rpmbuild"
- "special_testing_rootless"
- "special_testing_in_podman"
- "special_testing_cgroupv2"
diff --git a/CODE-OF-CONDUCT.md b/CODE-OF-CONDUCT.md
new file mode 100644
index 000000000..850e68db0
--- /dev/null
+++ b/CODE-OF-CONDUCT.md
@@ -0,0 +1,3 @@
+## The Libpod Project Community Code of Conduct
+
+The Libpod project which includes Podman, follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).
diff --git a/Makefile b/Makefile
index 1e5aa4d77..67e798c8d 100644
--- a/Makefile
+++ b/Makefile
@@ -582,7 +582,7 @@ install.libseccomp.sudo:
cmd/podman/varlink/iopodman.go: .gopathok cmd/podman/varlink/io.podman.varlink
-ifeq ("$(shell uname -o)", "GNU/Linux")
+ifneq (,$(findstring Linux,$(shell uname -s)))
# Only generate the varlink code on Linux (see issue #4814).
GO111MODULE=off $(GO) generate ./cmd/podman/varlink/...
endif
diff --git a/README.md b/README.md
index e7ab48fac..950602e0a 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Libpod provides a library for applications looking to use the Container Pod concept,
popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes.
-* [Latest Version: 1.7.0](https://github.com/containers/libpod/releases/latest)
+* [Latest Version: 1.8.0](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):
@@ -73,9 +73,9 @@ A little configuration by an administrator is required before rootless Podman ca
standard for composing Pods and for orchestrating containers, making
Kubernetes YAML a defacto standard file format. Hence, Podman allows the
creation and execution of Pods from a Kubernetes YAML file (see
- [podman-play-kube](https://github.com/containers/libpod/blob/master/docs/podman-play-kube.1.md)).
+ [podman-play-kube](https://github.com/containers/libpod/blob/master/docs/source/markdown/podman-play-kube.1.md)).
Podman can also generate Kubernetes YAML based on a container or Pod (see
- [podman-generate-kube](https://github.com/containers/libpod/blob/master/docs/podman-generate-kube.1.md)),
+ [podman-generate-kube](https://github.com/containers/libpod/blob/master/docs/source/markdown/podman-generate-kube.1.md)),
which allows for an easy transition from a local development environment
to a production Kubernetes cluster. If Kubernetes does not fit your requirements,
there are other third-party tools that support the docker-compose format such as
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index d961b713e..fc528d70f 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -2,7 +2,7 @@
## 1.8.0
### Features
-- The `podman service` command has been added, providing a preview of Podman's new Docker-compatible API. This API is still very new, and not yet ready for production use, but is available for early testing
+- The `podman system service` command has been added, providing a preview of Podman's new Docker-compatible API. This API is still very new, and not yet ready for production use, but is available for early testing
- Rootless Podman now uses Rootlesskit for port forwarding, which should greatly improve performance and capabilities
- The `podman untag` command has been added to remove tags from images without deleting them
- The `podman inspect` command on images now displays previous names they used
@@ -29,13 +29,20 @@
- Fixed a bug where `podman history` was not computing image sizes correctly ([#4916](https://github.com/containers/libpod/issues/4916))
- Fixed a bug where Podman would not error on invalid values to the `--sort` flag to `podman images`
- Fixed a bug where providing a name for the image made by `podman commit` was mandatory, not optional as it should be ([#5027](https://github.com/containers/libpod/issues/5027))
+- Fixed a bug where the remote Podman client would append an extra `"` to `%PATH` ([#4335](https://github.com/containers/libpod/issues/4335))
+- Fixed a bug where the `podman build` command would sometimes ignore the `-f` option and build the wrong Containerfile
+- Fixed a bug where the `podman ps --filter` command would only filter running containers, instead of all containers, if `--all` was not passed ([#5050](https://github.com/containers/libpod/issues/5050))
+- Fixed a bug where the `podman load` command on compressed images would leave an extra copy on disk
+- Fixed a bug where the `podman restart` command would not properly clean up the network, causing it to function differently from `podman stop; podman start` ([#5051](https://github.com/containers/libpod/issues/5051))
+- Fixed a bug where setting the `--memory-swap` flag to `podman create` and `podman run` to `-1` (to indicate unlimited) was not supported ([#5091](https://github.com/containers/libpod/issues/5091))
### Misc
- Initial work on version 2 of the Podman remote API has been merged, but is still in an alpha state and not ready for use. Read more [here](https://podman.io/releases/2020/01/17/podman-new-api.html)
- Many formatting corrections have been made to the manpages
- The changes to address ([#5009](https://github.com/containers/libpod/issues/5009)) may cause anonymous volumes created by Podman versions 1.6.3 to 1.7.0 to not be removed when their container is removed
- Updated vendored Buildah to v1.13.1
-- Updated vendored containers/storage to v1.15.7
+- Updated vendored containers/storage to v1.15.8
+- Updated vendored containers/image to v5.2.0
## 1.7.0
### Features
diff --git a/changelog.txt b/changelog.txt
index 996c87441..320526596 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,35 @@
+- Changelog for v1.8.0 (2020-02-06)
+ * [CI:DOCS]update contrib systemd user
+ * [CI:DOCS]fix systemd files for apiv2
+ * Update release notes for final release of v1.8.0
+ * Move podman-service to podman-system-service
+ * Only modify conmon cgroup if we have running containers
+ * fix swagger docs and make sure docs validation runs
+ * Special case memory-swap=-1
+ * vendor github.com/mtrmac/gpgme@v0.1.2
+ * vendor github.com/containers/image/v5@v5.2.0
+ * Add Containerfile location e2e test
+ * [CI:DOCS]addition of specgen package
+ * {CI:DOCS] run gofmt before lint
+ * build(deps): bump github.com/onsi/ginkgo from 1.11.0 to 1.12.0
+ * Close tarSource when finished using it
+ * Force --all when --filter is passed to podman ps
+ * Initial implementation of a spec generator package
+ * Fix wrong Containerfile location on build
+ * Wrap error for failing ImageSize calls
+ * swagger: v2: libpod/images/{import,load,pull}
+ * seperate container create network options
+ * Cirrus: Fix gate task + make lint|validate
+ * Add a binding test to check image tag and list commands.
+ * Update /_ping support
+ * [CI:DOCS]add apiv2 endpoints for exec
+ * build(deps): bump github.com/containers/storage from 1.15.7 to 1.15.8
+ * build(deps): bump github.com/onsi/gomega from 1.8.1 to 1.9.0
+ * Tear down network when restarting containers
+ * Move install.md to podman.io, leave link page
+ * Update XML to not embed quote in PATH on windows
+ * Bump to v1.8.0-dev
+
- Changelog for v1.8.0-rc1 (2020-01-31)
* Fix a syntax error in hack/release.sh
* Minor update to release notes
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index ebd7aeb0c..d6018a6f4 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -26,9 +26,6 @@ func getMainCommands() []*cobra.Command {
if len(_varlinkCommand.Use) > 0 {
rootCommands = append(rootCommands, _varlinkCommand)
}
- if len(_serviceCommand.Use) > 0 {
- rootCommands = append(rootCommands, _serviceCommand)
- }
return rootCommands
}
@@ -71,9 +68,15 @@ func getTrustSubCommands() []*cobra.Command {
// Commands that the local client implements
func getSystemSubCommands() []*cobra.Command {
- return []*cobra.Command{
+ systemCommands := []*cobra.Command{
_renumberCommand,
_dfSystemCommand,
_migrateCommand,
}
+
+ if len(_serviceCommand.Use) > 0 {
+ systemCommands = append(systemCommands, _serviceCommand)
+ }
+
+ return systemCommands
}
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 604e8d31c..b4d249c66 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -6,7 +6,6 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
- "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -65,17 +64,6 @@ func commitCmd(c *cliconfig.CommitValues) error {
if len(args) > 1 {
reference = args[1]
}
- if c.Flag("change").Changed {
- for _, change := range c.Change {
- splitChange := strings.Split(strings.ToUpper(change), "=")
- if len(splitChange) == 1 {
- splitChange = strings.Split(strings.ToUpper(change), " ")
- }
- if !util.StringInSlice(splitChange[0], ChangeCmds) {
- return errors.Errorf("invalid syntax for --change: %s", change)
- }
- }
- }
iid, err := runtime.Commit(getContext(), c, container, reference)
if err != nil {
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 7610edbc0..6fa2b3c71 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -257,6 +257,10 @@ func getCreateFlags(c *cliconfig.PodmanCommand) {
"Add a host device to the container (default [])",
)
createFlags.StringSlice(
+ "device-cgroup-rule", []string{},
+ "Add a rule to the cgroup allowed devices list",
+ )
+ createFlags.StringSlice(
"device-read-bps", []string{},
"Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
)
diff --git a/cmd/podman/images.go b/cmd/podman/images.go
index 115f30d9b..de61690ae 100644
--- a/cmd/podman/images.go
+++ b/cmd/podman/images.go
@@ -21,16 +21,16 @@ import (
)
type imagesTemplateParams struct {
- Repository string
- Tag string
- ID string
- Digest digest.Digest
- Digests []digest.Digest
- Created string
- CreatedTime time.Time
- Size string
- ReadOnly bool
- History string
+ Repository string
+ Tag string
+ ID string
+ Digest digest.Digest
+ Digests []digest.Digest
+ CreatedAt time.Time
+ CreatedSince string
+ Size string
+ ReadOnly bool
+ History string
}
type imagesJSONParams struct {
@@ -65,7 +65,7 @@ func (a imagesSorted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type imagesSortedCreated struct{ imagesSorted }
func (a imagesSortedCreated) Less(i, j int) bool {
- return a.imagesSorted[i].CreatedTime.After(a.imagesSorted[j].CreatedTime)
+ return a.imagesSorted[i].CreatedAt.After(a.imagesSorted[j].CreatedAt)
}
type imagesSortedID struct{ imagesSorted }
@@ -185,7 +185,17 @@ func imagesCmd(c *cliconfig.ImagesValues) error {
history: c.History,
}
- opts.outputformat = opts.setOutputFormat()
+ outputformat := opts.setOutputFormat()
+ // These fields were renamed, so we need to provide backward compat for
+ // the old names.
+ if strings.Contains(outputformat, "{{.Created}}") {
+ outputformat = strings.Replace(outputformat, "{{.Created}}", "{{.CreatedSince}}", -1)
+ }
+ if strings.Contains(outputformat, "{{.CreatedTime}}") {
+ outputformat = strings.Replace(outputformat, "{{.CreatedTime}}", "{{.CreatedAt}}", -1)
+ }
+ opts.outputformat = outputformat
+
filteredImages, err := runtime.GetFilteredImages(filters, false)
if err != nil {
return errors.Wrapf(err, "unable to get images")
@@ -216,7 +226,7 @@ func (i imagesOptions) setOutputFormat() string {
if i.digests {
format += "{{.Digest}}\t"
}
- format += "{{.ID}}\t{{.Created}}\t{{.Size}}\t"
+ format += "{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t"
if i.history {
format += "{{if .History}}{{.History}}{{else}}<none>{{end}}\t"
}
@@ -301,16 +311,16 @@ func getImagesTemplateOutput(ctx context.Context, images []*adapter.ContainerIma
imageDigest = img.Digest()
}
params := imagesTemplateParams{
- Repository: repo,
- Tag: tag,
- ID: imageID,
- Digest: imageDigest,
- Digests: img.Digests(),
- CreatedTime: createdTime,
- Created: units.HumanDuration(time.Since(createdTime)) + " ago",
- Size: sizeStr,
- ReadOnly: img.IsReadOnly(),
- History: strings.Join(img.NamesHistory(), ", "),
+ Repository: repo,
+ Tag: tag,
+ ID: imageID,
+ Digest: imageDigest,
+ Digests: img.Digests(),
+ CreatedAt: createdTime,
+ CreatedSince: units.HumanDuration(time.Since(createdTime)) + " ago",
+ Size: sizeStr,
+ ReadOnly: img.IsReadOnly(),
+ History: strings.Join(img.NamesHistory(), ", "),
}
imagesOutput = append(imagesOutput, params)
if opts.quiet { // Show only one image ID when quiet
@@ -384,6 +394,9 @@ func GenImageOutputMap() map[string]string {
values[key] = "R/O"
continue
}
+ if value == "CreatedSince" {
+ value = "created"
+ }
values[key] = strings.ToUpper(splitCamelCase(value))
}
return values
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index 9425cfb9c..e9dc87de1 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -13,32 +13,66 @@ import (
"github.com/pkg/errors"
)
+type runtimeOptions struct {
+ name string
+ renumber bool
+ migrate bool
+ noStore bool
+ withFDS bool
+}
+
// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
func GetRuntimeMigrate(ctx context.Context, c *cliconfig.PodmanCommand, newRuntime string) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, true, false, true, newRuntime)
+ return getRuntime(ctx, c, &runtimeOptions{
+ name: newRuntime,
+ renumber: false,
+ migrate: true,
+ noStore: false,
+ withFDS: true,
+ })
}
// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify
func GetRuntimeDisableFDs(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, false, false, false, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: false,
+ migrate: false,
+ noStore: false,
+ withFDS: false,
+ })
}
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
func GetRuntimeRenumber(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, true, false, false, true, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: true,
+ migrate: false,
+ noStore: false,
+ withFDS: true,
+ })
}
// GetRuntime generates a new libpod runtime configured by command line options
func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, false, false, true, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: false,
+ migrate: false,
+ noStore: false,
+ withFDS: true,
+ })
}
// GetRuntimeNoStore generates a new libpod runtime configured by command line options
func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
- return getRuntime(ctx, c, false, false, true, true, "")
+ return getRuntime(ctx, c, &runtimeOptions{
+ renumber: false,
+ migrate: false,
+ noStore: true,
+ withFDS: true,
+ })
}
-func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migrate, noStore, withFDS bool, newRuntime string) (*libpod.Runtime, error) {
+func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, opts *runtimeOptions) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{}
storageSet := false
@@ -86,14 +120,14 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
storageSet = true
storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
}
- if migrate {
+ if opts.migrate {
options = append(options, libpod.WithMigrate())
- if newRuntime != "" {
- options = append(options, libpod.WithMigrateRuntime(newRuntime))
+ if opts.name != "" {
+ options = append(options, libpod.WithMigrateRuntime(opts.name))
}
}
- if renumber {
+ if opts.renumber {
options = append(options, libpod.WithRenumber())
}
@@ -102,7 +136,7 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
options = append(options, libpod.WithStorageConfig(storageOpts))
}
- if !storageSet && noStore {
+ if !storageSet && opts.noStore {
options = append(options, libpod.WithNoStore())
}
// TODO CLI flags for image config?
@@ -174,7 +208,7 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber, migra
options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
}
- if !withFDS {
+ if !opts.withFDS {
options = append(options, libpod.WithEnableSDNotify())
}
if c.Flags().Changed("config") {
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index d93ccc24c..accd5b51a 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -205,9 +205,15 @@ func checkFlagsPassed(c *cliconfig.PsValues) error {
if c.Last >= 0 && c.Latest {
return errors.Errorf("last and latest are mutually exclusive")
}
- // Filter forces all
+ // Filter on status forces all
if len(c.Filter) > 0 {
- c.All = true
+ for _, filter := range c.Filter {
+ splitFilter := strings.SplitN(filter, "=", 2)
+ if strings.ToLower(splitFilter[0]) == "status" {
+ c.All = true
+ break
+ }
+ }
}
// Quiet conflicts with size and namespace and is overridden by a Go
// template.
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index 1cbb3f45e..f800d68fe 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -4,7 +4,6 @@ import (
"fmt"
"io"
"os"
- "strings"
buildahcli "github.com/containers/buildah/pkg/cli"
"github.com/containers/image/v5/docker"
@@ -15,6 +14,7 @@ import (
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/util"
+ "github.com/docker/distribution/reference"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -101,18 +101,32 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
}
}
- arr := strings.SplitN(args[0], ":", 2)
- if len(arr) == 2 {
- if c.Bool("all-tags") {
- return errors.Errorf("tag can't be used with --all-tags")
+ ctx := getContext()
+ imageName := args[0]
+
+ imageRef, err := alltransports.ParseImageName(imageName)
+ if err != nil {
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s://%s", docker.Transport.Name(), imageName))
+ if err != nil {
+ return errors.Errorf("invalid image reference %q", imageName)
}
}
- ctx := getContext()
- imgArg := args[0]
+ var writer io.Writer
+ if !c.Quiet {
+ writer = os.Stderr
+ }
+ // Special-case for docker-archive which allows multiple tags.
+ if imageRef.Transport().Name() == dockerarchive.Transport.Name() {
+ newImage, err := runtime.LoadFromArchiveReference(getContext(), imageRef, c.SignaturePolicy, writer)
+ if err != nil {
+ return errors.Wrapf(err, "error pulling image %q", imageName)
+ }
+ fmt.Println(newImage[0].ID())
+ return nil
+ }
var registryCreds *types.DockerAuthConfig
-
if c.Flag("creds").Changed {
creds, err := util.ParseRegistryCreds(c.Creds)
if err != nil {
@@ -120,14 +134,6 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
}
registryCreds = creds
}
-
- var (
- writer io.Writer
- )
- if !c.Quiet {
- writer = os.Stderr
- }
-
dockerRegistryOptions := image.DockerRegistryOptions{
DockerRegistryCreds: registryCreds,
DockerCertPath: c.CertDir,
@@ -138,79 +144,52 @@ func pullCmd(c *cliconfig.PullValues) (retError error) {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.TlsVerify)
}
- // Special-case for docker-archive which allows multiple tags.
- if strings.HasPrefix(imgArg, dockerarchive.Transport.Name()+":") {
- srcRef, err := alltransports.ParseImageName(imgArg)
- if err != nil {
- return errors.Wrapf(err, "error parsing %q", imgArg)
- }
- newImage, err := runtime.LoadFromArchiveReference(getContext(), srcRef, c.SignaturePolicy, writer)
- if err != nil {
- return errors.Wrapf(err, "error pulling image from %q", imgArg)
- }
- fmt.Println(newImage[0].ID())
-
- return nil
- }
-
- // FIXME: the default pull consults the registries.conf's search registries
- // while the all-tags pull does not. This behavior must be fixed in the
- // future and span across c/buildah, c/image and c/libpod to avoid redundant
- // and error prone code.
- //
- // See https://bugzilla.redhat.com/show_bug.cgi?id=1701922 for background
- // information.
if !c.Bool("all-tags") {
- newImage, err := runtime.New(getContext(), imgArg, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ newImage, err := runtime.New(getContext(), imageName, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
if err != nil {
- return errors.Wrapf(err, "error pulling image %q", imgArg)
+ return errors.Wrapf(err, "error pulling image %q", imageName)
}
fmt.Println(newImage.ID())
return nil
}
- // FIXME: all-tags should use the libpod backend instead of baking its own bread.
- spec := imgArg
- systemContext := image.GetSystemContext("", c.Authfile, false)
- srcRef, err := alltransports.ParseImageName(spec)
+ // --all-tags requires the docker transport
+ if imageRef.Transport().Name() != docker.Transport.Name() {
+ return errors.New("--all-tags requires docker transport")
+ }
+
+ // all-tags doesn't work with a tagged reference, so let's check early
+ namedRef, err := reference.Parse(imageName)
if err != nil {
- dockerTransport := "docker://"
- logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, dockerTransport, err)
- spec = dockerTransport + spec
- srcRef2, err2 := alltransports.ParseImageName(spec)
- if err2 != nil {
- return errors.Wrapf(err2, "error parsing image name %q", imgArg)
- }
- srcRef = srcRef2
+ return errors.Wrapf(err, "error parsing %q", imageName)
}
- var names []string
- if srcRef.DockerReference() == nil {
- return errors.New("Non-docker transport is currently not supported")
+ if _, isTagged := namedRef.(reference.Tagged); isTagged {
+ return errors.New("--all-tags requires a reference without a tag")
+
}
- tags, err := docker.GetRepositoryTags(ctx, systemContext, srcRef)
+
+ systemContext := image.GetSystemContext("", c.Authfile, false)
+ tags, err := docker.GetRepositoryTags(ctx, systemContext, imageRef)
if err != nil {
return errors.Wrapf(err, "error getting repository tags")
}
- for _, tag := range tags {
- name := spec + ":" + tag
- names = append(names, name)
- }
var foundIDs []string
- foundImage := true
- for _, name := range names {
+ for _, tag := range tags {
+ name := imageName + ":" + tag
newImage, err := runtime.New(getContext(), name, c.SignaturePolicy, c.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
if err != nil {
logrus.Errorf("error pulling image %q", name)
- foundImage = false
continue
}
foundIDs = append(foundIDs, newImage.ID())
}
- if len(names) == 1 && !foundImage {
- return errors.Wrapf(err, "error pulling image %q", imgArg)
+
+ if len(tags) != len(foundIDs) {
+ return errors.Errorf("error pulling image %q", imageName)
}
- if len(names) > 1 {
+
+ if len(foundIDs) > 1 {
fmt.Println("Pulled Images:")
}
for _, id := range foundIDs {
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index 9459247ed..ff3846e70 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -640,6 +640,11 @@ func GetNamespaces(pid int) *Namespace {
}
}
+// GetNamespaceInfo is an exported wrapper for getNamespaceInfo
+func GetNamespaceInfo(path string) (string, error) {
+ return getNamespaceInfo(path)
+}
+
func getNamespaceInfo(path string) (string, error) {
val, err := os.Readlink(path)
if err != nil {
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 2f637694b..be5adcccb 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -22,6 +22,7 @@ import (
"github.com/containers/libpod/pkg/inspect"
ns "github.com/containers/libpod/pkg/namespaces"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/seccomp"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/util"
"github.com/docker/go-connections/nat"
@@ -31,10 +32,6 @@ import (
"github.com/sirupsen/logrus"
)
-// seccompLabelKey is the key of the image annotation embedding a seccomp
-// profile.
-const seccompLabelKey = "io.containers.seccomp.profile"
-
func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime) (*libpod.Container, *cc.CreateConfig, error) {
var (
healthCheck *manifest.Schema2HealthConfig
@@ -109,11 +106,11 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
if overrideOS == "" && imageData.Os != goruntime.GOOS {
- return nil, nil, errors.Errorf("incompatible image OS %q on %q host", imageData.Os, goruntime.GOOS)
+ logrus.Infof("Using %q (OS) image on %q host", imageData.Os, goruntime.GOOS)
}
if overrideArch == "" && imageData.Architecture != goruntime.GOARCH {
- return nil, nil, errors.Errorf("incompatible image architecture %q on %q host", imageData.Architecture, goruntime.GOARCH)
+ logrus.Infof("Using %q (architecture) on %q host", imageData.Architecture, goruntime.GOARCH)
}
names := newImage.Names()
@@ -309,9 +306,13 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
if c.String("memory-swap") != "" {
- memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-swap")
+ if c.String("memory-swap") == "-1" {
+ memorySwap = -1
+ } else {
+ memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
+ if err != nil {
+ return nil, errors.Wrapf(err, "invalid value for memory-swap")
+ }
}
}
if c.String("kernel-memory") != "" {
@@ -709,11 +710,11 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
// SECCOMP
if data != nil {
- if value, exists := labels[seccompLabelKey]; exists {
+ if value, exists := labels[seccomp.ContainerImageLabel]; exists {
secConfig.SeccompProfileFromImage = value
}
}
- if policy, err := cc.LookupSeccompPolicy(c.String("seccomp-policy")); err != nil {
+ if policy, err := seccomp.LookupPolicy(c.String("seccomp-policy")); err != nil {
return nil, err
} else {
secConfig.SeccompPolicy = policy
@@ -757,6 +758,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
CPURtPeriod: c.Uint64("cpu-rt-period"),
CPURtRuntime: c.Int64("cpu-rt-runtime"),
CPUs: c.Float64("cpus"),
+ DeviceCgroupRules: c.StringSlice("device-cgroup-rule"),
DeviceReadBps: c.StringSlice("device-read-bps"),
DeviceReadIOps: c.StringSlice("device-read-iops"),
DeviceWriteBps: c.StringSlice("device-write-bps"),
diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go
index cfb3f612c..ee212234f 100644
--- a/cmd/podman/shared/intermediate.go
+++ b/cmd/podman/shared/intermediate.go
@@ -386,6 +386,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes
m["detach"] = newCRBool(c, "detach")
m["detach-keys"] = newCRString(c, "detach-keys")
m["device"] = newCRStringSlice(c, "device")
+ m["device-cgroup-rule"] = newCRStringSlice(c, "device-cgroup-rule")
m["device-read-bps"] = newCRStringSlice(c, "device-read-bps")
m["device-read-iops"] = newCRStringSlice(c, "device-read-iops")
m["device-write-bps"] = newCRStringSlice(c, "device-write-bps")
diff --git a/code-of-conduct.md b/code-of-conduct.md
deleted file mode 100644
index 215ce7ac6..000000000
--- a/code-of-conduct.md
+++ /dev/null
@@ -1,55 +0,0 @@
-## Kubernetes Community Code of Conduct
-
-### Contributor Code of Conduct
-
-As contributors and maintainers of this project, and in the interest of fostering
-an open and welcoming community, we pledge to respect all people who contribute
-through reporting issues, posting feature requests, updating documentation,
-submitting pull requests or patches, and other activities.
-
-We are committed to making participation in this project a harassment-free experience for
-everyone, regardless of level of experience, gender, gender identity and expression,
-sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
-religion, or nationality.
-
-Examples of unacceptable behavior by participants include:
-
-* The use of sexualized language or imagery.
-* Personal attacks.
-* Trolling or insulting/derogatory comments.
-* Public or private harassment.
-* Publishing other's private information, such as physical or electronic addresses,
- without explicit permission.
-* Other unethical or unprofessional conduct.
-
-Project maintainers have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions that are not
-aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers
-commit themselves to fairly and consistently applying these principles to every aspect
-of managing this project. Project maintainers who do not follow or enforce the Code of
-Conduct may be permanently removed from the project team.
-
-This code of conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community.
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a Kubernetes maintainer, Sarah Novotny <sarahnovotny@google.com>, and/or Dan Kohn <dan@linuxfoundation.org>.
-
-This Code of Conduct is adapted from the Contributor Covenant
-(http://contributor-covenant.org), version 1.2.0, available at
-http://contributor-covenant.org/version/1/2/0/
-
-### Kubernetes Events Code of Conduct
-
-Kubernetes events are working conferences intended for professional networking and collaboration in the
-Kubernetes community. Attendees are expected to behave according to professional standards and in accordance
-with their employer's policies on appropriate workplace behavior.
-
-While at Kubernetes events or related social networking opportunities, attendees should not engage in
-discriminatory or offensive speech or actions regarding gender, sexuality, race, or religion. Speakers should
-be especially aware of these concerns.
-
-The Kubernetes team does not condone any statements by speakers contrary to these standards. The Kubernetes
-team reserves the right to deny entrance and/or eject from an event (without refund) any individual found to
-be engaging in discriminatory or offensive speech or actions.
-
-Please bring any concerns to the immediate attention of the Kubernetes event staff.
diff --git a/completions/bash/podman b/completions/bash/podman
index 57b9547a7..d1dcef0a4 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -1200,6 +1200,19 @@ _podman_system_prune() {
esac
}
+_podman_system_service() {
+ local options_with_args="
+ -t
+ --timeout
+ "
+ local boolean_options="
+ --help
+ -h
+ --varlink
+ "
+ _complete_ "$options_with_args" "$boolean_options"
+}
+
_podman_system() {
local boolean_options="
--help
@@ -1208,8 +1221,11 @@ _podman_system() {
subcommands="
df
info
+ migrate
prune
+ renumber
reset
+ service
"
__podman_subcommands "$subcommands" && return
@@ -1298,7 +1314,6 @@ _podman_build() {
--net
--network
--pid
- --runtime
--runtime-flag
--security-opt
--shm-size
@@ -1316,15 +1331,10 @@ _podman_build() {
-v
"
- local all_options="$options_with_args $boolean_options"
-
- case "$prev" in
- --runtime)
- COMPREPLY=($(compgen -W 'runc runv' -- "$cur"))
+ case "$prev" in
+ --file|-f)
+ COMPREPLY=($(compgen -W "`ls`" -- "$cur"))
;;
- $(__podman_to_extglob "$options_with_args"))
- return
- ;;
esac
case "$cur" in
@@ -1755,19 +1765,6 @@ _podman_search() {
_complete_ "$options_with_args" "$boolean_options"
}
-_podman_service() {
- local options_with_args="
- -t
- --timeout
- "
- local boolean_options="
- --help
- -h
- --varlink
- "
- _complete_ "$options_with_args" "$boolean_options"
-}
-
_podman_unmount() {
_podman_umount $@
}
@@ -1876,6 +1873,7 @@ _podman_container_run() {
--cpuset-mems
--cpu-shares -c
--device
+ --device-cgroup-rule
--device-read-bps
--device-read-iops
--device-write-bps
diff --git a/contrib/fedora-minimal/Dockerfile b/contrib/fedora-minimal/Dockerfile
new file mode 100644
index 000000000..8ea4e6765
--- /dev/null
+++ b/contrib/fedora-minimal/Dockerfile
@@ -0,0 +1 @@
+FROM fedora-minimal:latest
diff --git a/contrib/fedora-minimal/README.md b/contrib/fedora-minimal/README.md
new file mode 100644
index 000000000..52bf94b53
--- /dev/null
+++ b/contrib/fedora-minimal/README.md
@@ -0,0 +1,4 @@
+This dockerfile exists so that the container image can be "mirrored"
+onto quay.io automatically, so automated testing can be more resilient.
+
+https://quay.io/repository/libpod/fedora-minimal?tab=builds
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index a64f473f4..276dd327e 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -43,7 +43,7 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
-Version: 1.8.0
+Version: 1.8.1
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
@@ -385,6 +385,7 @@ mkdir -p src/%{provider}.%{provider_tld}/%{project}
ln -s ../../../../ src/%{import_path}
popd
ln -s vendor src
+export GO111MODULE=off
export GOPATH=$(pwd)/_build:$(pwd):$(pwd):%{gopath}
export BUILDTAGS="varlink selinux seccomp $(%{hackdir}/hack/btrfs_installed_tag.sh) $(%{hackdir}/hack/btrfs_tag.sh) $(%{hackdir}/hack/libdm_tag.sh) exclude_graphdriver_devicemapper"
@@ -507,7 +508,7 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath}
%files
%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md
+%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
%{_bindir}/%{name}
%{_datadir}/bash-completion/completions/*
%{_datadir}/zsh/site-functions/*
@@ -523,19 +524,19 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath}
%if 0%{?with_devel}
%files -n libpod-devel -f devel.file-list
%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md
+%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
%dir %{gopath}/src/%{provider}.%{provider_tld}/%{project}
%endif
%if 0%{?with_unit_test} && 0%{?with_devel}
%files unit-test-devel -f unit-test-devel.file-list
%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md
+%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
%endif
%files -n podman-remote
%license LICENSE
-%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md
+%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md CODE-OF-CONDUCT.md transfer.md
%{_bindir}/%{name}-remote
%if %{with doc}
diff --git a/contrib/spec/python-podman.spec.in b/contrib/spec/python-podman.spec.in
index 6296586dd..b921f2645 100644
--- a/contrib/spec/python-podman.spec.in
+++ b/contrib/spec/python-podman.spec.in
@@ -92,7 +92,7 @@ popd
%files
%license LICENSE
-%doc README.md CONTRIBUTING.md install.md code-of-conduct.md transfer.md
+%doc README.md CONTRIBUTING.md install.md CODE-OF-CONDUCT.md transfer.md
%{_bindir}/pypodman
%{_mandir}/man1/pypodman.1*
%dir %{python3_sitelib}/podman
diff --git a/contrib/systemd/README.md b/contrib/systemd/README.md
index ff266c6a5..9f1d37792 100644
--- a/contrib/systemd/README.md
+++ b/contrib/systemd/README.md
@@ -2,11 +2,6 @@
## system-wide (podman service run as root)
-The following unit file examples assume:
- 1. copied the `service` executable into `/usr/local/bin`
- 1. `chcon system_u:object_r:container_runtime_exec_t:s0 /usr/local/bin/service`
-
-then:
1. copy the `podman.service` and `podman.socket` files into `/etc/systemd/system`
1. `systemctl daemon-reload`
1. `systemctl enable podman.socket`
@@ -16,47 +11,12 @@ then:
Assuming the status messages show no errors, the libpod service is ready to respond to the APIv2 on the unix domain socket `/run/podman/podman.sock`
### podman.service
-```toml
-[Unit]
-Description=Podman API Service
-Requires=podman.socket
-After=podman.socket
-Documentation=man:podman-api(1)
-StartLimitIntervalSec=0
-
-[Service]
-Type=oneshot
-Environment=REGISTRIES_CONFIG_PATH=/etc/containers/registries.conf
-ExecStart=/usr/local/bin/service
-TimeoutStopSec=30
-KillMode=process
-
-[Install]
-WantedBy=multi-user.target
-Also=podman.socket
-```
+You can refer to [this example](https://github.com/containers/libpod/blob/master/contrib/systemd/system/podman.service) for a sample podman.service file.
### podman.socket
+You can refer to [this example](https://github.com/containers/libpod/blob/master/contrib/systemd/system/podman.socket) for a sample podman.socket file.
-```toml
-[Unit]
-Description=Podman API Socket
-Documentation=man:podman-api(1)
-
-[Socket]
-ListenStream=%t/podman/podman.sock
-SocketMode=0660
-
-[Install]
-WantedBy=sockets.target
-```
## user (podman service run as given user aka "rootless")
-The following unit file examples assume:
- 1. you have a created a directory `~/bin`
- 1. copied the `service` executable into `~/bin`
- 1. `chcon system_u:object_r:container_runtime_exec_t:s0 ~/bin/service`
-
-then:
1. `mkdir -p ~/.config/systemd/user`
1. copy the `podman.service` and `podman.socket` files into `~/.config/systemd/user`
1. `systemctl --user enable podman.socket`
@@ -66,37 +26,7 @@ then:
Assuming the status messages show no errors, the libpod service is ready to respond to the APIv2 on the unix domain socket `/run/user/$(id -u)/podman/podman.sock`
### podman.service
+You can refer to [this example](https://github.com/containers/libpod/blob/master/contrib/systemd/user/podman.service) for a rootless podman.service file.
-```toml
-[Unit]
-Description=Podman API Service
-Requires=podman.socket
-After=podman.socket
-Documentation=man:podman-api(1)
-StartLimitIntervalSec=0
-
-[Service]
-Type=oneshot
-Environment=REGISTRIES_CONFIG_PATH=/etc/containers/registries.conf
-ExecStart=%h/bin/service
-TimeoutStopSec=30
-KillMode=process
-
-[Install]
-WantedBy=multi-user.target
-Also=podman.socket
-```
### podman.socket
-
-```toml
-[Unit]
-Description=Podman API Socket
-Documentation=man:podman-api(1)
-
-[Socket]
-ListenStream=%t/podman/podman.sock
-SocketMode=0660
-
-[Install]
-WantedBy=sockets.target
-```
+You can refer to [this example](https://github.com/containers/libpod/blob/master/contrib/systemd/user/podman.socket) for a rootless podman.socket file.
diff --git a/contrib/systemd/system/podman.service b/contrib/systemd/system/podman.service
index 13d858627..eaa2ec437 100644
--- a/contrib/systemd/system/podman.service
+++ b/contrib/systemd/system/podman.service
@@ -8,7 +8,7 @@ StartLimitIntervalSec=0
[Service]
Type=oneshot
Environment=REGISTRIES_CONFIG_PATH=/etc/containers/registries.conf
-ExecStart=/usr/local/bin/service
+ExecStart=/usr/bin/podman system service
TimeoutStopSec=30
KillMode=process
diff --git a/contrib/systemd/user/podman.service b/contrib/systemd/user/podman.service
index 81fa55cf8..eaa2ec437 100644
--- a/contrib/systemd/user/podman.service
+++ b/contrib/systemd/user/podman.service
@@ -8,7 +8,7 @@ StartLimitIntervalSec=0
[Service]
Type=oneshot
Environment=REGISTRIES_CONFIG_PATH=/etc/containers/registries.conf
-ExecStart=%h/bin/service
+ExecStart=/usr/bin/podman system service
TimeoutStopSec=30
KillMode=process
diff --git a/docs/source/markdown/podman-build.1.md b/docs/source/markdown/podman-build.1.md
index 0f3bfa0d3..738644c16 100644
--- a/docs/source/markdown/podman-build.1.md
+++ b/docs/source/markdown/podman-build.1.md
@@ -178,7 +178,7 @@ Add a host device to the container. The format is `<device-on-host>[:<device-on-
Note: if the user only has access rights via a group then accessing the device
from inside a rootless container will fail. The `crun` runtime offers a
-workaround for this by adding the option `--annotation io.crun.keep_original_groups=1`.
+workaround for this by adding the option `--annotation run.oci.keep_original_groups=1`.
**--disable-compression, -D**
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 0e641f3a3..ca38be6a1 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -207,7 +207,14 @@ Add a host device to the container. The format is `<device-on-host>[:<device-on-
Note: if the user only has access rights via a group then accessing the device
from inside a rootless container will fail. The `crun` runtime offers a
-workaround for this by adding the option `--annotation io.crun.keep_original_groups=1`.
+workaround for this by adding the option `--annotation run.oci.keep_original_groups=1`.
+
+**--device-cgroup-rule**="type major:minor mode"
+
+Add a rule to the cgroup allowed devices list. The rule is expected to be in the format specified in the Linux kernel documentation (Documentation/cgroup-v1/devices.txt):
+ - type: a (all), c (char), or b (block);
+ - major and minor: either a number, or * for all;
+ - mode: a composition of r (read), w (write), and m (mknod(2)).
**--device-read-bps**=*path*
diff --git a/docs/source/markdown/podman-images.1.md b/docs/source/markdown/podman-images.1.md
index 21fca1dbd..d22fb940f 100644
--- a/docs/source/markdown/podman-images.1.md
+++ b/docs/source/markdown/podman-images.1.md
@@ -51,6 +51,18 @@ Filter output based on conditions provided
Change the default output format. This can be of a supported type like 'json'
or a Go template.
+Valid placeholders for the Go template are listed below:
+
+| **Placeholder** | **Description** |
+| --------------- | ----------------------------------------------------------------------------- |
+| .ID | Image ID |
+| .Repository | Image repository |
+| .Tag | Image tag |
+| .Digest | Image digest |
+| .CreatedSince | Elapsed time since the image was created |
+| .CreatedAt | Time when the image was created |
+| .Size | Size of layer on disk |
+| .History | History of the image layer |
**--history**
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index bf79ea031..3befc74c8 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -213,7 +213,7 @@ Add a host device to the container. The format is `<device-on-host>[:<device-on-
Note: if the user only has access rights via a group then accessing the device
from inside a rootless container will fail. The `crun` runtime offers a
-workaround for this by adding the option `--annotation io.crun.keep_original_groups=1`.
+workaround for this by adding the option `--annotation run.oci.keep_original_groups=1`.
**--device-read-bps**=*path*
diff --git a/docs/source/markdown/podman-service.1.md b/docs/source/markdown/podman-system-service.1.md
index 5c55e20d3..a2fefe4dd 100644
--- a/docs/source/markdown/podman-service.1.md
+++ b/docs/source/markdown/podman-system-service.1.md
@@ -1,13 +1,13 @@
% podman-service(1)
## NAME
-podman\-service - Run an API service
+podman\-system\-service - Run an API service
## SYNOPSIS
-**podman service** [*options*]
+**podman system service** [*options*]
## DESCRIPTION
-The **podman service** command creates a listening service that will answer API calls for Podman. You may
+The **podman system service** command creates a listening service that will answer API calls for Podman. You may
optionally provide an endpoint for the API in URI form. For example, *unix://tmp/foobar.sock* or *tcp:localhost:8080*.
If no endpoint is provided, defaults will be used. The default endpoint for a rootfull
service is *unix:/run/podman/podman.sock* and rootless is *unix:/$XDG_RUNTIME_DIR/podman/podman.sock* (for
@@ -32,12 +32,12 @@ Print usage statement.
Run an API listening for 5 seconds using the default socket.
```
-podman service --timeout 5000
+podman system service --timeout 5000
```
Run the podman varlink service with an alternate URI and accept the default timeout.
```
-$ podman service --varlink unix:/tmp/io.podman
+$ podman system service --varlink unix:/tmp/io.podman
```
## SEE ALSO
diff --git a/docs/source/markdown/podman-system.1.md b/docs/source/markdown/podman-system.1.md
index 1af97290d..5f163c6f0 100644
--- a/docs/source/markdown/podman-system.1.md
+++ b/docs/source/markdown/podman-system.1.md
@@ -19,6 +19,8 @@ The system command allows you to manage the podman systems
| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused container, image and volume data. |
| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. |
| reset | [podman-system-reset(1)](podman-system-reset.1.md) | Reset storage back to initial state. |
+| service | [podman-service(1)](podman-system-service.1.md) | Run an API service |
+
## SEE ALSO
podman(1)
diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md
index af0e55925..853b5ecec 100644
--- a/docs/source/markdown/podman.1.md
+++ b/docs/source/markdown/podman.1.md
@@ -191,7 +191,6 @@ the exit codes follow the `chroot` standard, see below:
| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
| [podman-run(1)](podman-run.1.md) | Run a command in a new container. |
| [podman-save(1)](podman-save.1.md) | Save an image to a container archive. |
-| [podman-service(1)](podman-service.1.md) | Run an API service |
| [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
| [podman-start(1)](podman-start.1.md) | Start one or more containers. |
| [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. |
diff --git a/go.mod b/go.mod
index b6ad7bf14..076a22808 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/containernetworking/plugins v0.8.5
github.com/containers/buildah v1.13.1
github.com/containers/conmon v2.0.10+incompatible
- github.com/containers/image/v5 v5.1.0
+ github.com/containers/image/v5 v5.2.1
github.com/containers/psgo v1.4.0
github.com/containers/storage v1.15.8
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
@@ -38,7 +38,7 @@ require (
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/google/uuid v1.1.1
github.com/gorilla/handlers v1.4.2 // indirect
- github.com/gorilla/mux v1.7.3
+ github.com/gorilla/mux v1.7.4
github.com/gorilla/schema v1.1.0
github.com/hashicorp/go-multierror v1.0.0
github.com/hpcloud/tail v1.0.0
@@ -46,7 +46,7 @@ require (
github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd // indirect
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
github.com/olekukonko/tablewriter v0.0.4 // indirect
- github.com/onsi/ginkgo v1.11.0
+ github.com/onsi/ginkgo v1.12.0
github.com/onsi/gomega v1.9.0
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
@@ -77,8 +77,8 @@ require (
google.golang.org/appengine v1.6.1 // indirect
google.golang.org/genproto v0.0.0-20190620144150-6af8c5fc6601 // indirect
gopkg.in/yaml.v2 v2.2.8
- k8s.io/api v0.17.2
- k8s.io/apimachinery v0.17.2
+ k8s.io/api v0.17.3
+ k8s.io/apimachinery v0.17.3
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a // indirect
)
diff --git a/go.sum b/go.sum
index 628ef0f95..691c580ec 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,5 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg=
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@@ -8,18 +7,13 @@ github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/DataDog/zstd v1.4.0 h1:vhoV+DUHnRZdKW1i5UMjAk2G4JY8wN4ayRfYDNdEhwo=
github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
-github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
-github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
-github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
-github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c h1:YMP6olTU903X3gxQJckdmiP8/zkSMq4kN3uipsU9XjU=
github.com/Microsoft/hcsshim v0.8.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8=
github.com/Microsoft/hcsshim v0.8.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg=
github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
@@ -30,17 +24,17 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
+github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
+github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
-github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
@@ -66,59 +60,38 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
-github.com/containernetworking/cni v0.7.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK31EJ9FzE=
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784 h1:rqUVLD8I859xRgUx/WMC3v7QAFqbLKZbs+0kqYboRJc=
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
-github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w=
-github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc=
github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7/Eu+jpahihy8=
github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o=
-github.com/containers/buildah v1.12.0 h1:bi/8ACl8qobazwfYgNze5y+aRuBIG+R7lMStFbnDOxE=
-github.com/containers/buildah v1.12.0/go.mod h1:yzPuQ/mJTPsfSLCyBPbeaoXgBLanjnf36M2cDzyckMg=
github.com/containers/buildah v1.13.1 h1:EdhllQxXmOZ56mGFf68AkrpIj9XtEkkGq0WaPWFuGM0=
github.com/containers/buildah v1.13.1/go.mod h1:U0LcOzSqoYdyQC5L2hMeLbtCDuCCLxmZV1eb+SWY4GA=
-github.com/containers/common v0.0.3 h1:C2Zshb0w720FqPa42MCRuiGfbW0kwbURRwvK1EWIC5I=
-github.com/containers/common v0.0.3/go.mod h1:CaOgMRiwi2JJHISMZ6VPPZhQYFUDRv3YYVss2RqUCMg=
github.com/containers/common v0.0.7 h1:eKYZLKfJ2d/RNDgecLDFv45cHb4imYzIcrQHx1Y029M=
github.com/containers/common v0.0.7/go.mod h1:lhWV3MLhO1+KGE2x6v9+K38MxpjXGso+edmpkFnCOqI=
-github.com/containers/conmon v2.0.9+incompatible h1:YcEgk0Ny1WBdH35M2LKe2cG6FiQqzDdVaURw84XvS7A=
-github.com/containers/conmon v2.0.9+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/conmon v2.0.10+incompatible h1:EiwL41r5vx8SxG+dyUmbJ3baV9GUWjijPOdCkzM6gWU=
github.com/containers/conmon v2.0.10+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
-github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqdBDn4=
-github.com/containers/image/v5 v5.0.0/go.mod h1:MgiLzCfIeo8lrHi+4Lb8HP+rh513sm0Mlk6RrhjFOLY=
-github.com/containers/image/v5 v5.1.0 h1:5FjAvPJniamuNNIQHkh4PnsL+n+xzs6Aonzaz5dqTEo=
github.com/containers/image/v5 v5.1.0/go.mod h1:BKlMD34WxRo1ruGHHEOrPQP0Qci7SWoPwU6fS7arsCU=
+github.com/containers/image/v5 v5.2.0 h1:DowY5OII5x9Pb6Pt76vnHU79BgG4/jdwhZjeAj2R+t8=
+github.com/containers/image/v5 v5.2.0/go.mod h1:IAub4gDGvXoxaIAdNy4e3FbVTDPVNMv9F0UfVVFbYCU=
+github.com/containers/image/v5 v5.2.1 h1:rQR6QSUneWBoW1bTFpP9EJJTevQFv27YsKYQVJIzg+s=
+github.com/containers/image/v5 v5.2.1/go.mod h1:TfhmLwH+v1/HBVPIWH7diLs8XwcOkP3c7t7JFgqaUEc=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741 h1:8tQkOcednLJtUcZgK7sPglscXtxvMOnFOa6wd09VWLM=
github.com/containers/ocicrypt v0.0.0-20190930154801-b87a4a69c741/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
github.com/containers/psgo v1.4.0 h1:D8B4fZCCZhYgc8hDyMPCiShOinmOB1TP1qe46sSC19k=
github.com/containers/psgo v1.4.0/go.mod h1:ENXXLQ5E1At4K0EUsGogXBJi/C28gwqkONWeLPI9fJ8=
-github.com/containers/storage v1.13.2/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA=
-github.com/containers/storage v1.13.4 h1:j0bBaJDKbUHtAW1MXPFnwXJtqcH+foWeuXK1YaBV5GA=
-github.com/containers/storage v1.13.4/go.mod h1:6D8nK2sU9V7nEmAraINRs88ZEscM5C5DK+8Npp27GeA=
github.com/containers/storage v1.13.5/go.mod h1:HELz8Sn+UVbPaUZMI8RvIG9doD4y4z6Gtg4k7xdd2ZY=
-github.com/containers/storage v1.15.3 h1:+lFSQZnnKUFyUEtguIgdoQLJfWSuYz+j/wg5GxLtsN4=
github.com/containers/storage v1.15.3/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
-github.com/containers/storage v1.15.4 h1:eiUtV9MOTnPHibO18nDRI+aDhKudY7WmAiJdyVMsqSM=
-github.com/containers/storage v1.15.4/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
-github.com/containers/storage v1.15.5 h1:dBZx9yRFHod9c8FVaXlVtRqr2cmlAhpl+9rt87cE7J4=
github.com/containers/storage v1.15.5/go.mod h1:v0lq/3f+cXH3Y/HiDaFYRR0zilwDve7I4W7U5xQxvF8=
-github.com/containers/storage v1.15.7 h1:ecPmv2y/qpxeSTHZ147jQLO6to8wDn8yUPtDCZlz0H4=
-github.com/containers/storage v1.15.7/go.mod h1:gLZIp+/hP8nFn9tLS0uJlnk4h1tSoDu3oS2eFiaIqkE=
github.com/containers/storage v1.15.8 h1:ef7OfUMTpyq0PIVAhV7qfufEI92gAldk25nItrip+6Q=
github.com/containers/storage v1.15.8/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
-github.com/coreos/go-iptables v0.4.2 h1:KH0EwId05JwWIfb96gWvkiT2cbuOu8ygqUaB+yPAwIg=
-github.com/coreos/go-iptables v0.4.2/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c=
@@ -140,19 +113,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/docker/distribution v0.0.0-20170817175659-5f6282db7d65 h1:4zlOyrJUbYnrvlzChJ+jP2J3i77Jbhm336NEuCv7kZo=
github.com/docker/distribution v0.0.0-20170817175659-5f6282db7d65/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.0.0-20171019062838-86f080cff091/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.0.0-20180522102801-da99009bbb11/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23 h1:oqgGT9O61YAYvI41EBsLePOr+LE6roB0xY4gpkZuFSE=
github.com/docker/docker v1.4.2-0.20191101170500-ac7306503d23/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f h1:Sm8iD2lifO31DwXfkGzq8VgA7rwxPjRsYmeo0K/dF9Y=
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
-github.com/docker/docker-credential-helpers v0.6.1 h1:Dq4iIfcM7cNtddhLVWe9h4QDjsi4OER3Z8voPu/I52g=
-github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.0.0-20180212134524-7beb39f0b969/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
@@ -164,17 +132,13 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316 h1:moehPjPiGUaWdwgOl92xRyFHJyaqXDHcCyW9M6nmCK4=
github.com/docker/libnetwork v0.8.0-dev.2.0.20190625141545-5a177b73e316/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
-github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s=
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
-github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
-github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs=
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
-github.com/elazarl/goproxy/ext v0.0.0-20190911111923-ecfe977594f1 h1:8B7WF1rIoM8H1smfpXFvOawSAzlRDMVzoGu9zE3+OCk=
github.com/elazarl/goproxy/ext v0.0.0-20190911111923-ecfe977594f1/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@@ -182,7 +146,6 @@ github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -194,7 +157,6 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
github.com/ghodss/yaml v0.0.0-20161207003320-04f313413ffd/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/go-ini/ini v1.51.1 h1:/QG3cj23k5V8mOl4JnNzUNhc1kr/jzMiNsNuWKcx8gM=
github.com/go-ini/ini v1.51.1/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -219,29 +181,23 @@ github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j
github.com/gogo/protobuf v0.0.0-20170815085658-fcdc5011193f/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
-github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -250,16 +206,15 @@ github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIE
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
-github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
-github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v0.0.0-20170217192616-94e7d24fd285/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
+github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY=
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
@@ -277,8 +232,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
-github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
-github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
@@ -290,11 +243,8 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t
github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -305,17 +255,11 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.7.2 h1:liMOoeIvFpr9kEvalrZ7VVBA4wGf7zfOgwBjzz/5g2Y=
github.com/klauspost/compress v1.7.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.8.1 h1:oygt2ychZFHOB6M9gUgajzgKrwRgHbGC77NwA4COVgI=
github.com/klauspost/compress v1.8.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.9.4 h1:xhvAeUPQ2drNUhKtrGdTGNvV9nNafHMUkRyLkzxJoB4=
github.com/klauspost/compress v1.9.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug26aA=
-github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA=
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@@ -323,28 +267,20 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
-github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
-github.com/mattn/go-shellwords v1.0.5 h1:JhhFTIOslh5ZsPrpa3Wdg8bF0WI3b44EMblmU9wIsXc=
github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
-github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3ZkeUUI=
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
-github.com/mattn/go-shellwords v1.0.7 h1:KqhVjVZomx2puPACkj9vrGFqnp42Htvo9SEAWePHKOs=
-github.com/mattn/go-shellwords v1.0.7/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.9 h1:eaB5JspOwiKKcHdqcjbfe5lA9cNn/4NRRtddXJCimqk=
github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@@ -364,51 +300,44 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
-github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd h1:3k5dpxjeXlUuz8STW9BE2WsvPnaMcmlfGKAbe3J5v+0=
github.com/mrtazz/checkmake v0.0.0-20191009095831-03dd76b964dd/go.mod h1:YBPKCT1PrhoFU743gPdtJNp+LmM0QlGMWME1J+FJtQI=
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM=
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
-github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c h1:xa+eQWKuJ9MbB9FBL/eoNvDFvveAkz2LQoz8PzX7Q/4=
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c/go.mod h1:GhAqVMEWnTcW2dxoD/SO3n2enrgWl3y6Dnx4m59GvcA=
+github.com/mtrmac/gpgme v0.1.1/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI=
+github.com/mtrmac/gpgme v0.1.2 h1:dNOmvYmsrakgW7LcgiprD0yfRuQQe8/C8F6Z+zogO3s=
+github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
-github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
-github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
+github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.8.1 h1:C5Dqfs/LeauYDX0jJXIe2SWmwCbGzx9yF8C8xy3Lh34=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 h1:yN8BPXVwMBAm3Cuvh1L5XE8XpvYRMdsVLd82ILprhUU=
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.0.0-20190425234816-dae70e8efea4/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v1.0.0-rc8 h1:dDCFes8Hj1r/i5qnypONo5jdOme/8HWZC/aNDyhECt0=
github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190827142921-dd075602f158/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc=
@@ -419,16 +348,12 @@ github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.m
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
-github.com/opencontainers/selinux v1.2.2 h1:Kx9J6eDG5/24A6DtUquGSpJQ+m2MUTahn4FtGEe8bFg=
github.com/opencontainers/selinux v1.2.2/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
-github.com/opencontainers/selinux v1.3.0 h1:xsI95WzPZu5exzA6JzkLSfdr/DilzOhCJOqGe5TgR0g=
github.com/opencontainers/selinux v1.3.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
github.com/opencontainers/selinux v1.3.1 h1:dn2Rc3wTEvTB6iVqoFrKKeMb0uZ38ZheeyMu2h5C1TI=
github.com/opencontainers/selinux v1.3.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316 h1:enQG2QUGwug4fR1yM6hL0Fjzx6Km/exZY6RbSPwMu3o=
github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316/go.mod h1:dv+J0b/HWai0QnMVb37/H0v36klkLBi2TNpPeWDxX10=
-github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible h1:s55wx8JIG/CKnewev892HifTBrtKzMdvgB3rm4rxC2s=
-github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
github.com/openshift/imagebuilder v1.1.1 h1:KAUR31p8UBJdfVO42azWgb+LeMAed2zaKQ19e0C0X2I=
github.com/openshift/imagebuilder v1.1.1/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
@@ -439,23 +364,18 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.0.0-20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k=
github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI=
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7 h1:gGBSHPOU7g8YjTbhwn+lvFm2VDEhhA+PwDIlstkgSxE=
github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9 h1:kyf9snWXHvQc+yxE9imhdI8YAm4oKeZISlaAR+x73zs=
github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8=
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
@@ -466,23 +386,18 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
-github.com/rootless-containers/rootlesskit v0.7.1 h1:enhwHIAXDjfpV83bL4xF60WZ+1ATjMB7spDDvpWAfPk=
-github.com/rootless-containers/rootlesskit v0.7.1/go.mod h1:r9YL5mKRIdnwcYk4G8E5CSc9MDeFtgYmhfE4CSvDGYA=
github.com/rootless-containers/rootlesskit v0.7.2 h1:gcWQ9/GN98ne1AqnoeOgQ8e6qpKd3BuB4ug+2h95Fr0=
github.com/rootless-containers/rootlesskit v0.7.2/go.mod h1:r9YL5mKRIdnwcYk4G8E5CSc9MDeFtgYmhfE4CSvDGYA=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4 h1:rOG9oHVIndNR14f3HRyBy9UPQYmIPniWqTU1TDdHhq4=
github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4/go.mod h1:f/98/SnvAzhAEFQJ3u836FePXvcbE8BS0YGMQNn4mhA=
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f h1:OtU/w6sBKmXYaw2KEODxjcYi3oPSyyslhgGFgIJVGAI=
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f/go.mod h1:f/98/SnvAzhAEFQJ3u836FePXvcbE8BS0YGMQNn4mhA=
@@ -503,7 +418,6 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -513,7 +427,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -524,8 +437,6 @@ github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmD
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
github.com/theckman/go-flock v0.7.1/go.mod h1:kjuth3y9VJ2aNlkNEO99G/8lp9fMIKaGyBmh84IBheM=
github.com/u-root/u-root v5.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
-github.com/uber/jaeger-client-go v2.20.1+incompatible h1:HgqpYBng0n7tLJIlyT4kPCIv5XgCsF+kai1NnnrJzEU=
-github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM=
github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v0.0.0-20190122222657-d036253de8f5 h1:CwmGyzHTzCqCdZJkWR0A7ucZXgrCY7spRcpvm7ci//s=
@@ -540,22 +451,17 @@ github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b h1:hdDRrn9OP/roL8a/e/5Z
github.com/varlink/go v0.0.0-20190502142041-0f1d566d194b/go.mod h1:YHaw8N660ESgMgLOZfLQqT1htFItynAUxMesFBho52s=
github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE=
github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g=
-github.com/vbauerster/mpb v3.4.0+incompatible h1:mfiiYw87ARaeRW6x5gWwYRUawxaW1tLAD8IceomUCNw=
-github.com/vbauerster/mpb v3.4.0+incompatible/go.mod h1:zAHG26FUhVKETRu+MWqYXcI70POlC6N8up9p1dID7SU=
-github.com/vbauerster/mpb/v4 v4.11.1 h1:ZOYQSVHgmeanXsbyC44aDg76tBGCS/54Rk8VkL8dJGA=
github.com/vbauerster/mpb/v4 v4.11.1/go.mod h1:vMLa1J/ZKC83G2lB/52XpqT+ZZtFG4aZOdKhmpRL1uM=
+github.com/vbauerster/mpb/v4 v4.11.2 h1:ynkUoKzi65DZ1UsQPx7sgi/KN6G9f7br+Us2nKm35AM=
+github.com/vbauerster/mpb/v4 v4.11.2/go.mod h1:jIuIRCltGJUnm6DCyPVkwjlLUk4nHTH+m4eD14CdFF0=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
-github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
-github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
-github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I=
github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -566,7 +472,6 @@ github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66/go.mod h1:anY
github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg=
github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -580,7 +485,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ=
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4=
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -607,7 +511,6 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
@@ -618,7 +521,6 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7O
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
@@ -633,7 +535,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190425145619-16072639606e h1:4ktJgTV34+N3qOZUc5fAaG3Pb11qzMm3PkAoTAgUZ2I=
golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -641,21 +542,18 @@ golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4=
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2 h1:/J2nHFg1MTqaRLFO7M+J78ASNsJoz3r0cvHBPQ77fsE=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@@ -699,9 +597,7 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -715,35 +611,27 @@ gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
-gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v0.0.0-20190624233834-05ebafbffc79/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
-gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A=
-k8s.io/api v0.0.0-20190813020757-36bff7324fb7 h1:4uJOjRn9kWq4AqJRE8+qzmAy+lJd9rh8TY455dNef4U=
-k8s.io/api v0.0.0-20190813020757-36bff7324fb7/go.mod h1:3Iy+myeAORNCLgjd/Xu9ebwN7Vh59Bw0vh9jhoX+V58=
-k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/api v0.17.2 h1:NF1UFXcKN7/OOv1uxdRz3qfra8AHsPav5M93hlV9+Dc=
k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4=
+k8s.io/api v0.17.3 h1:XAm3PZp3wnEdzekNkcmj/9Y1zdmQYJ1I4GKSBBZ8aG0=
+k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0=
k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA=
-k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010 h1:pyoq062NftC1y/OcnbSvgolyZDJ8y4fmUPWMkdA6gfU=
-k8s.io/apimachinery v0.0.0-20190809020650-423f5d784010/go.mod h1:Waf/xTS2FGRrgXCkO5FP3XxTOWh0qLf2QhL1qFZZ/R8=
-k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
k8s.io/apimachinery v0.17.2 h1:hwDQQFbdRlpnnsR64Asdi55GyCaIP/3WQpMmbNBeWr4=
k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
+k8s.io/apimachinery v0.17.3 h1:f+uZV6rm4/tHE7xXgLyToprg6xWairaClGVkm2t8omg=
+k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g=
k8s.io/client-go v0.0.0-20170217214107-bcde30fb7eae/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v0.0.0-20181219152756-3dd551c0f083 h1:+Qf/nITucAbm09aIdxvoA+7X0BwaXmQGVoR8k7Ynk9o=
k8s.io/client-go v0.0.0-20181219152756-3dd551c0f083/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab h1:E8Fecph0qbNsAbijJJQryKu4Oi9QTp5cVpjTE+nqg6g=
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
@@ -753,12 +641,9 @@ k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
-k8s.io/klog v0.3.3 h1:niceAagH1tzskmaie/icWd7ci1wbG7Bf2c6YGcQv+3c=
-k8s.io/klog v0.3.3/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
-k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
diff --git a/install.md b/install.md
index b143c7f7a..12dc62b32 100644
--- a/install.md
+++ b/install.md
@@ -1,530 +1,5 @@
# libpod Installation Instructions
-## Installing packaged versions of Podman
+The installation instructions for Podman and libpod now reside **[here](https://podman.io/getting-started/installation)** in the **[podman.io](https://podman.io)** site. From the hompage, the installation instructions can be found under "Get Started->Installing Podman".
-#### [Arch Linux](https://www.archlinux.org) & [Manjaro Linux](https://manjaro.org)
-
-```bash
-sudo pacman -S podman
-```
-
-If you have problems when running Podman in [rootless](README.md#rootless) mode follow the instructions [here](https://wiki.archlinux.org/index.php/Linux_Containers#Enable_support_to_run_unprivileged_containers_(optional))
-
-#### [Debian](https://debian.org)
-
-The libpod package is [being worked on](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=930440)
-for inclusion in the default Debian repos. Relevant status updates can also be
-found [here](https://github.com/containers/libpod/issues/1742).
-
-Alternatively, the [Kubic project](https://build.opensuse.org/project/show/devel:kubic:libcontainers:stable)
-provides packages for Debian 10, testing and unstable.
-
-```bash
-# Debian Unstable/Sid
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Unstable/Release.key -O Release.key
-
-# Debian Testing
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Testing/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Testing/Release.key -O Release.key
-
-# Debian 10
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_10/Release.key -O Release.key
-
-sudo apt-key add - < Release.key
-sudo apt-get update -qq
-sudo apt-get -qq -y install podman
-```
-
-There are many [packages](https://packages.debian.org/search?keywords=libpod&searchon=names&suite=stable&section=all)
-with the libpod prefix available already on Debian. However, those are
-unrelated to this project.
-
-
-#### [Fedora](https://www.fedoraproject.org), [CentOS](https://www.centos.org)
-
-```bash
-sudo yum -y install podman
-```
-
-#### [Fedora-CoreOS](https://coreos.fedoraproject.org), [Fedora SilverBlue](https://silverblue.fedoraproject.org)
-
-Built-in, no need to install
-
-#### [Gentoo](https://www.gentoo.org)
-
-```bash
-sudo emerge app-emulation/libpod
-```
-
-#### [MacOS](https://www.apple.com/macos)
-
-Using [Homebrew](https://brew.sh/):
-
-```bash
-brew cask install podman
-```
-
-#### [OpenEmbedded](https://www.openembedded.org)
-
-Bitbake recipes for podman and its dependencies are available in the
-[meta-virtualization layer](https://git.yoctoproject.org/cgit/cgit.cgi/meta-virtualization/).
-Add the layer to your OpenEmbedded build environment and build podman using:
-
-```bash
-bitbake podman
-```
-
-#### [openSUSE](https://www.opensuse.org)
-
-```bash
-sudo zypper install podman
-```
-
-#### [openSUSE Kubic](https://kubic.opensuse.org)
-
-Built-in, no need to install
-
-
-#### [Raspbian](https://raspbian.org)
-
-The Kubic project provides packages for Raspbian 10.
-
-```bash
-# Raspbian 10
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Raspbian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Raspbian_10/Release.key -O Release.key
-sudo apt-key add - < Release.key
-sudo apt-get update -qq
-sudo apt-get -qq -y install podman
-```
-
-
-#### [RHEL7](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux)
-
-Subscribe, then enable Extras channel and install Podman.
-
-```bash
-sudo subscription-manager repos --enable=rhel-7-server-extras-rpms
-sudo yum -y install podman
-```
-
-#### [RHEL8 Beta](https://www.redhat.com/en/blog/powering-its-future-while-preserving-present-introducing-red-hat-enterprise-linux-8-beta?intcmp=701f2000001Cz6OAAS)
-
-```bash
-sudo yum module enable -y container-tools:1.0
-sudo yum module install -y container-tools:1.0
-```
-
-
-#### [Ubuntu](https://www.ubuntu.com)
-
-The Kubic project provides packages for Ubuntu 18.04, 19.04 and 19.10.
-
-```bash
-. /etc/os-release
-sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
-wget -q https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${VERSION_ID}/Release.key -O- | sudo apt-key add -
-sudo apt-get update -qq
-sudo apt-get -qq -y install podman
-```
-
-There are many [packages](https://packages.ubuntu.com/search?keywords=libpod&searchon=names&suite=eoan&section=all)
-with the libpod prefix available already on Ubuntu. However, those are
-unrelated to this project.
-
-
-### Installing development versions of Podman
-
-#### Debian
-
-The Kubic project provides RC/testing packages for Debian 10, testing and
-unstable.
-
-```bash
-# Debian Unstable/Sid
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/Debian_Unstable/Release.key -O Release.key
-
-# Debian Testing
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/Debian_Testing/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/Debian_Testing/Release.key -O Release.key
-
-# Debian 10
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/Debian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/Debian_10/Release.key -O Release.key
-
-# Raspbian 10
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/Raspbian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/Raspbian_10/Release.key -O Release.key
-
-sudo apt-key add - < Release.key
-sudo apt-get update -qq
-sudo apt-get -qq -y install podman
-```
-
-
-#### Fedora
-
-You can test the very latest Podman in Fedora's `updates-testing`
-repository before it goes out to all Fedora users.
-
-```console
-sudo yum distro-sync --enablerepo=updates-testing podman
-```
-
-If you use a newer Podman package from Fedora's `updates-testing`, we would
-appreciate your `+1` feedback in [Bodhi, Fedora's update management
-system](https://bodhi.fedoraproject.org/updates/?packages=podman).
-
-If you are running a non-rawhide Fedora distribution, you can also test the latest packages
-with our [COPR repository](https://copr.fedorainfracloud.org/coprs/baude/Upstream_CRIO_Family/).
-
-#### [Raspbian](https://raspbian.org)
-
-The Kubic project provides RC/testing packages for Raspbian 10.
-
-```bash
-# Raspbian 10
-echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/Raspbian_10/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/Raspbian_10/Release.key -O Release.key
-sudo apt-key add - < Release.key
-sudo apt-get update -qq
-sudo apt-get -qq -y install podman
-```
-
-
-#### Ubuntu
-
-The Kubic project provides RC/testing packages for Ubuntu 18.04, 19.04 and 19.10.
-
-```bash
-. /etc/os-release
-sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/x${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list"
-wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/x${NAME}_${VERSION_ID}/Release.key -O Release.key
-sudo apt-key add - < Release.key
-sudo apt-get update -qq
-sudo apt-get -qq -y install podman
-```
-
-
-## Building from scratch
-
-### Build and Run Dependencies
-
-**Required**
-
-Fedora, CentOS, RHEL, and related distributions you should try to run
-`make package-install` which will install dependencies, build the source,
-produce rpms for the current platform and install them in the end.
-
-```bash
-sudo yum install -y \
- atomic-registries \
- btrfs-progs-devel \
- containernetworking-cni \
- device-mapper-devel \
- git \
- glib2-devel \
- glibc-devel \
- glibc-static \
- go \
- golang-github-cpuguy83-go-md2man \
- gpgme-devel \
- iptables \
- libassuan-devel \
- libgpg-error-devel \
- libseccomp-devel \
- libselinux-devel \
- make \
- pkgconfig \
- runc \
- containers-common
-```
-
-Debian, Ubuntu, and related distributions:
-
-```bash
-sudo apt-get install \
- btrfs-tools \
- git \
- golang-go \
- go-md2man \
- iptables \
- libassuan-dev \
- libbtrfs-dev \
- libc6-dev \
- libdevmapper-dev \
- libglib2.0-dev \
- libgpgme-dev \
- libgpg-error-dev \
- libprotobuf-dev \
- libprotobuf-c0-dev \
- libseccomp-dev \
- libselinux1-dev \
- libsystemd-dev \
- pkg-config \
- runc \
- uidmap
-```
-
-On openSUSE Leap 15.x and Tumbleweed:
-
-```bash
-sudo zypper -n in libseccomp-devel libgpgme-devel
-```
-
-On Manjaro (and maybe other Linux distributions):
-
-Make sure that the Linux kernel supports user namespaces:
-
-```
-> zgrep CONFIG_USER_NS /proc/config.gz
-CONFIG_USER_NS=y
-
-```
-
-If not, please update the kernel.
-For Manjaro Linux the instructions can be found here:
-https://wiki.manjaro.org/index.php/Manjaro_Kernels
-
-After that enable user namespaces:
-
-```
-sudo sysctl kernel.unprivileged_userns_clone=1
-```
-
-To enable the user namespaces permanently:
-
-```
-echo 'kernel.unprivileged_userns_clone=1' > /etc/sysctl.d/userns.conf
-```
-
-### Building missing dependencies
-
-If any dependencies cannot be installed or are not sufficiently current, they have to be built from source.
-This will mainly affect Debian, Ubuntu, and related distributions, or RHEL where no subscription is active (e.g. Cloud VMs).
-
-#### golang
-
-Be careful to double-check that the version of golang is new enough (i.e. `go version`), version 1.10.x or higher is required.
-If needed, golang kits are available at https://golang.org/dl/. Alternatively, go can be built from source as follows
-(it's helpful to leave the system-go installed, to avoid having to [bootstrap go](https://golang.org/doc/install/source):
-
-```bash
-export GOPATH=~/go
-git clone https://go.googlesource.com/go $GOPATH
-cd $GOPATH
-git checkout tags/go1.10.8 # optional
-cd src
-./all.bash
-export PATH=$GOPATH/bin:$PATH
-```
-
-#### conmon
-
-The latest version of `conmon` is expected to be installed on the system. Conmon is used to monitor OCI Runtimes.
-To build from source, use the following:
-
-```bash
-git clone https://github.com/containers/conmon
-cd conmon
-export GOCACHE="$(mktemp -d)"
-make
-sudo make podman
-```
-
-#### runc
-
-The latest version of `runc` is expected to be installed on the system. It is picked up as the default runtime by Podman.
-Version 1.0.0-rc4 is the minimal requirement, which is available in Ubuntu 18.04 already.
-To double-check, `runc --version` should produce at least `spec: 1.0.1`, otherwise build your own:
-
-```bash
-git clone https://github.com/opencontainers/runc.git $GOPATH/src/github.com/opencontainers/runc
-cd $GOPATH/src/github.com/opencontainers/runc
-make BUILDTAGS="selinux seccomp"
-sudo cp runc /usr/bin/runc
-```
-
-#### CNI plugins
-
-#### Setup CNI networking
-
-A proper description of setting up CNI networking is given in the [`cni` README](cni/README.md).
-
-A basic setup for CNI networking is done by default during the installation or make processes and
-no further configuration is needed to start using Podman.
-
-#### Add configuration
-
-```bash
-sudo mkdir -p /etc/containers
-sudo curl https://raw.githubusercontent.com/projectatomic/registries/master/registries.fedora -o /etc/containers/registries.conf
-sudo curl https://raw.githubusercontent.com/containers/skopeo/master/default-policy.json -o /etc/containers/policy.json
-```
-
-
-#### Optional packages
-
-Fedora, CentOS, RHEL, and related distributions:
-
-(no optional packages)
-
-Debian, Ubuntu, and related distributions:
-
-```bash
-apt-get install -y \
- libapparmor-dev
-```
-
-### Get Source Code
-
-As with other Go projects, Podman must be cloned into a directory structure like:
-
-```
-GOPATH
-└── src
- └── github.com
- └── containers
- └── libpod
-```
-
-First, ensure that the go version that is found first on the $PATH (in case you built your own; see [above](#golang)) is sufficiently recent -
-`go version` must be higher than 1.10.x). Then we can finally build Podman (assuming we already have a `$GOPATH` and the corresponding folder,
-`export GOPATH=~/go && mkdir -p $GOPATH`):
-
-```bash
-git clone https://github.com/containers/libpod/ $GOPATH/src/github.com/containers/libpod
-cd $GOPATH/src/github.com/containers/libpod
-make BUILDTAGS="selinux seccomp"
-sudo make install PREFIX=/usr
-```
-
-#### Build Tags
-
-Otherwise, if you do not want to build Podman with seccomp or selinux support you can add `BUILDTAGS=""` when running make.
-
-```bash
-make BUILDTAGS=""
-sudo make install
-```
-
-Podman supports optional build tags for compiling support of various features.
-To add build tags to the make option the `BUILDTAGS` variable must be set, for example:
-
-```bash
-make BUILDTAGS='seccomp apparmor'
-```
-
-| Build Tag | Feature | Dependency |
-|----------------------------------|------------------------------------|----------------------|
-| apparmor | apparmor support | libapparmor |
-| exclude_graphdriver_btrfs | exclude btrfs | libbtrfs |
-| exclude_graphdriver_devicemapper | exclude device-mapper | libdm |
-| libdm_no_deferred_remove | exclude deferred removal in libdm | libdm |
-| seccomp | syscall filtering | libseccomp |
-| selinux | selinux process and mount labeling | |
-| systemd | journald logging | libsystemd |
-
-Note that Podman does not officially support device-mapper. Thus, the `exclude_graphdriver_devicemapper` tag is mandatory.
-
-### Vendoring - Dependency Management
-
-This project is using [go modules](https://github.com/golang/go/wiki/Modules) for dependency management. If the CI is complaining about a pull request leaving behind an unclean state, it is very likely right about it. After changing dependencies, make sure to run `make vendor` to synchronize the code with the go module and repopulate the `./vendor` directory.
-
-## Configuration files
-
-### [registries.conf](https://src.fedoraproject.org/rpms/skopeo/blob/master/f/registries.conf)
-
-#### Man Page: [registries.conf.5](https://github.com/containers/image/blob/master/docs/registries.conf.5.md)
-
-`/etc/containers/registries.conf`
-
-registries.conf is the configuration file which specifies which container registries should be consulted when completing image names which do not include a registry or domain portion.
-
-#### Example from the Fedora `containers-common` package
-
-```
-cat /etc/containers/registries.conf
-# This is a system-wide configuration file used to
-# keep track of registries for various container backends.
-# It adheres to TOML format and does not support recursive
-# lists of registries.
-
-# The default location for this configuration file is /etc/containers/registries.conf.
-
-# The only valid categories are: 'registries.search', 'registries.insecure',
-# and 'registries.block'.
-
-[registries.search]
-registries = ['docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.access.redhat.com', 'registry.centos.org']
-
-# If you need to access insecure registries, add the registry's fully-qualified name.
-# An insecure registry is one that does not have a valid SSL certificate or only does HTTP.
-[registries.insecure]
-registries = []
-
-
-# If you need to block pull access from a registry, uncomment the section below
-# and add the registries fully-qualified name.
-#
-[registries.block]
-registries = []
-```
-
-### [mounts.conf](https://src.fedoraproject.org/rpms/skopeo/blob/master/f/mounts.conf)
-
-`/usr/share/containers/mounts.conf` and optionally `/etc/containers/mounts.conf`
-
-The mounts.conf files specify volume mount directories that are automatically mounted inside containers when executing the `podman run` or `podman build` commands. Container process can then use this content. The volume mount content does not get committed to the final image.
-
-Usually these directories are used for passing secrets or credentials required by the package software to access remote package repositories.
-
-For example, a mounts.conf with the line "`/usr/share/rhel/secrets:/run/secrets`", the content of `/usr/share/rhel/secrets` directory is mounted on `/run/secrets` inside the container. This mountpoint allows Red Hat Enterprise Linux subscriptions from the host to be used within the container.
-
-Note this is not a volume mount. The content of the volumes is copied into container storage, not bind mounted directly from the host.
-
-#### Example from the Fedora `containers-common` package:
-
-```
-cat /usr/share/containers/mounts.conf
-/usr/share/rhel/secrets:/run/secrets
-```
-
-### [seccomp.json](https://src.fedoraproject.org/rpms/skopeo/blob/master/f/seccomp.json)
-
-`/usr/share/containers/seccomp.json`
-
-seccomp.json contains the whitelist of seccomp rules to be allowed inside of
-containers. This file is usually provided by the containers-common package.
-
-The link above takes you to the seccomp.json
-
-### [policy.json](https://github.com/containers/skopeo/blob/master/default-policy.json)
-
-`/etc/containers/policy.json`
-
-#### Man Page: [policy.json.5](https://github.com/containers/image/blob/master/docs/policy.json.md)
-
-
-#### Example from the Fedora `containers-common` package:
-
-```
-cat /etc/containers/policy.json
-{
- "default": [
- {
- "type": "insecureAcceptAnything"
- }
- ],
- "transports":
- {
- "docker-daemon":
- {
- "": [{"type":"insecureAcceptAnything"}]
- }
- }
-}
-```
+The podman.io site resides in a GitHub under the Containers repository at [https://github.com/containers/podman.io](https://github.com/containers/podman.io). If you see a change that needs to happen to the installation instructions, please feel free to open a pull request there, we're always happy to have new contributors!
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 0e883588c..216bbe669 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1254,6 +1254,12 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
}
}
}
+ // Ensure we tear down the container network so it will be
+ // recreated - otherwise, behavior of restart differs from stop
+ // and start
+ if err := c.cleanupNetwork(); err != nil {
+ return err
+ }
}
defer func() {
if err != nil {
@@ -1377,18 +1383,34 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
}
if vol.state.NeedsCopyUp {
logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name())
+
+ // Set NeedsCopyUp to false immediately, so we don't try this
+ // again when there are already files copied.
+ vol.state.NeedsCopyUp = false
+ if err := vol.save(); err != nil {
+ return nil, err
+ }
+
+ // If the volume is not empty, we should not copy up.
+ volMount := vol.MountPoint()
+ contents, err := ioutil.ReadDir(volMount)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error listing contents of volume %s mountpoint when copying up from container %s", vol.Name(), c.ID())
+ }
+ if len(contents) > 0 {
+ // The volume is not empty. It was likely modified
+ // outside of Podman. For safety, let's not copy up into
+ // it. Fixes CVE-2020-1726.
+ return vol, nil
+ }
+
srcDir, err := securejoin.SecureJoin(mountpoint, v.Dest)
if err != nil {
return nil, errors.Wrapf(err, "error calculating destination path to copy up container %s volume %s", c.ID(), vol.Name())
}
- if err := c.copyWithTarFromImage(srcDir, vol.MountPoint()); err != nil && !os.IsNotExist(err) {
+ if err := c.copyWithTarFromImage(srcDir, volMount); err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "error copying content from container %s into volume %s", c.ID(), vol.Name())
}
-
- vol.state.NeedsCopyUp = false
- if err := vol.save(); err != nil {
- return nil, err
- }
}
return vol, nil
}
diff --git a/libpod/image/image.go b/libpod/image/image.go
index ba1080a71..43fd52a1a 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -99,10 +99,7 @@ func NewImageRuntimeFromOptions(options storage.StoreOptions) (*Runtime, error)
if err != nil {
return nil, err
}
-
- return &Runtime{
- store: store,
- }, nil
+ return NewImageRuntimeFromStore(store), nil
}
func setStore(options storage.StoreOptions) (storage.Store, error) {
@@ -114,30 +111,29 @@ func setStore(options storage.StoreOptions) (storage.Store, error) {
return store, nil
}
-// newFromStorage creates a new image object from a storage.Image
-func (ir *Runtime) newFromStorage(img *storage.Image) *Image {
- image := Image{
- InputName: img.ID,
+// newImage creates a new image object given an "input name" and a storage.Image
+func (ir *Runtime) newImage(inputName string, img *storage.Image) *Image {
+ return &Image{
+ InputName: inputName,
imageruntime: ir,
image: img,
}
- return &image
+}
+
+// newFromStorage creates a new image object from a storage.Image. Its "input name" will be its ID.
+func (ir *Runtime) newFromStorage(img *storage.Image) *Image {
+ return ir.newImage(img.ID, img)
}
// NewFromLocal creates a new image object that is intended
// to only deal with local images already in the store (or
// its aliases)
func (ir *Runtime) NewFromLocal(name string) (*Image, error) {
- image := Image{
- InputName: name,
- imageruntime: ir,
- }
- localImage, err := image.getLocalImage()
+ updatedInputName, localImage, err := ir.getLocalImage(name)
if err != nil {
return nil, err
}
- image.image = localImage
- return &image, nil
+ return ir.newImage(updatedInputName, localImage), nil
}
// New creates a new image object where the image could be local
@@ -148,15 +144,10 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile
defer span.Finish()
// We don't know if the image is local or not ... check local first
- newImage := Image{
- InputName: name,
- imageruntime: ir,
- }
if pullType != util.PullImageAlways {
- localImage, err := newImage.getLocalImage()
+ newImage, err := ir.NewFromLocal(name)
if err == nil {
- newImage.image = localImage
- return &newImage, nil
+ return newImage, nil
} else if pullType == util.PullImageNever {
return nil, err
}
@@ -171,13 +162,11 @@ func (ir *Runtime) New(ctx context.Context, name, signaturePolicyPath, authfile
return nil, errors.Wrapf(err, "unable to pull %s", name)
}
- newImage.InputName = imageName[0]
- img, err := newImage.getLocalImage()
+ newImage, err := ir.NewFromLocal(imageName[0])
if err != nil {
return nil, errors.Wrapf(err, "error retrieving local image after pulling %s", name)
}
- newImage.image = img
- return &newImage, nil
+ return newImage, nil
}
// LoadFromArchiveReference creates a new image object for images pulled from a tar archive and the like (podman load)
@@ -194,16 +183,11 @@ func (ir *Runtime) LoadFromArchiveReference(ctx context.Context, srcRef types.Im
}
for _, name := range imageNames {
- newImage := Image{
- InputName: name,
- imageruntime: ir,
- }
- img, err := newImage.getLocalImage()
+ newImage, err := ir.NewFromLocal(name)
if err != nil {
return nil, errors.Wrapf(err, "error retrieving local image after pulling %s", name)
}
- newImage.image = img
- newImages = append(newImages, &newImage)
+ newImages = append(newImages, newImage)
}
ir.newImageEvent(events.LoadFromArchive, "")
return newImages, nil
@@ -234,7 +218,7 @@ func (i *Image) reloadImage() error {
if err != nil {
return errors.Wrapf(err, "unable to reload image")
}
- i.image = newImage.image
+ i.image = newImage
return nil
}
@@ -247,60 +231,60 @@ func stripSha256(name string) string {
}
// getLocalImage resolves an unknown input describing an image and
-// returns a storage.Image or an error. It is used by NewFromLocal.
-func (i *Image) getLocalImage() (*storage.Image, error) {
- imageError := fmt.Sprintf("unable to find '%s' in local storage", i.InputName)
- if i.InputName == "" {
- return nil, errors.Errorf("input name is blank")
+// returns an updated input name, and a storage.Image, or an error. It is used by NewFromLocal.
+func (ir *Runtime) getLocalImage(inputName string) (string, *storage.Image, error) {
+ imageError := fmt.Sprintf("unable to find '%s' in local storage", inputName)
+ if inputName == "" {
+ return "", nil, errors.Errorf("input name is blank")
}
// Check if the input name has a transport and if so strip it
- dest, err := alltransports.ParseImageName(i.InputName)
+ dest, err := alltransports.ParseImageName(inputName)
if err == nil && dest.DockerReference() != nil {
- i.InputName = dest.DockerReference().String()
+ inputName = dest.DockerReference().String()
}
- img, err := i.imageruntime.getImage(stripSha256(i.InputName))
+ img, err := ir.getImage(stripSha256(inputName))
if err == nil {
- return img.image, err
+ return inputName, img, err
}
// container-storage wasn't able to find it in its current form
// check if the input name has a tag, and if not, run it through
// again
- decomposedImage, err := decompose(i.InputName)
+ decomposedImage, err := decompose(inputName)
if err != nil {
- return nil, err
+ return "", nil, err
}
// The image has a registry name in it and we made sure we looked for it locally
// with a tag. It cannot be local.
if decomposedImage.hasRegistry {
- return nil, errors.Wrapf(ErrNoSuchImage, imageError)
+ return "", nil, errors.Wrapf(ErrNoSuchImage, imageError)
}
// if the image is saved with the repository localhost, searching with localhost prepended is necessary
// We don't need to strip the sha because we have already determined it is not an ID
ref, err := decomposedImage.referenceWithRegistry(DefaultLocalRegistry)
if err != nil {
- return nil, err
+ return "", nil, err
}
- img, err = i.imageruntime.getImage(ref.String())
+ img, err = ir.getImage(ref.String())
if err == nil {
- return img.image, err
+ return inputName, img, err
}
// grab all the local images
- images, err := i.imageruntime.GetImages()
+ images, err := ir.GetImages()
if err != nil {
- return nil, err
+ return "", nil, err
}
// check the repotags of all images for a match
repoImage, err := findImageInRepotags(decomposedImage, images)
if err == nil {
- return repoImage, nil
+ return inputName, repoImage, nil
}
- return nil, errors.Wrapf(ErrNoSuchImage, err.Error())
+ return "", nil, errors.Wrapf(ErrNoSuchImage, err.Error())
}
// ID returns the image ID as a string
@@ -460,7 +444,7 @@ func (i *Image) Remove(ctx context.Context, force bool) error {
// getImage retrieves an image matching the given name or hash from system
// storage
// If no matching image can be found, an error is returned
-func (ir *Runtime) getImage(image string) (*Image, error) {
+func (ir *Runtime) getImage(image string) (*storage.Image, error) {
var img *storage.Image
ref, err := is.Transport.ParseStoreReference(ir.store, image)
if err == nil {
@@ -476,8 +460,7 @@ func (ir *Runtime) getImage(image string) (*Image, error) {
}
img = img2
}
- newImage := ir.newFromStorage(img)
- return newImage, nil
+ return img, nil
}
// GetImages retrieves all images present in storage
@@ -702,13 +685,6 @@ func (i *Image) toImageSourceRef(ctx context.Context) (types.ImageSource, error)
//Size returns the size of the image
func (i *Image) Size(ctx context.Context) (*uint64, error) {
- if i.image == nil {
- localImage, err := i.getLocalImage()
- if err != nil {
- return nil, err
- }
- i.image = localImage
- }
sum, err := i.imageruntime.store.ImageSize(i.ID())
if err == nil && sum >= 0 {
usum := uint64(sum)
diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go
index 3ff6210d9..19f7eee1e 100644
--- a/libpod/image/image_test.go
+++ b/libpod/image/image_test.go
@@ -18,7 +18,6 @@ import (
var (
bbNames = []string{"docker.io/library/busybox:latest", "docker.io/library/busybox", "docker.io/busybox:latest", "docker.io/busybox", "busybox:latest", "busybox"}
bbGlibcNames = []string{"docker.io/library/busybox:glibc", "docker.io/busybox:glibc", "busybox:glibc"}
- fedoraNames = []string{"registry.fedoraproject.org/fedora-minimal:latest", "registry.fedoraproject.org/fedora-minimal", "fedora-minimal:latest", "fedora-minimal"}
)
type localImageTest struct {
@@ -139,7 +138,6 @@ func TestImage_New(t *testing.T) {
ir.Eventer = events.NewNullEventer()
// Build the list of pull names
names = append(names, bbNames...)
- names = append(names, fedoraNames...)
writer := os.Stdout
// Iterate over the names and delete the image
diff --git a/libpod/options.go b/libpod/options.go
index 923e7292c..4957f822d 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1784,3 +1784,156 @@ func WithInfraContainerPorts(bindings []ocicni.PortMapping) PodCreateOption {
return nil
}
}
+
+// WithPodStaticIP sets a static IP for the pod.
+func WithPodStaticIP(ip net.IP) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if len(pod.config.InfraContainer.Networks) > 1 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set a static IP if joining more than 1 CNI network")
+ }
+
+ pod.config.InfraContainer.StaticIP = ip
+
+ return nil
+ }
+}
+
+// WithPodStaticMAC sets a static MAC address for the pod.
+func WithPodStaticMAC(mac net.HardwareAddr) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if len(pod.config.InfraContainer.Networks) > 1 {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot set a static MAC if joining more than 1 CNI network")
+ }
+
+ pod.config.InfraContainer.StaticMAC = mac
+
+ return nil
+ }
+}
+
+// WithPodUseImageResolvConf sets a pod to use an image's resolv.conf and not
+// create its own.
+func WithPodUseImageResolvConf() PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if len(pod.config.InfraContainer.DNSServer) != 0 ||
+ len(pod.config.InfraContainer.DNSSearch) != 0 ||
+ len(pod.config.InfraContainer.DNSOption) != 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "requested use of image resolv.conf conflicts with already-configured DNS settings")
+ }
+
+ pod.config.InfraContainer.UseImageResolvConf = true
+
+ return nil
+ }
+}
+
+// WithPodDNS sets the DNS Servers for a pod.
+func WithPodDNS(dnsServer []string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if pod.config.InfraContainer.UseImageResolvConf {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS servers if pod will not create /etc/resolv.conf")
+ }
+
+ pod.config.InfraContainer.DNSServer = dnsServer
+
+ return nil
+ }
+}
+
+// WithPodDNSSearch sets the DNS Search domains for a pod.
+func WithPodDNSSearch(dnsSearch []string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if pod.config.InfraContainer.UseImageResolvConf {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS search domains if pod will not create /etc/resolv.conf")
+ }
+
+ pod.config.InfraContainer.DNSSearch = dnsSearch
+
+ return nil
+ }
+}
+
+// WithPodDNSOption sets DNS Options for a pod.
+func WithPodDNSOption(dnsOption []string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if pod.config.InfraContainer.UseImageResolvConf {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot add DNS options if pod will not create /etc/resolv.conf")
+ }
+
+ pod.config.InfraContainer.DNSOption = dnsOption
+
+ return nil
+ }
+}
+
+// WithPodUseImageHosts tells the pod not to create /etc/hosts and instead to
+// use the one provided by the image.
+func WithPodUseImageHosts() PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if len(pod.config.InfraContainer.HostAdd) != 0 {
+ return errors.Wrapf(define.ErrInvalidArg, "not creating /etc/hosts conflicts with adding to the hosts file")
+ }
+
+ pod.config.InfraContainer.UseImageHosts = true
+
+ return nil
+ }
+}
+
+// WithPodHosts adds additional entries to the pod's /etc/hosts
+func WithPodHosts(hosts []string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ if pod.config.InfraContainer.UseImageHosts {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot add to /etc/hosts if container is using image hosts")
+ }
+
+ pod.config.InfraContainer.HostAdd = hosts
+
+ return nil
+ }
+}
+
+// WithPodNetworks sets additional CNI networks for the pod to join.
+func WithPodNetworks(networks []string) PodCreateOption {
+ return func(pod *Pod) error {
+ if pod.valid {
+ return define.ErrPodFinalized
+ }
+
+ pod.config.InfraContainer.Networks = networks
+
+ return nil
+ }
+}
diff --git a/libpod/pod.go b/libpod/pod.go
index 3b9bb9c60..4f85caf08 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "net"
"time"
"github.com/containers/libpod/libpod/define"
@@ -97,8 +98,17 @@ type PodContainerInfo struct {
// InfraContainerConfig is the configuration for the pod's infra container
type InfraContainerConfig struct {
- HasInfraContainer bool `json:"makeInfraContainer"`
- PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
+ HasInfraContainer bool `json:"makeInfraContainer"`
+ PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
+ StaticIP net.IP `json:"staticIP,omitempty"`
+ StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
+ UseImageResolvConf bool `json:"useImageResolvConf,omitempty"`
+ DNSServer []string `json:"dnsServer,omitempty"`
+ DNSSearch []string `json:"dnsSearch,omitempty"`
+ DNSOption []string `json:"dnsOption,omitempty"`
+ UseImageHosts bool `json:"useImageHosts,omitempty"`
+ HostAdd []string `json:"hostsAdd,omitempty"`
+ Networks []string `json:"networks,omitempty"`
}
// ID retrieves the pod's ID
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 6a27c2800..1b1421ca8 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -94,14 +94,38 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
options = append(options, withIsInfra())
// Since user namespace sharing is not implemented, we only need to check if it's rootless
- networks := make([]string, 0)
netmode := "bridge"
if isRootless {
netmode = "slirp4netns"
}
// PostConfigureNetNS should not be set since user namespace sharing is not implemented
// and rootless networking no longer supports post configuration setup
- options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, networks))
+ options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, p.config.InfraContainer.Networks))
+
+ if p.config.InfraContainer.StaticIP != nil {
+ options = append(options, WithStaticIP(p.config.InfraContainer.StaticIP))
+ }
+ if p.config.InfraContainer.StaticMAC != nil {
+ options = append(options, WithStaticMAC(p.config.InfraContainer.StaticMAC))
+ }
+ if p.config.InfraContainer.UseImageResolvConf {
+ options = append(options, WithUseImageResolvConf())
+ }
+ if len(p.config.InfraContainer.DNSServer) > 0 {
+ options = append(options, WithDNS(p.config.InfraContainer.DNSServer))
+ }
+ if len(p.config.InfraContainer.DNSSearch) > 0 {
+ options = append(options, WithDNSSearch(p.config.InfraContainer.DNSSearch))
+ }
+ if len(p.config.InfraContainer.DNSOption) > 0 {
+ options = append(options, WithDNSOption(p.config.InfraContainer.DNSOption))
+ }
+ if p.config.InfraContainer.UseImageHosts {
+ options = append(options, WithUseImageHosts())
+ }
+ if len(p.config.InfraContainer.HostAdd) > 0 {
+ options = append(options, WithHosts(p.config.InfraContainer.HostAdd))
+ }
return r.newContainer(ctx, g.Config, options...)
}
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 5b0111b85..4afd5760a 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -193,8 +193,6 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
}
}
- var removalErr error
-
// We're going to be removing containers.
// If we are CGroupfs cgroup driver, to avoid races, we need to hit
// the pod and conmon CGroups with a PID limit to prevent them from
@@ -205,7 +203,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
conmonCgroup, err := cgroups.Load(conmonCgroupPath)
if err != nil && err != cgroups.ErrCgroupDeleted && err != cgroups.ErrCgroupV1Rootless {
- removalErr = errors.Wrapf(err, "error retrieving pod %s conmon cgroup %s", p.ID(), conmonCgroupPath)
+ logrus.Errorf("Error retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
}
// New resource limits
@@ -216,15 +214,13 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
// Don't try if we failed to retrieve the cgroup
if err == nil {
if err := conmonCgroup.Update(resLimits); err != nil {
- if removalErr == nil {
- removalErr = errors.Wrapf(err, "error updating pod %s conmon group", p.ID())
- } else {
- logrus.Errorf("Error updating pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
- }
+ logrus.Warnf("Error updating pod %s conmon cgroup %s PID limit: %v", p.ID(), conmonCgroupPath, err)
}
}
}
+ var removalErr error
+
ctrNamedVolumes := make(map[string]*ContainerNamedVolume)
// Second loop - all containers are good, so we should be clear to
diff --git a/libpod/stats.go b/libpod/stats.go
index 3b5e0958c..6f42afd18 100644
--- a/libpod/stats.go
+++ b/libpod/stats.go
@@ -66,7 +66,9 @@ func (c *Container) GetContainerStats(previousStats *ContainerStats) (*Container
}
stats.BlockInput, stats.BlockOutput = calculateBlockIO(cgroupStats)
stats.CPUNano = cgroupStats.CPU.Usage.Total
+ stats.CPUSystemNano = cgroupStats.CPU.Usage.Kernel
stats.SystemNano = now
+ stats.PerCPU = cgroupStats.CPU.Usage.PerCPU
// Handle case where the container is not in a network namespace
if netStats != nil {
stats.NetInput = netStats.TxBytes
diff --git a/libpod/stats_config.go b/libpod/stats_config.go
index 9c7d97298..91d3d1493 100644
--- a/libpod/stats_config.go
+++ b/libpod/stats_config.go
@@ -2,17 +2,19 @@ package libpod
// ContainerStats contains the statistics information for a running container
type ContainerStats struct {
- ContainerID string
- Name string
- CPU float64
- CPUNano uint64
- SystemNano uint64
- MemUsage uint64
- MemLimit uint64
- MemPerc float64
- NetInput uint64
- NetOutput uint64
- BlockInput uint64
- BlockOutput uint64
- PIDs uint64
+ ContainerID string
+ Name string
+ PerCPU []uint64
+ CPU float64
+ CPUNano uint64
+ CPUSystemNano uint64
+ SystemNano uint64
+ MemUsage uint64
+ MemLimit uint64
+ MemPerc float64
+ NetInput uint64
+ NetOutput uint64
+ BlockInput uint64
+ BlockOutput uint64
+ PIDs uint64
}
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index b0e63f770..a30ec6649 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -764,7 +764,6 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
containerConfig.ImageID = newImage.ID()
containerConfig.Name = containerYAML.Name
containerConfig.Tty = containerYAML.TTY
- containerConfig.WorkDir = containerYAML.WorkingDir
containerConfig.Pod = podID
@@ -796,6 +795,27 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
containerConfig.StopSignal = 15
+ containerConfig.WorkDir = "/"
+ if imageData != nil {
+ // FIXME,
+ // we are currently ignoring imageData.Config.ExposedPorts
+ containerConfig.BuiltinImgVolumes = imageData.Config.Volumes
+ if imageData.Config.WorkingDir != "" {
+ containerConfig.WorkDir = imageData.Config.WorkingDir
+ }
+ containerConfig.Labels = imageData.Config.Labels
+ if imageData.Config.StopSignal != "" {
+ stopSignal, err := util.ParseSignal(imageData.Config.StopSignal)
+ if err != nil {
+ return nil, err
+ }
+ containerConfig.StopSignal = stopSignal
+ }
+ }
+
+ if containerYAML.WorkingDir != "" {
+ containerConfig.WorkDir = containerYAML.WorkingDir
+ }
// If the user does not pass in ID mappings, just set to basics
if userConfig.IDMappings == nil {
userConfig.IDMappings = &storage.IDMappingOptions{}
diff --git a/pkg/api/Makefile b/pkg/api/Makefile
index c68e50011..6b24bfd83 100644
--- a/pkg/api/Makefile
+++ b/pkg/api/Makefile
@@ -9,4 +9,4 @@ validate: ${SWAGGER_OUT}
${SWAGGER_OUT}:
# generate doesn't remove file on error
rm -f ${SWAGGER_OUT}
- swagger generate spec -o ${SWAGGER_OUT} -i tags.yaml -w ./
+ swagger generate spec -o ${SWAGGER_OUT} -i tags.yaml -w ./ -m
diff --git a/pkg/api/handlers/containers.go b/pkg/api/handlers/containers.go
index f180fbc2b..d7d040ce2 100644
--- a/pkg/api/handlers/containers.go
+++ b/pkg/api/handlers/containers.go
@@ -41,10 +41,9 @@ func StopContainer(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, errors.Wrapf(err, "unable to get state for Container %s", name))
return
}
- // If the Container is stopped already, send a 302
+ // If the Container is stopped already, send a 304
if state == define.ContainerStateStopped || state == define.ContainerStateExited {
- utils.Error(w, http.StatusText(http.StatusNotModified), http.StatusNotModified,
- errors.Errorf("Container %s is already stopped ", name))
+ utils.WriteResponse(w, http.StatusNotModified, "")
return
}
@@ -134,8 +133,7 @@ func StartContainer(w http.ResponseWriter, r *http.Request) {
return
}
if state == define.ContainerStateRunning {
- msg := fmt.Sprintf("Container %s is already running", name)
- utils.Error(w, msg, http.StatusNotModified, errors.New(msg))
+ utils.WriteResponse(w, http.StatusNotModified, "")
return
}
if err := con.Start(r.Context(), false); err != nil {
diff --git a/pkg/api/handlers/events.go b/pkg/api/handlers/events.go
index 44bf35254..22dad9923 100644
--- a/pkg/api/handlers/events.go
+++ b/pkg/api/handlers/events.go
@@ -1,19 +1,24 @@
package handlers
import (
+ "encoding/json"
"fmt"
"net/http"
- "strings"
- "time"
+ "github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func GetEvents(w http.ResponseWriter, r *http.Request) {
+ var (
+ fromStart bool
+ eventsError error
+ )
query := struct {
- Since time.Time `schema:"since"`
- Until time.Time `schema:"until"`
+ Since string `schema:"since"`
+ Until string `schema:"until"`
Filters map[string][]string `schema:"filters"`
}{}
if err := decodeQuery(r, &query); err != nil {
@@ -27,15 +32,30 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
}
}
- libpodEvents, err := getRuntime(r).GetEvents(libpodFilters)
- if err != nil {
- utils.BadRequest(w, "filters", strings.Join(r.URL.Query()["filters"], ", "), err)
+ if len(query.Since) > 0 || len(query.Until) > 0 {
+ fromStart = true
+ }
+ eventChannel := make(chan *events.Event)
+ go func() {
+ readOpts := events.ReadOptions{FromStart: fromStart, Stream: true, Filters: libpodFilters, EventChannel: eventChannel, Since: query.Since, Until: query.Until}
+ eventsError = getRuntime(r).Events(readOpts)
+ }()
+ if eventsError != nil {
+ utils.InternalServerError(w, eventsError)
return
}
-
- var apiEvents = make([]*Event, len(libpodEvents))
- for _, v := range libpodEvents {
- apiEvents = append(apiEvents, EventToApiEvent(v))
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ for event := range eventChannel {
+ e := EventToApiEvent(event)
+ //utils.WriteJSON(w, http.StatusOK, e)
+ coder := json.NewEncoder(w)
+ coder.SetEscapeHTML(true)
+ if err := coder.Encode(e); err != nil {
+ logrus.Errorf("unable to write json: %q", err)
+ }
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ }
}
- utils.WriteJSON(w, http.StatusOK, apiEvents)
}
diff --git a/pkg/api/handlers/generic/containers_stats.go b/pkg/api/handlers/generic/containers_stats.go
index f8804b5c0..19e2cc882 100644
--- a/pkg/api/handlers/generic/containers_stats.go
+++ b/pkg/api/handlers/generic/containers_stats.go
@@ -19,9 +19,6 @@ import (
const DefaultStatsPeriod = 5 * time.Second
func StatsContainer(w http.ResponseWriter, r *http.Request) {
- // 200 no error
- // 404 no such
- // 500 internal
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@@ -64,14 +61,15 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
var preCPUStats docker.CPUStats
if query.Stream {
preRead = time.Now()
+ systemUsage, _ := cgroups.GetSystemCPUUsage()
preCPUStats = docker.CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: stats.CPUNano,
- PercpuUsage: []uint64{uint64(stats.CPU)},
- UsageInKernelmode: 0,
- UsageInUsermode: 0,
+ PercpuUsage: stats.PerCPU,
+ UsageInKernelmode: stats.CPUSystemNano,
+ UsageInUsermode: stats.CPUNano - stats.CPUSystemNano,
},
- SystemUsage: 0,
+ SystemUsage: systemUsage,
OnlineCPUs: 0,
ThrottlingData: docker.ThrottlingData{},
}
@@ -125,6 +123,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
InstanceID: "",
}
+ systemUsage, _ := cgroups.GetSystemCPUUsage()
+
s := handlers.Stats{StatsJSON: docker.StatsJSON{
Stats: docker.Stats{
Read: time.Now(),
@@ -146,11 +146,11 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
CPUStats: docker.CPUStats{
CPUUsage: docker.CPUUsage{
TotalUsage: cgroupStat.CPU.Usage.Total,
- PercpuUsage: []uint64{uint64(stats.CPU)},
+ PercpuUsage: cgroupStat.CPU.Usage.PerCPU,
UsageInKernelmode: cgroupStat.CPU.Usage.Kernel,
UsageInUsermode: cgroupStat.CPU.Usage.Total - cgroupStat.CPU.Usage.Kernel,
},
- SystemUsage: 0,
+ SystemUsage: systemUsage,
OnlineCPUs: uint32(len(cgroupStat.CPU.Usage.PerCPU)),
ThrottlingData: docker.ThrottlingData{
Periods: 0,
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 54acdbd36..e11e26510 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -1,16 +1,20 @@
package libpod
import (
- "fmt"
"net/http"
+ "path/filepath"
+ "sort"
"strconv"
+ "time"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/gorilla/schema"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func StopContainer(w http.ResponseWriter, r *http.Request) {
@@ -46,12 +50,13 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
}
func ListContainers(w http.ResponseWriter, r *http.Request) {
var (
- filters []string
+ filterFuncs []libpod.ContainerFilter
+ pss []ListContainer
)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
All bool `schema:"all"`
- Filter map[string][]string `schema:"filter"`
+ Filters map[string][]string `schema:"filters"`
Last int `schema:"last"`
Namespace bool `schema:"namespace"`
Pod bool `schema:"pod"`
@@ -66,6 +71,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
return
}
+
runtime := r.Context().Value("runtime").(*libpod.Runtime)
opts := shared.PsOptions{
All: query.All,
@@ -73,20 +79,55 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
Size: query.Size,
Sort: "",
Namespace: query.Namespace,
+ NoTrunc: true,
Pod: query.Pod,
Sync: query.Sync,
}
- if len(query.Filter) > 0 {
- for k, v := range query.Filter {
+ if len(query.Filters) > 0 {
+ for k, v := range query.Filters {
for _, val := range v {
- filters = append(filters, fmt.Sprintf("%s=%s", k, val))
+ generatedFunc, err := shared.GenerateContainerFilterFuncs(k, val, runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filterFuncs = append(filterFuncs, generatedFunc)
}
}
}
- pss, err := shared.GetPsContainerOutput(runtime, opts, filters, 2)
+
+ if !query.All {
+ // The default is get only running containers. Do this with a filterfunc
+ runningOnly, err := shared.GenerateContainerFilterFuncs("status", define.ContainerStateRunning.String(), runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ filterFuncs = append(filterFuncs, runningOnly)
+ }
+
+ cons, err := runtime.GetContainers(filterFuncs...)
if err != nil {
utils.InternalServerError(w, err)
}
+ if query.Last > 0 {
+ // Sort the containers we got
+ sort.Sort(psSortCreateTime{cons})
+ // we should perform the lopping before we start getting
+ // the expensive information on containers
+ if query.Last < len(cons) {
+ cons = cons[len(cons)-query.Last:]
+ }
+ }
+ for _, con := range cons {
+ listCon, err := ListContainerBatch(runtime, con, opts)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ pss = append(pss, listCon)
+
+ }
utils.WriteResponse(w, http.StatusOK, pss)
}
@@ -194,3 +235,122 @@ func ShowMountedContainers(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, response)
}
+
+// BatchContainerOp is used in ps to reduce performance hits by "batching"
+// locks.
+func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts shared.PsOptions) (ListContainer, error) {
+ var (
+ conConfig *libpod.ContainerConfig
+ conState define.ContainerStatus
+ err error
+ exitCode int32
+ exited bool
+ pid int
+ size *shared.ContainerSize
+ startedTime time.Time
+ exitedTime time.Time
+ cgroup, ipc, mnt, net, pidns, user, uts string
+ )
+
+ batchErr := ctr.Batch(func(c *libpod.Container) error {
+ conConfig = c.Config()
+ conState, err = c.State()
+ if err != nil {
+ return errors.Wrapf(err, "unable to obtain container state")
+ }
+
+ exitCode, exited, err = c.ExitCode()
+ if err != nil {
+ return errors.Wrapf(err, "unable to obtain container exit code")
+ }
+ startedTime, err = c.StartedTime()
+ if err != nil {
+ logrus.Errorf("error getting started time for %q: %v", c.ID(), err)
+ }
+ exitedTime, err = c.FinishedTime()
+ if err != nil {
+ logrus.Errorf("error getting exited time for %q: %v", c.ID(), err)
+ }
+
+ if !opts.Size && !opts.Namespace {
+ return nil
+ }
+
+ if opts.Namespace {
+ pid, err = c.PID()
+ if err != nil {
+ return errors.Wrapf(err, "unable to obtain container pid")
+ }
+ ctrPID := strconv.Itoa(pid)
+ cgroup, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "cgroup"))
+ ipc, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "ipc"))
+ mnt, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "mnt"))
+ net, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "net"))
+ pidns, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "pid"))
+ user, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "user"))
+ uts, _ = shared.GetNamespaceInfo(filepath.Join("/proc", ctrPID, "ns", "uts"))
+ }
+ if opts.Size {
+ size = new(shared.ContainerSize)
+
+ rootFsSize, err := c.RootFsSize()
+ if err != nil {
+ logrus.Errorf("error getting root fs size for %q: %v", c.ID(), err)
+ }
+
+ rwSize, err := c.RWSize()
+ if err != nil {
+ logrus.Errorf("error getting rw size for %q: %v", c.ID(), err)
+ }
+
+ size.RootFsSize = rootFsSize
+ size.RwSize = rwSize
+ }
+ return nil
+ })
+
+ if batchErr != nil {
+ return ListContainer{}, batchErr
+ }
+
+ ps := ListContainer{
+ Command: conConfig.Command,
+ Created: conConfig.CreatedTime.Unix(),
+ Exited: exited,
+ ExitCode: exitCode,
+ ExitedAt: exitedTime.Unix(),
+ ID: conConfig.ID,
+ Image: conConfig.RootfsImageName,
+ IsInfra: conConfig.IsInfra,
+ Labels: conConfig.Labels,
+ Mounts: ctr.UserVolumes(),
+ Names: []string{conConfig.Name},
+ Pid: pid,
+ Pod: conConfig.Pod,
+ Ports: conConfig.PortMappings,
+ Size: size,
+ StartedAt: startedTime.Unix(),
+ State: conState.String(),
+ }
+ if opts.Pod && len(conConfig.Pod) > 0 {
+ pod, err := rt.GetPod(conConfig.Pod)
+ if err != nil {
+ return ListContainer{}, err
+ }
+ ps.PodName = pod.Name()
+ }
+
+ if opts.Namespace {
+ ns := ListContainerNamespaces{
+ Cgroup: cgroup,
+ IPC: ipc,
+ MNT: mnt,
+ NET: net,
+ PIDNS: pidns,
+ User: user,
+ UTS: uts,
+ }
+ ps.Namespaces = ns
+ }
+ return ps, nil
+}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 6c926c45b..bcbe4977e 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -1,15 +1,23 @@
package libpod
import (
+ "context"
"fmt"
+ "io"
"io/ioutil"
"net/http"
"os"
"strconv"
+ "github.com/containers/image/v5/docker"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/transports/alltransports"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/containers/libpod/pkg/util"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
@@ -176,16 +184,205 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
}
func ImagesLoad(w http.ResponseWriter, r *http.Request) {
- //TODO ...
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/load is not yet implemented"))
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ query := struct {
+ Reference string `schema:"reference"`
+ }{
+ // Add defaults here once needed.
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ tmpfile, err := ioutil.TempFile("", "libpod-images-load.tar")
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ return
+ }
+ defer os.Remove(tmpfile.Name())
+ defer tmpfile.Close()
+
+ if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ return
+ }
+
+ tmpfile.Close()
+ loadedImage, err := runtime.LoadImage(context.Background(), query.Reference, tmpfile.Name(), os.Stderr, "")
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image"))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, []handlers.LibpodImagesLoadReport{{ID: loadedImage}})
}
func ImagesImport(w http.ResponseWriter, r *http.Request) {
- //TODO ...
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/import is not yet implemented"))
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ query := struct {
+ Changes []string `schema:"changes"`
+ Message string `schema:"message"`
+ Reference string `schema:"reference"`
+ URL string `schema:"URL"`
+ }{
+ // Add defaults here once needed.
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ // Check if we need to load the image from a URL or from the request's body.
+ source := query.URL
+ if len(query.URL) == 0 {
+ tmpfile, err := ioutil.TempFile("", "libpod-images-import.tar")
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ return
+ }
+ defer os.Remove(tmpfile.Name())
+ defer tmpfile.Close()
+
+ if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ return
+ }
+
+ tmpfile.Close()
+ source = tmpfile.Name()
+ }
+
+ importedImage, err := runtime.Import(context.Background(), source, query.Reference, query.Changes, query.Message, true)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import image"))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesImportReport{ID: importedImage})
}
func ImagesPull(w http.ResponseWriter, r *http.Request) {
- //TODO ...
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.New("/libpod/images/pull is not yet implemented"))
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ query := struct {
+ Reference string `schema:"reference"`
+ Credentials string `schema:"credentials"`
+ OverrideOS string `schema:"overrideOS"`
+ OverrideArch string `schema:"overrideArch"`
+ TLSVerify bool `schema:"tlsVerify"`
+ AllTags bool `schema:"allTags"`
+ }{
+ TLSVerify: true,
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ if len(query.Reference) == 0 {
+ utils.InternalServerError(w, errors.New("reference parameter cannot be empty"))
+ return
+ }
+ // Enforce the docker transport. This is just a precaution as some callers
+ // might accustomed to using the "transport:reference" notation. Using
+ // another than the "docker://" transport does not really make sense for a
+ // remote case. For loading tarballs, the load and import endpoints should
+ // be used.
+ imageRef, err := alltransports.ParseImageName(query.Reference)
+ if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Errorf("reference %q must be a docker reference", query.Reference))
+ return
+ } else if err != nil {
+ origErr := err
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s://%s", docker.Transport.Name(), query.Reference))
+ if err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(origErr, "reference %q must be a docker reference", query.Reference))
+ return
+ }
+ }
+
+ // all-tags doesn't work with a tagged reference, so let's check early
+ namedRef, err := reference.Parse(query.Reference)
+ if err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "error parsing reference %q", query.Reference))
+ return
+ }
+ if _, isTagged := namedRef.(reference.Tagged); isTagged && query.AllTags {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Errorf("reference %q must not have a tag for all-tags", query.Reference))
+ return
+ }
+
+ var registryCreds *types.DockerAuthConfig
+ if len(query.Credentials) != 0 {
+ creds, err := util.ParseRegistryCreds(query.Credentials)
+ if err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "error parsing credentials %q", query.Credentials))
+ return
+ }
+ registryCreds = creds
+ }
+
+ // Setup the registry options
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ OSChoice: query.OverrideOS,
+ ArchitectureChoice: query.OverrideArch,
+ }
+ if query.TLSVerify {
+ dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
+ }
+
+ // Prepare the images we want to pull
+ imagesToPull := []string{}
+ res := []handlers.LibpodImagesPullReport{}
+ imageName := namedRef.String()
+
+ if !query.AllTags {
+ imagesToPull = append(imagesToPull, imageName)
+ } else {
+ systemContext := image.GetSystemContext("", "", false)
+ tags, err := docker.GetRepositoryTags(context.Background(), systemContext, imageRef)
+ if err != nil {
+ utils.InternalServerError(w, errors.Wrap(err, "error getting repository tags"))
+ return
+ }
+ for _, tag := range tags {
+ imagesToPull = append(imagesToPull, fmt.Sprintf("%s:%s", imageName, tag))
+ }
+ }
+
+ // Finally pull the images
+ for _, img := range imagesToPull {
+ newImage, err := runtime.ImageRuntime().New(
+ context.Background(),
+ img,
+ "",
+ "",
+ os.Stderr,
+ &dockerRegistryOptions,
+ image.SigningOptions{},
+ nil,
+ util.PullImageAlways)
+ if err != nil {
+ utils.InternalServerError(w, errors.Wrapf(err, "error pulling image %q", query.Reference))
+ return
+ }
+ res = append(res, handlers.LibpodImagesPullReport{ID: newImage.ID()})
+ }
+
+ utils.WriteResponse(w, http.StatusOK, res)
}
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 091368985..e9297d91b 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -91,7 +91,11 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
pod, err := runtime.NewPod(r.Context(), options...)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ http_code := http.StatusInternalServerError
+ if errors.Cause(err) == define.ErrPodExists {
+ http_code = http.StatusConflict
+ }
+ utils.Error(w, "Something went wrong.", http_code, err)
return
}
utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.CgroupParent()})
@@ -198,8 +202,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
}
}
if allContainersStopped {
- alreadyStopped := errors.Errorf("pod %s is already stopped", pod.ID())
- utils.Error(w, "Something went wrong", http.StatusNotModified, alreadyStopped)
+ utils.WriteResponse(w, http.StatusNotModified, "")
return
}
@@ -245,8 +248,7 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
}
}
if allContainersRunning {
- alreadyRunning := errors.Errorf("pod %s is already running", pod.ID())
- utils.Error(w, "Something went wrong", http.StatusNotModified, alreadyRunning)
+ utils.WriteResponse(w, http.StatusNotModified, "")
return
}
if _, err := pod.Start(r.Context()); err != nil {
@@ -409,5 +411,5 @@ func PodExists(w http.ResponseWriter, r *http.Request) {
utils.PodNotFound(w, name, err)
return
}
- utils.WriteResponse(w, http.StatusOK, "")
+ utils.WriteResponse(w, http.StatusNoContent, "")
}
diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go
new file mode 100644
index 000000000..aec30ef56
--- /dev/null
+++ b/pkg/api/handlers/libpod/swagger.go
@@ -0,0 +1,8 @@
+package libpod
+
+// List Containers
+// swagger:response ListContainers
+type swagInspectPodResponse struct {
+ // in:body
+ Body []ListContainer
+}
diff --git a/pkg/api/handlers/libpod/types.go b/pkg/api/handlers/libpod/types.go
new file mode 100644
index 000000000..0949b2a72
--- /dev/null
+++ b/pkg/api/handlers/libpod/types.go
@@ -0,0 +1,82 @@
+package libpod
+
+import (
+ "github.com/containers/libpod/cmd/podman/shared"
+ "github.com/containers/libpod/libpod"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+)
+
+// Listcontainer describes a container suitable for listing
+type ListContainer struct {
+ // Container command
+ Command []string
+ // Container creation time
+ Created int64
+ // If container has exited/stopped
+ Exited bool
+ // Time container exited
+ ExitedAt int64
+ // If container has exited, the return code from the command
+ ExitCode int32
+ // The unique identifier for the container
+ ID string `json:"Id"`
+ // Container image
+ Image string
+ // If this container is a Pod infra container
+ IsInfra bool
+ // Labels for container
+ Labels map[string]string
+ // User volume mounts
+ Mounts []string
+ // The names assigned to the container
+ Names []string
+ // Namespaces the container belongs to. Requires the
+ // namespace boolean to be true
+ Namespaces ListContainerNamespaces
+ // The process id of the container
+ Pid int
+ // If the container is part of Pod, the Pod ID. Requires the pod
+ // boolean to be set
+ Pod string
+ // If the container is part of Pod, the Pod name. Requires the pod
+ // boolean to be set
+ PodName string
+ // Port mappings
+ Ports []ocicni.PortMapping
+ // Size of the container rootfs. Requires the size boolean to be true
+ Size *shared.ContainerSize
+ // Time when container started
+ StartedAt int64
+ // State of container
+ State string
+}
+
+// ListContainer Namespaces contains the identifiers of the container's Linux namespaces
+type ListContainerNamespaces struct {
+ // Mount namespace
+ MNT string `json:"Mnt,omitempty"`
+ // Cgroup namespace
+ Cgroup string `json:"Cgroup,omitempty"`
+ // IPC namespace
+ IPC string `json:"Ipc,omitempty"`
+ // Network namespace
+ NET string `json:"Net,omitempty"`
+ // PID namespace
+ PIDNS string `json:"Pidns,omitempty"`
+ // UTS namespace
+ UTS string `json:"Uts,omitempty"`
+ // User namespace
+ User string `json:"User,omitempty"`
+}
+
+// sortContainers helps us set-up ability to sort by createTime
+type sortContainers []*libpod.Container
+
+func (a sortContainers) Len() int { return len(a) }
+func (a sortContainers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+
+type psSortCreateTime struct{ sortContainers }
+
+func (a psSortCreateTime) Less(i, j int) bool {
+ return a.sortContainers[i].CreatedTime().Before(a.sortContainers[j].CreatedTime())
+}
diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go
index bc75777aa..10525bfc7 100644
--- a/pkg/api/handlers/swagger.go
+++ b/pkg/api/handlers/swagger.go
@@ -1,7 +1,6 @@
package handlers
import (
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/inspect"
@@ -104,13 +103,6 @@ type swagDockerTopResponse struct {
}
}
-// List containers
-// swagger:response LibpodListContainersResponse
-type swagLibpodListContainersResponse struct {
- // in:body
- Body []shared.PsContainerOutput
-}
-
// Inspect container
// swagger:response LibpodInspectContainerResponse
type swagLibpodInspectContainerResponse struct {
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 6169adb18..f5d9f9ad5 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -33,6 +33,18 @@ type ContainerConfig struct {
dockerContainer.Config
}
+type LibpodImagesLoadReport struct {
+ ID string `json:"id"`
+}
+
+type LibpodImagesImportReport struct {
+ ID string `json:"id"`
+}
+
+type LibpodImagesPullReport struct {
+ ID string `json:"id"`
+}
+
type ImageSummary struct {
docker.ImageSummary
CreatedTime time.Time `json:"CreatedTime,omitempty"`
@@ -49,21 +61,6 @@ type LibpodContainersPruneReport struct {
PruneError string `json:"error"`
}
-type LibpodImagesLoadReport struct {
- ID string `json:"id"`
- RepoTags []string `json:"repoTags"`
-}
-
-type LibpodImagesImportReport struct {
- ID string `json:"id"`
- RepoTags []string `json:"repoTags"`
-}
-
-type LibpodImagesPullReport struct {
- ID string `json:"id"`
- RepoTags []string `json:"repoTags"`
-}
-
type Info struct {
docker.Info
BuildahVersion string
diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go
index 970f93791..44bcc794c 100644
--- a/pkg/api/handlers/utils/handler.go
+++ b/pkg/api/handlers/utils/handler.go
@@ -23,6 +23,14 @@ func IsLibpodRequest(r *http.Request) bool {
// WriteResponse encodes the given value as JSON or string and renders it for http client
func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
+ // RFC2616 explicitly states that the following status codes "MUST NOT
+ // include a message-body":
+ switch code {
+ case http.StatusNoContent, http.StatusNotModified: // 204, 304
+ w.WriteHeader(code)
+ return
+ }
+
switch v := value.(type) {
case string:
w.Header().Set("Content-Type", "text/plain; charset=us-ascii")
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index abae81c38..ed30bc14a 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -610,7 +610,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error {
// - application/json
// responses:
// 200:
- // $ref: "#/responses/LibpodListContainersResponse"
+ // $ref: "#/responses/ListContainers"
// 400:
// $ref: "#/responses/BadParamError"
// 500:
diff --git a/pkg/api/server/register_events.go b/pkg/api/server/register_events.go
index a32244f4d..090f66323 100644
--- a/pkg/api/server/register_events.go
+++ b/pkg/api/server/register_events.go
@@ -29,7 +29,7 @@ func (s *APIServer) RegisterEventsHandlers(r *mux.Router) error {
// description: JSON encoded map[string][]string of constraints
// responses:
// 200:
- // $ref: "#/responses/ok"
+ // description: returns a string of json data describing an event
// 500:
// "$ref": "#/responses/InternalError"
r.Handle(VersionedPath("/events"), APIHandler(s.Context, handlers.GetEvents))
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 2959e604a..f082c5fec 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -638,25 +638,22 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// summary: Load image
// description: Load an image (oci-archive or docker-archive) stream.
// parameters:
- // - in: query
- // name: change
- // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string"
- // type: string
- // - in: query
- // name: message
- // description: Set commit message for imported image
- // type: string
- // - in: body
- // name: request
- // description: tarball of container image
- // required: true
- // schema:
- // type: string
+ // - in: query
+ // name: reference
+ // description: "Optional Name[:TAG] for the image"
+ // type: string
+ // - in: formData
+ // name: upload
+ // description: tarball of container image
+ // type: file
+ // required: true
// produces:
// - application/json
// responses:
// 200:
- // $ref: "#/response/LibpodImagesLoadResponse"
+ // $ref: "#/responses/DocsLibpodImagesLoadResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImagesLoad)).Methods(http.MethodPost)
@@ -665,59 +662,80 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// tags:
// - images
// summary: Import image
- // description: Import a previosly exported tarball as an image.
+ // description: Import a previously exported tarball as an image.
// parameters:
- // - in: query
- // name: change
- // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string"
- // type: string
- // - in: query
- // name: message
- // description: Set commit message for imported image
- // type: string
- // - in: query
- // name: url
- // description: Specify a URL instead of a tarball
- // type: bool
- // - in: body
- // name: request
- // description: Tarball of (or URL to) container image
- // required: true
- // schema:
- // type: string
+ // - in: query
+ // name: changes
+ // description: "Apply the following possible instructions to the created image: CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string"
+ // type: array
+ // items:
+ // type: string
+ // - in: query
+ // name: message
+ // description: Set commit message for imported image
+ // type: string
+ // - in: query
+ // name: reference
+ // description: "Optional Name[:TAG] for the image"
+ // type: string
+ // - in: query
+ // name: url
+ // description: Load image from the specified URL
+ // type: string
+ // - in: formData
+ // name: upload
+ // type: file
+ // required: true
+ // description: tarball for imported image
// produces:
// - application/json
// responses:
// 200:
- // $ref: "#/response/LibpodImagesImportResponse"
+ // $ref: "#/responses/DocsLibpodImagesImportResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/import"), APIHandler(s.Context, libpod.ImagesImport)).Methods(http.MethodPost)
- // swagger:operation GET /libpod/images/pull libpod libpodImagesPull
+ // swagger:operation POST /libpod/images/pull libpod libpodImagesPull
// ---
// tags:
// - images
- // summary: Import image
- // description: Import a previosly exported image as a tarball.
+ // summary: Pull images
+ // description: Pull one or more images from a container registry.
// parameters:
- // - in: query
- // name: reference
- // description: Mandatory reference to the image (e.g., quay.io/image/name:tag)/
- // type: string
- // - in: query
- // name: credentials
- // description: username:password for the registry.
- // type: string
- // - in: query
- // name: tls-verify
- // description: Require TLS verification.
- // type: bool
- // default: true
+ // - in: query
+ // name: reference
+ // description: "Mandatory reference to the image (e.g., quay.io/image/name:tag)"
+ // type: string
+ // - in: query
+ // name: credentials
+ // description: "username:password for the registry"
+ // type: string
+ // - in: query
+ // name: overrideOS
+ // description: Pull image for the specified operating system.
+ // type: string
+ // - in: query
+ // name: overrideArch
+ // description: Pull image for the specified architecture.
+ // type: string
+ // - in: query
+ // name: tlsVerify
+ // description: Require TLS verification.
+ // type: boolean
+ // default: true
+ // - in: query
+ // name: allTags
+ // description: Pull all tagged images in the repository.
+ // type: boolean
// produces:
// - application/json
// responses:
// 200:
- // $ref: "#/response/LibpodImagesPullResponse"
+ // $ref: "#/responses/DocsLibpodImagesPullResponse"
+ // 400:
+ // $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/pull"), APIHandler(s.Context, libpod.ImagesPull)).Methods(http.MethodPost)
diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go
index 5c7b51871..974568d47 100644
--- a/pkg/api/server/register_pods.go
+++ b/pkg/api/server/register_pods.go
@@ -41,6 +41,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// type: string
// 400:
// $ref: "#/responses/BadParamError"
+ // 409:
+ // description: pod already exists
// 500:
// $ref: "#/responses/InternalError"
r.Handle(VersionedPath("/libpod/pods/prune"), APIHandler(s.Context, libpod.PodPrune)).Methods(http.MethodPost)
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 69f04034d..2c709bc59 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -106,6 +106,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
server.RegisterContainersHandlers,
server.RegisterDistributionHandlers,
server.registerExecHandlers,
+ server.RegisterEventsHandlers,
server.registerHealthCheckHandlers,
server.registerImagesHandlers,
server.registerInfoHandlers,
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 116af9709..f270060a6 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -130,7 +130,7 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string,
// if more desirable we could use url to form the encoded endpoint with params
r := req.URL.Query()
for k, v := range queryParams {
- r.Add(k, url.QueryEscape(v))
+ r.Add(k, v)
}
req.URL.RawQuery = r.Encode()
}
@@ -155,18 +155,14 @@ func GetConnectionFromContext(ctx context.Context) (*Connection, error) {
return conn, nil
}
-// FiltersToHTML converts our typical filter format of a
+// FiltersToString converts our typical filter format of a
// map[string][]string to a query/html safe string.
-func FiltersToHTML(filters map[string][]string) (string, error) {
+func FiltersToString(filters map[string][]string) (string, error) {
lowerCaseKeys := make(map[string][]string)
for k, v := range filters {
lowerCaseKeys[strings.ToLower(k)] = v
}
- unsafeString, err := jsoniter.MarshalToString(lowerCaseKeys)
- if err != nil {
- return "", err
- }
- return url.QueryEscape(unsafeString), nil
+ return jsoniter.MarshalToString(lowerCaseKeys)
}
// IsInformation returns true if the response code is 1xx
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index 334a656d4..04f7f8802 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -5,8 +5,8 @@ import (
"net/http"
"strconv"
- "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod"
"github.com/containers/libpod/pkg/bindings"
)
@@ -15,13 +15,16 @@ import (
// the most recent number of containers. The pod and size booleans indicate that pod information and rootfs
// size information should also be included. Finally, the sync bool synchronizes the OCI runtime and
// container state.
-func List(ctx context.Context, filters map[string][]string, last *int, pod, size, sync *bool) ([]*shared.PsContainerOutput, error) { // nolint:typecheck
+func List(ctx context.Context, filters map[string][]string, all *bool, last *int, pod, size, sync *bool) ([]lpapiv2.ListContainer, error) { // nolint:typecheck
conn, err := bindings.GetConnectionFromContext(ctx)
if err != nil {
return nil, err
}
- var images []*shared.PsContainerOutput
+ var containers []lpapiv2.ListContainer
params := make(map[string]string)
+ if all != nil {
+ params["all"] = strconv.FormatBool(*all)
+ }
if last != nil {
params["last"] = strconv.Itoa(*last)
}
@@ -35,7 +38,7 @@ func List(ctx context.Context, filters map[string][]string, last *int, pod, size
params["sync"] = strconv.FormatBool(*sync)
}
if filters != nil {
- filterString, err := bindings.FiltersToHTML(filters)
+ filterString, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
@@ -43,9 +46,9 @@ func List(ctx context.Context, filters map[string][]string, last *int, pod, size
}
response, err := conn.DoRequest(nil, http.MethodGet, "/containers/json", params)
if err != nil {
- return images, err
+ return containers, err
}
- return images, response.Process(nil)
+ return containers, response.Process(&containers)
}
// Prune removes stopped and exited containers from local storage. The optional filters can be
@@ -62,7 +65,7 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
}
params := make(map[string]string)
if filters != nil {
- filterString, err := bindings.FiltersToHTML(filters)
+ filterString, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index deaf93f0e..b19482943 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -38,7 +38,7 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*handl
params["all"] = strconv.FormatBool(*all)
}
if filters != nil {
- strFilters, err := bindings.FiltersToHTML(filters)
+ strFilters, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
@@ -155,7 +155,7 @@ func Prune(ctx context.Context, filters map[string][]string) ([]string, error) {
}
params := make(map[string]string)
if filters != nil {
- stringFilter, err := bindings.FiltersToHTML(filters)
+ stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/images/search.go b/pkg/bindings/images/search.go
index d98ddf18d..58b25425b 100644
--- a/pkg/bindings/images/search.go
+++ b/pkg/bindings/images/search.go
@@ -26,7 +26,7 @@ func Search(ctx context.Context, term string, limit *int, filters map[string][]s
params["limit"] = strconv.Itoa(*limit)
}
if filters != nil {
- stringFilter, err := bindings.FiltersToHTML(filters)
+ stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/pods/pods.go b/pkg/bindings/pods/pods.go
index a6b74c21d..d079f01c2 100644
--- a/pkg/bindings/pods/pods.go
+++ b/pkg/bindings/pods/pods.go
@@ -97,7 +97,7 @@ func List(ctx context.Context, filters map[string][]string) (*[]libpod.PodInspec
}
params := make(map[string]string)
if filters != nil {
- stringFilter, err := bindings.FiltersToHTML(filters)
+ stringFilter, err := bindings.FiltersToString(filters)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go
index 15783041f..22cd0b7e0 100644
--- a/pkg/bindings/test/common_test.go
+++ b/pkg/bindings/test/common_test.go
@@ -16,6 +16,7 @@ import (
const (
defaultPodmanBinaryLocation string = "/usr/bin/podman"
alpine string = "docker.io/library/alpine:latest"
+ busybox string = "docker.io/library/busybox:latest"
)
type bindingTest struct {
@@ -113,7 +114,38 @@ func (b *bindingTest) startAPIService() *gexec.Session {
}
func (b *bindingTest) cleanup() {
+ s := b.runPodman([]string{"stop", "-a", "-t", "0"})
+ s.Wait(45)
if err := os.RemoveAll(b.tempDirPath); err != nil {
fmt.Println(err)
}
}
+
+// Pull is a helper function to pull in images
+func (b *bindingTest) Pull(name string) {
+ p := b.runPodman([]string{"pull", name})
+ p.Wait(45)
+}
+
+// Run a container and add append the alpine image to it
+func (b *bindingTest) RunTopContainer(name *string) {
+ cmd := []string{"run", "-dt"}
+ if name != nil {
+ containerName := *name
+ cmd = append(cmd, "--name", containerName)
+ }
+ cmd = append(cmd, alpine, "top")
+ p := b.runPodman(cmd)
+ p.Wait(45)
+}
+
+// StringInSlice returns a boolean based on whether a given
+// string is in a given slice
+func StringInSlice(s string, sl []string) bool {
+ for _, val := range sl {
+ if s == val {
+ return true
+ }
+ }
+ return false
+}
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index f2dc856b2..fea611601 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -2,10 +2,10 @@ package test_bindings
import (
"context"
- "fmt"
"time"
"github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/bindings/images"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -17,12 +17,12 @@ var _ = Describe("Podman images", func() {
//tempdir string
//err error
//podmanTest *PodmanTestIntegration
- bt *bindingTest
- s *gexec.Session
- connText context.Context
- err error
- false bool
- //true bool = true
+ bt *bindingTest
+ s *gexec.Session
+ connText context.Context
+ err error
+ falseFlag bool = false
+ trueFlag bool = true
)
BeforeEach(func() {
@@ -34,8 +34,8 @@ var _ = Describe("Podman images", func() {
//podmanTest.Setup()
//podmanTest.SeedImages()
bt = newBindingTest()
- p := bt.runPodman([]string{"pull", alpine})
- p.Wait(45)
+ bt.Pull(alpine)
+ bt.Pull(busybox)
s = bt.startAPIService()
time.Sleep(1 * time.Second)
connText, err = bindings.NewConnection(bt.sock)
@@ -68,28 +68,63 @@ var _ = Describe("Podman images", func() {
_, err = images.GetImage(connText, data.ID[0:12], nil)
Expect(err).To(BeNil())
- //Inspect by long name should work, it doesnt (yet) i think it needs to be html escaped
- _, err = images.GetImage(connText, alpine, nil)
- Expect(err).To(BeNil())
+ // The test to inspect by long name needs to fixed.
+ // Inspect by long name should work, it doesnt (yet) i think it needs to be html escaped
+ // _, err = images.GetImage(connText, alpine, nil)
+ // Expect(err).To(BeNil())
})
+
+ // Test to validate the remove image api
It("remove image", func() {
// Remove invalid image should be a 404
- _, err = images.Remove(connText, "foobar5000", &false)
+ _, err = images.Remove(connText, "foobar5000", &falseFlag)
Expect(err).ToNot(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", 404))
- _, err := images.GetImage(connText, "alpine", nil)
+ // Remove an image by name, validate image is removed and error is nil
+ inspectData, err := images.GetImage(connText, "busybox", nil)
+ Expect(err).To(BeNil())
+ response, err := images.Remove(connText, "busybox", nil)
+ Expect(err).To(BeNil())
+ Expect(inspectData.ID).To(Equal(response[0]["Deleted"]))
+ inspectData, err = images.GetImage(connText, "busybox", nil)
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", 404))
+
+ // Start a container with alpine image
+ var top string = "top"
+ bt.RunTopContainer(&top)
+ // we should now have a container called "top" running
+ containerResponse, err := containers.Inspect(connText, "top", &falseFlag)
Expect(err).To(BeNil())
+ Expect(containerResponse.Name).To(Equal("top"))
- response, err := images.Remove(connText, "alpine", &false)
+ // try to remove the image "alpine". This should fail since we are not force
+ // deleting hence image cannot be deleted until the container is deleted.
+ response, err = images.Remove(connText, "alpine", &falseFlag)
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", 500))
+
+ // Removing the image "alpine" where force = true
+ response, err = images.Remove(connText, "alpine", &trueFlag)
Expect(err).To(BeNil())
- fmt.Println(response)
- // to be continued
+ // Checking if both the images are gone as well as the container is deleted
+ inspectData, err = images.GetImage(connText, "busybox", nil)
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", 404))
+
+ inspectData, err = images.GetImage(connText, "alpine", nil)
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", 404))
+
+ _, err = containers.Inspect(connText, "top", &falseFlag)
+ code, _ = bindings.CheckResponseCode(err)
+ Expect(code).To(BeNumerically("==", 404))
})
- //Tests to validate the image tag command.
+ // Tests to validate the image tag command.
It("tag image", func() {
// Validates if invalid image name is given a bad response is encountered.
err = images.Tag(connText, "dummy", "demo", "alpine")
@@ -107,21 +142,30 @@ var _ = Describe("Podman images", func() {
})
- //Test to validate the List images command.
+ // Test to validate the List images command.
It("List image", func() {
- //Array to hold the list of images returned
+ // Array to hold the list of images returned
imageSummary, err := images.List(connText, nil, nil)
- //There Should be no errors in the response.
+ // There Should be no errors in the response.
Expect(err).To(BeNil())
- //Since in the begin context only one image is created the list context should have only one image
- Expect(len(imageSummary)).To(Equal(1))
-
- //To be written create a new image and check list count again
- //imageSummary, err = images.List(connText, nil, nil)
-
- //Since in the begin context only one image adding one more image should
- ///Expect(len(imageSummary)).To(Equal(2)
-
+ // Since in the begin context two images are created the
+ // list context should have only 2 images
+ Expect(len(imageSummary)).To(Equal(2))
+
+ // Adding one more image. There Should be no errors in the response.
+ // And the count should be three now.
+ bt.Pull("busybox:glibc")
+ imageSummary, err = images.List(connText, nil, nil)
+ Expect(err).To(BeNil())
+ Expect(len(imageSummary)).To(Equal(3))
+
+ //Validate the image names.
+ var names []string
+ for _, i := range imageSummary {
+ names = append(names, i.RepoTags...)
+ }
+ Expect(StringInSlice(alpine, names)).To(BeTrue())
+ Expect(StringInSlice(busybox, names)).To(BeTrue())
})
})
diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go
index 96786223d..6c5b7978c 100644
--- a/pkg/cgroups/cgroups.go
+++ b/pkg/cgroups/cgroups.go
@@ -536,15 +536,14 @@ func (c *CgroupControl) Stat() (*Metrics, error) {
return &m, nil
}
-func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) {
+func readCgroup2MapPath(path string) (map[string][]string, error) {
ret := map[string][]string{}
- p := filepath.Join(cgroupRoot, ctr.path, name)
- f, err := os.Open(p)
+ f, err := os.Open(path)
if err != nil {
if os.IsNotExist(err) {
return ret, nil
}
- return nil, errors.Wrapf(err, "open file %s", p)
+ return nil, errors.Wrapf(err, "open file %s", path)
}
defer f.Close()
scanner := bufio.NewScanner(f)
@@ -557,7 +556,13 @@ func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, e
ret[parts[0]] = parts[1:]
}
if err := scanner.Err(); err != nil {
- return nil, errors.Wrapf(err, "parsing file %s", p)
+ return nil, errors.Wrapf(err, "parsing file %s", path)
}
return ret, nil
}
+
+func readCgroup2MapFile(ctr *CgroupControl, name string) (map[string][]string, error) {
+ p := filepath.Join(cgroupRoot, ctr.path, name)
+
+ return readCgroup2MapPath(p)
+}
diff --git a/pkg/cgroups/cpu.go b/pkg/cgroups/cpu.go
index a43a76b22..5f0a18031 100644
--- a/pkg/cgroups/cpu.go
+++ b/pkg/cgroups/cpu.go
@@ -121,3 +121,42 @@ func (c *cpuHandler) Stat(ctr *CgroupControl, m *Metrics) error {
m.CPU = CPUMetrics{Usage: usage}
return nil
}
+
+// GetSystemCPUUsage returns the system usage for all the cgroups
+func GetSystemCPUUsage() (uint64, error) {
+ cgroupv2, err := IsCgroup2UnifiedMode()
+ if err != nil {
+ return 0, err
+ }
+ if !cgroupv2 {
+ p := filepath.Join(cgroupRoot, CPUAcct, "cpuacct.usage")
+ return readFileAsUint64(p)
+ }
+
+ files, err := ioutil.ReadDir(cgroupRoot)
+ if err != nil {
+ return 0, errors.Wrapf(err, "read directory %q", cgroupRoot)
+ }
+ var total uint64
+ for _, file := range files {
+ if !file.IsDir() {
+ continue
+ }
+ p := filepath.Join(cgroupRoot, file.Name(), "cpu.stat")
+
+ values, err := readCgroup2MapPath(p)
+ if err != nil {
+ return 0, err
+ }
+
+ if val, found := values["usage_usec"]; found {
+ v, err := strconv.ParseUint(cleanString(val[0]), 10, 0)
+ if err != nil {
+ return 0, err
+ }
+ total += v * 1000
+ }
+
+ }
+ return total, nil
+}
diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go
index 3e678d33a..2b51f4e09 100644
--- a/pkg/rootlessport/rootlessport_linux.go
+++ b/pkg/rootlessport/rootlessport_linux.go
@@ -122,6 +122,7 @@ func parent() error {
logrus.WithError(driverErr).Warn("parent driver exited")
}
errCh <- driverErr
+ close(errCh)
}()
opaque := driver.OpaqueForChild()
logrus.Infof("opaque=%+v", opaque)
@@ -142,15 +143,12 @@ func parent() error {
}()
// reexec the child process in the child netns
- cmd := exec.Command(fmt.Sprintf("/proc/%d/exe", os.Getpid()))
+ cmd := exec.Command("/proc/self/exe")
cmd.Args = []string{reexecChildKey}
cmd.Stdin = childQuitR
cmd.Stdout = &logrusWriter{prefix: "child"}
cmd.Stderr = cmd.Stdout
cmd.Env = append(os.Environ(), reexecChildEnvOpaque+"="+string(opaqueJSON))
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: syscall.SIGTERM,
- }
childNS, err := ns.GetNS(cfg.NetNSPath)
if err != nil {
return err
@@ -162,14 +160,27 @@ func parent() error {
return err
}
+ defer func() {
+ if err := syscall.Kill(cmd.Process.Pid, syscall.SIGTERM); err != nil {
+ logrus.WithError(err).Warn("kill child process")
+ }
+ }()
+
logrus.Info("waiting for initComplete")
// wait for the child to connect to the parent
- select {
- case <-initComplete:
- logrus.Infof("initComplete is closed; parent and child established the communication channel")
- case err := <-errCh:
- return err
+outer:
+ for {
+ select {
+ case <-initComplete:
+ logrus.Infof("initComplete is closed; parent and child established the communication channel")
+ break outer
+ case err := <-errCh:
+ if err != nil {
+ return err
+ }
+ }
}
+
defer func() {
logrus.Info("stopping parent driver")
quit <- struct{}{}
diff --git a/pkg/seccomp/seccomp.go b/pkg/seccomp/seccomp.go
new file mode 100644
index 000000000..dcf255378
--- /dev/null
+++ b/pkg/seccomp/seccomp.go
@@ -0,0 +1,54 @@
+package seccomp
+
+import (
+ "sort"
+
+ "github.com/pkg/errors"
+)
+
+// ContianerImageLabel is the key of the image annotation embedding a seccomp
+// profile.
+const ContainerImageLabel = "io.containers.seccomp.profile"
+
+// Policy denotes a seccomp policy.
+type Policy int
+
+const (
+ // PolicyDefault - if set use SecurityConfig.SeccompProfilePath,
+ // otherwise use the default profile. The SeccompProfilePath might be
+ // explicitly set by the user.
+ PolicyDefault Policy = iota
+ // PolicyImage - if set use SecurityConfig.SeccompProfileFromImage,
+ // otherwise follow SeccompPolicyDefault.
+ PolicyImage
+)
+
+// Map for easy lookups of supported policies.
+var supportedPolicies = map[string]Policy{
+ "": PolicyDefault,
+ "default": PolicyDefault,
+ "image": PolicyImage,
+}
+
+// LookupPolicy looksup the corresponding Policy for the specified
+// string. If none is found, an errors is returned including the list of
+// supported policies.
+//
+// Note that an empty string resolved to SeccompPolicyDefault.
+func LookupPolicy(s string) (Policy, error) {
+ policy, exists := supportedPolicies[s]
+ if exists {
+ return policy, nil
+ }
+
+ // Sort the keys first as maps are non-deterministic.
+ keys := []string{}
+ for k := range supportedPolicies {
+ if k != "" {
+ keys = append(keys, k)
+ }
+ }
+ sort.Strings(keys)
+
+ return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys)
+}
diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go
index 32d8cb4de..5f39b6d0d 100644
--- a/pkg/spec/config_linux.go
+++ b/pkg/spec/config_linux.go
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "strconv"
"strings"
"github.com/containers/libpod/pkg/rootless"
@@ -90,6 +91,42 @@ func devicesFromPath(g *generate.Generator, devicePath string) error {
return addDevice(g, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":"))
}
+func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error {
+ for _, deviceCgroupRule := range deviceCgroupRules {
+ if err := validateDeviceCgroupRule(deviceCgroupRule); err != nil {
+ return err
+ }
+ ss := parseDeviceCgroupRule(deviceCgroupRule)
+ if len(ss[0]) != 5 {
+ return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ matches := ss[0]
+ var major, minor *int64
+ if matches[2] == "*" {
+ majorDev := int64(-1)
+ major = &majorDev
+ } else {
+ majorDev, err := strconv.ParseInt(matches[2], 10, 64)
+ if err != nil {
+ return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ major = &majorDev
+ }
+ if matches[3] == "*" {
+ minorDev := int64(-1)
+ minor = &minorDev
+ } else {
+ minorDev, err := strconv.ParseInt(matches[2], 10, 64)
+ if err != nil {
+ return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ minor = &minorDev
+ }
+ g.AddLinuxResourcesDevice(true, matches[1], major, minor, matches[4])
+ }
+ return nil
+}
+
func addDevice(g *generate.Generator, device string) error {
src, dst, permissions, err := ParseDevice(device)
if err != nil {
diff --git a/pkg/spec/config_linux_cgo.go b/pkg/spec/config_linux_cgo.go
index ae83c9d52..05f42c4da 100644
--- a/pkg/spec/config_linux_cgo.go
+++ b/pkg/spec/config_linux_cgo.go
@@ -5,9 +5,10 @@ package createconfig
import (
"io/ioutil"
+ "github.com/containers/libpod/pkg/seccomp"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
- seccomp "github.com/seccomp/containers-golang"
+ goSeccomp "github.com/seccomp/containers-golang"
"github.com/sirupsen/logrus"
)
@@ -15,9 +16,9 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu
var seccompConfig *spec.LinuxSeccomp
var err error
- if config.SeccompPolicy == SeccompPolicyImage && config.SeccompProfileFromImage != "" {
+ if config.SeccompPolicy == seccomp.PolicyImage && config.SeccompProfileFromImage != "" {
logrus.Debug("Loading seccomp profile from the security config")
- seccompConfig, err = seccomp.LoadProfile(config.SeccompProfileFromImage, configSpec)
+ seccompConfig, err = goSeccomp.LoadProfile(config.SeccompProfileFromImage, configSpec)
if err != nil {
return nil, errors.Wrap(err, "loading seccomp profile failed")
}
@@ -30,13 +31,13 @@ func getSeccompConfig(config *SecurityConfig, configSpec *spec.Spec) (*spec.Linu
if err != nil {
return nil, errors.Wrapf(err, "opening seccomp profile (%s) failed", config.SeccompProfilePath)
}
- seccompConfig, err = seccomp.LoadProfile(string(seccompProfile), configSpec)
+ seccompConfig, err = goSeccomp.LoadProfile(string(seccompProfile), configSpec)
if err != nil {
return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath)
}
} else {
logrus.Debug("Loading default seccomp profile")
- seccompConfig, err = seccomp.GetDefaultProfile(configSpec)
+ seccompConfig, err = goSeccomp.GetDefaultProfile(configSpec)
if err != nil {
return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", config.SeccompProfilePath)
}
diff --git a/pkg/spec/config_unsupported.go b/pkg/spec/config_unsupported.go
index a2c7f4416..be3e7046d 100644
--- a/pkg/spec/config_unsupported.go
+++ b/pkg/spec/config_unsupported.go
@@ -30,3 +30,7 @@ func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrott
func devicesFromPath(g *generate.Generator, devicePath string) error {
return errors.New("function not implemented")
}
+
+func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error {
+ return errors.New("function not implemented")
+}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index fb222083b..8010be0d4 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -2,7 +2,6 @@ package createconfig
import (
"os"
- "sort"
"strconv"
"strings"
"syscall"
@@ -11,6 +10,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/namespaces"
+ "github.com/containers/libpod/pkg/seccomp"
"github.com/containers/storage"
"github.com/docker/go-connections/nat"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -38,6 +38,7 @@ type CreateResourceConfig struct {
CPUs float64 // cpus
CPUsetCPUs string
CPUsetMems string // cpuset-mems
+ DeviceCgroupRules []string //device-cgroup-rule
DeviceReadBps []string // device-read-bps
DeviceReadIOps []string // device-read-iops
DeviceWriteBps []string // device-write-bps
@@ -107,48 +108,6 @@ type NetworkConfig struct {
PublishAll bool //publish-all
}
-// SeccompPolicy determines which seccomp profile gets applied to the container.
-type SeccompPolicy int
-
-const (
- // SeccompPolicyDefault - if set use SecurityConfig.SeccompProfilePath,
- // otherwise use the default profile. The SeccompProfilePath might be
- // explicitly set by the user.
- SeccompPolicyDefault SeccompPolicy = iota
- // SeccompPolicyImage - if set use SecurityConfig.SeccompProfileFromImage,
- // otherwise follow SeccompPolicyDefault.
- SeccompPolicyImage
-)
-
-// Map for easy lookups of supported policies.
-var supportedSeccompPolicies = map[string]SeccompPolicy{
- "": SeccompPolicyDefault,
- "default": SeccompPolicyDefault,
- "image": SeccompPolicyImage,
-}
-
-// LookupSeccompPolicy looksup the corresponding SeccompPolicy for the specified
-// string. If none is found, an errors is returned including the list of
-// supported policies.
-// Note that an empty string resolved to SeccompPolicyDefault.
-func LookupSeccompPolicy(s string) (SeccompPolicy, error) {
- policy, exists := supportedSeccompPolicies[s]
- if exists {
- return policy, nil
- }
-
- // Sort the keys first as maps are non-deterministic.
- keys := []string{}
- for k := range supportedSeccompPolicies {
- if k != "" {
- keys = append(keys, k)
- }
- }
- sort.Strings(keys)
-
- return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys)
-}
-
// SecurityConfig configures the security features for the container
type SecurityConfig struct {
CapAdd []string // cap-add
@@ -158,7 +117,7 @@ type SecurityConfig struct {
ApparmorProfile string //SecurityOpts
SeccompProfilePath string //SecurityOpts
SeccompProfileFromImage string // seccomp profile from the container image
- SeccompPolicy SeccompPolicy
+ SeccompPolicy seccomp.Policy
SecurityOpts []string
Privileged bool //privileged
ReadOnlyRootfs bool //read-only
diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go
index 6fa0b0636..a5dfccdb9 100644
--- a/pkg/spec/parse.go
+++ b/pkg/spec/parse.go
@@ -2,12 +2,17 @@ package createconfig
import (
"fmt"
+ "regexp"
"strconv"
"strings"
"github.com/docker/go-units"
+ "github.com/pkg/errors"
)
+// deviceCgroupRulegex defines the valid format of device-cgroup-rule
+var deviceCgroupRuleRegex = regexp.MustCompile(`^([acb]) ([0-9]+|\*):([0-9]+|\*) ([rwm]{1,3})$`)
+
// Pod signifies a kernel namespace is being shared
// by a container with the pod it is associated with
const Pod = "pod"
@@ -205,3 +210,16 @@ func IsValidDeviceMode(mode string) bool {
}
return true
}
+
+// validateDeviceCgroupRule validates the format of deviceCgroupRule
+func validateDeviceCgroupRule(deviceCgroupRule string) error {
+ if !deviceCgroupRuleRegex.MatchString(deviceCgroupRule) {
+ return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule)
+ }
+ return nil
+}
+
+// parseDeviceCgroupRule matches and parses the deviceCgroupRule into slice
+func parseDeviceCgroupRule(deviceCgroupRule string) [][]string {
+ return deviceCgroupRuleRegex.FindAllStringSubmatch(deviceCgroupRule, -1)
+}
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index cae055bb0..b2a152a2d 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -232,6 +232,12 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
return nil, err
}
}
+ if len(config.Resources.DeviceCgroupRules) != 0 {
+ if err := deviceCgroupRules(&g, config.Resources.DeviceCgroupRules); err != nil {
+ return nil, err
+ }
+ addedResources = true
+ }
}
// SECURITY OPTS
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index 333595a96..b144bfa5e 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -143,6 +143,7 @@ func (i *LibpodAPI) GetImage(call iopodman.VarlinkCall, id string) error {
func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildInfo) error {
var (
namespace []buildah.NamespaceOption
+ imageID string
err error
)
@@ -249,7 +250,8 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
c := make(chan error)
go func() {
- _, _, err := i.Runtime.Build(getContext(), options, newPathDockerFiles...)
+ iid, _, err := i.Runtime.Build(getContext(), options, newPathDockerFiles...)
+ imageID = iid
c <- err
close(c)
}()
@@ -291,13 +293,9 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI
}
call.Continues = false
- newImage, err := i.Runtime.ImageRuntime().NewFromLocal(config.Output)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
br := iopodman.MoreResponse{
Logs: log,
- Id: newImage.ID(),
+ Id: imageID,
}
return call.ReplyBuildImage(br)
}
diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at
index e87ec534c..a54063260 100644
--- a/test/apiv2/01-basic.at
+++ b/test/apiv2/01-basic.at
@@ -27,7 +27,8 @@ t GET /nonesuch 404
t POST /nonesuch '' 404
t GET container/nonesuch/json 404
t GET libpod/containers/nonesuch/json 404
-t GET 'libpod/containers/json?a=b' 400
+
+#### FIXME: maybe someday: t GET 'libpod/containers/json?a=b' 400
# Method not allowed
t POST /_ping '' 405
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 243b35e9f..42ec028d0 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -6,9 +6,9 @@
# FIXME: API doesn't support pull yet, so use podman
podman pull -q $IMAGE
-# We want the SHA without the "sha256:" prefix
-full_iid=$(podman images --no-trunc --format '{{.ID}}' $IMAGE)
-iid=${full_iid##sha256:}
+t GET libpod/images/json 200 \
+ .[0].Id~[0-9a-f]\\{64\\}
+iid=$(jq -r '.[0].Id' <<<"$output")
t GET libpod/images/$iid/exists 204
t GET libpod/images/$PODMAN_TEST_IMAGE_NAME/exists 204
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index 5f0a145f0..a69e8cc99 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -11,18 +11,22 @@ podman pull $IMAGE &>/dev/null
# Ensure clean slate
podman rm -a -f &>/dev/null
-t GET libpod/containers/json 200 []
+t GET libpod/containers/json 200 length=0
podman run $IMAGE true
-t GET libpod/containers/json 200 \
- .[0].ID~[0-9a-f]\\{12\\} \
+t GET libpod/containers/json 200 length=0
+
+t GET libpod/containers/json?all=true 200 \
+ length=1 \
+ .[0].Id~[0-9a-f]\\{12\\} \
.[0].Image=$IMAGE \
- .[0].Command=true \
- .[0].State=4 \
+ .[0].Command[0]="true" \
+ .[0].State=exited \
+ .[0].ExitCode=0 \
.[0].IsInfra=false
-cid=$(jq -r '.[0].ID' <<<"$output")
+cid=$(jq -r '.[0].Id' <<<"$output")
t DELETE libpod/containers/$cid 204
diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at
index 1c25a3822..705de94d2 100644
--- a/test/apiv2/40-pods.at
+++ b/test/apiv2/40-pods.at
@@ -3,19 +3,31 @@
# test pod-related endpoints
#
+# FIXME! Shouldn't /create give an actual pod ID?
+expected_id='machine.slice'
+if rootless; then
+ expected_id=/libpod_parent
+fi
+
t GET libpod/pods/json 200 null
-t POST libpod/pods/create name=foo 201 '{"id":"machine.slice"}' # FIXME!
+t POST libpod/pods/create name=foo 201 .id=$expected_id
t GET libpod/pods/foo/exists 204
t GET libpod/pods/notfoo/exists 404
t GET libpod/pods/foo/json 200 .Config.name=foo .Containers=null
t GET libpod/pods/json 200 .[0].Config.name=foo .[0].Containers=null
-# Cannot create a dup pod with the same name (FIXME: should that be 409?)
-t POST libpod/pods/create name=foo 500 .cause="pod already exists"
+# Cannot create a dup pod with the same name
+t POST libpod/pods/create name=foo 409 .cause="pod already exists"
#t POST libpod/pods/create a=b 400 .cause='bad parameter' # FIXME: unimplemented
-t POST libpod/pods/foo/pause '' 204
+if root; then
+ t POST libpod/pods/foo/pause '' 204
+else
+ t POST libpod/pods/foo/pause '' 500 \
+ .cause="this container does not have a cgroup" \
+ .message~".*pause pods containing rootless containers with cgroup V1"
+fi
t POST libpod/pods/foo/unpause '' 200
t POST libpod/pods/foo/unpause '' 200 # (2nd time)
t POST libpod/pods/foo/stop '' 304
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index 786c976d6..fffd7b085 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -41,6 +41,9 @@ echo 0 >$failures_file
# Where the tests live
TESTS_DIR=$(realpath $(dirname $0))
+# Path to podman binary
+PODMAN_BIN=${PODMAN:-${TESTS_DIR}/../../bin/podman}
+
# END setup
###############################################################################
# BEGIN infrastructure code - the helper functions used in tests themselves
@@ -97,7 +100,7 @@ function _show_ok() {
local green=
local reset=
local bold=
- if [ -t 3 ]; then
+ if [ -t 1 ]; then
red='\e[31m'
green='\e[32m'
reset='\e[0m'
@@ -107,16 +110,16 @@ function _show_ok() {
_bump $testcounter_file
count=$(<$testcounter_file)
if [ $ok -eq 1 ]; then
- echo -e "${green}ok $count $testname${reset}" >&3
+ echo -e "${green}ok $count $testname${reset}"
return
fi
# Failed
local expect=$3
local actual=$4
- echo -e "${red}not ok $count $testname${reset}" >&3
- echo -e "${red}# expected: $expect${reset}" >&3
- echo -e "${red}# actual: ${bold}$actual${reset}" >&3
+ echo -e "${red}not ok $count $testname${reset}"
+ echo -e "${red}# expected: $expect${reset}"
+ echo -e "${red}# actual: ${bold}$actual${reset}"
_bump $failures_file
}
@@ -201,17 +204,28 @@ function t() {
output=$(< $WORKDIR/curl.result.out)
+ # Special case: 204/304, by definition, MUST NOT return content (rfc2616)
+ if [[ $expected_code = 204 || $expected_code = 304 ]]; then
+ if [ -n "$*" ]; then
+ die "Internal error: ${expected_code} status returns no output; fix your test."
+ fi
+ if [ -n "$output" ]; then
+ _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output"
+ fi
+ return
+ fi
+
for i; do
case "$i" in
# Exact match on json field
- .*=*)
+ *=*)
json_field=$(expr "$i" : "\([^=]*\)=")
expect=$(expr "$i" : '[^=]*=\(.*\)')
actual=$(jq -r "$json_field" <<<"$output")
is "$actual" "$expect" "$testname : $json_field"
;;
# regex match on json field
- .*~*)
+ *~*)
json_field=$(expr "$i" : "\([^~]*\)~")
expect=$(expr "$i" : '[^~]*~\(.*\)')
actual=$(jq -r "$json_field" <<<"$output")
@@ -231,35 +245,51 @@ function t() {
service_pid=
function start_service() {
# If there's a listener on the port, nothing for us to do
- echo -n >/dev/tcp/$HOST/$PORT &>/dev/null && return
+ { exec 3<> /dev/tcp/$HOST/$PORT; } &>/dev/null && return
+
+ test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN"
if [ "$HOST" != "localhost" ]; then
die "Cannot start service on non-localhost ($HOST)"
fi
- if [ $(id -u) -ne 0 ]; then
- echo "$ME: WARNING: running service rootless is unlikely to work!" >&2
- fi
-
- # Find the binary
- SERVICE_BIN=${SERVICE_BIN:-${TESTS_DIR}/../../bin/service}
- test -x $SERVICE_BIN || die "Not found: $SERVICE_BIN"
-
- systemd-socket-activate -l 127.0.0.1:$PORT \
- $SERVICE_BIN --root $WORKDIR/root \
+ $PODMAN_BIN --root $WORKDIR system service --timeout 15000 tcp:127.0.0.1:$PORT \
&> $WORKDIR/server.log &
service_pid=$!
# Wait
local _timeout=5
while [ $_timeout -gt 0 ]; do
- echo -n >/dev/tcp/$HOST/$PORT &>/dev/null && return
+ { exec 3<> /dev/tcp/$HOST/$PORT; } &>/dev/null && return
sleep 1
_timeout=$(( $_timeout - 1 ))
done
die "Timed out waiting for service"
}
+############
+# podman # Needed by some test scripts to invoke the actual podman binary
+############
+function podman() {
+ echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log
+ $PODMAN_BIN --root $WORKDIR "$@" >>$WORKDIR/output.log 2>&1
+}
+
+####################
+# root, rootless # Is server rootless?
+####################
+ROOTLESS=
+function root() {
+ ! rootless
+}
+
+function rootless() {
+ if [[ -z $ROOTLESS ]]; then
+ ROOTLESS=$(curl -s http://$HOST:$PORT/v1.40/info | jq .Rootless)
+ fi
+ test "$ROOTLESS" = "true"
+}
+
# END infrastructure code
###############################################################################
# BEGIN sanity checks
@@ -288,10 +318,6 @@ else
tests_to_run=($TESTS_DIR/*.at)
fi
-# Because subtests may run podman or other commands that emit stderr;
-# redirect all those and use fd 3 for all output
-exec 3>&1 &>$WORKDIR/output.log
-
start_service
for i in ${tests_to_run[@]}; do
@@ -304,22 +330,17 @@ done
# Clean up
if [ -n "$service_pid" ]; then
- # Yep, has to be -9. It ignores everything else.
- kill -9 $service_pid
+ kill $service_pid
+ wait -f $service_pid
fi
test_count=$(<$testcounter_file)
failure_count=$(<$failures_file)
-if [ $failure_count -gt 0 -a -s "$WORKDIR/output.log" ]; then
- echo "# Collected stdout/stderr:" >&3
- sed -e 's/^/# /' < $WORKDIR/output.log >&3
-fi
-
if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then
rm -rf $WORKDIR
fi
-echo "1..${test_count}" >&3
+echo "1..${test_count}"
exit $failure_count
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 71f5d1b02..b4e400549 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -3,7 +3,9 @@
package integration
import (
+ "io/ioutil"
"os"
+ "path/filepath"
"strings"
. "github.com/containers/libpod/test/utils"
@@ -105,4 +107,39 @@ var _ = Describe("Podman build", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
+
+ It("podman build Containerfile locations", func() {
+ // Given
+ // Switch to temp dir and restore it afterwards
+ cwd, err := os.Getwd()
+ Expect(err).To(BeNil())
+ Expect(os.Chdir(os.TempDir())).To(BeNil())
+ defer Expect(os.Chdir(cwd)).To(BeNil())
+
+ // Write target and fake files
+ targetPath := filepath.Join(os.TempDir(), "dir")
+ Expect(os.MkdirAll(targetPath, 0755)).To(BeNil())
+
+ fakeFile := filepath.Join(os.TempDir(), "Containerfile")
+ Expect(ioutil.WriteFile(fakeFile, []byte("FROM alpine"), 0755)).To(BeNil())
+
+ targetFile := filepath.Join(targetPath, "Containerfile")
+ Expect(ioutil.WriteFile(targetFile, []byte("FROM scratch"), 0755)).To(BeNil())
+
+ defer func() {
+ Expect(os.RemoveAll(fakeFile)).To(BeNil())
+ Expect(os.RemoveAll(targetFile)).To(BeNil())
+ }()
+
+ // When
+ session := podmanTest.PodmanNoCache([]string{
+ "build", "-f", targetFile, "-t", "test-locations",
+ })
+ session.WaitWithDefaultTimeout()
+
+ // Then
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(strings.Fields(session.OutputToString())).
+ To(ContainElement("scratch"))
+ })
})
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index e9d274649..d4503d5a8 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -115,6 +115,25 @@ var _ = Describe("Podman commit", func() {
Expect(foundBlue).To(Equal(true))
})
+ It("podman commit container with change flag and JSON entrypoint with =", func() {
+ test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"})
+ test.WaitWithDefaultTimeout()
+ Expect(test.ExitCode()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(1))
+
+ session := podmanTest.Podman([]string{"commit", "--change", `ENTRYPOINT ["foo", "bar=baz"]`, "test1", "foobar.com/test1-image:latest"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"})
+ check.WaitWithDefaultTimeout()
+ data := check.InspectImageJSON()
+ Expect(len(data)).To(Equal(1))
+ Expect(len(data[0].Config.Entrypoint)).To(Equal(2))
+ Expect(data[0].Config.Entrypoint[0]).To(Equal("foo"))
+ Expect(data[0].Config.Entrypoint[1]).To(Equal("bar=baz"))
+ })
+
It("podman commit container with change CMD flag", func() {
test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"})
test.WaitWithDefaultTimeout()
diff --git a/test/e2e/config.go b/test/e2e/config.go
index 96cc157be..95b0481b3 100644
--- a/test/e2e/config.go
+++ b/test/e2e/config.go
@@ -2,7 +2,7 @@ package integration
var (
redis = "docker.io/library/redis:alpine"
- fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest"
+ fedoraMinimal = "quay.io/libpod/fedora-minimal:latest"
ALPINE = "docker.io/library/alpine:latest"
ALPINELISTTAG = "docker.io/library/alpine:3.10.2"
ALPINELISTDIGEST = "docker.io/library/alpine@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb"
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index 9a67cc83a..8b6b679a5 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -116,7 +116,8 @@ var _ = Describe("Podman images", func() {
})
It("podman images in GO template format", func() {
- session := podmanTest.Podman([]string{"images", "--format={{.ID}}"})
+ formatStr := "{{.ID}}\t{{.Created}}\t{{.CreatedAt}}\t{{.CreatedSince}}\t{{.CreatedTime}}"
+ session := podmanTest.Podman([]string{"images", fmt.Sprintf("--format=%s", formatStr)})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
@@ -280,7 +281,7 @@ RUN apk update && apk add man
return session.OutputToStringArray()
}
- sortedArr := sortValueTest("created", 0, "CreatedTime")
+ sortedArr := sortValueTest("created", 0, "CreatedAt")
Expect(sort.SliceIsSorted(sortedArr, func(i, j int) bool { return sortedArr[i] > sortedArr[j] })).To(BeTrue())
sortedArr = sortValueTest("id", 0, "ID")
diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go
index 9ff358d26..9a2cee9e1 100644
--- a/test/e2e/load_test.go
+++ b/test/e2e/load_test.go
@@ -205,7 +205,7 @@ var _ = Describe("Podman load", func() {
podmanTest.RestoreArtifact(fedoraMinimal)
outfile := filepath.Join(podmanTest.TempDir, "load_test.tar.gz")
- setup := podmanTest.PodmanNoCache([]string{"tag", "fedora-minimal", "hello"})
+ setup := podmanTest.PodmanNoCache([]string{"tag", fedoraMinimal, "hello"})
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 8411e632a..9daf266b8 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -4,6 +4,7 @@ package integration
import (
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"text/template"
@@ -486,4 +487,46 @@ var _ = Describe("Podman generate kube", func() {
newBBinspect := inspect.InspectImageJSON()
Expect(oldBBinspect[0].Digest).To(Not(Equal(newBBinspect[0].Digest)))
})
+
+ It("podman play kube with image data", func() {
+ testyaml := `
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo_pod
+spec:
+ containers:
+ - image: demo
+ name: demo_kube
+`
+ pull := podmanTest.Podman([]string{"create", "--workdir", "/etc", "--name", "newBB", "--label", "key1=value1", "alpine"})
+
+ pull.WaitWithDefaultTimeout()
+ Expect(pull.ExitCode()).To(BeZero())
+
+ c := podmanTest.Podman([]string{"commit", "-c", "STOPSIGNAL=51", "newBB", "demo"})
+ c.WaitWithDefaultTimeout()
+ Expect(c.ExitCode()).To(Equal(0))
+
+ conffile := filepath.Join(podmanTest.TempDir, "kube.yaml")
+ tempdir, err = CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+
+ err := ioutil.WriteFile(conffile, []byte(testyaml), 0755)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", conffile})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", "demo_kube"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+
+ ctr := inspect.InspectContainerToJSON()
+ Expect(ctr[0].Config.WorkingDir).To(ContainSubstring("/etc"))
+ Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
+ Expect(ctr[0].Config.Labels["key1"]).To(ContainSubstring("value1"))
+ Expect(ctr[0].Config.StopSignal).To(Equal(uint(51)))
+ })
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index fccc5c93b..48dd186e2 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -243,6 +243,19 @@ var _ = Describe("Podman ps", func() {
Expect(psAll.OutputToString()).To(Equal(psFilter.OutputToString()))
})
+ It("podman filter without status does not find non-running", func() {
+ ctrName := "aContainerName"
+ ctr := podmanTest.Podman([]string{"create", "--name", ctrName, "-t", "-i", ALPINE, "ls", "/"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ psFilter := podmanTest.Podman([]string{"ps", "--no-trunc", "--quiet", "--format", "{{.Names}}", "--filter", fmt.Sprintf("name=%s", ctrName)})
+ psFilter.WaitWithDefaultTimeout()
+ Expect(psFilter.ExitCode()).To(Equal(0))
+
+ Expect(strings.Contains(psFilter.OutputToString(), ctrName)).To(BeFalse())
+ })
+
It("podman ps mutually exclusive flags", func() {
session := podmanTest.Podman([]string{"ps", "-aqs"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 72547ea00..3eb93b84a 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -999,4 +999,16 @@ USER mail`
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
})
+
+ It("podman run --device-cgroup-rule", func() {
+ SkipIfRemote()
+ SkipIfRootless()
+ deviceCgroupRule := "c 42:* rwm"
+ session := podmanTest.Podman([]string{"run", "--name", "test", "-d", "--device-cgroup-rule", deviceCgroupRule, ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"exec", "test", "mknod", "newDev", "c", "42", "1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
})
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 0c2389e40..46c27dc2e 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -397,4 +397,28 @@ var _ = Describe("Podman run with volumes", func() {
volMount.WaitWithDefaultTimeout()
Expect(volMount.ExitCode()).To(Not(Equal(0)))
})
+
+ It("Podman fix for CVE-2020-1726", func() {
+ volName := "testVol"
+ volCreate := podmanTest.Podman([]string{"volume", "create", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate.ExitCode()).To(Equal(0))
+
+ volPath := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{.Mountpoint}}", volName})
+ volPath.WaitWithDefaultTimeout()
+ Expect(volPath.ExitCode()).To(Equal(0))
+ path := volPath.OutputToString()
+
+ fileName := "thisIsATestFile"
+ file, err := os.Create(filepath.Join(path, fileName))
+ Expect(err).To(BeNil())
+ defer file.Close()
+
+ runLs := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "-v", fmt.Sprintf("%v:/etc/ssl", volName), ALPINE, "ls", "-1", "/etc/ssl"})
+ runLs.WaitWithDefaultTimeout()
+ Expect(runLs.ExitCode()).To(Equal(0))
+ outputArr := runLs.OutputToStringArray()
+ Expect(len(outputArr)).To(Equal(1))
+ Expect(strings.Contains(outputArr[0], fileName)).To(BeTrue())
+ })
})
diff --git a/test/endpoint/endpoint.go b/test/endpoint/endpoint.go
index 78aa957ab..f1634b6f0 100644
--- a/test/endpoint/endpoint.go
+++ b/test/endpoint/endpoint.go
@@ -29,7 +29,7 @@ var (
infra = "k8s.gcr.io/pause:3.1"
BB = "docker.io/library/busybox:latest"
redis = "docker.io/library/redis:alpine"
- fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest"
+ fedoraMinimal = "quay.io/libpod/fedora-minimal:latest"
)
type EndpointTestIntegration struct {
diff --git a/vendor/github.com/acarl005/stripansi/LICENSE b/vendor/github.com/acarl005/stripansi/LICENSE
new file mode 100644
index 000000000..00abe0dbf
--- /dev/null
+++ b/vendor/github.com/acarl005/stripansi/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Andrew Carlson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/acarl005/stripansi/README.md b/vendor/github.com/acarl005/stripansi/README.md
new file mode 100644
index 000000000..8bdb1f505
--- /dev/null
+++ b/vendor/github.com/acarl005/stripansi/README.md
@@ -0,0 +1,30 @@
+Strip ANSI
+==========
+
+This Go package removes ANSI escape codes from strings.
+
+Ideally, we would prevent these from appearing in any text we want to process.
+However, sometimes this can't be helped, and we need to be able to deal with that noise.
+This will use a regexp to remove those unwanted escape codes.
+
+
+## Install
+
+```sh
+$ go get -u github.com/acarl005/stripansi
+```
+
+## Usage
+
+```go
+import (
+ "fmt"
+ "github.com/acarl005/stripansi"
+)
+
+func main() {
+ msg := "\x1b[38;5;140m foo\x1b[0m bar"
+ cleanMsg := stripansi.Strip(msg)
+ fmt.Println(cleanMsg) // " foo bar"
+}
+```
diff --git a/vendor/github.com/acarl005/stripansi/stripansi.go b/vendor/github.com/acarl005/stripansi/stripansi.go
new file mode 100644
index 000000000..235732a78
--- /dev/null
+++ b/vendor/github.com/acarl005/stripansi/stripansi.go
@@ -0,0 +1,13 @@
+package stripansi
+
+import (
+ "regexp"
+)
+
+const ansi = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
+
+var re = regexp.MustCompile(ansi)
+
+func Strip(str string) string {
+ return re.ReplaceAllString(str, "")
+}
diff --git a/vendor/github.com/containers/image/v5/copy/copy.go b/vendor/github.com/containers/image/v5/copy/copy.go
index 29660b6b2..8432dbe32 100644
--- a/vendor/github.com/containers/image/v5/copy/copy.go
+++ b/vendor/github.com/containers/image/v5/copy/copy.go
@@ -380,6 +380,7 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
return nil, "", errors.Wrap(err, "Can not copy signatures")
}
}
+ canModifyManifestList := (len(sigs) == 0)
// Determine if we'll need to convert the manifest list to a different format.
forceListMIMEType := options.ForceManifestMIMEType
@@ -394,7 +395,6 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
return nil, "", errors.Wrapf(err, "Error determining manifest list type to write to destination")
}
if selectedListType != list.MIMEType() {
- canModifyManifestList := (len(sigs) == 0)
if !canModifyManifestList {
return nil, "", errors.Errorf("Error: manifest list must be converted to type %q to be written to destination, but that would invalidate signatures", selectedListType)
}
@@ -451,12 +451,6 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
return nil, "", errors.Wrapf(err, "Error updating manifest list")
}
- // Check if the updates meaningfully changed the list of images.
- listIsModified := false
- if !reflect.DeepEqual(list.Instances(), originalList.Instances()) {
- listIsModified = true
- }
-
// Perform the list conversion.
if selectedListType != list.MIMEType() {
list, err = list.ConvertToMIMEType(selectedListType)
@@ -465,12 +459,23 @@ func (c *copier) copyMultipleImages(ctx context.Context, policyContext *signatur
}
}
- // If we can't use the original value, but we have to change it, flag an error.
- if listIsModified {
- manifestList, err = list.Serialize()
- if err != nil {
- return nil, "", errors.Wrapf(err, "Error encoding updated manifest list (%q: %#v)", list.MIMEType(), list.Instances())
+ // Check if the updates or a type conversion meaningfully changed the list of images
+ // by serializing them both so that we can compare them.
+ updatedManifestList, err := list.Serialize()
+ if err != nil {
+ return nil, "", errors.Wrapf(err, "Error encoding updated manifest list (%q: %#v)", list.MIMEType(), list.Instances())
+ }
+ originalManifestList, err := originalList.Serialize()
+ if err != nil {
+ return nil, "", errors.Wrapf(err, "Error encoding original manifest list for comparison (%q: %#v)", originalList.MIMEType(), originalList.Instances())
+ }
+
+ // If we can't just use the original value, but we have to change it, flag an error.
+ if !bytes.Equal(updatedManifestList, originalManifestList) {
+ if !canModifyManifestList {
+ return nil, "", errors.Errorf("Error: manifest list must be converted to type %q to be written to destination, but that would invalidate signatures", selectedListType)
}
+ manifestList = updatedManifestList
logrus.Debugf("Manifest list has been updated")
}
@@ -709,7 +714,7 @@ func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.Syst
wantedOS = sys.OSChoice
}
if wantedOS != c.OS {
- return fmt.Errorf("Image operating system mismatch: image uses %q, expecting %q", c.OS, wantedOS)
+ logrus.Infof("Image operating system mismatch: image uses %q, expecting %q", c.OS, wantedOS)
}
wantedArch := runtime.GOARCH
@@ -717,7 +722,7 @@ func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.Syst
wantedArch = sys.ArchitectureChoice
}
if wantedArch != c.Architecture {
- return fmt.Errorf("Image architecture mismatch: image uses %q, expecting %q", c.Architecture, wantedArch)
+ logrus.Infof("Image architecture mismatch: image uses %q, expecting %q", c.Architecture, wantedArch)
}
}
return nil
diff --git a/vendor/github.com/containers/image/v5/copy/manifest.go b/vendor/github.com/containers/image/v5/copy/manifest.go
index bcf082df3..5a3cf06a4 100644
--- a/vendor/github.com/containers/image/v5/copy/manifest.go
+++ b/vendor/github.com/containers/image/v5/copy/manifest.go
@@ -127,14 +127,14 @@ func isMultiImage(ctx context.Context, img types.UnparsedImage) (bool, error) {
// forced value, and returns the MIME type to which we should convert the list
// of manifests, whether we are converting to it or using it unmodified.
func (c *copier) determineListConversion(currentListMIMEType string, destSupportedMIMETypes []string, forcedListMIMEType string) (string, error) {
- // If we're forcing it, we prefer the forced value over everything else.
- if forcedListMIMEType != "" {
- return forcedListMIMEType, nil
- }
// If there's no list of supported types, then anything we support is expected to be supported.
if len(destSupportedMIMETypes) == 0 {
destSupportedMIMETypes = manifest.SupportedListMIMETypes
}
+ // If we're forcing it, replace the list of supported types with the forced value.
+ if forcedListMIMEType != "" {
+ destSupportedMIMETypes = []string{forcedListMIMEType}
+ }
var selectedType string
for i := range destSupportedMIMETypes {
// The second priority is the first member of the list of acceptable types that is a list,
@@ -148,9 +148,15 @@ func (c *copier) determineListConversion(currentListMIMEType string, destSupport
selectedType = destSupportedMIMETypes[i]
}
}
+ logrus.Debugf("Manifest list has MIME type %s, ordered candidate list [%s]", currentListMIMEType, strings.Join(destSupportedMIMETypes, ", "))
if selectedType == "" {
return "", errors.Errorf("destination does not support any supported manifest list types (%v)", manifest.SupportedListMIMETypes)
}
+ if selectedType != currentListMIMEType {
+ logrus.Debugf("... will convert to %s", selectedType)
+ } else {
+ logrus.Debugf("... will use the original manifest list type")
+ }
// Done.
return selectedType, nil
}
diff --git a/vendor/github.com/containers/image/v5/directory/directory_dest.go b/vendor/github.com/containers/image/v5/directory/directory_dest.go
index caa7a207f..d70b6c07f 100644
--- a/vendor/github.com/containers/image/v5/directory/directory_dest.go
+++ b/vendor/github.com/containers/image/v5/directory/directory_dest.go
@@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "runtime"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
@@ -142,8 +143,11 @@ func (d *dirImageDestination) PutBlob(ctx context.Context, stream io.Reader, inp
return types.BlobInfo{}, err
}
succeeded := false
+ explicitClosed := false
defer func() {
- blobFile.Close()
+ if !explicitClosed {
+ blobFile.Close()
+ }
if !succeeded {
os.Remove(blobFile.Name())
}
@@ -164,10 +168,21 @@ func (d *dirImageDestination) PutBlob(ctx context.Context, stream io.Reader, inp
if err := blobFile.Sync(); err != nil {
return types.BlobInfo{}, err
}
- if err := blobFile.Chmod(0644); err != nil {
- return types.BlobInfo{}, err
+
+ // On POSIX systems, blobFile was created with mode 0600, so we need to make it readable.
+ // On Windows, the “permissions of newly created files” argument to syscall.Open is
+ // ignored and the file is already readable; besides, blobFile.Chmod, i.e. syscall.Fchmod,
+ // always fails on Windows.
+ if runtime.GOOS != "windows" {
+ if err := blobFile.Chmod(0644); err != nil {
+ return types.BlobInfo{}, err
+ }
}
+
blobPath := d.ref.layerPath(computedDigest)
+ // need to explicitly close the file, since a rename won't otherwise not work on Windows
+ blobFile.Close()
+ explicitClosed = true
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
return types.BlobInfo{}, err
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_client.go b/vendor/github.com/containers/image/v5/docker/docker_client.go
index 986bcb986..aa8463d18 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_client.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_client.go
@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/url"
"os"
@@ -17,6 +16,7 @@ import (
"time"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/pkg/docker/config"
"github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/image/v5/pkg/tlsclientconfig"
@@ -45,6 +45,10 @@ const (
extensionSignatureSchemaVersion = 2 // extensionSignature.Version
extensionSignatureTypeAtomic = "atomic" // extensionSignature.Type
+
+ backoffNumIterations = 5
+ backoffInitialDelay = 2 * time.Second
+ backoffMaxDelay = 60 * time.Second
)
var systemPerHostCertDirPaths = [2]string{"/etc/containers/certs.d", "/etc/docker/certs.d"}
@@ -277,7 +281,7 @@ func CheckAuth(ctx context.Context, sys *types.SystemContext, username, password
}
defer resp.Body.Close()
- return httpResponseToError(resp)
+ return httpResponseToError(resp, "")
}
// SearchResult holds the information of each matching image
@@ -351,7 +355,7 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
} else {
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
- logrus.Debugf("error getting search results from v1 endpoint %q: %v", registry, httpResponseToError(resp))
+ logrus.Debugf("error getting search results from v1 endpoint %q: %v", registry, httpResponseToError(resp, ""))
} else {
if err := json.NewDecoder(resp.Body).Decode(v1Res); err != nil {
return nil, err
@@ -368,7 +372,7 @@ func SearchRegistry(ctx context.Context, sys *types.SystemContext, registry, ima
} else {
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
- logrus.Errorf("error getting search results from v2 endpoint %q: %v", registry, httpResponseToError(resp))
+ logrus.Errorf("error getting search results from v2 endpoint %q: %v", registry, httpResponseToError(resp, ""))
} else {
if err := json.NewDecoder(resp.Body).Decode(v2Res); err != nil {
return nil, err
@@ -400,74 +404,64 @@ func (c *dockerClient) makeRequest(ctx context.Context, method, path string, hea
return c.makeRequestToResolvedURL(ctx, method, url, headers, stream, -1, auth, extraScope)
}
+// parseRetryAfter determines the delay required by the "Retry-After" header in res and returns it,
+// silently falling back to fallbackDelay if the header is missing or invalid.
+func parseRetryAfter(res *http.Response, fallbackDelay time.Duration) time.Duration {
+ after := res.Header.Get("Retry-After")
+ if after == "" {
+ return fallbackDelay
+ }
+ logrus.Debugf("Detected 'Retry-After' header %q", after)
+ // First, check if we have a numerical value.
+ if num, err := strconv.ParseInt(after, 10, 64); err == nil {
+ return time.Duration(num) * time.Second
+ }
+ // Second, check if we have an HTTP date.
+ // If the delta between the date and now is positive, use it.
+ // Otherwise, fall back to using the default exponential back off.
+ if t, err := http.ParseTime(after); err == nil {
+ delta := time.Until(t)
+ if delta > 0 {
+ return delta
+ }
+ logrus.Debugf("Retry-After date in the past, ignoring it")
+ return fallbackDelay
+ }
+ // If the header contents are bogus, fall back to using the default exponential back off.
+ logrus.Debugf("Invalid Retry-After format, ignoring it")
+ return fallbackDelay
+}
+
// makeRequestToResolvedURL creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
// streamLen, if not -1, specifies the length of the data expected on stream.
// makeRequest should generally be preferred.
-// In case of an http 429 status code in the response, it performs an exponential back off starting at 2 seconds for at most 5 iterations.
-// If the `Retry-After` header is set in the response, the specified value or date is
-// If the stream is non-nil, no back off will be performed.
+// In case of an HTTP 429 status code in the response, it may automatically retry a few times.
// TODO(runcom): too many arguments here, use a struct
func (c *dockerClient) makeRequestToResolvedURL(ctx context.Context, method, url string, headers map[string][]string, stream io.Reader, streamLen int64, auth sendAuth, extraScope *authScope) (*http.Response, error) {
- var (
- res *http.Response
- err error
- delay int64
- )
- delay = 2
- const numIterations = 5
- const maxDelay = 60
-
- // math.Min() only supports float64, so have an anonymous func to avoid
- // casting.
- min := func(a int64, b int64) int64 {
- if a < b {
- return a
+ delay := backoffInitialDelay
+ attempts := 0
+ for {
+ res, err := c.makeRequestToResolvedURLOnce(ctx, method, url, headers, stream, streamLen, auth, extraScope)
+ attempts++
+ if res == nil || res.StatusCode != http.StatusTooManyRequests || // Only retry on StatusTooManyRequests, success or other failure is returned to caller immediately
+ stream != nil || // We can't retry with a body (which is not restartable in the general case)
+ attempts == backoffNumIterations {
+ return res, err
}
- return b
- }
- nextDelay := func(r *http.Response, delay int64) int64 {
- after := res.Header.Get("Retry-After")
- if after == "" {
- return min(delay, maxDelay)
- }
- logrus.Debugf("detected 'Retry-After' header %q", after)
- // First check if we have a numerical value.
- if num, err := strconv.ParseInt(after, 10, 64); err == nil {
- return min(num, maxDelay)
+ delay = parseRetryAfter(res, delay)
+ if delay > backoffMaxDelay {
+ delay = backoffMaxDelay
}
- // Secondly check if we have an http date.
- // If the delta between the date and now is positive, use it.
- // Otherwise, fall back to using the default exponential back off.
- if t, err := http.ParseTime(after); err == nil {
- delta := int64(time.Until(t).Seconds())
- if delta > 0 {
- return min(delta, maxDelay)
- }
- logrus.Debugf("negative date: falling back to using %d seconds", delay)
- return min(delay, maxDelay)
+ logrus.Debugf("Too many requests to %s: sleeping for %f seconds before next attempt", url, delay.Seconds())
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-time.After(delay):
+ // Nothing
}
- // If the header contains bogus, fall back to using the default
- // exponential back off.
- logrus.Debugf("invalid format: falling back to using %d seconds", delay)
- return min(delay, maxDelay)
- }
-
- for i := 0; i < numIterations; i++ {
- res, err = c.makeRequestToResolvedURLOnce(ctx, method, url, headers, stream, streamLen, auth, extraScope)
- if stream == nil && res != nil && res.StatusCode == http.StatusTooManyRequests {
- if i < numIterations-1 {
- logrus.Errorf("HEADER %v", res.Header)
- delay = nextDelay(res, delay) // compute next delay - does NOT exceed maxDelay
- logrus.Debugf("too many request to %s: sleeping for %d seconds before next attempt", url, delay)
- time.Sleep(time.Duration(delay) * time.Second)
- delay = delay * 2 // exponential back off
- }
- continue
- }
- break
+ delay = delay * 2 // exponential back off
}
- return res, err
}
// makeRequestToResolvedURLOnce creates and executes a http.Request with the specified parameters, adding authentication and TLS options for the Docker client.
@@ -597,7 +591,7 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
default:
return nil, errors.Errorf("unexpected http code: %d (%s), URL: %s", res.StatusCode, http.StatusText(res.StatusCode), authReq.URL)
}
- tokenBlob, err := ioutil.ReadAll(res.Body)
+ tokenBlob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxAuthTokenBodySize)
if err != nil {
return nil, err
}
@@ -627,7 +621,7 @@ func (c *dockerClient) detectPropertiesHelper(ctx context.Context) error {
defer resp.Body.Close()
logrus.Debugf("Ping %s status %d", url, resp.StatusCode)
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusUnauthorized {
- return httpResponseToError(resp)
+ return httpResponseToError(resp, "")
}
c.challenges = parseAuthHeader(resp.Header)
c.scheme = scheme
@@ -690,7 +684,7 @@ func (c *dockerClient) getExtensionsSignatures(ctx context.Context, ref dockerRe
return nil, errors.Wrapf(clientLib.HandleErrorResponse(res), "Error downloading signatures for %s in %s", manifestDigest, ref.ref.Name())
}
- body, err := ioutil.ReadAll(res.Body)
+ body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureListBodySize)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image.go b/vendor/github.com/containers/image/v5/docker/docker_image.go
index dad382cd0..483581dbc 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image.go
@@ -70,7 +70,7 @@ func GetRepositoryTags(ctx context.Context, sys *types.SystemContext, ref types.
return nil, err
}
defer res.Body.Close()
- if err := httpResponseToError(res); err != nil {
+ if err := httpResponseToError(res, "Error fetching tags list"); err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
index 47a73d868..ab74e1607 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_dest.go
@@ -15,6 +15,7 @@ import (
"strings"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/blobinfocache/none"
"github.com/containers/image/v5/types"
@@ -58,14 +59,16 @@ func (d *dockerImageDestination) Close() error {
}
func (d *dockerImageDestination) SupportedManifestMIMETypes() []string {
- return []string{
+ mimeTypes := []string{
imgspecv1.MediaTypeImageManifest,
manifest.DockerV2Schema2MediaType,
imgspecv1.MediaTypeImageIndex,
manifest.DockerV2ListMediaType,
- manifest.DockerV2Schema1SignedMediaType,
- manifest.DockerV2Schema1MediaType,
}
+ if d.c.sys == nil || !d.c.sys.DockerDisableDestSchema1MIMETypes {
+ mimeTypes = append(mimeTypes, manifest.DockerV2Schema1SignedMediaType, manifest.DockerV2Schema1MediaType)
+ }
+ return mimeTypes
}
// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
@@ -620,7 +623,7 @@ sigExists:
}
defer res.Body.Close()
if res.StatusCode != http.StatusCreated {
- body, err := ioutil.ReadAll(res.Body)
+ body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxErrorBodySize)
if err == nil {
logrus.Debugf("Error body %s", string(body))
}
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image_src.go b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
index 35beb30e5..967845e72 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image_src.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image_src.go
@@ -10,8 +10,10 @@ import (
"net/url"
"os"
"strconv"
+ "strings"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/sysregistriesv2"
"github.com/containers/image/v5/types"
@@ -53,43 +55,77 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
// 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")
pullSources, err := registry.PullSourcesFromReference(ref.ref)
if err != nil {
return nil, err
}
+ type attempt struct {
+ ref reference.Named
+ err error
+ }
+ attempts := []attempt{}
for _, pullSource := range pullSources {
- logrus.Debugf("Trying to pull %q", pullSource.Reference)
- dockerRef, err := newReference(pullSource.Reference)
- if err != nil {
- return nil, err
+ logrus.Debugf("Trying to access %q", pullSource.Reference)
+ s, err := newImageSourceAttempt(ctx, sys, pullSource, primaryDomain)
+ if err == nil {
+ return s, nil
}
-
- endpointSys := sys
- // sys.DockerAuthConfig does not explicitly specify a registry; we must not blindly send the credentials intended for the primary endpoint to mirrors.
- if endpointSys != nil && endpointSys.DockerAuthConfig != nil && reference.Domain(dockerRef.ref) != primaryDomain {
- copy := *endpointSys
- copy.DockerAuthConfig = nil
- endpointSys = &copy
+ logrus.Debugf("Accessing %q failed: %v", pullSource.Reference, err)
+ attempts = append(attempts, attempt{
+ ref: pullSource.Reference,
+ err: err,
+ })
+ }
+ switch len(attempts) {
+ case 0:
+ return nil, errors.New("Internal error: newImageSource returned without trying any endpoint")
+ case 1:
+ return nil, attempts[0].err // If no mirrors are used, perfectly preserve the error type and add no noise.
+ default:
+ // Don’t just build a string, try to preserve the typed error.
+ primary := &attempts[len(attempts)-1]
+ extras := []string{}
+ for i := 0; i < len(attempts)-1; i++ {
+ // This is difficult to fit into a single-line string, when the error can contain arbitrary strings including any metacharacters we decide to use.
+ // The paired [] at least have some chance of being unambiguous.
+ extras = append(extras, fmt.Sprintf("[%s: %v]", attempts[i].ref.String(), attempts[i].err))
}
+ return nil, errors.Wrapf(primary.err, "(Mirrors also failed: %s): %s", strings.Join(extras, "\n"), primary.ref.String())
+ }
+}
- client, err := newDockerClientFromRef(endpointSys, dockerRef, false, "pull")
- if err != nil {
- return nil, err
- }
- client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
+// newImageSourceAttempt is an internal helper for newImageSource. Everyone else must call newImageSource.
+// Given a pullSource and primaryDomain, return a dockerImageSource if it is reachable.
+// The caller must call .Close() on the returned ImageSource.
+func newImageSourceAttempt(ctx context.Context, sys *types.SystemContext, pullSource sysregistriesv2.PullSource, primaryDomain string) (*dockerImageSource, error) {
+ ref, err := newReference(pullSource.Reference)
+ if err != nil {
+ return nil, err
+ }
- testImageSource := &dockerImageSource{
- ref: dockerRef,
- c: client,
- }
+ endpointSys := sys
+ // sys.DockerAuthConfig does not explicitly specify a registry; we must not blindly send the credentials intended for the primary endpoint to mirrors.
+ if endpointSys != nil && endpointSys.DockerAuthConfig != nil && reference.Domain(ref.ref) != primaryDomain {
+ copy := *endpointSys
+ copy.DockerAuthConfig = nil
+ endpointSys = &copy
+ }
- manifestLoadErr = testImageSource.ensureManifestIsLoaded(ctx)
- if manifestLoadErr == nil {
- return testImageSource, nil
- }
+ client, err := newDockerClientFromRef(endpointSys, ref, false, "pull")
+ if err != nil {
+ return nil, err
}
- return nil, manifestLoadErr
+ client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
+
+ s := &dockerImageSource{
+ ref: ref,
+ c: client,
+ }
+
+ if err := s.ensureManifestIsLoaded(ctx); err != nil {
+ return nil, err
+ }
+ return s, nil
}
// Reference returns the reference used to set up this source, _as specified by the user_
@@ -156,7 +192,8 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin
if res.StatusCode != http.StatusOK {
return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.ref.ref.Name())
}
- manblob, err := ioutil.ReadAll(res.Body)
+
+ manblob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxManifestBodySize)
if err != nil {
return nil, "", err
}
@@ -239,7 +276,7 @@ func (s *dockerImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
if err != nil {
return nil, 0, err
}
- if err := httpResponseToError(res); err != nil {
+ if err := httpResponseToError(res, "Error fetching blob"); err != nil {
return nil, 0, err
}
cache.RecordKnownLocation(s.ref.Transport(), bicTransportScope(s.ref), info.Digest, newBICLocationReference(s.ref))
@@ -342,7 +379,7 @@ func (s *dockerImageSource) getOneSignature(ctx context.Context, url *url.URL) (
} else if res.StatusCode != http.StatusOK {
return nil, false, errors.Errorf("Error reading signature from %s: status %d (%s)", url.String(), res.StatusCode, http.StatusText(res.StatusCode))
}
- sig, err := ioutil.ReadAll(res.Body)
+ sig, err := iolimits.ReadAtMost(res.Body, iolimits.MaxSignatureBodySize)
if err != nil {
return nil, false, err
}
@@ -401,7 +438,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
return err
}
defer get.Body.Close()
- manifestBody, err := ioutil.ReadAll(get.Body)
+ manifestBody, err := iolimits.ReadAtMost(get.Body, iolimits.MaxManifestBodySize)
if err != nil {
return err
}
@@ -424,7 +461,7 @@ func deleteImage(ctx context.Context, sys *types.SystemContext, ref dockerRefere
}
defer delete.Body.Close()
- body, err := ioutil.ReadAll(delete.Body)
+ body, err := iolimits.ReadAtMost(delete.Body, iolimits.MaxErrorBodySize)
if err != nil {
return err
}
diff --git a/vendor/github.com/containers/image/v5/docker/errors.go b/vendor/github.com/containers/image/v5/docker/errors.go
index 860868f41..f626cc7da 100644
--- a/vendor/github.com/containers/image/v5/docker/errors.go
+++ b/vendor/github.com/containers/image/v5/docker/errors.go
@@ -14,7 +14,7 @@ var (
// docker V1 registry.
ErrV1NotSupported = errors.New("can't talk to a V1 docker registry")
// ErrTooManyRequests is returned when the status code returned is 429
- ErrTooManyRequests = errors.New("too many request to registry")
+ ErrTooManyRequests = errors.New("too many requests to registry")
)
// ErrUnauthorizedForCredentials is returned when the status code returned is 401
@@ -26,9 +26,9 @@ func (e ErrUnauthorizedForCredentials) Error() string {
return fmt.Sprintf("unable to retrieve auth token: invalid username/password: %s", e.Err.Error())
}
-// httpResponseToError translates the https.Response into an error. It returns
+// httpResponseToError translates the https.Response into an error, possibly prefixing it with the supplied context. It returns
// nil if the response is not considered an error.
-func httpResponseToError(res *http.Response) error {
+func httpResponseToError(res *http.Response, context string) error {
switch res.StatusCode {
case http.StatusOK:
return nil
@@ -38,6 +38,9 @@ func httpResponseToError(res *http.Response) error {
err := client.HandleErrorResponse(res)
return ErrUnauthorizedForCredentials{Err: err}
default:
- return perrors.Errorf("invalid status code from registry %d (%s)", res.StatusCode, http.StatusText(res.StatusCode))
+ if context != "" {
+ context = context + ": "
+ }
+ return perrors.Errorf("%sinvalid status code from registry %d (%s)", context, res.StatusCode, http.StatusText(res.StatusCode))
}
}
diff --git a/vendor/github.com/containers/image/v5/docker/tarfile/dest.go b/vendor/github.com/containers/image/v5/docker/tarfile/dest.go
index c322156b5..c171da505 100644
--- a/vendor/github.com/containers/image/v5/docker/tarfile/dest.go
+++ b/vendor/github.com/containers/image/v5/docker/tarfile/dest.go
@@ -13,6 +13,7 @@ import (
"time"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/internal/tmpdir"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
@@ -143,7 +144,7 @@ func (d *Destination) PutBlob(ctx context.Context, stream io.Reader, inputInfo t
}
if isConfig {
- buf, err := ioutil.ReadAll(stream)
+ buf, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
if err != nil {
return types.BlobInfo{}, errors.Wrap(err, "Error reading Config file stream")
}
diff --git a/vendor/github.com/containers/image/v5/docker/tarfile/src.go b/vendor/github.com/containers/image/v5/docker/tarfile/src.go
index 80dd753e4..c1f1a0f27 100644
--- a/vendor/github.com/containers/image/v5/docker/tarfile/src.go
+++ b/vendor/github.com/containers/image/v5/docker/tarfile/src.go
@@ -11,6 +11,7 @@ import (
"path"
"sync"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/internal/tmpdir"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/compression"
@@ -203,13 +204,13 @@ func findTarComponent(inputFile io.Reader, path string) (*tar.Reader, *tar.Heade
}
// readTarComponent returns full contents of componentPath.
-func (s *Source) readTarComponent(path string) ([]byte, error) {
+func (s *Source) readTarComponent(path string, limit int) ([]byte, error) {
file, err := s.openTarComponent(path)
if err != nil {
return nil, errors.Wrapf(err, "Error loading tar component %s", path)
}
defer file.Close()
- bytes, err := ioutil.ReadAll(file)
+ bytes, err := iolimits.ReadAtMost(file, limit)
if err != nil {
return nil, err
}
@@ -240,7 +241,7 @@ func (s *Source) ensureCachedDataIsPresentPrivate() error {
}
// Read and parse config.
- configBytes, err := s.readTarComponent(tarManifest[0].Config)
+ configBytes, err := s.readTarComponent(tarManifest[0].Config, iolimits.MaxConfigBodySize)
if err != nil {
return err
}
@@ -266,7 +267,7 @@ func (s *Source) ensureCachedDataIsPresentPrivate() error {
// loadTarManifest loads and decodes the manifest.json.
func (s *Source) loadTarManifest() ([]ManifestItem, error) {
// FIXME? Do we need to deal with the legacy format?
- bytes, err := s.readTarComponent(manifestFileName)
+ bytes, err := s.readTarComponent(manifestFileName, iolimits.MaxTarFileManifestSize)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/v5/image/docker_schema2.go b/vendor/github.com/containers/image/v5/image/docker_schema2.go
index 7891562b7..1e2114d7e 100644
--- a/vendor/github.com/containers/image/v5/image/docker_schema2.go
+++ b/vendor/github.com/containers/image/v5/image/docker_schema2.go
@@ -7,10 +7,10 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
- "io/ioutil"
"strings"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/blobinfocache/none"
"github.com/containers/image/v5/types"
@@ -102,7 +102,7 @@ func (m *manifestSchema2) ConfigBlob(ctx context.Context) ([]byte, error) {
return nil, err
}
defer stream.Close()
- blob, err := ioutil.ReadAll(stream)
+ blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/v5/image/oci.go b/vendor/github.com/containers/image/v5/image/oci.go
index 059d84977..b5ddb9aaa 100644
--- a/vendor/github.com/containers/image/v5/image/oci.go
+++ b/vendor/github.com/containers/image/v5/image/oci.go
@@ -4,9 +4,9 @@ import (
"context"
"encoding/json"
"fmt"
- "io/ioutil"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/blobinfocache/none"
"github.com/containers/image/v5/types"
@@ -67,7 +67,7 @@ func (m *manifestOCI1) ConfigBlob(ctx context.Context) ([]byte, error) {
return nil, err
}
defer stream.Close()
- blob, err := ioutil.ReadAll(stream)
+ blob, err := iolimits.ReadAtMost(stream, iolimits.MaxConfigBodySize)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go b/vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go
new file mode 100644
index 000000000..3fed1995c
--- /dev/null
+++ b/vendor/github.com/containers/image/v5/internal/iolimits/iolimits.go
@@ -0,0 +1,60 @@
+package iolimits
+
+import (
+ "io"
+ "io/ioutil"
+
+ "github.com/pkg/errors"
+)
+
+// All constants below are intended to be used as limits for `ReadAtMost`. The
+// immediate use-case for limiting the size of in-memory copied data is to
+// protect against OOM DOS attacks as described inCVE-2020-1702. Instead of
+// copying data until running out of memory, we error out after hitting the
+// specified limit.
+const (
+ // megaByte denotes one megabyte and is intended to be used as a limit in
+ // `ReadAtMost`.
+ megaByte = 1 << 20
+ // MaxManifestBodySize is the maximum allowed size of a manifest. The limit
+ // of 4 MB aligns with the one of a Docker registry:
+ // https://github.com/docker/distribution/blob/a8371794149d1d95f1e846744b05c87f2f825e5a/registry/handlers/manifests.go#L30
+ MaxManifestBodySize = 4 * megaByte
+ // MaxAuthTokenBodySize is the maximum allowed size of an auth token.
+ // The limit of 1 MB is considered to be greatly sufficient.
+ MaxAuthTokenBodySize = megaByte
+ // MaxSignatureListBodySize is the maximum allowed size of a signature list.
+ // The limit of 4 MB is considered to be greatly sufficient.
+ MaxSignatureListBodySize = 4 * megaByte
+ // MaxSignatureBodySize is the maximum allowed size of a signature.
+ // The limit of 4 MB is considered to be greatly sufficient.
+ MaxSignatureBodySize = 4 * megaByte
+ // MaxErrorBodySize is the maximum allowed size of an error-response body.
+ // The limit of 1 MB is considered to be greatly sufficient.
+ MaxErrorBodySize = megaByte
+ // MaxConfigBodySize is the maximum allowed size of a config blob.
+ // The limit of 4 MB is considered to be greatly sufficient.
+ MaxConfigBodySize = 4 * megaByte
+ // MaxOpenShiftStatusBody is the maximum allowed size of an OpenShift status body.
+ // The limit of 4 MB is considered to be greatly sufficient.
+ MaxOpenShiftStatusBody = 4 * megaByte
+ // MaxTarFileManifestSize is the maximum allowed size of a (docker save)-like manifest (which may contain multiple images)
+ // The limit of 1 MB is considered to be greatly sufficient.
+ MaxTarFileManifestSize = megaByte
+)
+
+// ReadAtMost reads from reader and errors out if the specified limit (in bytes) is exceeded.
+func ReadAtMost(reader io.Reader, limit int) ([]byte, error) {
+ limitedReader := io.LimitReader(reader, int64(limit+1))
+
+ res, err := ioutil.ReadAll(limitedReader)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(res) > limit {
+ return nil, errors.Errorf("exceeded maximum allowed size of %d bytes", limit)
+ }
+
+ return res, nil
+}
diff --git a/vendor/github.com/containers/image/v5/openshift/openshift.go b/vendor/github.com/containers/image/v5/openshift/openshift.go
index b9242da6e..28bfc456d 100644
--- a/vendor/github.com/containers/image/v5/openshift/openshift.go
+++ b/vendor/github.com/containers/image/v5/openshift/openshift.go
@@ -7,13 +7,13 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
"github.com/containers/image/v5/version"
@@ -102,7 +102,7 @@ func (c *openshiftClient) doRequest(ctx context.Context, method, path string, re
return nil, err
}
defer res.Body.Close()
- body, err := ioutil.ReadAll(res.Body)
+ body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxOpenShiftStatusBody)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
index 4825ab27c..277fba16b 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_gpgme.go
@@ -139,7 +139,7 @@ func (m *gpgmeSigningMechanism) Sign(input []byte, keyIdentity string) ([]byte,
}
// Verify parses unverifiedSignature and returns the content and the signer's identity
-func (m gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) {
+func (m *gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []byte, keyIdentity string, err error) {
signedBuffer := bytes.Buffer{}
signedData, err := gpgme.NewDataWriter(&signedBuffer)
if err != nil {
@@ -170,6 +170,6 @@ func (m gpgmeSigningMechanism) Verify(unverifiedSignature []byte) (contents []by
// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys)
// is NOT the same as a "key identity" used in other calls ot this interface, and
// the values may have no recognizable relationship if the public key is not available.
-func (m gpgmeSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
+func (m *gpgmeSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
return gpgUntrustedSignatureContents(untrustedSignature)
}
diff --git a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
index eccd610c9..51f20f310 100644
--- a/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
+++ b/vendor/github.com/containers/image/v5/signature/mechanism_openpgp.go
@@ -154,6 +154,6 @@ func (m *openpgpSigningMechanism) Verify(unverifiedSignature []byte) (contents [
// WARNING: The short key identifier (which correponds to "Key ID" for OpenPGP keys)
// is NOT the same as a "key identity" used in other calls ot this interface, and
// the values may have no recognizable relationship if the public key is not available.
-func (m openpgpSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
+func (m *openpgpSigningMechanism) UntrustedSignatureContents(untrustedSignature []byte) (untrustedContents []byte, shortKeyIdentifier string, err error) {
return gpgUntrustedSignatureContents(untrustedSignature)
}
diff --git a/vendor/github.com/containers/image/v5/types/types.go b/vendor/github.com/containers/image/v5/types/types.go
index d38a17fab..ba249ca25 100644
--- a/vendor/github.com/containers/image/v5/types/types.go
+++ b/vendor/github.com/containers/image/v5/types/types.go
@@ -547,6 +547,8 @@ type SystemContext struct {
// Note that this field is used mainly to integrate containers/image into projectatomic/docker
// in order to not break any existing docker's integration tests.
DockerDisableV1Ping bool
+ // If true, dockerImageDestination.SupportedManifestMIMETypes will omit the Schema1 media types from the supported list
+ DockerDisableDestSchema1MIMETypes bool
// Directory to use for OSTree temporary files
OSTreeTmpDirPath string
diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go
index a92774466..0fd7a4a37 100644
--- a/vendor/github.com/containers/image/v5/version/version.go
+++ b/vendor/github.com/containers/image/v5/version/version.go
@@ -6,9 +6,9 @@ const (
// VersionMajor is for an API incompatible changes
VersionMajor = 5
// VersionMinor is for functionality in a backwards-compatible manner
- VersionMinor = 1
+ VersionMinor = 2
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 0
+ VersionPatch = 1
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = ""
diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md
index 92e422eed..35eea9f10 100644
--- a/vendor/github.com/gorilla/mux/README.md
+++ b/vendor/github.com/gorilla/mux/README.md
@@ -1,11 +1,10 @@
# gorilla/mux
[![GoDoc](https://godoc.org/github.com/gorilla/mux?status.svg)](https://godoc.org/github.com/gorilla/mux)
-[![Build Status](https://travis-ci.org/gorilla/mux.svg?branch=master)](https://travis-ci.org/gorilla/mux)
[![CircleCI](https://circleci.com/gh/gorilla/mux.svg?style=svg)](https://circleci.com/gh/gorilla/mux)
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/mux/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/mux?badge)
-![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png)
+![Gorilla Logo](https://cloud-cdn.questionable.services/gorilla-icon-64.png)
https://www.gorillatoolkit.org/pkg/mux
@@ -26,6 +25,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv
* [Examples](#examples)
* [Matching Routes](#matching-routes)
* [Static Files](#static-files)
+* [Serving Single Page Applications](#serving-single-page-applications) (e.g. React, Vue, Ember.js, etc.)
* [Registered URLs](#registered-urls)
* [Walking Routes](#walking-routes)
* [Graceful Shutdown](#graceful-shutdown)
@@ -212,6 +212,93 @@ func main() {
}
```
+### Serving Single Page Applications
+
+Most of the time it makes sense to serve your SPA on a separate web server from your API,
+but sometimes it's desirable to serve them both from one place. It's possible to write a simple
+handler for serving your SPA (for use with React Router's [BrowserRouter](https://reacttraining.com/react-router/web/api/BrowserRouter) for example), and leverage
+mux's powerful routing for your API endpoints.
+
+```go
+package main
+
+import (
+ "encoding/json"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/gorilla/mux"
+)
+
+// spaHandler implements the http.Handler interface, so we can use it
+// to respond to HTTP requests. The path to the static directory and
+// path to the index file within that static directory are used to
+// serve the SPA in the given static directory.
+type spaHandler struct {
+ staticPath string
+ indexPath string
+}
+
+// ServeHTTP inspects the URL path to locate a file within the static dir
+// on the SPA handler. If a file is found, it will be served. If not, the
+// file located at the index path on the SPA handler will be served. This
+// is suitable behavior for serving an SPA (single page application).
+func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // get the absolute path to prevent directory traversal
+ path, err := filepath.Abs(r.URL.Path)
+ if err != nil {
+ // if we failed to get the absolute path respond with a 400 bad request
+ // and stop
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ // prepend the path with the path to the static directory
+ path = filepath.Join(h.staticPath, path)
+
+ // check whether a file exists at the given path
+ _, err = os.Stat(path)
+ if os.IsNotExist(err) {
+ // file does not exist, serve index.html
+ http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
+ return
+ } else if err != nil {
+ // if we got an error (that wasn't that the file doesn't exist) stating the
+ // file, return a 500 internal server error and stop
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // otherwise, use http.FileServer to serve the static dir
+ http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
+}
+
+func main() {
+ router := mux.NewRouter()
+
+ router.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) {
+ // an example API handler
+ json.NewEncoder(w).Encode(map[string]bool{"ok": true})
+ })
+
+ spa := spaHandler{staticPath: "build", indexPath: "index.html"}
+ router.PathPrefix("/").Handler(spa)
+
+ srv := &http.Server{
+ Handler: router,
+ Addr: "127.0.0.1:8000",
+ // Good practice: enforce timeouts for servers you create!
+ WriteTimeout: 15 * time.Second,
+ ReadTimeout: 15 * time.Second,
+ }
+
+ log.Fatal(srv.ListenAndServe())
+}
+```
+
### Registered URLs
Now let's see how to build registered URLs.
diff --git a/vendor/github.com/gorilla/mux/context.go b/vendor/github.com/gorilla/mux/context.go
deleted file mode 100644
index 665940a26..000000000
--- a/vendor/github.com/gorilla/mux/context.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package mux
-
-import (
- "context"
- "net/http"
-)
-
-func contextGet(r *http.Request, key interface{}) interface{} {
- return r.Context().Value(key)
-}
-
-func contextSet(r *http.Request, key, val interface{}) *http.Request {
- if val == nil {
- return r
- }
-
- return r.WithContext(context.WithValue(r.Context(), key, val))
-}
diff --git a/vendor/github.com/gorilla/mux/go.mod b/vendor/github.com/gorilla/mux/go.mod
index cfc8ede58..df170a399 100644
--- a/vendor/github.com/gorilla/mux/go.mod
+++ b/vendor/github.com/gorilla/mux/go.mod
@@ -1 +1,3 @@
module github.com/gorilla/mux
+
+go 1.12
diff --git a/vendor/github.com/gorilla/mux/middleware.go b/vendor/github.com/gorilla/mux/middleware.go
index cf2b26dc0..cb51c565e 100644
--- a/vendor/github.com/gorilla/mux/middleware.go
+++ b/vendor/github.com/gorilla/mux/middleware.go
@@ -58,22 +58,17 @@ func CORSMethodMiddleware(r *Router) MiddlewareFunc {
func getAllMethodsForRoute(r *Router, req *http.Request) ([]string, error) {
var allMethods []string
- err := r.Walk(func(route *Route, _ *Router, _ []*Route) error {
- for _, m := range route.matchers {
- if _, ok := m.(*routeRegexp); ok {
- if m.Match(req, &RouteMatch{}) {
- methods, err := route.GetMethods()
- if err != nil {
- return err
- }
-
- allMethods = append(allMethods, methods...)
- }
- break
+ for _, route := range r.routes {
+ var match RouteMatch
+ if route.Match(req, &match) || match.MatchErr == ErrMethodMismatch {
+ methods, err := route.GetMethods()
+ if err != nil {
+ return nil, err
}
+
+ allMethods = append(allMethods, methods...)
}
- return nil
- })
+ }
- return allMethods, err
+ return allMethods, nil
}
diff --git a/vendor/github.com/gorilla/mux/mux.go b/vendor/github.com/gorilla/mux/mux.go
index a2cd193e4..c9ba64707 100644
--- a/vendor/github.com/gorilla/mux/mux.go
+++ b/vendor/github.com/gorilla/mux/mux.go
@@ -5,6 +5,7 @@
package mux
import (
+ "context"
"errors"
"fmt"
"net/http"
@@ -58,8 +59,7 @@ type Router struct {
// If true, do not clear the request context after handling the request.
//
- // Deprecated: No effect when go1.7+ is used, since the context is stored
- // on the request itself.
+ // Deprecated: No effect, since the context is stored on the request itself.
KeepContext bool
// Slice of middlewares to be called after a match is found
@@ -111,10 +111,8 @@ func copyRouteConf(r routeConf) routeConf {
c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q))
}
- c.matchers = make([]matcher, 0, len(r.matchers))
- for _, m := range r.matchers {
- c.matchers = append(c.matchers, m)
- }
+ c.matchers = make([]matcher, len(r.matchers))
+ copy(c.matchers, r.matchers)
return c
}
@@ -197,8 +195,8 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var handler http.Handler
if r.Match(req, &match) {
handler = match.Handler
- req = setVars(req, match.Vars)
- req = setCurrentRoute(req, match.Route)
+ req = requestWithVars(req, match.Vars)
+ req = requestWithRoute(req, match.Route)
}
if handler == nil && match.MatchErr == ErrMethodMismatch {
@@ -428,7 +426,7 @@ const (
// Vars returns the route variables for the current request, if any.
func Vars(r *http.Request) map[string]string {
- if rv := contextGet(r, varsKey); rv != nil {
+ if rv := r.Context().Value(varsKey); rv != nil {
return rv.(map[string]string)
}
return nil
@@ -440,18 +438,20 @@ func Vars(r *http.Request) map[string]string {
// after the handler returns, unless the KeepContext option is set on the
// Router.
func CurrentRoute(r *http.Request) *Route {
- if rv := contextGet(r, routeKey); rv != nil {
+ if rv := r.Context().Value(routeKey); rv != nil {
return rv.(*Route)
}
return nil
}
-func setVars(r *http.Request, val interface{}) *http.Request {
- return contextSet(r, varsKey, val)
+func requestWithVars(r *http.Request, vars map[string]string) *http.Request {
+ ctx := context.WithValue(r.Context(), varsKey, vars)
+ return r.WithContext(ctx)
}
-func setCurrentRoute(r *http.Request, val interface{}) *http.Request {
- return contextSet(r, routeKey, val)
+func requestWithRoute(r *http.Request, route *Route) *http.Request {
+ ctx := context.WithValue(r.Context(), routeKey, route)
+ return r.WithContext(ctx)
}
// ----------------------------------------------------------------------------
diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go
index ac1abcd47..96dd94ad1 100644
--- a/vendor/github.com/gorilla/mux/regexp.go
+++ b/vendor/github.com/gorilla/mux/regexp.go
@@ -181,21 +181,21 @@ func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
}
}
return r.regexp.MatchString(host)
- } else {
- if r.regexpType == regexpTypeQuery {
- return r.matchQueryString(req)
- }
- path := req.URL.Path
- if r.options.useEncodedPath {
- path = req.URL.EscapedPath()
- }
- return r.regexp.MatchString(path)
}
+
+ if r.regexpType == regexpTypeQuery {
+ return r.matchQueryString(req)
+ }
+ path := req.URL.Path
+ if r.options.useEncodedPath {
+ path = req.URL.EscapedPath()
+ }
+ return r.regexp.MatchString(path)
}
// url builds a URL part using the given values.
func (r *routeRegexp) url(values map[string]string) (string, error) {
- urlValues := make([]interface{}, len(r.varsN))
+ urlValues := make([]interface{}, len(r.varsN), len(r.varsN))
for k, v := range r.varsN {
value, ok := values[v]
if !ok {
@@ -230,14 +230,51 @@ func (r *routeRegexp) getURLQuery(req *http.Request) string {
return ""
}
templateKey := strings.SplitN(r.template, "=", 2)[0]
- for key, vals := range req.URL.Query() {
- if key == templateKey && len(vals) > 0 {
- return key + "=" + vals[0]
- }
+ val, ok := findFirstQueryKey(req.URL.RawQuery, templateKey)
+ if ok {
+ return templateKey + "=" + val
}
return ""
}
+// findFirstQueryKey returns the same result as (*url.URL).Query()[key][0].
+// If key was not found, empty string and false is returned.
+func findFirstQueryKey(rawQuery, key string) (value string, ok bool) {
+ query := []byte(rawQuery)
+ for len(query) > 0 {
+ foundKey := query
+ if i := bytes.IndexAny(foundKey, "&;"); i >= 0 {
+ foundKey, query = foundKey[:i], foundKey[i+1:]
+ } else {
+ query = query[:0]
+ }
+ if len(foundKey) == 0 {
+ continue
+ }
+ var value []byte
+ if i := bytes.IndexByte(foundKey, '='); i >= 0 {
+ foundKey, value = foundKey[:i], foundKey[i+1:]
+ }
+ if len(foundKey) < len(key) {
+ // Cannot possibly be key.
+ continue
+ }
+ keyString, err := url.QueryUnescape(string(foundKey))
+ if err != nil {
+ continue
+ }
+ if keyString != key {
+ continue
+ }
+ valueString, err := url.QueryUnescape(string(value))
+ if err != nil {
+ continue
+ }
+ return valueString, true
+ }
+ return "", false
+}
+
func (r *routeRegexp) matchQueryString(req *http.Request) bool {
return r.regexp.MatchString(r.getURLQuery(req))
}
diff --git a/vendor/github.com/gorilla/mux/route.go b/vendor/github.com/gorilla/mux/route.go
index 8479c68c1..750afe570 100644
--- a/vendor/github.com/gorilla/mux/route.go
+++ b/vendor/github.com/gorilla/mux/route.go
@@ -74,7 +74,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
return false
}
- if match.MatchErr == ErrMethodMismatch {
+ if match.MatchErr == ErrMethodMismatch && r.handler != nil {
// We found a route which matches request method, clear MatchErr
match.MatchErr = nil
// Then override the mis-matched handler
@@ -412,11 +412,30 @@ func (r *Route) Queries(pairs ...string) *Route {
type schemeMatcher []string
func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool {
- return matchInArray(m, r.URL.Scheme)
+ scheme := r.URL.Scheme
+ // https://golang.org/pkg/net/http/#Request
+ // "For [most] server requests, fields other than Path and RawQuery will be
+ // empty."
+ // Since we're an http muxer, the scheme is either going to be http or https
+ // though, so we can just set it based on the tls termination state.
+ if scheme == "" {
+ if r.TLS == nil {
+ scheme = "http"
+ } else {
+ scheme = "https"
+ }
+ }
+ return matchInArray(m, scheme)
}
// Schemes adds a matcher for URL schemes.
// It accepts a sequence of schemes to be matched, e.g.: "http", "https".
+// If the request's URL has a scheme set, it will be matched against.
+// Generally, the URL scheme will only be set if a previous handler set it,
+// such as the ProxyHeaders handler from gorilla/handlers.
+// If unset, the scheme will be determined based on the request's TLS
+// termination state.
+// The first argument to Schemes will be used when constructing a route URL.
func (r *Route) Schemes(schemes ...string) *Route {
for k, v := range schemes {
schemes[k] = strings.ToLower(v)
@@ -493,8 +512,8 @@ func (r *Route) Subrouter() *Router {
// This also works for host variables:
//
// r := mux.NewRouter()
-// r.Host("{subdomain}.domain.com").
-// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+// Host("{subdomain}.domain.com").
// Name("article")
//
// // url.String() will be "http://news.domain.com/articles/technology/42"
@@ -502,6 +521,13 @@ func (r *Route) Subrouter() *Router {
// "category", "technology",
// "id", "42")
//
+// The scheme of the resulting url will be the first argument that was passed to Schemes:
+//
+// // url.String() will be "https://example.com"
+// r := mux.NewRouter()
+// url, err := r.Host("example.com")
+// .Schemes("https", "http").URL()
+//
// All variables defined in the route are required, and their values must
// conform to the corresponding patterns.
func (r *Route) URL(pairs ...string) (*url.URL, error) {
@@ -635,7 +661,7 @@ func (r *Route) GetQueriesRegexp() ([]string, error) {
if r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries")
}
- var queries []string
+ queries := make([]string, 0, len(r.regexp.queries))
for _, query := range r.regexp.queries {
queries = append(queries, query.regexp.String())
}
@@ -654,7 +680,7 @@ func (r *Route) GetQueriesTemplates() ([]string, error) {
if r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries")
}
- var queries []string
+ queries := make([]string, 0, len(r.regexp.queries))
for _, query := range r.regexp.queries {
queries = append(queries, query.template)
}
diff --git a/vendor/github.com/gorilla/mux/test_helpers.go b/vendor/github.com/gorilla/mux/test_helpers.go
index 32ecffde4..5f5c496de 100644
--- a/vendor/github.com/gorilla/mux/test_helpers.go
+++ b/vendor/github.com/gorilla/mux/test_helpers.go
@@ -15,5 +15,5 @@ import "net/http"
// can be set by making a route that captures the required variables,
// starting a server and sending the request to that server.
func SetURLVars(r *http.Request, val map[string]string) *http.Request {
- return setVars(r, val)
+ return requestWithVars(r, val)
}
diff --git a/vendor/github.com/mtrmac/gpgme/.appveyor.yml b/vendor/github.com/mtrmac/gpgme/.appveyor.yml
new file mode 100644
index 000000000..2fdc09ab5
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/.appveyor.yml
@@ -0,0 +1,40 @@
+---
+version: 0.{build}
+platform: x86
+branches:
+ only:
+ - master
+
+clone_folder: c:\gopath\src\github.com\proglottis\gpgme
+
+environment:
+ GOPATH: c:\gopath
+ GOROOT: C:\go-x86
+ CGO_LDFLAGS: -LC:\gpg\lib
+ CGO_CFLAGS: -IC:\gpg\include
+ GPG_DIR: C:\gpg
+
+install:
+ - nuget install 7ZipCLI -ExcludeVersion
+ - set PATH=%appveyor_build_folder%\7ZipCLI\tools;%PATH%
+ - appveyor DownloadFile https://www.gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.1.20_20170403.exe -FileName gnupg-w32-2.1.20_20170403.exe
+ - 7z x -o%GPG_DIR% gnupg-w32-2.1.20_20170403.exe
+ - copy "%GPG_DIR%\lib\libgpg-error.imp" "%GPG_DIR%\lib\libgpg-error.a"
+ - copy "%GPG_DIR%\lib\libassuan.imp" "%GPG_DIR%\lib\libassuan.a"
+ - copy "%GPG_DIR%\lib\libgpgme.imp" "%GPG_DIR%\lib\libgpgme.a"
+ - set PATH=%GOPATH%\bin;%GOROOT%\bin;%GPG_DIR%\bin;C:\MinGW\bin;%PATH%
+ - C:\cygwin\bin\sed -i 's/"GPG_AGENT_INFO"/"GPG_AGENT_INFO="/;s/C.unsetenv(v)/C.putenv(v)/' %APPVEYOR_BUILD_FOLDER%\gpgme.go
+
+test_script:
+ - go test -v github.com/proglottis/gpgme
+
+
+build_script:
+ - go build -o example_decrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\decrypt.go
+ - go build -o example_encrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\encrypt.go
+
+artifacts:
+ - path: example_decrypt.exe
+ name: decrypt example binary
+ - path: example_encrypt.exe
+ name: encrypt example binary \ No newline at end of file
diff --git a/vendor/github.com/mtrmac/gpgme/.travis.yml b/vendor/github.com/mtrmac/gpgme/.travis.yml
new file mode 100644
index 000000000..619e33721
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/.travis.yml
@@ -0,0 +1,32 @@
+---
+language: go
+os:
+ - linux
+ - osx
+ - windows
+dist: xenial
+sudo: false
+
+go:
+ - 1.11
+ - 1.12
+ - 1.13
+
+addons:
+ apt:
+ packages:
+ - libgpgme11-dev
+ homebrew:
+ packages:
+ - gnupg
+ - gnupg@1.4
+ - gpgme
+ update: true
+
+matrix:
+ allow_failures:
+ - os: windows
+
+before_install:
+ - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install msys2; fi
+ - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install gpg4win; fi
diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/mtrmac/gpgme/data.go
index eebc97263..eee32c032 100644
--- a/vendor/github.com/mtrmac/gpgme/data.go
+++ b/vendor/github.com/mtrmac/gpgme/data.go
@@ -50,25 +50,25 @@ func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
}
//export gogpgme_seekfunc
-func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t {
+func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {
d := callbackLookup(uintptr(handle)).(*Data)
n, err := d.s.Seek(int64(offset), int(whence))
if err != nil {
C.gpgme_err_set_errno(C.EIO)
return -1
}
- return C.off_t(n)
+ return C.gpgme_off_t(n)
}
// The Data buffer used to communicate with GPGME
type Data struct {
- dh C.gpgme_data_t
+ dh C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C
buf []byte
cbs C.struct_gpgme_data_cbs
r io.Reader
w io.Writer
s io.Seeker
- cbc uintptr
+ cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)
}
func newData() *Data {
@@ -154,12 +154,14 @@ func (d *Data) Close() error {
callbackDelete(d.cbc)
}
_, err := C.gpgme_data_release(d.dh)
+ runtime.KeepAlive(d)
d.dh = nil
return err
}
func (d *Data) Write(p []byte) (int, error) {
n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
+ runtime.KeepAlive(d)
if err != nil {
return 0, err
}
@@ -171,6 +173,7 @@ func (d *Data) Write(p []byte) (int, error) {
func (d *Data) Read(p []byte) (int, error) {
n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
+ runtime.KeepAlive(d)
if err != nil {
return 0, err
}
@@ -181,11 +184,14 @@ func (d *Data) Read(p []byte) (int, error) {
}
func (d *Data) Seek(offset int64, whence int) (int64, error) {
- n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence))
+ n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))
+ runtime.KeepAlive(d)
return int64(n), err
}
// Name returns the associated filename if any
func (d *Data) Name() string {
- return C.GoString(C.gpgme_data_get_file_name(d.dh))
+ res := C.GoString(C.gpgme_data_get_file_name(d.dh))
+ runtime.KeepAlive(d)
+ return res
}
diff --git a/vendor/github.com/mtrmac/gpgme/go.mod b/vendor/github.com/mtrmac/gpgme/go.mod
new file mode 100644
index 000000000..3dd09c9fb
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/go.mod
@@ -0,0 +1,3 @@
+module github.com/mtrmac/gpgme
+
+go 1.11
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
index b887574e0..00da3ab30 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
@@ -8,6 +8,28 @@ void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintpt
gpgme_set_passphrase_cb(ctx, cb, (void *)handle);
}
+gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence) {
+ return gpgme_data_seek(dh, offset, whence);
+}
+
+gpgme_error_t gogpgme_op_assuan_transact_ext(
+ gpgme_ctx_t ctx,
+ char* cmd,
+ uintptr_t data_h,
+ uintptr_t inquiry_h,
+ uintptr_t status_h,
+ gpgme_error_t *operr
+ ){
+ return gpgme_op_assuan_transact_ext(
+ ctx,
+ cmd,
+ (gpgme_assuan_data_cb_t) gogpgme_assuan_data_callback, (void *)data_h,
+ (gpgme_assuan_inquire_cb_t) gogpgme_assuan_inquiry_callback, (void *)inquiry_h,
+ (gpgme_assuan_status_cb_t) gogpgme_assuan_status_callback, (void *)status_h,
+ operr
+ );
+}
+
unsigned int key_revoked(gpgme_key_t k) {
return k->revoked;
}
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
index a3678b127..d4826ab36 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
@@ -6,12 +6,24 @@
#include <gpgme.h>
+/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */
+#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402
+typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */
+#endif
+
extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd);
extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle);
extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle);
+extern gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence);
+
+extern gpgme_error_t gogpgme_op_assuan_transact_ext(gpgme_ctx_t ctx, char *cmd, uintptr_t data_h, uintptr_t inquiry_h , uintptr_t status_h, gpgme_error_t *operr);
+
+extern gpgme_error_t gogpgme_assuan_data_callback(void *opaque, void* data, size_t datalen );
+extern gpgme_error_t gogpgme_assuan_inquiry_callback(void *opaque, char* name, char* args);
+extern gpgme_error_t gogpgme_assuan_status_callback(void *opaque, char* status, char* args);
extern unsigned int key_revoked(gpgme_key_t k);
extern unsigned int key_expired(gpgme_key_t k);
diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go
index 20aad737c..c19b9aebc 100644
--- a/vendor/github.com/mtrmac/gpgme/gpgme.go
+++ b/vendor/github.com/mtrmac/gpgme/gpgme.go
@@ -7,7 +7,6 @@ package gpgme
// #include <gpgme.h>
// #include "go_gpgme.h"
import "C"
-
import (
"fmt"
"io"
@@ -48,9 +47,8 @@ const (
ProtocolAssuan Protocol = C.GPGME_PROTOCOL_ASSUAN
ProtocolG13 Protocol = C.GPGME_PROTOCOL_G13
ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
- // ProtocolSpawn Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
- ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
- ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
+ ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
+ ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
)
type PinEntryMode int
@@ -70,7 +68,6 @@ const (
EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
EncryptPrepare EncryptFlag = C.GPGME_ENCRYPT_PREPARE
EncryptExceptSign EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
- // EncryptNoCompress EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
)
type HashAlgo int
@@ -84,7 +81,6 @@ const (
KeyListModeExtern KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
KeyListModeSigs KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
- // KeyListModeWithSecret KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
KeyListModeEphemeral KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
)
@@ -168,39 +164,60 @@ func EngineCheckVersion(p Protocol) error {
}
type EngineInfo struct {
- info C.gpgme_engine_info_t
+ next *EngineInfo
+ protocol Protocol
+ fileName string
+ homeDir string
+ version string
+ requiredVersion string
}
-func (e *EngineInfo) Next() *EngineInfo {
- if e.info.next == nil {
- return nil
+func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
+ res := &EngineInfo{
+ next: nil,
+ protocol: Protocol(info.protocol),
+ fileName: C.GoString(info.file_name),
+ homeDir: C.GoString(info.home_dir),
+ version: C.GoString(info.version),
+ requiredVersion: C.GoString(info.req_version),
+ }
+ if info.next != nil {
+ res.next = copyEngineInfo(info.next)
}
- return &EngineInfo{info: e.info.next}
+ return res
+}
+
+func (e *EngineInfo) Next() *EngineInfo {
+ return e.next
}
func (e *EngineInfo) Protocol() Protocol {
- return Protocol(e.info.protocol)
+ return e.protocol
}
func (e *EngineInfo) FileName() string {
- return C.GoString(e.info.file_name)
+ return e.fileName
}
func (e *EngineInfo) Version() string {
- return C.GoString(e.info.version)
+ return e.version
}
func (e *EngineInfo) RequiredVersion() string {
- return C.GoString(e.info.req_version)
+ return e.requiredVersion
}
func (e *EngineInfo) HomeDir() string {
- return C.GoString(e.info.home_dir)
+ return e.homeDir
}
func GetEngineInfo() (*EngineInfo, error) {
- info := &EngineInfo{}
- return info, handleError(C.gpgme_get_engine_info(&info.info))
+ var cInfo C.gpgme_engine_info_t
+ err := handleError(C.gpgme_get_engine_info(&cInfo))
+ if err != nil {
+ return nil, err
+ }
+ return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
}
func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
@@ -261,9 +278,9 @@ type Context struct {
KeyError error
callback Callback
- cbc uintptr
+ cbc uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
- ctx C.gpgme_ctx_t
+ ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
}
func New() (*Context, error) {
@@ -281,49 +298,68 @@ func (c *Context) Release() {
callbackDelete(c.cbc)
}
C.gpgme_release(c.ctx)
+ runtime.KeepAlive(c)
c.ctx = nil
}
func (c *Context) SetArmor(yes bool) {
C.gpgme_set_armor(c.ctx, cbool(yes))
+ runtime.KeepAlive(c)
}
func (c *Context) Armor() bool {
- return C.gpgme_get_armor(c.ctx) != 0
+ res := C.gpgme_get_armor(c.ctx) != 0
+ runtime.KeepAlive(c)
+ return res
}
func (c *Context) SetTextMode(yes bool) {
C.gpgme_set_textmode(c.ctx, cbool(yes))
+ runtime.KeepAlive(c)
}
func (c *Context) TextMode() bool {
- return C.gpgme_get_textmode(c.ctx) != 0
+ res := C.gpgme_get_textmode(c.ctx) != 0
+ runtime.KeepAlive(c)
+ return res
}
func (c *Context) SetProtocol(p Protocol) error {
- return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
+ err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) Protocol() Protocol {
- return Protocol(C.gpgme_get_protocol(c.ctx))
+ res := Protocol(C.gpgme_get_protocol(c.ctx))
+ runtime.KeepAlive(c)
+ return res
}
func (c *Context) SetKeyListMode(m KeyListMode) error {
- return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
+ err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) KeyListMode() KeyListMode {
- return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
+ res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
+ runtime.KeepAlive(c)
+ return res
}
// Unavailable in 1.3.2:
// func (c *Context) SetPinEntryMode(m PinEntryMode) error {
-// return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+// err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+// runtime.KeepAlive(c)
+// return err
// }
// Unavailable in 1.3.2:
// func (c *Context) PinEntryMode() PinEntryMode {
-// return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+// res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+// runtime.KeepAlive(c)
+// return res
// }
func (c *Context) SetCallback(callback Callback) error {
@@ -340,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error {
c.cbc = 0
_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
}
+ runtime.KeepAlive(c)
return err
}
func (c *Context) EngineInfo() *EngineInfo {
- return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
+ cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
+ runtime.KeepAlive(c)
+ // NOTE: c must be live as long as we are accessing cInfo.
+ res := copyEngineInfo(cInfo)
+ runtime.KeepAlive(c) // for accesses to cInfo
+ return res
}
func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
@@ -357,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error
chome = C.CString(homeDir)
defer C.free(unsafe.Pointer(chome))
}
- return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
+ err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
cpattern := C.CString(pattern)
defer C.free(unsafe.Pointer(cpattern))
- err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
- return handleError(err)
+ err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) KeyListNext() bool {
c.Key = newKey()
err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
+ runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
if err != nil {
if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
c.KeyError = nil
@@ -383,7 +429,9 @@ func (c *Context) KeyListNext() bool {
}
func (c *Context) KeyListEnd() error {
- return handleError(C.gpgme_op_keylist_end(c.ctx))
+ err := handleError(C.gpgme_op_keylist_end(c.ctx))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
@@ -391,7 +439,11 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
cfpr := C.CString(fingerprint)
defer C.free(unsafe.Pointer(cfpr))
err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
- if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF {
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(key)
+ keyKIsNil := key.k == nil
+ runtime.KeepAlive(key)
+ if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
return nil, fmt.Errorf("key %q not found", fingerprint)
}
if err != nil {
@@ -401,11 +453,19 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
}
func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
- return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
+ err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(ciphertext)
+ runtime.KeepAlive(plaintext)
+ return err
}
func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
- return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
+ err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(ciphertext)
+ runtime.KeepAlive(plaintext)
+ return err
}
type Signature struct {
@@ -432,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
plainPtr = plain.dh
}
err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(sig)
+ if signedText != nil {
+ runtime.KeepAlive(signedText)
+ }
+ if plain != nil {
+ runtime.KeepAlive(plain)
+ }
if err != nil {
return "", nil, err
}
res := C.gpgme_op_verify_result(c.ctx)
+ runtime.KeepAlive(c)
+ // NOTE: c must be live as long as we are accessing res.
sigs := []Signature{}
for s := res.signatures; s != nil; s = s.next {
sig := Signature{
@@ -455,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
}
sigs = append(sigs, sig)
}
- return C.GoString(res.file_name), sigs, nil
+ fileName := C.GoString(res.file_name)
+ runtime.KeepAlive(c) // for all accesses to res above
+ return fileName, sigs, nil
}
func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
@@ -467,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe
*ptr = recipients[i].k
}
err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(recipients)
+ runtime.KeepAlive(plaintext)
+ runtime.KeepAlive(ciphertext)
return handleError(err)
}
func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
C.gpgme_signers_clear(c.ctx)
+ runtime.KeepAlive(c)
for _, k := range signers {
- if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
+ err := handleError(C.gpgme_signers_add(c.ctx, k.k))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(k)
+ if err != nil {
C.gpgme_signers_clear(c.ctx)
+ runtime.KeepAlive(c)
return err
}
}
- return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
+ err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(plain)
+ runtime.KeepAlive(sig)
+ return err
+}
+
+type AssuanDataCallback func(data []byte) error
+type AssuanInquireCallback func(name, args string) error
+type AssuanStatusCallback func(status, args string) error
+
+// AssuanSend sends a raw Assuan command to gpg-agent
+func (c *Context) AssuanSend(
+ cmd string,
+ data AssuanDataCallback,
+ inquiry AssuanInquireCallback,
+ status AssuanStatusCallback,
+) error {
+ var operr C.gpgme_error_t
+
+ dataPtr := callbackAdd(&data)
+ inquiryPtr := callbackAdd(&inquiry)
+ statusPtr := callbackAdd(&status)
+ cmdCStr := C.CString(cmd)
+ defer C.free(unsafe.Pointer(cmdCStr))
+ err := C.gogpgme_op_assuan_transact_ext(
+ c.ctx,
+ cmdCStr,
+ C.uintptr_t(dataPtr),
+ C.uintptr_t(inquiryPtr),
+ C.uintptr_t(statusPtr),
+ &operr,
+ )
+ runtime.KeepAlive(c)
+
+ if handleError(operr) != nil {
+ return handleError(operr)
+ }
+ return handleError(err)
+}
+
+//export gogpgme_assuan_data_callback
+func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
+ c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
+ if *c == nil {
+ return 0
+ }
+ (*c)(C.GoBytes(data, C.int(datalen)))
+ return 0
+}
+
+//export gogpgme_assuan_inquiry_callback
+func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
+ name := C.GoString(cName)
+ args := C.GoString(cArgs)
+ c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
+ if *c == nil {
+ return 0
+ }
+ (*c)(name, args)
+ return 0
+}
+
+//export gogpgme_assuan_status_callback
+func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
+ status := C.GoString(cStatus)
+ args := C.GoString(cArgs)
+ c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
+ if *c == nil {
+ return 0
+ }
+ (*c)(status, args)
+ return 0
+}
+
+// ExportModeFlags defines how keys are exported from Export
+type ExportModeFlags uint
+
+const (
+ ExportModeExtern ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
+ ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
+)
+
+func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
+ pat := C.CString(pattern)
+ defer C.free(unsafe.Pointer(pat))
+ err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(data)
+ return err
}
// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
@@ -517,10 +687,14 @@ type ImportResult struct {
func (c *Context) Import(keyData *Data) (*ImportResult, error) {
err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(keyData)
if err != nil {
return nil, err
}
res := C.gpgme_op_import_result(c.ctx)
+ runtime.KeepAlive(c)
+ // NOTE: c must be live as long as we are accessing res.
imports := []ImportStatus{}
for s := res.imports; s != nil; s = s.next {
imports = append(imports, ImportStatus{
@@ -529,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
Status: ImportStatusFlags(s.status),
})
}
- return &ImportResult{
+ importResult := &ImportResult{
Considered: int(res.considered),
NoUserID: int(res.no_user_id),
Imported: int(res.imported),
@@ -544,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
SecretUnchanged: int(res.secret_unchanged),
NotImported: int(res.not_imported),
Imports: imports,
- }, nil
+ }
+ runtime.KeepAlive(c) // for all accesses to res above
+ return importResult, nil
}
type Key struct {
- k C.gpgme_key_t
+ k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
}
func newKey() *Key {
@@ -559,85 +735,122 @@ func newKey() *Key {
func (k *Key) Release() {
C.gpgme_key_release(k.k)
+ runtime.KeepAlive(k)
k.k = nil
}
func (k *Key) Revoked() bool {
- return C.key_revoked(k.k) != 0
+ res := C.key_revoked(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Expired() bool {
- return C.key_expired(k.k) != 0
+ res := C.key_expired(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Disabled() bool {
- return C.key_disabled(k.k) != 0
+ res := C.key_disabled(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Invalid() bool {
- return C.key_invalid(k.k) != 0
+ res := C.key_invalid(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanEncrypt() bool {
- return C.key_can_encrypt(k.k) != 0
+ res := C.key_can_encrypt(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanSign() bool {
- return C.key_can_sign(k.k) != 0
+ res := C.key_can_sign(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanCertify() bool {
- return C.key_can_certify(k.k) != 0
+ res := C.key_can_certify(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Secret() bool {
- return C.key_secret(k.k) != 0
+ res := C.key_secret(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanAuthenticate() bool {
- return C.key_can_authenticate(k.k) != 0
+ res := C.key_can_authenticate(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) IsQualified() bool {
- return C.key_is_qualified(k.k) != 0
+ res := C.key_is_qualified(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Protocol() Protocol {
- return Protocol(k.k.protocol)
+ res := Protocol(k.k.protocol)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) IssuerSerial() string {
- return C.GoString(k.k.issuer_serial)
+ res := C.GoString(k.k.issuer_serial)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) IssuerName() string {
- return C.GoString(k.k.issuer_name)
+ res := C.GoString(k.k.issuer_name)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) ChainID() string {
- return C.GoString(k.k.chain_id)
+ res := C.GoString(k.k.chain_id)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) OwnerTrust() Validity {
- return Validity(k.k.owner_trust)
+ res := Validity(k.k.owner_trust)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) SubKeys() *SubKey {
- if k.k.subkeys == nil {
+ subKeys := k.k.subkeys
+ runtime.KeepAlive(k)
+ if subKeys == nil {
return nil
}
- return &SubKey{k: k.k.subkeys, parent: k}
+ return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
}
func (k *Key) UserIDs() *UserID {
- if k.k.uids == nil {
+ uids := k.k.uids
+ runtime.KeepAlive(k)
+ if uids == nil {
return nil
}
- return &UserID{u: k.k.uids, parent: k}
+ return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
}
func (k *Key) KeyListMode() KeyListMode {
- return KeyListMode(k.k.keylist_mode)
+ res := KeyListMode(k.k.keylist_mode)
+ runtime.KeepAlive(k)
+ return res
}
type SubKey struct {
@@ -737,12 +950,3 @@ func (u *UserID) Comment() string {
func (u *UserID) Email() string {
return C.GoString(u.u.email)
}
-
-// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
-// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
-// - and cgo can't be used in tests. So, provide this helper for test initialization.
-func unsetenvGPGAgentInfo() {
- v := C.CString("GPG_AGENT_INFO")
- defer C.free(unsafe.Pointer(v))
- C.unsetenv(v)
-}
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
new file mode 100644
index 000000000..986aca59f
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
@@ -0,0 +1,18 @@
+// +build !windows
+
+package gpgme
+
+// #include <stdlib.h>
+import "C"
+import (
+ "unsafe"
+)
+
+// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
+// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
+// - and cgo can't be used in tests. So, provide this helper for test initialization.
+func unsetenvGPGAgentInfo() {
+ v := C.CString("GPG_AGENT_INFO")
+ defer C.free(unsafe.Pointer(v))
+ C.unsetenv(v)
+}
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
new file mode 100644
index 000000000..431ec86d3
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
@@ -0,0 +1,14 @@
+package gpgme
+
+// #include <stdlib.h>
+import "C"
+import (
+ "unsafe"
+)
+
+// unsetenv is not available in mingw
+func unsetenvGPGAgentInfo() {
+ v := C.CString("GPG_AGENT_INFO=")
+ defer C.free(unsafe.Pointer(v))
+ C.putenv(v)
+}
diff --git a/vendor/github.com/onsi/ginkgo/.travis.yml b/vendor/github.com/onsi/ginkgo/.travis.yml
index b454d643c..65dc3002b 100644
--- a/vendor/github.com/onsi/ginkgo/.travis.yml
+++ b/vendor/github.com/onsi/ginkgo/.travis.yml
@@ -4,14 +4,22 @@ go:
- 1.13.x
- tip
+cache:
+ directories:
+ - $GOPATH/pkg/mod
+
# allow internal package imports, necessary for forked repositories
go_import_path: github.com/onsi/ginkgo
install:
- - go get -v -t ./...
- - go get golang.org/x/tools/cmd/cover
- - go get github.com/onsi/gomega
- - go install github.com/onsi/ginkgo/ginkgo
+ - GO111MODULE="off" go get -v -t ./...
+ - GO111MODULE="off" go get golang.org/x/tools/cmd/cover
+ - GO111MODULE="off" go get github.com/onsi/gomega
+ - GO111MODULE="off" go install github.com/onsi/ginkgo/ginkgo
- export PATH=$PATH:$HOME/gopath/bin
-script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace && go vet
+script:
+ - GO111MODULE="on" go mod tidy
+ - diff -u <(echo -n) <(git diff go.mod)
+ - diff -u <(echo -n) <(git diff go.sum)
+ - $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --randomizeSuites --race --trace && go vet
diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md
index 96f03ad7c..84b479404 100644
--- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md
+++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.12.0
+
+### Features
+- Add module definition (#630) [78916ab]
+
## 1.11.0
### Features
diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go
index 14c82ec3a..949f8130f 100644
--- a/vendor/github.com/onsi/ginkgo/config/config.go
+++ b/vendor/github.com/onsi/ginkgo/config/config.go
@@ -20,7 +20,7 @@ import (
"fmt"
)
-const VERSION = "1.11.0"
+const VERSION = "1.12.0"
type GinkgoConfigType struct {
RandomSeed int64
diff --git a/vendor/github.com/onsi/ginkgo/go.mod b/vendor/github.com/onsi/ginkgo/go.mod
new file mode 100644
index 000000000..15a4ab571
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/go.mod
@@ -0,0 +1,9 @@
+module github.com/onsi/ginkgo
+
+require (
+ github.com/hpcloud/tail v1.0.0
+ github.com/onsi/gomega v1.7.1
+ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e
+)
+
+go 1.12
diff --git a/vendor/github.com/onsi/ginkgo/go.sum b/vendor/github.com/onsi/ginkgo/go.sum
new file mode 100644
index 000000000..29adce41a
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/go.sum
@@ -0,0 +1,26 @@
+github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/vendor/github.com/vbauerster/mpb/v4/bar_option.go b/vendor/github.com/vbauerster/mpb/v4/bar_option.go
index bb79ac6a4..7fb152562 100644
--- a/vendor/github.com/vbauerster/mpb/v4/bar_option.go
+++ b/vendor/github.com/vbauerster/mpb/v4/bar_option.go
@@ -10,11 +10,10 @@ import (
// BarOption is a function option which changes the default behavior of a bar.
type BarOption func(*bState)
-type mergeWrapper interface {
- MergeUnwrap() []decor.Decorator
-}
-
func (s *bState) addDecorators(dest *[]decor.Decorator, decorators ...decor.Decorator) {
+ type mergeWrapper interface {
+ MergeUnwrap() []decor.Decorator
+ }
for _, decorator := range decorators {
if mw, ok := decorator.(mergeWrapper); ok {
*dest = append(*dest, mw.MergeUnwrap()...)
diff --git a/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go b/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
index 5c0d16880..2271cbbe1 100644
--- a/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
+++ b/vendor/github.com/vbauerster/mpb/v4/decor/decorator.go
@@ -4,6 +4,8 @@ import (
"fmt"
"time"
"unicode/utf8"
+
+ "github.com/acarl005/stripansi"
)
const (
@@ -117,25 +119,29 @@ var (
// W represents width and C represents bit set of width related config.
// A decorator should embed WC, to enable width synchronization.
type WC struct {
- W int
- C int
- dynFormat string
- staticFormat string
- wsync chan int
+ W int
+ C int
+ dynFormat string
+ wsync chan int
}
// FormatMsg formats final message according to WC.W and WC.C.
// Should be called by any Decorator implementation.
func (wc *WC) FormatMsg(msg string) string {
+ var format string
+ runeCount := utf8.RuneCountInString(stripansi.Strip(msg))
+ ansiCount := utf8.RuneCountInString(msg) - runeCount
if (wc.C & DSyncWidth) != 0 {
- wc.wsync <- utf8.RuneCountInString(msg)
- max := <-wc.wsync
if (wc.C & DextraSpace) != 0 {
- max++
+ runeCount++
}
- return fmt.Sprintf(fmt.Sprintf(wc.dynFormat, max), msg)
+ wc.wsync <- runeCount
+ max := <-wc.wsync
+ format = fmt.Sprintf(wc.dynFormat, ansiCount+max)
+ } else {
+ format = fmt.Sprintf(wc.dynFormat, ansiCount+wc.W)
}
- return fmt.Sprintf(wc.staticFormat, msg)
+ return fmt.Sprintf(format, msg)
}
// Init initializes width related config.
@@ -145,7 +151,6 @@ func (wc *WC) Init() WC {
wc.dynFormat += "-"
}
wc.dynFormat += "%ds"
- wc.staticFormat = fmt.Sprintf(wc.dynFormat, wc.W)
if (wc.C & DSyncWidth) != 0 {
// it's deliberate choice to override wsync on each Init() call,
// this way globals like WCSyncSpace can be reused
diff --git a/vendor/github.com/vbauerster/mpb/v4/decor/merge.go b/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
index fdf9e107b..723869209 100644
--- a/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
+++ b/vendor/github.com/vbauerster/mpb/v4/decor/merge.go
@@ -2,6 +2,7 @@ package decor
import (
"fmt"
+ "strings"
"unicode/utf8"
)
@@ -28,10 +29,7 @@ func Merge(decorator Decorator, placeholders ...WC) Decorator {
if (wc.C & DSyncWidth) == 0 {
return decorator
}
- md.placeHolders[i] = &placeHolderDecorator{
- WC: wc.Init(),
- wch: make(chan int),
- }
+ md.placeHolders[i] = &placeHolderDecorator{wc.Init()}
}
return md
}
@@ -69,29 +67,40 @@ func (d *mergeDecorator) Base() Decorator {
func (d *mergeDecorator) Decor(st *Statistics) string {
msg := d.Decorator.Decor(st)
msgLen := utf8.RuneCountInString(msg)
-
- var space int
- for _, ph := range d.placeHolders {
- space += <-ph.wch
+ if (d.wc.C & DextraSpace) != 0 {
+ msgLen++
}
- d.wc.wsync <- msgLen - space
+ var total int
+ max := utf8.RuneCountInString(d.placeHolders[0].FormatMsg(""))
+ total += max
+ pw := (msgLen - max) / len(d.placeHolders)
+ rem := (msgLen - max) % len(d.placeHolders)
- max := <-d.wc.wsync
- if (d.wc.C & DextraSpace) != 0 {
- max++
+ var diff int
+ for i := 1; i < len(d.placeHolders); i++ {
+ ph := d.placeHolders[i]
+ width := pw - diff
+ if (ph.WC.C & DextraSpace) != 0 {
+ width--
+ if width < 0 {
+ width = 0
+ }
+ }
+ max = utf8.RuneCountInString(ph.FormatMsg(strings.Repeat(" ", width)))
+ total += max
+ diff = max - pw
}
- return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max+space), msg)
+
+ d.wc.wsync <- pw + rem
+ max = <-d.wc.wsync
+ return fmt.Sprintf(fmt.Sprintf(d.wc.dynFormat, max+total), msg)
}
type placeHolderDecorator struct {
WC
- wch chan int
}
-func (d *placeHolderDecorator) Decor(st *Statistics) string {
- go func() {
- d.wch <- utf8.RuneCountInString(d.FormatMsg(""))
- }()
+func (d *placeHolderDecorator) Decor(_ *Statistics) string {
return ""
}
diff --git a/vendor/github.com/vbauerster/mpb/v4/go.mod b/vendor/github.com/vbauerster/mpb/v4/go.mod
index 0c5ce51f1..9e7287d5d 100644
--- a/vendor/github.com/vbauerster/mpb/v4/go.mod
+++ b/vendor/github.com/vbauerster/mpb/v4/go.mod
@@ -2,6 +2,7 @@ module github.com/vbauerster/mpb/v4
require (
github.com/VividCortex/ewma v1.1.1
+ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708
golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056 // indirect
)
diff --git a/vendor/github.com/vbauerster/mpb/v4/go.sum b/vendor/github.com/vbauerster/mpb/v4/go.sum
index 94a9f1a28..5a1316274 100644
--- a/vendor/github.com/vbauerster/mpb/v4/go.sum
+++ b/vendor/github.com/vbauerster/mpb/v4/go.sum
@@ -1,5 +1,7 @@
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
+github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
+github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708 h1:pXVtWnwHkrWD9ru3sDxY/qFK/bfc0egRovX91EjWjf4=
golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
diff --git a/vendor/github.com/vbauerster/mpb/v4/proxyreader.go b/vendor/github.com/vbauerster/mpb/v4/proxyreader.go
index 736142412..0e4b51f09 100644
--- a/vendor/github.com/vbauerster/mpb/v4/proxyreader.go
+++ b/vendor/github.com/vbauerster/mpb/v4/proxyreader.go
@@ -18,9 +18,7 @@ func (prox *proxyReader) Read(p []byte) (n int, err error) {
prox.iT = time.Now()
}
if err == io.EOF {
- go func() {
- prox.bar.SetTotal(0, true)
- }()
+ go prox.bar.SetTotal(0, true)
}
return
}
@@ -37,9 +35,7 @@ func (prox *proxyWriterTo) WriteTo(w io.Writer) (n int64, err error) {
prox.iT = time.Now()
}
if err == io.EOF {
- go func() {
- prox.bar.SetTotal(0, true)
- }()
+ go prox.bar.SetTotal(0, true)
}
return
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 2a384e865..73bca1ef8 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -29,6 +29,8 @@ github.com/Microsoft/hcsshim/internal/wclayer
github.com/Microsoft/hcsshim/osversion
# github.com/VividCortex/ewma v1.1.1
github.com/VividCortex/ewma
+# github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
+github.com/acarl005/stripansi
# github.com/beorn7/perks v1.0.1
github.com/beorn7/perks/quantile
# github.com/blang/semver v3.5.1+incompatible
@@ -80,7 +82,7 @@ github.com/containers/common/pkg/cgroups
github.com/containers/common/pkg/unshare
# github.com/containers/conmon v2.0.10+incompatible
github.com/containers/conmon/runner/config
-# github.com/containers/image/v5 v5.1.0
+# github.com/containers/image/v5 v5.2.1
github.com/containers/image/v5/copy
github.com/containers/image/v5/directory
github.com/containers/image/v5/directory/explicitfilepath
@@ -91,6 +93,7 @@ github.com/containers/image/v5/docker/policyconfiguration
github.com/containers/image/v5/docker/reference
github.com/containers/image/v5/docker/tarfile
github.com/containers/image/v5/image
+github.com/containers/image/v5/internal/iolimits
github.com/containers/image/v5/internal/pkg/keyctl
github.com/containers/image/v5/internal/tmpdir
github.com/containers/image/v5/manifest
@@ -288,7 +291,7 @@ github.com/google/gofuzz
github.com/google/shlex
# github.com/google/uuid v1.1.1
github.com/google/uuid
-# github.com/gorilla/mux v1.7.3
+# github.com/gorilla/mux v1.7.4
github.com/gorilla/mux
# github.com/gorilla/schema v1.1.0
github.com/gorilla/schema
@@ -337,9 +340,9 @@ github.com/modern-go/reflect2
github.com/morikuni/aec
# github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
github.com/mrunalp/fileutils
-# github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c
+# github.com/mtrmac/gpgme v0.1.2
github.com/mtrmac/gpgme
-# github.com/onsi/ginkgo v1.11.0
+# github.com/onsi/ginkgo v1.12.0
github.com/onsi/ginkgo
github.com/onsi/ginkgo/config
github.com/onsi/ginkgo/extensions/table
@@ -510,7 +513,7 @@ github.com/varlink/go/varlink/idl
github.com/vbatts/tar-split/archive/tar
github.com/vbatts/tar-split/tar/asm
github.com/vbatts/tar-split/tar/storage
-# github.com/vbauerster/mpb/v4 v4.11.1
+# github.com/vbauerster/mpb/v4 v4.11.2
github.com/vbauerster/mpb/v4
github.com/vbauerster/mpb/v4/cwriter
github.com/vbauerster/mpb/v4/decor
@@ -627,9 +630,9 @@ gopkg.in/square/go-jose.v2/json
gopkg.in/tomb.v1
# gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v2
-# k8s.io/api v0.17.2
+# k8s.io/api v0.17.3
k8s.io/api/core/v1
-# k8s.io/apimachinery v0.17.2
+# k8s.io/apimachinery v0.17.3
k8s.io/apimachinery/pkg/api/errors
k8s.io/apimachinery/pkg/api/resource
k8s.io/apimachinery/pkg/apis/meta/v1
diff --git a/version/version.go b/version/version.go
index 4665023a4..d5926d744 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.8.0-dev"
+const Version = "1.8.1-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility