summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml4
-rw-r--r--.gitignore1
-rw-r--r--Makefile12
-rw-r--r--README.md2
-rw-r--r--cmd/podman/cliconfig/config.go2
-rw-r--r--cmd/podman/errors_remote.go2
-rw-r--r--cmd/podman/generate_systemd.go8
-rw-r--r--cmd/podman/pod_stop.go5
-rw-r--r--cmd/podman/restart.go9
-rw-r--r--cmd/podman/service.go2
-rw-r--r--cmd/podman/shared/create.go27
-rw-r--r--cmd/podman/shared/intermediate_varlink.go2
-rw-r--r--cmd/podman/stop.go13
-rw-r--r--cmd/podman/utils.go2
-rw-r--r--cmd/podman/varlink.go2
-rw-r--r--cmd/podman/varlink/generate.go3
-rw-r--r--cmd/podmanV2/Makefile2
-rw-r--r--cmd/podmanV2/common/inspect.go18
-rw-r--r--cmd/podmanV2/containers/export.go57
-rw-r--r--cmd/podmanV2/containers/inspect.go32
-rw-r--r--cmd/podmanV2/containers/restart.go11
-rw-r--r--cmd/podmanV2/containers/stop.go16
-rw-r--r--cmd/podmanV2/healthcheck/healthcheck.go33
-rw-r--r--cmd/podmanV2/healthcheck/run.go42
-rw-r--r--cmd/podmanV2/images/import.go87
-rw-r--r--cmd/podmanV2/images/inspect.go141
-rw-r--r--cmd/podmanV2/images/list.go2
-rw-r--r--cmd/podmanV2/images/load.go61
-rw-r--r--cmd/podmanV2/images/pull.go140
-rw-r--r--cmd/podmanV2/images/push.go127
-rw-r--r--cmd/podmanV2/images/tag.go34
-rw-r--r--cmd/podmanV2/images/untag.go33
-rw-r--r--cmd/podmanV2/inspect.go62
-rw-r--r--cmd/podmanV2/main.go7
-rw-r--r--cmd/podmanV2/pods/pod.go30
-rw-r--r--cmd/podmanV2/pods/ps.go134
-rw-r--r--cmd/podmanV2/pods/stop.go7
-rw-r--r--cmd/podmanV2/registry/registry.go17
-rw-r--r--cmd/podmanV2/report/templates.go3
-rw-r--r--cmd/podmanV2/root.go5
-rw-r--r--cmd/podmanV2/system/system.go2
-rw-r--r--cmd/podmanV2/utils/alias.go24
-rw-r--r--completions/bash/podman10
-rwxr-xr-xcontrib/build_rpm.sh13
-rw-r--r--contrib/cirrus/README.md4
-rw-r--r--contrib/spec/podman.spec.in6
-rw-r--r--docs/generate.go2
-rw-r--r--docs/source/markdown/podman-generate-systemd.1.md2
-rw-r--r--docs/source/markdown/podman-pod-stop.1.md2
-rw-r--r--docs/source/markdown/podman-restart.1.md2
-rw-r--r--docs/source/markdown/podman-stop.1.md4
-rw-r--r--go.mod10
-rw-r--r--go.sum23
-rwxr-xr-xhack/podmanv2-retry37
-rw-r--r--libpod/image/image.go6
-rw-r--r--libpod/image/image_test.go2
-rw-r--r--libpod/oci_attach_linux.go6
-rw-r--r--libpod/oci_conmon_linux.go37
-rw-r--r--libpod/podfilters/pods.go115
-rw-r--r--pkg/adapter/containers.go4
-rw-r--r--pkg/adapter/containers_remote.go2
-rw-r--r--pkg/adapter/errors.go2
-rw-r--r--pkg/adapter/images_remote.go2
-rw-r--r--pkg/adapter/info_remote.go4
-rw-r--r--pkg/adapter/pods_remote.go2
-rw-r--r--pkg/adapter/reset_remote.go2
-rw-r--r--pkg/adapter/runtime_remote.go2
-rw-r--r--pkg/api/handlers/compat/containers_export.go42
-rw-r--r--pkg/api/handlers/compat/images_push.go80
-rw-r--r--pkg/api/handlers/libpod/images.go162
-rw-r--r--pkg/api/handlers/swagger.go4
-rw-r--r--pkg/api/handlers/types.go4
-rw-r--r--pkg/api/handlers/utils/images.go41
-rw-r--r--pkg/api/handlers/utils/pods.go5
-rw-r--r--pkg/api/server/register_containers.go45
-rw-r--r--pkg/api/server/register_images.go106
-rw-r--r--pkg/bindings/containers/containers.go20
-rw-r--r--pkg/bindings/images/images.go106
-rw-r--r--pkg/bindings/test/images_test.go25
-rw-r--r--pkg/domain/entities/containers.go10
-rw-r--r--pkg/domain/entities/engine_container.go20
-rw-r--r--pkg/domain/entities/engine_image.go7
-rw-r--r--pkg/domain/entities/healthcheck.go3
-rw-r--r--pkg/domain/entities/images.go117
-rw-r--r--pkg/domain/entities/pods.go13
-rw-r--r--pkg/domain/entities/types.go7
-rw-r--r--pkg/domain/infra/abi/containers.go10
-rw-r--r--pkg/domain/infra/abi/healthcheck.go26
-rw-r--r--pkg/domain/infra/abi/images.go243
-rw-r--r--pkg/domain/infra/abi/pods.go59
-rw-r--r--pkg/domain/infra/tunnel/containers.go18
-rw-r--r--pkg/domain/infra/tunnel/healthcheck.go13
-rw-r--r--pkg/domain/infra/tunnel/images.go103
-rw-r--r--pkg/domain/infra/tunnel/pods.go4
-rw-r--r--pkg/spec/spec.go12
-rw-r--r--pkg/systemd/generate/systemdgen.go2
-rw-r--r--pkg/varlink/generate.go3
-rw-r--r--pkg/varlink/io.podman.varlink (renamed from cmd/podman/varlink/io.podman.varlink)0
-rw-r--r--pkg/varlinkapi/attach.go4
-rw-r--r--pkg/varlinkapi/config.go2
-rw-r--r--pkg/varlinkapi/containers.go4
-rw-r--r--pkg/varlinkapi/containers_create.go2
-rw-r--r--pkg/varlinkapi/events.go2
-rw-r--r--pkg/varlinkapi/generate.go2
-rw-r--r--pkg/varlinkapi/images.go2
-rw-r--r--pkg/varlinkapi/mount.go4
-rw-r--r--pkg/varlinkapi/pods.go2
-rw-r--r--pkg/varlinkapi/remote_client.go2
-rw-r--r--pkg/varlinkapi/system.go2
-rw-r--r--pkg/varlinkapi/transfers.go2
-rw-r--r--pkg/varlinkapi/util.go2
-rw-r--r--pkg/varlinkapi/volumes.go2
-rw-r--r--test/e2e/build/basicalpine/Containerfile.path2
-rw-r--r--test/e2e/build_test.go20
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/exec_test.go12
-rw-r--r--test/e2e/generate_systemd_test.go14
-rw-r--r--test/e2e/run_volume_test.go86
-rw-r--r--test/endpoint/endpoint.go2
-rw-r--r--test/endpoint/setup.go14
-rw-r--r--utils/utils.go1
-rw-r--r--vendor/github.com/containers/buildah/.gitignore1
-rw-r--r--vendor/github.com/containers/buildah/CHANGELOG.md14
-rw-r--r--vendor/github.com/containers/buildah/buildah.go2
-rw-r--r--vendor/github.com/containers/buildah/changelog.txt14
-rw-r--r--vendor/github.com/containers/buildah/chroot/run.go2
-rw-r--r--vendor/github.com/containers/buildah/common.go2
-rw-r--r--vendor/github.com/containers/buildah/go.mod14
-rw-r--r--vendor/github.com/containers/buildah/go.sum62
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/executor.go100
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/stage_executor.go103
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/util.go8
-rw-r--r--vendor/github.com/containers/buildah/info.go2
-rw-r--r--vendor/github.com/containers/buildah/install.md2
-rw-r--r--vendor/github.com/containers/buildah/pkg/overlay/overlay.go2
-rw-r--r--vendor/github.com/containers/buildah/pkg/parse/parse_unix.go2
-rw-r--r--vendor/github.com/containers/buildah/run_linux.go6
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor.go21
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go289
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go49
-rw-r--r--vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go31
-rw-r--r--vendor/github.com/containers/common/pkg/capabilities/capabilities.go4
-rw-r--r--vendor/github.com/containers/common/pkg/cgroupv2/cgroups_linux.go27
-rw-r--r--vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go8
-rw-r--r--vendor/github.com/containers/common/pkg/config/config.go36
-rw-r--r--vendor/github.com/containers/common/pkg/config/containers.conf15
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go136
-rw-r--r--vendor/github.com/containers/common/pkg/config/default_linux.go14
-rw-r--r--vendor/github.com/containers/common/pkg/config/libpodConfig.go15
-rw-r--r--vendor/github.com/containers/common/pkg/config/nosystemd.go11
-rw-r--r--vendor/github.com/containers/common/pkg/config/systemd.go10
-rw-r--r--vendor/github.com/containers/common/pkg/config/util_supported.go2
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/README.md1
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/numcpu.go12
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go44
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go37
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo.go153
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go261
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go122
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go9
-rw-r--r--vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go9
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/go.mod4
-rw-r--r--vendor/github.com/containers/storage/go.sum36
-rw-r--r--vendor/github.com/containers/storage/layers.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/config/config.go12
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/getenv_linux_cgo.go (renamed from vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go)0
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/getenv_linux_nocgo.go (renamed from vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go)0
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare.c (renamed from vendor/github.com/containers/common/pkg/unshare/unshare.c)4
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare.go (renamed from vendor/github.com/containers/common/pkg/unshare/unshare.go)0
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare_cgo.go (renamed from vendor/github.com/containers/common/pkg/unshare/unshare_cgo.go)0
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare_gccgo.go (renamed from vendor/github.com/containers/common/pkg/unshare/unshare_gccgo.go)0
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go (renamed from vendor/github.com/containers/common/pkg/unshare/unshare_linux.go)6
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go (renamed from vendor/github.com/containers/common/pkg/unshare/unshare_unsupported.go)0
-rw-r--r--vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported_cgo.go10
-rw-r--r--vendor/github.com/containers/storage/storage.conf18
-rw-r--r--vendor/github.com/containers/storage/store.go131
-rw-r--r--vendor/github.com/containers/storage/userns.go457
-rw-r--r--vendor/github.com/openshift/imagebuilder/builder.go55
-rw-r--r--vendor/github.com/openshift/imagebuilder/dispatchers.go14
-rw-r--r--vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go3
-rw-r--r--vendor/modules.txt17
182 files changed, 4819 insertions, 625 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 0770e0702..01cecd5a8 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -39,7 +39,7 @@ env:
UBUNTU_NAME: "ubuntu-19"
PRIOR_UBUNTU_NAME: "ubuntu-18"
- _BUILT_IMAGE_SUFFIX: "libpod-5633729662025728"
+ _BUILT_IMAGE_SUFFIX: "libpod-6465271544152064"
FEDORA_CACHE_IMAGE_NAME: "${FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "${PRIOR_FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "${UBUNTU_NAME}-${_BUILT_IMAGE_SUFFIX}"
@@ -139,8 +139,6 @@ gating_task:
- '/usr/local/bin/entrypoint.sh clean podman-remote |& ${TIMESTAMP}'
- '/usr/local/bin/entrypoint.sh clean podman xref_helpmsgs_manpages BUILDTAGS="exclude_graphdriver_devicemapper selinux seccomp" |& ${TIMESTAMP}'
- '/usr/local/bin/entrypoint.sh local-cross |& ${TIMESTAMP}'
- - '/usr/local/bin/entrypoint.sh podman-remote-darwin |& ${TIMESTAMP}'
- - '/usr/local/bin/entrypoint.sh podman-remote-windows |& ${TIMESTAMP}'
# Verify some aspects of ci/related scripts
ci_script:
diff --git a/.gitignore b/.gitignore
index ea154fe5d..c1742a27e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
__pycache__
/cmd/podman/varlink/ioprojectatomicpodman.go
/cmd/podman/varlink/iopodman.go
+/pkg/varlink/iopodman.go
.gopathok
release.txt
podman-remote*.zip
diff --git a/Makefile b/Makefile
index 7e5a564a0..92e0f1539 100644
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ endif
BUILDTAGS_CROSS ?= containers_image_openpgp exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_overlay
ifneq (,$(findstring varlink,$(BUILDTAGS)))
- PODMAN_VARLINK_DEPENDENCIES = cmd/podman/varlink/iopodman.go
+ PODMAN_VARLINK_DEPENDENCIES = pkg/varlink/iopodman.go
endif
CONTAINER_RUNTIME := $(shell command -v podman 2> /dev/null || echo docker)
OCI_RUNTIME ?= ""
@@ -237,7 +237,7 @@ clean: ## Clean artifacts
test/checkseccomp/checkseccomp \
test/goecho/goecho \
test/testdata/redis-image \
- cmd/podman/varlink/iopodman.go \
+ pkg/varlink/iopodman.go \
libpod/container_ffjson.go \
libpod/pod_ffjson.go \
libpod/container_easyjson.go \
@@ -597,7 +597,7 @@ endef
fi
.PHONY: varlink_generate
-varlink_generate: .gopathok cmd/podman/varlink/iopodman.go ## Generate varlink
+varlink_generate: .gopathok pkg/varlink/iopodman.go ## Generate varlink
.PHONY: varlink_api_generate
varlink_api_generate: .gopathok API.md
@@ -609,13 +609,13 @@ install.libseccomp.sudo:
cd ../../seccomp/libseccomp && git checkout --detach $(LIBSECCOMP_COMMIT) && ./autogen.sh && ./configure --prefix=/usr && make all && make install
-cmd/podman/varlink/iopodman.go: .gopathok cmd/podman/varlink/io.podman.varlink
+pkg/varlink/iopodman.go: .gopathok pkg/varlink/io.podman.varlink
ifneq (,$(findstring Linux,$(shell uname -s)))
# Only generate the varlink code on Linux (see issue #4814).
- GO111MODULE=off $(GO) generate ./cmd/podman/varlink/...
+ GO111MODULE=off $(GO) generate ./pkg/varlink/...
endif
-API.md: cmd/podman/varlink/io.podman.varlink
+API.md: pkg/varlink/io.podman.varlink
$(GO) generate ./docs/...
.PHONY: validate.completions
diff --git a/README.md b/README.md
index ea10454be..25d1432e0 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ and
tracking system.
There is also a [mailing list](https://lists.podman.io/archives/) at `lists.podman.io`.
-You can subscribe by sending a message to `podman@lists.podman.io` with the subject `subscribe`.
+You can subscribe by sending a message to `podman-join@lists.podman.io` with the subject `subscribe`.
## Rootless
Podman can be easily run as a normal user, without requiring a setuid binary.
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index faf292ea0..99f389799 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -174,7 +174,7 @@ type GenerateSystemdValues struct {
New bool
Files bool
RestartPolicy string
- StopTimeout int
+ StopTimeout uint
}
type HistoryValues struct {
diff --git a/cmd/podman/errors_remote.go b/cmd/podman/errors_remote.go
index 378f9398f..4b543ccd5 100644
--- a/cmd/podman/errors_remote.go
+++ b/cmd/podman/errors_remote.go
@@ -8,8 +8,8 @@ import (
"os/exec"
"syscall"
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod/define"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
diff --git a/cmd/podman/generate_systemd.go b/cmd/podman/generate_systemd.go
index a9775f9cb..fd0d13d78 100644
--- a/cmd/podman/generate_systemd.go
+++ b/cmd/podman/generate_systemd.go
@@ -43,9 +43,10 @@ func init() {
if !remoteclient {
flags.BoolVarP(&containerSystemdCommand.Files, "files", "f", false, "generate files instead of printing to stdout")
}
- flags.IntVarP(&containerSystemdCommand.StopTimeout, "timeout", "t", -1, "stop timeout override")
+ flags.UintVarP(&containerSystemdCommand.StopTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "stop timeout override")
flags.StringVar(&containerSystemdCommand.RestartPolicy, "restart-policy", "on-failure", "applicable systemd restart-policy")
flags.BoolVarP(&containerSystemdCommand.New, "new", "", false, "create a new container instead of starting an existing one")
+ flags.SetNormalizeFunc(aliasFlags)
}
func generateSystemdCmd(c *cliconfig.GenerateSystemdValues) error {
@@ -55,11 +56,6 @@ func generateSystemdCmd(c *cliconfig.GenerateSystemdValues) error {
}
defer runtime.DeferredShutdown(false)
- // User input stop timeout must be 0 or greater
- if c.Flag("timeout").Changed && c.StopTimeout < 0 {
- return errors.New("timeout value must be 0 or greater")
- }
-
unit, err := runtime.GenerateSystemd(c)
if err != nil {
return err
diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go
index 7d3951ec4..395731551 100644
--- a/cmd/podman/pod_stop.go
+++ b/cmd/podman/pod_stop.go
@@ -31,7 +31,7 @@ var (
},
Example: `podman pod stop mywebserverpod
podman pod stop --latest
- podman pod stop --timeout 0 490eb 3557fb`,
+ podman pod stop --time 0 490eb 3557fb`,
}
)
@@ -43,7 +43,8 @@ func init() {
flags.BoolVarP(&podStopCommand.All, "all", "a", false, "Stop all running pods")
flags.BoolVarP(&podStopCommand.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
flags.BoolVarP(&podStopCommand.Latest, "latest", "l", false, "Stop the latest pod podman is aware of")
- flags.UintVarP(&podStopCommand.Timeout, "timeout", "t", 0, "Seconds to wait for pod stop before killing the container")
+ flags.UintVarP(&podStopCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for pod stop before killing the container")
+ flags.SetNormalizeFunc(aliasFlags)
markFlagHiddenForRemoteClient("ignore", flags)
markFlagHiddenForRemoteClient("latest", flags)
}
diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go
index a55f83c67..4ee043442 100644
--- a/cmd/podman/restart.go
+++ b/cmd/podman/restart.go
@@ -1,6 +1,8 @@
package main
import (
+ "fmt"
+
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/adapter"
@@ -10,9 +12,9 @@ import (
var (
restartCommand cliconfig.RestartValues
- restartDescription = `Restarts one or more running containers. The container ID or name can be used.
+ restartDescription = fmt.Sprintf(`Restarts one or more running containers. The container ID or name can be used.
- A timeout before forcibly stopping can be set, but defaults to 10 seconds.`
+ A timeout before forcibly stopping can be set, but defaults to %d seconds.`, defaultContainerConfig.Engine.StopTimeout)
_restartCommand = &cobra.Command{
Use: "restart [flags] CONTAINER [CONTAINER...]",
Short: "Restart one or more containers",
@@ -40,10 +42,9 @@ func init() {
flags.BoolVarP(&restartCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&restartCommand.Running, "running", false, "Restart only running containers when --all is used")
flags.UintVarP(&restartCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- flags.UintVar(&restartCommand.Timeout, "timeout", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- markFlagHidden(flags, "timeout")
markFlagHiddenForRemoteClient("latest", flags)
+ flags.SetNormalizeFunc(aliasFlags)
}
func restartCmd(c *cliconfig.RestartValues) error {
diff --git a/cmd/podman/service.go b/cmd/podman/service.go
index 7606e3009..bcb37eac5 100644
--- a/cmd/podman/service.go
+++ b/cmd/podman/service.go
@@ -12,13 +12,13 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter"
api "github.com/containers/libpod/pkg/api/server"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/systemd"
"github.com/containers/libpod/pkg/util"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/pkg/varlinkapi"
"github.com/containers/libpod/version"
"github.com/pkg/errors"
diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go
index 5fa8d6c0b..68a36d967 100644
--- a/cmd/podman/shared/create.go
+++ b/cmd/podman/shared/create.go
@@ -538,14 +538,16 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
- // env overrides any previous variables
- cmdlineEnv := c.StringSlice("env")
- if len(cmdlineEnv) > 0 {
- parsedEnv, err := envLib.ParseSlice(cmdlineEnv)
- if err != nil {
- return nil, err
+ if c.IsSet("env") {
+ // env overrides any previous variables
+ cmdlineEnv := c.StringSlice("env")
+ if len(cmdlineEnv) > 0 {
+ parsedEnv, err := envLib.ParseSlice(cmdlineEnv)
+ if err != nil {
+ return nil, err
+ }
+ env = envLib.Join(env, parsedEnv)
}
- env = envLib.Join(env, parsedEnv)
}
// LABEL VARIABLES
@@ -636,10 +638,13 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
if err != nil {
return nil, errors.Wrapf(err, "unable to translate --shm-size")
}
- // Verify the additional hosts are in correct format
- for _, host := range c.StringSlice("add-host") {
- if _, err := parse.ValidateExtraHost(host); err != nil {
- return nil, err
+
+ if c.IsSet("add-host") {
+ // Verify the additional hosts are in correct format
+ for _, host := range c.StringSlice("add-host") {
+ if _, err := parse.ValidateExtraHost(host); err != nil {
+ return nil, err
+ }
}
}
diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go
index d2b048025..82594fb40 100644
--- a/cmd/podman/shared/intermediate_varlink.go
+++ b/cmd/podman/shared/intermediate_varlink.go
@@ -4,8 +4,8 @@ package shared
import (
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/rootless"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/pkg/errors"
)
diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go
index 383a1f61c..5033218e4 100644
--- a/cmd/podman/stop.go
+++ b/cmd/podman/stop.go
@@ -1,6 +1,8 @@
package main
import (
+ "fmt"
+
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
"github.com/opentracing/opentracing-go"
@@ -10,9 +12,9 @@ import (
var (
stopCommand cliconfig.StopValues
- stopDescription = `Stops one or more running containers. The container name or ID can be used.
+ stopDescription = fmt.Sprintf(`Stops one or more running containers. The container name or ID can be used.
- A timeout to forcibly stop the container can also be set but defaults to 10 seconds otherwise.`
+ A timeout to forcibly stop the container can also be set but defaults to %d seconds otherwise.`, defaultContainerConfig.Engine.StopTimeout)
_stopCommand = &cobra.Command{
Use: "stop [flags] CONTAINER [CONTAINER...]",
Short: "Stop one or more containers",
@@ -42,19 +44,14 @@ func init() {
flags.StringArrayVarP(&stopCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file")
flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.UintVarP(&stopCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- flags.UintVar(&stopCommand.Timeout, "timeout", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- markFlagHidden(flags, "timeout")
markFlagHiddenForRemoteClient("latest", flags)
markFlagHiddenForRemoteClient("cidfile", flags)
markFlagHiddenForRemoteClient("ignore", flags)
+ flags.SetNormalizeFunc(aliasFlags)
}
// stopCmd stops a container or containers
func stopCmd(c *cliconfig.StopValues) error {
- if c.Flag("timeout").Changed && c.Flag("time").Changed {
- return errors.New("the --timeout and --time flags are mutually exclusive")
- }
-
if c.Bool("trace") {
span, _ := opentracing.StartSpanFromContext(Ctx, "stopCmd")
defer span.Finish()
diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go
index 44e65b223..938a3f41e 100644
--- a/cmd/podman/utils.go
+++ b/cmd/podman/utils.go
@@ -63,6 +63,8 @@ func aliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName {
name = "health-timeout"
case "net":
name = "network"
+ case "timeout":
+ name = "time"
}
return pflag.NormalizedName(name)
}
diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go
index 047d94fc2..20334ec96 100644
--- a/cmd/podman/varlink.go
+++ b/cmd/podman/varlink.go
@@ -10,10 +10,10 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/pkg/varlinkapi"
"github.com/containers/libpod/version"
"github.com/pkg/errors"
diff --git a/cmd/podman/varlink/generate.go b/cmd/podman/varlink/generate.go
deleted file mode 100644
index 2fa2d8e23..000000000
--- a/cmd/podman/varlink/generate.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package iopodman
-
-//go:generate go run ../../../vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go io.podman.varlink
diff --git a/cmd/podmanV2/Makefile b/cmd/podmanV2/Makefile
index 147a78d9c..f2f7bd73c 100644
--- a/cmd/podmanV2/Makefile
+++ b/cmd/podmanV2/Makefile
@@ -1,2 +1,2 @@
all:
- GO111MODULE=off go build -tags 'ABISupport'
+ GO111MODULE=off go build -tags 'ABISupport systemd'
diff --git a/cmd/podmanV2/common/inspect.go b/cmd/podmanV2/common/inspect.go
new file mode 100644
index 000000000..dfc6fe679
--- /dev/null
+++ b/cmd/podmanV2/common/inspect.go
@@ -0,0 +1,18 @@
+package common
+
+import (
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+// AddInspectFlagSet takes a command and adds the inspect flags and returns an InspectOptions object
+// Since this cannot live in `package main` it lives here until a better home is found
+func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions {
+ opts := entities.InspectOptions{}
+
+ flags := cmd.Flags()
+ flags.BoolVarP(&opts.Size, "size", "s", false, "Display total file size")
+ flags.StringVarP(&opts.Format, "format", "f", "", "Change the output format to a Go template")
+
+ return &opts
+}
diff --git a/cmd/podmanV2/containers/export.go b/cmd/podmanV2/containers/export.go
new file mode 100644
index 000000000..b93b60878
--- /dev/null
+++ b/cmd/podmanV2/containers/export.go
@@ -0,0 +1,57 @@
+package containers
+
+import (
+ "context"
+ "os"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+var (
+ exportDescription = "Exports container's filesystem contents as a tar archive" +
+ " and saves it on the local machine."
+
+ exportCommand = &cobra.Command{
+ Use: "export [flags] CONTAINER",
+ Short: "Export container's filesystem contents as a tar archive",
+ Long: exportDescription,
+ PersistentPreRunE: preRunE,
+ RunE: export,
+ Args: cobra.ExactArgs(1),
+ Example: `podman export ctrID > myCtr.tar
+ podman export --output="myCtr.tar" ctrID`,
+ }
+)
+
+var (
+ exportOpts entities.ContainerExportOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: exportCommand,
+ })
+ exportCommand.SetHelpTemplate(registry.HelpTemplate())
+ exportCommand.SetUsageTemplate(registry.UsageTemplate())
+ flags := exportCommand.Flags()
+ flags.StringVarP(&exportOpts.Output, "output", "o", "", "Write to a specified file (default: stdout, which must be redirected)")
+}
+
+func export(cmd *cobra.Command, args []string) error {
+ if len(exportOpts.Output) == 0 {
+ file := os.Stdout
+ if terminal.IsTerminal(int(file.Fd())) {
+ return errors.Errorf("refusing to export to terminal. Use -o flag or redirect")
+ }
+ exportOpts.Output = "/dev/stdout"
+ } else if err := parse.ValidateFileName(exportOpts.Output); err != nil {
+ return err
+ }
+ return registry.ContainerEngine().ContainerExport(context.Background(), args[0], exportOpts)
+}
diff --git a/cmd/podmanV2/containers/inspect.go b/cmd/podmanV2/containers/inspect.go
index 648289f0b..3147426cb 100644
--- a/cmd/podmanV2/containers/inspect.go
+++ b/cmd/podmanV2/containers/inspect.go
@@ -7,9 +7,11 @@ import (
"strings"
"text/template"
+ "github.com/containers/libpod/cmd/podmanV2/common"
"github.com/containers/libpod/cmd/podmanV2/registry"
+
"github.com/containers/libpod/pkg/domain/entities"
- jsoniter "github.com/json-iterator/go"
+ json "github.com/json-iterator/go"
"github.com/spf13/cobra"
)
@@ -24,10 +26,7 @@ var (
Example: `podman container inspect myCtr
podman container inspect -l --format '{{.Id}} {{.Config.Labels}}'`,
}
-)
-
-var (
- inspectOptions entities.ContainerInspectOptions
+ inspectOpts *entities.InspectOptions
)
func init() {
@@ -36,29 +35,29 @@ func init() {
Command: inspectCmd,
Parent: containerCmd,
})
+ inspectOpts = common.AddInspectFlagSet(inspectCmd)
flags := inspectCmd.Flags()
- flags.StringVarP(&inspectOptions.Format, "format", "f", "", "Change the output format to a Go template")
- flags.BoolVarP(&inspectOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- flags.BoolVarP(&inspectOptions.Size, "size", "s", false, "Display total file size")
- if registry.IsRemote() {
- _ = flags.MarkHidden("latest")
+
+ if !registry.IsRemote() {
+ flags.BoolVarP(&inspectOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
}
+
}
func inspect(cmd *cobra.Command, args []string) error {
- responses, err := registry.ContainerEngine().ContainerInspect(context.Background(), args, inspectOptions)
+ responses, err := registry.ContainerEngine().ContainerInspect(context.Background(), args, *inspectOpts)
if err != nil {
return err
}
- if inspectOptions.Format == "" {
- b, err := jsoniter.MarshalIndent(responses, "", " ")
+ if inspectOpts.Format == "" {
+ b, err := json.MarshalIndent(responses, "", " ")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
}
- format := inspectOptions.Format
+ format := inspectOpts.Format
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
@@ -73,3 +72,8 @@ func inspect(cmd *cobra.Command, args []string) error {
}
return nil
}
+
+func Inspect(cmd *cobra.Command, args []string, options *entities.InspectOptions) error {
+ inspectOpts = options
+ return inspect(cmd, args)
+}
diff --git a/cmd/podmanV2/containers/restart.go b/cmd/podmanV2/containers/restart.go
index 1f1bb11fa..5f1d3fe51 100644
--- a/cmd/podmanV2/containers/restart.go
+++ b/cmd/podmanV2/containers/restart.go
@@ -14,9 +14,10 @@ import (
)
var (
- restartDescription = `Restarts one or more running containers. The container ID or name can be used.
+ restartDescription = fmt.Sprintf(`Restarts one or more running containers. The container ID or name can be used.
+
+ A timeout before forcibly stopping can be set, but defaults to %d seconds.`, defaultContainerConfig.Engine.StopTimeout)
- A timeout before forcibly stopping can be set, but defaults to 10 seconds.`
restartCommand = &cobra.Command{
Use: "restart [flags] CONTAINER [CONTAINER...]",
Short: "Restart one or more containers",
@@ -46,11 +47,11 @@ func init() {
flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all non-running containers")
flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&restartOptions.Running, "running", false, "Restart only running containers when --all is used")
- flags.UintVarP(&restartTimeout, "timeout", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- flags.UintVar(&restartTimeout, "time", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
+ flags.UintVarP(&restartTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
if registry.IsRemote() {
_ = flags.MarkHidden("latest")
}
+ flags.SetNormalizeFunc(utils.AliasFlags)
}
func restart(cmd *cobra.Command, args []string) error {
@@ -61,7 +62,7 @@ func restart(cmd *cobra.Command, args []string) error {
return errors.Wrapf(define.ErrInvalidArg, "you must provide at least one container name or ID")
}
- if cmd.Flag("timeout").Changed || cmd.Flag("time").Changed {
+ if cmd.Flag("time").Changed {
restartOptions.Timeout = &restartTimeout
}
responses, err := registry.ContainerEngine().ContainerRestart(context.Background(), args, restartOptions)
diff --git a/cmd/podmanV2/containers/stop.go b/cmd/podmanV2/containers/stop.go
index 9a106e8fe..d6f31352f 100644
--- a/cmd/podmanV2/containers/stop.go
+++ b/cmd/podmanV2/containers/stop.go
@@ -8,14 +8,13 @@ import (
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/cmd/podmanV2/utils"
"github.com/containers/libpod/pkg/domain/entities"
- "github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
- stopDescription = `Stops one or more running containers. The container name or ID can be used.
+ stopDescription = fmt.Sprintf(`Stops one or more running containers. The container name or ID can be used.
- A timeout to forcibly stop the container can also be set but defaults to 10 seconds otherwise.`
+ A timeout to forcibly stop the container can also be set but defaults to %d seconds otherwise.`, defaultContainerConfig.Engine.StopTimeout)
stopCommand = &cobra.Command{
Use: "stop [flags] CONTAINER [CONTAINER...]",
Short: "Stop one or more containers",
@@ -27,7 +26,7 @@ var (
},
Example: `podman stop ctrID
podman stop --latest
- podman stop --timeout 2 mywebserver 6e534f14da9d`,
+ podman stop --time 2 mywebserver 6e534f14da9d`,
}
)
@@ -46,24 +45,21 @@ func init() {
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing")
flags.StringArrayVarP(&stopOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file")
flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- flags.UintVar(&stopTimeout, "time", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
- flags.UintVarP(&stopTimeout, "timeout", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
+ flags.UintVarP(&stopTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
if registry.EngineOptions.EngineMode == entities.ABIMode {
_ = flags.MarkHidden("latest")
_ = flags.MarkHidden("cidfile")
_ = flags.MarkHidden("ignore")
}
+ flags.SetNormalizeFunc(utils.AliasFlags)
}
func stop(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
- if cmd.Flag("timeout").Changed && cmd.Flag("time").Changed {
- return errors.New("the --timeout and --time flags are mutually exclusive")
- }
stopOptions.Timeout = defaultContainerConfig.Engine.StopTimeout
- if cmd.Flag("timeout").Changed || cmd.Flag("time").Changed {
+ if cmd.Flag("time").Changed {
stopOptions.Timeout = stopTimeout
}
diff --git a/cmd/podmanV2/healthcheck/healthcheck.go b/cmd/podmanV2/healthcheck/healthcheck.go
new file mode 100644
index 000000000..2af398ff0
--- /dev/null
+++ b/cmd/podmanV2/healthcheck/healthcheck.go
@@ -0,0 +1,33 @@
+package healthcheck
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ // Command: healthcheck
+ healthCmd = &cobra.Command{
+ Use: "healthcheck",
+ Short: "Manage Healthcheck",
+ Long: "Manage Healthcheck",
+ TraverseChildren: true,
+ PersistentPreRunE: preRunE,
+ RunE: registry.SubCommandExists,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: healthCmd,
+ })
+ healthCmd.SetHelpTemplate(registry.HelpTemplate())
+ healthCmd.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func preRunE(cmd *cobra.Command, args []string) error {
+ _, err := registry.NewContainerEngine(cmd, args)
+ return err
+}
diff --git a/cmd/podmanV2/healthcheck/run.go b/cmd/podmanV2/healthcheck/run.go
new file mode 100644
index 000000000..bb2962eaf
--- /dev/null
+++ b/cmd/podmanV2/healthcheck/run.go
@@ -0,0 +1,42 @@
+package healthcheck
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ healthcheckRunDescription = "run the health check of a container"
+ healthcheckrunCommand = &cobra.Command{
+ Use: "run [flags] CONTAINER",
+ Short: "run the health check of a container",
+ Long: healthcheckRunDescription,
+ Example: `podman healthcheck run mywebapp`,
+ RunE: run,
+ Args: cobra.ExactArgs(1),
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: healthcheckrunCommand,
+ Parent: healthCmd,
+ })
+}
+
+func run(cmd *cobra.Command, args []string) error {
+ response, err := registry.ContainerEngine().HealthCheckRun(context.Background(), args[0], entities.HealthCheckOptions{})
+ if err != nil {
+ return err
+ }
+ if response.Status == "unhealthy" {
+ registry.SetExitCode(1)
+ }
+ fmt.Println(response.Status)
+ return err
+}
diff --git a/cmd/podmanV2/images/import.go b/cmd/podmanV2/images/import.go
new file mode 100644
index 000000000..09a15585f
--- /dev/null
+++ b/cmd/podmanV2/images/import.go
@@ -0,0 +1,87 @@
+package images
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/parse"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/hashicorp/go-multierror"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ importDescription = `Create a container image from the contents of the specified tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz).
+
+ Note remote tar balls can be specified, via web address.
+ Optionally tag the image. You can specify the instructions using the --change option.`
+ importCommand = &cobra.Command{
+ Use: "import [flags] PATH [REFERENCE]",
+ Short: "Import a tarball to create a filesystem image",
+ Long: importDescription,
+ RunE: importCon,
+ PersistentPreRunE: preRunE,
+ Example: `podman import http://example.com/ctr.tar url-image
+ cat ctr.tar | podman -q import --message "importing the ctr.tar tarball" - image-imported
+ cat ctr.tar | podman import -`,
+ }
+)
+
+var (
+ importOpts entities.ImageImportOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: importCommand,
+ })
+
+ importCommand.SetHelpTemplate(registry.HelpTemplate())
+ importCommand.SetUsageTemplate(registry.UsageTemplate())
+ flags := importCommand.Flags()
+ flags.StringArrayVarP(&importOpts.Changes, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR")
+ flags.StringVarP(&importOpts.Message, "message", "m", "", "Set commit message for imported image")
+ flags.BoolVarP(&importOpts.Quiet, "quiet", "q", false, "Suppress output")
+}
+
+func importCon(cmd *cobra.Command, args []string) error {
+ var (
+ source string
+ reference string
+ )
+ switch len(args) {
+ case 0:
+ return errors.Errorf("need to give the path to the tarball, or must specify a tarball of '-' for stdin")
+ case 1:
+ source = args[0]
+ case 2:
+ source = args[0]
+ // TODO when save is merged, we need to process reference
+ // like it is done in there or we end up with docker.io prepends
+ // instead of the localhost ones
+ reference = args[1]
+ default:
+ return errors.Errorf("too many arguments. Usage TARBALL [REFERENCE]")
+ }
+ errFileName := parse.ValidateFileName(source)
+ errURL := parse.ValidURL(source)
+ if errURL == nil {
+ importOpts.SourceIsURL = true
+ }
+ if errFileName != nil && errURL != nil {
+ return multierror.Append(errFileName, errURL)
+ }
+
+ importOpts.Source = source
+ importOpts.Reference = reference
+
+ response, err := registry.ImageEngine().Import(context.Background(), importOpts)
+ if err != nil {
+ return err
+ }
+ fmt.Println(response.Id)
+ return nil
+}
diff --git a/cmd/podmanV2/images/inspect.go b/cmd/podmanV2/images/inspect.go
index f8fd44571..d7f6b0ee1 100644
--- a/cmd/podmanV2/images/inspect.go
+++ b/cmd/podmanV2/images/inspect.go
@@ -1,71 +1,44 @@
package images
import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "os"
"strings"
+ "text/tabwriter"
+ "text/template"
"github.com/containers/buildah/pkg/formats"
+ "github.com/containers/libpod/cmd/podmanV2/common"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/pkg/domain/entities"
- "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
- inspectOpts = entities.ImageInspectOptions{}
-
// Command: podman image _inspect_
inspectCmd = &cobra.Command{
Use: "inspect [flags] IMAGE",
Short: "Display the configuration of an image",
Long: `Displays the low-level information on an image identified by name or ID.`,
- PreRunE: populateEngines,
- RunE: imageInspect,
+ RunE: inspect,
Example: `podman image inspect alpine`,
}
-
- containerEngine entities.ContainerEngine
+ inspectOpts *entities.InspectOptions
)
-// Inspect is unique in that it needs both an ImageEngine and a ContainerEngine
-func populateEngines(cmd *cobra.Command, args []string) (err error) {
- // Populate registry.ImageEngine
- err = preRunE(cmd, args)
- if err != nil {
- return
- }
-
- // Populate registry.ContainerEngine
- containerEngine, err = registry.NewContainerEngine(cmd, args)
- return
-}
-
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: inspectCmd,
Parent: imageCmd,
})
-
- flags := inspectCmd.Flags()
- flags.BoolVarP(&inspectOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- flags.BoolVarP(&inspectOpts.Size, "size", "s", false, "Display total file size")
- flags.StringVarP(&inspectOpts.Format, "format", "f", "", "Change the output format to a Go template")
-
- if registry.EngineOptions.EngineMode == entities.ABIMode {
- // TODO: This is the same as V1. We could skip creating the flag altogether in V2...
- _ = flags.MarkHidden("latest")
- }
+ inspectOpts = common.AddInspectFlagSet(inspectCmd)
}
-const (
- inspectTypeContainer = "container"
- inspectTypeImage = "image"
- inspectAll = "all"
-)
-
-func imageInspect(cmd *cobra.Command, args []string) error {
- inspectType := inspectTypeImage
+func inspect(cmd *cobra.Command, args []string) error {
latestContainer := inspectOpts.Latest
if len(args) == 0 && !latestContainer {
@@ -76,49 +49,61 @@ func imageInspect(cmd *cobra.Command, args []string) error {
return errors.Errorf("you cannot provide additional arguments with --latest")
}
- if !util.StringInSlice(inspectType, []string{inspectTypeContainer, inspectTypeImage, inspectAll}) {
- return errors.Errorf("the only recognized types are %q, %q, and %q", inspectTypeContainer, inspectTypeImage, inspectAll)
+ results, err := registry.ImageEngine().Inspect(context.Background(), args, *inspectOpts)
+ if err != nil {
+ return err
}
- outputFormat := inspectOpts.Format
- if strings.Contains(outputFormat, "{{.Id}}") {
- outputFormat = strings.Replace(outputFormat, "{{.Id}}", formats.IDString, -1)
- }
- // These fields were renamed, so we need to provide backward compat for
- // the old names.
- if strings.Contains(outputFormat, ".Src") {
- outputFormat = strings.Replace(outputFormat, ".Src", ".Source", -1)
+ if len(results.Images) > 0 {
+ if inspectOpts.Format == "" {
+ buf, err := json.MarshalIndent(results.Images, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(buf))
+
+ for id, e := range results.Errors {
+ fmt.Fprintf(os.Stderr, "%s: %s\n", id, e.Error())
+ }
+ return nil
+ }
+
+ row := inspectFormat(inspectOpts.Format)
+ format := "{{range . }}" + row + "{{end}}"
+ tmpl, err := template.New("inspect").Parse(format)
+ if err != nil {
+ return err
+ }
+
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ defer func() { _ = w.Flush() }()
+ err = tmpl.Execute(w, results)
+ if err != nil {
+ return err
+ }
}
- if strings.Contains(outputFormat, ".Dst") {
- outputFormat = strings.Replace(outputFormat, ".Dst", ".Destination", -1)
- }
- if strings.Contains(outputFormat, ".ImageID") {
- outputFormat = strings.Replace(outputFormat, ".ImageID", ".Image", -1)
+
+ for id, e := range results.Errors {
+ fmt.Fprintf(os.Stderr, "%s: %s\n", id, e.Error())
}
- _ = outputFormat
- // if latestContainer {
- // lc, err := ctnrRuntime.GetLatestContainer()
- // if err != nil {
- // return err
- // }
- // args = append(args, lc.ID())
- // inspectType = inspectTypeContainer
- // }
-
- // inspectedObjects, iterateErr := iterateInput(getContext(), c.Size, args, runtime, inspectType)
- // if iterateErr != nil {
- // return iterateErr
- // }
- //
- // var out formats.Writer
- // if outputFormat != "" && outputFormat != formats.JSONString {
- // // template
- // out = formats.StdoutTemplateArray{Output: inspectedObjects, Template: outputFormat}
- // } else {
- // // default is json output
- // out = formats.JSONStructArray{Output: inspectedObjects}
- // }
- //
- // return out.Out()
return nil
}
+
+func inspectFormat(row string) string {
+ r := strings.NewReplacer("{{.Id}}", formats.IDString,
+ ".Src", ".Source",
+ ".Dst", ".Destination",
+ ".ImageID", ".Image",
+ )
+ row = r.Replace(row)
+
+ if !strings.HasSuffix(row, "\n") {
+ row += "\n"
+ }
+ return row
+}
+
+func Inspect(cmd *cobra.Command, args []string, options *entities.InspectOptions) error {
+ inspectOpts = options
+ return inspect(cmd, args)
+}
diff --git a/cmd/podmanV2/images/list.go b/cmd/podmanV2/images/list.go
index 9a5b47299..2d6cb3596 100644
--- a/cmd/podmanV2/images/list.go
+++ b/cmd/podmanV2/images/list.go
@@ -152,7 +152,7 @@ func writeTemplate(imageS []*entities.ImageSummary, err error) error {
hdr, row := imageListFormat(listFlag)
format := hdr + "{{range . }}" + row + "{{end}}"
- tmpl := template.Must(template.New("report").Funcs(report.PodmanTemplateFuncs()).Parse(format))
+ tmpl := template.Must(template.New("list").Funcs(report.PodmanTemplateFuncs()).Parse(format))
w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
defer w.Flush()
return tmpl.Execute(w, imgs)
diff --git a/cmd/podmanV2/images/load.go b/cmd/podmanV2/images/load.go
new file mode 100644
index 000000000..f60dc4908
--- /dev/null
+++ b/cmd/podmanV2/images/load.go
@@ -0,0 +1,61 @@
+package images
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ loadDescription = "Loads an image from a locally stored archive (tar file) into container storage."
+ loadCommand = &cobra.Command{
+ Use: "load [flags] [NAME[:TAG]]",
+ Short: "Load an image from container archive",
+ Long: loadDescription,
+ RunE: load,
+ Args: cobra.MaximumNArgs(1),
+ PersistentPreRunE: preRunE,
+ }
+)
+
+var (
+ loadOpts entities.ImageLoadOptions
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: loadCommand,
+ })
+
+ loadCommand.SetHelpTemplate(registry.HelpTemplate())
+ loadCommand.SetUsageTemplate(registry.UsageTemplate())
+ flags := loadCommand.Flags()
+ flags.StringVarP(&loadOpts.Input, "input", "i", "", "Read from specified archive file (default: stdin)")
+ flags.BoolVarP(&loadOpts.Quiet, "quiet", "q", false, "Suppress the output")
+ flags.StringVar(&loadOpts.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("signature-policy")
+ }
+
+}
+
+func load(cmd *cobra.Command, args []string) error {
+ if len(args) > 0 {
+ repo, err := image.NormalizedTag(args[0])
+ if err != nil {
+ return err
+ }
+ loadOpts.Name = repo.Name()
+ }
+ response, err := registry.ImageEngine().Load(context.Background(), loadOpts)
+ if err != nil {
+ return err
+ }
+ fmt.Println("Loaded image: " + response.Name)
+ return nil
+}
diff --git a/cmd/podmanV2/images/pull.go b/cmd/podmanV2/images/pull.go
new file mode 100644
index 000000000..c7e325409
--- /dev/null
+++ b/cmd/podmanV2/images/pull.go
@@ -0,0 +1,140 @@
+package images
+
+import (
+ "fmt"
+
+ buildahcli "github.com/containers/buildah/pkg/cli"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/opentracing/opentracing-go"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+// pullOptionsWrapper wraps entities.ImagePullOptions and prevents leaking
+// CLI-only fields into the API types.
+type pullOptionsWrapper struct {
+ entities.ImagePullOptions
+ TLSVerifyCLI bool // CLI only
+}
+
+var (
+ pullOptions = pullOptionsWrapper{}
+ pullDescription = `Pulls an image from a registry and stores it locally.
+
+ An image can be pulled by tag or digest. If a tag is not specified, the image with the 'latest' tag is pulled.`
+
+ // Command: podman pull
+ pullCmd = &cobra.Command{
+ Use: "pull [flags] IMAGE",
+ Short: "Pull an image from a registry",
+ Long: pullDescription,
+ PreRunE: preRunE,
+ RunE: imagePull,
+ Example: `podman pull imageName
+ podman pull fedora:latest`,
+ }
+
+ // Command: podman image pull
+ // It's basically a clone of `pullCmd` with the exception of being a
+ // child of the images command.
+ imagesPullCmd = &cobra.Command{
+ Use: pullCmd.Use,
+ Short: pullCmd.Short,
+ Long: pullCmd.Long,
+ PreRunE: pullCmd.PreRunE,
+ RunE: pullCmd.RunE,
+ Example: `podman image pull imageName
+ podman image pull fedora:latest`,
+ }
+)
+
+func init() {
+ // pull
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: pullCmd,
+ })
+
+ pullCmd.SetHelpTemplate(registry.HelpTemplate())
+ pullCmd.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := pullCmd.Flags()
+ pullFlags(flags)
+
+ // images pull
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: imagesPullCmd,
+ Parent: imageCmd,
+ })
+
+ imagesPullCmd.SetHelpTemplate(registry.HelpTemplate())
+ imagesPullCmd.SetUsageTemplate(registry.UsageTemplate())
+ imagesPullFlags := imagesPullCmd.Flags()
+ pullFlags(imagesPullFlags)
+}
+
+// pullFlags set the flags for the pull command.
+func pullFlags(flags *pflag.FlagSet) {
+ flags.BoolVar(&pullOptions.AllTags, "all-tags", false, "All tagged images in the repository will be pulled")
+ flags.StringVar(&pullOptions.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
+ flags.StringVar(&pullOptions.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
+ flags.StringVar(&pullOptions.Credentials, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
+ flags.StringVar(&pullOptions.OverrideArch, "override-arch", "", "Use `ARCH` instead of the architecture of the machine for choosing images")
+ flags.StringVar(&pullOptions.OverrideOS, "override-os", "", "Use `OS` instead of the running OS for choosing images")
+ flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images")
+ flags.StringVar(&pullOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
+ flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("authfile")
+ _ = flags.MarkHidden("cert-dir")
+ _ = flags.MarkHidden("signature-policy")
+ _ = flags.MarkHidden("tls-verify")
+ }
+}
+
+// imagePull is implement the command for pulling images.
+func imagePull(cmd *cobra.Command, args []string) error {
+ // Sanity check input.
+ if len(args) == 0 {
+ return errors.Errorf("an image name must be specified")
+ }
+ if len(args) > 1 {
+ return errors.Errorf("too many arguments. Requires exactly 1")
+ }
+
+ // Start tracing if requested.
+ if cmd.Flags().Changed("trace") {
+ span, _ := opentracing.StartSpanFromContext(registry.GetContext(), "pullCmd")
+ defer span.Finish()
+ }
+
+ pullOptsAPI := pullOptions.ImagePullOptions
+ // TLS verification in c/image is controlled via a `types.OptionalBool`
+ // which allows for distinguishing among set-true, set-false, unspecified
+ // which is important to implement a sane way of dealing with defaults of
+ // boolean CLI flags.
+ if cmd.Flags().Changed("tls-verify") {
+ pullOptsAPI.TLSVerify = types.NewOptionalBool(pullOptions.TLSVerifyCLI)
+ }
+
+ // Let's do all the remaining Yoga in the API to prevent us from
+ // scattering logic across (too) many parts of the code.
+ pullReport, err := registry.ImageEngine().Pull(registry.GetContext(), args[0], pullOptsAPI)
+ if err != nil {
+ return err
+ }
+
+ if len(pullReport.Images) > 1 {
+ fmt.Println("Pulled Images:")
+ }
+ for _, img := range pullReport.Images {
+ fmt.Println(img)
+ }
+
+ return nil
+}
diff --git a/cmd/podmanV2/images/push.go b/cmd/podmanV2/images/push.go
new file mode 100644
index 000000000..82cc0c486
--- /dev/null
+++ b/cmd/podmanV2/images/push.go
@@ -0,0 +1,127 @@
+package images
+
+import (
+ buildahcli "github.com/containers/buildah/pkg/cli"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+// pushOptionsWrapper wraps entities.ImagepushOptions and prevents leaking
+// CLI-only fields into the API types.
+type pushOptionsWrapper struct {
+ entities.ImagePushOptions
+ TLSVerifyCLI bool // CLI only
+}
+
+var (
+ pushOptions = pushOptionsWrapper{}
+ pushDescription = `Pushes a source image to a specified destination.
+
+ The Image "DESTINATION" uses a "transport":"details" format. See podman-push(1) section "DESTINATION" for the expected format.`
+
+ // Command: podman push
+ pushCmd = &cobra.Command{
+ Use: "push [flags] SOURCE DESTINATION",
+ Short: "Push an image to a specified destination",
+ Long: pushDescription,
+ PreRunE: preRunE,
+ RunE: imagePush,
+ Example: `podman push imageID docker://registry.example.com/repository:tag
+ podman push imageID oci-archive:/path/to/layout:image:tag`,
+ }
+
+ // Command: podman image push
+ // It's basically a clone of `pushCmd` with the exception of being a
+ // child of the images command.
+ imagePushCmd = &cobra.Command{
+ Use: pushCmd.Use,
+ Short: pushCmd.Short,
+ Long: pushCmd.Long,
+ PreRunE: pushCmd.PreRunE,
+ RunE: pushCmd.RunE,
+ Example: `podman image push imageID docker://registry.example.com/repository:tag
+ podman image push imageID oci-archive:/path/to/layout:image:tag`,
+ }
+)
+
+func init() {
+ // push
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: pushCmd,
+ })
+
+ pushCmd.SetHelpTemplate(registry.HelpTemplate())
+ pushCmd.SetUsageTemplate(registry.UsageTemplate())
+
+ flags := pushCmd.Flags()
+ pushFlags(flags)
+
+ // images push
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: imagePushCmd,
+ Parent: imageCmd,
+ })
+
+ imagePushCmd.SetHelpTemplate(registry.HelpTemplate())
+ imagePushCmd.SetUsageTemplate(registry.UsageTemplate())
+ pushFlags(imagePushCmd.Flags())
+}
+
+// pushFlags set the flags for the push command.
+func pushFlags(flags *pflag.FlagSet) {
+ flags.StringVar(&pushOptions.Authfile, "authfile", buildahcli.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
+ flags.StringVar(&pushOptions.CertDir, "cert-dir", "", "Path to a directory containing TLS certificates and keys")
+ flags.BoolVar(&pushOptions.Compress, "compress", false, "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)")
+ flags.StringVar(&pushOptions.Credentials, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
+ flags.StringVar(&pushOptions.DigestFile, "digestfile", "", "Write the digest of the pushed image to the specified file")
+ flags.StringVarP(&pushOptions.Format, "format", "f", "", "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir' transport (default is manifest type of source)")
+ flags.BoolVarP(&pushOptions.Quiet, "quiet", "q", false, "Suppress output information when pushing images")
+ flags.BoolVar(&pushOptions.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image")
+ flags.StringVar(&pushOptions.SignaturePolicy, "signature-policy", "", "Path to a signature-policy file")
+ flags.StringVar(&pushOptions.SignBy, "sign-by", "", "Add a signature at the destination using the specified key")
+ flags.BoolVar(&pushOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
+
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("authfile")
+ _ = flags.MarkHidden("cert-dir")
+ _ = flags.MarkHidden("compress")
+ _ = flags.MarkHidden("quiet")
+ _ = flags.MarkHidden("signature-policy")
+ _ = flags.MarkHidden("tls-verify")
+ }
+}
+
+// imagePush is implement the command for pushing images.
+func imagePush(cmd *cobra.Command, args []string) error {
+ var source, destination string
+ switch len(args) {
+ case 1:
+ source = args[0]
+ case 2:
+ source = args[0]
+ destination = args[1]
+ case 0:
+ fallthrough
+ default:
+ return errors.New("push requires at least one image name, or optionally a second to specify a different destination")
+ }
+
+ pushOptsAPI := pushOptions.ImagePushOptions
+ // TLS verification in c/image is controlled via a `types.OptionalBool`
+ // which allows for distinguishing among set-true, set-false, unspecified
+ // which is important to implement a sane way of dealing with defaults of
+ // boolean CLI flags.
+ if cmd.Flags().Changed("tls-verify") {
+ pushOptsAPI.TLSVerify = types.NewOptionalBool(pushOptions.TLSVerifyCLI)
+ }
+
+ // Let's do all the remaining Yoga in the API to prevent us from scattering
+ // logic across (too) many parts of the code.
+ return registry.ImageEngine().Push(registry.GetContext(), source, destination, pushOptsAPI)
+}
diff --git a/cmd/podmanV2/images/tag.go b/cmd/podmanV2/images/tag.go
new file mode 100644
index 000000000..f66fe7857
--- /dev/null
+++ b/cmd/podmanV2/images/tag.go
@@ -0,0 +1,34 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ tagDescription = "Adds one or more additional names to locally-stored image."
+ tagCommand = &cobra.Command{
+ Use: "tag [flags] IMAGE TARGET_NAME [TARGET_NAME...]",
+ Short: "Add an additional name to a local image",
+ Long: tagDescription,
+ RunE: tag,
+ Args: cobra.MinimumNArgs(2),
+ Example: `podman tag 0e3bbc2 fedora:latest
+ podman tag imageID:latest myNewImage:newTag
+ podman tag httpd myregistryhost:5000/fedora/httpd:v2`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: tagCommand,
+ })
+ tagCommand.SetHelpTemplate(registry.HelpTemplate())
+ tagCommand.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func tag(cmd *cobra.Command, args []string) error {
+ return registry.ImageEngine().Tag(registry.GetContext(), args[0], args[1:], entities.ImageTagOptions{})
+}
diff --git a/cmd/podmanV2/images/untag.go b/cmd/podmanV2/images/untag.go
new file mode 100644
index 000000000..c84827bb3
--- /dev/null
+++ b/cmd/podmanV2/images/untag.go
@@ -0,0 +1,33 @@
+package images
+
+import (
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+var (
+ untagCommand = &cobra.Command{
+ Use: "untag [flags] IMAGE [NAME...]",
+ Short: "Remove a name from a local image",
+ Long: "Removes one or more names from a locally-stored image.",
+ RunE: untag,
+ Args: cobra.MinimumNArgs(1),
+ Example: `podman untag 0e3bbc2
+ podman untag imageID:latest otherImageName:latest
+ podman untag httpd myregistryhost:5000/fedora/httpd:v2`,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: untagCommand,
+ })
+ untagCommand.SetHelpTemplate(registry.HelpTemplate())
+ untagCommand.SetUsageTemplate(registry.UsageTemplate())
+}
+
+func untag(cmd *cobra.Command, args []string) error {
+ return registry.ImageEngine().Untag(registry.GetContext(), args[0], args[1:], entities.ImageUntagOptions{})
+}
diff --git a/cmd/podmanV2/inspect.go b/cmd/podmanV2/inspect.go
new file mode 100644
index 000000000..4975cf632
--- /dev/null
+++ b/cmd/podmanV2/inspect.go
@@ -0,0 +1,62 @@
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/containers/libpod/cmd/podmanV2/common"
+ "github.com/containers/libpod/cmd/podmanV2/containers"
+ "github.com/containers/libpod/cmd/podmanV2/images"
+ "github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+// Inspect is one of the out layer commands in that it operates on images/containers/...
+
+var (
+ inspectOpts *entities.InspectOptions
+
+ // Command: podman _inspect_ Object_ID
+ inspectCmd = &cobra.Command{
+ Use: "inspect [flags] {CONTAINER_ID | IMAGE_ID}",
+ Args: cobra.ExactArgs(1),
+ Short: "Display the configuration of object denoted by ID",
+ Long: "Displays the low-level information on an object identified by name or ID",
+ TraverseChildren: true,
+ RunE: inspect,
+ }
+)
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: inspectCmd,
+ })
+ inspectOpts = common.AddInspectFlagSet(inspectCmd)
+}
+
+func inspect(cmd *cobra.Command, args []string) error {
+ ie, err := registry.NewImageEngine(cmd, args)
+ if err != nil {
+ return err
+ }
+
+ if found, err := ie.Exists(context.Background(), args[0]); err != nil {
+ return err
+ } else if found.Value {
+ return images.Inspect(cmd, args, inspectOpts)
+ }
+
+ ce, err := registry.NewContainerEngine(cmd, args)
+ if err != nil {
+ return err
+ }
+
+ if found, err := ce.ContainerExists(context.Background(), args[0]); err != nil {
+ return err
+ } else if found.Value {
+ return containers.Inspect(cmd, args, inspectOpts)
+ }
+ return fmt.Errorf("%s not found on system", args[0])
+}
diff --git a/cmd/podmanV2/main.go b/cmd/podmanV2/main.go
index bd9fbb25e..6781a7f06 100644
--- a/cmd/podmanV2/main.go
+++ b/cmd/podmanV2/main.go
@@ -7,6 +7,7 @@ import (
"strings"
_ "github.com/containers/libpod/cmd/podmanV2/containers"
+ _ "github.com/containers/libpod/cmd/podmanV2/healthcheck"
_ "github.com/containers/libpod/cmd/podmanV2/images"
_ "github.com/containers/libpod/cmd/podmanV2/networks"
_ "github.com/containers/libpod/cmd/podmanV2/pods"
@@ -14,6 +15,7 @@ import (
_ "github.com/containers/libpod/cmd/podmanV2/volumes"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/storage/pkg/reexec"
"github.com/sirupsen/logrus"
)
@@ -44,6 +46,11 @@ func init() {
}
func main() {
+ if reexec.Init() {
+ // We were invoked with a different argv[0] indicating that we
+ // had a specific job to do as a subprocess, and it's done.
+ return
+ }
for _, c := range registry.Commands {
if Contains(registry.EngineOptions.EngineMode, c.Mode) {
parent := rootCmd
diff --git a/cmd/podmanV2/pods/pod.go b/cmd/podmanV2/pods/pod.go
index 81c0d33e1..3766893bb 100644
--- a/cmd/podmanV2/pods/pod.go
+++ b/cmd/podmanV2/pods/pod.go
@@ -1,6 +1,9 @@
package pods
import (
+ "strings"
+ "text/template"
+
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
@@ -18,6 +21,33 @@ var (
}
)
+var podFuncMap = template.FuncMap{
+ "numCons": func(cons []*entities.ListPodContainer) int {
+ return len(cons)
+ },
+ "podcids": func(cons []*entities.ListPodContainer) string {
+ var ctrids []string
+ for _, c := range cons {
+ ctrids = append(ctrids, c.Id[:12])
+ }
+ return strings.Join(ctrids, ",")
+ },
+ "podconnames": func(cons []*entities.ListPodContainer) string {
+ var ctrNames []string
+ for _, c := range cons {
+ ctrNames = append(ctrNames, c.Names[:12])
+ }
+ return strings.Join(ctrNames, ",")
+ },
+ "podconstatuses": func(cons []*entities.ListPodContainer) string {
+ var statuses []string
+ for _, c := range cons {
+ statuses = append(statuses, c.Status)
+ }
+ return strings.Join(statuses, ",")
+ },
+}
+
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
diff --git a/cmd/podmanV2/pods/ps.go b/cmd/podmanV2/pods/ps.go
index d4c625b2e..9546dff9e 100644
--- a/cmd/podmanV2/pods/ps.go
+++ b/cmd/podmanV2/pods/ps.go
@@ -1,8 +1,19 @@
package pods
import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+ "text/tabwriter"
+ "text/template"
+
"github.com/containers/libpod/cmd/podmanV2/registry"
+ "github.com/containers/libpod/cmd/podmanV2/report"
"github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -19,14 +30,137 @@ var (
}
)
+var (
+ defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED"
+ inputFilters string
+ noTrunc bool
+ psInput entities.PodPSOptions
+)
+
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: psCmd,
Parent: podCmd,
})
+ flags := psCmd.Flags()
+ flags.BoolVar(&psInput.CtrNames, "ctr-names", false, "Display the container names")
+ flags.BoolVar(&psInput.CtrIds, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated")
+ flags.BoolVar(&psInput.CtrStatus, "ctr-status", false, "Display the container status")
+ // TODO should we make this a [] ?
+ flags.StringVarP(&inputFilters, "filter", "f", "", "Filter output based on conditions given")
+ flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template")
+ flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
+ flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod")
+ flags.BoolVar(&psInput.Namespace, "ns", false, "Display namespace information of the pod")
+ flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate pod and container IDs")
+ flags.BoolVarP(&psInput.Quiet, "quiet", "q", false, "Print the numeric IDs of the pods only")
+ flags.StringVar(&psInput.Sort, "sort", "created", "Sort output by created, id, name, or number")
+ if registry.IsRemote() {
+ _ = flags.MarkHidden("latest")
+ }
}
func pods(cmd *cobra.Command, args []string) error {
+ var (
+ w io.Writer = os.Stdout
+ row string
+ )
+ if cmd.Flag("filter").Changed {
+ for _, f := range strings.Split(inputFilters, ",") {
+ split := strings.Split(f, "=")
+ if len(split) < 2 {
+ return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
+ }
+ psInput.Filters[split[0]] = append(psInput.Filters[split[0]], split[1])
+ }
+ }
+ responses, err := registry.ContainerEngine().PodPs(context.Background(), psInput)
+ if err != nil {
+ return err
+ }
+
+ if psInput.Format == "json" {
+ b, err := json.MarshalIndent(responses, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(b))
+ return nil
+ }
+ headers, row := createPodPsOut(cmd)
+ if psInput.Quiet {
+ if noTrunc {
+ row = "{{.Id}}\n"
+ } else {
+ row = "{{slice .Id 0 12}}\n"
+ }
+ }
+ if cmd.Flag("format").Changed {
+ row = psInput.Format
+ if !strings.HasPrefix(row, "\n") {
+ row += "\n"
+ }
+ }
+ format := "{{range . }}" + row + "{{end}}"
+ if !psInput.Quiet && !cmd.Flag("format").Changed {
+ format = headers + format
+ }
+ funcs := report.AppendFuncMap(podFuncMap)
+ tmpl, err := template.New("listPods").Funcs(funcs).Parse(format)
+ if err != nil {
+ return err
+ }
+ if !psInput.Quiet {
+ w = tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
+ }
+ if err := tmpl.Execute(w, responses); err != nil {
+ return err
+ }
+ if flusher, ok := w.(interface{ Flush() error }); ok {
+ return flusher.Flush()
+ }
return nil
}
+
+func createPodPsOut(cmd *cobra.Command) (string, string) {
+ var row string
+ headers := defaultHeaders
+ if noTrunc {
+ row += "{{.Id}}"
+ } else {
+ row += "{{slice .Id 0 12}}"
+ }
+
+ row += "\t{{.Name}}\t{{.Status}}\t{{humanDurationFromTime .Created}}"
+
+ //rowFormat string = "{{slice .Id 0 12}}\t{{.Name}}\t{{.Status}}\t{{humanDurationFromTime .Created}}"
+ if psInput.CtrIds {
+ headers += "\tIDS"
+ row += "\t{{podcids .Containers}}"
+ }
+ if psInput.CtrNames {
+ headers += "\tNAMES"
+ row += "\t{{podconnames .Containers}}"
+ }
+ if psInput.CtrStatus {
+ headers += "\tSTATUS"
+ row += "\t{{podconstatuses .Containers}}"
+ }
+ if psInput.Namespace {
+ headers += "\tCGROUP\tNAMESPACES"
+ row += "\t{{.Cgroup}}\t{{.Namespace}}"
+ }
+ if !psInput.CtrStatus && !psInput.CtrNames && !psInput.CtrIds {
+ headers += "\t# OF CONTAINERS"
+ row += "\t{{numCons .Containers}}"
+
+ }
+ headers += "\tINFRA ID\n"
+ if noTrunc {
+ row += "\t{{.InfraId}}\n"
+ } else {
+ row += "\t{{slice .InfraId 0 12}}\n"
+ }
+ return headers, row
+}
diff --git a/cmd/podmanV2/pods/stop.go b/cmd/podmanV2/pods/stop.go
index 2b61850e2..403c7d95d 100644
--- a/cmd/podmanV2/pods/stop.go
+++ b/cmd/podmanV2/pods/stop.go
@@ -26,7 +26,7 @@ var (
},
Example: `podman pod stop mywebserverpod
podman pod stop --latest
- podman pod stop --timeout 0 490eb 3557fb`,
+ podman pod stop --time 0 490eb 3557fb`,
}
)
@@ -47,19 +47,20 @@ func init() {
flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running pods")
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Stop the latest pod podman is aware of")
- flags.UintVarP(&timeout, "timeout", "t", 0, "Seconds to wait for pod stop before killing the container")
+ flags.UintVarP(&timeout, "time", "t", 0, "Seconds to wait for pod stop before killing the container")
if registry.IsRemote() {
_ = flags.MarkHidden("latest")
_ = flags.MarkHidden("ignore")
}
+ flags.SetNormalizeFunc(utils.AliasFlags)
}
func stop(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
- if cmd.Flag("timeout").Changed {
+ if cmd.Flag("time").Changed {
stopOptions.Timeout = int(timeout)
}
responses, err := registry.ContainerEngine().PodStop(context.Background(), args, stopOptions)
diff --git a/cmd/podmanV2/registry/registry.go b/cmd/podmanV2/registry/registry.go
index 5cdb8a840..401f82718 100644
--- a/cmd/podmanV2/registry/registry.go
+++ b/cmd/podmanV2/registry/registry.go
@@ -3,7 +3,6 @@ package registry
import (
"context"
- "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra"
"github.com/pkg/errors"
@@ -18,24 +17,24 @@ type CliCommand struct {
Parent *cobra.Command
}
-var (
- Commands []CliCommand
+const ExecErrorCodeGeneric = 125
- imageEngine entities.ImageEngine
- containerEngine entities.ContainerEngine
+var (
cliCtx context.Context
+ containerEngine entities.ContainerEngine
+ exitCode = ExecErrorCodeGeneric
+ imageEngine entities.ImageEngine
+ Commands []CliCommand
EngineOptions entities.EngineOptions
-
- ExitCode = define.ExecErrorCodeGeneric
)
func SetExitCode(code int) {
- ExitCode = code
+ exitCode = code
}
func GetExitCode() int {
- return ExitCode
+ return exitCode
}
// HelpTemplate returns the help template for podman commands
diff --git a/cmd/podmanV2/report/templates.go b/cmd/podmanV2/report/templates.go
index f3bc06405..e46048e97 100644
--- a/cmd/podmanV2/report/templates.go
+++ b/cmd/podmanV2/report/templates.go
@@ -19,6 +19,9 @@ var defaultFuncMap = template.FuncMap{
"humanDuration": func(t int64) string {
return units.HumanDuration(time.Since(time.Unix(t, 0))) + " ago"
},
+ "humanDurationFromTime": func(t time.Time) string {
+ return units.HumanDuration(time.Since(t)) + " ago"
+ },
"humanSize": func(sz int64) string {
s := units.HumanSizeWithPrecision(float64(sz), 3)
i := strings.LastIndexFunc(s, unicode.IsNumber)
diff --git a/cmd/podmanV2/root.go b/cmd/podmanV2/root.go
index cb4cb4e00..6fc12f57e 100644
--- a/cmd/podmanV2/root.go
+++ b/cmd/podmanV2/root.go
@@ -7,7 +7,6 @@ import (
"path"
"github.com/containers/libpod/cmd/podmanV2/registry"
- "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/version"
"github.com/sirupsen/logrus"
@@ -88,8 +87,8 @@ func Execute() {
o := registry.NewOptions(rootCmd.Context(), &registry.EngineOptions)
if err := rootCmd.ExecuteContext(o); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err.Error())
- } else if registry.GetExitCode() == define.ExecErrorCodeGeneric {
- // The exitCode modified from define.ExecErrorCodeGeneric,
+ } else if registry.GetExitCode() == registry.ExecErrorCodeGeneric {
+ // The exitCode modified from registry.ExecErrorCodeGeneric,
// indicates an application
// running inside of a container failed, as opposed to the
// podman command failed. Must exit with that exit code
diff --git a/cmd/podmanV2/system/system.go b/cmd/podmanV2/system/system.go
index 30ed328e8..4e805c7bd 100644
--- a/cmd/podmanV2/system/system.go
+++ b/cmd/podmanV2/system/system.go
@@ -1,4 +1,4 @@
-package images
+package system
import (
"github.com/containers/libpod/cmd/podmanV2/registry"
diff --git a/cmd/podmanV2/utils/alias.go b/cmd/podmanV2/utils/alias.go
new file mode 100644
index 000000000..54b3c5e89
--- /dev/null
+++ b/cmd/podmanV2/utils/alias.go
@@ -0,0 +1,24 @@
+package utils
+
+import "github.com/spf13/pflag"
+
+// AliasFlags is a function to handle backwards compatability with old flags
+func AliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ switch name {
+ case "healthcheck-command":
+ name = "health-cmd"
+ case "healthcheck-interval":
+ name = "health-interval"
+ case "healthcheck-retries":
+ name = "health-retries"
+ case "healthcheck-start-period":
+ name = "health-start-period"
+ case "healthcheck-timeout":
+ name = "health-timeout"
+ case "net":
+ name = "network"
+ case "timeout":
+ name = "time"
+ }
+ return pflag.NormalizedName(name)
+}
diff --git a/completions/bash/podman b/completions/bash/podman
index 4a694ca44..77f881d53 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -2161,7 +2161,7 @@ _podman_run() {
_podman_restart() {
local options_with_args="
- --timeout -t
+ --time -t
"
local boolean_options="
--all
@@ -2171,8 +2171,6 @@ _podman_restart() {
--latest
-l
--running
- --timeout
- -t
"
case "$cur" in
-*)
@@ -2462,7 +2460,7 @@ _podman_start() {
}
_podman_stop() {
local options_with_args="
- --timeout -t
+ --time -t
"
local boolean_options="
--all
@@ -2656,7 +2654,7 @@ _podman_generate_systemd() {
local options_with_args="
--restart-policy
-t
- --timeout"
+ --time"
local boolean_options="
-h
@@ -3088,7 +3086,7 @@ _podman_pod_start() {
_podman_pod_stop() {
local options_with_args="
-t
- --timeout
+ --time
"
local boolean_options="
diff --git a/contrib/build_rpm.sh b/contrib/build_rpm.sh
index de6941199..a9db029df 100755
--- a/contrib/build_rpm.sh
+++ b/contrib/build_rpm.sh
@@ -7,11 +7,18 @@ echo "Package manager binary: $pkg_manager"
if [[ $pkg_manager == *yum ]]; then
- echo "[virt7-container-common-candidate]
-name=virt7-container-common-candidate
-baseurl=https://cbs.centos.org/repos/virt7-container-common-candidate/x86_64/os/
+ echo "[virt7-container]
+name=virt7-container
+baseurl=https://buildlogs.centos.org/centos/7/virt/x86_64/container/
enabled=1
gpgcheck=0" > /etc/yum.repos.d/container_virt.repo
+ echo "[paas_openshift_origin311]
+name=paas_openshift_origin311
+# Use this if you need the newest *-testing packages
+# baseurl=https://buildlogs.centos.org/centos/7/paas/x86_64/openshift-origin311/
+baseurl=http://mirror.centos.org/centos/7/paas/x86_64/openshift-origin311/
+enabled=1
+gpgcheck=0" > /etc/yum.repos.d/paas_openshift_origin311.repo
fi
declare -a PKGS=(\
diff --git a/contrib/cirrus/README.md b/contrib/cirrus/README.md
index 3789965d6..709985b5b 100644
--- a/contrib/cirrus/README.md
+++ b/contrib/cirrus/README.md
@@ -80,7 +80,7 @@ having `SPECIALMODE` set to 'cgroupv2`
Modifying the contents of cache-images is tested by making changes to
one or more of the ``./contrib/cirrus/packer/*_setup.sh`` files. Then
-in the PR description, add the magic string: ``***CIRRUS: TEST IMAGES***``
+in the PR description, add the magic string: ``[CI:IMG]``
***N/B: Steps below are performed by automation***
@@ -153,7 +153,7 @@ env:
***NOTES:***
* If re-using the same PR with new images in `.cirrus.yml`,
take care to also *update the PR description* to remove
- the magic ``***CIRRUS: TEST IMAGES***`` string. Keeping it and
+ the magic ``[CI:IMG]`` string. Keeping it and
`--force` pushing would needlessly cause Cirrus-CI to build
and test images again.
* In the future, if you need to review the log from the build that produced
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 817be31b7..9641a52e6 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -392,9 +392,9 @@ 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"
+export BUILDTAGS="varlink selinux seccomp systemd $(%{hackdir}/hack/btrfs_installed_tag.sh) $(%{hackdir}/hack/btrfs_tag.sh) $(%{hackdir}/hack/libdm_tag.sh) exclude_graphdriver_devicemapper"
-GOPATH=$GOPATH go generate ./cmd/podman/varlink/...
+GOPATH=$GOPATH go generate ./pkg/varlink/...
%if %{with doc}
BUILDTAGS=$BUILDTAGS make binaries docs
@@ -410,7 +410,7 @@ mkdir -p src/%{provider}.%{provider_tld}/{containers,opencontainers}
ln -s $(dirs +1 -l) src/%{import_path_conmon}
popd
-export BUILDTAGS="selinux seccomp $(%{hackdir}/hack/btrfs_installed_tag.sh) $(%{hackdir}/hack/btrfs_tag.sh)"
+export BUILDTAGS="selinux seccomp systemd $(%{hackdir}/hack/btrfs_installed_tag.sh) $(%{hackdir}/hack/btrfs_tag.sh)"
BUILDTAGS=$BUILDTAGS make
popd
diff --git a/docs/generate.go b/docs/generate.go
index 9ab370e2c..2adca8fc1 100644
--- a/docs/generate.go
+++ b/docs/generate.go
@@ -1,3 +1,3 @@
package docs
-//go:generate go run varlink/apidoc.go ../cmd/podman/varlink/io.podman.varlink ../API.md
+//go:generate go run varlink/apidoc.go ../pkg/varlink/io.podman.varlink ../API.md
diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md
index 27b40bbb6..57ed9a5eb 100644
--- a/docs/source/markdown/podman-generate-systemd.1.md
+++ b/docs/source/markdown/podman-generate-systemd.1.md
@@ -27,7 +27,7 @@ Use the name of the container for the start, stop, and description in the unit f
Create a new container via podman-run instead of starting an existing one. This option relies on container configuration files, which may not map directly to podman CLI flags; please review the generated output carefully before placing in production.
Since we use systemd `Type=forking` service, using this option will force the container run with the detached param `-d`
-**--timeout**, **-t**=*value*
+**--time**, **-t**=*value*
Override the default stop timeout for the container with the given value.
diff --git a/docs/source/markdown/podman-pod-stop.1.md b/docs/source/markdown/podman-pod-stop.1.md
index 42d2a2d3f..b5e7aef7d 100644
--- a/docs/source/markdown/podman-pod-stop.1.md
+++ b/docs/source/markdown/podman-pod-stop.1.md
@@ -27,7 +27,7 @@ Instead of providing the pod name or ID, stop the last created pod.
The latest option is not supported on the remote client.
-**--timeout**, **-t**=*time*
+**--time**, **-t**=*time*
Timeout to wait before forcibly stopping the containers in the pod.
diff --git a/docs/source/markdown/podman-restart.1.md b/docs/source/markdown/podman-restart.1.md
index 247d50685..87217f096 100644
--- a/docs/source/markdown/podman-restart.1.md
+++ b/docs/source/markdown/podman-restart.1.md
@@ -46,7 +46,7 @@ ff6cf1e5e77e6dba1efc7f3fcdb20e8b89ad8947bc0518be1fcb2c78681f226f
Restart two containers by name with a timeout of 4 seconds
```
-$ podman restart --timeout 4 test1 test2
+$ podman restart --time 4 test1 test2
c3bb026838c30e5097f079fa365c9a4769d52e1017588278fa00d5c68ebc1502
17e13a63081a995136f907024bcfe50ff532917988a152da229db9d894c5a9ec
```
diff --git a/docs/source/markdown/podman-stop.1.md b/docs/source/markdown/podman-stop.1.md
index 23b3415e9..1534063a5 100644
--- a/docs/source/markdown/podman-stop.1.md
+++ b/docs/source/markdown/podman-stop.1.md
@@ -9,7 +9,7 @@ podman\-stop - Stop one or more running containers
**podman container stop** [*options*] *container* ...
## DESCRIPTION
-Stops one or more containers. You may use container IDs or names as input. The **--timeout** switch
+Stops one or more containers. You may use container IDs or names as input. The **--time** switch
allows you to specify the number of seconds to wait before forcibly stopping the container after the stop command
is issued to the container. The default is 10 seconds. By default, containers are stopped with SIGTERM
and then SIGKILL after the timeout. The SIGTERM default can be overridden by the image used to create the
@@ -54,7 +54,7 @@ $ podman stop --cidfile /home/user/cidfile-1
$ podman stop --cidfile /home/user/cidfile-1 --cidfile ./cidfile-2
-$ podman stop --timeout 2 860a4b235279
+$ podman stop --time 2 860a4b235279
$ podman stop -a
diff --git a/go.mod b/go.mod
index 37207067f..96108b370 100644
--- a/go.mod
+++ b/go.mod
@@ -9,12 +9,12 @@ require (
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect
github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921
github.com/containernetworking/plugins v0.8.5
- github.com/containers/buildah v1.14.5
- github.com/containers/common v0.6.1
- github.com/containers/conmon v2.0.10+incompatible
+ github.com/containers/buildah v1.14.6-0.20200402210551-e9a6703edee2
+ github.com/containers/common v0.8.0
+ github.com/containers/conmon v2.0.14+incompatible
github.com/containers/image/v5 v5.3.1
github.com/containers/psgo v1.4.0
- github.com/containers/storage v1.16.6
+ github.com/containers/storage v1.18.1
github.com/coreos/go-systemd/v22 v22.0.0
github.com/cri-o/ocicni v0.1.1-0.20190920040751-deac903fd99b
github.com/cyphar/filepath-securejoin v0.2.2
@@ -46,7 +46,7 @@ require (
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0
- github.com/rootless-containers/rootlesskit v0.9.2
+ github.com/rootless-containers/rootlesskit v0.9.3
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
github.com/sirupsen/logrus v1.5.0
github.com/spf13/cobra v0.0.7
diff --git a/go.sum b/go.sum
index 3a26a1e3a..db0663584 100644
--- a/go.sum
+++ b/go.sum
@@ -64,10 +64,17 @@ github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7
github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o=
github.com/containers/buildah v1.14.5 h1:0Q+UgkIG4gAgAEZCu+0Syu/fSKsM1EsrctwV8G299jo=
github.com/containers/buildah v1.14.5/go.mod h1:2rfICEnpTtrMhWF6FZLnAL1Bh7SNmjhiKrjuIo0ZuN8=
+github.com/containers/buildah v1.14.6-0.20200402210551-e9a6703edee2 h1:9WchHVTk/FuAHHMuClpAZqk8dxOsPi6i6Yw5ocLbZxk=
+github.com/containers/buildah v1.14.6-0.20200402210551-e9a6703edee2/go.mod h1:auylD7PH2uPpE+a/FmgZmP/uC30pIbR3cNYMPSNHxXg=
github.com/containers/common v0.6.1 h1:z9VeVXYeOnNV99uNLp7zoE5KO1n0hqz1mdm5a6AiIrA=
github.com/containers/common v0.6.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
-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/common v0.7.0/go.mod h1:UmhIdvSkhTR0hWR01AnuZGNufm80+A0s8isb05eTmz0=
+github.com/containers/common v0.8.0 h1:C+wjkcmR4gooeKCXZpyjsHSFARm5AZRegflGz0x0MMw=
+github.com/containers/common v0.8.0/go.mod h1:QJTx9+SvhHKP6e+p7Nxqc8oNnS5rSf0KVhxudIbDslU=
+github.com/containers/common v1.0.0 h1:sZB48LzGP4bP1CmrkQIFUzdUVBysqRv3kWVk4+qbaVA=
+github.com/containers/common v1.0.0/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
+github.com/containers/conmon v2.0.14+incompatible h1:knU1O1QxXy5YxtjMQVKEyCajROaehizK9FHaICl+P5Y=
+github.com/containers/conmon v2.0.14+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.2.1/go.mod h1:TfhmLwH+v1/HBVPIWH7diLs8XwcOkP3c7t7JFgqaUEc=
github.com/containers/image/v5 v5.3.1 h1:AL0pR0d1ho3kLUAuBr+wnFlXuD3ChzKVljk0M8JBJHQ=
github.com/containers/image/v5 v5.3.1/go.mod h1:JnCfhbTIL9IxPPZm1JoQwiE0S9KET46M4OZySJsLylk=
@@ -82,6 +89,9 @@ github.com/containers/storage v1.16.0/go.mod h1:nqN09JSi1/RSI1UAUwDYXPRiGSlq5FPb
github.com/containers/storage v1.16.5/go.mod h1:SdysZeLKJOvfHYysUWg9OZUC3gdZWi5b2b7NC18VpPE=
github.com/containers/storage v1.16.6 h1:G/thPW/LVRwJpQvve1V4DQXVZpxzSltC2fzc3yTEdi8=
github.com/containers/storage v1.16.6/go.mod h1:Fws4I+U+C4DmJxDbBs1z9SKk50DzN4LtA+g1b+FmkTY=
+github.com/containers/storage v1.18.0/go.mod h1:gbFeFybWhlVCk3buJ0sovNKs8MzWEBTrk8/sbJw8irQ=
+github.com/containers/storage v1.18.1 h1:W134oYa8ALd78yo6DKiDp6n7EWXrc+fCnYmJi6o49vo=
+github.com/containers/storage v1.18.1/go.mod h1:6NtCgnUeYsRlyZyrZ5qKkXYC560GRgvA7YrKRSAYSlo=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
@@ -189,6 +199,7 @@ github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v1.0.0/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/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
@@ -283,6 +294,7 @@ github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJd
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
github.com/moby/vpnkit v0.3.1-0.20200304131818-6bc1679a048d/go.mod h1:KyjUrL9cb6ZSNNAUwZfqRjhwwgJ3BJN+kXh0t43WTUQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
@@ -300,6 +312,7 @@ github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgi
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -342,6 +355,8 @@ github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316 h1:enQG2QUGwug4fR1yM
github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316/go.mod h1:dv+J0b/HWai0QnMVb37/H0v36klkLBi2TNpPeWDxX10=
github.com/openshift/imagebuilder v1.1.3 h1:8TiphsD2wboU7tygtGZ5ZBfCP9FH2ZtvEAli67V2PJ4=
github.com/openshift/imagebuilder v1.1.3/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
+github.com/openshift/imagebuilder v1.1.4 h1:LUg8aTjyXMtlDx6IbtvaqofFGZ6aYqe+VIeATE735LM=
+github.com/openshift/imagebuilder v1.1.4/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
@@ -383,6 +398,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uY
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rootless-containers/rootlesskit v0.9.2 h1:avrVoGuC8xdrUEwVuxGncEc46bMixvGfjyolMI4H3/U=
github.com/rootless-containers/rootlesskit v0.9.2/go.mod h1:QNzDKFGrnpXx3z7zQRu3nvK6lo9zyaR7O+WvLy6Azu4=
+github.com/rootless-containers/rootlesskit v0.9.3 h1:hrkZzBZT5vEnhAso6H1jHAcc4DT8h6/hp2z4yL0xu/8=
+github.com/rootless-containers/rootlesskit v0.9.3/go.mod h1:fx5DhInDgnR0Upj+2cOVacKuZJYSNKV5P/bCwGa+quQ=
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=
@@ -593,6 +610,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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=
@@ -612,6 +630,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/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 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=
diff --git a/hack/podmanv2-retry b/hack/podmanv2-retry
new file mode 100755
index 000000000..ea77486ff
--- /dev/null
+++ b/hack/podmanv2-retry
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# podman-try - try running a command via PODMAN1; use PODMAN2 as fallback
+#
+# Intended for use with a podmanv2 client. If a command isn't yet
+# implemented, fall back to regular podman:
+#
+# Set PODMAN_V2 to the path to a podman v2 client
+# Set PODMAN_FALLBACK to the path to regular podman
+#
+# THIS IS IMPERFECT. In particular, it will not work if stdin is redirected
+# (e.g. 'podman ... < file' or 'something | podman'); nor for anything
+# that generates continuous output ('podman logs -f'); and probably more
+# situations.
+#
+
+die() {
+ echo "$(basename $0): $*" >&2
+ exit 1
+}
+
+test -n "$PODMAN_V2" || die "Please set \$PODMAN_V2 (path to podman v2)"
+test -n "$PODMAN_FALLBACK" || die "Please set \$PODMAN_FALLBACK (path to podman)"
+
+
+result=$(${PODMAN_V2} "$@" 2>&1)
+rc=$?
+
+if [ $rc == 125 ]; then
+ if [[ "$result" =~ unrecognized\ command|unknown\ flag|unknown\ shorthand ]]; then
+ result=$(${PODMAN_FALLBACK} "$@")
+ rc=$?
+ fi
+fi
+
+echo -n "$result"
+exit $rc
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 5f914ed79..80cc6f15a 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -512,8 +512,8 @@ func getImageDigest(ctx context.Context, src types.ImageReference, sc *types.Sys
return "@" + imageDigest.Hex(), nil
}
-// normalizedTag returns the canonical version of tag for use in Image.Names()
-func normalizedTag(tag string) (reference.Named, error) {
+// NormalizedTag returns the canonical version of tag for use in Image.Names()
+func NormalizedTag(tag string) (reference.Named, error) {
decomposedTag, err := decompose(tag)
if err != nil {
return nil, err
@@ -541,7 +541,7 @@ func (i *Image) TagImage(tag string) error {
if err := i.reloadImage(); err != nil {
return err
}
- ref, err := normalizedTag(tag)
+ ref, err := NormalizedTag(tag)
if err != nil {
return err
}
diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go
index 19f7eee1e..3cd368cdc 100644
--- a/libpod/image/image_test.go
+++ b/libpod/image/image_test.go
@@ -292,7 +292,7 @@ func TestNormalizedTag(t *testing.T) {
{"ns/busybox:latest", "localhost/ns/busybox:latest"}, // Unqualified with a dot-less namespace
{"docker.io/busybox:latest", "docker.io/library/busybox:latest"}, // docker.io without /library/
} {
- res, err := normalizedTag(c.input)
+ res, err := NormalizedTag(c.input)
if c.expected == "" {
assert.Error(t, err, c.input)
} else {
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index 433993edb..fb0a54bff 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -200,8 +200,10 @@ func setupStdioChannels(streams *AttachStreams, conn *net.UnixConn, detachKeys [
var err error
if streams.AttachInput {
_, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys)
- if connErr := conn.CloseWrite(); connErr != nil {
- logrus.Errorf("unable to close conn: %q", connErr)
+ if err == nil {
+ if connErr := conn.CloseWrite(); connErr != nil {
+ logrus.Errorf("unable to close conn: %q", connErr)
+ }
}
}
stdinDone <- err
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index ce888c690..6a0097b8e 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -575,13 +575,36 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, httpConn net.Conn, httpBuf
}
}
+// isRetryable returns whether the error was caused by a blocked syscall or the
+// specified operation on a non blocking file descriptor wasn't ready for completion.
+func isRetryable(err error) bool {
+ if errno, isErrno := errors.Cause(err).(syscall.Errno); isErrno {
+ return errno == syscall.EINTR || errno == syscall.EAGAIN
+ }
+ return false
+}
+
+// openControlFile opens the terminal control file.
+func openControlFile(ctr *Container, parentDir string) (*os.File, error) {
+ controlPath := filepath.Join(parentDir, "ctl")
+ for i := 0; i < 600; i++ {
+ controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY|unix.O_NONBLOCK, 0)
+ if err == nil {
+ return controlFile, err
+ }
+ if !isRetryable(err) {
+ return nil, errors.Wrapf(err, "could not open ctl file for terminal resize for container %s", ctr.ID())
+ }
+ time.Sleep(time.Second / 10)
+ }
+ return nil, errors.Errorf("timeout waiting for %q", controlPath)
+}
+
// AttachResize resizes the terminal used by the given container.
func (r *ConmonOCIRuntime) AttachResize(ctr *Container, newSize remotecommand.TerminalSize) error {
- // TODO: probably want a dedicated function to get ctl file path?
- controlPath := filepath.Join(ctr.bundlePath(), "ctl")
- controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0)
+ controlFile, err := openControlFile(ctr, ctr.bundlePath())
if err != nil {
- return errors.Wrapf(err, "could not open ctl file for terminal resize")
+ return err
}
defer controlFile.Close()
@@ -785,11 +808,9 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options
// ExecAttachResize resizes the TTY of the given exec session.
func (r *ConmonOCIRuntime) ExecAttachResize(ctr *Container, sessionID string, newSize remotecommand.TerminalSize) error {
- // TODO: probably want a dedicated function to get ctl file path?
- controlPath := filepath.Join(ctr.execBundlePath(sessionID), "ctl")
- controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0)
+ controlFile, err := openControlFile(ctr, ctr.execBundlePath(sessionID))
if err != nil {
- return errors.Wrapf(err, "could not open ctl file for terminal resize for container %s exec session %s", ctr.ID(), sessionID)
+ return err
}
defer controlFile.Close()
diff --git a/libpod/podfilters/pods.go b/libpod/podfilters/pods.go
new file mode 100644
index 000000000..54fa85edc
--- /dev/null
+++ b/libpod/podfilters/pods.go
@@ -0,0 +1,115 @@
+package podfilters
+
+import (
+ "strconv"
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/pkg/errors"
+)
+
+// GeneratePodFilterFunc takes a filter and filtervalue (key, value)
+// and generates a libpod function that can be used to filter
+// pods
+func GeneratePodFilterFunc(filter, filterValue string) (
+ func(pod *libpod.Pod) bool, error) {
+ switch filter {
+ case "ctr-ids":
+ return func(p *libpod.Pod) bool {
+ ctrIds, err := p.AllContainersByID()
+ if err != nil {
+ return false
+ }
+ return util.StringInSlice(filterValue, ctrIds)
+ }, nil
+ case "ctr-names":
+ return func(p *libpod.Pod) bool {
+ ctrs, err := p.AllContainers()
+ if err != nil {
+ return false
+ }
+ for _, ctr := range ctrs {
+ if filterValue == ctr.Name() {
+ return true
+ }
+ }
+ return false
+ }, nil
+ case "ctr-number":
+ return func(p *libpod.Pod) bool {
+ ctrIds, err := p.AllContainersByID()
+ if err != nil {
+ return false
+ }
+
+ fVint, err2 := strconv.Atoi(filterValue)
+ if err2 != nil {
+ return false
+ }
+ return len(ctrIds) == fVint
+ }, nil
+ case "ctr-status":
+ if !util.StringInSlice(filterValue,
+ []string{"created", "restarting", "running", "paused",
+ "exited", "unknown"}) {
+ return nil, errors.Errorf("%s is not a valid status", filterValue)
+ }
+ return func(p *libpod.Pod) bool {
+ ctr_statuses, err := p.Status()
+ if err != nil {
+ return false
+ }
+ for _, ctr_status := range ctr_statuses {
+ state := ctr_status.String()
+ if ctr_status == define.ContainerStateConfigured {
+ state = "created"
+ }
+ if state == filterValue {
+ return true
+ }
+ }
+ return false
+ }, nil
+ case "id":
+ return func(p *libpod.Pod) bool {
+ return strings.Contains(p.ID(), filterValue)
+ }, nil
+ case "name":
+ return func(p *libpod.Pod) bool {
+ return strings.Contains(p.Name(), filterValue)
+ }, nil
+ case "status":
+ if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created"}) {
+ return nil, errors.Errorf("%s is not a valid pod status", filterValue)
+ }
+ return func(p *libpod.Pod) bool {
+ status, err := p.GetPodStatus()
+ if err != nil {
+ return false
+ }
+ if strings.ToLower(status) == filterValue {
+ return true
+ }
+ return false
+ }, nil
+ case "label":
+ var filterArray = strings.SplitN(filterValue, "=", 2)
+ var filterKey = filterArray[0]
+ if len(filterArray) > 1 {
+ filterValue = filterArray[1]
+ } else {
+ filterValue = ""
+ }
+ return func(p *libpod.Pod) bool {
+ for labelKey, labelValue := range p.Labels() {
+ if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
+ return true
+ }
+ }
+ return false
+ }, nil
+ }
+ return nil, errors.Errorf("%s is an invalid filter", filter)
+}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index a2f73307b..c395ffc7f 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -1213,8 +1213,8 @@ func (r *LocalRuntime) generateSystemdgenContainerInfo(c *cliconfig.GenerateSyst
return nil, false, err
}
- timeout := int(ctr.StopTimeout())
- if c.StopTimeout >= 0 {
+ timeout := ctr.StopTimeout()
+ if c.Flags().Changed("timeout") || c.Flags().Changed("time") {
timeout = c.StopTimeout
}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 46db7ebe8..fc8b524d6 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -15,11 +15,11 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/logs"
envLib "github.com/containers/libpod/pkg/env"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/pkg/varlinkapi/virtwriter"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/docker/pkg/term"
diff --git a/pkg/adapter/errors.go b/pkg/adapter/errors.go
index ede3d4b1a..012d01d39 100644
--- a/pkg/adapter/errors.go
+++ b/pkg/adapter/errors.go
@@ -3,8 +3,8 @@
package adapter
import (
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod/define"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/pkg/errors"
)
diff --git a/pkg/adapter/images_remote.go b/pkg/adapter/images_remote.go
index e7b38dccc..2df0ffcde 100644
--- a/pkg/adapter/images_remote.go
+++ b/pkg/adapter/images_remote.go
@@ -6,8 +6,8 @@ import (
"context"
"encoding/json"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/inspect"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// Inspect returns returns an ImageData struct from over a varlink connection
diff --git a/pkg/adapter/info_remote.go b/pkg/adapter/info_remote.go
index c55d1f6ef..0e8fb06d1 100644
--- a/pkg/adapter/info_remote.go
+++ b/pkg/adapter/info_remote.go
@@ -4,9 +4,9 @@ package adapter
import (
"encoding/json"
- "github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod/define"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// Info returns information for the host system and its components
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index 6b8f22f15..ebd10a92a 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -10,9 +10,9 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/pkg/varlinkapi"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
diff --git a/pkg/adapter/reset_remote.go b/pkg/adapter/reset_remote.go
index 663fab639..284b54a17 100644
--- a/pkg/adapter/reset_remote.go
+++ b/pkg/adapter/reset_remote.go
@@ -3,7 +3,7 @@
package adapter
import (
- "github.com/containers/libpod/cmd/podman/varlink"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// Info returns information for the host system and its components
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index a616e6c7a..a4ac660ea 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -22,12 +22,12 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/remoteclientconfig"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/util"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/utils"
"github.com/containers/storage/pkg/archive"
"github.com/opencontainers/go-digest"
diff --git a/pkg/api/handlers/compat/containers_export.go b/pkg/api/handlers/compat/containers_export.go
new file mode 100644
index 000000000..37b9fbf2b
--- /dev/null
+++ b/pkg/api/handlers/compat/containers_export.go
@@ -0,0 +1,42 @@
+package compat
+
+import (
+ "io/ioutil"
+ "net/http"
+ "os"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/pkg/errors"
+)
+
+func ExportContainer(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ name := utils.GetName(r)
+ con, err := runtime.LookupContainer(name)
+ if err != nil {
+ utils.ContainerNotFound(w, name, err)
+ return
+ }
+ tmpfile, err := ioutil.TempFile("", "api.tar")
+ if err != nil {
+ utils.Error(w, "unable to create tarball tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ return
+ }
+ defer os.Remove(tmpfile.Name())
+ if err := tmpfile.Close(); err != nil {
+ utils.Error(w, "unable to close tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ return
+ }
+ if err := con.Export(tmpfile.Name()); err != nil {
+ utils.Error(w, "failed to save the image", http.StatusInternalServerError, errors.Wrap(err, "failed to save image"))
+ return
+ }
+ rdr, err := os.Open(tmpfile.Name())
+ if err != nil {
+ utils.Error(w, "failed to read temp tarball", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ return
+ }
+ defer rdr.Close()
+ utils.WriteResponse(w, http.StatusOK, rdr)
+}
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
new file mode 100644
index 000000000..2260d5557
--- /dev/null
+++ b/pkg/api/handlers/compat/images_push.go
@@ -0,0 +1,80 @@
+package compat
+
+import (
+ "context"
+ "net/http"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/gorilla/schema"
+ "github.com/pkg/errors"
+)
+
+// PushImage is the handler for the compat http endpoint for pushing images.
+func PushImage(w http.ResponseWriter, r *http.Request) {
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ query := struct {
+ Tag string `schema:"tag"`
+ }{
+ // This is where you can override the golang default value for one of fields
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ // Note that Docker's docs state "Image name or ID" to be in the path
+ // parameter but it really must be a name as Docker does not allow for
+ // pushing an image by ID.
+ imageName := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
+ if query.Tag != "" {
+ imageName += ":" + query.Tag
+ }
+ if _, err := utils.ParseStorageReference(imageName); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName))
+ return
+ }
+
+ newImage, err := runtime.ImageRuntime().NewFromLocal(imageName)
+ if err != nil {
+ utils.ImageNotFound(w, imageName, errors.Wrapf(err, "Failed to find image %s", imageName))
+ return
+ }
+
+ // TODO: the X-Registry-Auth header is not checked yet here nor in any other
+ // endpoint. Pushing does NOT work with authentication at the moment.
+ dockerRegistryOptions := &image.DockerRegistryOptions{}
+ authfile := ""
+ if sys := runtime.SystemContext(); sys != nil {
+ dockerRegistryOptions.DockerCertPath = sys.DockerCertPath
+ authfile = sys.AuthFilePath
+ }
+
+ err = newImage.PushImageToHeuristicDestination(
+ context.Background(),
+ imageName,
+ "", // manifest type
+ authfile,
+ "", // digest file
+ "", // signature policy
+ os.Stderr,
+ false, // force compression
+ image.SigningOptions{},
+ dockerRegistryOptions,
+ nil, // additional tags
+ )
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Error pushing image %q", imageName))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, "")
+
+}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index 4b24d7d9f..e7f20854c 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -14,7 +14,6 @@ import (
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
- "github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
@@ -254,7 +253,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
return
}
}
- utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesLoadReport{ID: loadedImage})
+ utils.WriteResponse(w, http.StatusOK, entities.ImageLoadReport{Name: loadedImage})
}
func ImagesImport(w http.ResponseWriter, r *http.Request) {
@@ -300,9 +299,13 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
return
}
- utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesImportReport{ID: importedImage})
+ utils.WriteResponse(w, http.StatusOK, entities.ImageImportReport{Id: importedImage})
}
+// ImagesPull is the v2 libpod endpoint for pulling images. Note that the
+// mandatory `reference` must be a reference to a registry (i.e., of docker
+// transport or be normalized to one). Other transports are rejected as they
+// do not make sense in a remote context.
func ImagesPull(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@@ -327,36 +330,27 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
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() {
+
+ imageRef, err := utils.ParseDockerReference(query.Reference)
+ if err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Errorf("reference %q must be a docker reference", query.Reference))
+ errors.Wrapf(err, "image destination %q is not a docker-transport 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
- }
}
+ // Trim the docker-transport prefix.
+ rawImage := strings.TrimPrefix(query.Reference, fmt.Sprintf("%s://", docker.Transport.Name()))
+
// all-tags doesn't work with a tagged reference, so let's check early
- namedRef, err := reference.Parse(query.Reference)
+ namedRef, err := reference.Parse(rawImage)
if err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- errors.Wrapf(err, "error parsing reference %q", query.Reference))
+ errors.Wrapf(err, "error parsing reference %q", rawImage))
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))
+ errors.Errorf("reference %q must not have a tag for all-tags", rawImage))
return
}
@@ -377,7 +371,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
OSChoice: query.OverrideOS,
ArchitectureChoice: query.OverrideArch,
}
- if query.TLSVerify {
+ if _, found := r.URL.Query()["tlsVerify"]; found {
dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
}
@@ -400,13 +394,19 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
}
}
+ authfile := ""
+ if sys := runtime.SystemContext(); sys != nil {
+ dockerRegistryOptions.DockerCertPath = sys.DockerCertPath
+ authfile = sys.AuthFilePath
+ }
+
// Finally pull the images
for _, img := range imagesToPull {
newImage, err := runtime.ImageRuntime().New(
context.Background(),
img,
"",
- "",
+ authfile,
os.Stderr,
&dockerRegistryOptions,
image.SigningOptions{},
@@ -422,6 +422,94 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, res)
}
+// PushImage is the handler for the compat http endpoint for pushing images.
+func PushImage(w http.ResponseWriter, r *http.Request) {
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ query := struct {
+ Credentials string `schema:"credentials"`
+ Destination string `schema:"destination"`
+ TLSVerify bool `schema:"tlsVerify"`
+ }{
+ // This is where you can override the golang default value for one of fields
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ source := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
+ if _, err := utils.ParseStorageReference(source); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", source))
+ return
+ }
+
+ destination := query.Destination
+ if destination == "" {
+ destination = source
+ }
+
+ if _, err := utils.ParseDockerReference(destination); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "image destination %q is not a docker-transport reference", destination))
+ return
+ }
+
+ newImage, err := runtime.ImageRuntime().NewFromLocal(source)
+ if err != nil {
+ utils.ImageNotFound(w, source, errors.Wrapf(err, "Failed to find image %s", source))
+ 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
+ }
+
+ // TODO: the X-Registry-Auth header is not checked yet here nor in any other
+ // endpoint. Pushing does NOT work with authentication at the moment.
+ dockerRegistryOptions := &image.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ }
+ authfile := ""
+ if sys := runtime.SystemContext(); sys != nil {
+ dockerRegistryOptions.DockerCertPath = sys.DockerCertPath
+ authfile = sys.AuthFilePath
+ }
+ if _, found := r.URL.Query()["tlsVerify"]; found {
+ dockerRegistryOptions.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
+ }
+
+ err = newImage.PushImageToHeuristicDestination(
+ context.Background(),
+ destination,
+ "", // manifest type
+ authfile,
+ "", // digest file
+ "", // signature policy
+ os.Stderr,
+ false, // force compression
+ image.SigningOptions{},
+ dockerRegistryOptions,
+ nil, // additional tags
+ )
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Error pushing image %q", destination))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, "")
+}
+
func CommitContainer(w http.ResponseWriter, r *http.Request) {
var (
destImage string
@@ -502,3 +590,29 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: commitImage.ID()}) // nolint
}
+
+func UntagImage(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ name := utils.GetName(r)
+ newImage, err := runtime.ImageRuntime().NewFromLocal(name)
+ if err != nil {
+ utils.ImageNotFound(w, name, errors.Wrapf(err, "Failed to find image %s", name))
+ return
+ }
+ tag := "latest"
+ if len(r.Form.Get("tag")) > 0 {
+ tag = r.Form.Get("tag")
+ }
+ if len(r.Form.Get("repo")) < 1 {
+ utils.Error(w, "repo tag is required", http.StatusBadRequest, errors.New("repo parameter is required to tag an image"))
+ return
+ }
+ repo := r.Form.Get("repo")
+ tagName := fmt.Sprintf("%s:%s", repo, tag)
+ if err := newImage.UntagImage(tagName); err != nil {
+ utils.Error(w, "failed to untag", http.StatusInternalServerError, err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusCreated, "")
+}
diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go
index 52763a050..33a9fdd58 100644
--- a/pkg/api/handlers/swagger.go
+++ b/pkg/api/handlers/swagger.go
@@ -31,14 +31,14 @@ type swagImageInspect struct {
// swagger:response DocsLibpodImagesLoadResponse
type swagLibpodImagesLoadResponse struct {
// in:body
- Body []LibpodImagesLoadReport
+ Body entities.ImageLoadReport
}
// Import response
// swagger:response DocsLibpodImagesImportResponse
type swagLibpodImagesImportResponse struct {
// in:body
- Body LibpodImagesImportReport
+ Body entities.ImageImportReport
}
// Pull response
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 89a571e67..496512f2e 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -38,10 +38,6 @@ type LibpodImagesLoadReport struct {
ID string `json:"id"`
}
-type LibpodImagesImportReport struct {
- ID string `json:"id"`
-}
-
type LibpodImagesPullReport struct {
ID string `json:"id"`
}
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index 696d5f745..1c67de9db 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -4,11 +4,52 @@ import (
"fmt"
"net/http"
+ "github.com/containers/image/v5/docker"
+ "github.com/containers/image/v5/storage"
+ "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/gorilla/schema"
+ "github.com/pkg/errors"
)
+// ParseDockerReference parses the specified image name to a
+// `types.ImageReference` and enforces it to refer to a docker-transport
+// reference.
+func ParseDockerReference(name string) (types.ImageReference, error) {
+ dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+ imageRef, err := alltransports.ParseImageName(name)
+ if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
+ return nil, errors.Errorf("reference %q must be a docker reference", name)
+ } else if err != nil {
+ origErr := err
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, name))
+ if err != nil {
+ return nil, errors.Wrapf(origErr, "reference %q must be a docker reference", name)
+ }
+ }
+ return imageRef, nil
+}
+
+// ParseStorageReference parses the specified image name to a
+// `types.ImageReference` and enforces it to refer to a
+// containers-storage-transport reference.
+func ParseStorageReference(name string) (types.ImageReference, error) {
+ storagePrefix := fmt.Sprintf("%s:", storage.Transport.Name())
+ imageRef, err := alltransports.ParseImageName(name)
+ if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
+ return nil, errors.Errorf("reference %q must be a storage reference", name)
+ } else if err != nil {
+ origErr := err
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", storagePrefix, name))
+ if err != nil {
+ return nil, errors.Wrapf(origErr, "reference %q must be a storage reference", name)
+ }
+ }
+ return imageRef, nil
+}
+
// GetImages is a common function used to get images for libpod and other compatibility
// mechanisms
func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) {
diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go
index 79d1a5090..d47053eda 100644
--- a/pkg/api/handlers/utils/pods.go
+++ b/pkg/api/handlers/utils/pods.go
@@ -59,6 +59,10 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
if err != nil {
return nil, err
}
+ infraId, err := pod.InfraContainerID()
+ if err != nil {
+ return nil, err
+ }
lp := entities.ListPodsReport{
Cgroup: pod.CgroupParent(),
Created: pod.CreatedTime(),
@@ -66,6 +70,7 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
Name: pod.Name(),
Namespace: pod.Namespace(),
Status: status,
+ InfraId: infraId,
}
for _, ctr := range ctrs {
state, err := ctr.State()
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 08834ff01..145c054c0 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -587,6 +587,29 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
r.HandleFunc(VersionedPath("/containers/{name}/resize"), s.APIHandler(compat.ResizeContainer)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
r.HandleFunc("/containers/{name}/resize", s.APIHandler(compat.ResizeContainer)).Methods(http.MethodPost)
+ // swagger:operation GET /containers/{name}/export compat exportContainer
+ // ---
+ // tags:
+ // - containers (compat)
+ // summary: Export a container
+ // description: Export the contents of a container as a tarball.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the container
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: tarball is returned in body
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/containers/{name}/export"), s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
+ r.HandleFunc("/containers/{name}/export", s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
/*
libpod endpoints
@@ -1237,5 +1260,27 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/resize"), s.APIHandler(compat.ResizeContainer)).Methods(http.MethodPost)
+ // swagger:operation GET /libpod/containers/{name}/export libpod libpodExportContainer
+ // ---
+ // tags:
+ // - containers
+ // summary: Export a container
+ // description: Export the contents of a container as a tarball.
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name or ID of the container
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: tarball is returned in body
+ // 404:
+ // $ref: "#/responses/NoSuchContainer"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/containers/{name}/export"), s.APIHandler(compat.ExportContainer)).Methods(http.MethodGet)
return nil
}
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index e8dfe2fa8..e4e46025b 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -211,6 +211,41 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
r.Handle(VersionedPath("/images/{name:.*}"), s.APIHandler(compat.RemoveImage)).Methods(http.MethodDelete)
// Added non version path to URI to support docker non versioned paths
r.Handle("/images/{name:.*}", s.APIHandler(compat.RemoveImage)).Methods(http.MethodDelete)
+ // swagger:operation POST /images/{name:.*}/push compat pushImage
+ // ---
+ // tags:
+ // - images (compat)
+ // summary: Push Image
+ // description: Push an image to a container registry
+ // parameters:
+ // - in: path
+ // name: name:.*
+ // type: string
+ // required: true
+ // description: Name of image to push.
+ // - in: query
+ // name: tag
+ // type: string
+ // description: The tag to associate with the image on the registry.
+ // - in: header
+ // name: X-Registry-Auth
+ // type: string
+ // description: A base64-encoded auth configuration.
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: no error
+ // schema:
+ // type: string
+ // format: binary
+ // 404:
+ // $ref: '#/responses/NoSuchImage'
+ // 500:
+ // $ref: '#/responses/InternalError'
+ r.Handle(VersionedPath("/images/{name:.*}/push"), s.APIHandler(compat.PushImage)).Methods(http.MethodPost)
+ // Added non version path to URI to support docker non versioned paths
+ r.Handle("/images/{name:.*}/push", s.APIHandler(compat.PushImage)).Methods(http.MethodPost)
// swagger:operation GET /images/{name:.*}/get compat exportImage
// ---
// tags:
@@ -583,6 +618,43 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
libpod endpoints
*/
+ // swagger:operation POST /libpod/images/{name:.*}/push libpod libpodPushImage
+ // ---
+ // tags:
+ // - images (libpod)
+ // summary: Push Image
+ // description: Push an image to a container registry
+ // parameters:
+ // - in: path
+ // name: name:.*
+ // type: string
+ // required: true
+ // description: Name of image to push.
+ // - in: query
+ // name: tag
+ // type: string
+ // description: The tag to associate with the image on the registry.
+ // - in: query
+ // name: credentials
+ // description: username:password for the registry.
+ // type: string
+ // - in: header
+ // name: X-Registry-Auth
+ // type: string
+ // description: A base64-encoded auth configuration.
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // description: no error
+ // schema:
+ // type: string
+ // format: binary
+ // 404:
+ // $ref: '#/responses/NoSuchImage'
+ // 500:
+ // $ref: '#/responses/InternalError'
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/push"), s.APIHandler(libpod.PushImage)).Methods(http.MethodPost)
// swagger:operation GET /libpod/images/{name:.*}/exists libpod libpodImageExists
// ---
// tags:
@@ -1019,5 +1091,39 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/commit"), s.APIHandler(libpod.CommitContainer)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/images/{name:.*}/untag libpod libpodUntagImage
+ // ---
+ // tags:
+ // - images
+ // summary: Untag an image
+ // description: Untag an image
+ // parameters:
+ // - in: path
+ // name: name:.*
+ // type: string
+ // required: true
+ // description: the name or ID of the container
+ // - in: query
+ // name: repo
+ // type: string
+ // description: the repository to untag
+ // - in: query
+ // name: tag
+ // type: string
+ // description: the name of the tag to untag
+ // produces:
+ // - application/json
+ // responses:
+ // 201:
+ // description: no error
+ // 400:
+ // $ref: '#/responses/BadParamError'
+ // 404:
+ // $ref: '#/responses/NoSuchImage'
+ // 409:
+ // $ref: '#/responses/ConflictError'
+ // 500:
+ // $ref: '#/responses/InternalError'
+ r.Handle(VersionedPath("/libpod/images/{name:.*}/untag"), s.APIHandler(libpod.UntagImage)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index bad1294f4..49a2dfd58 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -2,6 +2,7 @@ package containers
import (
"context"
+ "io"
"net/http"
"net/url"
"strconv"
@@ -296,3 +297,22 @@ func Stop(ctx context.Context, nameOrID string, timeout *uint) error {
}
return response.Process(nil)
}
+
+// Export creates a tarball of the given name or ID of a container. It
+// requires an io.Writer be provided to write the tarball.
+func Export(ctx context.Context, nameOrID string, w io.Writer) error {
+ params := url.Values{}
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/export", params, nameOrID)
+ if err != nil {
+ return err
+ }
+ if response.StatusCode/100 == 2 {
+ _, err = io.Copy(w, response.Body)
+ return err
+ }
+ return response.Process(nil)
+}
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index 5e3af7a60..dcb568d6b 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -3,15 +3,16 @@ package images
import (
"context"
"errors"
+ "fmt"
"io"
"net/http"
"net/url"
"strconv"
+ "github.com/containers/image/v5/types"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
- "github.com/containers/libpod/pkg/inspect"
)
// Exists a lightweight way to determine if an image exists in local storage. It returns a
@@ -56,7 +57,7 @@ func List(ctx context.Context, all *bool, filters map[string][]string) ([]*entit
// Get performs an image inspect. To have the on-disk size of the image calculated, you can
// use the optional size parameter.
-func GetImage(ctx context.Context, nameOrID string, size *bool) (*inspect.ImageData, error) {
+func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.ImageData, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
@@ -65,7 +66,7 @@ func GetImage(ctx context.Context, nameOrID string, size *bool) (*inspect.ImageD
if size != nil {
params.Set("size", strconv.FormatBool(*size))
}
- inspectedData := inspect.ImageData{}
+ inspectedData := entities.ImageData{}
response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID)
if err != nil {
return &inspectedData, err
@@ -91,11 +92,11 @@ func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse,
return history, response.Process(&history)
}
-func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
- var id handlers.IDResponse
+func Load(ctx context.Context, r io.Reader, name *string) (*entities.ImageLoadReport, error) {
+ var report entities.ImageLoadReport
conn, err := bindings.GetClient(ctx)
if err != nil {
- return "", err
+ return nil, err
}
params := url.Values{}
if name != nil {
@@ -103,9 +104,9 @@ func Load(ctx context.Context, r io.Reader, name *string) (string, error) {
}
response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
if err != nil {
- return "", err
+ return nil, err
}
- return id.ID, response.Process(&id)
+ return &report, response.Process(&report)
}
// Remove deletes an image from local storage. The optional force parameter will forcibly remove
@@ -196,19 +197,35 @@ func Tag(ctx context.Context, nameOrID, tag, repo string) error {
return response.Process(nil)
}
+// Untag removes a name from locally-stored image. Both the tag and repo parameters are required.
+func Untag(ctx context.Context, nameOrID, tag, repo string) error {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ params := url.Values{}
+ params.Set("tag", tag)
+ params.Set("repo", repo)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nameOrID)
+ if err != nil {
+ return err
+ }
+ return response.Process(nil)
+}
+
func Build(nameOrId string) {}
// Imports adds the given image to the local image store. This can be done by file and the given reader
// or via the url parameter. Additional metadata can be associated with the image by using the changes and
// message parameters. The image can also be tagged given a reference. One of url OR r must be provided.
-func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (string, error) {
- var id handlers.IDResponse
+func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (*entities.ImageImportReport, error) {
+ var report entities.ImageImportReport
if r != nil && u != nil {
- return "", errors.New("url and r parameters cannot be used together")
+ return nil, errors.New("url and r parameters cannot be used together")
}
conn, err := bindings.GetClient(ctx)
if err != nil {
- return "", err
+ return nil, err
}
params := url.Values{}
for _, change := range changes {
@@ -225,7 +242,68 @@ func Import(ctx context.Context, changes []string, message, reference, u *string
}
response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params)
if err != nil {
- return "", err
+ return nil, err
+ }
+ return &report, response.Process(&report)
+}
+
+// Pull is the binding for libpod's v2 endpoints for pulling images. Note that
+// `rawImage` must be a reference to a registry (i.e., of docker transport or be
+// normalized to one). Other transports are rejected as they do not make sense
+// in a remote context.
+func Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) ([]string, error) {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ params.Set("reference", rawImage)
+ params.Set("credentials", options.Credentials)
+ params.Set("overrideArch", options.OverrideArch)
+ params.Set("overrideOS", options.OverrideOS)
+ if options.TLSVerify != types.OptionalBoolUndefined {
+ val := bool(options.TLSVerify == types.OptionalBoolTrue)
+ params.Set("tlsVerify", strconv.FormatBool(val))
+ }
+ params.Set("allTags", strconv.FormatBool(options.AllTags))
+
+ response, err := conn.DoRequest(nil, http.MethodPost, "/images/pull", params)
+ if err != nil {
+ return nil, err
+ }
+
+ reports := []handlers.LibpodImagesPullReport{}
+ if err := response.Process(&reports); err != nil {
+ return nil, err
+ }
+
+ pulledImages := []string{}
+ for _, r := range reports {
+ pulledImages = append(pulledImages, r.ID)
}
- return id.ID, response.Process(&id)
+
+ return pulledImages, nil
+}
+
+// Push is the binding for libpod's v2 endpoints for push images. Note that
+// `source` must be a refering to an image in the remote's container storage.
+// The destination must be a reference to a registry (i.e., of docker transport
+// or be normalized to one). Other transports are rejected as they do not make
+// sense in a remote context.
+func Push(ctx context.Context, source string, destination string, options entities.ImagePushOptions) error {
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ params := url.Values{}
+ params.Set("credentials", options.Credentials)
+ params.Set("destination", destination)
+ if options.TLSVerify != types.OptionalBoolUndefined {
+ val := bool(options.TLSVerify == types.OptionalBoolTrue)
+ params.Set("tlsVerify", strconv.FormatBool(val))
+ }
+
+ path := fmt.Sprintf("/images/%s/push", source)
+ _, err = conn.DoRequest(nil, http.MethodPost, path, params)
+ return err
}
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index 13b6086c3..992720196 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -9,6 +9,7 @@ import (
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/bindings/images"
+ "github.com/containers/libpod/pkg/domain/entities"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
@@ -218,7 +219,7 @@ var _ = Describe("Podman images", func() {
Expect(err).To(BeNil())
names, err := images.Load(bt.conn, f, nil)
Expect(err).To(BeNil())
- Expect(names).To(Equal(alpine.name))
+ Expect(names.Name).To(Equal(alpine.name))
exists, err = images.Exists(bt.conn, alpine.name)
Expect(err).To(BeNil())
Expect(exists).To(BeTrue())
@@ -234,7 +235,7 @@ var _ = Describe("Podman images", func() {
newName := "quay.io/newname:fizzle"
names, err = images.Load(bt.conn, f, &newName)
Expect(err).To(BeNil())
- Expect(names).To(Equal(alpine.name))
+ Expect(names.Name).To(Equal(alpine.name))
exists, err = images.Exists(bt.conn, newName)
Expect(err).To(BeNil())
Expect(exists).To(BeTrue())
@@ -353,4 +354,24 @@ var _ = Describe("Podman images", func() {
Expect(results).To(ContainElement("docker.io/library/alpine:latest"))
})
+ // TODO: we really need to extent to pull tests once we have a more sophisticated CI.
+ It("Image Pull", func() {
+ rawImage := "docker.io/library/busybox:latest"
+
+ pulledImages, err := images.Pull(bt.conn, rawImage, entities.ImagePullOptions{})
+ Expect(err).To(BeNil())
+ Expect(len(pulledImages)).To(Equal(1))
+
+ exists, err := images.Exists(bt.conn, rawImage)
+ Expect(err).To(BeNil())
+ Expect(exists).To(BeTrue())
+
+ // Make sure the normalization AND the full-transport reference works.
+ _, err = images.Pull(bt.conn, "docker://"+rawImage, entities.ImagePullOptions{})
+ Expect(err).To(BeNil())
+
+ // The v2 endpoint only supports the docker transport. Let's see if that's really true.
+ _, err = images.Pull(bt.conn, "bogus-transport:bogus.com/image:reference", entities.ImagePullOptions{})
+ Expect(err).To(Not(BeNil()))
+ })
})
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 3389e4db5..d51124f55 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -98,12 +98,6 @@ type RmReport struct {
Id string
}
-type ContainerInspectOptions struct {
- Format string
- Latest bool
- Size bool
-}
-
type ContainerInspectReport struct {
*define.InspectContainerData
}
@@ -123,3 +117,7 @@ type CommitOptions struct {
type CommitReport struct {
Id string
}
+
+type ContainerExportOptions struct {
+ Output string
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index dddaa6013..a122857cd 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -2,34 +2,38 @@ package entities
import (
"context"
+
+ "github.com/containers/libpod/libpod/define"
)
type ContainerEngine interface {
ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error)
ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error)
- ContainerInspect(ctx context.Context, namesOrIds []string, options ContainerInspectOptions) ([]*ContainerInspectReport, error)
+ ContainerInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]*ContainerInspectReport, error)
+ ContainerExport(ctx context.Context, nameOrId string, options ContainerExportOptions) error
ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error)
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
- ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
- ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
ContainerTop(ctx context.Context, options TopOptions) (*StringSliceReport, error)
+ ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
+ ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
+ HealthCheckRun(ctx context.Context, nameOrId string, options HealthCheckOptions) (*define.HealthCheckResults, error)
PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error)
PodExists(ctx context.Context, nameOrId string) (*BoolReport, error)
PodKill(ctx context.Context, namesOrIds []string, options PodKillOptions) ([]*PodKillReport, error)
PodPause(ctx context.Context, namesOrIds []string, options PodPauseOptions) ([]*PodPauseReport, error)
+ PodPs(ctx context.Context, options PodPSOptions) ([]*ListPodsReport, error)
PodRestart(ctx context.Context, namesOrIds []string, options PodRestartOptions) ([]*PodRestartReport, error)
+ PodRm(ctx context.Context, namesOrIds []string, options PodRmOptions) ([]*PodRmReport, error)
PodStart(ctx context.Context, namesOrIds []string, options PodStartOptions) ([]*PodStartReport, error)
PodStop(ctx context.Context, namesOrIds []string, options PodStopOptions) ([]*PodStopReport, error)
- PodRm(ctx context.Context, namesOrIds []string, options PodRmOptions) ([]*PodRmReport, error)
- PodUnpause(ctx context.Context, namesOrIds []string, options PodunpauseOptions) ([]*PodUnpauseReport, error)
PodTop(ctx context.Context, options PodTopOptions) (*StringSliceReport, error)
-
+ PodUnpause(ctx context.Context, namesOrIds []string, options PodunpauseOptions) ([]*PodUnpauseReport, error)
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
- VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
- VolumePrune(ctx context.Context, opts VolumePruneOptions) ([]*VolumePruneReport, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
+ VolumePrune(ctx context.Context, opts VolumePruneOptions) ([]*VolumePruneReport, error)
+ VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)
}
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index d0c860a04..04b9d34e6 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -8,6 +8,13 @@ type ImageEngine interface {
Delete(ctx context.Context, nameOrId []string, opts ImageDeleteOptions) (*ImageDeleteReport, error)
Exists(ctx context.Context, nameOrId string) (*BoolReport, error)
History(ctx context.Context, nameOrId string, opts ImageHistoryOptions) (*ImageHistoryReport, error)
+ Inspect(ctx context.Context, names []string, opts InspectOptions) (*ImageInspectReport, error)
List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error)
Prune(ctx context.Context, opts ImagePruneOptions) (*ImagePruneReport, error)
+ Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
+ Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error
+ Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error
+ Load(ctx context.Context, opts ImageLoadOptions) (*ImageLoadReport, error)
+ Import(ctx context.Context, opts ImageImportOptions) (*ImageImportReport, error)
+ Push(ctx context.Context, source string, destination string, opts ImagePushOptions) error
}
diff --git a/pkg/domain/entities/healthcheck.go b/pkg/domain/entities/healthcheck.go
new file mode 100644
index 000000000..a880805f9
--- /dev/null
+++ b/pkg/domain/entities/healthcheck.go
@@ -0,0 +1,3 @@
+package entities
+
+type HealthCheckOptions struct{}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 20af0356f..d66de3c5e 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -4,6 +4,8 @@ import (
"net/url"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/pkg/inspect"
docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/opencontainers/go-digest"
@@ -11,7 +13,6 @@ import (
)
type Image struct {
- IdOrNamed
ID string `json:"Id"`
RepoTags []string `json:",omitempty"`
RepoDigests []string `json:",omitempty"`
@@ -110,11 +111,74 @@ type ImageHistoryReport struct {
Layers []ImageHistoryLayer
}
-type ImageInspectOptions struct {
- TypeObject string `json:",omitempty"`
- Format string `json:",omitempty"`
- Size bool `json:",omitempty"`
- Latest bool `json:",omitempty"`
+// ImagePullOptions are the arguments for pulling images.
+type ImagePullOptions struct {
+ // AllTags can be specified to pull all tags of the spiecifed image. Note
+ // that this only works if the specified image does not include a tag.
+ AllTags bool
+ // Authfile is the path to the authentication file. Ignored for remote
+ // calls.
+ Authfile string
+ // CertDir is the path to certificate directories. Ignored for remote
+ // calls.
+ CertDir string
+ // Credentials for authenticating against the registry in the format
+ // USERNAME:PASSWORD.
+ Credentials string
+ // OverrideArch will overwrite the local architecture for image pulls.
+ OverrideArch string
+ // OverrideOS will overwrite the local operating system (OS) for image
+ // pulls.
+ OverrideOS string
+ // Quiet can be specified to suppress pull progress when pulling. Ignored
+ // for remote calls.
+ Quiet bool
+ // SignaturePolicy to use when pulling. Ignored for remote calls.
+ SignaturePolicy string
+ // TLSVerify to enable/disable HTTPS and certificate verification.
+ TLSVerify types.OptionalBool
+}
+
+// ImagePullReport is the response from pulling one or more images.
+type ImagePullReport struct {
+ Images []string
+}
+
+// ImagePushOptions are the arguments for pushing images.
+type ImagePushOptions struct {
+ // Authfile is the path to the authentication file. Ignored for remote
+ // calls.
+ Authfile string
+ // CertDir is the path to certificate directories. Ignored for remote
+ // calls.
+ CertDir string
+ // Compress tarball image layers when pushing to a directory using the 'dir'
+ // transport. Default is same compression type as source. Ignored for remote
+ // calls.
+ Compress bool
+ // Credentials for authenticating against the registry in the format
+ // USERNAME:PASSWORD.
+ Credentials string
+ // DigestFile, after copying the image, write the digest of the resulting
+ // image to the file. Ignored for remote calls.
+ DigestFile string
+ // Format is the Manifest type (oci, v2s1, or v2s2) to use when pushing an
+ // image using the 'dir' transport. Default is manifest type of source.
+ // Ignored for remote calls.
+ Format string
+ // Quiet can be specified to suppress pull progress when pulling. Ignored
+ // for remote calls.
+ Quiet bool
+ // RemoveSignatures, discard any pre-existing signatures in the image.
+ // Ignored for remote calls.
+ RemoveSignatures bool
+ // SignaturePolicy to use when pulling. Ignored for remote calls.
+ SignaturePolicy string
+ // SignBy adds a signature at the destination using the specified key.
+ // Ignored for remote calls.
+ SignBy string
+ // TLSVerify to enable/disable HTTPS and certificate verification.
+ TLSVerify types.OptionalBool
}
type ImageListOptions struct {
@@ -123,10 +187,6 @@ type ImageListOptions struct {
Filters url.Values `json:"filters" schema:"filters"`
}
-// type ImageListReport struct {
-// Images []ImageSummary
-// }
-
type ImagePruneOptions struct {
All bool `json:"all" schema:"all"`
Filter []string `json:"filter" schema:"filter"`
@@ -137,3 +197,40 @@ type ImagePruneReport struct {
Report Report
Size int64
}
+
+type ImageTagOptions struct{}
+type ImageUntagOptions struct{}
+
+type ImageData struct {
+ *inspect.ImageData
+}
+
+type ImageInspectReport struct {
+ Images []*ImageData
+ Errors map[string]error
+}
+
+type ImageLoadOptions struct {
+ Name string
+ Tag string
+ Input string
+ Quiet bool
+ SignaturePolicy string
+}
+
+type ImageLoadReport struct {
+ Name string
+}
+
+type ImageImportOptions struct {
+ Changes []string
+ Message string
+ Quiet bool
+ Reference string
+ Source string
+ SourceIsURL bool
+}
+
+type ImageImportReport struct {
+ Id string
+}
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index d92d1bc7a..a0b2c6cec 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -22,6 +22,7 @@ type ListPodsReport struct {
Containers []*ListPodContainer
Created time.Time
Id string
+ InfraId string
Name string
Namespace string
Status string
@@ -151,3 +152,15 @@ type PodTopOptions struct {
Descriptors []string
NameOrID string
}
+
+type PodPSOptions struct {
+ CtrNames bool
+ CtrIds bool
+ CtrStatus bool
+ Filters map[string][]string
+ Format string
+ Latest bool
+ Namespace bool
+ Quiet bool
+ Sort string
+}
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index a1a729584..dd7aaa07f 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -42,3 +42,10 @@ type NetOptions struct {
StaticIP *net.IP
StaticMAC *net.HardwareAddr
}
+
+// All CLI inspect commands and inspect sub-commands use the same options
+type InspectOptions struct {
+ Format string `json:",omitempty"`
+ Latest bool `json:",omitempty"`
+ Size bool `json:",omitempty"`
+}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index d25af24c5..d4c5ac311 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -243,7 +243,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return reports, nil
}
-func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.ContainerInspectOptions) ([]*entities.ContainerInspectReport, error) {
+func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) {
var reports []*entities.ContainerInspectReport
ctrs, err := shortcuts.GetContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
@@ -325,3 +325,11 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string,
}
return &entities.CommitReport{Id: newImage.ID()}, nil
}
+
+func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string, options entities.ContainerExportOptions) error {
+ ctr, err := ic.Libpod.LookupContainer(nameOrId)
+ if err != nil {
+ return err
+ }
+ return ctr.Export(options.Output)
+}
diff --git a/pkg/domain/infra/abi/healthcheck.go b/pkg/domain/infra/abi/healthcheck.go
new file mode 100644
index 000000000..699483243
--- /dev/null
+++ b/pkg/domain/infra/abi/healthcheck.go
@@ -0,0 +1,26 @@
+// +build ABISupport
+
+package abi
+
+import (
+ "context"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/domain/entities"
+)
+
+func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrId string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) {
+ status, err := ic.Libpod.HealthCheck(nameOrId)
+ if err != nil {
+ return nil, err
+ }
+ hcStatus := "unhealthy"
+ if status == libpod.HealthCheckSuccess {
+ hcStatus = "healthy"
+ }
+ report := define.HealthCheckResults{
+ Status: hcStatus,
+ }
+ return &report, nil
+}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 44420c1e1..94008f287 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -5,11 +5,25 @@ package abi
import (
"context"
"fmt"
+ "io"
+ "os"
+ "strings"
+ "github.com/containers/image/v5/docker"
+ dockerarchive "github.com/containers/image/v5/docker/archive"
+ "github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/transports/alltransports"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/libpod/libpod/image"
libpodImage "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
+ domainUtils "github.com/containers/libpod/pkg/domain/utils"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/storage"
+ imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
@@ -134,6 +148,178 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer
return l
}
+func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) (*entities.ImagePullReport, error) {
+ var writer io.Writer
+ if !options.Quiet {
+ writer = os.Stderr
+ }
+
+ dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+ imageRef, err := alltransports.ParseImageName(rawImage)
+ if err != nil {
+ imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, rawImage))
+ if err != nil {
+ return nil, errors.Errorf("invalid image reference %q", rawImage)
+ }
+ }
+
+ // Special-case for docker-archive which allows multiple tags.
+ if imageRef.Transport().Name() == dockerarchive.Transport.Name() {
+ newImage, err := ir.Libpod.ImageRuntime().LoadFromArchiveReference(ctx, imageRef, options.SignaturePolicy, writer)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error pulling image %q", rawImage)
+ }
+ return &entities.ImagePullReport{Images: []string{newImage[0].ID()}}, nil
+ }
+
+ var registryCreds *types.DockerAuthConfig
+ if options.Credentials != "" {
+ creds, err := util.ParseRegistryCreds(options.Credentials)
+ if err != nil {
+ return nil, err
+ }
+ registryCreds = creds
+ }
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ DockerCertPath: options.CertDir,
+ OSChoice: options.OverrideOS,
+ ArchitectureChoice: options.OverrideArch,
+ DockerInsecureSkipTLSVerify: options.TLSVerify,
+ }
+
+ if !options.AllTags {
+ newImage, err := ir.Libpod.ImageRuntime().New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error pulling image %q", rawImage)
+ }
+ return &entities.ImagePullReport{Images: []string{newImage.ID()}}, nil
+ }
+
+ // --all-tags requires the docker transport
+ if imageRef.Transport().Name() != docker.Transport.Name() {
+ return nil, errors.New("--all-tags requires docker transport")
+ }
+
+ // Trim the docker-transport prefix.
+ rawImage = strings.TrimPrefix(rawImage, docker.Transport.Name())
+
+ // all-tags doesn't work with a tagged reference, so let's check early
+ namedRef, err := reference.Parse(rawImage)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing %q", rawImage)
+ }
+ if _, isTagged := namedRef.(reference.Tagged); isTagged {
+ return nil, errors.New("--all-tags requires a reference without a tag")
+
+ }
+
+ systemContext := image.GetSystemContext("", options.Authfile, false)
+ tags, err := docker.GetRepositoryTags(ctx, systemContext, imageRef)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting repository tags")
+ }
+
+ var foundIDs []string
+ for _, tag := range tags {
+ name := rawImage + ":" + tag
+ newImage, err := ir.Libpod.ImageRuntime().New(ctx, name, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ if err != nil {
+ logrus.Errorf("error pulling image %q", name)
+ continue
+ }
+ foundIDs = append(foundIDs, newImage.ID())
+ }
+
+ if len(tags) != len(foundIDs) {
+ return nil, errors.Errorf("error pulling image %q", rawImage)
+ }
+ return &entities.ImagePullReport{Images: foundIDs}, nil
+}
+
+func (ir *ImageEngine) Inspect(ctx context.Context, names []string, opts entities.InspectOptions) (*entities.ImageInspectReport, error) {
+ report := entities.ImageInspectReport{
+ Errors: make(map[string]error),
+ }
+
+ for _, id := range names {
+ img, err := ir.Libpod.ImageRuntime().NewFromLocal(id)
+ if err != nil {
+ report.Errors[id] = err
+ continue
+ }
+
+ results, err := img.Inspect(ctx)
+ if err != nil {
+ report.Errors[id] = err
+ continue
+ }
+
+ cookedResults := entities.ImageData{}
+ _ = domainUtils.DeepCopy(&cookedResults, results)
+ report.Images = append(report.Images, &cookedResults)
+ }
+ return &report, nil
+}
+
+func (ir *ImageEngine) Push(ctx context.Context, source string, destination string, options entities.ImagePushOptions) error {
+ var writer io.Writer
+ if !options.Quiet {
+ writer = os.Stderr
+ }
+
+ var manifestType string
+ switch options.Format {
+ case "":
+ // Default
+ case "oci":
+ manifestType = imgspecv1.MediaTypeImageManifest
+ case "v2s1":
+ manifestType = manifest.DockerV2Schema1SignedMediaType
+ case "v2s2", "docker":
+ manifestType = manifest.DockerV2Schema2MediaType
+ default:
+ return fmt.Errorf("unknown format %q. Choose on of the supported formats: 'oci', 'v2s1', or 'v2s2'", options.Format)
+ }
+
+ var registryCreds *types.DockerAuthConfig
+ if options.Credentials != "" {
+ creds, err := util.ParseRegistryCreds(options.Credentials)
+ if err != nil {
+ return err
+ }
+ registryCreds = creds
+ }
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ DockerCertPath: options.CertDir,
+ DockerInsecureSkipTLSVerify: options.TLSVerify,
+ }
+
+ signOptions := image.SigningOptions{
+ RemoveSignatures: options.RemoveSignatures,
+ SignBy: options.SignBy,
+ }
+
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(source)
+ if err != nil {
+ return err
+ }
+
+ return newImage.PushImageToHeuristicDestination(
+ ctx,
+ destination,
+ manifestType,
+ options.Authfile,
+ options.DigestFile,
+ options.SignaturePolicy,
+ writer,
+ options.Compress,
+ signOptions,
+ &dockerRegistryOptions,
+ nil)
+}
+
// func (r *imageRuntime) Delete(ctx context.Context, nameOrId string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
// image, err := r.libpod.ImageEngine().NewFromLocal(nameOrId)
// if err != nil {
@@ -146,7 +332,7 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer
// }
//
// report := entities.ImageDeleteReport{}
-// if err := utils.DeepCopy(&report, results); err != nil {
+// if err := domainUtils.DeepCopy(&report, results); err != nil {
// return nil, err
// }
// return &report, nil
@@ -164,3 +350,58 @@ func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer
// copy(report.Report.Id, id)
// return &report, nil
// }
+
+func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error {
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+ if err != nil {
+ return err
+ }
+ for _, tag := range tags {
+ if err := newImage.TagImage(tag); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error {
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+ if err != nil {
+ return err
+ }
+ for _, tag := range tags {
+ if err := newImage.UntagImage(tag); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) {
+ var (
+ writer io.Writer
+ )
+ if !opts.Quiet {
+ writer = os.Stderr
+ }
+ name, err := ir.Libpod.LoadImage(ctx, opts.Name, opts.Input, writer, opts.SignaturePolicy)
+ if err != nil {
+ return nil, err
+ }
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(name)
+ if err != nil {
+ return nil, errors.Wrap(err, "image loaded but no additional tags were created")
+ }
+ if err := newImage.TagImage(opts.Name); err != nil {
+ return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName)
+ }
+ return &entities.ImageLoadReport{Name: name}, nil
+}
+
+func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) {
+ id, err := ir.Libpod.Import(ctx, opts.Source, opts.Reference, opts.Changes, opts.Message, opts.Quiet)
+ if err != nil {
+ return nil, err
+ }
+ return &entities.ImageImportReport{Id: id}, nil
+}
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 8abcc6e4b..494a048ec 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/libpod/podfilters"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/signal"
"github.com/containers/libpod/pkg/specgen"
@@ -272,3 +273,61 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp
report.Value, err = pod.GetPodPidInformation(options.Descriptors)
return report, err
}
+
+func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
+ var (
+ filters []libpod.PodFilter
+ reports []*entities.ListPodsReport
+ )
+ for k, v := range options.Filters {
+ for _, filter := range v {
+ f, err := podfilters.GeneratePodFilterFunc(k, filter)
+ if err != nil {
+ return nil, err
+ }
+ filters = append(filters, f)
+
+ }
+ }
+ pds, err := ic.Libpod.Pods(filters...)
+ if err != nil {
+ return nil, err
+ }
+ for _, p := range pds {
+ var lpcs []*entities.ListPodContainer
+ status, err := p.GetPodStatus()
+ if err != nil {
+ return nil, err
+ }
+ cons, err := p.AllContainers()
+ if err != nil {
+ return nil, err
+ }
+ for _, c := range cons {
+ state, err := c.State()
+ if err != nil {
+ return nil, err
+ }
+ lpcs = append(lpcs, &entities.ListPodContainer{
+ Id: c.ID(),
+ Names: c.Name(),
+ Status: state.String(),
+ })
+ }
+ infraId, err := p.InfraContainerID()
+ if err != nil {
+ return nil, err
+ }
+ reports = append(reports, &entities.ListPodsReport{
+ Cgroup: p.CgroupParent(),
+ Containers: lpcs,
+ Created: p.CreatedTime(),
+ Id: p.ID(),
+ InfraId: infraId,
+ Name: p.Name(),
+ Namespace: p.Namespace(),
+ Status: status,
+ })
+ }
+ return reports, nil
+}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 3c8be90dc..8885ae7c7 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -2,6 +2,8 @@ package tunnel
import (
"context"
+ "io"
+ "os"
"github.com/containers/image/v5/docker/reference"
@@ -142,7 +144,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return reports, nil
}
-func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.ContainerInspectOptions) ([]*entities.ContainerInspectReport, error) {
+func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) {
var (
reports []*entities.ContainerInspectReport
)
@@ -210,3 +212,17 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string,
}
return &entities.CommitReport{Id: response.ID}, nil
}
+
+func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string, options entities.ContainerExportOptions) error {
+ var (
+ err error
+ w io.Writer
+ )
+ if len(options.Output) > 0 {
+ w, err = os.Create(options.Output)
+ if err != nil {
+ return err
+ }
+ }
+ return containers.Export(ic.ClientCxt, nameOrId, w)
+}
diff --git a/pkg/domain/infra/tunnel/healthcheck.go b/pkg/domain/infra/tunnel/healthcheck.go
new file mode 100644
index 000000000..e589489b3
--- /dev/null
+++ b/pkg/domain/infra/tunnel/healthcheck.go
@@ -0,0 +1,13 @@
+package tunnel
+
+import (
+ "context"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/bindings/containers"
+ "github.com/containers/libpod/pkg/domain/entities"
+)
+
+func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrId string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) {
+ return containers.RunHealthCheck(ic.ClientCxt, nameOrId)
+}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 6a3adc9ee..028603d98 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -2,10 +2,13 @@ package tunnel
import (
"context"
+ "os"
+ "github.com/containers/image/v5/docker/reference"
images "github.com/containers/libpod/pkg/bindings/images"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/utils"
+ "github.com/pkg/errors"
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
@@ -85,3 +88,103 @@ func (ir *ImageEngine) Prune(ctx context.Context, opts entities.ImagePruneOption
}
return &report, nil
}
+
+func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) (*entities.ImagePullReport, error) {
+ pulledImages, err := images.Pull(ir.ClientCxt, rawImage, options)
+ if err != nil {
+ return nil, err
+ }
+ return &entities.ImagePullReport{Images: pulledImages}, nil
+}
+
+func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error {
+ for _, newTag := range tags {
+ var (
+ tag, repo string
+ )
+ ref, err := reference.Parse(newTag)
+ if err != nil {
+ return err
+ }
+ if t, ok := ref.(reference.Tagged); ok {
+ tag = t.Tag()
+ }
+ if r, ok := ref.(reference.Named); ok {
+ repo = r.Name()
+ }
+ if len(repo) < 1 {
+ return errors.Errorf("invalid image name %q", nameOrId)
+ }
+ if err := images.Tag(ir.ClientCxt, nameOrId, tag, repo); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error {
+ for _, newTag := range tags {
+ var (
+ tag, repo string
+ )
+ ref, err := reference.Parse(newTag)
+ if err != nil {
+ return err
+ }
+ if t, ok := ref.(reference.Tagged); ok {
+ tag = t.Tag()
+ }
+ if r, ok := ref.(reference.Named); ok {
+ repo = r.Name()
+ }
+ if len(repo) < 1 {
+ return errors.Errorf("invalid image name %q", nameOrId)
+ }
+ if err := images.Untag(ir.ClientCxt, nameOrId, tag, repo); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (ir *ImageEngine) Inspect(_ context.Context, names []string, opts entities.InspectOptions) (*entities.ImageInspectReport, error) {
+ report := entities.ImageInspectReport{}
+ for _, id := range names {
+ r, err := images.GetImage(ir.ClientCxt, id, &opts.Size)
+ if err != nil {
+ report.Errors[id] = err
+ }
+ report.Images = append(report.Images, r)
+ }
+ return &report, nil
+}
+
+func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) (*entities.ImageLoadReport, error) {
+ f, err := os.Open(opts.Input)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return images.Load(ir.ClientCxt, f, &opts.Name)
+}
+
+func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) {
+ var (
+ err error
+ sourceURL *string
+ f *os.File
+ )
+ if opts.SourceIsURL {
+ sourceURL = &opts.Source
+ } else {
+ f, err = os.Open(opts.Source)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return images.Import(ir.ClientCxt, opts.Changes, &opts.Message, &opts.Reference, sourceURL, f)
+}
+
+func (ir *ImageEngine) Push(ctx context.Context, source string, destination string, options entities.ImagePushOptions) error {
+ return images.Push(ir.ClientCxt, source, destination, options)
+}
diff --git a/pkg/domain/infra/tunnel/pods.go b/pkg/domain/infra/tunnel/pods.go
index 9561a9807..ad87a0a29 100644
--- a/pkg/domain/infra/tunnel/pods.go
+++ b/pkg/domain/infra/tunnel/pods.go
@@ -193,3 +193,7 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp
}
return &entities.StringSliceReport{Value: topOutput}, nil
}
+
+func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
+ return pods.List(ic.ClientCxt, options.Filters)
+}
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 194d2fcb3..5de07fc28 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -316,7 +316,17 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
// Make sure to always set the default variables unless overridden in the
// config.
- config.Env = env.Join(env.DefaultEnvVariables, config.Env)
+ var defaultEnv map[string]string
+ if runtimeConfig == nil {
+ defaultEnv = env.DefaultEnvVariables
+ } else {
+ defaultEnv, err = env.ParseSlice(runtimeConfig.Containers.Env)
+ if err != nil {
+ return nil, errors.Wrap(err, "Env fields in containers.conf failed ot parse")
+ }
+ defaultEnv = env.Join(env.DefaultEnvVariables, defaultEnv)
+ }
+ config.Env = env.Join(defaultEnv, config.Env)
for name, val := range config.Env {
g.AddProcessEnv(name, val)
}
diff --git a/pkg/systemd/generate/systemdgen.go b/pkg/systemd/generate/systemdgen.go
index eb15d4927..73fe52c0e 100644
--- a/pkg/systemd/generate/systemdgen.go
+++ b/pkg/systemd/generate/systemdgen.go
@@ -31,7 +31,7 @@ type ContainerInfo struct {
InfraContainer string
// StopTimeout sets the timeout Podman waits before killing the container
// during service stop.
- StopTimeout int
+ StopTimeout uint
// RestartPolicy of the systemd unit (e.g., no, on-failure, always).
RestartPolicy string
// PIDFile of the service. Required for forking services. Must point to the
diff --git a/pkg/varlink/generate.go b/pkg/varlink/generate.go
new file mode 100644
index 000000000..b3f58d4a5
--- /dev/null
+++ b/pkg/varlink/generate.go
@@ -0,0 +1,3 @@
+package iopodman
+
+//go:generate go run ../../vendor/github.com/varlink/go/cmd/varlink-go-interface-generator/main.go io.podman.varlink
diff --git a/cmd/podman/varlink/io.podman.varlink b/pkg/varlink/io.podman.varlink
index 0cb95ef97..0cb95ef97 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/pkg/varlink/io.podman.varlink
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
index 5beca3c6f..94f4d653e 100644
--- a/pkg/varlinkapi/attach.go
+++ b/pkg/varlinkapi/attach.go
@@ -6,10 +6,10 @@ import (
"bufio"
"io"
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/pkg/varlinkapi/virtwriter"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -28,7 +28,7 @@ func setupStreams(call iopodman.VarlinkCall) (*bufio.Reader, *bufio.Writer, *io.
stdoutWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.ToStdout)
// TODO if runc ever starts passing stderr, we can too
- //stderrWriter := NewVirtWriteCloser(writer, ToStderr)
+ // stderrWriter := NewVirtWriteCloser(writer, ToStderr)
streams := libpod.AttachStreams{
OutputStream: stdoutWriter,
diff --git a/pkg/varlinkapi/config.go b/pkg/varlinkapi/config.go
index e75170547..c69dc794a 100644
--- a/pkg/varlinkapi/config.go
+++ b/pkg/varlinkapi/config.go
@@ -4,8 +4,8 @@ package varlinkapi
import (
"github.com/containers/libpod/cmd/podman/cliconfig"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/spf13/cobra"
)
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 55427771c..2d051470f 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -15,13 +15,13 @@ import (
"time"
"github.com/containers/libpod/cmd/podman/shared"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/logs"
"github.com/containers/libpod/pkg/adapter/shortcuts"
"github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/rootless"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/pkg/varlinkapi/virtwriter"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
@@ -900,7 +900,7 @@ func (i *LibpodAPI) ExecContainer(call iopodman.VarlinkCall, opts iopodman.ExecO
return ecErr.Error
}
-//HealthCheckRun executes defined container's healthcheck command and returns the container's health status.
+// HealthCheckRun executes defined container's healthcheck command and returns the container's health status.
func (i *LibpodAPI) HealthCheckRun(call iopodman.VarlinkCall, nameOrID string) error {
hcStatus, err := i.Runtime.HealthCheck(nameOrID)
if err != nil && hcStatus != libpod.HealthCheckFailure {
diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go
index 6b23dce5e..bbd4d59f1 100644
--- a/pkg/varlinkapi/containers_create.go
+++ b/pkg/varlinkapi/containers_create.go
@@ -4,7 +4,7 @@ package varlinkapi
import (
"github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/cmd/podman/varlink"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// CreateContainer ...
diff --git a/pkg/varlinkapi/events.go b/pkg/varlinkapi/events.go
index f9a9d9321..4ae2d1cb2 100644
--- a/pkg/varlinkapi/events.go
+++ b/pkg/varlinkapi/events.go
@@ -6,8 +6,8 @@ import (
"fmt"
"time"
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod/events"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// GetEvents is a remote endpoint to get events from the event log
diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go
index 19010097d..c19c8dede 100644
--- a/pkg/varlinkapi/generate.go
+++ b/pkg/varlinkapi/generate.go
@@ -6,7 +6,7 @@ import (
"encoding/json"
"github.com/containers/libpod/cmd/podman/shared"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// GenerateKube ...
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index 82587f5c4..c3b4bd9ae 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -21,12 +21,12 @@ import (
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
"github.com/containers/libpod/cmd/podman/shared"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/channelwriter"
"github.com/containers/libpod/pkg/util"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/libpod/utils"
"github.com/containers/storage/pkg/archive"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
diff --git a/pkg/varlinkapi/mount.go b/pkg/varlinkapi/mount.go
index 63ce44291..2450f6fd9 100644
--- a/pkg/varlinkapi/mount.go
+++ b/pkg/varlinkapi/mount.go
@@ -2,9 +2,7 @@
package varlinkapi
-import (
- "github.com/containers/libpod/cmd/podman/varlink"
-)
+import iopodman "github.com/containers/libpod/pkg/varlink"
// ListContainerMounts ...
func (i *LibpodAPI) ListContainerMounts(call iopodman.VarlinkCall) error {
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index 2ec45f7a1..79ffb6677 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -8,9 +8,9 @@ import (
"syscall"
"github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter/shortcuts"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// CreatePod ...
diff --git a/pkg/varlinkapi/remote_client.go b/pkg/varlinkapi/remote_client.go
index dd0613494..a16d11dec 100644
--- a/pkg/varlinkapi/remote_client.go
+++ b/pkg/varlinkapi/remote_client.go
@@ -3,8 +3,8 @@
package varlinkapi
import (
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
index e88d010c5..04fb9f648 100644
--- a/pkg/varlinkapi/system.go
+++ b/pkg/varlinkapi/system.go
@@ -10,8 +10,8 @@ import (
"time"
"github.com/containers/image/v5/pkg/sysregistriesv2"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod/define"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/sirupsen/logrus"
)
diff --git a/pkg/varlinkapi/transfers.go b/pkg/varlinkapi/transfers.go
index 31d26c3aa..654da276e 100644
--- a/pkg/varlinkapi/transfers.go
+++ b/pkg/varlinkapi/transfers.go
@@ -9,7 +9,7 @@ import (
"io/ioutil"
"os"
- "github.com/containers/libpod/cmd/podman/varlink"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/sirupsen/logrus"
)
diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go
index d3a41f7ab..6b196f384 100644
--- a/pkg/varlinkapi/util.go
+++ b/pkg/varlinkapi/util.go
@@ -10,10 +10,10 @@ import (
"github.com/containers/buildah"
"github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/channelwriter"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/storage/pkg/archive"
)
diff --git a/pkg/varlinkapi/volumes.go b/pkg/varlinkapi/volumes.go
index e497cb537..b0c3608c4 100644
--- a/pkg/varlinkapi/volumes.go
+++ b/pkg/varlinkapi/volumes.go
@@ -6,8 +6,8 @@ import (
"encoding/json"
"github.com/containers/libpod/cmd/podman/shared"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/libpod"
+ iopodman "github.com/containers/libpod/pkg/varlink"
)
// VolumeCreate creates a libpod volume based on input from a varlink connection
diff --git a/test/e2e/build/basicalpine/Containerfile.path b/test/e2e/build/basicalpine/Containerfile.path
new file mode 100644
index 000000000..d2b03a6b8
--- /dev/null
+++ b/test/e2e/build/basicalpine/Containerfile.path
@@ -0,0 +1,2 @@
+FROM alpine
+ENV PATH=/tmp:/bin:/usr/bin:/usr/sbin
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 8b03e9386..9e41fd231 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -175,4 +175,24 @@ var _ = Describe("Podman build", func() {
data := inspect.InspectImageJSON()
Expect(data[0].ID).To(Equal(string(id)))
})
+
+ It("podman Test PATH in built image", func() {
+ path := "/tmp:/bin:/usr/bin:/usr/sbin"
+ session := podmanTest.PodmanNoCache([]string{
+ "build", "-f", "build/basicalpine/Containerfile.path", "-t", "test-path",
+ })
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"run", "test-path", "printenv", "PATH"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ stdoutLines := session.OutputToStringArray()
+ Expect(stdoutLines[0]).Should(Equal(path))
+
+ session = podmanTest.PodmanNoCache([]string{"rmi", "-a", "-f"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
})
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index b10c3237d..8c4fe9223 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -431,7 +431,7 @@ func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegrat
// Cleanup cleans up the temporary store
func (p *PodmanTestIntegration) Cleanup() {
// Remove all containers
- stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"})
+ stopall := p.Podman([]string{"stop", "-a", "--time", "0"})
stopall.Wait(90)
podstop := p.Podman([]string{"pod", "stop", "-a", "-t", "0"})
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index ab806f683..5d0d6e689 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -122,6 +122,18 @@ var _ = Describe("Podman exec", func() {
Expect(session.ExitCode()).To(Equal(100))
})
+ It("podman exec terminal doesn't hang", func() {
+ setup := podmanTest.Podman([]string{"run", "-dti", fedoraMinimal, "sleep", "+Inf"})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ for i := 0; i < 5; i++ {
+ session := podmanTest.Podman([]string{"exec", "-lti", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ }
+ })
+
It("podman exec pseudo-terminal sanity check", func() {
setup := podmanTest.Podman([]string{"run", "--detach", "--name", "test1", fedoraMinimal, "sleep", "+Inf"})
setup.WaitWithDefaultTimeout()
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index e5ab0b854..abfca4db9 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -47,7 +47,7 @@ var _ = Describe("Podman generate systemd", func() {
})
It("podman generate systemd bad timeout value", func() {
- session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "-1", "foobar"})
+ session := podmanTest.Podman([]string{"generate", "systemd", "--time", "-1", "foobar"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
})
@@ -57,7 +57,7 @@ var _ = Describe("Podman generate systemd", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- session = podmanTest.Podman([]string{"generate", "systemd", "--timeout", "1234", "foobar"})
+ session = podmanTest.Podman([]string{"generate", "systemd", "--time", "1234", "foobar"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -97,7 +97,7 @@ var _ = Describe("Podman generate systemd", func() {
n.WaitWithDefaultTimeout()
Expect(n.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "5", "nginx"})
+ session := podmanTest.Podman([]string{"generate", "systemd", "--time", "5", "nginx"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -118,7 +118,7 @@ var _ = Describe("Podman generate systemd", func() {
n.WaitWithDefaultTimeout()
Expect(n.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "foo"})
+ session := podmanTest.Podman([]string{"generate", "systemd", "--time", "42", "--name", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -183,7 +183,7 @@ var _ = Describe("Podman generate systemd", func() {
n.WaitWithDefaultTimeout()
Expect(n.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "--new", "foo"})
+ session := podmanTest.Podman([]string{"generate", "systemd", "-t", "42", "--name", "--new", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -214,7 +214,7 @@ var _ = Describe("Podman generate systemd", func() {
n.WaitWithDefaultTimeout()
Expect(n.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "--new", "foo"})
+ session := podmanTest.Podman([]string{"generate", "systemd", "--time", "42", "--name", "--new", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -228,7 +228,7 @@ var _ = Describe("Podman generate systemd", func() {
n.WaitWithDefaultTimeout()
Expect(n.ExitCode()).To(Equal(0))
- session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "--new", "foo"})
+ session := podmanTest.Podman([]string{"generate", "systemd", "--time", "42", "--name", "--new", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))
})
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index e31338dbc..1f892d9f8 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -15,9 +15,9 @@ import (
"github.com/onsi/gomega/gexec"
)
-var VolumeTrailingSlashDockerfile = `
-FROM alpine:latest
-VOLUME /test/`
+// in-container mount point: using a path that is definitely not present
+// on the host system might help to uncover some issues.
+const dest = "/unique/path"
var _ = Describe("Podman run with volumes", func() {
var (
@@ -45,46 +45,44 @@ var _ = Describe("Podman run with volumes", func() {
It("podman run with volume flag", func() {
mountPath := filepath.Join(podmanTest.TempDir, "secrets")
os.Mkdir(mountPath, 0755)
- session := podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ vol := mountPath + ":" + dest
+
+ session := podmanTest.Podman([]string{"run", "--rm", "-v", vol, ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches := session.GrepString("/run/test")
+ found, matches := session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(ContainSubstring("rw"))
- mountPath = filepath.Join(podmanTest.TempDir, "secrets")
- os.Mkdir(mountPath, 0755)
- session = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:ro", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":ro", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches = session.GrepString("/run/test")
+ found, matches = session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(ContainSubstring("ro"))
- mountPath = filepath.Join(podmanTest.TempDir, "secrets")
- os.Mkdir(mountPath, 0755)
- session = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:shared", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":shared", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches = session.GrepString("/run/test")
+ found, matches = session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(ContainSubstring("rw"))
Expect(matches[0]).To(ContainSubstring("shared"))
// Cached is ignored
- session = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:cached", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":cached", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches = session.GrepString("/run/test")
+ found, matches = session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(ContainSubstring("rw"))
Expect(matches[0]).To(Not(ContainSubstring("cached")))
// Delegated is ignored
- session = podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:delegated", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":delegated", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches = session.GrepString("/run/test")
+ found, matches = session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(ContainSubstring("rw"))
Expect(matches[0]).To(Not(ContainSubstring("delegated")))
@@ -96,30 +94,30 @@ var _ = Describe("Podman run with volumes", func() {
}
mountPath := filepath.Join(podmanTest.TempDir, "secrets")
os.Mkdir(mountPath, 0755)
- session := podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ mount := "type=bind,src=" + mountPath + ",target=" + dest
+
+ session := podmanTest.Podman([]string{"run", "--rm", "--mount", mount, ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("/run/test rw"))
+ Expect(session.OutputToString()).To(ContainSubstring(dest + " rw"))
- session = podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test,ro", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("/run/test ro"))
+ Expect(session.OutputToString()).To(ContainSubstring(dest + " ro"))
- session = podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test,shared", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",shared", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches := session.GrepString("/run/test")
+ found, matches := session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(ContainSubstring("rw"))
Expect(matches[0]).To(ContainSubstring("shared"))
- mountPath = filepath.Join(podmanTest.TempDir, "scratchpad")
- os.Mkdir(mountPath, 0755)
- session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=/run/test", ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=" + dest, ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("/run/test rw,nosuid,nodev,noexec,relatime - tmpfs"))
+ Expect(session.OutputToString()).To(ContainSubstring(dest + " rw,nosuid,nodev,noexec,relatime - tmpfs"))
session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=/etc/ssl,tmpcopyup", ALPINE, "ls", "/etc/ssl"})
session.WaitWithDefaultTimeout()
@@ -147,7 +145,7 @@ var _ = Describe("Podman run with volumes", func() {
It("podman run with conflicting volumes errors", func() {
mountPath := filepath.Join(podmanTest.TmpDir, "secrets")
os.Mkdir(mountPath, 0755)
- session := podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:/run/test", mountPath), "-v", "/tmp:/run/test", ALPINE, "ls"})
+ session := podmanTest.Podman([]string{"run", "-v", mountPath + ":" + dest, "-v", "/tmp" + ":" + dest, ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))
})
@@ -169,17 +167,19 @@ var _ = Describe("Podman run with volumes", func() {
It("podman run with mount flag and boolean options", func() {
mountPath := filepath.Join(podmanTest.TempDir, "secrets")
os.Mkdir(mountPath, 0755)
- session := podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test,ro=false", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ mount := "type=bind,src=" + mountPath + ",target=" + dest
+
+ session := podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro=false", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("/run/test rw"))
+ Expect(session.OutputToString()).To(ContainSubstring(dest + " rw"))
- session = podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test,ro=true", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro=true", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("/run/test ro"))
+ Expect(session.OutputToString()).To(ContainSubstring(dest + " ro"))
- session = podmanTest.Podman([]string{"run", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/run/test,ro=true,rw=false", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro=true,rw=false", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
})
@@ -195,19 +195,20 @@ var _ = Describe("Podman run with volumes", func() {
It("podman run with volumes and suid/dev/exec options", func() {
mountPath := filepath.Join(podmanTest.TempDir, "secrets")
os.Mkdir(mountPath, 0755)
- session := podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/run/test:suid,dev,exec", mountPath), ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+
+ session := podmanTest.Podman([]string{"run", "--rm", "-v", mountPath + ":" + dest + ":suid,dev,exec", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches := session.GrepString("/run/test")
+ found, matches := session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(Not(ContainSubstring("noexec")))
Expect(matches[0]).To(Not(ContainSubstring("nodev")))
Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
- session = podmanTest.Podman([]string{"run", "--rm", "--tmpfs", "/run/test:suid,dev,exec", ALPINE, "grep", "/run/test", "/proc/self/mountinfo"})
+ session = podmanTest.Podman([]string{"run", "--rm", "--tmpfs", dest + ":suid,dev,exec", ALPINE, "grep", dest, "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- found, matches = session.GrepString("/run/test")
+ found, matches = session.GrepString(dest)
Expect(found).Should(BeTrue())
Expect(matches[0]).To(Not(ContainSubstring("noexec")))
Expect(matches[0]).To(Not(ContainSubstring("nodev")))
@@ -255,7 +256,7 @@ var _ = Describe("Podman run with volumes", func() {
Expect(strings.Contains(mountOut2, volName)).To(BeTrue())
// Stop the container to unmount
- podmanStopSession := podmanTest.Podman([]string{"stop", "--timeout", "0", ctrName})
+ podmanStopSession := podmanTest.Podman([]string{"stop", "--time", "0", ctrName})
podmanStopSession.WaitWithDefaultTimeout()
Expect(podmanStopSession.ExitCode()).To(Equal(0))
@@ -298,11 +299,11 @@ var _ = Describe("Podman run with volumes", func() {
})
It("podman read-only tmpfs conflict with volume", func() {
- session := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "-v", "tmp_volume:/run", ALPINE, "touch", "/run/a"})
+ session := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "-v", "tmp_volume:" + dest, ALPINE, "touch", dest + "/a"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- session2 := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "--tmpfs", "/run", ALPINE, "touch", "/run/a"})
+ session2 := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "--tmpfs", dest, ALPINE, "touch", dest + "/a"})
session2.WaitWithDefaultTimeout()
Expect(session2.ExitCode()).To(Equal(0))
})
@@ -428,7 +429,10 @@ var _ = Describe("Podman run with volumes", func() {
It("Podman mount over image volume with trailing /", func() {
image := "podman-volume-test:trailing"
- podmanTest.BuildImage(VolumeTrailingSlashDockerfile, image, "false")
+ dockerfile := `
+FROM alpine:latest
+VOLUME /test/`
+ podmanTest.BuildImage(dockerfile, image, "false")
ctrName := "testCtr"
create := podmanTest.Podman([]string{"create", "-v", "/tmp:/test", "--name", ctrName, image, "ls"})
diff --git a/test/endpoint/endpoint.go b/test/endpoint/endpoint.go
index 5b5484865..f1677ec5f 100644
--- a/test/endpoint/endpoint.go
+++ b/test/endpoint/endpoint.go
@@ -11,8 +11,8 @@ import (
"syscall"
"time"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/rootless"
+ iopodman "github.com/containers/libpod/pkg/varlink"
. "github.com/onsi/ginkgo"
"github.com/onsi/gomega/gexec"
)
diff --git a/test/endpoint/setup.go b/test/endpoint/setup.go
index 727f29ec6..11fa77b5c 100644
--- a/test/endpoint/setup.go
+++ b/test/endpoint/setup.go
@@ -8,8 +8,8 @@ import (
"path/filepath"
"strings"
- iopodman "github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/rootless"
+ iopodman "github.com/containers/libpod/pkg/varlink"
"github.com/containers/storage/pkg/stringid"
"github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -90,7 +90,7 @@ func Setup(tempDir string) *EndpointTestIntegration {
SignaturePolicyPath: filepath.Join(INTEGRATION_ROOT, "test/policy.json"),
StorageOptions: storageOptions,
TmpDir: tempDir,
- //Timings: nil,
+ // Timings: nil,
VarlinkBinary: VarlinkBinary,
VarlinkCommand: nil,
VarlinkEndpoint: endpoint,
@@ -105,7 +105,7 @@ func (p *EndpointTestIntegration) Cleanup() {
p.stopAllContainers()
- //TODO need to make stop all pods
+ // TODO need to make stop all pods
p.StopVarlink()
// Nuke tempdir
@@ -153,9 +153,9 @@ func (p *EndpointTestIntegration) createArtifact(image string) {
Expect(pull.ExitCode()).To(Equal(0))
imageSave := iopodman.ImageSaveOptions{
- //Name:image,
- //Output: destName,
- //Format: "oci-archive",
+ // Name:image,
+ // Output: destName,
+ // Format: "oci-archive",
}
imageSave.Name = image
imageSave.Output = destName
@@ -186,7 +186,7 @@ func (p *EndpointTestIntegration) RestoreArtifactToCache(image string) error {
fmt.Printf("Restoring %s...\n", image)
dest := strings.Split(image, "/")
destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- //fmt.Println(destName, p.ImageCacheDir)
+ // fmt.Println(destName, p.ImageCacheDir)
load := p.Varlink("LoadImage", fmt.Sprintf("{\"name\": \"%s\", \"inputFile\": \"%s\"}", image, destName), false)
Expect(load.ExitCode()).To(BeZero())
return nil
diff --git a/utils/utils.go b/utils/utils.go
index 3c8c0a9b0..cf58ca3fb 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -65,7 +65,6 @@ func CopyDetachable(dst io.Writer, src io.Reader, keys []byte) (written int64, e
break
}
if i == len(keys)-1 {
- // src.Close()
return 0, ErrDetach
}
nr, er = src.Read(buf)
diff --git a/vendor/github.com/containers/buildah/.gitignore b/vendor/github.com/containers/buildah/.gitignore
index c70cab336..a362b3800 100644
--- a/vendor/github.com/containers/buildah/.gitignore
+++ b/vendor/github.com/containers/buildah/.gitignore
@@ -4,3 +4,4 @@ docs/buildah*.1
/build/
tests/tools/build
Dockerfile*
+*.swp
diff --git a/vendor/github.com/containers/buildah/CHANGELOG.md b/vendor/github.com/containers/buildah/CHANGELOG.md
index a888a1569..b456cffa8 100644
--- a/vendor/github.com/containers/buildah/CHANGELOG.md
+++ b/vendor/github.com/containers/buildah/CHANGELOG.md
@@ -2,6 +2,20 @@
# Changelog
+## v1.14.6 (2020-04-02)
+ bud.bats - cleanup, refactoring
+ vendor in latest containers/storage 1.18.0 and containers/common v0.7.0
+ Bump github.com/spf13/cobra from 0.0.6 to 0.0.7
+ Bump github.com/containers/storage from 1.16.5 to 1.17.0
+ Bump github.com/containers/image/v5 from 5.2.1 to 5.3.1
+ Fix Amazon install step
+ Bump back to v1.15.0-dev
+ Fix bud-build-arg-cache test
+ Make image history work correctly with new args handling
+ Don't add args to the RUN environment from the Builder
+ Update github.com/openshift/imagebuilder to v1.1.4
+ Add .swp files to .gitignore
+
## v1.14.5 (2020-03-26)
revert #2246 FIPS mode change
Bump back to v1.15.0-dev
diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go
index de0350d3d..2ece11acd 100644
--- a/vendor/github.com/containers/buildah/buildah.go
+++ b/vendor/github.com/containers/buildah/buildah.go
@@ -27,7 +27,7 @@ const (
Package = "buildah"
// Version for the Package. Bump version in contrib/rpm/buildah.spec
// too.
- Version = "1.14.5"
+ Version = "1.15.0-dev"
// The value we use to identify what type of information, currently a
// serialized Builder structure, we are using as per-container state.
// This should only be changed when we make incompatible changes to
diff --git a/vendor/github.com/containers/buildah/changelog.txt b/vendor/github.com/containers/buildah/changelog.txt
index 91affb33a..c740a4da3 100644
--- a/vendor/github.com/containers/buildah/changelog.txt
+++ b/vendor/github.com/containers/buildah/changelog.txt
@@ -1,3 +1,17 @@
+- Changelog for v1.14.6 (2020-04-02)
+ * bud.bats - cleanup, refactoring
+ * vendor in latest containers/storage 1.18.0 and containers/common v0.7.0
+ * Bump github.com/spf13/cobra from 0.0.6 to 0.0.7
+ * Bump github.com/containers/storage from 1.16.5 to 1.17.0
+ * Bump github.com/containers/image/v5 from 5.2.1 to 5.3.1
+ * Fix Amazon install step
+ * Bump back to v1.15.0-dev
+ * Fix bud-build-arg-cache test
+ * Make image history work correctly with new args handling
+ * Don't add args to the RUN environment from the Builder
+ * Update github.com/openshift/imagebuilder to v1.1.4
+ * Add .swp files to .gitignore
+
- Changelog for v1.14.5 (2020-03-26)
* revert #2246 FIPS mode change
* Bump back to v1.15.0-dev
diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go
index 8dfa8aba0..d65c36470 100644
--- a/vendor/github.com/containers/buildah/chroot/run.go
+++ b/vendor/github.com/containers/buildah/chroot/run.go
@@ -20,10 +20,10 @@ import (
"github.com/containers/buildah/bind"
"github.com/containers/buildah/util"
- "github.com/containers/common/pkg/unshare"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/mount"
"github.com/containers/storage/pkg/reexec"
+ "github.com/containers/storage/pkg/unshare"
"github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
diff --git a/vendor/github.com/containers/buildah/common.go b/vendor/github.com/containers/buildah/common.go
index 22bbb1efd..8fb3ebdb7 100644
--- a/vendor/github.com/containers/buildah/common.go
+++ b/vendor/github.com/containers/buildah/common.go
@@ -10,12 +10,12 @@ import (
"syscall"
"time"
- "github.com/containers/common/pkg/unshare"
cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/signature"
"github.com/containers/image/v5/types"
"github.com/containers/storage"
+ "github.com/containers/storage/pkg/unshare"
"github.com/docker/distribution/registry/api/errcode"
errcodev2 "github.com/docker/distribution/registry/api/v2"
multierror "github.com/hashicorp/go-multierror"
diff --git a/vendor/github.com/containers/buildah/go.mod b/vendor/github.com/containers/buildah/go.mod
index aec65c5da..a04a72f12 100644
--- a/vendor/github.com/containers/buildah/go.mod
+++ b/vendor/github.com/containers/buildah/go.mod
@@ -4,9 +4,9 @@ go 1.12
require (
github.com/containernetworking/cni v0.7.2-0.20190904153231-83439463f784
- github.com/containers/common v0.6.1
- github.com/containers/image/v5 v5.2.1
- github.com/containers/storage v1.16.5
+ github.com/containers/common v0.7.0
+ github.com/containers/image/v5 v5.3.1
+ github.com/containers/storage v1.18.0
github.com/cyphar/filepath-securejoin v0.2.2
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/go-metrics v0.0.1 // indirect
@@ -27,15 +27,15 @@ require (
github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/selinux v1.4.0
github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316
- github.com/openshift/imagebuilder v1.1.3
+ github.com/openshift/imagebuilder v1.1.4
github.com/pkg/errors v0.9.1
github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f
github.com/seccomp/libseccomp-golang v0.9.1
- github.com/sirupsen/logrus v1.4.2
- github.com/spf13/cobra v0.0.6
+ github.com/sirupsen/logrus v1.5.0
+ github.com/spf13/cobra v0.0.7
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.5.1
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
- golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2
+ golang.org/x/sys v0.0.0-20200217220822-9197077df867
)
diff --git a/vendor/github.com/containers/buildah/go.sum b/vendor/github.com/containers/buildah/go.sum
index 6c4a7724a..9e235bb3d 100644
--- a/vendor/github.com/containers/buildah/go.sum
+++ b/vendor/github.com/containers/buildah/go.sum
@@ -5,7 +5,6 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX
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/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
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.7-0.20191101173118-65519b62243c/go.mod h1:7xhjOwRV2+0HXGmM0jxaEu+ZiXJFoVZOTfL/dmqbrD8=
@@ -47,20 +46,17 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
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/containers/common v0.5.0 h1:ZAef7h3oO46PcbTyfooZf8XLHrYad+GkhSu3EhH6P24=
-github.com/containers/common v0.5.0/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
-github.com/containers/common v0.6.1 h1:z9VeVXYeOnNV99uNLp7zoE5KO1n0hqz1mdm5a6AiIrA=
-github.com/containers/common v0.6.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
-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/common v0.7.0 h1:wlcHuOa8CcsreCMd0BlvKUubIVzkLy8EMLtJ0JO+Y6I=
+github.com/containers/common v0.7.0/go.mod h1:UmhIdvSkhTR0hWR01AnuZGNufm80+A0s8isb05eTmz0=
+github.com/containers/image/v5 v5.3.1 h1:AL0pR0d1ho3kLUAuBr+wnFlXuD3ChzKVljk0M8JBJHQ=
+github.com/containers/image/v5 v5.3.1/go.mod h1:JnCfhbTIL9IxPPZm1JoQwiE0S9KET46M4OZySJsLylk=
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/storage v1.15.8/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI=
-github.com/containers/storage v1.16.0/go.mod h1:nqN09JSi1/RSI1UAUwDYXPRiGSlq5FPbNkN/xb0TfG0=
-github.com/containers/storage v1.16.5 h1:eHeWEhUEWX3VMIG1Vn1rEjfRoLHUQev3cwtA5zd89wk=
-github.com/containers/storage v1.16.5/go.mod h1:SdysZeLKJOvfHYysUWg9OZUC3gdZWi5b2b7NC18VpPE=
+github.com/containers/storage v1.16.6/go.mod h1:Fws4I+U+C4DmJxDbBs1z9SKk50DzN4LtA+g1b+FmkTY=
+github.com/containers/storage v1.18.0 h1:l0vqAJwhMvfg2VM8Kwcc92bMyBrsQIul+Rs88pd7c+A=
+github.com/containers/storage v1.18.0/go.mod h1:gbFeFybWhlVCk3buJ0sovNKs8MzWEBTrk8/sbJw8irQ=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -79,7 +75,6 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
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=
@@ -185,14 +180,10 @@ 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.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.10.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
-github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
-github.com/klauspost/pgzip v1.2.2 h1:8d4I0LDiieuGngsqlqOih9ker/NS0LX4V0i+EhiFWg0=
-github.com/klauspost/pgzip v1.2.2/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/klauspost/pgzip v1.2.3 h1:Ce2to9wvs/cuJ2b86/CKQoTYr9VHfpanYosZ0UBJqdw=
+github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
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=
@@ -206,8 +197,6 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
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/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@@ -255,16 +244,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.3.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
-github.com/opencontainers/selinux v1.3.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/opencontainers/selinux v1.4.0 h1:cpiX/2wWIju/6My60T6/z9CxNG7c8xTQyEmA9fChpUo=
github.com/opencontainers/selinux v1.4.0/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/imagebuilder v1.1.2 h1:vCO8hZQR/4uzo+j0PceBH5aKFcvCDM43UzUGOYQN+Go=
-github.com/openshift/imagebuilder v1.1.2/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
-github.com/openshift/imagebuilder v1.1.3 h1:8TiphsD2wboU7tygtGZ5ZBfCP9FH2ZtvEAli67V2PJ4=
-github.com/openshift/imagebuilder v1.1.3/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
+github.com/openshift/imagebuilder v1.1.4 h1:LUg8aTjyXMtlDx6IbtvaqofFGZ6aYqe+VIeATE735LM=
+github.com/openshift/imagebuilder v1.1.4/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@@ -308,14 +293,15 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
-github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
+github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs=
-github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
+github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU=
+github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
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.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -338,14 +324,14 @@ 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/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
-github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
-github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
+github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4=
+github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
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/v4 v4.11.2 h1:ynkUoKzi65DZ1UsQPx7sgi/KN6G9f7br+Us2nKm35AM=
-github.com/vbauerster/mpb/v4 v4.11.2/go.mod h1:jIuIRCltGJUnm6DCyPVkwjlLUk4nHTH+m4eD14CdFF0=
+github.com/vbauerster/mpb/v4 v4.12.2 h1:TsBs1nWRYF0m8cUH13pxNhOUqY6yKcOr2PeSYxp2L3I=
+github.com/vbauerster/mpb/v4 v4.12.2/go.mod h1:LVRGvMch8T4HQO3eg2pFPsACH9kO/O6fT/7vhGje3QE=
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=
@@ -357,7 +343,8 @@ github.com/xeipuuv/gojsonschema v0.0.0-20190816131739-be0936907f66/go.mod h1:anY
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
+go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -367,7 +354,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
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-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -418,11 +405,12 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
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-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/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw=
+golang.org/x/sys v0.0.0-20200217220822-9197077df867/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/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
diff --git a/vendor/github.com/containers/buildah/imagebuildah/executor.go b/vendor/github.com/containers/buildah/imagebuildah/executor.go
index 846900656..a0debc460 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/executor.go
@@ -93,7 +93,6 @@ type Executor struct {
blobDirectory string
excludes []string
unusedArgs map[string]struct{}
- buildArgs map[string]string
capabilities []string
devices []configs.Device
signBy string
@@ -179,7 +178,6 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
rootfsMap: make(map[string]bool),
blobDirectory: options.BlobDirectory,
unusedArgs: make(map[string]struct{}),
- buildArgs: copyStringStringMap(options.Args),
capabilities: capabilities,
devices: devices,
signBy: options.SignBy,
@@ -232,25 +230,26 @@ func NewExecutor(store storage.Store, options BuildOptions, mainNode *parser.Nod
// startStage creates a new stage executor that will be referenced whenever a
// COPY or ADD statement uses a --from=NAME flag.
-func (b *Executor) startStage(name string, index, stages int, from, output string) *StageExecutor {
+func (b *Executor) startStage(stage *imagebuilder.Stage, stages int, from, output string) *StageExecutor {
if b.stages == nil {
b.stages = make(map[string]*StageExecutor)
}
- stage := &StageExecutor{
+ stageExec := &StageExecutor{
executor: b,
- index: index,
+ index: stage.Position,
stages: stages,
- name: name,
+ name: stage.Name,
volumeCache: make(map[string]string),
volumeCacheInfo: make(map[string]os.FileInfo),
output: output,
+ stage: stage,
}
- b.stages[name] = stage
- b.stages[from] = stage
- if idx := strconv.Itoa(index); idx != name {
- b.stages[idx] = stage
+ b.stages[stage.Name] = stageExec
+ b.stages[from] = stageExec
+ if idx := strconv.Itoa(stage.Position); idx != stage.Name {
+ b.stages[idx] = stageExec
}
- return stage
+ return stageExec
}
// resolveNameToImageRef creates a types.ImageReference for the output name in local storage
@@ -291,81 +290,6 @@ func (b *Executor) getImageHistory(ctx context.Context, imageID string) ([]v1.Hi
return oci.History, nil
}
-// getCreatedBy returns the command the image at node will be created by. If
-// the passed-in CompositeDigester is not nil, it is assumed to have the digest
-// information for the content if the node is ADD or COPY.
-func (b *Executor) getCreatedBy(node *parser.Node, addedContentDigest string) string {
- if node == nil {
- return "/bin/sh"
- }
- switch strings.ToUpper(node.Value) {
- case "RUN":
- buildArgs := b.getBuildArgs()
- if buildArgs != "" {
- return "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " /bin/sh -c " + node.Original[4:]
- }
- return "/bin/sh -c " + node.Original[4:]
- case "ADD", "COPY":
- destination := node
- for destination.Next != nil {
- destination = destination.Next
- }
- return "/bin/sh -c #(nop) " + strings.ToUpper(node.Value) + " " + addedContentDigest + " in " + destination.Value + " "
- default:
- return "/bin/sh -c #(nop) " + node.Original
- }
-}
-
-// historyMatches returns true if a candidate history matches the history of our
-// base image (if we have one), plus the current instruction.
-// Used to verify whether a cache of the intermediate image exists and whether
-// to run the build again.
-func (b *Executor) historyMatches(baseHistory []v1.History, child *parser.Node, history []v1.History, addedContentDigest string) bool {
- if len(baseHistory) >= len(history) {
- return false
- }
- if len(history)-len(baseHistory) != 1 {
- return false
- }
- for i := range baseHistory {
- if baseHistory[i].CreatedBy != history[i].CreatedBy {
- return false
- }
- if baseHistory[i].Comment != history[i].Comment {
- return false
- }
- if baseHistory[i].Author != history[i].Author {
- return false
- }
- if baseHistory[i].EmptyLayer != history[i].EmptyLayer {
- return false
- }
- if baseHistory[i].Created != nil && history[i].Created == nil {
- return false
- }
- if baseHistory[i].Created == nil && history[i].Created != nil {
- return false
- }
- if baseHistory[i].Created != nil && history[i].Created != nil && *baseHistory[i].Created != *history[i].Created {
- return false
- }
- }
- return history[len(baseHistory)].CreatedBy == b.getCreatedBy(child, addedContentDigest)
-}
-
-// getBuildArgs returns a string of the build-args specified during the build process
-// it excludes any build-args that were not used in the build process
-func (b *Executor) getBuildArgs() string {
- var buildArgs []string
- for k, v := range b.buildArgs {
- if _, ok := b.unusedArgs[k]; !ok {
- buildArgs = append(buildArgs, k+"="+v)
- }
- }
- sort.Strings(buildArgs)
- return strings.Join(buildArgs, " ")
-}
-
// Build takes care of the details of running Prepare/Execute/Commit/Delete
// over each of the one or more parsed Dockerfiles and stages.
func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (imageID string, ref reference.Canonical, err error) {
@@ -494,7 +418,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
output = b.output
}
- stageExecutor := b.startStage(stage.Name, stage.Position, len(stages), base, output)
+ stageExecutor := b.startStage(&stage, len(stages), base, output)
// If this a single-layer build, or if it's a multi-layered
// build and b.forceRmIntermediateCtrs is set, make sure we
@@ -505,7 +429,7 @@ func (b *Executor) Build(ctx context.Context, stages imagebuilder.Stages) (image
}
// Build this stage.
- if imageID, ref, err = stageExecutor.Execute(ctx, stage, base); err != nil {
+ if imageID, ref, err = stageExecutor.Execute(ctx, base); err != nil {
lastErr = err
}
if lastErr != nil {
diff --git a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
index 8e49395a4..5ab70e54c 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/stage_executor.go
@@ -6,6 +6,7 @@ import (
"io"
"os"
"path/filepath"
+ "sort"
"strconv"
"strings"
"time"
@@ -56,6 +57,7 @@ type StageExecutor struct {
copyFrom string // Used to keep track of the --from flag from COPY and ADD
output string
containerIDs []string
+ stage *imagebuilder.Stage
}
// Preserve informs the stage executor that from this point on, it needs to
@@ -579,7 +581,8 @@ func (s *StageExecutor) UnrecognizedInstruction(step *imagebuilder.Step) error {
// prepare creates a working container based on the specified image, or if one
// isn't specified, the first argument passed to the first FROM instruction we
// can find in the stage's parsed tree.
-func (s *StageExecutor) prepare(ctx context.Context, stage imagebuilder.Stage, from string, initializeIBConfig, rebase bool) (builder *buildah.Builder, err error) {
+func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBConfig, rebase bool) (builder *buildah.Builder, err error) {
+ stage := s.stage
ib := stage.Builder
node := stage.Node
@@ -732,11 +735,11 @@ func (*StageExecutor) stepRequiresLayer(step *imagebuilder.Step) bool {
// storage. If it isn't found, it pulls down a copy. Then, if we don't have a
// working container root filesystem based on the image, it creates one. Then
// it returns that root filesystem's location.
-func (s *StageExecutor) getImageRootfs(ctx context.Context, stage imagebuilder.Stage, image string) (mountPoint string, err error) {
+func (s *StageExecutor) getImageRootfs(ctx context.Context, image string) (mountPoint string, err error) {
if builder, ok := s.executor.containerMap[image]; ok {
return builder.MountPoint, nil
}
- builder, err := s.prepare(ctx, stage, image, false, false)
+ builder, err := s.prepare(ctx, image, false, false)
if err != nil {
return "", err
}
@@ -745,7 +748,8 @@ func (s *StageExecutor) getImageRootfs(ctx context.Context, stage imagebuilder.S
}
// Execute runs each of the steps in the stage's parsed tree, in turn.
-func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, base string) (imgID string, ref reference.Canonical, err error) {
+func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string, ref reference.Canonical, err error) {
+ stage := s.stage
ib := stage.Builder
checkForLayers := s.executor.layers && s.executor.useCache
moreStages := s.index < s.stages-1
@@ -765,7 +769,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// Create the (first) working container for this stage. Reinitializing
// the imagebuilder configuration may alter the list of steps we have,
// so take a snapshot of them *after* that.
- if _, err := s.prepare(ctx, stage, base, true, true); err != nil {
+ if _, err := s.prepare(ctx, base, true, true); err != nil {
return "", nil, err
}
children := stage.Node.Children
@@ -809,14 +813,14 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// squash the contents of the base image. Whichever is
// the case, we need to commit() to create a new image.
logCommit(s.output, -1)
- if imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(nil, ""), false, s.output); err != nil {
+ if imgID, ref, err = s.commit(ctx, s.getCreatedBy(nil, ""), false, s.output); err != nil {
return "", nil, errors.Wrapf(err, "error committing base container")
}
} else if len(s.executor.labels) > 0 || len(s.executor.annotations) > 0 {
// The image would be modified by the labels passed
// via the command line, so we need to commit.
logCommit(s.output, -1)
- if imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(stage.Node, ""), true, s.output); err != nil {
+ if imgID, ref, err = s.commit(ctx, s.getCreatedBy(stage.Node, ""), true, s.output); err != nil {
return "", nil, err
}
} else {
@@ -866,7 +870,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
otherStage, ok := s.executor.stages[arr[1]]
if !ok {
- if mountPoint, err = s.getImageRootfs(ctx, stage, arr[1]); err != nil {
+ if mountPoint, err = s.getImageRootfs(ctx, arr[1]); err != nil {
return "", nil, errors.Errorf("%s --from=%s: no stage or image found with that name", command, arr[1])
}
} else {
@@ -905,7 +909,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// instruction in the history that we'll write
// for the image when we eventually commit it.
now := time.Now()
- s.builder.AddPrependedEmptyLayer(&now, s.executor.getCreatedBy(node, addedContentDigest), "", "")
+ s.builder.AddPrependedEmptyLayer(&now, s.getCreatedBy(node, addedContentDigest), "", "")
continue
} else {
// This is the last instruction for this stage,
@@ -914,7 +918,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// if it's used as the basis for a later stage.
if lastStage || imageIsUsedLater {
logCommit(s.output, i)
- imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(node, addedContentDigest), false, s.output)
+ imgID, ref, err = s.commit(ctx, s.getCreatedBy(node, addedContentDigest), false, s.output)
if err != nil {
return "", nil, errors.Wrapf(err, "error committing container for step %+v", *step)
}
@@ -1008,7 +1012,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
}
// Create a new image, maybe with a new layer.
logCommit(s.output, i)
- imgID, ref, err = s.commit(ctx, ib, s.executor.getCreatedBy(node, addedContentDigest), !s.stepRequiresLayer(step), commitName)
+ imgID, ref, err = s.commit(ctx, s.getCreatedBy(node, addedContentDigest), !s.stepRequiresLayer(step), commitName)
if err != nil {
return "", nil, errors.Wrapf(err, "error committing container for step %+v", *step)
}
@@ -1034,7 +1038,7 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
// creating a new working container with the
// just-committed or updated cached image as its new
// base image.
- if _, err := s.prepare(ctx, stage, imgID, false, true); err != nil {
+ if _, err := s.prepare(ctx, imgID, false, true); err != nil {
return "", nil, errors.Wrap(err, "error preparing container for next step")
}
}
@@ -1042,6 +1046,76 @@ func (s *StageExecutor) Execute(ctx context.Context, stage imagebuilder.Stage, b
return imgID, ref, nil
}
+// historyMatches returns true if a candidate history matches the history of our
+// base image (if we have one), plus the current instruction.
+// Used to verify whether a cache of the intermediate image exists and whether
+// to run the build again.
+func (s *StageExecutor) historyMatches(baseHistory []v1.History, child *parser.Node, history []v1.History, addedContentDigest string) bool {
+ if len(baseHistory) >= len(history) {
+ return false
+ }
+ if len(history)-len(baseHistory) != 1 {
+ return false
+ }
+ for i := range baseHistory {
+ if baseHistory[i].CreatedBy != history[i].CreatedBy {
+ return false
+ }
+ if baseHistory[i].Comment != history[i].Comment {
+ return false
+ }
+ if baseHistory[i].Author != history[i].Author {
+ return false
+ }
+ if baseHistory[i].EmptyLayer != history[i].EmptyLayer {
+ return false
+ }
+ if baseHistory[i].Created != nil && history[i].Created == nil {
+ return false
+ }
+ if baseHistory[i].Created == nil && history[i].Created != nil {
+ return false
+ }
+ if baseHistory[i].Created != nil && history[i].Created != nil && *baseHistory[i].Created != *history[i].Created {
+ return false
+ }
+ }
+ return history[len(baseHistory)].CreatedBy == s.getCreatedBy(child, addedContentDigest)
+}
+
+// getCreatedBy returns the command the image at node will be created by. If
+// the passed-in CompositeDigester is not nil, it is assumed to have the digest
+// information for the content if the node is ADD or COPY.
+func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentDigest string) string {
+ if node == nil {
+ return "/bin/sh"
+ }
+ switch strings.ToUpper(node.Value) {
+ case "RUN":
+ buildArgs := s.getBuildArgs()
+ if buildArgs != "" {
+ return "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " /bin/sh -c " + node.Original[4:]
+ }
+ return "/bin/sh -c " + node.Original[4:]
+ case "ADD", "COPY":
+ destination := node
+ for destination.Next != nil {
+ destination = destination.Next
+ }
+ return "/bin/sh -c #(nop) " + strings.ToUpper(node.Value) + " " + addedContentDigest + " in " + destination.Value + " "
+ default:
+ return "/bin/sh -c #(nop) " + node.Original
+ }
+}
+
+// getBuildArgs returns a string of the build-args specified during the build process
+// it excludes any build-args that were not used in the build process
+func (s *StageExecutor) getBuildArgs() string {
+ buildArgs := s.stage.Builder.Arguments()
+ sort.Strings(buildArgs)
+ return strings.Join(buildArgs, " ")
+}
+
// tagExistingImage adds names to an image already in the store
func (s *StageExecutor) tagExistingImage(ctx context.Context, cacheID, output string) (string, reference.Canonical, error) {
// If we don't need to attach a name to the image, just return the cache ID.
@@ -1128,7 +1202,7 @@ func (s *StageExecutor) intermediateImageExists(ctx context.Context, currNode *p
return "", errors.Wrapf(err, "error getting history of %q", image.ID)
}
// children + currNode is the point of the Dockerfile we are currently at.
- if s.executor.historyMatches(baseHistory, currNode, history, addedContentDigest) {
+ if s.historyMatches(baseHistory, currNode, history, addedContentDigest) {
return image.ID, nil
}
}
@@ -1138,7 +1212,8 @@ func (s *StageExecutor) intermediateImageExists(ctx context.Context, currNode *p
// commit writes the container's contents to an image, using a passed-in tag as
// the name if there is one, generating a unique ID-based one otherwise.
-func (s *StageExecutor) commit(ctx context.Context, ib *imagebuilder.Builder, createdBy string, emptyLayer bool, output string) (string, reference.Canonical, error) {
+func (s *StageExecutor) commit(ctx context.Context, createdBy string, emptyLayer bool, output string) (string, reference.Canonical, error) {
+ ib := s.stage.Builder
var imageRef types.ImageReference
if output != "" {
imageRef2, err := s.executor.resolveNameToImageRef(output)
diff --git a/vendor/github.com/containers/buildah/imagebuildah/util.go b/vendor/github.com/containers/buildah/imagebuildah/util.go
index 5f14c9883..29cdf44d0 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/util.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/util.go
@@ -166,11 +166,3 @@ func convertMounts(mounts []Mount) []specs.Mount {
}
return specmounts
}
-
-func copyStringStringMap(m map[string]string) map[string]string {
- n := map[string]string{}
- for k, v := range m {
- n[k] = v
- }
- return n
-}
diff --git a/vendor/github.com/containers/buildah/info.go b/vendor/github.com/containers/buildah/info.go
index a40af08ed..4332a0adc 100644
--- a/vendor/github.com/containers/buildah/info.go
+++ b/vendor/github.com/containers/buildah/info.go
@@ -12,9 +12,9 @@ import (
"time"
"github.com/containers/buildah/util"
- "github.com/containers/common/pkg/unshare"
"github.com/containers/storage"
"github.com/containers/storage/pkg/system"
+ "github.com/containers/storage/pkg/unshare"
"github.com/sirupsen/logrus"
)
diff --git a/vendor/github.com/containers/buildah/install.md b/vendor/github.com/containers/buildah/install.md
index 78d70765b..8dd429bc8 100644
--- a/vendor/github.com/containers/buildah/install.md
+++ b/vendor/github.com/containers/buildah/install.md
@@ -12,7 +12,7 @@ provides updated packages for CentOS 7 which can be used unmodified on Amazon Li
```bash
cd /etc/yum.repos.d/
sudo wget https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_7/devel:kubic:libcontainers:stable.repo
-sudo yum -y yum-plugin-copr
+sudo yum -y install yum-plugin-copr
sudo yum -y copr enable lsm5/container-selinux
sudo yum -y install buildah
```
diff --git a/vendor/github.com/containers/buildah/pkg/overlay/overlay.go b/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
index 61b65e425..c3d9302bb 100644
--- a/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
+++ b/vendor/github.com/containers/buildah/pkg/overlay/overlay.go
@@ -8,9 +8,9 @@ import (
"path/filepath"
"strings"
- "github.com/containers/common/pkg/unshare"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/system"
+ "github.com/containers/storage/pkg/unshare"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
diff --git a/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go b/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
index 33dc565d9..0a6d44195 100644
--- a/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
+++ b/vendor/github.com/containers/buildah/pkg/parse/parse_unix.go
@@ -6,7 +6,7 @@ import (
"os"
"path/filepath"
- "github.com/containers/common/pkg/unshare"
+ "github.com/containers/storage/pkg/unshare"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/devices"
"github.com/pkg/errors"
diff --git a/vendor/github.com/containers/buildah/run_linux.go b/vendor/github.com/containers/buildah/run_linux.go
index 6e4d31d78..ca112d50c 100644
--- a/vendor/github.com/containers/buildah/run_linux.go
+++ b/vendor/github.com/containers/buildah/run_linux.go
@@ -28,11 +28,11 @@ import (
"github.com/containers/buildah/util"
"github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
- "github.com/containers/common/pkg/unshare"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/reexec"
"github.com/containers/storage/pkg/stringid"
+ "github.com/containers/storage/pkg/unshare"
"github.com/docker/go-units"
"github.com/docker/libnetwork/resolvconf"
"github.com/docker/libnetwork/types"
@@ -1972,10 +1972,6 @@ func (b *Builder) configureEnvironment(g *generate.Generator, options RunOptions
g.AddProcessEnv(env[0], env[1])
}
}
-
- for src, dest := range b.Args {
- g.AddProcessEnv(src, dest)
- }
}
func setupRootlessSpecChanges(spec *specs.Spec, bundleDir string, shmSize string) error {
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor.go
new file mode 100644
index 000000000..8b4207efc
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor.go
@@ -0,0 +1,21 @@
+package apparmor
+
+import (
+ "errors"
+)
+
+const (
+ // ProfilePrefix is used for version-independent presence checks.
+ ProfilePrefix = "apparmor_profile"
+
+ // Profile default name
+ Profile = "container-default"
+)
+
+var (
+
+ // ErrApparmorUnsupported indicates that AppArmor support is not supported.
+ ErrApparmorUnsupported = errors.New("AppArmor is not supported")
+ // ErrApparmorRootless indicates that AppArmor support is not supported in rootless mode.
+ ErrApparmorRootless = errors.New("AppArmor is not supported in rootless mode")
+)
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
new file mode 100644
index 000000000..f0fab4597
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux.go
@@ -0,0 +1,289 @@
+// +build linux,apparmor
+
+package apparmor
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "path"
+ "strconv"
+ "strings"
+ "text/template"
+
+ "github.com/containers/storage/pkg/unshare"
+ runcaa "github.com/opencontainers/runc/libcontainer/apparmor"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// profileDirectory is the file store for apparmor profiles and macros.
+var profileDirectory = "/etc/apparmor.d"
+
+// IsEnabled returns true if AppArmor is enabled on the host.
+func IsEnabled() bool {
+ if unshare.IsRootless() {
+ return false
+ }
+ return runcaa.IsEnabled()
+}
+
+// profileData holds information about the given profile for generation.
+type profileData struct {
+ // Name is profile name.
+ Name string
+ // Imports defines the apparmor functions to import, before defining the profile.
+ Imports []string
+ // InnerImports defines the apparmor functions to import in the profile.
+ InnerImports []string
+ // Version is the {major, minor, patch} version of apparmor_parser as a single number.
+ Version int
+}
+
+// generateDefault creates an apparmor profile from ProfileData.
+func (p *profileData) generateDefault(out io.Writer) error {
+ compiled, err := template.New("apparmor_profile").Parse(defaultProfileTemplate)
+ if err != nil {
+ return err
+ }
+
+ if macroExists("tunables/global") {
+ p.Imports = append(p.Imports, "#include <tunables/global>")
+ } else {
+ p.Imports = append(p.Imports, "@{PROC}=/proc/")
+ }
+
+ if macroExists("abstractions/base") {
+ p.InnerImports = append(p.InnerImports, "#include <abstractions/base>")
+ }
+
+ ver, err := getAAParserVersion()
+ if err != nil {
+ return err
+ }
+ p.Version = ver
+
+ return compiled.Execute(out, p)
+}
+
+// macrosExists checks if the passed macro exists.
+func macroExists(m string) bool {
+ _, err := os.Stat(path.Join(profileDirectory, m))
+ return err == nil
+}
+
+// InstallDefault generates a default profile and loads it into the kernel
+// using 'apparmor_parser'.
+func InstallDefault(name string) error {
+ if unshare.IsRootless() {
+ return ErrApparmorRootless
+ }
+
+ p := profileData{
+ Name: name,
+ }
+
+ cmd := exec.Command("apparmor_parser", "-Kr")
+ pipe, err := cmd.StdinPipe()
+ if err != nil {
+ return err
+ }
+ if err := cmd.Start(); err != nil {
+ if pipeErr := pipe.Close(); pipeErr != nil {
+ logrus.Errorf("unable to close apparmor pipe: %q", pipeErr)
+ }
+ return err
+ }
+ if err := p.generateDefault(pipe); err != nil {
+ if pipeErr := pipe.Close(); pipeErr != nil {
+ logrus.Errorf("unable to close apparmor pipe: %q", pipeErr)
+ }
+ if cmdErr := cmd.Wait(); cmdErr != nil {
+ logrus.Errorf("unable to wait for apparmor command: %q", cmdErr)
+ }
+ return err
+ }
+
+ if pipeErr := pipe.Close(); pipeErr != nil {
+ logrus.Errorf("unable to close apparmor pipe: %q", pipeErr)
+ }
+ return cmd.Wait()
+}
+
+// DefaultContent returns the default profile content as byte slice. The
+// profile is named as the provided `name`. The function errors if the profile
+// generation fails.
+func DefaultContent(name string) ([]byte, error) {
+ p := profileData{Name: name}
+ var bytes bytes.Buffer
+ if err := p.generateDefault(&bytes); err != nil {
+ return nil, err
+ }
+ return bytes.Bytes(), nil
+}
+
+// IsLoaded checks if a profile with the given name has been loaded into the
+// kernel.
+func IsLoaded(name string) (bool, error) {
+ if name != "" && unshare.IsRootless() {
+ return false, errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
+ }
+
+ file, err := os.Open("/sys/kernel/security/apparmor/profiles")
+ if err != nil {
+ if os.IsNotExist(err) {
+ return false, nil
+ }
+ return false, err
+ }
+ defer file.Close()
+
+ r := bufio.NewReader(file)
+ for {
+ p, err := r.ReadString('\n')
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return false, err
+ }
+ if strings.HasPrefix(p, name+" ") {
+ return true, nil
+ }
+ }
+
+ return false, nil
+}
+
+// execAAParser runs `apparmor_parser` with the passed arguments.
+func execAAParser(dir string, args ...string) (string, error) {
+ c := exec.Command("apparmor_parser", args...)
+ c.Dir = dir
+
+ output, err := c.CombinedOutput()
+ if err != nil {
+ return "", fmt.Errorf("running `%s %s` failed with output: %s\nerror: %v", c.Path, strings.Join(c.Args, " "), output, err)
+ }
+
+ return string(output), nil
+}
+
+// getAAParserVersion returns the major and minor version of apparmor_parser.
+func getAAParserVersion() (int, error) {
+ output, err := execAAParser("", "--version")
+ if err != nil {
+ return -1, err
+ }
+ return parseAAParserVersion(output)
+}
+
+// parseAAParserVersion parses the given `apparmor_parser --version` output and
+// returns the major and minor version number as an integer.
+func parseAAParserVersion(output string) (int, error) {
+ // output is in the form of the following:
+ // AppArmor parser version 2.9.1
+ // Copyright (C) 1999-2008 Novell Inc.
+ // Copyright 2009-2012 Canonical Ltd.
+ lines := strings.SplitN(output, "\n", 2)
+ words := strings.Split(lines[0], " ")
+ version := words[len(words)-1]
+
+ // split by major minor version
+ v := strings.Split(version, ".")
+ if len(v) == 0 || len(v) > 3 {
+ return -1, fmt.Errorf("parsing version failed for output: `%s`", output)
+ }
+
+ // Default the versions to 0.
+ var majorVersion, minorVersion, patchLevel int
+
+ majorVersion, err := strconv.Atoi(v[0])
+ if err != nil {
+ return -1, err
+ }
+
+ if len(v) > 1 {
+ minorVersion, err = strconv.Atoi(v[1])
+ if err != nil {
+ return -1, err
+ }
+ }
+ if len(v) > 2 {
+ patchLevel, err = strconv.Atoi(v[2])
+ if err != nil {
+ return -1, err
+ }
+ }
+
+ // major*10^5 + minor*10^3 + patch*10^0
+ numericVersion := majorVersion*1e5 + minorVersion*1e3 + patchLevel
+ return numericVersion, nil
+
+}
+
+// CheckProfileAndLoadDefault checks if the specified profile is loaded and
+// loads the DefaultLibpodProfile if the specified on is prefixed by
+// DefaultLipodProfilePrefix. This allows to always load and apply the latest
+// default AppArmor profile. Note that AppArmor requires root. If it's a
+// default profile, return DefaultLipodProfilePrefix, otherwise the specified
+// one.
+func CheckProfileAndLoadDefault(name string) (string, error) {
+ if name == "unconfined" {
+ return name, nil
+ }
+
+ // AppArmor is not supported in rootless mode as it requires root
+ // privileges. Return an error in case a specific profile is specified.
+ if unshare.IsRootless() {
+ if name != "" {
+ return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
+ } else {
+ logrus.Debug("skipping loading default AppArmor profile (rootless mode)")
+ return "", nil
+ }
+ }
+
+ // Check if AppArmor is disabled and error out if a profile is to be set.
+ if !runcaa.IsEnabled() {
+ if name == "" {
+ return "", nil
+ } else {
+ return "", fmt.Errorf("profile %q specified but AppArmor is disabled on the host", name)
+ }
+ }
+
+ // If the specified name is not empty or is not a default libpod one,
+ // ignore it and return the name.
+ if name != "" && !strings.HasPrefix(name, ProfilePrefix) {
+ isLoaded, err := IsLoaded(name)
+ if err != nil {
+ return "", err
+ }
+ if !isLoaded {
+ return "", fmt.Errorf("AppArmor profile %q specified but not loaded", name)
+ }
+ return name, nil
+ }
+
+ name = Profile
+ // To avoid expensive redundant loads on each invocation, check
+ // if it's loaded before installing it.
+ isLoaded, err := IsLoaded(name)
+ if err != nil {
+ return "", err
+ }
+ if !isLoaded {
+ err = InstallDefault(name)
+ if err != nil {
+ return "", err
+ }
+ logrus.Infof("successfully loaded AppAmor profile %q", name)
+ } else {
+ logrus.Infof("AppAmor profile %q is already loaded", name)
+ }
+
+ return name, nil
+}
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go
new file mode 100644
index 000000000..021e32571
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_linux_template.go
@@ -0,0 +1,49 @@
+// +build linux,apparmor
+
+package apparmor
+
+const defaultProfileTemplate = `
+{{range $value := .Imports}}
+{{$value}}
+{{end}}
+
+profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
+{{range $value := .InnerImports}}
+ {{$value}}
+{{end}}
+
+ network,
+ capability,
+ file,
+ umount,
+
+{{if ge .Version 208096}}
+ # Allow signals from privileged profiles and from within the same profile
+ signal (receive) peer=unconfined,
+ signal (send,receive) peer={{.Name}},
+{{end}}
+
+ deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
+ # deny write to files not in /proc/<number>/** or /proc/sys/**
+ deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w,
+ deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
+ deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/
+ deny @{PROC}/sysrq-trigger rwklx,
+ deny @{PROC}/kcore rwklx,
+
+ deny mount,
+
+ deny /sys/[^f]*/** wklx,
+ deny /sys/f[^s]*/** wklx,
+ deny /sys/fs/[^c]*/** wklx,
+ deny /sys/fs/c[^g]*/** wklx,
+ deny /sys/fs/cg[^r]*/** wklx,
+ deny /sys/firmware/** rwklx,
+ deny /sys/kernel/security/** rwklx,
+
+{{if ge .Version 208095}}
+ # suppress ptrace denials when using using 'ps' inside a container
+ ptrace (trace,read) peer={{.Name}},
+{{end}}
+}
+`
diff --git a/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go b/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go
new file mode 100644
index 000000000..13469f1b6
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/apparmor/apparmor_unsupported.go
@@ -0,0 +1,31 @@
+// +build !linux !apparmor
+
+package apparmor
+
+// IsEnabled dummy.
+func IsEnabled() bool {
+ return false
+}
+
+// InstallDefault dummy.
+func InstallDefault(name string) error {
+ return ErrApparmorUnsupported
+}
+
+// IsLoaded dummy.
+func IsLoaded(name string) (bool, error) {
+ return false, ErrApparmorUnsupported
+}
+
+// CheckProfileAndLoadDefault dummy.
+func CheckProfileAndLoadDefault(name string) (string, error) {
+ if name == "" {
+ return "", nil
+ }
+ return "", ErrApparmorUnsupported
+}
+
+// DefaultContent dummy.
+func DefaultContent(name string) ([]byte, error) {
+ return nil, nil
+}
diff --git a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
index a57c048bc..51e711631 100644
--- a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
+++ b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go
@@ -99,6 +99,10 @@ func MergeCapabilities(base, adds, drops []string) ([]string, error) {
return base, nil
}
+ base, err := normalizeCapabilities(base)
+ if err != nil {
+ return nil, err
+ }
capDrop, err := normalizeCapabilities(drops)
if err != nil {
return nil, err
diff --git a/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_linux.go b/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_linux.go
new file mode 100644
index 000000000..b11eafebb
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_linux.go
@@ -0,0 +1,27 @@
+package cgroupv2
+
+import (
+ "sync"
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+var (
+ isCgroupV2Once sync.Once
+ isCgroupV2 bool
+ isCgroupV2Err error
+)
+
+// Enabled returns whether we are running in cgroup 2 cgroup2 mode.
+func Enabled() (bool, error) {
+ isCgroupV2Once.Do(func() {
+ var st syscall.Statfs_t
+ if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
+ isCgroupV2, isCgroupV2Err = false, err
+ } else {
+ isCgroupV2, isCgroupV2Err = st.Type == unix.CGROUP2_SUPER_MAGIC, nil
+ }
+ })
+ return isCgroupV2, isCgroupV2Err
+}
diff --git a/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go b/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go
new file mode 100644
index 000000000..cda68b405
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/cgroupv2/cgroups_unsupported.go
@@ -0,0 +1,8 @@
+// +build !linux
+
+package cgroupv2
+
+// Enabled returns whether we are running in cgroup 2 cgroup2 mode.
+func Enabled() (bool, error) {
+ return false, nil
+}
diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go
index db70e53a4..b65db2722 100644
--- a/vendor/github.com/containers/common/pkg/config/config.go
+++ b/vendor/github.com/containers/common/pkg/config/config.go
@@ -11,7 +11,7 @@ import (
"github.com/BurntSushi/toml"
"github.com/containers/common/pkg/capabilities"
- "github.com/containers/common/pkg/unshare"
+ "github.com/containers/storage/pkg/unshare"
units "github.com/docker/go-units"
selinux "github.com/opencontainers/selinux/go-selinux"
"github.com/pkg/errors"
@@ -173,7 +173,7 @@ type ContainersConfig struct {
// EngineConfig contains configuration options used to set up a engine runtime
type EngineConfig struct {
// CgroupCheck indicates the configuration has been rewritten after an
- // upgrade to Fedora 31 to change the default OCI runtime for cgroupsv2.
+ // upgrade to Fedora 31 to change the default OCI runtime for cgroupv2v2.
CgroupCheck bool `toml:"cgroup_check,omitempty"`
// CGroupManager is the CGroup Manager to use Valid values are "cgroupfs"
@@ -269,7 +269,7 @@ type EngineConfig struct {
// RuntimeSupportsNoCgroups is a list of OCI runtimes that support
// running containers without CGroups.
- RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups"`
+ RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroupv2"`
// SetOptions contains a subset of config options. It's used to indicate if
// a given option has either been set by the user or by the parsed
@@ -373,7 +373,7 @@ type NetworkConfig struct {
// running as root or rootless, we then merge the system configuration followed
// by merging the default config (hard-coded default in memory).
// Note that the OCI runtime is hard-set to `crun` if we're running on a system
-// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This
+// with cgroupv2v2. Other OCI runtimes are not yet supporting cgroupv2v2. This
// might change in the future.
func NewConfig(userConfigPath string) (*Config, error) {
@@ -494,7 +494,7 @@ func (c *Config) CheckCgroupsAndAdjustConfig() {
}
if !hasSession {
- logrus.Warningf("The cgroups manager is set to systemd but there is no systemd user session available")
+ logrus.Warningf("The cgroupv2 manager is set to systemd but there is no systemd user session available")
logrus.Warningf("For using systemd, you may need to login using an user session")
logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", unshare.GetRootlessUID())
logrus.Warningf("Falling back to --cgroup-manager=cgroupfs")
@@ -806,9 +806,35 @@ func IsValidDeviceMode(mode string) bool {
return true
}
+// resolveHomeDir converts a path referencing the home directory via "~"
+// to an absolute path
+func resolveHomeDir(path string) (string, error) {
+ // check if the path references the home dir to avoid work
+ // don't use strings.HasPrefix(path, "~") as this doesn't match "~" alone
+ // use strings.HasPrefix(...) to not match "something/~/something"
+ if !(path == "~" || strings.HasPrefix(path, "~/")) {
+ // path does not reference home dir -> Nothing to do
+ return path, nil
+ }
+
+ // only get HomeDir when necessary
+ home, err := unshare.HomeDir()
+ if err != nil {
+ return "", err
+ }
+
+ // replace the first "~" (start of path) with the HomeDir to resolve "~"
+ return strings.Replace(path, "~", home, 1), nil
+}
+
// isDirectory tests whether the given path exists and is a directory. It
// follows symlinks.
func isDirectory(path string) error {
+ path, err := resolveHomeDir(path)
+ if err != nil {
+ return err
+ }
+
info, err := os.Stat(path)
if err != nil {
return err
diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf
index b01db5f88..067be429e 100644
--- a/vendor/github.com/containers/common/pkg/config/containers.conf
+++ b/vendor/github.com/containers/common/pkg/config/containers.conf
@@ -288,7 +288,7 @@
# associated with the pod. This container does nothing other then sleep,
# reserving the pods resources for the lifetime of the pod.
#
-# infra_image = "k8s.gcr.io/pause:3.1"
+# infra_image = "k8s.gcr.io/pause:3.2"
# Specify the locking mechanism to use; valid values are "shm" and "file".
# Change the default only if you are sure of what you are doing, in general
@@ -345,9 +345,9 @@
# List of the OCI runtimes that support --format=json. When json is supported
# engine will use it for reporting nicer errors.
#
-# runtime_supports_json = ["crun", "runc"]
+# runtime_supports_json = ["crun", "runc", "kata"]
-# Paths to look for a valid OCI runtime (runc, runv, etc)
+# Paths to look for a valid OCI runtime (runc, runv, kata, etc)
[engine.runtimes]
# runc = [
# "/usr/bin/runc",
@@ -369,6 +369,15 @@
# "/run/current-system/sw/bin/crun",
# ]
+# kata = [
+# "/usr/bin/kata-runtime",
+# "/usr/sbin/kata-runtime",
+# "/usr/local/bin/kata-runtime",
+# "/usr/local/sbin/kata-runtime",
+# "/sbin/kata-runtime",
+# "/bin/kata-runtime",
+# ]
+
# Number of seconds to wait for container to exit before sending kill signal.
#stop_timeout = 10
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 04c3f9773..78bfd8a28 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -2,14 +2,19 @@ package config
import (
"bytes"
+ "fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
- "github.com/containers/common/pkg/unshare"
+ "github.com/containers/common/pkg/apparmor"
+ "github.com/containers/common/pkg/cgroupv2"
+ "github.com/containers/common/pkg/sysinfo"
"github.com/containers/storage"
+ "github.com/containers/storage/pkg/unshare"
+ "github.com/opencontainers/selinux/go-selinux"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -40,7 +45,7 @@ var (
// DefaultInitPath is the default path to the container-init binary
DefaultInitPath = "/usr/libexec/podman/catatonit"
// DefaultInfraImage to use for infra container
- DefaultInfraImage = "k8s.gcr.io/pause:3.1"
+ DefaultInfraImage = "k8s.gcr.io/pause:3.2"
// DefaultInfraCommand to be run in an infra container
DefaultInfraCommand = "/pause"
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
@@ -87,7 +92,7 @@ const (
// CgroupfsCgroupsManager represents cgroupfs native cgroup manager
CgroupfsCgroupsManager = "cgroupfs"
// DefaultApparmorProfile specifies the default apparmor profile for the container.
- DefaultApparmorProfile = "container-default"
+ DefaultApparmorProfile = apparmor.Profile
// SystemdCgroupsManager represents systemd native cgroup manager
SystemdCgroupsManager = "systemd"
// DefaultLogDriver is the default type of log files
@@ -207,11 +212,11 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
c.StateType = BoltDBStateStore
c.OCIRuntime = "runc"
- // If we're running on cgroups v2, default to using crun.
- if onCgroupsv2, _ := isCgroup2UnifiedMode(); onCgroupsv2 {
+ // If we're running on cgroupv2 v2, default to using crun.
+ if cgroup2, _ := cgroupv2.Enabled(); cgroup2 {
c.OCIRuntime = "crun"
}
- c.CgroupManager = SystemdCgroupsManager
+ c.CgroupManager = defaultCgroupManager()
c.StopTimeout = uint(10)
c.OCIRuntimes = map[string][]string{
@@ -234,6 +239,14 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
"/bin/crun",
"/run/current-system/sw/bin/crun",
},
+ "kata": {
+ "/usr/bin/kata-runtime",
+ "/usr/sbin/kata-runtime",
+ "/usr/local/bin/kata-runtime",
+ "/usr/local/sbin/kata-runtime",
+ "/sbin/kata-runtime",
+ "/bin/kata-runtime",
+ },
}
c.ConmonEnvVars = []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
@@ -261,7 +274,7 @@ func defaultConfigFromMemory() (*EngineConfig, error) {
c.InfraImage = DefaultInfraImage
c.EnablePortReservation = true
c.NumLocks = 2048
- c.EventsLogger = "journald"
+ c.EventsLogger = defaultEventsLogger()
c.DetachKeys = DefaultDetachKeys
c.SDNotify = false
// TODO - ideally we should expose a `type LockType string` along with
@@ -344,3 +357,112 @@ func probeConmon(conmonBinary string) error {
return nil
}
+
+// NetNS returns the default network namespace
+func (c *Config) NetNS() string {
+ if c.Containers.NetNS == "private" && unshare.IsRootless() {
+ return "slirp4netns"
+ }
+ return c.Containers.NetNS
+}
+
+// SecurityOptions returns the default security options
+func (c *Config) SecurityOptions() []string {
+ securityOpts := []string{}
+ if c.Containers.SeccompProfile != "" && c.Containers.SeccompProfile != SeccompDefaultPath {
+ securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", c.Containers.SeccompProfile))
+ }
+ if apparmor.IsEnabled() && c.Containers.ApparmorProfile != "" {
+ securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", c.Containers.ApparmorProfile))
+ }
+ if selinux.GetEnabled() && !c.Containers.EnableLabeling {
+ securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0]))
+ }
+ return securityOpts
+}
+
+// Sysctls returns the default sysctls
+func (c *Config) Sysctls() []string {
+ return c.Containers.DefaultSysctls
+}
+
+// Volumes returns the default additional volumes for containersvolumes
+func (c *Config) Volumes() []string {
+ return c.Containers.Volumes
+}
+
+// Devices returns the default additional devices for containers
+func (c *Config) Devices() []string {
+ return c.Containers.Devices
+}
+
+// DNSServers returns the default DNS servers to add to resolv.conf in containers
+func (c *Config) DNSServers() []string {
+ return c.Containers.DNSServers
+}
+
+// DNSSerches returns the default DNS searches to add to resolv.conf in containers
+func (c *Config) DNSSearches() []string {
+ return c.Containers.DNSSearches
+}
+
+// DNSOptions returns the default DNS options to add to resolv.conf in containers
+func (c *Config) DNSOptions() []string {
+ return c.Containers.DNSOptions
+}
+
+// Env returns the default additional environment variables to add to containers
+func (c *Config) Env() []string {
+ return c.Containers.Env
+}
+
+// InitPath returns the default init path to add to containers
+func (c *Config) InitPath() string {
+ return c.Containers.InitPath
+}
+
+// IPCNS returns the default IPC Namespace configuration to run containers with
+func (c *Config) IPCNS() string {
+ return c.Containers.IPCNS
+}
+
+// PIDNS returns the default PID Namespace configuration to run containers with
+func (c *Config) PidNS() string {
+ return c.Containers.PidNS
+}
+
+// CgroupNS returns the default Cgroup Namespace configuration to run containers with
+func (c *Config) CgroupNS() string {
+ return c.Containers.CgroupNS
+}
+
+// UTSNS returns the default UTS Namespace configuration to run containers with
+func (c *Config) UTSNS() string {
+ return c.Containers.UTSNS
+}
+
+// ShmSize returns the default size for temporary file systems to use in containers
+func (c *Config) ShmSize() string {
+ return c.Containers.ShmSize
+}
+
+// Ulimits returns the default ulimits to use in containers
+func (c *Config) Ulimits() []string {
+ return c.Containers.DefaultUlimits
+}
+
+// PidsLimit returns the default maximum number of pids to use in containers
+func (c *Config) PidsLimit() int64 {
+ if unshare.IsRootless() {
+ cgroup2, _ := cgroupv2.Enabled()
+ if cgroup2 {
+ return c.Containers.PidsLimit
+ }
+ }
+ return sysinfo.GetDefaultPidsLimit()
+}
+
+// DetachKeys returns the default detach keys to detach from a container
+func (c *Config) DetachKeys() string {
+ return c.Engine.DetachKeys
+}
diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go
index 91b73d344..e49413d7a 100644
--- a/vendor/github.com/containers/common/pkg/config/default_linux.go
+++ b/vendor/github.com/containers/common/pkg/config/default_linux.go
@@ -5,24 +5,10 @@ import (
"io/ioutil"
"strconv"
"strings"
- "syscall"
"golang.org/x/sys/unix"
)
-// isCgroup2UnifiedMode returns whether we are running in cgroup2 mode.
-func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) {
- cgroupRoot := "/sys/fs/cgroup"
-
- var st syscall.Statfs_t
- if err := syscall.Statfs(cgroupRoot, &st); err != nil {
- isUnified, isUnifiedErr = false, err
- } else {
- isUnified, isUnifiedErr = int64(st.Type) == int64(unix.CGROUP2_SUPER_MAGIC), nil
- }
- return
-}
-
const (
oldMaxSize = uint64(1048576)
)
diff --git a/vendor/github.com/containers/common/pkg/config/libpodConfig.go b/vendor/github.com/containers/common/pkg/config/libpodConfig.go
index 333f43815..cdb38a514 100644
--- a/vendor/github.com/containers/common/pkg/config/libpodConfig.go
+++ b/vendor/github.com/containers/common/pkg/config/libpodConfig.go
@@ -9,7 +9,8 @@ import (
"path/filepath"
"github.com/BurntSushi/toml"
- "github.com/containers/common/pkg/unshare"
+ "github.com/containers/common/pkg/cgroupv2"
+ "github.com/containers/storage/pkg/unshare"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -69,7 +70,7 @@ type ConfigFromLibpod struct {
// RuntimeSupportsNoCgroups is a list of OCI runtimes that support
// running containers without CGroups.
- RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups,omitempty"`
+ RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroupv2,omitempty"`
// RuntimePath is the path to OCI runtime binary for launching containers.
// The first path pointing to a valid file will be used This is used only
@@ -175,7 +176,7 @@ type ConfigFromLibpod struct {
SDNotify bool `toml:",omitempty"`
// CgroupCheck indicates the configuration has been rewritten after an
- // upgrade to Fedora 31 to change the default OCI runtime for cgroupsv2.
+ // upgrade to Fedora 31 to change the default OCI runtime for cgroupv2v2.
CgroupCheck bool `toml:"cgroup_check,omitempty"`
}
@@ -183,7 +184,7 @@ type ConfigFromLibpod struct {
// Depending if we're running as root or rootless, we then merge the system configuration followed
// by merging the default config (hard-coded default in memory).
// Note that the OCI runtime is hard-set to `crun` if we're running on a system
-// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This
+// with cgroupv2v2. Other OCI runtimes are not yet supporting cgroupv2v2. This
// might change in the future.
func newLibpodConfig(c *Config) error {
// Start with the default config and interatively merge
@@ -205,13 +206,13 @@ func newLibpodConfig(c *Config) error {
// Since runc does not currently support cgroupV2
// Change to default crun on first running of libpod.conf
- // TODO Once runc has support for cgroups, this function should be removed.
+ // TODO Once runc has support for cgroupv2, this function should be removed.
if !config.CgroupCheck && unshare.IsRootless() {
- cgroupsV2, err := isCgroup2UnifiedMode()
+ cgroup2, err := cgroupv2.Enabled()
if err != nil {
return err
}
- if cgroupsV2 {
+ if cgroup2 {
path, err := exec.LookPath("crun")
if err != nil {
// Can't find crun path so do nothing
diff --git a/vendor/github.com/containers/common/pkg/config/nosystemd.go b/vendor/github.com/containers/common/pkg/config/nosystemd.go
new file mode 100644
index 000000000..5b82b1389
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/nosystemd.go
@@ -0,0 +1,11 @@
+// +build !systemd
+
+package config
+
+func defaultCgroupManager() string {
+ return "cgroupfs"
+}
+
+func defaultEventsLogger() string {
+ return "file"
+}
diff --git a/vendor/github.com/containers/common/pkg/config/systemd.go b/vendor/github.com/containers/common/pkg/config/systemd.go
new file mode 100644
index 000000000..e02f52192
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/config/systemd.go
@@ -0,0 +1,10 @@
+// +build systemd
+
+package config
+
+func defaultCgroupManager() string {
+ return SystemdCgroupsManager
+}
+func defaultEventsLogger() string {
+ return "journald"
+}
diff --git a/vendor/github.com/containers/common/pkg/config/util_supported.go b/vendor/github.com/containers/common/pkg/config/util_supported.go
index 101952f1d..2cdf54549 100644
--- a/vendor/github.com/containers/common/pkg/config/util_supported.go
+++ b/vendor/github.com/containers/common/pkg/config/util_supported.go
@@ -9,7 +9,7 @@ import (
"sync"
"syscall"
- "github.com/containers/common/pkg/unshare"
+ "github.com/containers/storage/pkg/unshare"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/README.md b/vendor/github.com/containers/common/pkg/sysinfo/README.md
new file mode 100644
index 000000000..c1530cef0
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/README.md
@@ -0,0 +1 @@
+SysInfo stores information about which features a kernel supports.
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go b/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go
new file mode 100644
index 000000000..aeb1a3a80
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/numcpu.go
@@ -0,0 +1,12 @@
+// +build !linux,!windows
+
+package sysinfo
+
+import (
+ "runtime"
+)
+
+// NumCPU returns the number of CPUs
+func NumCPU() int {
+ return runtime.NumCPU()
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go
new file mode 100644
index 000000000..f1d2d9db3
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_linux.go
@@ -0,0 +1,44 @@
+// +build linux
+
+package sysinfo
+
+import (
+ "runtime"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// numCPU queries the system for the count of threads available
+// for use to this process.
+//
+// Issues two syscalls.
+// Returns 0 on errors. Use |runtime.NumCPU| in that case.
+func numCPU() int {
+ // Gets the affinity mask for a process: The very one invoking this function.
+ pid, _, _ := unix.RawSyscall(unix.SYS_GETPID, 0, 0, 0)
+
+ var mask [1024 / 64]uintptr
+ _, _, err := unix.RawSyscall(unix.SYS_SCHED_GETAFFINITY, pid, uintptr(len(mask)*8), uintptr(unsafe.Pointer(&mask[0])))
+ if err != 0 {
+ return 0
+ }
+
+ // For every available thread a bit is set in the mask.
+ ncpu := 0
+ for _, e := range mask {
+ if e == 0 {
+ continue
+ }
+ ncpu += int(popcnt(uint64(e)))
+ }
+ return ncpu
+}
+
+// NumCPU returns the number of CPUs which are currently online
+func NumCPU() int {
+ if ncpu := numCPU(); ncpu > 0 {
+ return ncpu
+ }
+ return runtime.NumCPU()
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go
new file mode 100644
index 000000000..1d89dd550
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/numcpu_windows.go
@@ -0,0 +1,37 @@
+// +build windows
+
+package sysinfo
+
+import (
+ "runtime"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+var (
+ kernel32 = windows.NewLazySystemDLL("kernel32.dll")
+ getCurrentProcess = kernel32.NewProc("GetCurrentProcess")
+ getProcessAffinityMask = kernel32.NewProc("GetProcessAffinityMask")
+)
+
+func numCPU() int {
+ // Gets the affinity mask for a process
+ var mask, sysmask uintptr
+ currentProcess, _, _ := getCurrentProcess.Call()
+ ret, _, _ := getProcessAffinityMask.Call(currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+ if ret == 0 {
+ return 0
+ }
+ // For every available thread a bit is set in the mask.
+ ncpu := int(popcnt(uint64(mask)))
+ return ncpu
+}
+
+// NumCPU returns the number of CPUs which are currently online
+func NumCPU() int {
+ if ncpu := numCPU(); ncpu > 0 {
+ return ncpu
+ }
+ return runtime.NumCPU()
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo.go
new file mode 100644
index 000000000..686f66ce5
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo.go
@@ -0,0 +1,153 @@
+package sysinfo
+
+import "github.com/docker/docker/pkg/parsers"
+
+// SysInfo stores information about which features a kernel supports.
+// TODO Windows: Factor out platform specific capabilities.
+type SysInfo struct {
+ // Whether the kernel supports AppArmor or not
+ AppArmor bool
+ // Whether the kernel supports Seccomp or not
+ Seccomp bool
+
+ cgroupMemInfo
+ cgroupCPUInfo
+ cgroupBlkioInfo
+ cgroupCpusetInfo
+ cgroupPids
+
+ // Whether IPv4 forwarding is supported or not, if this was disabled, networking will not work
+ IPv4ForwardingDisabled bool
+
+ // Whether bridge-nf-call-iptables is supported or not
+ BridgeNFCallIPTablesDisabled bool
+
+ // Whether bridge-nf-call-ip6tables is supported or not
+ BridgeNFCallIP6TablesDisabled bool
+
+ // Whether the cgroup has the mountpoint of "devices" or not
+ CgroupDevicesEnabled bool
+}
+
+type cgroupMemInfo struct {
+ // Whether memory limit is supported or not
+ MemoryLimit bool
+
+ // Whether swap limit is supported or not
+ SwapLimit bool
+
+ // Whether soft limit is supported or not
+ MemoryReservation bool
+
+ // Whether OOM killer disable is supported or not
+ OomKillDisable bool
+
+ // Whether memory swappiness is supported or not
+ MemorySwappiness bool
+
+ // Whether kernel memory limit is supported or not
+ KernelMemory bool
+}
+
+type cgroupCPUInfo struct {
+ // Whether CPU shares is supported or not
+ CPUShares bool
+
+ // Whether CPU CFS(Completely Fair Scheduler) period is supported or not
+ CPUCfsPeriod bool
+
+ // Whether CPU CFS(Completely Fair Scheduler) quota is supported or not
+ CPUCfsQuota bool
+
+ // Whether CPU real-time period is supported or not
+ CPURealtimePeriod bool
+
+ // Whether CPU real-time runtime is supported or not
+ CPURealtimeRuntime bool
+}
+
+type cgroupBlkioInfo struct {
+ // Whether Block IO weight is supported or not
+ BlkioWeight bool
+
+ // Whether Block IO weight_device is supported or not
+ BlkioWeightDevice bool
+
+ // Whether Block IO read limit in bytes per second is supported or not
+ BlkioReadBpsDevice bool
+
+ // Whether Block IO write limit in bytes per second is supported or not
+ BlkioWriteBpsDevice bool
+
+ // Whether Block IO read limit in IO per second is supported or not
+ BlkioReadIOpsDevice bool
+
+ // Whether Block IO write limit in IO per second is supported or not
+ BlkioWriteIOpsDevice bool
+}
+
+type cgroupCpusetInfo struct {
+ // Whether Cpuset is supported or not
+ Cpuset bool
+
+ // Available Cpuset's cpus
+ Cpus string
+
+ // Available Cpuset's memory nodes
+ Mems string
+}
+
+type cgroupPids struct {
+ // Whether Pids Limit is supported or not
+ PidsLimit bool
+}
+
+// IsCpusetCpusAvailable returns `true` if the provided string set is contained
+// in cgroup's cpuset.cpus set, `false` otherwise.
+// If error is not nil a parsing error occurred.
+func (c cgroupCpusetInfo) IsCpusetCpusAvailable(provided string) (bool, error) {
+ return isCpusetListAvailable(provided, c.Cpus)
+}
+
+// IsCpusetMemsAvailable returns `true` if the provided string set is contained
+// in cgroup's cpuset.mems set, `false` otherwise.
+// If error is not nil a parsing error occurred.
+func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) {
+ return isCpusetListAvailable(provided, c.Mems)
+}
+
+func isCpusetListAvailable(provided, available string) (bool, error) {
+ parsedProvided, err := parsers.ParseUintList(provided)
+ if err != nil {
+ return false, err
+ }
+ parsedAvailable, err := parsers.ParseUintList(available)
+ if err != nil {
+ return false, err
+ }
+ for k := range parsedProvided {
+ if !parsedAvailable[k] {
+ return false, nil
+ }
+ }
+ return true, nil
+}
+
+// Returns bit count of 1, used by NumCPU
+func popcnt(x uint64) (n byte) {
+ x -= (x >> 1) & 0x5555555555555555
+ x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
+ x += x >> 4
+ x &= 0x0f0f0f0f0f0f0f0f
+ x *= 0x0101010101010101
+ return byte(x >> 56)
+}
+
+// GetDefaultPidsLimit returns the default pids limit to run containers with
+func GetDefaultPidsLimit() int64 {
+ sysInfo := New(true)
+ if !sysInfo.PidsLimit {
+ return 0
+ }
+ return 4096
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
new file mode 100644
index 000000000..269ea686a
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_linux.go
@@ -0,0 +1,261 @@
+package sysinfo
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/containers/common/pkg/cgroupv2"
+ "github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
+)
+
+func findCgroupMountpoints() (map[string]string, error) {
+ cgMounts, err := cgroups.GetCgroupMounts(false)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse cgroup information: %v", err)
+ }
+ mps := make(map[string]string)
+ for _, m := range cgMounts {
+ for _, ss := range m.Subsystems {
+ mps[ss] = m.Mountpoint
+ }
+ }
+ return mps, nil
+}
+
+// New returns a new SysInfo, using the filesystem to detect which features
+// the kernel supports. If `quiet` is `false` warnings are printed in logs
+// whenever an error occurs or misconfigurations are present.
+func New(quiet bool) *SysInfo {
+ sysInfo := &SysInfo{}
+ cgMounts, err := findCgroupMountpoints()
+ if err != nil {
+ logrus.Warnf("Failed to parse cgroup information: %v", err)
+ } else {
+ sysInfo.cgroupMemInfo = checkCgroupMem(cgMounts, quiet)
+ sysInfo.cgroupCPUInfo = checkCgroupCPU(cgMounts, quiet)
+ sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet)
+ sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet)
+ sysInfo.cgroupPids = checkCgroupPids(quiet)
+ }
+
+ _, ok := cgMounts["devices"]
+ sysInfo.CgroupDevicesEnabled = ok
+
+ sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
+ sysInfo.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
+ sysInfo.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
+
+ // Check if AppArmor is supported.
+ if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
+ sysInfo.AppArmor = true
+ }
+
+ // Check if Seccomp is supported, via CONFIG_SECCOMP.
+ if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
+ // Make sure the kernel has CONFIG_SECCOMP_FILTER.
+ if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
+ sysInfo.Seccomp = true
+ }
+ }
+
+ return sysInfo
+}
+
+// checkCgroupMem reads the memory information from the memory cgroup mount point.
+func checkCgroupMem(cgMounts map[string]string, quiet bool) cgroupMemInfo {
+ mountPoint, ok := cgMounts["memory"]
+ if !ok {
+ if !quiet {
+ logrus.Warn("Your kernel does not support cgroup memory limit")
+ }
+ return cgroupMemInfo{}
+ }
+
+ swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
+ if !quiet && !swapLimit {
+ logrus.Warn("Your kernel does not support swap memory limit")
+ }
+ memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
+ if !quiet && !memoryReservation {
+ logrus.Warn("Your kernel does not support memory reservation")
+ }
+ oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control")
+ if !quiet && !oomKillDisable {
+ logrus.Warn("Your kernel does not support oom control")
+ }
+ memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness")
+ if !quiet && !memorySwappiness {
+ logrus.Warn("Your kernel does not support memory swappiness")
+ }
+ kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
+ if !quiet && !kernelMemory {
+ logrus.Warn("Your kernel does not support kernel memory limit")
+ }
+
+ return cgroupMemInfo{
+ MemoryLimit: true,
+ SwapLimit: swapLimit,
+ MemoryReservation: memoryReservation,
+ OomKillDisable: oomKillDisable,
+ MemorySwappiness: memorySwappiness,
+ KernelMemory: kernelMemory,
+ }
+}
+
+// checkCgroupCPU reads the cpu information from the cpu cgroup mount point.
+func checkCgroupCPU(cgMounts map[string]string, quiet bool) cgroupCPUInfo {
+ mountPoint, ok := cgMounts["cpu"]
+ if !ok {
+ if !quiet {
+ logrus.Warn("Unable to find cpu cgroup in mounts")
+ }
+ return cgroupCPUInfo{}
+ }
+
+ cpuShares := cgroupEnabled(mountPoint, "cpu.shares")
+ if !quiet && !cpuShares {
+ logrus.Warn("Your kernel does not support cgroup cpu shares")
+ }
+
+ cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us")
+ if !quiet && !cpuCfsPeriod {
+ logrus.Warn("Your kernel does not support cgroup cfs period")
+ }
+
+ cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
+ if !quiet && !cpuCfsQuota {
+ logrus.Warn("Your kernel does not support cgroup cfs quotas")
+ }
+
+ cpuRealtimePeriod := cgroupEnabled(mountPoint, "cpu.rt_period_us")
+ if !quiet && !cpuRealtimePeriod {
+ logrus.Warn("Your kernel does not support cgroup rt period")
+ }
+
+ cpuRealtimeRuntime := cgroupEnabled(mountPoint, "cpu.rt_runtime_us")
+ if !quiet && !cpuRealtimeRuntime {
+ logrus.Warn("Your kernel does not support cgroup rt runtime")
+ }
+
+ return cgroupCPUInfo{
+ CPUShares: cpuShares,
+ CPUCfsPeriod: cpuCfsPeriod,
+ CPUCfsQuota: cpuCfsQuota,
+ CPURealtimePeriod: cpuRealtimePeriod,
+ CPURealtimeRuntime: cpuRealtimeRuntime,
+ }
+}
+
+// checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point.
+func checkCgroupBlkioInfo(cgMounts map[string]string, quiet bool) cgroupBlkioInfo {
+ mountPoint, ok := cgMounts["blkio"]
+ if !ok {
+ if !quiet {
+ logrus.Warn("Unable to find blkio cgroup in mounts")
+ }
+ return cgroupBlkioInfo{}
+ }
+
+ weight := cgroupEnabled(mountPoint, "blkio.weight")
+ if !quiet && !weight {
+ logrus.Warn("Your kernel does not support cgroup blkio weight")
+ }
+
+ weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device")
+ if !quiet && !weightDevice {
+ logrus.Warn("Your kernel does not support cgroup blkio weight_device")
+ }
+
+ readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device")
+ if !quiet && !readBpsDevice {
+ logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device")
+ }
+
+ writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device")
+ if !quiet && !writeBpsDevice {
+ logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device")
+ }
+ readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device")
+ if !quiet && !readIOpsDevice {
+ logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device")
+ }
+
+ writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device")
+ if !quiet && !writeIOpsDevice {
+ logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device")
+ }
+ return cgroupBlkioInfo{
+ BlkioWeight: weight,
+ BlkioWeightDevice: weightDevice,
+ BlkioReadBpsDevice: readBpsDevice,
+ BlkioWriteBpsDevice: writeBpsDevice,
+ BlkioReadIOpsDevice: readIOpsDevice,
+ BlkioWriteIOpsDevice: writeIOpsDevice,
+ }
+}
+
+// checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.
+func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetInfo {
+ mountPoint, ok := cgMounts["cpuset"]
+ if !ok {
+ if !quiet {
+ logrus.Warn("Unable to find cpuset cgroup in mounts")
+ }
+ return cgroupCpusetInfo{}
+ }
+
+ cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus"))
+ if err != nil {
+ return cgroupCpusetInfo{}
+ }
+
+ mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems"))
+ if err != nil {
+ return cgroupCpusetInfo{}
+ }
+
+ return cgroupCpusetInfo{
+ Cpuset: true,
+ Cpus: strings.TrimSpace(string(cpus)),
+ Mems: strings.TrimSpace(string(mems)),
+ }
+}
+
+// checkCgroupPids reads the pids information from the pids cgroup mount point.
+func checkCgroupPids(quiet bool) cgroupPids {
+ cgroup2, err := cgroupv2.Enabled()
+ if err != nil {
+ logrus.Errorf("Failed to check cgroups version: %v", err)
+ }
+ if !cgroup2 {
+ _, err := cgroups.FindCgroupMountpoint("", "pids")
+ if err != nil {
+ if !quiet {
+ logrus.Warn(err)
+ }
+ return cgroupPids{}
+ }
+ }
+
+ return cgroupPids{
+ PidsLimit: true,
+ }
+}
+
+func cgroupEnabled(mountPoint, name string) bool {
+ _, err := os.Stat(path.Join(mountPoint, name))
+ return err == nil
+}
+
+func readProcBool(path string) bool {
+ val, err := ioutil.ReadFile(path)
+ if err != nil {
+ return false
+ }
+ return strings.TrimSpace(string(val)) == "1"
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go
new file mode 100644
index 000000000..7463cdd8f
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_solaris.go
@@ -0,0 +1,122 @@
+// +build solaris,cgo
+
+package sysinfo
+
+import (
+ "bytes"
+ "os/exec"
+ "strconv"
+ "strings"
+)
+
+/*
+#cgo LDFLAGS: -llgrp
+#cgo CFLAGS: -Wall -Werror
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/lgrp_user.h>
+int getLgrpCount() {
+ lgrp_cookie_t lgrpcookie = LGRP_COOKIE_NONE;
+ uint_t nlgrps;
+
+ if ((lgrpcookie = lgrp_init(LGRP_VIEW_OS)) == LGRP_COOKIE_NONE) {
+ return -1;
+ }
+ nlgrps = lgrp_nlgrps(lgrpcookie);
+ return nlgrps;
+}
+*/
+import "C"
+
+// IsCPUSharesAvailable returns whether CPUShares setting is supported.
+// We need FSS to be set as default scheduling class to support CPU Shares
+func IsCPUSharesAvailable() bool {
+ cmd := exec.Command("/usr/sbin/dispadmin", "-d")
+ outBuf := new(bytes.Buffer)
+ errBuf := new(bytes.Buffer)
+ cmd.Stderr = errBuf
+ cmd.Stdout = outBuf
+
+ if err := cmd.Run(); err != nil {
+ return false
+ }
+ return (strings.Contains(outBuf.String(), "FSS"))
+}
+
+// New returns a new SysInfo, using the filesystem to detect which features
+// the kernel supports.
+//NOTE Solaris: If we change the below capabilities be sure
+// to update verifyPlatformContainerSettings() in daemon_solaris.go
+func New(quiet bool) *SysInfo {
+ sysInfo := &SysInfo{}
+ sysInfo.cgroupMemInfo = setCgroupMem(quiet)
+ sysInfo.cgroupCPUInfo = setCgroupCPU(quiet)
+ sysInfo.cgroupBlkioInfo = setCgroupBlkioInfo(quiet)
+ sysInfo.cgroupCpusetInfo = setCgroupCPUsetInfo(quiet)
+
+ sysInfo.IPv4ForwardingDisabled = false
+
+ sysInfo.AppArmor = false
+
+ return sysInfo
+}
+
+// setCgroupMem reads the memory information for Solaris.
+func setCgroupMem(quiet bool) cgroupMemInfo {
+
+ return cgroupMemInfo{
+ MemoryLimit: true,
+ SwapLimit: true,
+ MemoryReservation: false,
+ OomKillDisable: false,
+ MemorySwappiness: false,
+ KernelMemory: false,
+ }
+}
+
+// setCgroupCPU reads the cpu information for Solaris.
+func setCgroupCPU(quiet bool) cgroupCPUInfo {
+
+ return cgroupCPUInfo{
+ CPUShares: true,
+ CPUCfsPeriod: false,
+ CPUCfsQuota: true,
+ CPURealtimePeriod: false,
+ CPURealtimeRuntime: false,
+ }
+}
+
+// blkio switches are not supported in Solaris.
+func setCgroupBlkioInfo(quiet bool) cgroupBlkioInfo {
+
+ return cgroupBlkioInfo{
+ BlkioWeight: false,
+ BlkioWeightDevice: false,
+ }
+}
+
+// setCgroupCPUsetInfo reads the cpuset information for Solaris.
+func setCgroupCPUsetInfo(quiet bool) cgroupCpusetInfo {
+
+ return cgroupCpusetInfo{
+ Cpuset: true,
+ Cpus: getCPUCount(),
+ Mems: getLgrpCount(),
+ }
+}
+
+func getCPUCount() string {
+ ncpus := C.sysconf(C._SC_NPROCESSORS_ONLN)
+ if ncpus <= 0 {
+ return ""
+ }
+ return strconv.FormatInt(int64(ncpus), 16)
+}
+
+func getLgrpCount() string {
+ nlgrps := C.getLgrpCount()
+ if nlgrps <= 0 {
+ return ""
+ }
+ return strconv.FormatInt(int64(nlgrps), 16)
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go
new file mode 100644
index 000000000..45f3ef1c6
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_unix.go
@@ -0,0 +1,9 @@
+// +build !linux,!solaris,!windows
+
+package sysinfo
+
+// New returns an empty SysInfo for non linux nor solaris for now.
+func New(quiet bool) *SysInfo {
+ sysInfo := &SysInfo{}
+ return sysInfo
+}
diff --git a/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go
new file mode 100644
index 000000000..4e6255bc5
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/sysinfo/sysinfo_windows.go
@@ -0,0 +1,9 @@
+// +build windows
+
+package sysinfo
+
+// New returns an empty SysInfo for windows for now.
+func New(quiet bool) *SysInfo {
+ sysInfo := &SysInfo{}
+ return sysInfo
+}
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index de646d2fc..ec6d649be 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.16.6
+1.18.1
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 40cd856a9..b2426c9f9 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -5,12 +5,14 @@ require (
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5
github.com/Microsoft/hcsshim v0.8.7
github.com/docker/go-units v0.4.0
+ github.com/hashicorp/go-multierror v1.0.0
github.com/klauspost/compress v1.10.3
github.com/klauspost/pgzip v1.2.3
github.com/mattn/go-shellwords v1.0.10
github.com/mistifyio/go-zfs v2.1.1+incompatible
github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/runc v1.0.0-rc9
+ github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700
github.com/opencontainers/selinux v1.4.0
github.com/pkg/errors v0.9.1
github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7
@@ -20,7 +22,7 @@ require (
github.com/tchap/go-patricia v2.3.0+incompatible
github.com/vbatts/tar-split v0.11.1
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
- golang.org/x/sys v0.0.0-20191115151921-52ab43148777
+ golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2
gotest.tools v2.2.0+incompatible
)
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index 2c53f6ba6..990cfef57 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -1,6 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/DataDog/zstd v1.4.0/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
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.7 h1:ptnOoufxGSzauVTsdE+wMYnCWA301PdoN4xg5oRdZpg=
@@ -16,12 +17,19 @@ 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/containers/common v0.5.0 h1:ZAef7h3oO46PcbTyfooZf8XLHrYad+GkhSu3EhH6P24=
+github.com/containers/common v0.5.0/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
+github.com/containers/common v0.6.1 h1:z9VeVXYeOnNV99uNLp7zoE5KO1n0hqz1mdm5a6AiIrA=
+github.com/containers/common v0.6.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys=
+github.com/containers/storage v1.16.0/go.mod h1:nqN09JSi1/RSI1UAUwDYXPRiGSlq5FPbNkN/xb0TfG0=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/docker/docker v0.0.0-20171019062838-86f080cff091/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -32,15 +40,22 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
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/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
+github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.10.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.2 h1:Znfn6hXZAHaLPNnlqUYRrBSReFHYybslgv4PTiyz6P0=
github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+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=
github.com/klauspost/pgzip v1.2.2 h1:8d4I0LDiieuGngsqlqOih9ker/NS0LX4V0i+EhiFWg0=
@@ -53,14 +68,23 @@ github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvO
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mistifyio/go-zfs v2.1.1+incompatible h1:gAMO1HM9xBRONLHHYnu5iFsOJUiJdNZo6oqSENd4eW8=
github.com/mistifyio/go-zfs v2.1.1+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+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/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc=
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700 h1:eNUVfm/RFLIi1G7flU5/ZRTHvd4kcVuzfRnL6OFlzCI=
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7 h1:Dliu5QO+4JYWu/yMshaMU7G3JN2POGpwjJN7gjy10Go=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
+github.com/opencontainers/selinux v1.3.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
+github.com/opencontainers/selinux v1.3.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/opencontainers/selinux v1.4.0 h1:cpiX/2wWIju/6My60T6/z9CxNG7c8xTQyEmA9fChpUo=
github.com/opencontainers/selinux v1.4.0/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
@@ -77,10 +101,12 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -103,6 +129,7 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -115,6 +142,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -123,6 +151,9 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4=
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.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -130,6 +161,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
@@ -138,8 +170,12 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
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/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
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=
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=
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index dccfc169d..17227266e 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -281,6 +281,8 @@ func copyLayer(l *Layer) *Layer {
Flags: copyStringInterfaceMap(l.Flags),
UIDMap: copyIDMap(l.UIDMap),
GIDMap: copyIDMap(l.GIDMap),
+ UIDs: copyUint32Slice(l.UIDs),
+ GIDs: copyUint32Slice(l.GIDs),
}
}
diff --git a/vendor/github.com/containers/storage/pkg/config/config.go b/vendor/github.com/containers/storage/pkg/config/config.go
index 9e1131823..1ac6c04e3 100644
--- a/vendor/github.com/containers/storage/pkg/config/config.go
+++ b/vendor/github.com/containers/storage/pkg/config/config.go
@@ -134,6 +134,18 @@ type OptionsConfig struct {
// should be used to set up default GID mappings.
RemapGroup string `toml:"remap-group"`
+ // RootAutoUsernsUser is the name of one or more entries in /etc/subuid and
+ // /etc/subgid which should be used to set up automatically a userns.
+ RootAutoUsernsUser string `toml:"root-auto-userns-user"`
+
+ // AutoUsernsMinSize is the minimum size for a user namespace that is
+ // created automatically.
+ AutoUsernsMinSize uint32 `toml:"auto-userns-min-size"`
+
+ // AutoUsernsMaxSize is the maximum size for a user namespace that is
+ // created automatically.
+ AutoUsernsMaxSize uint32 `toml:"auto-userns-max-size"`
+
// Aufs container options to be handed to aufs drivers
Aufs struct{ AufsOptionsConfig } `toml:"aufs"`
diff --git a/vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go b/vendor/github.com/containers/storage/pkg/unshare/getenv_linux_cgo.go
index 4f441c32c..4f441c32c 100644
--- a/vendor/github.com/containers/common/pkg/unshare/getenv_linux_cgo.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/getenv_linux_cgo.go
diff --git a/vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go b/vendor/github.com/containers/storage/pkg/unshare/getenv_linux_nocgo.go
index a5005403a..a5005403a 100644
--- a/vendor/github.com/containers/common/pkg/unshare/getenv_linux_nocgo.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/getenv_linux_nocgo.go
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare.c b/vendor/github.com/containers/storage/pkg/unshare/unshare.c
index fd0d48d43..8969191fa 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare.c
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare.c
@@ -1,3 +1,5 @@
+#ifndef UNSHARE_NO_CODE_AT_ALL
+
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -285,3 +287,5 @@ void _containers_unshare(void)
}
return;
}
+
+#endif // !UNSHARE_NO_CODE_AT_ALL
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare.go b/vendor/github.com/containers/storage/pkg/unshare/unshare.go
index 1eff82e8e..1eff82e8e 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare.go
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare_cgo.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_cgo.go
index b3f8099f6..b3f8099f6 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare_cgo.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_cgo.go
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare_gccgo.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_gccgo.go
index 2f95da7d8..2f95da7d8 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare_gccgo.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_gccgo.go
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare_linux.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
index ef33ab8eb..96b857543 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare_linux.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_linux.go
@@ -31,9 +31,9 @@ type Cmd struct {
*exec.Cmd
UnshareFlags int
UseNewuidmap bool
- UidMappings []specs.LinuxIDMapping
+ UidMappings []specs.LinuxIDMapping // nolint: golint
UseNewgidmap bool
- GidMappings []specs.LinuxIDMapping
+ GidMappings []specs.LinuxIDMapping // nolint: golint
GidMappingsEnableSetgroups bool
Setsid bool
Setpgrp bool
@@ -367,7 +367,7 @@ type Runnable interface {
Run() error
}
-func bailOnError(err error, format string, a ...interface{}) {
+func bailOnError(err error, format string, a ...interface{}) { // nolint: golint,goprintffuncname
if err != nil {
if format != "" {
logrus.Errorf("%s: %v", fmt.Sprintf(format, a...), err)
diff --git a/vendor/github.com/containers/common/pkg/unshare/unshare_unsupported.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go
index bf4d567b8..bf4d567b8 100644
--- a/vendor/github.com/containers/common/pkg/unshare/unshare_unsupported.go
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported.go
diff --git a/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported_cgo.go b/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported_cgo.go
new file mode 100644
index 000000000..d5f2d22a8
--- /dev/null
+++ b/vendor/github.com/containers/storage/pkg/unshare/unshare_unsupported_cgo.go
@@ -0,0 +1,10 @@
+// +build !linux,cgo
+
+package unshare
+
+// Go refuses to compile a subpackage with CGO_ENABLED=1 if there is a *.c file but no 'import "C"'.
+// OTOH if we did have an 'import "C"', the Linux-only code would fail to compile.
+// So, satisfy the Go compiler by using import "C" but #ifdef-ing out all of the code.
+
+// #cgo CPPFLAGS: -DUNSHARE_NO_CODE_AT_ALL
+import "C"
diff --git a/vendor/github.com/containers/storage/storage.conf b/vendor/github.com/containers/storage/storage.conf
index 895b479de..c7f9b2cf8 100644
--- a/vendor/github.com/containers/storage/storage.conf
+++ b/vendor/github.com/containers/storage/storage.conf
@@ -43,8 +43,22 @@ additionalimagestores = [
# lowest host-level IDs first, to the lowest not-yet-mapped in-container ID,
# until all of the entries have been used for maps.
#
-# remap-user = "storage"
-# remap-group = "storage"
+# remap-user = "containers"
+# remap-group = "containers"
+
+# Root-auto-userns-user is a user name which can be used to look up one or more UID/GID
+# ranges in the /etc/subuid and /etc/subgid file. These ranges will be partioned
+# to containers configured to create automatically a user namespace. Containers
+# configured to automatically create a user namespace can still overlap with containers
+# having an explicit mapping set.
+# This setting is ignored when running as rootless.
+# root-auto-userns-user = "storage"
+#
+# Auto-userns-min-size is the minimum size for a user namespace created automatically.
+# auto-userns-min-size=1024
+#
+# Auto-userns-max-size is the minimum size for a user namespace created automatically.
+# auto-userns-max-size=65536
[storage.options.overlay]
# ignore_chown_errors can be set to allow a non privileged user running with
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 9bf32cbaa..697f30b5c 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -26,6 +26,7 @@ import (
"github.com/containers/storage/pkg/parsers"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/stringutils"
+ "github.com/hashicorp/go-multierror"
digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
@@ -152,6 +153,13 @@ type StoreOptions struct {
// for use inside of a user namespace where UID mapping is being used.
UIDMap []idtools.IDMap `json:"uidmap,omitempty"`
GIDMap []idtools.IDMap `json:"gidmap,omitempty"`
+ // RootAutoNsUser is the user used to pick a subrange when automatically setting
+ // a user namespace for the root user.
+ RootAutoNsUser string `json:"root_auto_ns_user,omitempty"`
+ // AutoNsMinSize is the minimum size for an automatic user namespace.
+ AutoNsMinSize uint32 `json:"auto_userns_min_size,omitempty"`
+ // AutoNsMaxSize is the maximum size for an automatic user namespace.
+ AutoNsMaxSize uint32 `json:"auto_userns_max_size,omitempty"`
}
// Store wraps up the various types of file-based stores that we use into a
@@ -469,6 +477,27 @@ type Store interface {
GetDigestLock(digest.Digest) (Locker, error)
}
+// AutoUserNsOptions defines how to automatically create a user namespace.
+type AutoUserNsOptions struct {
+ // Size defines the size for the user namespace. If it is set to a
+ // value bigger than 0, the user namespace will have exactly this size.
+ // If it is not set, some heuristics will be used to find its size.
+ Size uint32
+ // InitialSize defines the minimum size for the user namespace.
+ // The created user namespace will have at least this size.
+ InitialSize uint32
+ // PasswdFile to use if the container uses a volume.
+ PasswdFile string
+ // GroupFile to use if the container uses a volume.
+ GroupFile string
+ // AdditionalUIDMappings specified additional UID mappings to include in
+ // the generated user namespace.
+ AdditionalUIDMappings []idtools.IDMap
+ // AdditionalGIDMappings specified additional GID mappings to include in
+ // the generated user namespace.
+ AdditionalGIDMappings []idtools.IDMap
+}
+
// IDMappingOptions are used for specifying how ID mapping should be set up for
// a layer or container.
type IDMappingOptions struct {
@@ -485,6 +514,8 @@ type IDMappingOptions struct {
HostGIDMapping bool
UIDMap []idtools.IDMap
GIDMap []idtools.IDMap
+ AutoUserNs bool
+ AutoUserNsOpts AutoUserNsOptions
}
// LayerOptions is used for passing options to a Store's CreateLayer() and PutLayer() methods.
@@ -525,11 +556,17 @@ type store struct {
lastLoaded time.Time
runRoot string
graphLock Locker
+ usernsLock Locker
graphRoot string
graphDriverName string
graphOptions []string
uidMap []idtools.IDMap
gidMap []idtools.IDMap
+ autoUsernsUser string
+ autoUIDMap []idtools.IDMap // Set by getAvailableMappings()
+ autoGIDMap []idtools.IDMap // Set by getAvailableMappings()
+ autoNsMinSize uint32
+ autoNsMaxSize uint32
graphDriver drivers.Driver
layerStore LayerStore
roLayerStores []ROLayerStore
@@ -608,6 +645,20 @@ func GetStore(options StoreOptions) (Store, error) {
if err != nil {
return nil, err
}
+
+ usernsLock, err := GetLockfile(filepath.Join(options.GraphRoot, "userns.lock"))
+ if err != nil {
+ return nil, err
+ }
+
+ autoNsMinSize := options.AutoNsMinSize
+ autoNsMaxSize := options.AutoNsMaxSize
+ if autoNsMinSize == 0 {
+ autoNsMinSize = AutoUserNsMinSize
+ }
+ if autoNsMaxSize == 0 {
+ autoNsMaxSize = AutoUserNsMaxSize
+ }
s := &store{
runRoot: options.RunRoot,
graphLock: graphLock,
@@ -616,6 +667,12 @@ func GetStore(options StoreOptions) (Store, error) {
graphOptions: options.GraphDriverOptions,
uidMap: copyIDMap(options.UIDMap),
gidMap: copyIDMap(options.GIDMap),
+ autoUsernsUser: options.RootAutoNsUser,
+ autoNsMinSize: autoNsMinSize,
+ autoNsMaxSize: autoNsMaxSize,
+ autoUIDMap: nil,
+ autoGIDMap: nil,
+ usernsLock: usernsLock,
}
if err := s.load(); err != nil {
return nil, err
@@ -626,6 +683,18 @@ func GetStore(options StoreOptions) (Store, error) {
return s, nil
}
+func copyUint32Slice(slice []uint32) []uint32 {
+ m := []uint32{}
+ if slice != nil {
+ m = make([]uint32, len(slice))
+ copy(m, slice)
+ }
+ if len(m) > 0 {
+ return m[:]
+ }
+ return nil
+}
+
func copyIDMap(idmap []idtools.IDMap) []idtools.IDMap {
m := []idtools.IDMap{}
if idmap != nil {
@@ -1151,21 +1220,32 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
var imageTopLayer *Layer
imageID := ""
- uidMap := options.UIDMap
- gidMap := options.GIDMap
- idMappingsOptions := options.IDMappingOptions
+ if options.AutoUserNs || options.UIDMap != nil || options.GIDMap != nil {
+ // Prevent multiple instances to retrieve the same range when AutoUserNs
+ // are used.
+ // It doesn't prevent containers that specify an explicit mapping to overlap
+ // with AutoUserNs.
+ s.usernsLock.Lock()
+ defer s.usernsLock.Unlock()
+ }
+
+ var imageHomeStore ROImageStore
+ var istore ImageStore
+ var istores []ROImageStore
+ var lstores []ROLayerStore
+ var cimage *Image
if image != "" {
- var imageHomeStore ROImageStore
- lstores, err := s.ROLayerStores()
+ var err error
+ lstores, err = s.ROLayerStores()
if err != nil {
return nil, err
}
- istore, err := s.ImageStore()
+ istore, err = s.ImageStore()
if err != nil {
return nil, err
}
- istores, err := s.ROImageStores()
+ istores, err = s.ROImageStores()
if err != nil {
return nil, err
}
@@ -1176,7 +1256,6 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
return nil, err
}
}
- var cimage *Image
for _, s := range append([]ROImageStore{istore}, istores...) {
store := s
if store == istore {
@@ -1200,7 +1279,21 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
return nil, errors.Wrapf(ErrImageUnknown, "error locating image with ID %q", id)
}
imageID = cimage.ID
+ }
+
+ if options.AutoUserNs {
+ var err error
+ options.UIDMap, options.GIDMap, err = s.getAutoUserNS(id, &options.AutoUserNsOpts, cimage)
+ if err != nil {
+ return nil, err
+ }
+ }
+ uidMap := options.UIDMap
+ gidMap := options.GIDMap
+
+ idMappingsOptions := options.IDMappingOptions
+ if image != "" {
if cimage.TopLayer != "" {
createMappedLayer := imageHomeStore == istore
ilayer, err := s.imageTopLayerForMapping(cimage, imageHomeStore, createMappedLayer, rlstore, lstores, idMappingsOptions)
@@ -2356,14 +2449,15 @@ func (s *store) DeleteContainer(id string) error {
close(errChan)
}()
+ var errors []error
for {
select {
case err, ok := <-errChan:
if !ok {
- return nil
+ return multierror.Append(nil, errors...).ErrorOrNil()
}
if err != nil {
- return err
+ errors = append(errors, err)
}
}
}
@@ -3305,6 +3399,16 @@ func copyStringInterfaceMap(m map[string]interface{}) map[string]interface{} {
// defaultConfigFile path to the system wide storage.conf file
const defaultConfigFile = "/etc/containers/storage.conf"
+// AutoUserNsMinSize is the minimum size for automatically created user namespaces
+const AutoUserNsMinSize = 1024
+
+// AutoUserNsMaxSize is the maximum size for automatically created user namespaces
+const AutoUserNsMaxSize = 65536
+
+// RootAutoUserNsUser is the default user used for root containers when automatically
+// creating a user namespace.
+const RootAutoUserNsUser = "containers"
+
// DefaultConfigFile returns the path to the storage config file used
func DefaultConfigFile(rootless bool) (string, error) {
if rootless {
@@ -3406,6 +3510,13 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
} else {
storeOptions.GIDMap = append(storeOptions.GIDMap, gidmap...)
}
+ storeOptions.RootAutoNsUser = config.Storage.Options.RootAutoUsernsUser
+ if config.Storage.Options.AutoUsernsMinSize > 0 {
+ storeOptions.AutoNsMinSize = config.Storage.Options.AutoUsernsMinSize
+ }
+ if config.Storage.Options.AutoUsernsMaxSize > 0 {
+ storeOptions.AutoNsMaxSize = config.Storage.Options.AutoUsernsMaxSize
+ }
storeOptions.GraphDriverOptions = append(storeOptions.GraphDriverOptions, cfg.GetGraphDriverOptions(storeOptions.GraphDriverName, config.Storage.Options)...)
diff --git a/vendor/github.com/containers/storage/userns.go b/vendor/github.com/containers/storage/userns.go
new file mode 100644
index 000000000..18e72efd1
--- /dev/null
+++ b/vendor/github.com/containers/storage/userns.go
@@ -0,0 +1,457 @@
+package storage
+
+import (
+ "os"
+ "os/user"
+ "path/filepath"
+ "strconv"
+
+ drivers "github.com/containers/storage/drivers"
+ "github.com/containers/storage/pkg/idtools"
+ "github.com/containers/storage/pkg/unshare"
+ libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// getAdditionalSubIDs looks up the additional IDs configured for
+// the specified user.
+// The argument USERNAME is ignored for rootless users, as it is not
+// possible to use an arbitrary entry in /etc/sub*id.
+// Differently, if the username is not specified for root users, a
+// default name is used.
+func getAdditionalSubIDs(username string) ([]idtools.IDMap, []idtools.IDMap, error) {
+ var uids, gids []idtools.IDMap
+
+ if unshare.IsRootless() {
+ username = os.Getenv("USER")
+ if username == "" {
+ var id string
+ if os.Geteuid() == 0 {
+ id = strconv.Itoa(unshare.GetRootlessUID())
+ } else {
+ id = strconv.Itoa(os.Geteuid())
+ }
+ userID, err := user.LookupId(id)
+ if err == nil {
+ username = userID.Username
+ }
+ }
+ } else if username == "" {
+ username = RootAutoUserNsUser
+ }
+ mappings, err := idtools.NewIDMappings(username, username)
+ if err != nil {
+ logrus.Errorf("cannot find mappings for user %q: %v", username, err)
+ } else {
+ uids = mappings.UIDs()
+ gids = mappings.GIDs()
+ }
+ return uids, gids, nil
+}
+
+// getAvailableMappings returns the list of ranges that are usable by the current user.
+// When running as root, it looks up the additional IDs assigned to the specified user.
+// When running as rootless, the mappings assigned to the unprivileged user are converted
+// to the IDs inside of the initial rootless user namespace.
+func (s *store) getAvailableMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
+ if s.autoUIDMap == nil {
+ uids, gids, err := getAdditionalSubIDs(s.autoUsernsUser)
+ if err != nil {
+ return nil, nil, err
+ }
+ // Store the result so we don't need to look it up again next time
+ s.autoUIDMap, s.autoGIDMap = uids, gids
+ }
+
+ uids := s.autoUIDMap
+ gids := s.autoGIDMap
+
+ if !unshare.IsRootless() {
+ // No mapping to inner namespace needed
+ return copyIDMap(uids), copyIDMap(gids), nil
+ }
+
+ // We are already inside of the rootless user namespace.
+ // We need to remap the configured mappings to what is available
+ // inside of the rootless userns.
+ totaluid := 0
+ totalgid := 0
+ for _, u := range uids {
+ totaluid += u.Size
+ }
+ for _, g := range gids {
+ totalgid += g.Size
+ }
+
+ u := []idtools.IDMap{{ContainerID: 0, HostID: 1, Size: totaluid}}
+ g := []idtools.IDMap{{ContainerID: 0, HostID: 1, Size: totalgid}}
+ return u, g, nil
+}
+
+// parseMountedFiles returns the maximum UID and GID found in the /etc/passwd and
+// /etc/group files.
+func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
+ if passwdFile == "" {
+ passwdFile = filepath.Join(containerMount, "etc/passwd")
+ }
+ if groupFile == "" {
+ groupFile = filepath.Join(groupFile, "etc/group")
+ }
+
+ size := 0
+
+ users, err := libcontainerUser.ParsePasswdFile(passwdFile)
+ if err == nil {
+ for _, u := range users {
+ // Skip the "nobody" user otherwise we end up with 65536
+ // ids with most images
+ if u.Name == "nobody" {
+ continue
+ }
+ if u.Uid > size {
+ size = u.Uid
+ }
+ if u.Gid > size {
+ size = u.Uid
+ }
+ }
+ }
+
+ groups, err := libcontainerUser.ParseGroupFile(groupFile)
+ if err == nil {
+ for _, g := range groups {
+ if g.Name == "nobody" {
+ continue
+ }
+ if g.Gid > size {
+ size = g.Gid
+ }
+ }
+ }
+
+ return uint32(size)
+}
+
+// getMaxSizeFromImage returns the maximum ID used by the specified image.
+// The layer stores must be already locked.
+func (s *store) getMaxSizeFromImage(id string, image *Image, passwdFile, groupFile string) (uint32, error) {
+ lstore, err := s.LayerStore()
+ if err != nil {
+ return 0, err
+ }
+ lstores, err := s.ROLayerStores()
+ if err != nil {
+ return 0, err
+ }
+
+ size := uint32(0)
+
+ var topLayer *Layer
+ layerName := image.TopLayer
+outer:
+ for {
+ for _, ls := range append([]ROLayerStore{lstore}, lstores...) {
+ layer, err := ls.Get(layerName)
+ if err != nil {
+ continue
+ }
+ if image.TopLayer == layerName {
+ topLayer = layer
+ }
+ for _, uid := range layer.UIDs {
+ if uid >= size {
+ size = uid + 1
+ }
+ }
+ for _, gid := range layer.GIDs {
+ if gid >= size {
+ size = gid + 1
+ }
+ }
+ layerName = layer.Parent
+ if layerName == "" {
+ break outer
+ }
+ continue outer
+ }
+ return 0, errors.Errorf("cannot find layer %q", layerName)
+ }
+
+ rlstore, err := s.LayerStore()
+ if err != nil {
+ return 0, err
+ }
+
+ layerOptions := &LayerOptions{
+ IDMappingOptions: IDMappingOptions{
+ HostUIDMapping: true,
+ HostGIDMapping: true,
+ UIDMap: nil,
+ GIDMap: nil,
+ },
+ }
+
+ // We need to create a temporary layer so we can mount it and lookup the
+ // maximum IDs used.
+ clayer, err := rlstore.Create(id, topLayer, nil, "", nil, layerOptions, false)
+ if err != nil {
+ return 0, err
+ }
+ defer rlstore.Delete(clayer.ID)
+
+ mountOptions := drivers.MountOpts{
+ MountLabel: "",
+ UidMaps: nil,
+ GidMaps: nil,
+ Options: nil,
+ }
+
+ mountpoint, err := rlstore.Mount(clayer.ID, mountOptions)
+ if err != nil {
+ return 0, err
+ }
+ defer rlstore.Unmount(clayer.ID, true)
+
+ userFilesSize := parseMountedFiles(mountpoint, passwdFile, groupFile)
+ if userFilesSize > size {
+ size = userFilesSize
+ }
+
+ return size, nil
+}
+
+// subtractHostIDs return the subtraction of the range USED from AVAIL. The range is specified
+// by [HostID, HostID+Size).
+// ContainerID is ignored.
+func subtractHostIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap {
+ switch {
+ case used.HostID <= avail.HostID && used.HostID+used.Size >= avail.HostID+avail.Size:
+ return nil
+ case used.HostID <= avail.HostID && used.HostID+used.Size > avail.HostID && used.HostID+used.Size < avail.HostID+avail.Size:
+ newContainerID := used.HostID + used.Size
+ newHostID := used.HostID + used.Size
+ r := idtools.IDMap{
+ ContainerID: newContainerID,
+ HostID: newHostID,
+ Size: avail.Size + avail.HostID - newHostID,
+ }
+ return []idtools.IDMap{r}
+ case used.HostID > avail.HostID && used.HostID < avail.HostID+avail.Size && used.HostID+used.Size >= avail.HostID+avail.Size:
+ r := idtools.IDMap{
+ ContainerID: avail.ContainerID,
+ HostID: avail.HostID,
+ Size: used.HostID - avail.HostID,
+ }
+ return []idtools.IDMap{r}
+ case used.HostID > avail.HostID && used.HostID < avail.HostID+avail.Size && used.HostID+used.Size < avail.HostID+avail.Size:
+ r1 := idtools.IDMap{
+ ContainerID: avail.ContainerID,
+ HostID: avail.HostID,
+ Size: used.HostID - avail.HostID,
+ }
+ r2 := idtools.IDMap{
+ ContainerID: used.ContainerID + used.Size,
+ HostID: used.HostID + used.Size,
+ Size: avail.HostID + avail.Size - used.HostID - used.Size,
+ }
+ return []idtools.IDMap{r1, r2}
+ default:
+ r := idtools.IDMap{
+ ContainerID: 0,
+ HostID: avail.HostID,
+ Size: avail.Size,
+ }
+ return []idtools.IDMap{r}
+ }
+}
+
+// subtractContainerIDs return the subtraction of the range USED from AVAIL. The range is specified
+// by [ContainerID, ContainerID+Size).
+// HostID is ignored.
+func subtractContainerIDs(avail idtools.IDMap, used idtools.IDMap) []idtools.IDMap {
+ switch {
+ case used.ContainerID <= avail.ContainerID && used.ContainerID+used.Size >= avail.ContainerID+avail.Size:
+ return nil
+ case used.ContainerID <= avail.ContainerID && used.ContainerID+used.Size > avail.ContainerID && used.ContainerID+used.Size < avail.ContainerID+avail.Size:
+ newContainerID := used.ContainerID + used.Size
+ newHostID := used.HostID + used.Size
+ r := idtools.IDMap{
+ ContainerID: newContainerID,
+ HostID: newHostID,
+ Size: avail.Size + avail.ContainerID - newContainerID,
+ }
+ return []idtools.IDMap{r}
+ case used.ContainerID > avail.ContainerID && used.ContainerID < avail.ContainerID+avail.Size && used.ContainerID+used.Size >= avail.ContainerID+avail.Size:
+ r := idtools.IDMap{
+ ContainerID: avail.ContainerID,
+ HostID: avail.HostID,
+ Size: used.ContainerID - avail.ContainerID,
+ }
+ return []idtools.IDMap{r}
+ case used.ContainerID > avail.ContainerID && used.ContainerID < avail.ContainerID+avail.Size && used.ContainerID+used.Size < avail.ContainerID+avail.Size:
+ r1 := idtools.IDMap{
+ ContainerID: avail.ContainerID,
+ HostID: avail.HostID,
+ Size: used.ContainerID - avail.ContainerID,
+ }
+ r2 := idtools.IDMap{
+ ContainerID: used.ContainerID + used.Size,
+ HostID: used.HostID + used.Size,
+ Size: avail.ContainerID + avail.Size - used.ContainerID - used.Size,
+ }
+ return []idtools.IDMap{r1, r2}
+ default:
+ r := idtools.IDMap{
+ ContainerID: avail.ContainerID,
+ HostID: avail.HostID,
+ Size: avail.Size,
+ }
+ return []idtools.IDMap{r}
+ }
+}
+
+// subtractAll subtracts all usedIDs from the available IDs.
+func subtractAll(availableIDs, usedIDs []idtools.IDMap, host bool) []idtools.IDMap {
+ for _, u := range usedIDs {
+ for i := 0; i < len(availableIDs); {
+ var prev []idtools.IDMap
+ if i > 0 {
+ prev = availableIDs[:i-1]
+ }
+ next := availableIDs[i+1:]
+ cur := availableIDs[i]
+ var newRanges []idtools.IDMap
+ if host {
+ newRanges = subtractHostIDs(cur, u)
+ } else {
+ newRanges = subtractContainerIDs(cur, u)
+ }
+ availableIDs = append(append(prev, newRanges...), next...)
+ i += len(newRanges)
+ }
+ }
+ return availableIDs
+}
+
+// findAvailableIDRange returns the list of IDs that are not used by existing containers.
+// This function is used to lookup both UIDs and GIDs.
+func findAvailableIDRange(size uint32, availableIDs, usedIDs []idtools.IDMap) ([]idtools.IDMap, error) {
+ var avail []idtools.IDMap
+
+ // ContainerID will be adjusted later.
+ for _, i := range availableIDs {
+ n := idtools.IDMap{
+ ContainerID: 0,
+ HostID: i.HostID,
+ Size: i.Size,
+ }
+ avail = append(avail, n)
+ }
+ avail = subtractAll(avail, usedIDs, true)
+
+ currentID := 0
+ remaining := size
+ // We know the size for each intervals, let's adjust the ContainerID for each
+ // of them.
+ for i := 0; i < len(avail); i++ {
+ avail[i].ContainerID = currentID
+ if uint32(avail[i].Size) >= remaining {
+ avail[i].Size = int(remaining)
+ return avail[:i+1], nil
+ }
+ remaining -= uint32(avail[i].Size)
+ }
+
+ return nil, errors.New("could not find enough available IDs")
+}
+
+// findAvailableRange returns both the list of UIDs and GIDs ranges that are not
+// currently used by other containers.
+// It is a wrapper for findAvailableIDRange.
+func findAvailableRange(sizeUID, sizeGID uint32, availableUIDs, availableGIDs, usedUIDs, usedGIDs []idtools.IDMap) ([]idtools.IDMap, []idtools.IDMap, error) {
+ UIDMap, err := findAvailableIDRange(sizeUID, availableUIDs, usedUIDs)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ GIDMap, err := findAvailableIDRange(sizeGID, availableGIDs, usedGIDs)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return UIDMap, GIDMap, nil
+}
+
+// getAutoUserNS creates an automatic user namespace
+func (s *store) getAutoUserNS(id string, options *AutoUserNsOptions, image *Image) ([]idtools.IDMap, []idtools.IDMap, error) {
+ requestedSize := uint32(0)
+ initialSize := uint32(1)
+ if options.Size > 0 {
+ requestedSize = options.Size
+ }
+ if options.InitialSize > 0 {
+ initialSize = options.InitialSize
+ }
+
+ availableUIDs, availableGIDs, err := s.getAvailableMappings()
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "cannot read mappings")
+ }
+
+ // Look every container that is using a user namespace and store
+ // the intervals that are already used.
+ containers, err := s.Containers()
+ if err != nil {
+ return nil, nil, err
+ }
+ var usedUIDs, usedGIDs []idtools.IDMap
+ for _, c := range containers {
+ usedUIDs = append(usedUIDs, c.UIDMap...)
+ usedGIDs = append(usedGIDs, c.GIDMap...)
+ }
+
+ size := requestedSize
+
+ // If there is no requestedSize, lookup the maximum used IDs in the layers
+ // metadata. Make sure the size is at least s.autoNsMinSize and it is not
+ // bigger than s.autoNsMaxSize.
+ // This is a best effort heuristic.
+ if requestedSize == 0 {
+ size = initialSize
+ if s.autoNsMinSize > size {
+ size = s.autoNsMinSize
+ }
+ if image != nil {
+ sizeFromImage, err := s.getMaxSizeFromImage(id, image, options.PasswdFile, options.GroupFile)
+ if err != nil {
+ return nil, nil, err
+ }
+ if sizeFromImage > size {
+ size = sizeFromImage
+ }
+ }
+ if s.autoNsMaxSize > 0 && size > s.autoNsMaxSize {
+ return nil, nil, errors.Errorf("the container needs a user namespace with size %q that is bigger than the maximum value allowed with userns=auto %q", size, s.autoNsMaxSize)
+ }
+ }
+ // Make sure the specified additional IDs are not used as part of the automatic
+ // mapping
+ usedUIDs = append(usedUIDs, options.AdditionalUIDMappings...)
+ usedGIDs = append(usedGIDs, options.AdditionalGIDMappings...)
+ availableUIDs, availableGIDs, err = findAvailableRange(size, size, availableUIDs, availableGIDs, usedUIDs, usedGIDs)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // We need to make sure the specified container IDs are also dropped from the automatic
+ // namespaces we have found.
+ if len(options.AdditionalUIDMappings) > 0 {
+ availableUIDs = subtractAll(availableUIDs, options.AdditionalUIDMappings, false)
+ }
+ if len(options.AdditionalGIDMappings) > 0 {
+ availableGIDs = subtractAll(availableGIDs, options.AdditionalGIDMappings, false)
+ }
+
+ return append(availableUIDs, options.AdditionalUIDMappings...), append(availableGIDs, options.AdditionalGIDMappings...), nil
+}
diff --git a/vendor/github.com/openshift/imagebuilder/builder.go b/vendor/github.com/openshift/imagebuilder/builder.go
index 81d7b8421..7f2f6e482 100644
--- a/vendor/github.com/openshift/imagebuilder/builder.go
+++ b/vendor/github.com/openshift/imagebuilder/builder.go
@@ -209,12 +209,8 @@ func NewStages(node *parser.Node, b *Builder) (Stages, error) {
stages = append(stages, Stage{
Position: i,
Name: name,
- Builder: &Builder{
- Args: b.Args,
- AllowedArgs: b.AllowedArgs,
- Env: b.Env,
- },
- Node: root,
+ Builder: b.builderForStage(),
+ Node: root,
})
}
return stages, nil
@@ -235,17 +231,30 @@ func (b *Builder) extractHeadingArgsFromNode(node *parser.Node) error {
}
}
+ // Set children equal to everything except the leading ARG nodes
+ node.Children = children
+
+ // Use a separate builder to evaluate the heading args
+ tempBuilder := NewBuilder(b.UserArgs)
+
+ // Evaluate all the heading arg commands
for _, c := range args {
- step := b.Step()
+ step := tempBuilder.Step()
if err := step.Resolve(c); err != nil {
return err
}
- if err := b.Run(step, NoopExecutor, false); err != nil {
+ if err := tempBuilder.Run(step, NoopExecutor, false); err != nil {
return err
}
}
- node.Children = children
+ // Add all of the defined heading args to the original builder's HeadingArgs map
+ for k, v := range tempBuilder.Args {
+ if _, ok := tempBuilder.AllowedArgs[k]; ok {
+ b.HeadingArgs[k] = v
+ }
+ }
+
return nil
}
@@ -264,13 +273,23 @@ func extractNameFromNode(node *parser.Node) (string, bool) {
return n.Next.Value, true
}
+func (b *Builder) builderForStage() *Builder {
+ stageBuilder := NewBuilder(b.UserArgs)
+ for k, v := range b.HeadingArgs {
+ stageBuilder.HeadingArgs[k] = v
+ }
+ return stageBuilder
+}
+
type Builder struct {
RunConfig docker.Config
- Env []string
- Args map[string]string
- CmdSet bool
- Author string
+ Env []string
+ Args map[string]string
+ HeadingArgs map[string]string
+ UserArgs map[string]string
+ CmdSet bool
+ Author string
AllowedArgs map[string]bool
Volumes VolumeSet
@@ -288,12 +307,16 @@ func NewBuilder(args map[string]string) *Builder {
for k, v := range builtinAllowedBuildArgs {
allowed[k] = v
}
- provided := make(map[string]string)
+ userArgs := make(map[string]string)
+ initialArgs := make(map[string]string)
for k, v := range args {
- provided[k] = v
+ userArgs[k] = v
+ initialArgs[k] = v
}
return &Builder{
- Args: provided,
+ Args: initialArgs,
+ UserArgs: userArgs,
+ HeadingArgs: make(map[string]string),
AllowedArgs: allowed,
}
}
diff --git a/vendor/github.com/openshift/imagebuilder/dispatchers.go b/vendor/github.com/openshift/imagebuilder/dispatchers.go
index e7f2f97bf..1d77a193b 100644
--- a/vendor/github.com/openshift/imagebuilder/dispatchers.go
+++ b/vendor/github.com/openshift/imagebuilder/dispatchers.go
@@ -216,7 +216,7 @@ func from(b *Builder, args []string, attributes map[string]bool, flagArgs []stri
// Support ARG before from
argStrs := []string{}
- for n, v := range b.Args {
+ for n, v := range b.HeadingArgs {
argStrs = append(argStrs, n+"="+v)
}
var err error
@@ -598,10 +598,16 @@ func arg(b *Builder, args []string, attributes map[string]bool, flagArgs []strin
// add the arg to allowed list of build-time args from this step on.
b.AllowedArgs[name] = true
+ // If there is still no default value, a value can be assigned from the heading args
+ if val, ok := b.HeadingArgs[name]; ok && !hasDefault {
+ b.Args[name] = val
+ }
+
// If there is a default value associated with this arg then add it to the
- // b.buildArgs if one is not already passed to the builder. The args passed
- // to builder override the default value of 'arg'.
- if _, ok := b.Args[name]; !ok && hasDefault {
+ // b.buildArgs, later default values for the same arg override earlier ones.
+ // The args passed to builder (UserArgs) override the default value of 'arg'
+ // Don't add them here as they were already set in NewBuilder.
+ if _, ok := b.UserArgs[name]; !ok && hasDefault {
b.Args[name] = value
}
diff --git a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
index f1aa5f859..4fc081d43 100644
--- a/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
+++ b/vendor/github.com/rootless-containers/rootlesskit/pkg/port/portutil/portutil.go
@@ -58,8 +58,7 @@ func ValidatePortSpec(spec port.Spec, existingPorts map[int]*port.Status) error
sp := p.Spec
sameProto := sp.Proto == spec.Proto
sameParent := sp.ParentIP == spec.ParentIP && sp.ParentPort == spec.ParentPort
- sameChild := sp.ChildPort == spec.ChildPort
- if sameProto && (sameParent || sameChild) {
+ if sameProto && sameParent {
return errors.Errorf("conflict with ID %d", id)
}
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ad801a07a..f474a12cf 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -64,7 +64,7 @@ github.com/containernetworking/plugins/pkg/ns
github.com/containernetworking/plugins/pkg/utils/hwaddr
github.com/containernetworking/plugins/plugins/ipam/host-local/backend
github.com/containernetworking/plugins/plugins/ipam/host-local/backend/allocator
-# github.com/containers/buildah v1.14.5
+# github.com/containers/buildah v1.14.6-0.20200402210551-e9a6703edee2
github.com/containers/buildah
github.com/containers/buildah/bind
github.com/containers/buildah/chroot
@@ -82,11 +82,13 @@ github.com/containers/buildah/pkg/secrets
github.com/containers/buildah/pkg/supplemented
github.com/containers/buildah/pkg/umask
github.com/containers/buildah/util
-# github.com/containers/common v0.6.1
+# github.com/containers/common v0.8.0
+github.com/containers/common/pkg/apparmor
github.com/containers/common/pkg/capabilities
+github.com/containers/common/pkg/cgroupv2
github.com/containers/common/pkg/config
-github.com/containers/common/pkg/unshare
-# github.com/containers/conmon v2.0.10+incompatible
+github.com/containers/common/pkg/sysinfo
+# github.com/containers/conmon v2.0.14+incompatible
github.com/containers/conmon/runner/config
# github.com/containers/image/v5 v5.3.1
github.com/containers/image/v5/copy
@@ -148,7 +150,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.16.6
+# github.com/containers/storage v1.18.1
github.com/containers/storage
github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs
@@ -188,6 +190,7 @@ github.com/containers/storage/pkg/stringutils
github.com/containers/storage/pkg/system
github.com/containers/storage/pkg/tarlog
github.com/containers/storage/pkg/truncindex
+github.com/containers/storage/pkg/unshare
# github.com/coreos/go-iptables v0.4.5
github.com/coreos/go-iptables/iptables
# github.com/coreos/go-systemd/v22 v22.0.0
@@ -414,7 +417,7 @@ github.com/opencontainers/selinux/go-selinux/label
github.com/opencontainers/selinux/pkg/pwalk
# github.com/openshift/api v0.0.0-20200106203948-7ab22a2c8316
github.com/openshift/api/config/v1
-# github.com/openshift/imagebuilder v1.1.3
+# github.com/openshift/imagebuilder v1.1.4
github.com/openshift/imagebuilder
github.com/openshift/imagebuilder/dockerfile/command
github.com/openshift/imagebuilder/dockerfile/parser
@@ -450,7 +453,7 @@ github.com/prometheus/common/model
github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs
github.com/prometheus/procfs/internal/util
-# github.com/rootless-containers/rootlesskit v0.9.2
+# github.com/rootless-containers/rootlesskit v0.9.3
github.com/rootless-containers/rootlesskit/pkg/msgutil
github.com/rootless-containers/rootlesskit/pkg/port
github.com/rootless-containers/rootlesskit/pkg/port/builtin