summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.tool/lint2
-rw-r--r--Makefile20
-rw-r--r--README.md4
-rw-r--r--RELEASE_NOTES.md13
-rw-r--r--changelog.txt29
-rw-r--r--cmd/podman/build.go15
-rw-r--r--cmd/podman/shared/funcs.go8
-rw-r--r--cmd/podman/shared/funcs_test.go9
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/__init__.py2
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/version_action.py41
-rw-r--r--install.md2
-rw-r--r--libpod/container_api.go7
-rw-r--r--libpod/container_graph_test.go4
-rw-r--r--libpod/oci.go5
-rw-r--r--libpod/oci_linux.go10
-rw-r--r--pkg/rootless/rootless_linux.go11
-rw-r--r--pkg/varlinkapi/images.go3
-rw-r--r--test/README.md59
-rw-r--r--test/e2e/attach_test.go5
-rw-r--r--test/e2e/checkpoint_test.go5
-rw-r--r--test/e2e/commit_test.go5
-rw-r--r--test/e2e/create_test.go5
-rw-r--r--test/e2e/diff_test.go5
-rw-r--r--test/e2e/exec_test.go5
-rw-r--r--test/e2e/export_test.go5
-rw-r--r--test/e2e/history_test.go5
-rw-r--r--test/e2e/images_test.go5
-rw-r--r--test/e2e/import_test.go5
-rw-r--r--test/e2e/info_test.go5
-rw-r--r--test/e2e/inspect_test.go5
-rw-r--r--test/e2e/kill_test.go5
-rw-r--r--test/e2e/libpod_suite_test.go475
-rw-r--r--test/e2e/load_test.go9
-rw-r--r--test/e2e/logs_test.go5
-rw-r--r--test/e2e/mount_test.go5
-rw-r--r--test/e2e/namespace_test.go5
-rw-r--r--test/e2e/pause_test.go5
-rw-r--r--test/e2e/pod_create_test.go5
-rw-r--r--test/e2e/pod_infra_container_test.go5
-rw-r--r--test/e2e/pod_inspect_test.go5
-rw-r--r--test/e2e/pod_kill_test.go5
-rw-r--r--test/e2e/pod_pause_test.go5
-rw-r--r--test/e2e/pod_pod_namespaces.go5
-rw-r--r--test/e2e/pod_ps_test.go5
-rw-r--r--test/e2e/pod_restart_test.go5
-rw-r--r--test/e2e/pod_rm_test.go5
-rw-r--r--test/e2e/pod_start_test.go5
-rw-r--r--test/e2e/pod_stats_test.go5
-rw-r--r--test/e2e/pod_stop_test.go5
-rw-r--r--test/e2e/pod_top_test.go5
-rw-r--r--test/e2e/port_test.go5
-rw-r--r--test/e2e/ps_test.go5
-rw-r--r--test/e2e/pull_test.go13
-rw-r--r--test/e2e/push_test.go45
-rw-r--r--test/e2e/refresh_test.go13
-rw-r--r--test/e2e/restart_test.go7
-rw-r--r--test/e2e/rm_test.go5
-rw-r--r--test/e2e/rmi_test.go5
-rw-r--r--test/e2e/rootless_test.go13
-rw-r--r--test/e2e/run_cgroup_parent_test.go11
-rw-r--r--test/e2e/run_cleanup_test.go9
-rw-r--r--test/e2e/run_cpu_test.go5
-rw-r--r--test/e2e/run_device_test.go5
-rw-r--r--test/e2e/run_dns_test.go5
-rw-r--r--test/e2e/run_entrypoint_test.go5
-rw-r--r--test/e2e/run_exit_test.go5
-rw-r--r--test/e2e/run_memory_test.go5
-rw-r--r--test/e2e/run_networking_test.go11
-rw-r--r--test/e2e/run_ns_test.go11
-rw-r--r--test/e2e/run_passwd_test.go5
-rw-r--r--test/e2e/run_privileged_test.go17
-rw-r--r--test/e2e/run_restart_test.go7
-rw-r--r--test/e2e/run_selinux_test.go5
-rw-r--r--test/e2e/run_signal_test.go23
-rw-r--r--test/e2e/run_staticip_test.go5
-rw-r--r--test/e2e/run_test.go7
-rw-r--r--test/e2e/run_userns_test.go5
-rw-r--r--test/e2e/runlabel_test.go5
-rw-r--r--test/e2e/save_test.go5
-rw-r--r--test/e2e/search_test.go19
-rw-r--r--test/e2e/start_test.go5
-rw-r--r--test/e2e/stats_test.go5
-rw-r--r--test/e2e/stop_test.go5
-rw-r--r--test/e2e/tag_test.go5
-rw-r--r--test/e2e/top_test.go5
-rw-r--r--test/e2e/version_test.go5
-rw-r--r--test/e2e/wait_test.go5
-rw-r--r--test/goecho/goecho.go29
-rw-r--r--test/system/libpod_suite_test.go217
-rw-r--r--test/system/version_test.go51
-rw-r--r--test/utils/common_function_test.go150
-rw-r--r--test/utils/podmansession_test.go90
-rw-r--r--test/utils/podmantest_test.go74
-rw-r--r--test/utils/utils.go432
-rw-r--r--test/utils/utils_suite_test.go52
-rw-r--r--vendor.conf5
-rw-r--r--vendor/github.com/containers/buildah/README.md1
-rw-r--r--vendor/github.com/containers/buildah/buildah.go1
-rw-r--r--vendor/github.com/containers/buildah/chroot/run.go2
-rw-r--r--vendor/github.com/containers/buildah/common.go28
-rw-r--r--vendor/github.com/containers/buildah/delete.go3
-rw-r--r--vendor/github.com/containers/buildah/image.go1
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/build.go98
-rw-r--r--vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go133
-rw-r--r--vendor/github.com/containers/buildah/new.go81
-rw-r--r--vendor/github.com/containers/buildah/pkg/cli/common.go8
-rw-r--r--vendor/github.com/containers/buildah/pull.go5
-rw-r--r--vendor/github.com/containers/buildah/run.go180
-rw-r--r--vendor/github.com/containers/buildah/unshare/unshare.go4
-rw-r--r--vendor/github.com/containers/buildah/util/util.go61
-rw-r--r--vendor/github.com/containers/buildah/vendor.conf6
-rw-r--r--vendor/github.com/containers/storage/README.md2
-rw-r--r--vendor/github.com/containers/storage/drivers/aufs/aufs.go2
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go19
-rw-r--r--vendor/github.com/containers/storage/drivers/zfs/zfs.go2
-rw-r--r--vendor/github.com/containers/storage/layers.go12
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/example_changes.go97
-rw-r--r--vendor/github.com/containers/storage/pkg/idtools/parser.go56
-rw-r--r--vendor/github.com/containers/storage/store.go62
-rw-r--r--vendor/github.com/containers/storage/vendor.conf4
-rw-r--r--vendor/github.com/google/shlex/COPYING202
-rw-r--r--vendor/github.com/google/shlex/README2
-rw-r--r--vendor/github.com/google/shlex/shlex.go416
123 files changed, 2766 insertions, 1021 deletions
diff --git a/.tool/lint b/.tool/lint
index b7006c8fd..f7bf81c1d 100755
--- a/.tool/lint
+++ b/.tool/lint
@@ -40,6 +40,8 @@ ${LINTER} \
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$'\
--exclude='duplicate of.*_test.go.*\(dupl\)$'\
--exclude='cmd\/client\/.*\.go.*\(dupl\)$'\
+ --exclude='libpod\/.*_easyjson.go:.*'\
+ --exclude='.* other occurrence\(s\) of "(container|host|tmpfs|unknown)" found in: .*\(goconst\)$'\
--exclude='vendor\/.*'\
--exclude='podman\/.*'\
--exclude='server\/seccomp\/.*\.go.*$'\
diff --git a/Makefile b/Makefile
index 04d6230d6..195d105b7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
GO ?= go
DESTDIR ?= /
-EPOCH_TEST_COMMIT ?= 921ccac10c47e0865ec5e4ba00ebb69a03d89473
+EPOCH_TEST_COMMIT ?= 1b52843cfd2ae254a6e52c74e564730f1c875c4c
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
@@ -31,7 +31,7 @@ BASHINSTALLDIR=${PREFIX}/share/bash-completion/completions
OCIUMOUNTINSTALLDIR=$(PREFIX)/share/oci-umount/oci-umount.d
SELINUXOPT ?= $(shell test -x /usr/sbin/selinuxenabled && selinuxenabled && echo -Z)
-PACKAGES ?= $(shell $(GO) list -tags "${BUILDTAGS}" ./... | grep -v github.com/containers/libpod/vendor | grep -v e2e)
+PACKAGES ?= $(shell $(GO) list -tags "${BUILDTAGS}" ./... | grep -v github.com/containers/libpod/vendor | grep -v e2e | grep -v system )
COMMIT_NO ?= $(shell git rev-parse HEAD 2> /dev/null || true)
GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),"${COMMIT_NO}-dirty","${COMMIT_NO}")
@@ -104,6 +104,9 @@ test/copyimg/copyimg: .gopathok $(wildcard test/copyimg/*.go)
test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
$(GO) build -ldflags '$(LDFLAGS)' -tags "$(BUILDTAGS) containers_image_ostree_stub" -o $@ $(PROJECT)/test/checkseccomp
+test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go)
+ $(GO) build -ldflags '$(LDFLAGS)' -o $@ $(PROJECT)/test/goecho
+
podman: .gopathok $(PODMAN_VARLINK_DEPENDENCIES)
$(GO) build -i -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o bin/$@ $(PROJECT)/cmd/podman
@@ -130,6 +133,7 @@ clean:
test/bin2img/bin2img \
test/checkseccomp/checkseccomp \
test/copyimg/copyimg \
+ test/goecho/goecho \
test/testdata/redis-image \
cmd/podman/varlink/iopodman.go \
libpod/container_ffjson.go \
@@ -166,7 +170,7 @@ shell: libpodimage
testunit: libpodimage
${CONTAINER_RUNTIME} run -e STORAGE_OPTIONS="--storage-driver=vfs" -e TESTFLAGS -e CGROUP_MANAGER=cgroupfs -e TRAVIS -t --privileged --rm -v ${CURDIR}:/go/src/${PROJECT} ${LIBPOD_IMAGE} make localunit
-localunit: varlink_generate
+localunit: test/goecho/goecho varlink_generate
$(GO) test -tags "$(BUILDTAGS)" -cover $(PACKAGES)
ginkgo:
@@ -174,6 +178,12 @@ ginkgo:
localintegration: varlink_generate test-binaries clientintegration ginkgo
+localsystem: .install.ginkgo .install.gomega
+ ginkgo -v -noColor test/system/
+
+system.test-binary: .install.ginkgo .install.gomega
+ $(GO) test -c ./test/system
+
clientintegration:
$(MAKE) -C contrib/python/podman integration
$(MAKE) -C contrib/python/pypodman integration
@@ -183,7 +193,7 @@ vagrant-check:
binaries: varlink_generate easyjson_generate podman
-test-binaries: test/bin2img/bin2img test/copyimg/copyimg test/checkseccomp/checkseccomp
+test-binaries: test/bin2img/bin2img test/copyimg/copyimg test/checkseccomp/checkseccomp test/goecho/goecho
MANPAGES_MD ?= $(wildcard docs/*.md pkg/*/docs/*.md)
MANPAGES ?= $(MANPAGES_MD:%.md=%)
@@ -283,7 +293,7 @@ install.tools: .install.gitvalidation .install.gometalinter .install.md2man .ins
if [ ! -x "$(GOBIN)/gometalinter" ]; then \
$(GO) get -u github.com/alecthomas/gometalinter; \
cd $(FIRST_GOPATH)/src/github.com/alecthomas/gometalinter; \
- git checkout 23261fa046586808612c61da7a81d75a658e0814; \
+ git checkout e8d801238da6f0dfd14078d68f9b53fa50a7eeb5; \
$(GO) install github.com/alecthomas/gometalinter; \
$(GOBIN)/gometalinter --install; \
fi
diff --git a/README.md b/README.md
index 157e94d7c..9cfb5b14c 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
![PODMAN logo](logo/podman-logo-source.svg)
# libpod - library for running OCI-based containers in Pods
-### Latest Version: 0.10.1.3
+### Latest Version: 0.11.1.1
### Status: Active Development
+### Continuous Integration: [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod)
+
## What is the scope of this project?
libpod provides a library for applications looking to use the Container Pod concept popularized by Kubernetes.
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 9cdf3faae..05854c8d7 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,18 @@
# Release Notes
+## 0.11.1.1
+### Bugfixes
+- Fixed a bug where Podman was not correctly adding firewall rules for containers, preventing them from accessing the network
+- Fixed a bug where full error messages were being lost when creating containers with user namespaces
+- Fixed a bug where container state was not properly updated if a failure occurred during network setup, which could cause mounts to be left behind when the container was removed
+- Fixed a bug where `podman exec` could time out on slower systems by increasing the relevant timeout
+
+### Misc
+- `podman rm -f` now removes paused containers. As such, `podman rm -af` completing successfully guarantees all Podman containers have been removed
+- Added a field to `podman info` to show if Podman is being run as rootless
+- Made a small output format change to `podman images` - image sizes now feature a space between number and unit (e.g. `123 MB` now instead of `123MB`)
+- Vendored an updated version of `containers/storage` to fix several bugs reported upstream
+
## 0.11.1
### Features
- Added `--all` and `--latest` flags to `podman checkpoint` and `podman restore`
diff --git a/changelog.txt b/changelog.txt
index 9aaec0e74..7b0f0f3af 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,32 @@
+- Changelog for v0.11.1.1 (2018-11-15)
+ * Vendor in containers/storage
+ * Add release notes for 0.11.1.1
+ * Increase pidWaitTimeout to 60s
+ * Cirrus: Add master branch testing status badge
+ * rootless: call IsRootless just once
+ * Bump golang to v1.10 in install.md
+ * Standardized container image for gofmt and lint
+ * Make list of approvers same as reviewers
+ * vendor: update ostree-go
+ * vendor.conf: fix typo
+ * Cleanup podman spec to not show git checkout is dirty
+ * Add space between num & unit in images output
+ * Update troubleshooting guide to deal with rootless path
+ * troubleshooting.md: add a recipe for rootless ping
+ * remove $-prefix from (most) shell examples
+ * docs: Fix duplicated entry for pod-container-unmount
+ * Better document rootless containers
+ * info: add rootless field
+ * Accurately update state if prepare() partially fails
+ * Do not hide errors when creating container with UserNSRoot
+ * rm -f now removes a paused container
+ * correct assignment of networkStatus
+ * podman_tutorial: cni build path has changed
+ * Bump gitvalidation epoch
+ * Bump to v0.11.2-dev
+ * Cirrus: Ignore any error from the IRC messenger
+ * rootless: default to fuse-overlayfs when available
+
- Changelog for v0.11.1 (2018-11-08)
* Update release notes for 0.11.1
* update seccomp.json
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 14bf226f9..880cb892f 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -1,6 +1,11 @@
package main
import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
"github.com/containers/buildah"
"github.com/containers/buildah/imagebuildah"
buildahcli "github.com/containers/buildah/pkg/cli"
@@ -10,15 +15,15 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
)
var (
layerFlags = []cli.Flag{
cli.BoolTFlag{
+ Name: "force-rm",
+ Usage: "Always remove intermediate containers after a build, even if the build is unsuccessful. (default true)",
+ },
+ cli.BoolTFlag{
Name: "layers",
Usage: "cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. ",
},
@@ -230,7 +235,7 @@ func buildCmd(c *cli.Context) error {
Layers: layers,
NoCache: c.Bool("no-cache"),
RemoveIntermediateCtrs: c.BoolT("rm"),
- ForceRmIntermediateCtrs: c.Bool("force-rm"),
+ ForceRmIntermediateCtrs: c.BoolT("force-rm"),
}
if c.Bool("quiet") {
diff --git a/cmd/podman/shared/funcs.go b/cmd/podman/shared/funcs.go
index a92e0d547..8520c0616 100644
--- a/cmd/podman/shared/funcs.go
+++ b/cmd/podman/shared/funcs.go
@@ -5,6 +5,8 @@ import (
"os"
"path/filepath"
"strings"
+
+ "github.com/google/shlex"
)
func substituteCommand(cmd string) (string, error) {
@@ -42,7 +44,11 @@ func GenerateCommand(command, imageName, name string) ([]string, error) {
if name == "" {
name = imageName
}
- cmd := strings.Split(command, " ")
+
+ cmd, err := shlex.Split(command)
+ if err != nil {
+ return nil, err
+ }
prog, err := substituteCommand(cmd[0])
if err != nil {
diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go
index 596df84e8..7506b9d9c 100644
--- a/cmd/podman/shared/funcs_test.go
+++ b/cmd/podman/shared/funcs_test.go
@@ -18,10 +18,11 @@ var (
)
func TestGenerateCommand(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
+ inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\""
+ correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world"
newCommand, err := GenerateCommand(inputCommand, "foo", "bar")
assert.Nil(t, err)
+ assert.Equal(t, "hello world", newCommand[11])
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
}
@@ -108,8 +109,8 @@ func TestGenerateCommandNoSetName(t *testing.T) {
}
func TestGenerateCommandNoName(t *testing.T) {
- inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
+ inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
+ correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
newCommand, err := GenerateCommand(inputCommand, "foo", "")
assert.Nil(t, err)
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
diff --git a/contrib/python/pypodman/pypodman/lib/actions/__init__.py b/contrib/python/pypodman/pypodman/lib/actions/__init__.py
index 2668cd8ff..bc863ce6d 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/__init__.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/__init__.py
@@ -22,6 +22,7 @@ from pypodman.lib.actions.rm_action import Rm
from pypodman.lib.actions.rmi_action import Rmi
from pypodman.lib.actions.run_action import Run
from pypodman.lib.actions.search_action import Search
+from pypodman.lib.actions.version_action import Version
__all__ = [
'Attach',
@@ -47,4 +48,5 @@ __all__ = [
'Rmi',
'Run',
'Search',
+ 'Version',
]
diff --git a/contrib/python/pypodman/pypodman/lib/actions/version_action.py b/contrib/python/pypodman/pypodman/lib/actions/version_action.py
new file mode 100644
index 000000000..12b6dc576
--- /dev/null
+++ b/contrib/python/pypodman/pypodman/lib/actions/version_action.py
@@ -0,0 +1,41 @@
+"""Remote client command for reporting on Podman service."""
+import json
+import sys
+
+import podman
+import yaml
+from pypodman.lib import AbstractActionBase
+
+
+class Version(AbstractActionBase):
+ """Class for reporting on Podman Service."""
+
+ @classmethod
+ def subparser(cls, parent):
+ """Add Version command to parent parser."""
+ parser = parent.add_parser(
+ 'version', help='report version on podman service')
+ parser.set_defaults(class_=cls, method='version')
+
+ def __init__(self, args):
+ """Construct Version class."""
+ super().__init__(args)
+
+ def version(self):
+ """Report on Podman Service."""
+ try:
+ info = self.client.system.info()
+ except podman.ErrorOccurred as e:
+ sys.stdout.flush()
+ print(
+ '{}'.format(e.reason).capitalize(),
+ file=sys.stderr,
+ flush=True)
+ return 1
+ else:
+ version = info._asdict()['podman']
+ host = info._asdict()['host']
+ print("Version {}".format(version['podman_version']))
+ print("Go Version {}".format(version['go_version']))
+ print("Git Commit {}".format(version['git_commit']))
+ print("OS/Arch {}/{}".format(host["os"], host["arch"]))
diff --git a/install.md b/install.md
index 33224c810..efb568b66 100644
--- a/install.md
+++ b/install.md
@@ -83,7 +83,7 @@ Debian, Ubuntu, and related distributions will also need to do the following set
If using an older release or a long-term support release, be careful to double-check that the version of `runc` is new enough (running `runc --version` should produce `spec: 1.0.0`), or else [build](https://github.com/containers/libpod/blob/master/docs/tutorials/podman_tutorial.md#installing-runc) your own.
-Be careful to double-check that the version of golang is new enough, version 1.8.x or higher is required. If needed, golang kits are available at https://golang.org/dl/
+Be careful to double-check that the version of golang is new enough, version 1.10.x or higher is required. If needed, golang kits are available at https://golang.org/dl/
**Optional**
diff --git a/libpod/container_api.go b/libpod/container_api.go
index d99aec5b4..390987394 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -330,9 +330,10 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
}
pidFile := c.execPidPath(sessionID)
- // 1 second seems a reasonable time to wait
- // See https://github.com/containers/libpod/issues/1495
- const pidWaitTimeout = 1000
+ // 60 second seems a reasonable time to wait
+ // https://github.com/containers/libpod/issues/1495
+ // https://github.com/containers/libpod/issues/1816
+ const pidWaitTimeout = 60000
// Wait until the runtime makes the pidfile
// TODO: If runtime errors before the PID file is created, we have to
diff --git a/libpod/container_graph_test.go b/libpod/container_graph_test.go
index bba3d7aad..25461f1f4 100644
--- a/libpod/container_graph_test.go
+++ b/libpod/container_graph_test.go
@@ -205,6 +205,7 @@ func TestBuildContainerGraphFourContainersNoEdges(t *testing.T) {
ctr3, err := getTestCtrN("3", tmpDir)
assert.NoError(t, err)
ctr4, err := getTestCtrN("4", tmpDir)
+ assert.NoError(t, err)
graph, err := buildContainerGraph([]*Container{ctr1, ctr2, ctr3, ctr4})
assert.NoError(t, err)
@@ -241,6 +242,7 @@ func TestBuildContainerGraphFourContainersTwoInCycle(t *testing.T) {
ctr3, err := getTestCtrN("3", tmpDir)
assert.NoError(t, err)
ctr4, err := getTestCtrN("4", tmpDir)
+ assert.NoError(t, err)
ctr1.config.IPCNsCtr = ctr2.config.ID
ctr2.config.UserNsCtr = ctr1.config.ID
@@ -260,6 +262,7 @@ func TestBuildContainerGraphFourContainersAllInCycle(t *testing.T) {
ctr3, err := getTestCtrN("3", tmpDir)
assert.NoError(t, err)
ctr4, err := getTestCtrN("4", tmpDir)
+ assert.NoError(t, err)
ctr1.config.IPCNsCtr = ctr2.config.ID
ctr2.config.UserNsCtr = ctr3.config.ID
ctr3.config.NetNsCtr = ctr4.config.ID
@@ -281,6 +284,7 @@ func TestBuildContainerGraphFourContainersNoneInCycle(t *testing.T) {
ctr3, err := getTestCtrN("3", tmpDir)
assert.NoError(t, err)
ctr4, err := getTestCtrN("4", tmpDir)
+ assert.NoError(t, err)
ctr1.config.IPCNsCtr = ctr2.config.ID
ctr1.config.NetNsCtr = ctr3.config.ID
ctr2.config.UserNsCtr = ctr3.config.ID
diff --git a/libpod/oci.go b/libpod/oci.go
index 233bacfbb..71da830b5 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -350,7 +350,8 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
// Set the label of the conmon process to be level :s0
// This will allow the container processes to talk to fifo-files
// passed into the container by conmon
- plabel, err := selinux.CurrentLabel()
+ var plabel string
+ plabel, err = selinux.CurrentLabel()
if err != nil {
childPipe.Close()
return errors.Wrapf(err, "Failed to get current SELinux label")
@@ -360,7 +361,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
runtime.LockOSThread()
if c["level"] != "s0" && c["level"] != "" {
c["level"] = "s0"
- if err := label.SetProcessLabel(c.Get()); err != nil {
+ if err = label.SetProcessLabel(c.Get()); err != nil {
runtime.UnlockOSThread()
return err
}
diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go
index e6b7cbe4f..b159eae78 100644
--- a/libpod/oci_linux.go
+++ b/libpod/oci_linux.go
@@ -19,6 +19,8 @@ import (
"golang.org/x/sys/unix"
)
+const unknownPackage = "Unknown"
+
func (r *OCIRuntime) moveConmonToCgroup(ctr *Container, cgroupParent string, cmd *exec.Cmd) error {
if os.Geteuid() == 0 {
if r.cgroupManager == SystemdCgroupsManager {
@@ -112,7 +114,7 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string, restor
}
func rpmVersion(path string) string {
- output := "Unknown"
+ output := unknownPackage
cmd := exec.Command("/usr/bin/rpm", "-q", "-f", path)
if outp, err := cmd.Output(); err == nil {
output = string(outp)
@@ -121,7 +123,7 @@ func rpmVersion(path string) string {
}
func dpkgVersion(path string) string {
- output := "Unknown"
+ output := unknownPackage
cmd := exec.Command("/usr/bin/dpkg", "-S", path)
if outp, err := cmd.Output(); err == nil {
output = string(outp)
@@ -130,14 +132,14 @@ func dpkgVersion(path string) string {
}
func (r *OCIRuntime) pathPackage() string {
- if out := rpmVersion(r.path); out != "Unknown" {
+ if out := rpmVersion(r.path); out != unknownPackage {
return out
}
return dpkgVersion(r.path)
}
func (r *OCIRuntime) conmonPackage() string {
- if out := rpmVersion(r.conmonPath); out != "Unknown" {
+ if out := rpmVersion(r.conmonPath); out != unknownPackage {
return out
}
return dpkgVersion(r.conmonPath)
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index ff8c8fe34..85b0ef392 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -12,6 +12,7 @@ import (
"runtime"
"strconv"
"strings"
+ "sync"
"syscall"
"unsafe"
@@ -33,9 +34,17 @@ func runInUser() error {
return nil
}
+var (
+ isRootlessOnce sync.Once
+ isRootless bool
+)
+
// IsRootless tells us if we are running in rootless mode
func IsRootless() bool {
- return os.Geteuid() != 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != ""
+ isRootlessOnce.Do(func() {
+ isRootless = os.Geteuid() != 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != ""
+ })
+ return isRootless
}
var (
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index d14c61c39..42e285b53 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -271,6 +271,9 @@ func (i *LibpodAPI) InspectImage(call iopodman.VarlinkCall, name string) error {
return call.ReplyImageNotFound(name)
}
inspectInfo, err := newImage.Inspect(getContext())
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
b, err := json.Marshal(inspectInfo)
if err != nil {
return call.ReplyErrorOccurred(fmt.Sprintf("unable to serialize"))
diff --git a/test/README.md b/test/README.md
index a068bb4f5..2a9a4d4b1 100644
--- a/test/README.md
+++ b/test/README.md
@@ -1,8 +1,33 @@
![PODMAN logo](../logo/podman-logo-source.svg)
-# Integration Tests
+# Test utils
+Test utils provide common functions and structs for testing. It includes two structs:
+* `PodmanTest`: Handle the *podman* command and other global resources like temporary
+directory. It provides basic methods, like checking podman image and pod status. Test
+suites should create their owner test *struct* as a composite of `PodmanTest`, and their
+owner PodmanMakeOptions().
+
+* `PodmanSession`: Store execution session data and related *methods*. Such like get command
+output and so on. It can be used directly in the test suite, only embed it to your owner
+session struct if you need expend it.
+
+## Unittest for test/utils
+To ensure neither *tests* nor *utils* break, There are unit-tests for each *functions* and
+*structs* in `test/utils`. When you adding functions or structs to this *package*, please
+update both unit-tests for it and this documentation.
+
+### Run unit test for test/utils
+Run unit test for test/utils.
+
+```
+make localunit
+```
+
+## Structure of the test utils and test suites
+The test *utils* package is at the same level of test suites. Each test suites also have their
+owner common functions and structs stored in `libpod_suite_test.go`.
-Our primary means of performing integration testing for libpod is with the
-[Ginkgo](https://github.com/onsi/ginkgo) BDD testing framework. This allows
+# Ginkgo test framework
+[Ginkgo](https://github.com/onsi/ginkgo) is a BDD testing framework. This allows
us to use native Golang to perform our tests and there is a strong affiliation
between Ginkgo and the Go test framework.
@@ -32,8 +57,16 @@ The gomega sources can be simply installed with the command:
GOPATH=~/go go get github.com/onsi/gomega/...
```
-### Running the integration tests
+# Integration Tests
+Test suite for integration test for podman command line. It has its own structs:
+* `PodmanTestIntegration`: Integration test *struct* as a composite of `PodmanTest`. It
+set up the global options for *podman* command to ignore the environment influence from
+different test system.
+
+* `PodmanSessionIntegration`: This *struct* has it own *methods* for checking command
+output with given format JSON by using *structs* defined in inspect package.
+## Running the integration tests
You can run the entire suite of integration tests with the following command:
```
@@ -67,3 +100,21 @@ make shell
```
This will run a container and give you a shell and you can follow the instructions above.
+
+# System test
+System tests are used for testing the *podman* CLI in the context of a complete system. It
+requires that *podman*, all dependencies, and configurations are in place. The intention of
+system testing is to match as closely as possible with real-world user/developer use-cases
+and environments. The orchestration of the environments and tests is left to external
+tooling.
+
+* `PodmanTestSystem`: System test *struct* as a composite of `PodmanTest`. It will not add any
+options to the command by default. When you run system test, you can set GLOBALOPTIONS,
+PODMAN_SUBCMD_OPTIONS or PODMAN_BINARY in ENV to run the test suite for different test matrices.
+
+## Run system test
+You can run the test with following command:
+
+```
+make localsystem
+```
diff --git a/test/e2e/attach_test.go b/test/e2e/attach_test.go
index 245ccf649..6bc576461 100644
--- a/test/e2e/attach_test.go
+++ b/test/e2e/attach_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman attach", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman attach", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 928a76324..1e4f1eeac 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -5,6 +5,7 @@ import (
"os"
"github.com/containers/libpod/pkg/criu"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman checkpoint", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman checkpoint", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
if !criu.CheckForCriu() {
Skip("CRIU is missing or too old.")
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index c0e050da4..4ee5061f0 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman commit", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman commit", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index c36a8e31f..befe7b06d 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman create", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman create", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go
index a83bb14da..2c0060dd5 100644
--- a/test/e2e/diff_test.go
+++ b/test/e2e/diff_test.go
@@ -5,6 +5,7 @@ import (
"os"
"sort"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman diff", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman diff", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 250e08704..fec80717f 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman exec", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman exec", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/export_test.go b/test/e2e/export_test.go
index c11fd777b..42ea45041 100644
--- a/test/e2e/export_test.go
+++ b/test/e2e/export_test.go
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman export", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman export", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/history_test.go b/test/e2e/history_test.go
index d4b5ad5c0..9bec9ad13 100644
--- a/test/e2e/history_test.go
+++ b/test/e2e/history_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman history", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman history", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index a8854d08d..a927088ca 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -5,6 +5,7 @@ import (
"os"
"sort"
+ . "github.com/containers/libpod/test/utils"
"github.com/docker/go-units"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -14,7 +15,7 @@ var _ = Describe("Podman images", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -22,7 +23,7 @@ var _ = Describe("Podman images", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/import_test.go b/test/e2e/import_test.go
index 80773cf8b..9ed4593c6 100644
--- a/test/e2e/import_test.go
+++ b/test/e2e/import_test.go
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman import", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman import", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go
index dd8645223..e972c86c8 100644
--- a/test/e2e/info_test.go
+++ b/test/e2e/info_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman Info", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman Info", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
})
AfterEach(func() {
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index bff56189e..87c4db935 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -5,6 +5,7 @@ import (
"os"
"strings"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman inspect", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman inspect", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go
index fdf42f2b6..913a843cb 100644
--- a/test/e2e/kill_test.go
+++ b/test/e2e/kill_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman kill", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman kill", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index ec274cc34..52507c083 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -1,22 +1,18 @@
package integration
import (
- "bufio"
- "context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
- "runtime"
"strings"
"testing"
- "time"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/inspect"
- "github.com/containers/storage/pkg/parsers/kernel"
+ . "github.com/containers/libpod/test/utils"
"github.com/containers/storage/pkg/reexec"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -35,14 +31,9 @@ var (
defaultWaitTimeout = 90
)
-// PodmanSession wrapps the gexec.session so we can extend it
-type PodmanSession struct {
- *gexec.Session
-}
-
-// PodmanTest struct for command line options
-type PodmanTest struct {
- PodmanBinary string
+// PodmanTestIntegration struct for command line options
+type PodmanTestIntegration struct {
+ PodmanTest
ConmonBinary string
CrioRoot string
CNIConfigDir string
@@ -50,17 +41,13 @@ type PodmanTest struct {
RunRoot string
StorageOptions string
SignaturePolicyPath string
- ArtifactPath string
- TempDir string
CgroupManager string
Host HostOS
}
-// HostOS is a simple struct for the test os
-type HostOS struct {
- Distribution string
- Version string
- Arch string
+// PodmanSessionIntegration sturct for command line session
+type PodmanSessionIntegration struct {
+ *PodmanSession
}
// TestLibpod ginkgo master function
@@ -80,7 +67,7 @@ var _ = BeforeSuite(func() {
//Cache images
cwd, _ := os.Getwd()
INTEGRATION_ROOT = filepath.Join(cwd, "../../")
- podman := PodmanCreate("/tmp")
+ podman := PodmanTestCreate("/tmp")
podman.ArtifactPath = ARTIFACT_DIR
if _, err := os.Stat(ARTIFACT_DIR); os.IsNotExist(err) {
if err = os.Mkdir(ARTIFACT_DIR, 0777); err != nil {
@@ -110,13 +97,8 @@ var _ = BeforeSuite(func() {
}
})
-// CreateTempDirin
-func CreateTempDirInTempDir() (string, error) {
- return ioutil.TempDir("", "podman_test")
-}
-
-// PodmanCreate creates a PodmanTest instance for the tests
-func PodmanCreate(tempDir string) PodmanTest {
+// PodmanTestCreate creates a PodmanTestIntegration instance for the tests
+func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
host := GetHostDistributionInfo()
cwd, _ := os.Getwd()
@@ -157,8 +139,12 @@ func PodmanCreate(tempDir string) PodmanTest {
CNIConfigDir := "/etc/cni/net.d"
- p := PodmanTest{
- PodmanBinary: podmanBinary,
+ p := &PodmanTestIntegration{
+ PodmanTest: PodmanTest{
+ PodmanBinary: podmanBinary,
+ ArtifactPath: ARTIFACT_DIR,
+ TempDir: tempDir,
+ },
ConmonBinary: conmonBinary,
CrioRoot: filepath.Join(tempDir, "crio"),
CNIConfigDir: CNIConfigDir,
@@ -166,73 +152,50 @@ func PodmanCreate(tempDir string) PodmanTest {
RunRoot: filepath.Join(tempDir, "crio-run"),
StorageOptions: storageOptions,
SignaturePolicyPath: filepath.Join(INTEGRATION_ROOT, "test/policy.json"),
- ArtifactPath: ARTIFACT_DIR,
- TempDir: tempDir,
CgroupManager: cgroupManager,
Host: host,
}
// Setup registries.conf ENV variable
p.setDefaultRegistriesConfigEnv()
+ // Rewrite the PodmanAsUser function
+ p.PodmanMakeOptions = p.makeOptions
return p
}
//MakeOptions assembles all the podman main options
-func (p *PodmanTest) MakeOptions() []string {
- return strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s",
+func (p *PodmanTestIntegration) makeOptions(args []string) []string {
+ podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s",
p.CrioRoot, p.RunRoot, p.RunCBinary, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ")
-}
-
-// Podman is the exec call to podman on the filesystem, uid and gid the credentials to use
-func (p *PodmanTest) PodmanAsUser(args []string, uid, gid uint32, env []string) *PodmanSession {
- podmanOptions := p.MakeOptions()
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
podmanOptions = append(podmanOptions, args...)
- if env == nil {
- fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
- } else {
- fmt.Printf("Running: (env: %v) %s %s\n", env, p.PodmanBinary, strings.Join(podmanOptions, " "))
- }
- var command *exec.Cmd
-
- if uid != 0 || gid != 0 {
- nsEnterOpts := append([]string{"--userspec", fmt.Sprintf("%d:%d", uid, gid), "/", p.PodmanBinary}, podmanOptions...)
- command = exec.Command("chroot", nsEnterOpts...)
- } else {
- command = exec.Command(p.PodmanBinary, podmanOptions...)
- }
- if env != nil {
- command.Env = env
- }
-
- session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
- if err != nil {
- Fail(fmt.Sprintf("unable to run podman command: %s\n%v", strings.Join(podmanOptions, " "), err))
- }
- return &PodmanSession{session}
+ return podmanOptions
}
// Podman is the exec call to podman on the filesystem
-func (p *PodmanTest) Podman(args []string) *PodmanSession {
- return p.PodmanAsUser(args, 0, 0, nil)
+func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
+ podmanSession := p.PodmanBase(args)
+ return &PodmanSessionIntegration{podmanSession}
}
-//WaitForContainer waits on a started container
-func WaitForContainer(p *PodmanTest) bool {
- for i := 0; i < 10; i++ {
- if p.NumberOfRunningContainers() == 1 {
- return true
- }
- time.Sleep(1 * time.Second)
+// PodmanPID execs podman and returns its PID
+func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) {
+ podmanOptions := p.MakeOptions(args)
+ fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
+ command := exec.Command(p.PodmanBinary, podmanOptions...)
+ session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
+ if err != nil {
+ Fail(fmt.Sprintf("unable to run podman command: %s", strings.Join(podmanOptions, " ")))
}
- return false
+ podmanSession := &PodmanSession{session}
+ return &PodmanSessionIntegration{podmanSession}, command.Process.Pid
}
// Cleanup cleans up the temporary store
-func (p *PodmanTest) Cleanup() {
+func (p *PodmanTestIntegration) Cleanup() {
// Remove all containers
stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"})
stopall.WaitWithDefaultTimeout()
@@ -248,7 +211,7 @@ func (p *PodmanTest) Cleanup() {
}
// CleanupPod cleans up the temporary store
-func (p *PodmanTest) CleanupPod() {
+func (p *PodmanTestIntegration) CleanupPod() {
// Remove all containers
session := p.Podman([]string{"pod", "rm", "-fa"})
session.Wait(90)
@@ -258,103 +221,26 @@ func (p *PodmanTest) CleanupPod() {
}
}
-// GrepString takes session output and behaves like grep. it returns a bool
-// if successful and an array of strings on positive matches
-func (s *PodmanSession) GrepString(term string) (bool, []string) {
- var (
- greps []string
- matches bool
- )
-
- for _, line := range strings.Split(s.OutputToString(), "\n") {
- if strings.Contains(line, term) {
- matches = true
- greps = append(greps, line)
- }
- }
- return matches, greps
-}
-
-// Pull Images pulls multiple images
-func (p *PodmanTest) PullImages(images []string) error {
+// PullImages pulls multiple images
+func (p *PodmanTestIntegration) PullImages(images []string) error {
for _, i := range images {
p.PullImage(i)
}
return nil
}
-// Pull Image a single image
+// PullImage pulls a single image
// TODO should the timeout be configurable?
-func (p *PodmanTest) PullImage(image string) error {
+func (p *PodmanTestIntegration) PullImage(image string) error {
session := p.Podman([]string{"pull", image})
session.Wait(60)
Expect(session.ExitCode()).To(Equal(0))
return nil
}
-// OutputToString formats session output to string
-func (s *PodmanSession) OutputToString() string {
- fields := strings.Fields(fmt.Sprintf("%s", s.Out.Contents()))
- return strings.Join(fields, " ")
-}
-
-// OutputToStringArray returns the output as a []string
-// where each array item is a line split by newline
-func (s *PodmanSession) OutputToStringArray() []string {
- var results []string
- output := fmt.Sprintf("%s", s.Out.Contents())
- for _, line := range strings.Split(output, "\n") {
- if line != "" {
- results = append(results, line)
- }
- }
- return results
-}
-
-// ErrorGrepString takes session stderr output and behaves like grep. it returns a bool
-// if successful and an array of strings on positive matches
-func (s *PodmanSession) ErrorGrepString(term string) (bool, []string) {
- var (
- greps []string
- matches bool
- )
-
- for _, line := range strings.Split(s.ErrorToString(), "\n") {
- if strings.Contains(line, term) {
- matches = true
- greps = append(greps, line)
- }
- }
- return matches, greps
-}
-
-// ErrorToString formats session stderr to string
-func (s *PodmanSession) ErrorToString() string {
- fields := strings.Fields(fmt.Sprintf("%s", s.Err.Contents()))
- return strings.Join(fields, " ")
-}
-
-// ErrorToStringArray returns the stderr output as a []string
-// where each array item is a line split by newline
-func (s *PodmanSession) ErrorToStringArray() []string {
- output := fmt.Sprintf("%s", s.Err.Contents())
- return strings.Split(output, "\n")
-}
-
-// IsJSONOutputValid attempts to unmarshal the session buffer
-// and if successful, returns true, else false
-func (s *PodmanSession) IsJSONOutputValid() bool {
- var i interface{}
- if err := json.Unmarshal(s.Out.Contents(), &i); err != nil {
- fmt.Println(err)
- return false
- }
- return true
-}
-
// InspectContainerToJSON takes the session output of an inspect
// container and returns json
-func (s *PodmanSession) InspectContainerToJSON() []inspect.ContainerData {
+func (s *PodmanSessionIntegration) InspectContainerToJSON() []inspect.ContainerData {
var i []inspect.ContainerData
err := json.Unmarshal(s.Out.Contents(), &i)
Expect(err).To(BeNil())
@@ -362,7 +248,7 @@ func (s *PodmanSession) InspectContainerToJSON() []inspect.ContainerData {
}
// InspectPodToJSON takes the sessions output from a pod inspect and returns json
-func (s *PodmanSession) InspectPodToJSON() libpod.PodInspect {
+func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect {
var i libpod.PodInspect
err := json.Unmarshal(s.Out.Contents(), &i)
Expect(err).To(BeNil())
@@ -371,30 +257,15 @@ func (s *PodmanSession) InspectPodToJSON() libpod.PodInspect {
// InspectImageJSON takes the session output of an inspect
// image and returns json
-func (s *PodmanSession) InspectImageJSON() []inspect.ImageData {
+func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData {
var i []inspect.ImageData
err := json.Unmarshal(s.Out.Contents(), &i)
Expect(err).To(BeNil())
return i
}
-func (s *PodmanSession) WaitWithDefaultTimeout() {
- s.Wait(defaultWaitTimeout)
- fmt.Println("output:", s.OutputToString())
-}
-
-// SystemExec is used to exec a system command to check its exit code or output
-func (p *PodmanTest) SystemExec(command string, args []string) *PodmanSession {
- c := exec.Command(command, args...)
- session, err := gexec.Start(c, GinkgoWriter, GinkgoWriter)
- if err != nil {
- Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
- }
- return &PodmanSession{session}
-}
-
// CreateArtifact creates a cached image in the artifact dir
-func (p *PodmanTest) CreateArtifact(image string) error {
+func (p *PodmanTestIntegration) CreateArtifact(image string) error {
if os.Getenv("NO_TEST_CACHE") != "" {
return nil
}
@@ -415,7 +286,7 @@ func (p *PodmanTest) CreateArtifact(image string) error {
}
// RestoreArtifact puts the cached image into our test store
-func (p *PodmanTest) RestoreArtifact(image string) error {
+func (p *PodmanTestIntegration) RestoreArtifact(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))
@@ -425,7 +296,7 @@ func (p *PodmanTest) RestoreArtifact(image string) error {
}
// RestoreAllArtifacts unpacks all cached images
-func (p *PodmanTest) RestoreAllArtifacts() error {
+func (p *PodmanTestIntegration) RestoreAllArtifacts() error {
if os.Getenv("NO_TEST_CACHE") != "" {
return nil
}
@@ -439,7 +310,7 @@ func (p *PodmanTest) RestoreAllArtifacts() error {
// CreatePod creates a pod with no infra container
// it optionally takes a pod name
-func (p *PodmanTest) CreatePod(name string) (*PodmanSession, int, string) {
+func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) {
var podmanArgs = []string{"pod", "create", "--infra=false", "--share", ""}
if name != "" {
podmanArgs = append(podmanArgs, "--name", name)
@@ -451,7 +322,7 @@ func (p *PodmanTest) CreatePod(name string) (*PodmanSession, int, string) {
//RunTopContainer runs a simple container in the background that
// runs top. If the name passed != "", it will have a name
-func (p *PodmanTest) RunTopContainer(name string) *PodmanSession {
+func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionIntegration {
var podmanArgs = []string{"run"}
if name != "" {
podmanArgs = append(podmanArgs, "--name", name)
@@ -460,7 +331,7 @@ func (p *PodmanTest) RunTopContainer(name string) *PodmanSession {
return p.Podman(podmanArgs)
}
-func (p *PodmanTest) RunTopContainerInPod(name, pod string) *PodmanSession {
+func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration {
var podmanArgs = []string{"run", "--pod", pod}
if name != "" {
podmanArgs = append(podmanArgs, "--name", name)
@@ -471,7 +342,7 @@ func (p *PodmanTest) RunTopContainerInPod(name, pod string) *PodmanSession {
//RunLsContainer runs a simple container in the background that
// simply runs ls. If the name passed != "", it will have a name
-func (p *PodmanTest) RunLsContainer(name string) (*PodmanSession, int, string) {
+func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionIntegration, int, string) {
var podmanArgs = []string{"run"}
if name != "" {
podmanArgs = append(podmanArgs, "--name", name)
@@ -482,7 +353,7 @@ func (p *PodmanTest) RunLsContainer(name string) (*PodmanSession, int, string) {
return session, session.ExitCode(), session.OutputToString()
}
-func (p *PodmanTest) RunLsContainerInPod(name, pod string) (*PodmanSession, int, string) {
+func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) {
var podmanArgs = []string{"run", "--pod", pod}
if name != "" {
podmanArgs = append(podmanArgs, "--name", name)
@@ -493,147 +364,9 @@ func (p *PodmanTest) RunLsContainerInPod(name, pod string) (*PodmanSession, int,
return session, session.ExitCode(), session.OutputToString()
}
-//NumberOfContainersRunning returns an int of how many
-// containers are currently running.
-func (p *PodmanTest) NumberOfContainersRunning() int {
- var containers []string
- ps := p.Podman([]string{"ps", "-q"})
- ps.WaitWithDefaultTimeout()
- Expect(ps.ExitCode()).To(Equal(0))
- for _, i := range ps.OutputToStringArray() {
- if i != "" {
- containers = append(containers, i)
- }
- }
- return len(containers)
-}
-
-// NumberOfContainers returns an int of how many
-// containers are currently defined.
-func (p *PodmanTest) NumberOfContainers() int {
- var containers []string
- ps := p.Podman([]string{"ps", "-aq"})
- ps.WaitWithDefaultTimeout()
- Expect(ps.ExitCode()).To(Equal(0))
- for _, i := range ps.OutputToStringArray() {
- if i != "" {
- containers = append(containers, i)
- }
- }
- return len(containers)
-}
-
-// NumberOfPods returns an int of how many
-// pods are currently defined.
-func (p *PodmanTest) NumberOfPods() int {
- var pods []string
- ps := p.Podman([]string{"pod", "ps", "-q"})
- ps.WaitWithDefaultTimeout()
- Expect(ps.ExitCode()).To(Equal(0))
- for _, i := range ps.OutputToStringArray() {
- if i != "" {
- pods = append(pods, i)
- }
- }
- return len(pods)
-}
-
-// NumberOfRunningContainers returns an int of how many containers are currently
-// running
-func (p *PodmanTest) NumberOfRunningContainers() int {
- var containers []string
- ps := p.Podman([]string{"ps", "-q"})
- ps.WaitWithDefaultTimeout()
- Expect(ps.ExitCode()).To(Equal(0))
- for _, i := range ps.OutputToStringArray() {
- if i != "" {
- containers = append(containers, i)
- }
- }
- return len(containers)
-}
-
-// StringInSlice determines if a string is in a string slice, returns bool
-func StringInSlice(s string, sl []string) bool {
- for _, i := range sl {
- if i == s {
- return true
- }
- }
- return false
-}
-
-//LineInOutputStartsWith returns true if a line in a
-// session output starts with the supplied string
-func (s *PodmanSession) LineInOuputStartsWith(term string) bool {
- for _, i := range s.OutputToStringArray() {
- if strings.HasPrefix(i, term) {
- return true
- }
- }
- return false
-}
-
-//LineInOutputContains returns true if a line in a
-// session output starts with the supplied string
-func (s *PodmanSession) LineInOutputContains(term string) bool {
- for _, i := range s.OutputToStringArray() {
- if strings.Contains(i, term) {
- return true
- }
- }
- return false
-}
-
-//tagOutPutToMap parses each string in imagesOutput and returns
-// a map of repo:tag pairs. Notice, the first array item will
-// be skipped as it's considered to be the header.
-func tagOutputToMap(imagesOutput []string) map[string]string {
- m := make(map[string]string)
- // iterate over output but skip the header
- for _, i := range imagesOutput[1:] {
- tmp := []string{}
- for _, x := range strings.Split(i, " ") {
- if x != "" {
- tmp = append(tmp, x)
- }
- }
- // podman-images(1) return a list like output
- // in the format of "Repository Tag [...]"
- if len(tmp) < 2 {
- continue
- }
- m[tmp[0]] = tmp[1]
- }
- return m
-}
-
-//LineInOutputContainsTag returns true if a line in the
-// session's output contains the repo-tag pair as returned
-// by podman-images(1).
-func (s *PodmanSession) LineInOutputContainsTag(repo, tag string) bool {
- tagMap := tagOutputToMap(s.OutputToStringArray())
- for r, t := range tagMap {
- if repo == r && tag == t {
- return true
- }
- }
- return false
-}
-
-//GetContainerStatus returns the containers state.
-// This function assumes only one container is active.
-func (p *PodmanTest) GetContainerStatus() string {
- var podmanArgs = []string{"ps"}
- podmanArgs = append(podmanArgs, "--all", "--format={{.Status}}")
- session := p.Podman(podmanArgs)
- session.WaitWithDefaultTimeout()
- return session.OutputToString()
-}
-
// BuildImage uses podman build and buildah to build an image
// called imageName based on a string dockerfile
-func (p *PodmanTest) BuildImage(dockerfile, imageName string, layers string) {
+func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) {
dockerfilePath := filepath.Join(p.TempDir, "Dockerfile")
err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755)
Expect(err).To(BeNil())
@@ -642,34 +375,12 @@ func (p *PodmanTest) BuildImage(dockerfile, imageName string, layers string) {
Expect(session.ExitCode()).To(Equal(0))
}
-//GetHostDistributionInfo returns a struct with its distribution name and version
-func GetHostDistributionInfo() HostOS {
- f, err := os.Open("/etc/os-release")
- defer f.Close()
- if err != nil {
- return HostOS{}
- }
-
- l := bufio.NewScanner(f)
- host := HostOS{}
- host.Arch = runtime.GOARCH
- for l.Scan() {
- if strings.HasPrefix(l.Text(), "ID=") {
- host.Distribution = strings.Replace(strings.TrimSpace(strings.Join(strings.Split(l.Text(), "=")[1:], "")), "\"", "", -1)
- }
- if strings.HasPrefix(l.Text(), "VERSION_ID=") {
- host.Version = strings.Replace(strings.TrimSpace(strings.Join(strings.Split(l.Text(), "=")[1:], "")), "\"", "", -1)
- }
- }
- return host
-}
-
-func (p *PodmanTest) setDefaultRegistriesConfigEnv() {
+func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() {
defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf")
os.Setenv("REGISTRIES_CONFIG_PATH", defaultFile)
}
-func (p *PodmanTest) setRegistriesConfigEnv(b []byte) {
+func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) {
outfile := filepath.Join(p.TempDir, "registries.conf")
os.Setenv("REGISTRIES_CONFIG_PATH", outfile)
ioutil.WriteFile(outfile, b, 0644)
@@ -678,81 +389,3 @@ func (p *PodmanTest) setRegistriesConfigEnv(b []byte) {
func resetRegistriesConfigEnv() {
os.Setenv("REGISTRIES_CONFIG_PATH", "")
}
-
-// IsKernelNewThan compares the current kernel version to one provided. If
-// the kernel is equal to or greater, returns true
-func IsKernelNewThan(version string) (bool, error) {
- inputVersion, err := kernel.ParseRelease(version)
- if err != nil {
- return false, err
- }
- kv, err := kernel.GetKernelVersion()
- if err == nil {
- return false, err
- }
- // CompareKernelVersion compares two kernel.VersionInfo structs.
- // Returns -1 if a < b, 0 if a == b, 1 it a > b
- result := kernel.CompareKernelVersion(*kv, *inputVersion)
- if result >= 0 {
- return true, nil
- }
- return false, nil
-
-}
-
-//Wait process or service inside container start, and ready to be used.
-func WaitContainerReady(p *PodmanTest, id string, expStr string, timeout int, step int) bool {
- startTime := time.Now()
- s := p.Podman([]string{"logs", id})
- s.WaitWithDefaultTimeout()
- fmt.Println(startTime)
- for {
- if time.Since(startTime) >= time.Duration(timeout)*time.Second {
- return false
- }
- if strings.Contains(s.OutputToString(), expStr) {
- return true
- }
- time.Sleep(time.Duration(step) * time.Second)
- s = p.Podman([]string{"logs", id})
- s.WaitWithDefaultTimeout()
- }
-}
-
-//IsCommandAvaible check if command exist
-func IsCommandAvailable(command string) bool {
- check := exec.Command("bash", "-c", strings.Join([]string{"command -v", command}, " "))
- err := check.Run()
- if err != nil {
- return false
- }
- return true
-}
-
-// WriteJsonFile write json format data to a json file
-func WriteJsonFile(data []byte, filePath string) error {
- var jsonData map[string]interface{}
- json.Unmarshal(data, &jsonData)
- formatJson, _ := json.MarshalIndent(jsonData, "", " ")
- return ioutil.WriteFile(filePath, formatJson, 0644)
-}
-
-func getTestContext() context.Context {
- return context.Background()
-}
-
-func containerized() bool {
- container := os.Getenv("container")
- if container != "" {
- return true
- }
- b, err := ioutil.ReadFile("/proc/1/cgroup")
- if err != nil {
- // shrug, if we cannot read that file, return false
- return false
- }
- if strings.Index(string(b), "docker") > -1 {
- return true
- }
- return false
-}
diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go
index 21e8a4859..4d7007191 100644
--- a/test/e2e/load_test.go
+++ b/test/e2e/load_test.go
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman load", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman load", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -55,7 +56,7 @@ var _ = Describe("Podman load", func() {
save.WaitWithDefaultTimeout()
Expect(save.ExitCode()).To(Equal(0))
- compress := podmanTest.SystemExec("gzip", []string{outfile})
+ compress := SystemExec("gzip", []string{outfile})
compress.WaitWithDefaultTimeout()
outfile = outfile + ".gz"
@@ -253,7 +254,7 @@ var _ = Describe("Podman load", func() {
save := podmanTest.Podman([]string{"save", "-o", outfile, BB})
save.WaitWithDefaultTimeout()
Expect(save.ExitCode()).To(Equal(0))
- session := podmanTest.SystemExec("xz", []string{outfile})
+ session := SystemExec("xz", []string{outfile})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 6888863ca..236ddb221 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman logs", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman logs", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/mount_test.go b/test/e2e/mount_test.go
index fbb0a3eb7..a93a0aa4a 100644
--- a/test/e2e/mount_test.go
+++ b/test/e2e/mount_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman mount", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman mount", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/namespace_test.go b/test/e2e/namespace_test.go
index 017edd231..ebce09f54 100644
--- a/test/e2e/namespace_test.go
+++ b/test/e2e/namespace_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman namespaces", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman namespaces", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index e80915670..e109bc077 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pause", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
pausedState := "Paused"
@@ -23,7 +24,7 @@ var _ = Describe("Podman pause", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 0ce1e22a8..51522ffd1 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod create", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod create", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_infra_container_test.go b/test/e2e/pod_infra_container_test.go
index f1e2375ce..8c7c09c97 100644
--- a/test/e2e/pod_infra_container_test.go
+++ b/test/e2e/pod_infra_container_test.go
@@ -5,6 +5,7 @@ import (
"os"
"strconv"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman pod create", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman pod create", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
podmanTest.RestoreArtifact(infra)
})
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 667e59f38..51e95f788 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod inspect", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod inspect", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go
index b29fe1e17..d9cec2cad 100644
--- a/test/e2e/pod_kill_test.go
+++ b/test/e2e/pod_kill_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod kill", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod kill", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go
index 384cbfcb7..8f766d3db 100644
--- a/test/e2e/pod_pause_test.go
+++ b/test/e2e/pod_pause_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod pause", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
pausedState := "Paused"
@@ -22,7 +23,7 @@ var _ = Describe("Podman pod pause", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_pod_namespaces.go b/test/e2e/pod_pod_namespaces.go
index 3e84005c3..b1d5abb1c 100644
--- a/test/e2e/pod_pod_namespaces.go
+++ b/test/e2e/pod_pod_namespaces.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod create", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod create", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
podmanTest.RestoreArtifact(infra)
})
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index b48cb9578..9e816bcfa 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -5,6 +5,7 @@ import (
"os"
"sort"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman ps", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman ps", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_restart_test.go b/test/e2e/pod_restart_test.go
index e486f8791..d0964e8de 100644
--- a/test/e2e/pod_restart_test.go
+++ b/test/e2e/pod_restart_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod restart", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod restart", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index 09002e954..48767b33f 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod rm", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod rm", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go
index 9d2ea9b26..346346425 100644
--- a/test/e2e/pod_start_test.go
+++ b/test/e2e/pod_start_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod start", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod start", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_stats_test.go b/test/e2e/pod_stats_test.go
index f9c8e06c4..d7b9a8f48 100644
--- a/test/e2e/pod_stats_test.go
+++ b/test/e2e/pod_stats_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod stats", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod stats", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_stop_test.go b/test/e2e/pod_stop_test.go
index 32f8559ad..6c5319a3d 100644
--- a/test/e2e/pod_stop_test.go
+++ b/test/e2e/pod_stop_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman pod stop", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman pod stop", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pod_top_test.go b/test/e2e/pod_top_test.go
index f72456307..3dc80ddfb 100644
--- a/test/e2e/pod_top_test.go
+++ b/test/e2e/pod_top_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman top", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman top", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/port_test.go b/test/e2e/port_test.go
index ed15b54ac..09f3ab53a 100644
--- a/test/e2e/port_test.go
+++ b/test/e2e/port_test.go
@@ -5,6 +5,7 @@ import (
"os"
"strings"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman port", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman port", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index a873b57bb..9caa6e7f1 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -6,6 +6,7 @@ import (
"regexp"
"sort"
+ . "github.com/containers/libpod/test/utils"
"github.com/docker/go-units"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -15,7 +16,7 @@ var _ = Describe("Podman ps", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -23,7 +24,7 @@ var _ = Describe("Podman ps", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index 606160198..ad8742984 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -4,6 +4,7 @@ import (
"os"
"fmt"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"strings"
@@ -13,7 +14,7 @@ var _ = Describe("Podman pull", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman pull", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -101,7 +102,7 @@ var _ = Describe("Podman pull", func() {
session = podmanTest.Podman([]string{"rmi", "alpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"/tmp/alp.tar"})
+ clean := SystemExec("rm", []string{"/tmp/alp.tar"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
@@ -119,12 +120,12 @@ var _ = Describe("Podman pull", func() {
session = podmanTest.Podman([]string{"rmi", "alpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"/tmp/oci-alp.tar"})
+ clean := SystemExec("rm", []string{"/tmp/oci-alp.tar"})
clean.WaitWithDefaultTimeout()
})
It("podman pull from local directory", func() {
- setup := podmanTest.SystemExec("mkdir", []string{"-p", "/tmp/podmantestdir"})
+ setup := SystemExec("mkdir", []string{"-p", "/tmp/podmantestdir"})
setup.WaitWithDefaultTimeout()
session := podmanTest.Podman([]string{"push", "alpine", "dir:/tmp/podmantestdir"})
session.WaitWithDefaultTimeout()
@@ -139,7 +140,7 @@ var _ = Describe("Podman pull", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"-fr", "/tmp/podmantestdir"})
+ clean := SystemExec("rm", []string{"-fr", "/tmp/podmantestdir"})
clean.WaitWithDefaultTimeout()
})
diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go
index 5e3d3745a..3447cd57e 100644
--- a/test/e2e/push_test.go
+++ b/test/e2e/push_test.go
@@ -6,6 +6,7 @@ import (
"path/filepath"
"strings"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -14,7 +15,7 @@ var _ = Describe("Podman push", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -22,7 +23,7 @@ var _ = Describe("Podman push", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -52,7 +53,7 @@ var _ = Describe("Podman push", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"-fr", "/tmp/busybox"})
+ clean := SystemExec("rm", []string{"-fr", "/tmp/busybox"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
@@ -66,7 +67,7 @@ var _ = Describe("Podman push", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
@@ -82,20 +83,20 @@ var _ = Describe("Podman push", func() {
authPath := filepath.Join(podmanTest.TempDir, "auth")
os.Mkdir(authPath, os.ModePerm)
os.MkdirAll("/etc/containers/certs.d/localhost:5000", os.ModePerm)
- debug := podmanTest.SystemExec("ls", []string{"-l", podmanTest.TempDir})
+ debug := SystemExec("ls", []string{"-l", podmanTest.TempDir})
debug.WaitWithDefaultTimeout()
cwd, _ := os.Getwd()
certPath := filepath.Join(cwd, "../", "certs")
if IsCommandAvailable("getenforce") {
- ge := podmanTest.SystemExec("getenforce", []string{})
+ ge := SystemExec("getenforce", []string{})
ge.WaitWithDefaultTimeout()
if ge.OutputToString() == "Enforcing" {
- se := podmanTest.SystemExec("setenforce", []string{"0"})
+ se := SystemExec("setenforce", []string{"0"})
se.WaitWithDefaultTimeout()
- defer podmanTest.SystemExec("setenforce", []string{"1"})
+ defer SystemExec("setenforce", []string{"1"})
}
}
podmanTest.RestoreArtifact(registry)
@@ -108,7 +109,7 @@ var _ = Describe("Podman push", func() {
f.WriteString(session.OutputToString())
f.Sync()
- debug = podmanTest.SystemExec("cat", []string{filepath.Join(authPath, "htpasswd")})
+ debug = SystemExec("cat", []string{filepath.Join(authPath, "htpasswd")})
debug.WaitWithDefaultTimeout()
session = podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry", "-v",
@@ -119,7 +120,7 @@ var _ = Describe("Podman push", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
@@ -134,7 +135,7 @@ var _ = Describe("Podman push", func() {
push.WaitWithDefaultTimeout()
Expect(push.ExitCode()).To(Equal(0))
- setup := podmanTest.SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), "/etc/containers/certs.d/localhost:5000/ca.crt"})
+ setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), "/etc/containers/certs.d/localhost:5000/ca.crt"})
setup.WaitWithDefaultTimeout()
defer os.RemoveAll("/etc/containers/certs.d/localhost:5000")
@@ -155,20 +156,20 @@ var _ = Describe("Podman push", func() {
session := podmanTest.Podman([]string{"push", ALPINE, "docker-archive:/tmp/alp:latest"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"/tmp/alp"})
+ clean := SystemExec("rm", []string{"/tmp/alp"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
It("podman push to docker daemon", func() {
- setup := podmanTest.SystemExec("bash", []string{"-c", "systemctl status docker 2>&1"})
+ setup := SystemExec("bash", []string{"-c", "systemctl status docker 2>&1"})
setup.WaitWithDefaultTimeout()
if setup.LineInOutputContains("Active: inactive") {
- setup = podmanTest.SystemExec("systemctl", []string{"start", "docker"})
+ setup = SystemExec("systemctl", []string{"start", "docker"})
setup.WaitWithDefaultTimeout()
- defer podmanTest.SystemExec("systemctl", []string{"stop", "docker"})
+ defer SystemExec("systemctl", []string{"stop", "docker"})
} else if setup.ExitCode() != 0 {
Skip("Docker is not available")
}
@@ -177,12 +178,12 @@ var _ = Describe("Podman push", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- check := podmanTest.SystemExec("docker", []string{"images", "--format", "{{.Repository}}:{{.Tag}}"})
+ check := SystemExec("docker", []string{"images", "--format", "{{.Repository}}:{{.Tag}}"})
check.WaitWithDefaultTimeout()
Expect(check.ExitCode()).To(Equal(0))
Expect(check.OutputToString()).To(ContainSubstring("alpine:podmantest"))
- clean := podmanTest.SystemExec("docker", []string{"rmi", "alpine:podmantest"})
+ clean := SystemExec("docker", []string{"rmi", "alpine:podmantest"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
@@ -191,7 +192,7 @@ var _ = Describe("Podman push", func() {
session := podmanTest.Podman([]string{"push", ALPINE, "oci-archive:/tmp/alp.tar:latest"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"/tmp/alp.tar"})
+ clean := SystemExec("rm", []string{"/tmp/alp.tar"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
@@ -204,14 +205,14 @@ var _ = Describe("Podman push", func() {
ostreePath := filepath.Join(podmanTest.TempDir, "ostree/repo")
os.MkdirAll(ostreePath, os.ModePerm)
- setup := podmanTest.SystemExec("ostree", []string{strings.Join([]string{"--repo=", ostreePath}, ""), "init"})
+ setup := SystemExec("ostree", []string{strings.Join([]string{"--repo=", ostreePath}, ""), "init"})
setup.WaitWithDefaultTimeout()
session := podmanTest.Podman([]string{"push", ALPINE, strings.Join([]string{"ostree:alp@", ostreePath}, "")})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"-rf", ostreePath})
+ clean := SystemExec("rm", []string{"-rf", ostreePath})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
@@ -220,7 +221,7 @@ var _ = Describe("Podman push", func() {
session := podmanTest.Podman([]string{"push", ALPINE, "docker-archive:/tmp/alp"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"/tmp/alp"})
+ clean := SystemExec("rm", []string{"/tmp/alp"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
@@ -229,7 +230,7 @@ var _ = Describe("Podman push", func() {
session := podmanTest.Podman([]string{"push", ALPINE, "oci-archive:/tmp/alp-oci"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- clean := podmanTest.SystemExec("rm", []string{"/tmp/alp-oci"})
+ clean := SystemExec("rm", []string{"/tmp/alp-oci"})
clean.WaitWithDefaultTimeout()
Expect(clean.ExitCode()).To(Equal(0))
})
diff --git a/test/e2e/refresh_test.go b/test/e2e/refresh_test.go
index c4a65aa47..bf8fff105 100644
--- a/test/e2e/refresh_test.go
+++ b/test/e2e/refresh_test.go
@@ -5,6 +5,7 @@ import (
"os"
"time"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman refresh", func() {
var (
tmpdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman refresh", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tmpdir)
+ podmanTest = PodmanTestCreate(tmpdir)
podmanTest.RestoreAllArtifacts()
})
@@ -43,13 +44,13 @@ var _ = Describe("Podman refresh", func() {
createSession.WaitWithDefaultTimeout()
Expect(createSession.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfRunningContainers()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
refreshSession := podmanTest.Podman([]string{"container", "refresh"})
refreshSession.WaitWithDefaultTimeout()
Expect(refreshSession.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfRunningContainers()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
Specify("Refresh with running container restarts container", func() {
@@ -57,7 +58,7 @@ var _ = Describe("Podman refresh", func() {
createSession.WaitWithDefaultTimeout()
Expect(createSession.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfRunningContainers()).To(Equal(1))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
// HACK: ensure container starts before we move on
time.Sleep(1 * time.Second)
@@ -66,6 +67,6 @@ var _ = Describe("Podman refresh", func() {
refreshSession.WaitWithDefaultTimeout()
Expect(refreshSession.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfRunningContainers()).To(Equal(1))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
})
})
diff --git a/test/e2e/restart_test.go b/test/e2e/restart_test.go
index eca2bbcda..30801c272 100644
--- a/test/e2e/restart_test.go
+++ b/test/e2e/restart_test.go
@@ -5,6 +5,7 @@ import (
"os"
"time"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman restart", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman restart", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -74,7 +75,7 @@ var _ = Describe("Podman restart", func() {
It("Podman restart running container", func() {
_ = podmanTest.RunTopContainer("test1")
- ok := WaitForContainer(&podmanTest)
+ ok := WaitForContainer(podmanTest)
Expect(ok).To(BeTrue())
startTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1"})
startTime.WaitWithDefaultTimeout()
diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go
index cbc03a078..c6a2b61ee 100644
--- a/test/e2e/rm_test.go
+++ b/test/e2e/rm_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman rm", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman rm", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index 2a1a0da77..c2eb8b7d7 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman rmi", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman rmi", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go
index 876e10969..995744ae5 100644
--- a/test/e2e/rootless_test.go
+++ b/test/e2e/rootless_test.go
@@ -9,6 +9,7 @@ import (
"runtime"
"syscall"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -30,7 +31,7 @@ var _ = Describe("Podman rootless", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -38,7 +39,7 @@ var _ = Describe("Podman rootless", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.CgroupManager = "cgroupfs"
podmanTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS
podmanTest.RestoreAllArtifacts()
@@ -68,7 +69,7 @@ var _ = Describe("Podman rootless", func() {
return os.Lchown(p, 1000, 1000)
}
- type rootlessCB func(test PodmanTest, xdgRuntimeDir string, home string, mountPath string)
+ type rootlessCB func(test *PodmanTestIntegration, xdgRuntimeDir string, home string, mountPath string)
runInRootlessContext := func(cb rootlessCB) {
// Check if we can create an user namespace
@@ -91,7 +92,7 @@ var _ = Describe("Podman rootless", func() {
tempdir, err := CreateTempDirInTempDir()
Expect(err).To(BeNil())
- rootlessTest := PodmanCreate(tempdir)
+ rootlessTest := PodmanTestCreate(tempdir)
rootlessTest.CgroupManager = "cgroupfs"
rootlessTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS
err = filepath.Walk(tempdir, chownFunc)
@@ -116,7 +117,7 @@ var _ = Describe("Podman rootless", func() {
}
It("podman rootless pod", func() {
- f := func(rootlessTest PodmanTest, xdgRuntimeDir string, home string, mountPath string) {
+ f := func(rootlessTest *PodmanTestIntegration, xdgRuntimeDir string, home string, mountPath string) {
env := os.Environ()
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
env = append(env, fmt.Sprintf("HOME=%s", home))
@@ -157,7 +158,7 @@ var _ = Describe("Podman rootless", func() {
})
runRootlessHelper := func(args []string) {
- f := func(rootlessTest PodmanTest, xdgRuntimeDir string, home string, mountPath string) {
+ f := func(rootlessTest *PodmanTestIntegration, xdgRuntimeDir string, home string, mountPath string) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
env := os.Environ()
diff --git a/test/e2e/run_cgroup_parent_test.go b/test/e2e/run_cgroup_parent_test.go
index f266fafa4..57b3aa6b1 100644
--- a/test/e2e/run_cgroup_parent_test.go
+++ b/test/e2e/run_cgroup_parent_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run with --cgroup-parent", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run with --cgroup-parent", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreArtifact(fedoraMinimal)
})
@@ -32,7 +33,7 @@ var _ = Describe("Podman run with --cgroup-parent", func() {
})
Specify("valid --cgroup-parent using cgroupfs", func() {
- if !containerized() {
+ if !Containerized() {
Skip("Must be containerized to run this test.")
}
cgroup := "/zzz"
@@ -45,7 +46,7 @@ var _ = Describe("Podman run with --cgroup-parent", func() {
Specify("no --cgroup-parent", func() {
cgroup := "/libpod_parent"
- if !containerized() && podmanTest.CgroupManager != "cgroupfs" {
+ if !Containerized() && podmanTest.CgroupManager != "cgroupfs" {
cgroup = "/machine.slice"
}
run := podmanTest.Podman([]string{"run", fedoraMinimal, "cat", "/proc/self/cgroup"})
@@ -56,7 +57,7 @@ var _ = Describe("Podman run with --cgroup-parent", func() {
})
Specify("valid --cgroup-parent using slice", func() {
- if containerized() || podmanTest.CgroupManager == "cgroupfs" {
+ if Containerized() || podmanTest.CgroupManager == "cgroupfs" {
Skip("Requires Systemd cgroup manager support")
}
cgroup := "aaaa.slice"
diff --git a/test/e2e/run_cleanup_test.go b/test/e2e/run_cleanup_test.go
index 02c70734a..5b60efa86 100644
--- a/test/e2e/run_cleanup_test.go
+++ b/test/e2e/run_cleanup_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run exit", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run exit", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -32,14 +33,14 @@ var _ = Describe("Podman run exit", func() {
})
It("podman run -d mount cleanup test", func() {
- mount := podmanTest.SystemExec("mount", nil)
+ mount := SystemExec("mount", nil)
mount.WaitWithDefaultTimeout()
out1 := mount.OutputToString()
result := podmanTest.Podman([]string{"create", "-dt", ALPINE, "echo", "hello"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
- mount = podmanTest.SystemExec("mount", nil)
+ mount = SystemExec("mount", nil)
mount.WaitWithDefaultTimeout()
out2 := mount.OutputToString()
Expect(out1).To(Equal(out2))
diff --git a/test/e2e/run_cpu_test.go b/test/e2e/run_cpu_test.go
index d56dfac64..343fe656c 100644
--- a/test/e2e/run_cpu_test.go
+++ b/test/e2e/run_cpu_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run cpu", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run cpu", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go
index fedd696d1..7f1f7b2d0 100644
--- a/test/e2e/run_device_test.go
+++ b/test/e2e/run_device_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run device", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run device", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_dns_test.go b/test/e2e/run_dns_test.go
index a617035a1..444c568e0 100644
--- a/test/e2e/run_dns_test.go
+++ b/test/e2e/run_dns_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run dns", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run dns", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go
index 5e4ef75e1..227037f92 100644
--- a/test/e2e/run_entrypoint_test.go
+++ b/test/e2e/run_entrypoint_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run entrypoint", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run entrypoint", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreArtifact(ALPINE)
})
diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go
index bb38f7222..788cbd8dd 100644
--- a/test/e2e/run_exit_test.go
+++ b/test/e2e/run_exit_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run exit", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run exit", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go
index d1768138b..91a311e85 100644
--- a/test/e2e/run_memory_test.go
+++ b/test/e2e/run_memory_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run memory", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run memory", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 021825d4b..1b05ac031 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman rmi", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
hostname, _ = os.Hostname()
)
@@ -21,7 +22,7 @@ var _ = Describe("Podman rmi", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -54,7 +55,7 @@ var _ = Describe("Podman rmi", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--expose", "222-223", "-P", ALPINE, "/bin/sh"})
session.Wait(30)
Expect(session.ExitCode()).To(Equal(0))
- results := podmanTest.SystemExec("iptables", []string{"-t", "nat", "-L"})
+ results := SystemExec("iptables", []string{"-t", "nat", "-L"})
results.Wait(30)
Expect(results.ExitCode()).To(Equal(0))
Expect(results.OutputToString()).To(ContainSubstring("222"))
@@ -65,12 +66,12 @@ var _ = Describe("Podman rmi", func() {
session := podmanTest.Podman([]string{"run", "-dt", "-p", "80:8000", ALPINE, "/bin/sh"})
session.Wait(30)
Expect(session.ExitCode()).To(Equal(0))
- results := podmanTest.SystemExec("iptables", []string{"-t", "nat", "-L"})
+ results := SystemExec("iptables", []string{"-t", "nat", "-L"})
results.Wait(30)
Expect(results.ExitCode()).To(Equal(0))
Expect(results.OutputToString()).To(ContainSubstring("8000"))
- ncBusy := podmanTest.SystemExec("nc", []string{"-l", "-p", "80"})
+ ncBusy := SystemExec("nc", []string{"-l", "-p", "80"})
ncBusy.Wait(10)
Expect(ncBusy.ExitCode()).ToNot(Equal(0))
})
diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go
index 88c0b1ad2..e4dcc5adc 100644
--- a/test/e2e/run_ns_test.go
+++ b/test/e2e/run_ns_test.go
@@ -5,6 +5,7 @@ import (
"os"
"strings"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman run ns", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman run ns", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreArtifact(fedoraMinimal)
})
@@ -49,7 +50,7 @@ var _ = Describe("Podman run ns", func() {
})
It("podman run ipcns test", func() {
- setup := podmanTest.SystemExec("ls", []string{"--inode", "-d", "/dev/shm"})
+ setup := SystemExec("ls", []string{"--inode", "-d", "/dev/shm"})
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
hostShm := setup.OutputToString()
@@ -61,7 +62,7 @@ var _ = Describe("Podman run ns", func() {
})
It("podman run ipcns ipcmk host test", func() {
- setup := podmanTest.SystemExec("ipcmk", []string{"-M", "1024"})
+ setup := SystemExec("ipcmk", []string{"-M", "1024"})
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
output := strings.Split(setup.OutputToString(), " ")
@@ -70,7 +71,7 @@ var _ = Describe("Podman run ns", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- setup = podmanTest.SystemExec("ipcrm", []string{"-m", ipc})
+ setup = SystemExec("ipcrm", []string{"-m", ipc})
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
})
diff --git a/test/e2e/run_passwd_test.go b/test/e2e/run_passwd_test.go
index 0bea092bb..891f4fbd8 100644
--- a/test/e2e/run_passwd_test.go
+++ b/test/e2e/run_passwd_test.go
@@ -4,6 +4,7 @@ import (
"os"
"fmt"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run passwd", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run passwd", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index 0a62d8505..770ea3e6b 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -5,6 +5,7 @@ import (
"os"
"strings"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman privileged container tests", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman privileged container tests", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -42,7 +43,7 @@ var _ = Describe("Podman privileged container tests", func() {
})
It("podman privileged CapEff", func() {
- cap := podmanTest.SystemExec("grep", []string{"CapEff", "/proc/self/status"})
+ cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"})
cap.WaitWithDefaultTimeout()
Expect(cap.ExitCode()).To(Equal(0))
@@ -53,7 +54,7 @@ var _ = Describe("Podman privileged container tests", func() {
})
It("podman cap-add CapEff", func() {
- cap := podmanTest.SystemExec("grep", []string{"CapEff", "/proc/self/status"})
+ cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"})
cap.WaitWithDefaultTimeout()
Expect(cap.ExitCode()).To(Equal(0))
@@ -87,13 +88,13 @@ var _ = Describe("Podman privileged container tests", func() {
It("run no-new-privileges test", func() {
// Check if our kernel is new enough
- k, err := IsKernelNewThan("4.14")
+ k, err := IsKernelNewerThan("4.14")
Expect(err).To(BeNil())
if !k {
Skip("Kernel is not new enough to test this feature")
}
- cap := podmanTest.SystemExec("grep", []string{"NoNewPrivs", "/proc/self/status"})
+ cap := SystemExec("grep", []string{"NoNewPrivs", "/proc/self/status"})
cap.WaitWithDefaultTimeout()
if cap.ExitCode() != 0 {
Skip("Can't determine NoNewPrivs")
@@ -103,12 +104,12 @@ var _ = Describe("Podman privileged container tests", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- privs := strings.Split(cap.OutputToString(), ":")
+ privs := strings.Split(session.OutputToString(), ":")
session = podmanTest.Podman([]string{"run", "--security-opt", "no-new-privileges", "busybox", "grep", "NoNewPrivs", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- noprivs := strings.Split(cap.OutputToString(), ":")
+ noprivs := strings.Split(session.OutputToString(), ":")
Expect(privs[1]).To(Not(Equal(noprivs[1])))
})
diff --git a/test/e2e/run_restart_test.go b/test/e2e/run_restart_test.go
index a2f0b8b41..018c66b45 100644
--- a/test/e2e/run_restart_test.go
+++ b/test/e2e/run_restart_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run restart containers", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run restart containers", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -43,7 +44,7 @@ var _ = Describe("Podman run restart containers", func() {
It("Podman start after signal kill", func() {
_ = podmanTest.RunTopContainer("test1")
- ok := WaitForContainer(&podmanTest)
+ ok := WaitForContainer(podmanTest)
Expect(ok).To(BeTrue())
killSession := podmanTest.Podman([]string{"kill", "-s", "9", "test1"})
diff --git a/test/e2e/run_selinux_test.go b/test/e2e/run_selinux_test.go
index a1a18c780..418382e16 100644
--- a/test/e2e/run_selinux_test.go
+++ b/test/e2e/run_selinux_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/opencontainers/selinux/go-selinux"
@@ -13,7 +14,7 @@ var _ = Describe("Podman run", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman run", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
if !selinux.GetEnabled() {
Skip("SELinux not enabled")
diff --git a/test/e2e/run_signal_test.go b/test/e2e/run_signal_test.go
index 5de17108c..8f7894db8 100644
--- a/test/e2e/run_signal_test.go
+++ b/test/e2e/run_signal_test.go
@@ -4,39 +4,24 @@ import (
"fmt"
"io"
"os"
- "os/exec"
"path/filepath"
"strings"
"syscall"
"time"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "github.com/onsi/gomega/gexec"
"golang.org/x/sys/unix"
)
-// PodmanPID execs podman and returns its PID
-func (p *PodmanTest) PodmanPID(args []string) (*PodmanSession, int) {
- podmanOptions := p.MakeOptions()
- podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
- podmanOptions = append(podmanOptions, args...)
- fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
- command := exec.Command(p.PodmanBinary, podmanOptions...)
- session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
- if err != nil {
- Fail(fmt.Sprintf("unable to run podman command: %s", strings.Join(podmanOptions, " ")))
- }
- return &PodmanSession{session}, command.Process.Pid
-}
-
const sigCatch = "trap \"echo FOO >> /h/fifo \" 8; echo READY >> /h/fifo; while :; do sleep 0.25; done"
var _ = Describe("Podman run with --sig-proxy", func() {
var (
tmpdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -44,7 +29,7 @@ var _ = Describe("Podman run with --sig-proxy", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tmpdir)
+ podmanTest = PodmanTestCreate(tmpdir)
podmanTest.RestoreArtifact(fedoraMinimal)
})
@@ -122,7 +107,7 @@ var _ = Describe("Podman run with --sig-proxy", func() {
signal := syscall.SIGPOLL
session, pid := podmanTest.PodmanPID([]string{"run", "--name", "test2", "--sig-proxy=false", fedoraMinimal, "bash", "-c", sigCatch})
- ok := WaitForContainer(&podmanTest)
+ ok := WaitForContainer(podmanTest)
Expect(ok).To(BeTrue())
// Kill with given signal
diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go
index b69d15cee..b9fc00fce 100644
--- a/test/e2e/run_staticip_test.go
+++ b/test/e2e/run_staticip_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman run with --ip flag", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman run with --ip flag", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 98bf66a67..beb408fd4 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -7,6 +7,7 @@ import (
"path/filepath"
"strings"
+ . "github.com/containers/libpod/test/utils"
"github.com/mrunalp/fileutils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -16,7 +17,7 @@ var _ = Describe("Podman run", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -24,7 +25,7 @@ var _ = Describe("Podman run", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -355,7 +356,7 @@ var _ = Describe("Podman run", func() {
keyFile := filepath.Join(targetDir, "key.pem")
err = ioutil.WriteFile(keyFile, []byte(mountString), 0755)
Expect(err).To(BeNil())
- execSession := podmanTest.SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")})
+ execSession := SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")})
execSession.WaitWithDefaultTimeout()
Expect(execSession.ExitCode()).To(Equal(0))
diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go
index f2a9af6bf..b1f3d08b4 100644
--- a/test/e2e/run_userns_test.go
+++ b/test/e2e/run_userns_test.go
@@ -4,6 +4,7 @@ import (
"os"
"fmt"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman UserNS support", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman UserNS support", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/runlabel_test.go b/test/e2e/runlabel_test.go
index 8d10d3c24..93a19ba30 100644
--- a/test/e2e/runlabel_test.go
+++ b/test/e2e/runlabel_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -20,7 +21,7 @@ var _ = Describe("podman container runlabel", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -28,7 +29,7 @@ var _ = Describe("podman container runlabel", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index 586215c46..9f64e49a7 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman save", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -21,7 +22,7 @@ var _ = Describe("Podman save", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index 84f1efbca..0167e9062 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -5,6 +5,7 @@ import (
"os"
"strconv"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -13,7 +14,7 @@ var _ = Describe("Podman search", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
const regFileContents = `
[registries.search]
@@ -40,7 +41,7 @@ var _ = Describe("Podman search", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
@@ -136,7 +137,7 @@ var _ = Describe("Podman search", func() {
fakereg.WaitWithDefaultTimeout()
Expect(fakereg.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
@@ -159,7 +160,7 @@ var _ = Describe("Podman search", func() {
registry.WaitWithDefaultTimeout()
Expect(registry.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry3", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry3", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
@@ -182,7 +183,7 @@ var _ = Describe("Podman search", func() {
registry.WaitWithDefaultTimeout()
Expect(registry.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry4", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry4", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
@@ -214,7 +215,7 @@ var _ = Describe("Podman search", func() {
registry.WaitWithDefaultTimeout()
Expect(registry.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry5", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry5", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
@@ -245,7 +246,7 @@ var _ = Describe("Podman search", func() {
registry.WaitWithDefaultTimeout()
Expect(registry.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry6", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry6", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"})
@@ -276,7 +277,7 @@ var _ = Describe("Podman search", func() {
registryLocal.WaitWithDefaultTimeout()
Expect(registryLocal.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry7", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry7", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
@@ -284,7 +285,7 @@ var _ = Describe("Podman search", func() {
registryLocal.WaitWithDefaultTimeout()
Expect(registryLocal.ExitCode()).To(Equal(0))
- if !WaitContainerReady(&podmanTest, "registry8", "listening on", 20, 1) {
+ if !WaitContainerReady(podmanTest, "registry8", "listening on", 20, 1) {
Skip("Can not start docker registry.")
}
push := podmanTest.Podman([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:6000/my-alpine"})
diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go
index 9218cda69..c11511d1f 100644
--- a/test/e2e/start_test.go
+++ b/test/e2e/start_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman start", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman start", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go
index e456d7114..be00d68b2 100644
--- a/test/e2e/stats_test.go
+++ b/test/e2e/stats_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman stats", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman stats", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index 9698a3110..b172cd81e 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman stop", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman stop", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/tag_test.go b/test/e2e/tag_test.go
index 1b58fbd30..53896d1a2 100644
--- a/test/e2e/tag_test.go
+++ b/test/e2e/tag_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman tag", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman tag", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go
index 9537c2f50..cfcf2a959 100644
--- a/test/e2e/top_test.go
+++ b/test/e2e/top_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman top", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman top", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/e2e/version_test.go b/test/e2e/version_test.go
index 6caf0e3dd..68a462bdb 100644
--- a/test/e2e/version_test.go
+++ b/test/e2e/version_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman version", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman version", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
})
AfterEach(func() {
diff --git a/test/e2e/wait_test.go b/test/e2e/wait_test.go
index 8e7035204..a7e9b4c06 100644
--- a/test/e2e/wait_test.go
+++ b/test/e2e/wait_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
+ . "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -12,7 +13,7 @@ var _ = Describe("Podman wait", func() {
var (
tempdir string
err error
- podmanTest PodmanTest
+ podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
@@ -20,7 +21,7 @@ var _ = Describe("Podman wait", func() {
if err != nil {
os.Exit(1)
}
- podmanTest = PodmanCreate(tempdir)
+ podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
diff --git a/test/goecho/goecho.go b/test/goecho/goecho.go
new file mode 100644
index 000000000..1c8d2f586
--- /dev/null
+++ b/test/goecho/goecho.go
@@ -0,0 +1,29 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "strconv"
+ "time"
+)
+
+func main() {
+ args := os.Args[1:]
+ exitCode := 0
+
+ for i := 0; i < len(args); i++ {
+ fmt.Fprintln(os.Stdout, args[i])
+ fmt.Fprintln(os.Stderr, args[i])
+ }
+
+ if len(args) > 1 {
+ num, _ := strconv.Atoi(args[1])
+ if args[0] == "exitcode" {
+ exitCode = num
+ }
+ if args[0] == "sleep" {
+ time.Sleep(time.Duration(num) * time.Second)
+ }
+ }
+ os.Exit(exitCode)
+}
diff --git a/test/system/libpod_suite_test.go b/test/system/libpod_suite_test.go
new file mode 100644
index 000000000..5de50e4e7
--- /dev/null
+++ b/test/system/libpod_suite_test.go
@@ -0,0 +1,217 @@
+package system
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var (
+ PODMAN_BINARY string
+ GLOBALOPTIONS = []string{"--cgroup-manager",
+ "--cni-config-dir",
+ "--config", "-c",
+ "--conmon",
+ "--cpu-profile",
+ "--log-level",
+ "--root",
+ "--tmpdir",
+ "--runroot",
+ "--runtime",
+ "--storage-driver",
+ "--storage-opt",
+ "--syslog",
+ }
+ PODMAN_SUBCMD = []string{"attach",
+ "commit",
+ "container",
+ "build",
+ "create",
+ "diff",
+ "exec",
+ "export",
+ "history",
+ "image",
+ "images",
+ "import",
+ "info",
+ "inspect",
+ "kill",
+ "load",
+ "login",
+ "logout",
+ "logs",
+ "mount",
+ "pause",
+ "ps",
+ "pod",
+ "port",
+ "pull",
+ "push",
+ "restart",
+ "rm",
+ "rmi",
+ "run",
+ "save",
+ "search",
+ "start",
+ "stats",
+ "stop",
+ "tag",
+ "top",
+ "umount",
+ "unpause",
+ "version",
+ "wait",
+ "h",
+ }
+ INTEGRATION_ROOT string
+ ARTIFACT_DIR = "/tmp/.artifacts"
+ ALPINE = "docker.io/library/alpine:latest"
+ BB = "docker.io/library/busybox:latest"
+ BB_GLIBC = "docker.io/library/busybox:glibc"
+ fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest"
+ nginx = "quay.io/baude/alpine_nginx:latest"
+ redis = "docker.io/library/redis:alpine"
+ registry = "docker.io/library/registry:2"
+ infra = "k8s.gcr.io/pause:3.1"
+ defaultWaitTimeout = 90
+)
+
+// PodmanTestSystem struct for command line options
+type PodmanTestSystem struct {
+ PodmanTest
+ GlobalOptions map[string]string
+ PodmanCmdOptions map[string][]string
+}
+
+// TestLibpod ginkgo master function
+func TestLibpod(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Libpod Suite")
+}
+
+var _ = BeforeSuite(func() {
+})
+
+// PodmanTestCreate creates a PodmanTestSystem instance for the tests
+func PodmanTestCreate(tempDir string) *PodmanTestSystem {
+ var envKey string
+ globalOptions := make(map[string]string)
+ podmanCmdOptions := make(map[string][]string)
+
+ for _, n := range GLOBALOPTIONS {
+ envKey = strings.Replace(strings.ToUpper(strings.Trim(n, "-")), "-", "_", -1)
+ if isEnvSet(envKey) {
+ globalOptions[n] = os.Getenv(envKey)
+ }
+ }
+
+ for _, n := range PODMAN_SUBCMD {
+ envKey = strings.Replace("PODMAN_SUBCMD_OPTIONS", "SUBCMD", strings.ToUpper(n), -1)
+ if isEnvSet(envKey) {
+ podmanCmdOptions[n] = strings.Split(os.Getenv(envKey), " ")
+ }
+ }
+
+ podmanBinary := "podman"
+ if os.Getenv("PODMAN_BINARY") != "" {
+ podmanBinary = os.Getenv("PODMAN_BINARY")
+ }
+
+ p := &PodmanTestSystem{
+ PodmanTest: PodmanTest{
+ PodmanBinary: podmanBinary,
+ ArtifactPath: ARTIFACT_DIR,
+ TempDir: tempDir,
+ },
+ GlobalOptions: globalOptions,
+ PodmanCmdOptions: podmanCmdOptions,
+ }
+
+ p.PodmanMakeOptions = p.makeOptions
+
+ return p
+}
+
+func (p *PodmanTestSystem) Podman(args []string) *PodmanSession {
+ return p.PodmanBase(args)
+}
+
+//MakeOptions assembles all the podman options
+func (p *PodmanTestSystem) makeOptions(args []string) []string {
+ var addOptions, subArgs []string
+ for _, n := range GLOBALOPTIONS {
+ if p.GlobalOptions[n] != "" {
+ addOptions = append(addOptions, n, p.GlobalOptions[n])
+ }
+ }
+
+ if len(args) == 0 {
+ return addOptions
+ }
+
+ subCmd := args[0]
+ addOptions = append(addOptions, subCmd)
+ if subCmd == "unmount" {
+ subCmd = "umount"
+ }
+ if subCmd == "help" {
+ subCmd = "h"
+ }
+
+ if _, ok := p.PodmanCmdOptions[subCmd]; ok {
+ m := make(map[string]bool)
+ subArgs = p.PodmanCmdOptions[subCmd]
+ for i := 0; i < len(subArgs); i++ {
+ m[subArgs[i]] = true
+ }
+ for i := 1; i < len(args); i++ {
+ if _, ok := m[args[i]]; !ok {
+ subArgs = append(subArgs, args[i])
+ }
+ }
+ } else {
+ subArgs = args[1:]
+ }
+
+ addOptions = append(addOptions, subArgs...)
+
+ return addOptions
+}
+
+// Cleanup cleans up the temporary store
+func (p *PodmanTestSystem) Cleanup() {
+ // Remove all containers
+ stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"})
+ stopall.WaitWithDefaultTimeout()
+
+ session := p.Podman([]string{"rm", "-fa"})
+ session.Wait(90)
+ // Nuke tempdir
+ if err := os.RemoveAll(p.TempDir); err != nil {
+ fmt.Printf("%q\n", err)
+ }
+}
+
+// CleanupPod cleans up the temporary store
+func (p *PodmanTestSystem) CleanupPod() {
+ // Remove all containers
+ session := p.Podman([]string{"pod", "rm", "-fa"})
+ session.Wait(90)
+ // Nuke tempdir
+ if err := os.RemoveAll(p.TempDir); err != nil {
+ fmt.Printf("%q\n", err)
+ }
+}
+
+// Check if the key is set in Env
+func isEnvSet(key string) bool {
+ _, set := os.LookupEnv(key)
+ return set
+}
diff --git a/test/system/version_test.go b/test/system/version_test.go
new file mode 100644
index 000000000..ada0093b7
--- /dev/null
+++ b/test/system/version_test.go
@@ -0,0 +1,51 @@
+package system
+
+import (
+ "fmt"
+ "os"
+ "regexp"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman version test", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestSystem
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
+ GinkgoWriter.Write([]byte(timedResult))
+ })
+
+ It("Smoking test: podman version with extra args", func() {
+ logc := podmanTest.Podman([]string{"version", "anything", "-", "--"})
+ logc.WaitWithDefaultTimeout()
+ Expect(logc.ExitCode()).To(Equal(0))
+ ver := logc.OutputToString()
+ Expect(regexp.MatchString("Version:.*?Go Version:.*?OS/Arch", ver)).To(BeTrue())
+ })
+
+ It("Negative test: podman version with extra flag", func() {
+ logc := podmanTest.Podman([]string{"version", "--foo"})
+ logc.WaitWithDefaultTimeout()
+ Expect(logc.ExitCode()).NotTo(Equal(0))
+ err, _ := logc.GrepString("Incorrect Usage: flag provided but not defined: -foo")
+ Expect(err).To(BeTrue())
+ })
+
+})
diff --git a/test/utils/common_function_test.go b/test/utils/common_function_test.go
new file mode 100644
index 000000000..1648a4899
--- /dev/null
+++ b/test/utils/common_function_test.go
@@ -0,0 +1,150 @@
+package utils_test
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strings"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/ginkgo/extensions/table"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Common functions test", func() {
+ var defaultOSPath string
+ var defaultCgroupPath string
+
+ BeforeEach(func() {
+ defaultOSPath = OSReleasePath
+ defaultCgroupPath = ProcessOneCgroupPath
+ })
+
+ AfterEach(func() {
+ OSReleasePath = defaultOSPath
+ ProcessOneCgroupPath = defaultCgroupPath
+ })
+
+ It("Test CreateTempDirInTempDir", func() {
+ tmpDir, _ := CreateTempDirInTempDir()
+ _, err := os.Stat(tmpDir)
+ Expect(os.IsNotExist(err)).ShouldNot(BeTrue(), "Directory is not created as expect")
+ })
+
+ It("Test SystemExec", func() {
+ session := SystemExec(GoechoPath, []string{})
+ Expect(session.Command.Process).ShouldNot(BeNil(), "SystemExec can not start a process")
+ })
+
+ It("Test StringInSlice", func() {
+ testSlice := []string{"apple", "peach", "pear"}
+ Expect(StringInSlice("apple", testSlice)).To(BeTrue(), "apple should in ['apple', 'peach', 'pear']")
+ Expect(StringInSlice("banana", testSlice)).ShouldNot(BeTrue(), "banana should not in ['apple', 'peach', 'pear']")
+ Expect(StringInSlice("anything", []string{})).ShouldNot(BeTrue(), "anything should not in empty slice")
+ })
+
+ DescribeTable("Test GetHostDistributionInfo",
+ func(path, id, ver string, empty bool) {
+ txt := fmt.Sprintf("ID=%s\nVERSION_ID=%s", id, ver)
+ if !empty {
+ f, _ := os.Create(path)
+ f.WriteString(txt)
+ f.Close()
+ }
+
+ OSReleasePath = path
+ host := GetHostDistributionInfo()
+ if empty {
+ Expect(host).To(Equal(HostOS{}), "HostOs should be empty.")
+ } else {
+ Expect(host.Distribution).To(Equal(strings.Trim(id, "\"")))
+ Expect(host.Version).To(Equal(strings.Trim(ver, "\"")))
+ }
+ },
+ Entry("Configure file is not exist.", "/tmp/notexist", "", "", true),
+ Entry("Item value with and without \"", "/tmp/os-release.test", "fedora", "\"28\"", false),
+ Entry("Item empty with and without \"", "/tmp/os-release.test", "", "\"\"", false),
+ )
+
+ DescribeTable("Test IsKernelNewerThan",
+ func(kv string, expect, isNil bool) {
+ newer, err := IsKernelNewerThan(kv)
+ Expect(newer).To(Equal(expect), "Version compare results is not as expect.")
+ Expect(err == nil).To(Equal(isNil), "Error is not as expect.")
+ },
+ Entry("Invlid kernel version: 0", "0", false, false),
+ Entry("Older kernel version:0.0", "0.0", true, true),
+ Entry("Newer kernel version: 100.17.14", "100.17.14", false, true),
+ Entry("Invlid kernel version: I am not a kernel version", "I am not a kernel version", false, false),
+ )
+
+ DescribeTable("Test TestIsCommandAvailable",
+ func(cmd string, expect bool) {
+ cmdExist := IsCommandAvailable(cmd)
+ Expect(cmdExist).To(Equal(expect))
+ },
+ Entry("Command exist", GoechoPath, true),
+ Entry("Command exist", "Fakecmd", false),
+ )
+
+ It("Test WriteJsonFile", func() {
+ type testJson struct {
+ Item1 int
+ Item2 []string
+ }
+ compareData := &testJson{}
+
+ testData := &testJson{
+ Item1: 5,
+ Item2: []string{"test"},
+ }
+
+ testByte, _ := json.Marshal(testData)
+ err := WriteJsonFile(testByte, "/tmp/testJson")
+
+ Expect(err).To(BeNil(), "Failed to write JSON to file.")
+
+ read, err := os.Open("/tmp/testJson")
+ defer read.Close()
+
+ Expect(err).To(BeNil(), "Can not find the JSON file after we write it.")
+
+ bytes, _ := ioutil.ReadAll(read)
+ json.Unmarshal(bytes, compareData)
+
+ Expect(reflect.DeepEqual(testData, compareData)).To(BeTrue(), "Data chaned after we store it to file.")
+ })
+
+ DescribeTable("Test Containerized",
+ func(path string, setEnv, createFile, expect bool) {
+ if setEnv && (os.Getenv("container") == "") {
+ os.Setenv("container", "test")
+ defer os.Setenv("container", "")
+ }
+ if !setEnv && (os.Getenv("container") != "") {
+ containerized := os.Getenv("container")
+ os.Setenv("container", "")
+ defer os.Setenv("container", containerized)
+ }
+ txt := "1:test:/"
+ if expect {
+ txt = "2:docker:/"
+ }
+ if createFile {
+ f, _ := os.Create(path)
+ f.WriteString(txt)
+ f.Close()
+ }
+ ProcessOneCgroupPath = path
+ Expect(Containerized()).To(Equal(expect))
+ },
+ Entry("Set container in env", "", true, false, true),
+ Entry("Can not read from file", "/tmp/notexist", false, false, false),
+ Entry("Docker in cgroup file", "/tmp/cgroup.test", false, true, true),
+ Entry("Docker not in cgroup file", "/tmp/cgroup.test", false, true, false),
+ )
+
+})
diff --git a/test/utils/podmansession_test.go b/test/utils/podmansession_test.go
new file mode 100644
index 000000000..de8c20b24
--- /dev/null
+++ b/test/utils/podmansession_test.go
@@ -0,0 +1,90 @@
+package utils_test
+
+import (
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("PodmanSession test", func() {
+ var session *PodmanSession
+
+ BeforeEach(func() {
+ session = StartFakeCmdSession([]string{"PodmanSession", "test", "Podman Session"})
+ session.WaitWithDefaultTimeout()
+ })
+
+ It("Test OutputToString", func() {
+ Expect(session.OutputToString()).To(Equal("PodmanSession test Podman Session"))
+ })
+
+ It("Test OutputToStringArray", func() {
+ Expect(session.OutputToStringArray()).To(Equal([]string{"PodmanSession", "test", "Podman Session"}))
+ })
+
+ It("Test ErrorToString", func() {
+ Expect(session.ErrorToString()).To(Equal("PodmanSession test Podman Session"))
+ })
+
+ It("Test ErrorToStringArray", func() {
+ Expect(session.ErrorToStringArray()).To(Equal([]string{"PodmanSession", "test", "Podman Session", ""}))
+ })
+
+ It("Test GrepString", func() {
+ match, backStr := session.GrepString("Session")
+ Expect(match).To(BeTrue())
+ Expect(backStr).To(Equal([]string{"PodmanSession", "Podman Session"}))
+
+ match, backStr = session.GrepString("I am not here")
+ Expect(match).To(Not(BeTrue()))
+ Expect(backStr).To(BeNil())
+
+ })
+
+ It("Test ErrorGrepString", func() {
+ match, backStr := session.ErrorGrepString("Session")
+ Expect(match).To(BeTrue())
+ Expect(backStr).To(Equal([]string{"PodmanSession", "Podman Session"}))
+
+ match, backStr = session.ErrorGrepString("I am not here")
+ Expect(match).To(Not(BeTrue()))
+ Expect(backStr).To(BeNil())
+
+ })
+
+ It("Test LineInOutputStartsWith", func() {
+ Expect(session.LineInOuputStartsWith("Podman")).To(BeTrue())
+ Expect(session.LineInOuputStartsWith("Session")).To(Not(BeTrue()))
+ })
+
+ It("Test LineInOutputContains", func() {
+ Expect(session.LineInOutputContains("Podman")).To(BeTrue())
+ Expect(session.LineInOutputContains("Session")).To(BeTrue())
+ Expect(session.LineInOutputContains("I am not here")).To(Not(BeTrue()))
+ })
+
+ It("Test LineInOutputContainsTag", func() {
+ session = StartFakeCmdSession([]string{"HEAD LINE", "docker.io/library/busybox latest e1ddd7948a1c 5 weeks ago 1.38MB"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.LineInOutputContainsTag("docker.io/library/busybox", "latest")).To(BeTrue())
+ Expect(session.LineInOutputContainsTag("busybox", "latest")).To(Not(BeTrue()))
+ })
+
+ It("Test IsJSONOutputValid", func() {
+ session = StartFakeCmdSession([]string{`{"page":1,"fruits":["apple","peach","pear"]}`})
+ session.WaitWithDefaultTimeout()
+ Expect(session.IsJSONOutputValid()).To(BeTrue())
+
+ session = StartFakeCmdSession([]string{"I am not JSON"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.IsJSONOutputValid()).To(Not(BeTrue()))
+ })
+
+ It("Test WaitWithDefaultTimeout", func() {
+ session = StartFakeCmdSession([]string{"sleep", "2"})
+ Expect(session.ExitCode()).Should(Equal(-1))
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).Should(Equal(0))
+ })
+
+})
diff --git a/test/utils/podmantest_test.go b/test/utils/podmantest_test.go
new file mode 100644
index 000000000..87f756920
--- /dev/null
+++ b/test/utils/podmantest_test.go
@@ -0,0 +1,74 @@
+package utils_test
+
+import (
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("PodmanTest test", func() {
+ var podmanTest *FakePodmanTest
+
+ BeforeEach(func() {
+ podmanTest = FakePodmanTestCreate()
+ })
+
+ AfterEach(func() {
+ FakeOutputs = make(map[string][]string)
+ })
+
+ It("Test PodmanAsUser", func() {
+ FakeOutputs["check"] = []string{"check"}
+ os.Setenv("HOOK_OPTION", "hook_option")
+ env := os.Environ()
+ session := podmanTest.PodmanAsUser([]string{"check"}, 1000, 1000, env)
+ os.Unsetenv("HOOK_OPTION")
+ session.WaitWithDefaultTimeout()
+ Expect(session.Command.Process).ShouldNot(BeNil())
+ })
+
+ It("Test NumberOfContainersRunning", func() {
+ FakeOutputs["ps -q"] = []string{"one", "two"}
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
+ })
+
+ It("Test NumberOfContainers", func() {
+ FakeOutputs["ps -aq"] = []string{"one", "two"}
+ Expect(podmanTest.NumberOfContainers()).To(Equal(2))
+ })
+
+ It("Test NumberOfPods", func() {
+ FakeOutputs["pod ps -q"] = []string{"one", "two"}
+ Expect(podmanTest.NumberOfPods()).To(Equal(2))
+ })
+
+ It("Test WaitForContainer", func() {
+ FakeOutputs["ps -q"] = []string{"one", "two"}
+ Expect(WaitForContainer(podmanTest)).To(BeTrue())
+
+ FakeOutputs["ps -q"] = []string{"one"}
+ Expect(WaitForContainer(podmanTest)).To(BeTrue())
+
+ FakeOutputs["ps -q"] = []string{""}
+ Expect(WaitForContainer(podmanTest)).To(Not(BeTrue()))
+ })
+
+ It("Test GetContainerStatus", func() {
+ FakeOutputs["ps --all --format={{.Status}}"] = []string{"Need func update"}
+ Expect(podmanTest.GetContainerStatus()).To(Equal("Need func update"))
+ })
+
+ It("Test WaitContainerReady", func() {
+ FakeOutputs["logs testimage"] = []string{""}
+ Expect(WaitContainerReady(podmanTest, "testimage", "ready", 2, 1)).To(Not(BeTrue()))
+
+ FakeOutputs["logs testimage"] = []string{"I am ready"}
+ Expect(WaitContainerReady(podmanTest, "testimage", "am ready", 2, 1)).To(BeTrue())
+
+ FakeOutputs["logs testimage"] = []string{"I am ready"}
+ Expect(WaitContainerReady(podmanTest, "testimage", "", 2, 1)).To(BeTrue())
+ })
+
+})
diff --git a/test/utils/utils.go b/test/utils/utils.go
new file mode 100644
index 000000000..c9409c9d4
--- /dev/null
+++ b/test/utils/utils.go
@@ -0,0 +1,432 @@
+package utils
+
+import (
+ "bufio"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "runtime"
+ "strings"
+ "time"
+
+ "github.com/containers/storage/pkg/parsers/kernel"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var (
+ defaultWaitTimeout = 90
+ OSReleasePath = "/etc/os-release"
+ ProcessOneCgroupPath = "/proc/1/cgroup"
+)
+
+// PodmanTestCommon contains common functions will be updated later in
+// the inheritance structs
+type PodmanTestCommon interface {
+ MakeOptions(args []string) []string
+ WaitForContainer() bool
+ WaitContainerReady(id string, expStr string, timeout int, step int) bool
+}
+
+// PodmanTest struct for command line options
+type PodmanTest struct {
+ PodmanMakeOptions func(args []string) []string
+ PodmanBinary string
+ ArtifactPath string
+ TempDir string
+}
+
+// PodmanSession wraps the gexec.session so we can extend it
+type PodmanSession struct {
+ *gexec.Session
+}
+
+// HostOS is a simple struct for the test os
+type HostOS struct {
+ Distribution string
+ Version string
+ Arch string
+}
+
+// MakeOptions assembles all podman options
+func (p *PodmanTest) MakeOptions(args []string) []string {
+ return p.PodmanMakeOptions(args)
+}
+
+// PodmanAsUser exec podman as user. uid and gid is set for credentials useage. env is used
+// to record the env for debugging
+func (p *PodmanTest) PodmanAsUser(args []string, uid, gid uint32, env []string) *PodmanSession {
+ var command *exec.Cmd
+ podmanOptions := p.MakeOptions(args)
+
+ if env == nil {
+ fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
+ } else {
+ fmt.Printf("Running: (env: %v) %s %s\n", env, p.PodmanBinary, strings.Join(podmanOptions, " "))
+ }
+ if uid != 0 || gid != 0 {
+ nsEnterOpts := append([]string{"--userspec", fmt.Sprintf("%d:%d", uid, gid), "/", p.PodmanBinary}, podmanOptions...)
+ command = exec.Command("chroot", nsEnterOpts...)
+ } else {
+ command = exec.Command(p.PodmanBinary, podmanOptions...)
+ }
+ if env != nil {
+ command.Env = env
+ }
+
+ session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
+ if err != nil {
+ Fail(fmt.Sprintf("unable to run podman command: %s\n%v", strings.Join(podmanOptions, " "), err))
+ }
+ return &PodmanSession{session}
+}
+
+// PodmanBase exec podman with default env.
+func (p *PodmanTest) PodmanBase(args []string) *PodmanSession {
+ return p.PodmanAsUser(args, 0, 0, nil)
+}
+
+// WaitForContainer waits on a started container
+func (p *PodmanTest) WaitForContainer() bool {
+ for i := 0; i < 10; i++ {
+ if p.NumberOfContainersRunning() > 0 {
+ return true
+ }
+ time.Sleep(1 * time.Second)
+ }
+ return false
+}
+
+// NumberOfContainersRunning returns an int of how many
+// containers are currently running.
+func (p *PodmanTest) NumberOfContainersRunning() int {
+ var containers []string
+ ps := p.PodmanBase([]string{"ps", "-q"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ for _, i := range ps.OutputToStringArray() {
+ if i != "" {
+ containers = append(containers, i)
+ }
+ }
+ return len(containers)
+}
+
+// NumberOfContainers returns an int of how many
+// containers are currently defined.
+func (p *PodmanTest) NumberOfContainers() int {
+ var containers []string
+ ps := p.PodmanBase([]string{"ps", "-aq"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ for _, i := range ps.OutputToStringArray() {
+ if i != "" {
+ containers = append(containers, i)
+ }
+ }
+ return len(containers)
+}
+
+// NumberOfPods returns an int of how many
+// pods are currently defined.
+func (p *PodmanTest) NumberOfPods() int {
+ var pods []string
+ ps := p.PodmanBase([]string{"pod", "ps", "-q"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ for _, i := range ps.OutputToStringArray() {
+ if i != "" {
+ pods = append(pods, i)
+ }
+ }
+ return len(pods)
+}
+
+// GetContainerStatus returns the containers state.
+// This function assumes only one container is active.
+func (p *PodmanTest) GetContainerStatus() string {
+ var podmanArgs = []string{"ps"}
+ podmanArgs = append(podmanArgs, "--all", "--format={{.Status}}")
+ session := p.PodmanBase(podmanArgs)
+ session.WaitWithDefaultTimeout()
+ return session.OutputToString()
+}
+
+// WaitContainerReady waits process or service inside container start, and ready to be used.
+func (p *PodmanTest) WaitContainerReady(id string, expStr string, timeout int, step int) bool {
+ startTime := time.Now()
+ s := p.PodmanBase([]string{"logs", id})
+ s.WaitWithDefaultTimeout()
+
+ for {
+ if time.Since(startTime) >= time.Duration(timeout)*time.Second {
+ fmt.Printf("Container %s is not ready in %ds", id, timeout)
+ return false
+ }
+
+ if strings.Contains(s.OutputToString(), expStr) {
+ return true
+ }
+ time.Sleep(time.Duration(step) * time.Second)
+ s = p.PodmanBase([]string{"logs", id})
+ s.WaitWithDefaultTimeout()
+ }
+}
+
+// WaitForContainer is a wrapper function for accept inheritance PodmanTest struct.
+func WaitForContainer(p PodmanTestCommon) bool {
+ return p.WaitForContainer()
+}
+
+// WaitForContainerReady is a wrapper function for accept inheritance PodmanTest struct.
+func WaitContainerReady(p PodmanTestCommon, id string, expStr string, timeout int, step int) bool {
+ return p.WaitContainerReady(id, expStr, timeout, step)
+}
+
+// OutputToString formats session output to string
+func (s *PodmanSession) OutputToString() string {
+ fields := strings.Fields(fmt.Sprintf("%s", s.Out.Contents()))
+ return strings.Join(fields, " ")
+}
+
+// OutputToStringArray returns the output as a []string
+// where each array item is a line split by newline
+func (s *PodmanSession) OutputToStringArray() []string {
+ var results []string
+ output := fmt.Sprintf("%s", s.Out.Contents())
+ for _, line := range strings.Split(output, "\n") {
+ if line != "" {
+ results = append(results, line)
+ }
+ }
+ return results
+}
+
+// ErrorToString formats session stderr to string
+func (s *PodmanSession) ErrorToString() string {
+ fields := strings.Fields(fmt.Sprintf("%s", s.Err.Contents()))
+ return strings.Join(fields, " ")
+}
+
+// ErrorToStringArray returns the stderr output as a []string
+// where each array item is a line split by newline
+func (s *PodmanSession) ErrorToStringArray() []string {
+ output := fmt.Sprintf("%s", s.Err.Contents())
+ return strings.Split(output, "\n")
+}
+
+// GrepString takes session output and behaves like grep. it returns a bool
+// if successful and an array of strings on positive matches
+func (s *PodmanSession) GrepString(term string) (bool, []string) {
+ var (
+ greps []string
+ matches bool
+ )
+
+ for _, line := range s.OutputToStringArray() {
+ if strings.Contains(line, term) {
+ matches = true
+ greps = append(greps, line)
+ }
+ }
+ return matches, greps
+}
+
+// ErrorGrepString takes session stderr output and behaves like grep. it returns a bool
+// if successful and an array of strings on positive matches
+func (s *PodmanSession) ErrorGrepString(term string) (bool, []string) {
+ var (
+ greps []string
+ matches bool
+ )
+
+ for _, line := range s.ErrorToStringArray() {
+ if strings.Contains(line, term) {
+ matches = true
+ greps = append(greps, line)
+ }
+ }
+ return matches, greps
+}
+
+//LineInOutputStartsWith returns true if a line in a
+// session output starts with the supplied string
+func (s *PodmanSession) LineInOuputStartsWith(term string) bool {
+ for _, i := range s.OutputToStringArray() {
+ if strings.HasPrefix(i, term) {
+ return true
+ }
+ }
+ return false
+}
+
+//LineInOutputContains returns true if a line in a
+// session output starts with the supplied string
+func (s *PodmanSession) LineInOutputContains(term string) bool {
+ for _, i := range s.OutputToStringArray() {
+ if strings.Contains(i, term) {
+ return true
+ }
+ }
+ return false
+}
+
+//LineInOutputContainsTag returns true if a line in the
+// session's output contains the repo-tag pair as returned
+// by podman-images(1).
+func (s *PodmanSession) LineInOutputContainsTag(repo, tag string) bool {
+ tagMap := tagOutputToMap(s.OutputToStringArray())
+ for r, t := range tagMap {
+ if repo == r && tag == t {
+ return true
+ }
+ }
+ return false
+}
+
+// IsJSONOutputValid attempts to unmarshal the session buffer
+// and if successful, returns true, else false
+func (s *PodmanSession) IsJSONOutputValid() bool {
+ var i interface{}
+ if err := json.Unmarshal(s.Out.Contents(), &i); err != nil {
+ fmt.Println(err)
+ return false
+ }
+ return true
+}
+
+// WaitWithDefaultTimeout waits for process finished with defaultWaitTimeout
+func (s *PodmanSession) WaitWithDefaultTimeout() {
+ s.Wait(defaultWaitTimeout)
+ fmt.Println("output:", s.OutputToString())
+}
+
+// CreateTempDirinTempDir create a temp dir with prefix podman_test
+func CreateTempDirInTempDir() (string, error) {
+ return ioutil.TempDir("", "podman_test")
+}
+
+// SystemExec is used to exec a system command to check its exit code or output
+func SystemExec(command string, args []string) *PodmanSession {
+ c := exec.Command(command, args...)
+ session, err := gexec.Start(c, GinkgoWriter, GinkgoWriter)
+ if err != nil {
+ Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
+ }
+ return &PodmanSession{session}
+}
+
+// StringInSlice determines if a string is in a string slice, returns bool
+func StringInSlice(s string, sl []string) bool {
+ for _, i := range sl {
+ if i == s {
+ return true
+ }
+ }
+ return false
+}
+
+//tagOutPutToMap parses each string in imagesOutput and returns
+// a map of repo:tag pairs. Notice, the first array item will
+// be skipped as it's considered to be the header.
+func tagOutputToMap(imagesOutput []string) map[string]string {
+ m := make(map[string]string)
+ // iterate over output but skip the header
+ for _, i := range imagesOutput[1:] {
+ tmp := []string{}
+ for _, x := range strings.Split(i, " ") {
+ if x != "" {
+ tmp = append(tmp, x)
+ }
+ }
+ // podman-images(1) return a list like output
+ // in the format of "Repository Tag [...]"
+ if len(tmp) < 2 {
+ continue
+ }
+ m[tmp[0]] = tmp[1]
+ }
+ return m
+}
+
+//GetHostDistributionInfo returns a struct with its distribution name and version
+func GetHostDistributionInfo() HostOS {
+ f, err := os.Open(OSReleasePath)
+ defer f.Close()
+ if err != nil {
+ return HostOS{}
+ }
+
+ l := bufio.NewScanner(f)
+ host := HostOS{}
+ host.Arch = runtime.GOARCH
+ for l.Scan() {
+ if strings.HasPrefix(l.Text(), "ID=") {
+ host.Distribution = strings.Replace(strings.TrimSpace(strings.Join(strings.Split(l.Text(), "=")[1:], "")), "\"", "", -1)
+ }
+ if strings.HasPrefix(l.Text(), "VERSION_ID=") {
+ host.Version = strings.Replace(strings.TrimSpace(strings.Join(strings.Split(l.Text(), "=")[1:], "")), "\"", "", -1)
+ }
+ }
+ return host
+}
+
+// IsKernelNewerThan compares the current kernel version to one provided. If
+// the kernel is equal to or greater, returns true
+func IsKernelNewerThan(version string) (bool, error) {
+ inputVersion, err := kernel.ParseRelease(version)
+ if err != nil {
+ return false, err
+ }
+ kv, err := kernel.GetKernelVersion()
+ if err != nil {
+ return false, err
+ }
+
+ // CompareKernelVersion compares two kernel.VersionInfo structs.
+ // Returns -1 if a < b, 0 if a == b, 1 it a > b
+ result := kernel.CompareKernelVersion(*kv, *inputVersion)
+ if result >= 0 {
+ return true, nil
+ }
+ return false, nil
+
+}
+
+//IsCommandAvaible check if command exist
+func IsCommandAvailable(command string) bool {
+ check := exec.Command("bash", "-c", strings.Join([]string{"command -v", command}, " "))
+ err := check.Run()
+ if err != nil {
+ return false
+ }
+ return true
+}
+
+// WriteJsonFile write json format data to a json file
+func WriteJsonFile(data []byte, filePath string) error {
+ var jsonData map[string]interface{}
+ json.Unmarshal(data, &jsonData)
+ formatJson, _ := json.MarshalIndent(jsonData, "", " ")
+ return ioutil.WriteFile(filePath, formatJson, 0644)
+}
+
+// Containerized check the podman command run inside container
+func Containerized() bool {
+ container := os.Getenv("container")
+ if container != "" {
+ return true
+ }
+ b, err := ioutil.ReadFile(ProcessOneCgroupPath)
+ if err != nil {
+ // shrug, if we cannot read that file, return false
+ return false
+ }
+ if strings.Index(string(b), "docker") > -1 {
+ return true
+ }
+ return false
+}
diff --git a/test/utils/utils_suite_test.go b/test/utils/utils_suite_test.go
new file mode 100644
index 000000000..b1100892b
--- /dev/null
+++ b/test/utils/utils_suite_test.go
@@ -0,0 +1,52 @@
+package utils_test
+
+import (
+ "fmt"
+ "io"
+ "os/exec"
+ "strings"
+ "testing"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ "github.com/onsi/gomega/gexec"
+)
+
+var FakeOutputs map[string][]string
+var GoechoPath = "../goecho/goecho"
+
+type FakePodmanTest struct {
+ PodmanTest
+}
+
+func FakePodmanTestCreate() *FakePodmanTest {
+ FakeOutputs = make(map[string][]string)
+ p := &FakePodmanTest{
+ PodmanTest: PodmanTest{
+ PodmanBinary: GoechoPath,
+ },
+ }
+
+ p.PodmanMakeOptions = p.makeOptions
+ return p
+}
+
+func (p *FakePodmanTest) makeOptions(args []string) []string {
+ return FakeOutputs[strings.Join(args, " ")]
+}
+
+func StartFakeCmdSession(args []string) *PodmanSession {
+ var outWriter, errWriter io.Writer
+ command := exec.Command(GoechoPath, args...)
+ session, err := gexec.Start(command, outWriter, errWriter)
+ if err != nil {
+ fmt.Println(err)
+ }
+ return &PodmanSession{session}
+}
+
+func TestUtils(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Unit test for test utils package")
+}
diff --git a/vendor.conf b/vendor.conf
index 1b60d6ca4..c8e968648 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -12,7 +12,7 @@ github.com/containerd/continuity master
github.com/containernetworking/cni v0.7.0-alpha1
github.com/containernetworking/plugins 1562a1e60ed101aacc5e08ed9dbeba8e9f3d4ec1
github.com/containers/image bd10b1b53b2976f215b3f2f848fb8e7cad779aeb
-github.com/containers/storage 09abf3a26b8a3aa69e29fd7faeb260b98d675759
+github.com/containers/storage 3161726d1db0d0d4e86a9667dd476f09b997f497
github.com/containers/psgo 5dde6da0bc8831b35243a847625bcf18183bd1ee
github.com/coreos/go-systemd v14
github.com/cri-o/ocicni 2d2983e40c242322a56c22a903785e7f83eb378c
@@ -92,10 +92,11 @@ k8s.io/kube-openapi 275e2ce91dec4c05a4094a7b1daee5560b555ac9 https://github.com/
k8s.io/utils 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e https://github.com/kubernetes/utils
github.com/mrunalp/fileutils master
github.com/varlink/go master
-github.com/containers/buildah 46c577c87d5a7ab30ef40cfa695cd2b96b32b117
+github.com/containers/buildah 795d43e60e5a1ab283981b79eeda1dd14a65a0bd
github.com/Nvveen/Gotty master
github.com/fsouza/go-dockerclient master
github.com/openshift/imagebuilder master
github.com/ulikunitz/xz v0.5.4
github.com/mailru/easyjson 03f2033d19d5860aef995fe360ac7d395cd8ce65
github.com/coreos/go-iptables 25d087f3cffd9aedc0c2b7eff25f23cbf3c20fe1
+github.com/google/shlex c34317bd91bf98fab745d77b03933cf8769299fe
diff --git a/vendor/github.com/containers/buildah/README.md b/vendor/github.com/containers/buildah/README.md
index 6a79e524b..2b539bba8 100644
--- a/vendor/github.com/containers/buildah/README.md
+++ b/vendor/github.com/containers/buildah/README.md
@@ -107,6 +107,7 @@ $ sudo ./lighttpd.sh
| [buildah-images(1)](/docs/buildah-images.md) | List images in local storage. |
| [buildah-inspect(1)](/docs/buildah-inspect.md) | Inspects the configuration of a container or image. |
| [buildah-mount(1)](/docs/buildah-mount.md) | Mount the working container's root filesystem. |
+| [buildah-pull(1)](/docs/buildah-pull.md) | Pull an image from the specified location. |
| [buildah-push(1)](/docs/buildah-push.md) | Push an image from local storage to elsewhere. |
| [buildah-rename(1)](/docs/buildah-rename.md) | Rename a local container. |
| [buildah-rm(1)](/docs/buildah-rm.md) | Removes one or more working containers. |
diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go
index 9994d6cd0..1a642ed3d 100644
--- a/vendor/github.com/containers/buildah/buildah.go
+++ b/vendor/github.com/containers/buildah/buildah.go
@@ -224,6 +224,7 @@ func GetBuildInfo(b *Builder) BuilderInfo {
ContainerID: b.ContainerID,
MountPoint: b.MountPoint,
ProcessLabel: b.ProcessLabel,
+ MountLabel: b.MountLabel,
ImageAnnotations: b.ImageAnnotations,
ImageCreatedBy: b.ImageCreatedBy,
OCIv1: b.OCIv1,
diff --git a/vendor/github.com/containers/buildah/chroot/run.go b/vendor/github.com/containers/buildah/chroot/run.go
index 51e2d2bd4..8cfefb3de 100644
--- a/vendor/github.com/containers/buildah/chroot/run.go
+++ b/vendor/github.com/containers/buildah/chroot/run.go
@@ -1147,7 +1147,7 @@ func setupChrootBindMounts(spec *specs.Spec, bundlePath string) (undoBinds func(
}
if uintptr(fs.Flags)&expectedFlags != expectedFlags {
if err := unix.Mount(target, target, "bind", requestFlags|unix.MS_REMOUNT, ""); err != nil {
- return undoBinds, errors.Wrapf(err, "error remounting %q in mount namespace with expected flags")
+ return undoBinds, errors.Wrapf(err, "error remounting %q in mount namespace with expected flags", target)
}
}
}
diff --git a/vendor/github.com/containers/buildah/common.go b/vendor/github.com/containers/buildah/common.go
index 56a901925..be59215df 100644
--- a/vendor/github.com/containers/buildah/common.go
+++ b/vendor/github.com/containers/buildah/common.go
@@ -2,12 +2,14 @@ package buildah
import (
"io"
-
- "github.com/sirupsen/logrus"
+ "os"
+ "path/filepath"
cp "github.com/containers/image/copy"
"github.com/containers/image/transports"
"github.com/containers/image/types"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/sirupsen/logrus"
)
const (
@@ -17,10 +19,20 @@ const (
DOCKER = "docker"
)
+// userRegistriesFile is the path to the per user registry configuration file.
+var userRegistriesFile = filepath.Join(os.Getenv("HOME"), ".config/containers/registries.conf")
+
func getCopyOptions(reportWriter io.Writer, sourceReference types.ImageReference, sourceSystemContext *types.SystemContext, destinationReference types.ImageReference, destinationSystemContext *types.SystemContext, manifestType string) *cp.Options {
sourceCtx := &types.SystemContext{}
if sourceSystemContext != nil {
*sourceCtx = *sourceSystemContext
+ } else {
+ if rootless.IsRootless() {
+ if _, err := os.Stat(userRegistriesFile); err == nil {
+ sourceCtx.SystemRegistriesConfPath = userRegistriesFile
+ }
+
+ }
}
sourceInsecure, err := isReferenceInsecure(sourceReference, sourceCtx)
if err != nil {
@@ -33,6 +45,12 @@ func getCopyOptions(reportWriter io.Writer, sourceReference types.ImageReference
destinationCtx := &types.SystemContext{}
if destinationSystemContext != nil {
*destinationCtx = *destinationSystemContext
+ } else {
+ if rootless.IsRootless() {
+ if _, err := os.Stat(userRegistriesFile); err == nil {
+ destinationCtx.SystemRegistriesConfPath = userRegistriesFile
+ }
+ }
}
destinationInsecure, err := isReferenceInsecure(destinationReference, destinationCtx)
if err != nil {
@@ -58,5 +76,11 @@ func getSystemContext(defaults *types.SystemContext, signaturePolicyPath string)
if signaturePolicyPath != "" {
sc.SignaturePolicyPath = signaturePolicyPath
}
+ if sc.SystemRegistriesConfPath == "" && rootless.IsRootless() {
+ if _, err := os.Stat(userRegistriesFile); err == nil {
+ sc.SystemRegistriesConfPath = userRegistriesFile
+ }
+
+ }
return sc
}
diff --git a/vendor/github.com/containers/buildah/delete.go b/vendor/github.com/containers/buildah/delete.go
index 25f76cf74..e3bddba20 100644
--- a/vendor/github.com/containers/buildah/delete.go
+++ b/vendor/github.com/containers/buildah/delete.go
@@ -1,7 +1,6 @@
package buildah
import (
- "github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
)
@@ -14,5 +13,5 @@ func (b *Builder) Delete() error {
b.MountPoint = ""
b.Container = ""
b.ContainerID = ""
- return label.ReleaseLabel(b.ProcessLabel)
+ return nil
}
diff --git a/vendor/github.com/containers/buildah/image.go b/vendor/github.com/containers/buildah/image.go
index 31aff9eea..c0bf90ddd 100644
--- a/vendor/github.com/containers/buildah/image.go
+++ b/vendor/github.com/containers/buildah/image.go
@@ -107,7 +107,6 @@ func expectedDockerDiffIDs(image docker.V2Image) int {
// compression that we'll be applying.
func (i *containerImageRef) computeLayerMIMEType(what string) (omediaType, dmediaType string, err error) {
omediaType = v1.MediaTypeImageLayer
- //TODO: Convert to manifest.DockerV2Schema2LayerUncompressedMediaType once available
dmediaType = docker.V2S2MediaTypeUncompressedLayer
if i.compression != archive.Uncompressed {
switch i.compression {
diff --git a/vendor/github.com/containers/buildah/imagebuildah/build.go b/vendor/github.com/containers/buildah/imagebuildah/build.go
index 41d85cbc6..292ff9541 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/build.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/build.go
@@ -563,39 +563,39 @@ func NewExecutor(store storage.Store, options BuildOptions) (*Executor, error) {
registry: options.Registry,
transport: options.Transport,
ignoreUnrecognizedInstructions: options.IgnoreUnrecognizedInstructions,
- quiet: options.Quiet,
- runtime: options.Runtime,
- runtimeArgs: options.RuntimeArgs,
- transientMounts: options.TransientMounts,
- compression: options.Compression,
- output: options.Output,
- outputFormat: options.OutputFormat,
- additionalTags: options.AdditionalTags,
- signaturePolicyPath: options.SignaturePolicyPath,
- systemContext: options.SystemContext,
- volumeCache: make(map[string]string),
- volumeCacheInfo: make(map[string]os.FileInfo),
- log: options.Log,
- in: options.In,
- out: options.Out,
- err: options.Err,
- reportWriter: options.ReportWriter,
- isolation: options.Isolation,
- namespaceOptions: options.NamespaceOptions,
- configureNetwork: options.ConfigureNetwork,
- cniPluginPath: options.CNIPluginPath,
- cniConfigDir: options.CNIConfigDir,
- idmappingOptions: options.IDMappingOptions,
- commonBuildOptions: options.CommonBuildOpts,
- defaultMountsFilePath: options.DefaultMountsFilePath,
- iidfile: options.IIDFile,
- squash: options.Squash,
- labels: append([]string{}, options.Labels...),
- annotations: append([]string{}, options.Annotations...),
- layers: options.Layers,
- noCache: options.NoCache,
- removeIntermediateCtrs: options.RemoveIntermediateCtrs,
- forceRmIntermediateCtrs: options.ForceRmIntermediateCtrs,
+ quiet: options.Quiet,
+ runtime: options.Runtime,
+ runtimeArgs: options.RuntimeArgs,
+ transientMounts: options.TransientMounts,
+ compression: options.Compression,
+ output: options.Output,
+ outputFormat: options.OutputFormat,
+ additionalTags: options.AdditionalTags,
+ signaturePolicyPath: options.SignaturePolicyPath,
+ systemContext: options.SystemContext,
+ volumeCache: make(map[string]string),
+ volumeCacheInfo: make(map[string]os.FileInfo),
+ log: options.Log,
+ in: options.In,
+ out: options.Out,
+ err: options.Err,
+ reportWriter: options.ReportWriter,
+ isolation: options.Isolation,
+ namespaceOptions: options.NamespaceOptions,
+ configureNetwork: options.ConfigureNetwork,
+ cniPluginPath: options.CNIPluginPath,
+ cniConfigDir: options.CNIConfigDir,
+ idmappingOptions: options.IDMappingOptions,
+ commonBuildOptions: options.CommonBuildOpts,
+ defaultMountsFilePath: options.DefaultMountsFilePath,
+ iidfile: options.IIDFile,
+ squash: options.Squash,
+ labels: append([]string{}, options.Labels...),
+ annotations: append([]string{}, options.Annotations...),
+ layers: options.Layers,
+ noCache: options.NoCache,
+ removeIntermediateCtrs: options.RemoveIntermediateCtrs,
+ forceRmIntermediateCtrs: options.ForceRmIntermediateCtrs,
}
if exec.err == nil {
exec.err = os.Stderr
@@ -764,7 +764,7 @@ func (b *Executor) resolveNameToImageRef() (types.ImageReference, error) {
if err != nil {
candidates, _, err := util.ResolveName(b.output, "", b.systemContext, b.store)
if err != nil {
- return nil, errors.Wrapf(err, "error parsing target image name %q: %v", b.output)
+ return nil, errors.Wrapf(err, "error parsing target image name %q", b.output)
}
if len(candidates) == 0 {
return nil, errors.Errorf("error parsing target image name %q", b.output)
@@ -1044,17 +1044,14 @@ func (b *Executor) copiedFilesMatch(node *parser.Node, historyTime *time.Time) (
}
continue
}
- // For local files, walk the file tree and check the time stamps.
- timeIsGreater := false
- err := filepath.Walk(item, func(path string, info os.FileInfo, err error) error {
- if info.ModTime().After(*historyTime) {
- timeIsGreater = true
- return nil
- }
- return nil
- })
+ // Walks the file tree for local files and uses chroot to ensure we don't escape out of the allowed path
+ // when resolving any symlinks.
+ // Change the time format to ensure we don't run into a parsing error when converting again from string
+ // to time.Time. It is a known Go issue that the conversions cause errors sometimes, so specifying a particular
+ // time format here when converting to a string.
+ timeIsGreater, err := resolveModifiedTime(b.contextDir, item, historyTime.Format(time.RFC3339Nano))
if err != nil {
- return false, errors.Wrapf(err, "error walking file tree %q", item)
+ return false, errors.Wrapf(err, "error resolving symlinks and comparing modified times: %q", item)
}
if timeIsGreater {
return false, nil
@@ -1289,15 +1286,24 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options BuildOpt
} else {
// If the Dockerfile isn't found try prepending the
// context directory to it.
- if _, err := os.Stat(dfile); os.IsNotExist(err) {
+ dinfo, err := os.Stat(dfile)
+ if os.IsNotExist(err) {
dfile = filepath.Join(options.ContextDirectory, dfile)
}
+ dinfo, err = os.Stat(dfile)
+ if err != nil {
+ return "", nil, errors.Wrapf(err, "error reading info about %q", dfile)
+ }
+ // If given a directory, add '/Dockerfile' to it.
+ if dinfo.Mode().IsDir() {
+ dfile = filepath.Join(dfile, "Dockerfile")
+ }
logrus.Debugf("reading local Dockerfile %q", dfile)
contents, err := os.Open(dfile)
if err != nil {
return "", nil, errors.Wrapf(err, "error reading %q", dfile)
}
- dinfo, err := contents.Stat()
+ dinfo, err = contents.Stat()
if err != nil {
contents.Close()
return "", nil, errors.Wrapf(err, "error reading info about %q", dfile)
diff --git a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go
index 20e396f1f..2269b8dcc 100644
--- a/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go
+++ b/vendor/github.com/containers/buildah/imagebuildah/chroot_symlink.go
@@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"strings"
+ "time"
"github.com/containers/storage/pkg/reexec"
"github.com/pkg/errors"
@@ -14,13 +15,18 @@ import (
const (
symlinkChrootedCommand = "chrootsymlinks-resolve"
+ symlinkModifiedTime = "modtimesymlinks-resolve"
maxSymlinksResolved = 40
)
func init() {
reexec.Register(symlinkChrootedCommand, resolveChrootedSymlinks)
+ reexec.Register(symlinkModifiedTime, resolveSymlinkTimeModified)
}
+// main() for grandparent subprocess. Its main job is to shuttle stdio back
+// and forth, managing a pseudo-terminal if we want one, for our child, the
+// parent subprocess.
func resolveChrootedSymlinks() {
status := 0
flag.Parse()
@@ -39,7 +45,7 @@ func resolveChrootedSymlinks() {
}
// Our second parameter is the path name to evaluate for symbolic links
- symLink, err := getSymbolicLink(flag.Arg(0), flag.Arg(1))
+ symLink, err := getSymbolicLink(flag.Arg(1))
if err != nil {
fmt.Fprintf(os.Stderr, "error getting symbolic links: %v\n", err)
os.Exit(1)
@@ -51,7 +57,8 @@ func resolveChrootedSymlinks() {
os.Exit(status)
}
-// ResolveSymlink resolves any symlink in filename in the context of rootdir.
+// ResolveSymLink (in the grandparent process) resolves any symlink in filename
+// in the context of rootdir.
func ResolveSymLink(rootdir, filename string) (string, error) {
// The child process expects a chroot and one path that
// will be consulted relative to the chroot directory and evaluated
@@ -62,32 +69,121 @@ func ResolveSymLink(rootdir, filename string) (string, error) {
return "", errors.Wrapf(err, string(output))
}
- // Hand back the resolved symlink, will be "" if a symlink is not found
+ // Hand back the resolved symlink, will be filename if a symlink is not found
return string(output), nil
}
+// main() for grandparent subprocess. Its main job is to shuttle stdio back
+// and forth, managing a pseudo-terminal if we want one, for our child, the
+// parent subprocess.
+func resolveSymlinkTimeModified() {
+ status := 0
+ flag.Parse()
+ if len(flag.Args()) < 1 {
+ os.Exit(1)
+ }
+ // Our first parameter is the directory to chroot into.
+ if err := unix.Chdir(flag.Arg(0)); err != nil {
+ fmt.Fprintf(os.Stderr, "chdir(): %v\n", err)
+ os.Exit(1)
+ }
+ if err := unix.Chroot(flag.Arg(0)); err != nil {
+ fmt.Fprintf(os.Stderr, "chroot(): %v\n", err)
+ os.Exit(1)
+ }
+
+ // Our second parameter is the path name to evaluate for symbolic links.
+ // Our third parameter is the time the cached intermediate image was created.
+ // We check whether the modified time of the filepath we provide is after the time the cached image was created.
+ timeIsGreater, err := modTimeIsGreater(flag.Arg(0), flag.Arg(1), flag.Arg(2))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error checking if modified time of resolved symbolic link is greater: %v\n", err)
+ os.Exit(1)
+ }
+ if _, err := os.Stdout.WriteString(fmt.Sprintf("%v", timeIsGreater)); err != nil {
+ fmt.Fprintf(os.Stderr, "error writing string to stdout: %v\n", err)
+ os.Exit(1)
+ }
+ os.Exit(status)
+}
+
+// resolveModifiedTime (in the grandparent process) checks filename for any symlinks,
+// resolves it and compares the modified time of the file with historyTime, which is
+// the creation time of the cached image. It returns true if filename was modified after
+// historyTime, otherwise returns false.
+func resolveModifiedTime(rootdir, filename, historyTime string) (bool, error) {
+ // The child process expects a chroot and one path that
+ // will be consulted relative to the chroot directory and evaluated
+ // for any symbolic links present.
+ cmd := reexec.Command(symlinkModifiedTime, rootdir, filename, historyTime)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return false, errors.Wrapf(err, string(output))
+ }
+ // Hand back true/false depending on in the file was modified after the caches image was created.
+ return string(output) == "true", nil
+}
+
+// modTimeIsGreater goes through the files added/copied in using the Dockerfile and
+// checks the time stamp (follows symlinks) with the time stamp of when the cached
+// image was created. IT compares the two and returns true if the file was modified
+// after the cached image was created, otherwise it returns false.
+func modTimeIsGreater(rootdir, path string, historyTime string) (bool, error) {
+ var timeIsGreater bool
+
+ // Convert historyTime from string to time.Time for comparison
+ histTime, err := time.Parse(time.RFC3339Nano, historyTime)
+ if err != nil {
+ return false, errors.Wrapf(err, "error converting string to time.Time %q", historyTime)
+ }
+ // Walk the file tree and check the time stamps.
+ // Since we are chroot in rootdir, only want the path of the actual filename, i.e path - rootdir.
+ // +1 to account for the extra "/" (e.g rootdir=/home/user/mydir, path=/home/user/mydir/myfile.json)
+ err = filepath.Walk(path[len(rootdir)+1:], func(path string, info os.FileInfo, err error) error {
+ modTime := info.ModTime()
+ if info.Mode()&os.ModeSymlink == os.ModeSymlink {
+ // Evaluate any symlink that occurs to get updated modified information
+ resolvedPath, err := filepath.EvalSymlinks(path)
+ if err != nil {
+ return errors.Wrapf(err, "error evaluating symlink %q", path)
+ }
+ fileInfo, err := os.Stat(resolvedPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting file info %q", resolvedPath)
+ }
+ modTime = fileInfo.ModTime()
+ }
+ if modTime.After(histTime) {
+ timeIsGreater = true
+ return nil
+ }
+ return nil
+ })
+ if err != nil {
+ return false, errors.Wrapf(err, "error walking file tree %q", path)
+ }
+ return timeIsGreater, err
+}
+
// getSymbolic link goes through each part of the path and continues resolving symlinks as they appear.
// Returns what the whole target path for what "path" resolves to.
-func getSymbolicLink(rootdir, path string) (string, error) {
+func getSymbolicLink(path string) (string, error) {
var (
symPath string
symLinksResolved int
)
-
- // Splitting path as we need to resolve each parth of the path at a time
+ // Splitting path as we need to resolve each part of the path at a time
splitPath := strings.Split(path, "/")
if splitPath[0] == "" {
splitPath = splitPath[1:]
symPath = "/"
}
-
for _, p := range splitPath {
// If we have resolved 40 symlinks, that means something is terribly wrong
// will return an error and exit
if symLinksResolved >= maxSymlinksResolved {
return "", errors.Errorf("have resolved %q symlinks, something is terribly wrong!", maxSymlinksResolved)
}
-
symPath = filepath.Join(symPath, p)
isSymlink, resolvedPath, err := hasSymlink(symPath)
if err != nil {
@@ -119,16 +215,21 @@ func getSymbolicLink(rootdir, path string) (string, error) {
// otherwise it returns false and path
func hasSymlink(path string) (bool, string, error) {
info, err := os.Lstat(path)
- if os.IsNotExist(err) {
- if err = os.MkdirAll(path, 0755); err != nil {
- return false, "", errors.Wrapf(err, "error ensuring volume path %q exists", path)
- }
- info, err = os.Lstat(path)
- if err != nil {
- return false, "", errors.Wrapf(err, "error running lstat on %q", path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ if err = os.MkdirAll(path, 0755); err != nil {
+ return false, "", errors.Wrapf(err, "error ensuring volume path %q exists", path)
+ }
+ info, err = os.Lstat(path)
+ if err != nil {
+ return false, "", errors.Wrapf(err, "error running lstat on %q", path)
+ }
+ } else {
+ return false, path, errors.Wrapf(err, "error get stat of path %q", path)
}
}
- // Return false and path as path is not a symlink
+
+ // Return false and path as path if not a symlink
if info.Mode()&os.ModeSymlink != os.ModeSymlink {
return false, path, nil
}
diff --git a/vendor/github.com/containers/buildah/new.go b/vendor/github.com/containers/buildah/new.go
index 8b0e774ba..13bebf420 100644
--- a/vendor/github.com/containers/buildah/new.go
+++ b/vendor/github.com/containers/buildah/new.go
@@ -3,6 +3,7 @@ package buildah
import (
"context"
"fmt"
+ "math/rand"
"strings"
"github.com/containers/buildah/util"
@@ -12,7 +13,6 @@ import (
"github.com/containers/image/transports/alltransports"
"github.com/containers/image/types"
"github.com/containers/storage"
- "github.com/opencontainers/selinux/go-selinux/label"
"github.com/openshift/imagebuilder"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -23,11 +23,6 @@ const (
// as "no image".
BaseImageFakeName = imagebuilder.NoBaseImageSpecifier
- // DefaultTransport is a prefix that we apply to an image name if we
- // can't find one in the local Store, in order to generate a source
- // reference for the image that we can then copy to the local Store.
- DefaultTransport = "docker://"
-
// minimumTruncatedIDLength is the minimum length of an identifier that
// we'll accept as possibly being a truncated image ID.
minimumTruncatedIDLength = 3
@@ -150,7 +145,7 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
}
logrus.Debugf("error parsing image name %q as given, trying with transport %q: %v", image, options.Transport, err)
transport := options.Transport
- if transport != DefaultTransport {
+ if transport != util.DefaultTransport {
transport = transport + ":"
}
srcRef2, err := alltransports.ParseImageName(transport + image)
@@ -232,6 +227,27 @@ func resolveImage(ctx context.Context, systemContext *types.SystemContext, store
}
}
+func containerNameExist(name string, containers []storage.Container) bool {
+ for _, container := range containers {
+ for _, cname := range container.Names {
+ if cname == name {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+func findUnusedContainer(name string, containers []storage.Container) string {
+ suffix := 1
+ tmpName := name
+ for containerNameExist(tmpName, containers) {
+ tmpName = fmt.Sprintf("%s-%d", name, suffix)
+ suffix++
+ }
+ return tmpName
+}
+
func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions) (*Builder, error) {
var ref types.ImageReference
var img *storage.Image
@@ -241,7 +257,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
options.FromImage = ""
}
if options.Transport == "" {
- options.Transport = DefaultTransport
+ options.Transport = util.DefaultTransport
}
systemContext := getSystemContext(options.SystemContext, options.SignaturePolicyPath)
@@ -277,23 +293,33 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
name = imageNamePrefix(image) + "-" + name
}
}
+ var container *storage.Container
+ tmpName := name
+ if options.Container == "" {
+ containers, err := store.Containers()
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to check for container names")
+ }
+ tmpName = findUnusedContainer(tmpName, containers)
+ }
- coptions := storage.ContainerOptions{}
- coptions.IDMappingOptions = newContainerIDMappingOptions(options.IDMappingOptions)
-
- container, err := store.CreateContainer("", []string{name}, imageID, "", "", &coptions)
- suffix := 1
- for err != nil && errors.Cause(err) == storage.ErrDuplicateName && options.Container == "" {
- suffix++
- tmpName := fmt.Sprintf("%s-%d", name, suffix)
- if container, err = store.CreateContainer("", []string{tmpName}, imageID, "", "", &coptions); err == nil {
+ conflict := 100
+ for true {
+ coptions := storage.ContainerOptions{
+ LabelOpts: options.CommonBuildOpts.LabelOpts,
+ IDMappingOptions: newContainerIDMappingOptions(options.IDMappingOptions),
+ }
+ container, err = store.CreateContainer("", []string{tmpName}, imageID, "", "", &coptions)
+ if err == nil {
name = tmpName
+ break
}
+ if errors.Cause(err) != storage.ErrDuplicateName || options.Container != "" {
+ return nil, errors.Wrapf(err, "error creating container")
+ }
+ tmpName = fmt.Sprintf("%s-%d", name, rand.Int()%conflict)
+ conflict = conflict * 10
}
- if err != nil {
- return nil, errors.Wrapf(err, "error creating container")
- }
-
defer func() {
if err != nil {
if err2 := store.DeleteContainer(container.ID); err2 != nil {
@@ -302,13 +328,6 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
}
}()
- if err = ReserveSELinuxLabels(store, container.ID); err != nil {
- return nil, err
- }
- processLabel, mountLabel, err := label.InitLabels(options.CommonBuildOpts.LabelOpts)
- if err != nil {
- return nil, err
- }
uidmap, gidmap := convertStorageIDMaps(container.UIDMap, container.GIDMap)
defaultNamespaceOptions, err := DefaultNamespaceOptions()
@@ -328,8 +347,8 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
ContainerID: container.ID,
ImageAnnotations: map[string]string{},
ImageCreatedBy: "",
- ProcessLabel: processLabel,
- MountLabel: mountLabel,
+ ProcessLabel: container.ProcessLabel(),
+ MountLabel: container.MountLabel(),
DefaultMountsFilePath: options.DefaultMountsFilePath,
Isolation: options.Isolation,
NamespaceOptions: namespaceOptions,
@@ -351,7 +370,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions
}
if options.Mount {
- _, err = builder.Mount(mountLabel)
+ _, err = builder.Mount(container.MountLabel())
if err != nil {
return nil, errors.Wrapf(err, "error mounting build container %q", builder.ContainerID)
}
diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go
index b54663f5d..03b340294 100644
--- a/vendor/github.com/containers/buildah/pkg/cli/common.go
+++ b/vendor/github.com/containers/buildah/pkg/cli/common.go
@@ -71,6 +71,10 @@ var (
LayerFlags = []cli.Flag{
cli.BoolFlag{
+ Name: "force-rm",
+ Usage: "Always remove intermediate containers after a build, even if the build is unsuccessful.",
+ },
+ cli.BoolFlag{
Name: "layers",
Usage: fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. (default %t)", UseLayers()),
},
@@ -115,10 +119,6 @@ var (
Name: "file, f",
Usage: "`pathname or URL` of a Dockerfile",
},
- cli.BoolFlag{
- Name: "force-rm",
- Usage: "Always remove intermediate containers after a build, even if the build is unsuccessful.",
- },
cli.StringFlag{
Name: "format",
Usage: "`format` of the built image's manifest and metadata. Use BUILDAH_FORMAT environment variable to override.",
diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go
index 52269541a..1a51edb0e 100644
--- a/vendor/github.com/containers/buildah/pull.go
+++ b/vendor/github.com/containers/buildah/pull.go
@@ -146,11 +146,11 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio
srcRef, err := alltransports.ParseImageName(spec)
if err != nil {
if options.Transport == "" {
- options.Transport = DefaultTransport
+ options.Transport = util.DefaultTransport
}
logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, options.Transport, err)
transport := options.Transport
- if transport != DefaultTransport {
+ if transport != util.DefaultTransport {
transport = transport + ":"
}
spec = transport + spec
@@ -201,6 +201,7 @@ func pullImage(ctx context.Context, store storage.Store, imageName string, optio
logrus.Debugf("copying %q to %q", spec, destName)
if _, err := cp.Image(ctx, policyContext, destRef, srcRef, getCopyOptions(options.ReportWriter, srcRef, sc, destRef, nil, "")); err != nil {
+ logrus.Debugf("error copying src image [%q] to dest image [%q] err: %v", spec, destName, err)
return nil, err
}
return destRef, nil
diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go
index 718ef4e36..636a204b3 100644
--- a/vendor/github.com/containers/buildah/run.go
+++ b/vendor/github.com/containers/buildah/run.go
@@ -451,7 +451,7 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st
// Add temporary copies of the contents of volume locations at the
// volume locations, unless we already have something there.
copyWithTar := b.copyWithTar(nil, nil)
- builtins, err := runSetupBuiltinVolumes(b.MountLabel, mountPoint, cdir, copyWithTar, builtinVolumes)
+ builtins, err := runSetupBuiltinVolumes(b.MountLabel, mountPoint, cdir, copyWithTar, builtinVolumes, int(rootUID), int(rootGID))
if err != nil {
return err
}
@@ -493,15 +493,21 @@ func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts
return mounts, nil
}
-func runSetupBuiltinVolumes(mountLabel, mountPoint, containerDir string, copyWithTar func(srcPath, dstPath string) error, builtinVolumes []string) ([]specs.Mount, error) {
+func runSetupBuiltinVolumes(mountLabel, mountPoint, containerDir string, copyWithTar func(srcPath, dstPath string) error, builtinVolumes []string, rootUID, rootGID int) ([]specs.Mount, error) {
var mounts []specs.Mount
+ hostOwner := idtools.IDPair{UID: rootUID, GID: rootGID}
// Add temporary copies of the contents of volume locations at the
// volume locations, unless we already have something there.
for _, volume := range builtinVolumes {
subdir := digest.Canonical.FromString(volume).Hex()
volumePath := filepath.Join(containerDir, "buildah-volumes", subdir)
+ srcPath := filepath.Join(mountPoint, volume)
+ initializeVolume := false
// If we need to, initialize the volume path's initial contents.
- if _, err := os.Stat(volumePath); err != nil && os.IsNotExist(err) {
+ if _, err := os.Stat(volumePath); err != nil {
+ if !os.IsNotExist(err) {
+ return nil, errors.Wrapf(err, "failed to stat %q for volume %q", volumePath, volume)
+ }
logrus.Debugf("setting up built-in volume at %q", volumePath)
if err = os.MkdirAll(volumePath, 0755); err != nil {
return nil, errors.Wrapf(err, "error creating directory %q for volume %q", volumePath, volume)
@@ -509,11 +515,21 @@ func runSetupBuiltinVolumes(mountLabel, mountPoint, containerDir string, copyWit
if err = label.Relabel(volumePath, mountLabel, false); err != nil {
return nil, errors.Wrapf(err, "error relabeling directory %q for volume %q", volumePath, volume)
}
- srcPath := filepath.Join(mountPoint, volume)
- stat, err := os.Stat(srcPath)
- if err != nil {
+ initializeVolume = true
+ }
+ stat, err := os.Stat(srcPath)
+ if err != nil {
+ if !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "failed to stat %q for volume %q", srcPath, volume)
}
+ if err = idtools.MkdirAllAndChownNew(srcPath, 0755, hostOwner); err != nil {
+ return nil, errors.Wrapf(err, "error creating directory %q for volume %q", srcPath, volume)
+ }
+ if stat, err = os.Stat(srcPath); err != nil {
+ return nil, errors.Wrapf(err, "failed to stat %q for volume %q", srcPath, volume)
+ }
+ }
+ if initializeVolume {
if err = os.Chmod(volumePath, stat.Mode().Perm()); err != nil {
return nil, errors.Wrapf(err, "failed to chmod %q for volume %q", volumePath, volume)
}
@@ -1044,24 +1060,31 @@ func (b *Builder) Run(command []string, options RunOptions) error {
}
rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)}
- hostFile, err := b.addNetworkConfig(path, "/etc/hosts", rootIDPair)
- if err != nil {
- return err
- }
- resolvFile, err := b.addNetworkConfig(path, "/etc/resolv.conf", rootIDPair)
- if err != nil {
- return err
- }
+ bindFiles := make(map[string]string)
+ namespaceOptions := append(b.NamespaceOptions, options.NamespaceOptions...)
+ volumes := b.Volumes()
- if err := addHostsToFile(b.CommonBuildOpts.AddHost, hostFile); err != nil {
- return err
+ if !contains(volumes, "/etc/hosts") {
+ hostFile, err := b.addNetworkConfig(path, "/etc/hosts", rootIDPair)
+ if err != nil {
+ return err
+ }
+ bindFiles["/etc/hosts"] = hostFile
+
+ if err := addHostsToFile(b.CommonBuildOpts.AddHost, hostFile); err != nil {
+ return err
+ }
}
- bindFiles := map[string]string{
- "/etc/hosts": hostFile,
- "/etc/resolv.conf": resolvFile,
+ if !contains(volumes, "/etc/resolv.conf") {
+ resolvFile, err := b.addNetworkConfig(path, "/etc/resolv.conf", rootIDPair)
+ if err != nil {
+ return err
+ }
+ bindFiles["/etc/resolv.conf"] = resolvFile
}
- err = b.setupMounts(mountPoint, spec, path, options.Mounts, bindFiles, b.Volumes(), b.CommonBuildOpts.Volumes, b.CommonBuildOpts.ShmSize, append(b.NamespaceOptions, options.NamespaceOptions...))
+
+ err = b.setupMounts(mountPoint, spec, path, options.Mounts, bindFiles, volumes, b.CommonBuildOpts.Volumes, b.CommonBuildOpts.ShmSize, namespaceOptions)
if err != nil {
return errors.Wrapf(err, "error resolving mountpoints for container %q", b.ContainerID)
}
@@ -1095,7 +1118,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
} else {
moreCreateArgs = nil
}
- err = b.runUsingRuntimeSubproc(options, configureNetwork, configureNetworks, moreCreateArgs, spec, mountPoint, path, Package+"-"+filepath.Base(path))
+ err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, mountPoint, path, Package+"-"+filepath.Base(path))
case IsolationChroot:
err = chroot.RunUsingChroot(spec, path, options.Stdin, options.Stdout, options.Stderr)
case IsolationOCIRootless:
@@ -1109,13 +1132,22 @@ func (b *Builder) Run(command []string, options RunOptions) error {
}
}
options.Args = append(options.Args, rootlessFlag...)
- err = b.runUsingRuntimeSubproc(options, configureNetwork, configureNetworks, []string{"--no-new-keyring"}, spec, mountPoint, path, Package+"-"+filepath.Base(path))
+ err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, []string{"--no-new-keyring"}, spec, mountPoint, path, Package+"-"+filepath.Base(path))
default:
err = errors.Errorf("don't know how to run this command")
}
return err
}
+func contains(volumes []string, v string) bool {
+ for _, i := range volumes {
+ if i == v {
+ return true
+ }
+ }
+ return false
+}
+
func checkAndOverrideIsolationOptions(isolation Isolation, options *RunOptions) error {
switch isolation {
case IsolationOCIRootless:
@@ -1123,10 +1155,22 @@ func checkAndOverrideIsolationOptions(isolation Isolation, options *RunOptions)
logrus.Debugf("Forcing use of an IPC namespace.")
}
options.NamespaceOptions.AddOrReplace(NamespaceOption{Name: string(specs.IPCNamespace)})
- if ns := options.NamespaceOptions.Find(string(specs.NetworkNamespace)); ns != nil && !ns.Host {
- logrus.Debugf("Disabling network namespace.")
+ _, err := exec.LookPath("slirp4netns")
+ hostNetworking := err != nil
+ networkNamespacePath := ""
+ if ns := options.NamespaceOptions.Find(string(specs.NetworkNamespace)); ns != nil {
+ hostNetworking = ns.Host
+ networkNamespacePath = ns.Path
+ if !hostNetworking && networkNamespacePath != "" && !filepath.IsAbs(networkNamespacePath) {
+ logrus.Debugf("Disabling network namespace configuration.")
+ networkNamespacePath = ""
+ }
}
- options.NamespaceOptions.AddOrReplace(NamespaceOption{Name: string(specs.NetworkNamespace), Host: true})
+ options.NamespaceOptions.AddOrReplace(NamespaceOption{
+ Name: string(specs.NetworkNamespace),
+ Host: hostNetworking,
+ Path: networkNamespacePath,
+ })
if ns := options.NamespaceOptions.Find(string(specs.PIDNamespace)); ns == nil || ns.Host {
logrus.Debugf("Forcing use of a PID namespace.")
}
@@ -1227,9 +1271,10 @@ type runUsingRuntimeSubprocOptions struct {
ConfigureNetworks []string
MoreCreateArgs []string
ContainerName string
+ Isolation Isolation
}
-func (b *Builder) runUsingRuntimeSubproc(options RunOptions, configureNetwork bool, configureNetworks, moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName string) (err error) {
+func (b *Builder) runUsingRuntimeSubproc(isolation Isolation, options RunOptions, configureNetwork bool, configureNetworks, moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName string) (err error) {
var confwg sync.WaitGroup
config, conferr := json.Marshal(runUsingRuntimeSubprocOptions{
Options: options,
@@ -1240,6 +1285,7 @@ func (b *Builder) runUsingRuntimeSubproc(options RunOptions, configureNetwork bo
ConfigureNetworks: configureNetworks,
MoreCreateArgs: moreCreateArgs,
ContainerName: containerName,
+ Isolation: isolation,
})
if conferr != nil {
return errors.Wrapf(conferr, "error encoding configuration for %q", runUsingRuntimeCommand)
@@ -1318,7 +1364,7 @@ func runUsingRuntimeMain() {
os.Exit(1)
}
// Run the container, start to finish.
- status, err := runUsingRuntime(options.Options, options.ConfigureNetwork, options.ConfigureNetworks, options.MoreCreateArgs, options.Spec, options.RootPath, options.BundlePath, options.ContainerName)
+ status, err := runUsingRuntime(options.Isolation, options.Options, options.ConfigureNetwork, options.ConfigureNetworks, options.MoreCreateArgs, options.Spec, options.RootPath, options.BundlePath, options.ContainerName)
if err != nil {
fmt.Fprintf(os.Stderr, "error running container: %v\n", err)
os.Exit(1)
@@ -1333,7 +1379,7 @@ func runUsingRuntimeMain() {
os.Exit(1)
}
-func runUsingRuntime(options RunOptions, configureNetwork bool, configureNetworks, moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName string) (wstatus unix.WaitStatus, err error) {
+func runUsingRuntime(isolation Isolation, options RunOptions, configureNetwork bool, configureNetworks, moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName string) (wstatus unix.WaitStatus, err error) {
// Lock the caller to a single OS-level thread.
runtime.LockOSThread()
@@ -1490,7 +1536,7 @@ func runUsingRuntime(options RunOptions, configureNetwork bool, configureNetwork
}()
if configureNetwork {
- teardown, err := runConfigureNetwork(options, configureNetworks, pid, containerName, spec.Process.Args)
+ teardown, err := runConfigureNetwork(isolation, options, configureNetworks, pid, containerName, spec.Process.Args)
if teardown != nil {
defer teardown()
}
@@ -1623,9 +1669,81 @@ func runCollectOutput(fds, closeBeforeReadingFds []int) string {
}
return b.String()
}
+func setupRootlessNetwork(pid int) (teardown func(), err error) {
+ slirp4netns, err := exec.LookPath("slirp4netns")
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot find slirp4netns")
+ }
+
+ rootlessSlirpSyncR, rootlessSlirpSyncW, err := os.Pipe()
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot create slirp4netns sync pipe")
+ }
+ defer rootlessSlirpSyncR.Close()
+
+ // Be sure there are no fds inherited to slirp4netns except the sync pipe
+ files, err := ioutil.ReadDir("/proc/self/fd")
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot list open fds")
+ }
+ for _, f := range files {
+ fd, err := strconv.Atoi(f.Name())
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot parse fd")
+ }
+ if fd == int(rootlessSlirpSyncW.Fd()) {
+ continue
+ }
+ unix.CloseOnExec(fd)
+ }
+
+ cmd := exec.Command(slirp4netns, "-r", "3", "-c", fmt.Sprintf("%d", pid), "tap0")
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = nil, nil, nil
+ cmd.ExtraFiles = []*os.File{rootlessSlirpSyncW}
+
+ err = cmd.Start()
+ rootlessSlirpSyncW.Close()
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot start slirp4netns")
+ }
-func runConfigureNetwork(options RunOptions, configureNetworks []string, pid int, containerName string, command []string) (teardown func(), err error) {
+ b := make([]byte, 1)
+ for {
+ if err := rootlessSlirpSyncR.SetDeadline(time.Now().Add(1 * time.Second)); err != nil {
+ return nil, errors.Wrapf(err, "error setting slirp4netns pipe timeout")
+ }
+ if _, err := rootlessSlirpSyncR.Read(b); err == nil {
+ break
+ } else {
+ if os.IsTimeout(err) {
+ // Check if the process is still running.
+ var status syscall.WaitStatus
+ _, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to read slirp4netns process status")
+ }
+ if status.Exited() || status.Signaled() {
+ return nil, errors.New("slirp4netns failed")
+ }
+
+ continue
+ }
+ return nil, errors.Wrapf(err, "failed to read from slirp4netns sync pipe")
+ }
+ }
+
+ return func() {
+ cmd.Process.Kill()
+ cmd.Wait()
+ }, nil
+}
+
+func runConfigureNetwork(isolation Isolation, options RunOptions, configureNetworks []string, pid int, containerName string, command []string) (teardown func(), err error) {
var netconf, undo []*libcni.NetworkConfigList
+
+ if isolation == IsolationOCIRootless {
+ return setupRootlessNetwork(pid)
+ }
// Scan for CNI configuration files.
confdir := options.CNIConfigDir
files, err := libcni.ConfFiles(confdir, []string{".conf"})
@@ -1956,7 +2074,7 @@ func runAcceptTerminal(consoleListener *net.UnixListener, terminalSize *specs.Bo
for i := range scm {
fds, err := unix.ParseUnixRights(&scm[i])
if err != nil {
- return -1, errors.Wrapf(err, "error parsing unix rights control message: %v")
+ return -1, errors.Wrapf(err, "error parsing unix rights control message: %v", &scm[i])
}
logrus.Debugf("fds: %v", fds)
if len(fds) == 0 {
diff --git a/vendor/github.com/containers/buildah/unshare/unshare.go b/vendor/github.com/containers/buildah/unshare/unshare.go
index fbe623660..2a970b8d6 100644
--- a/vendor/github.com/containers/buildah/unshare/unshare.go
+++ b/vendor/github.com/containers/buildah/unshare/unshare.go
@@ -55,6 +55,10 @@ func (c *Cmd) Start() error {
}
c.Env = append(c.Env, fmt.Sprintf("_Buildah-unshare=%d", c.UnshareFlags))
+ // Please the libpod "rootless" package to find the expected env variables.
+ c.Env = append(c.Env, "_LIBPOD_USERNS_CONFIGURED=done")
+ c.Env = append(c.Env, fmt.Sprintf("_LIBPOD_ROOTLESS_UID=%d", os.Geteuid()))
+
// Create the pipe for reading the child's PID.
pidRead, pidWrite, err := os.Pipe()
if err != nil {
diff --git a/vendor/github.com/containers/buildah/util/util.go b/vendor/github.com/containers/buildah/util/util.go
index 3a415a7f3..b2451b78b 100644
--- a/vendor/github.com/containers/buildah/util/util.go
+++ b/vendor/github.com/containers/buildah/util/util.go
@@ -7,10 +7,8 @@ import (
"net/url"
"os"
"path"
- "path/filepath"
"strconv"
"strings"
- "syscall"
"github.com/containers/image/directory"
dockerarchive "github.com/containers/image/docker/archive"
@@ -31,6 +29,10 @@ import (
const (
minimumTruncatedIDLength = 3
+ // DefaultTransport is a prefix that we apply to an image name if we
+ // can't find one in the local Store, in order to generate a source
+ // reference for the image that we can then copy to the local Store.
+ DefaultTransport = "docker://"
)
var (
@@ -89,6 +91,7 @@ func ResolveName(name string, firstRegistry string, sc *types.SystemContext, sto
}
}
+ name = strings.TrimPrefix(name, DefaultTransport)
// If the image name already included a domain component, we're done.
named, err := reference.ParseNormalizedNamed(name)
if err != nil {
@@ -450,60 +453,6 @@ func ParseIDMappings(uidmap, gidmap []string) ([]idtools.IDMap, []idtools.IDMap,
return uid, gid, nil
}
-// UnsharedRootPath returns a location under ($XDG_DATA_HOME/containers/storage,
-// or $HOME/.local/share/containers/storage, or
-// (the user's home directory)/.local/share/containers/storage, or an error.
-func UnsharedRootPath(homedir string) (string, error) {
- // If $XDG_DATA_HOME is defined...
- if envDataHome, haveDataHome := os.LookupEnv("XDG_DATA_HOME"); haveDataHome {
- return filepath.Join(envDataHome, "containers", "storage"), nil
- }
- // If $XDG_DATA_HOME is not defined, but $HOME is defined...
- if envHomedir, haveHomedir := os.LookupEnv("HOME"); haveHomedir {
- // Default to the user's $HOME/.local/share/containers/storage subdirectory.
- return filepath.Join(envHomedir, ".local", "share", "containers", "storage"), nil
- }
- // If we know where our home directory is...
- if homedir != "" {
- // Default to the user's homedir/.local/share/containers/storage subdirectory.
- return filepath.Join(homedir, ".local", "share", "containers", "storage"), nil
- }
- return "", errors.New("unable to determine a --root location: neither $XDG_DATA_HOME nor $HOME is set")
-}
-
-// UnsharedRunrootPath returns $XDG_RUNTIME_DIR/run, /var/run/user/(the user's UID)/run, or an error.
-func UnsharedRunrootPath(uid string) (string, error) {
- // If $XDG_RUNTIME_DIR is defined...
- if envRuntimeDir, haveRuntimeDir := os.LookupEnv("XDG_RUNTIME_DIR"); haveRuntimeDir {
- return filepath.Join(envRuntimeDir, "run"), nil
- }
- var runtimeDir string
- // If $XDG_RUNTIME_DIR is not defined, but we know our UID...
- if uid != "" {
- tmpDir := filepath.Join("/var/run/user", uid)
- os.MkdirAll(tmpDir, 0700)
- st, err := os.Stat(tmpDir)
- if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Getuid() && st.Mode().Perm() == 0700 {
- runtimeDir = tmpDir
- }
- }
- if runtimeDir == "" {
- home := os.Getenv("HOME")
- if home == "" {
- return "", errors.New("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
- }
- resolvedHome, err := filepath.EvalSymlinks(home)
- if err != nil {
- return "", errors.Wrapf(err, "cannot resolve %s", home)
- }
- runtimeDir = filepath.Join(resolvedHome, "rundir")
- }
- if err := os.Setenv("XDG_RUNTIME_DIR", runtimeDir); err != nil {
- return "", errors.New("could not set XDG_RUNTIME_DIR")
- }
- return runtimeDir, nil
-}
-
// GetPolicyContext sets up, initializes and returns a new context for the specified policy
func GetPolicyContext(ctx *types.SystemContext) (*signature.PolicyContext, error) {
policy, err := signature.DefaultPolicy(ctx)
diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf
index d79412afc..c4410d0af 100644
--- a/vendor/github.com/containers/buildah/vendor.conf
+++ b/vendor/github.com/containers/buildah/vendor.conf
@@ -4,8 +4,8 @@ github.com/BurntSushi/toml master
github.com/containerd/continuity master
github.com/containernetworking/cni v0.7.0-alpha1
github.com/containers/image 5e5b67d6b1cf43cc349128ec3ed7d5283a6cc0d1
-github.com/containers/libpod 2afadeec6696fefac468a49c8ba24b0bc275aa75
-github.com/containers/storage 41294c85d97bef688e18f710402895dbecde3308
+github.com/containers/libpod e75469ab99c48e9fbe2b36ade229d384bdea9144
+github.com/containers/storage 09abf3a26b8a3aa69e29fd7faeb260b98d675759
github.com/docker/distribution 5f6282db7d65e6d72ad7c2cc66310724a57be716
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
@@ -36,7 +36,7 @@ github.com/opencontainers/image-spec v1.0.0
github.com/opencontainers/runc master
github.com/opencontainers/runtime-spec v1.0.0
github.com/opencontainers/runtime-tools master
-github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a
+github.com/opencontainers/selinux master
github.com/openshift/imagebuilder master
github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
github.com/pborman/uuid master
diff --git a/vendor/github.com/containers/storage/README.md b/vendor/github.com/containers/storage/README.md
index f68cc55c3..fef46a689 100644
--- a/vendor/github.com/containers/storage/README.md
+++ b/vendor/github.com/containers/storage/README.md
@@ -2,7 +2,7 @@
layers, container images, and containers. A `containers-storage` CLI wrapper
is also included for manual and scripting use.
-To build the CLI wrapper, use 'make build-binary'.
+To build the CLI wrapper, use 'make binary'.
Operations which use VMs expect to launch them using 'vagrant', defaulting to
using its 'libvirt' provider. The boxes used are also available for the
diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
index f14ba24b9..474c7574d 100644
--- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go
+++ b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
@@ -405,7 +405,7 @@ func atomicRemove(source string) error {
case os.IsExist(err):
// Got error saying the target dir already exists, maybe the source doesn't exist due to a previous (failed) remove
if _, e := os.Stat(source); !os.IsNotExist(e) {
- return errors.Wrapf(err, "target rename dir '%s' exists but should not, this needs to be manually cleaned up")
+ return errors.Wrapf(err, "target rename dir '%s' exists but should not, this needs to be manually cleaned up", target)
}
default:
return errors.Wrapf(err, "error preparing atomic delete")
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index d2cc65bca..b7e15a7f6 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -340,6 +340,10 @@ func supportsOverlay(home string, homeMagic graphdriver.FsMagic, rootUID, rootGI
func (d *Driver) useNaiveDiff() bool {
useNaiveDiffLock.Do(func() {
+ if d.options.mountProgram != "" {
+ useNaiveDiffOnly = true
+ return
+ }
if err := doesSupportNativeDiff(d.home, d.options.mountOptions); err != nil {
logrus.Warnf("Not using native diff for overlay, this may cause degraded performance for building images: %v", err)
useNaiveDiffOnly = true
@@ -841,6 +845,17 @@ func (d *Driver) isParent(id, parent string) bool {
return ld == parentDir
}
+func (d *Driver) getWhiteoutFormat() archive.WhiteoutFormat {
+ whiteoutFormat := archive.OverlayWhiteoutFormat
+ if d.options.mountProgram != "" {
+ // If we are using a mount program, we are most likely running
+ // as an unprivileged user that cannot use mknod, so fallback to the
+ // AUFS whiteout format.
+ whiteoutFormat = archive.AUFSWhiteoutFormat
+ }
+ return whiteoutFormat
+}
+
// ApplyDiff applies the new layer into a root
func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent string, mountLabel string, diff io.Reader) (size int64, err error) {
if !d.isParent(id, parent) {
@@ -858,7 +873,7 @@ func (d *Driver) ApplyDiff(id string, idMappings *idtools.IDMappings, parent str
if err := untar(diff, applyDir, &archive.TarOptions{
UIDMaps: idMappings.UIDs(),
GIDMaps: idMappings.GIDs(),
- WhiteoutFormat: archive.OverlayWhiteoutFormat,
+ WhiteoutFormat: d.getWhiteoutFormat(),
}); err != nil {
return 0, err
}
@@ -911,7 +926,7 @@ func (d *Driver) Diff(id string, idMappings *idtools.IDMappings, parent string,
Compression: archive.Uncompressed,
UIDMaps: idMappings.UIDs(),
GIDMaps: idMappings.GIDs(),
- WhiteoutFormat: archive.OverlayWhiteoutFormat,
+ WhiteoutFormat: d.getWhiteoutFormat(),
WhiteoutData: lowerDirs,
})
}
diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs.go b/vendor/github.com/containers/storage/drivers/zfs/zfs.go
index cb4424f2d..4e27a0a6f 100644
--- a/vendor/github.com/containers/storage/drivers/zfs/zfs.go
+++ b/vendor/github.com/containers/storage/drivers/zfs/zfs.go
@@ -52,7 +52,7 @@ func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdri
return nil, errors.Wrap(graphdriver.ErrPrerequisites, "the 'zfs' command is not available")
}
- file, err := os.OpenFile("/dev/zfs", os.O_RDWR, 600)
+ file, err := os.OpenFile("/dev/zfs", os.O_RDWR, 0600)
if err != nil {
logrus.Debugf("[zfs] cannot open /dev/zfs: %v", err)
return nil, errors.Wrapf(graphdriver.ErrPrerequisites, "could not open /dev/zfs: %v", err)
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index 1275ab47c..6c8f59b8b 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -542,8 +542,8 @@ func (r *layerStore) Put(id string, parentLayer *Layer, names []string, mountLab
_, idInUse = r.byid[id]
}
}
- if _, idInUse := r.byid[id]; idInUse {
- return nil, -1, ErrDuplicateID
+ if duplicateLayer, idInUse := r.byid[id]; idInUse {
+ return duplicateLayer, -1, ErrDuplicateID
}
names = dedupeNames(names)
for _, name := range names {
@@ -841,8 +841,12 @@ func (r *layerStore) Delete(id string) error {
return ErrLayerUnknown
}
id = layer.ID
- if _, err := r.Unmount(id, true); err != nil {
- return err
+ // This check is needed for idempotency of delete where the layer could have been
+ // already unmounted (since c/storage gives you that API directly)
+ for layer.MountCount > 0 {
+ if _, err := r.Unmount(id, false); err != nil {
+ return err
+ }
}
err := r.driver.Remove(id)
if err == nil {
diff --git a/vendor/github.com/containers/storage/pkg/archive/example_changes.go b/vendor/github.com/containers/storage/pkg/archive/example_changes.go
deleted file mode 100644
index 70f9c5564..000000000
--- a/vendor/github.com/containers/storage/pkg/archive/example_changes.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// +build ignore
-
-// Simple tool to create an archive stream from an old and new directory
-//
-// By default it will stream the comparison of two temporary directories with junk files
-package main
-
-import (
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path"
-
- "github.com/containers/storage/pkg/archive"
- "github.com/sirupsen/logrus"
-)
-
-var (
- flDebug = flag.Bool("D", false, "debugging output")
- flNewDir = flag.String("newdir", "", "")
- flOldDir = flag.String("olddir", "", "")
- log = logrus.New()
-)
-
-func main() {
- flag.Usage = func() {
- fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
- fmt.Printf("%s [OPTIONS]\n", os.Args[0])
- flag.PrintDefaults()
- }
- flag.Parse()
- log.Out = os.Stderr
- if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
- logrus.SetLevel(logrus.DebugLevel)
- }
- var newDir, oldDir string
-
- if len(*flNewDir) == 0 {
- var err error
- newDir, err = ioutil.TempDir("", "storage-test-newDir")
- if err != nil {
- log.Fatal(err)
- }
- defer os.RemoveAll(newDir)
- if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
- log.Fatal(err)
- }
- } else {
- newDir = *flNewDir
- }
-
- if len(*flOldDir) == 0 {
- oldDir, err := ioutil.TempDir("", "storage-test-oldDir")
- if err != nil {
- log.Fatal(err)
- }
- defer os.RemoveAll(oldDir)
- } else {
- oldDir = *flOldDir
- }
-
- changes, err := archive.ChangesDirs(newDir, oldDir)
- if err != nil {
- log.Fatal(err)
- }
-
- a, err := archive.ExportChanges(newDir, changes)
- if err != nil {
- log.Fatal(err)
- }
- defer a.Close()
-
- i, err := io.Copy(os.Stdout, a)
- if err != nil && err != io.EOF {
- log.Fatal(err)
- }
- fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
-}
-
-func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
- fileData := []byte("fooo")
- for n := 0; n < numberOfFiles; n++ {
- fileName := fmt.Sprintf("file-%d", n)
- if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
- return 0, err
- }
- if makeLinks {
- if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
- return 0, err
- }
- }
- }
- totalSize := numberOfFiles * len(fileData)
- return totalSize, nil
-}
diff --git a/vendor/github.com/containers/storage/pkg/idtools/parser.go b/vendor/github.com/containers/storage/pkg/idtools/parser.go
new file mode 100644
index 000000000..9b76395c2
--- /dev/null
+++ b/vendor/github.com/containers/storage/pkg/idtools/parser.go
@@ -0,0 +1,56 @@
+package idtools
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+func nonDigitsToWhitespace(r rune) rune {
+ if !strings.ContainsRune("0123456789", r) {
+ return ' '
+ }
+ return r
+}
+
+func parseTriple(spec []string) (container, host, size uint32, err error) {
+ cid, err := strconv.ParseUint(spec[0], 10, 32)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("error parsing id map value %q: %v", spec[0], err)
+ }
+ hid, err := strconv.ParseUint(spec[1], 10, 32)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("error parsing id map value %q: %v", spec[1], err)
+ }
+ sz, err := strconv.ParseUint(spec[2], 10, 32)
+ if err != nil {
+ return 0, 0, 0, fmt.Errorf("error parsing id map value %q: %v", spec[2], err)
+ }
+ return uint32(cid), uint32(hid), uint32(sz), nil
+}
+
+// ParseIDMap parses idmap triples from string.
+func ParseIDMap(idMapSpec, mapSetting string) (idmap []IDMap, err error) {
+ if len(idMapSpec) > 0 {
+ idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec))
+ if len(idSpec)%3 != 0 {
+ return nil, fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting)
+ }
+ for i := range idSpec {
+ if i%3 != 0 {
+ continue
+ }
+ cid, hid, size, err := parseTriple(idSpec[i : i+3])
+ if err != nil {
+ return nil, fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting)
+ }
+ mapping := IDMap{
+ ContainerID: int(cid),
+ HostID: int(hid),
+ Size: int(size),
+ }
+ idmap = append(idmap, mapping)
+ }
+ }
+ return idmap, nil
+}
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 7eaa82910..dfc30c43f 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -8,7 +8,6 @@ import (
"os"
"path/filepath"
"reflect"
- "strconv"
"strings"
"sync"
"time"
@@ -1069,7 +1068,7 @@ func (s *store) imageTopLayerForMapping(image *Image, ristore ROImageStore, read
}
mappedLayer, _, err := rlstore.Put("", parentLayer, nil, layer.MountLabel, nil, &layerOptions, false, nil, rc)
if err != nil {
- return nil, errors.Wrapf(err, "error creating ID-mapped copy of layer %q")
+ return nil, errors.Wrapf(err, "error creating ID-mapped copy of layer %q", parentLayer.ID)
}
if err = istore.addMappedTopLayer(image.ID, mappedLayer.ID); err != nil {
if err2 := rlstore.Delete(mappedLayer.ID); err2 != nil {
@@ -3203,56 +3202,19 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
storeOptions.UIDMap = mappings.UIDs()
storeOptions.GIDMap = mappings.GIDs()
}
- nonDigitsToWhitespace := func(r rune) rune {
- if strings.IndexRune("0123456789", r) == -1 {
- return ' '
- } else {
- return r
- }
- }
- parseTriple := func(spec []string) (container, host, size uint32, err error) {
- cid, err := strconv.ParseUint(spec[0], 10, 32)
- if err != nil {
- return 0, 0, 0, fmt.Errorf("error parsing id map value %q: %v", spec[0], err)
- }
- hid, err := strconv.ParseUint(spec[1], 10, 32)
- if err != nil {
- return 0, 0, 0, fmt.Errorf("error parsing id map value %q: %v", spec[1], err)
- }
- sz, err := strconv.ParseUint(spec[2], 10, 32)
- if err != nil {
- return 0, 0, 0, fmt.Errorf("error parsing id map value %q: %v", spec[2], err)
- }
- return uint32(cid), uint32(hid), uint32(sz), nil
+
+ uidmap, err := idtools.ParseIDMap(config.Storage.Options.RemapUIDs, "remap-uids")
+ if err != nil {
+ fmt.Print(err)
+ } else {
+ storeOptions.UIDMap = append(storeOptions.UIDMap, uidmap...)
}
- parseIDMap := func(idMapSpec, mapSetting string) (idmap []idtools.IDMap) {
- if len(idMapSpec) > 0 {
- idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec))
- if len(idSpec)%3 != 0 {
- fmt.Printf("Error initializing ID mappings: %s setting is malformed.\n", mapSetting)
- return nil
- }
- for i := range idSpec {
- if i%3 != 0 {
- continue
- }
- cid, hid, size, err := parseTriple(idSpec[i : i+3])
- if err != nil {
- fmt.Printf("Error initializing ID mappings: %s setting is malformed.\n", mapSetting)
- return nil
- }
- mapping := idtools.IDMap{
- ContainerID: int(cid),
- HostID: int(hid),
- Size: int(size),
- }
- idmap = append(idmap, mapping)
- }
- }
- return idmap
+ gidmap, err := idtools.ParseIDMap(config.Storage.Options.RemapGIDs, "remap-gids")
+ if err != nil {
+ fmt.Print(err)
+ } else {
+ storeOptions.GIDMap = append(storeOptions.GIDMap, gidmap...)
}
- storeOptions.UIDMap = append(storeOptions.UIDMap, parseIDMap(config.Storage.Options.RemapUIDs, "remap-uids")...)
- storeOptions.GIDMap = append(storeOptions.GIDMap, parseIDMap(config.Storage.Options.RemapGIDs, "remap-gids")...)
if os.Getenv("STORAGE_DRIVER") != "" {
storeOptions.GraphDriverName = os.Getenv("STORAGE_DRIVER")
}
diff --git a/vendor/github.com/containers/storage/vendor.conf b/vendor/github.com/containers/storage/vendor.conf
index 2276d5531..059ae94f0 100644
--- a/vendor/github.com/containers/storage/vendor.conf
+++ b/vendor/github.com/containers/storage/vendor.conf
@@ -2,13 +2,14 @@ github.com/BurntSushi/toml master
github.com/Microsoft/go-winio 307e919c663683a9000576fdc855acaf9534c165
github.com/Microsoft/hcsshim a8d9cc56cbce765a7eebdf4792e6ceceeff3edb8
github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76
-github.com/docker/engine-api 4290f40c056686fcaa5c9caf02eac1dde9315adf
+github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
github.com/docker/go-units 0dadbb0345b35ec7ef35e228dabb8de89a65bf52
github.com/mattn/go-shellwords 753a2322a99f87c0eff284980e77f53041555bc6
github.com/mistifyio/go-zfs c0224de804d438efd11ea6e52ada8014537d6062
github.com/opencontainers/go-digest master
github.com/opencontainers/runc 6c22e77604689db8725fa866f0f2ec0b3e8c3a07
github.com/opencontainers/selinux 36a9bc45a08c85f2c52bd9eb32e20267876773bd
+github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
github.com/pborman/uuid 1b00554d822231195d1babd97ff4a781231955c9
github.com/pkg/errors master
github.com/pmezard/go-difflib v1.0.0
@@ -20,4 +21,3 @@ github.com/tchap/go-patricia v2.2.6
github.com/vbatts/tar-split v0.10.2
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6
golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5
-github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
diff --git a/vendor/github.com/google/shlex/COPYING b/vendor/github.com/google/shlex/COPYING
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/github.com/google/shlex/COPYING
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/google/shlex/README b/vendor/github.com/google/shlex/README
new file mode 100644
index 000000000..c86bcc066
--- /dev/null
+++ b/vendor/github.com/google/shlex/README
@@ -0,0 +1,2 @@
+go-shlex is a simple lexer for go that supports shell-style quoting,
+commenting, and escaping.
diff --git a/vendor/github.com/google/shlex/shlex.go b/vendor/github.com/google/shlex/shlex.go
new file mode 100644
index 000000000..d98308bce
--- /dev/null
+++ b/vendor/github.com/google/shlex/shlex.go
@@ -0,0 +1,416 @@
+/*
+Copyright 2012 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/*
+Package shlex implements a simple lexer which splits input in to tokens using
+shell-style rules for quoting and commenting.
+
+The basic use case uses the default ASCII lexer to split a string into sub-strings:
+
+ shlex.Split("one \"two three\" four") -> []string{"one", "two three", "four"}
+
+To process a stream of strings:
+
+ l := NewLexer(os.Stdin)
+ for ; token, err := l.Next(); err != nil {
+ // process token
+ }
+
+To access the raw token stream (which includes tokens for comments):
+
+ t := NewTokenizer(os.Stdin)
+ for ; token, err := t.Next(); err != nil {
+ // process token
+ }
+
+*/
+package shlex
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// TokenType is a top-level token classification: A word, space, comment, unknown.
+type TokenType int
+
+// runeTokenClass is the type of a UTF-8 character classification: A quote, space, escape.
+type runeTokenClass int
+
+// the internal state used by the lexer state machine
+type lexerState int
+
+// Token is a (type, value) pair representing a lexographical token.
+type Token struct {
+ tokenType TokenType
+ value string
+}
+
+// Equal reports whether tokens a, and b, are equal.
+// Two tokens are equal if both their types and values are equal. A nil token can
+// never be equal to another token.
+func (a *Token) Equal(b *Token) bool {
+ if a == nil || b == nil {
+ return false
+ }
+ if a.tokenType != b.tokenType {
+ return false
+ }
+ return a.value == b.value
+}
+
+// Named classes of UTF-8 runes
+const (
+ spaceRunes = " \t\r\n"
+ escapingQuoteRunes = `"`
+ nonEscapingQuoteRunes = "'"
+ escapeRunes = `\`
+ commentRunes = "#"
+)
+
+// Classes of rune token
+const (
+ unknownRuneClass runeTokenClass = iota
+ spaceRuneClass
+ escapingQuoteRuneClass
+ nonEscapingQuoteRuneClass
+ escapeRuneClass
+ commentRuneClass
+ eofRuneClass
+)
+
+// Classes of lexographic token
+const (
+ UnknownToken TokenType = iota
+ WordToken
+ SpaceToken
+ CommentToken
+)
+
+// Lexer state machine states
+const (
+ startState lexerState = iota // no runes have been seen
+ inWordState // processing regular runes in a word
+ escapingState // we have just consumed an escape rune; the next rune is literal
+ escapingQuotedState // we have just consumed an escape rune within a quoted string
+ quotingEscapingState // we are within a quoted string that supports escaping ("...")
+ quotingState // we are within a string that does not support escaping ('...')
+ commentState // we are within a comment (everything following an unquoted or unescaped #
+)
+
+// tokenClassifier is used for classifying rune characters.
+type tokenClassifier map[rune]runeTokenClass
+
+func (typeMap tokenClassifier) addRuneClass(runes string, tokenType runeTokenClass) {
+ for _, runeChar := range runes {
+ typeMap[runeChar] = tokenType
+ }
+}
+
+// newDefaultClassifier creates a new classifier for ASCII characters.
+func newDefaultClassifier() tokenClassifier {
+ t := tokenClassifier{}
+ t.addRuneClass(spaceRunes, spaceRuneClass)
+ t.addRuneClass(escapingQuoteRunes, escapingQuoteRuneClass)
+ t.addRuneClass(nonEscapingQuoteRunes, nonEscapingQuoteRuneClass)
+ t.addRuneClass(escapeRunes, escapeRuneClass)
+ t.addRuneClass(commentRunes, commentRuneClass)
+ return t
+}
+
+// ClassifyRune classifiees a rune
+func (t tokenClassifier) ClassifyRune(runeVal rune) runeTokenClass {
+ return t[runeVal]
+}
+
+// Lexer turns an input stream into a sequence of tokens. Whitespace and comments are skipped.
+type Lexer Tokenizer
+
+// NewLexer creates a new lexer from an input stream.
+func NewLexer(r io.Reader) *Lexer {
+
+ return (*Lexer)(NewTokenizer(r))
+}
+
+// Next returns the next word, or an error. If there are no more words,
+// the error will be io.EOF.
+func (l *Lexer) Next() (string, error) {
+ for {
+ token, err := (*Tokenizer)(l).Next()
+ if err != nil {
+ return "", err
+ }
+ switch token.tokenType {
+ case WordToken:
+ return token.value, nil
+ case CommentToken:
+ // skip comments
+ default:
+ return "", fmt.Errorf("Unknown token type: %v", token.tokenType)
+ }
+ }
+}
+
+// Tokenizer turns an input stream into a sequence of typed tokens
+type Tokenizer struct {
+ input bufio.Reader
+ classifier tokenClassifier
+}
+
+// NewTokenizer creates a new tokenizer from an input stream.
+func NewTokenizer(r io.Reader) *Tokenizer {
+ input := bufio.NewReader(r)
+ classifier := newDefaultClassifier()
+ return &Tokenizer{
+ input: *input,
+ classifier: classifier}
+}
+
+// scanStream scans the stream for the next token using the internal state machine.
+// It will panic if it encounters a rune which it does not know how to handle.
+func (t *Tokenizer) scanStream() (*Token, error) {
+ state := startState
+ var tokenType TokenType
+ var value []rune
+ var nextRune rune
+ var nextRuneType runeTokenClass
+ var err error
+
+ for {
+ nextRune, _, err = t.input.ReadRune()
+ nextRuneType = t.classifier.ClassifyRune(nextRune)
+
+ if err == io.EOF {
+ nextRuneType = eofRuneClass
+ err = nil
+ } else if err != nil {
+ return nil, err
+ }
+
+ switch state {
+ case startState: // no runes read yet
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ return nil, io.EOF
+ }
+ case spaceRuneClass:
+ {
+ }
+ case escapingQuoteRuneClass:
+ {
+ tokenType = WordToken
+ state = quotingEscapingState
+ }
+ case nonEscapingQuoteRuneClass:
+ {
+ tokenType = WordToken
+ state = quotingState
+ }
+ case escapeRuneClass:
+ {
+ tokenType = WordToken
+ state = escapingState
+ }
+ case commentRuneClass:
+ {
+ tokenType = CommentToken
+ state = commentState
+ }
+ default:
+ {
+ tokenType = WordToken
+ value = append(value, nextRune)
+ state = inWordState
+ }
+ }
+ }
+ case inWordState: // in a regular word
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ case spaceRuneClass:
+ {
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ case escapingQuoteRuneClass:
+ {
+ state = quotingEscapingState
+ }
+ case nonEscapingQuoteRuneClass:
+ {
+ state = quotingState
+ }
+ case escapeRuneClass:
+ {
+ state = escapingState
+ }
+ default:
+ {
+ value = append(value, nextRune)
+ }
+ }
+ }
+ case escapingState: // the rune after an escape character
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ err = fmt.Errorf("EOF found after escape character")
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ default:
+ {
+ state = inWordState
+ value = append(value, nextRune)
+ }
+ }
+ }
+ case escapingQuotedState: // the next rune after an escape character, in double quotes
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ err = fmt.Errorf("EOF found after escape character")
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ default:
+ {
+ state = quotingEscapingState
+ value = append(value, nextRune)
+ }
+ }
+ }
+ case quotingEscapingState: // in escaping double quotes
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ err = fmt.Errorf("EOF found when expecting closing quote")
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ case escapingQuoteRuneClass:
+ {
+ state = inWordState
+ }
+ case escapeRuneClass:
+ {
+ state = escapingQuotedState
+ }
+ default:
+ {
+ value = append(value, nextRune)
+ }
+ }
+ }
+ case quotingState: // in non-escaping single quotes
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ err = fmt.Errorf("EOF found when expecting closing quote")
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ case nonEscapingQuoteRuneClass:
+ {
+ state = inWordState
+ }
+ default:
+ {
+ value = append(value, nextRune)
+ }
+ }
+ }
+ case commentState: // in a comment
+ {
+ switch nextRuneType {
+ case eofRuneClass:
+ {
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ }
+ case spaceRuneClass:
+ {
+ if nextRune == '\n' {
+ state = startState
+ token := &Token{
+ tokenType: tokenType,
+ value: string(value)}
+ return token, err
+ } else {
+ value = append(value, nextRune)
+ }
+ }
+ default:
+ {
+ value = append(value, nextRune)
+ }
+ }
+ }
+ default:
+ {
+ return nil, fmt.Errorf("Unexpected state: %v", state)
+ }
+ }
+ }
+}
+
+// Next returns the next token in the stream.
+func (t *Tokenizer) Next() (*Token, error) {
+ return t.scanStream()
+}
+
+// Split partitions a string into a slice of strings.
+func Split(s string) ([]string, error) {
+ l := NewLexer(strings.NewReader(s))
+ subStrings := make([]string, 0)
+ for {
+ word, err := l.Next()
+ if err != nil {
+ if err == io.EOF {
+ return subStrings, nil
+ }
+ return subStrings, err
+ }
+ subStrings = append(subStrings, word)
+ }
+}