summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml6
-rw-r--r--Makefile62
-rw-r--r--cmd/podman/common/create.go2
-rw-r--r--docs/source/markdown/podman-create.1.md13
-rw-r--r--docs/source/markdown/podman-login.1.md4
-rw-r--r--docs/source/markdown/podman-run.1.md14
-rwxr-xr-xhack/install_bats.sh8
-rw-r--r--libpod/container_exec.go7
-rw-r--r--libpod/kube.go18
-rw-r--r--libpod/runtime_pod_infra_linux.go4
-rw-r--r--nix/nixpkgs.json6
-rw-r--r--pkg/api/handlers/compat/containers_logs.go21
-rw-r--r--pkg/domain/infra/abi/play.go13
-rw-r--r--pkg/domain/infra/tunnel/images.go17
-rw-r--r--pkg/specgen/generate/storage.go4
-rw-r--r--test/e2e/build_test.go2
-rw-r--r--test/e2e/exec_test.go28
-rw-r--r--test/e2e/generate_kube_test.go34
-rw-r--r--test/e2e/play_kube_test.go68
-rw-r--r--test/e2e/pod_create_test.go24
-rw-r--r--test/e2e/run_test.go70
21 files changed, 322 insertions, 103 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 9d220c69a..a11bbbe61 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -594,12 +594,14 @@ static_build_task:
mv .cache /nix
if [[ -z $(ls -A /nix) ]]; then podman run --rm --privileged -ti -v /:/mnt nixos/nix cp -rfT /nix /mnt/nix; fi
podman run --rm --privileged -ti -v /nix:/nix -v ${PWD}:${PWD} -w ${PWD} nixos/nix nix --print-build-logs --option cores 8 --option max-jobs 8 build --file nix/
- mv /nix .cache
- chown -Rf $(whoami) .cache
binaries_artifacts:
path: "result/bin/podman"
+ save_cache_script: |
+ mv /nix .cache
+ chown -Rf $(whoami) .cache
+
darwin_build_task:
depends_on:
diff --git a/Makefile b/Makefile
index 07ff21445..253207f49 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,6 @@ PROJECT := github.com/containers/podman
GIT_BASE_BRANCH ?= origin/master
GIT_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
GIT_BRANCH_CLEAN ?= $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g")
-LIBPOD_IMAGE ?= libpod_dev$(if $(GIT_BRANCH_CLEAN),:$(GIT_BRANCH_CLEAN))
LIBPOD_INSTANCE := libpod_dev
PREFIX ?= /usr/local
BINDIR ?= ${PREFIX}/bin
@@ -38,7 +37,7 @@ PRE_COMMIT = $(shell command -v bin/venv/bin/pre-commit ~/.local/bin/pre-commit
SOURCES = $(shell find . -path './.*' -prune -o -name "*.go")
-GO_BUILD ?= $(GO) build -mod=vendor
+BUILDFLAGS := -mod=vendor $(BUILDFLAGS)
BUILDTAGS_CROSS ?= containers_image_openpgp exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_overlay
ifneq (,$(findstring varlink,$(BUILDTAGS)))
@@ -170,11 +169,11 @@ gofmt: ## Verify the source code gofmt
.PHONY: test/checkseccomp/checkseccomp
test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go)
- $(GO_BUILD) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
+ $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./test/checkseccomp
.PHONY: test/goecho/goechoe
test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go)
- $(GO_BUILD) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
+ $(GO) build $(BUILDFLAGS) -ldflags '$(LDFLAGS_PODMAN)' -o $@ ./test/goecho
.PHONY: bin/podman
@@ -184,18 +183,18 @@ ifeq (,$(findstring systemd,$(BUILDTAGS)))
@echo "Podman is being compiled without the systemd build tag. Install libsystemd on \
Ubuntu or systemd-devel on rpm based distro for journald support."
endif
- $(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./cmd/podman
+ $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o $@ ./cmd/podman
.PHONY: podman
podman: bin/podman
.PHONY: bin/podman-remote
bin/podman-remote: .gopathok $(SOURCES) go.mod go.sum $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on remote environment
- $(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "${REMOTETAGS}" -o $@ ./cmd/podman
+ $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "${REMOTETAGS}" -o $@ ./cmd/podman
.PHONY: bin/podman-remote-static
podman-remote-static: bin/podman-remote-static
- CGO_ENABLED=0 $(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN_STATIC)' -tags "${REMOTETAGS}" -o bin/podman-remote-static ./cmd/podman
+ CGO_ENABLED=0 $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN_STATIC)' -tags "${REMOTETAGS}" -o bin/podman-remote-static ./cmd/podman
.PHONY: podman-remote
podman-remote: bin/podman-remote
@@ -209,7 +208,7 @@ podman.msi: podman-remote podman-remote-windows install-podman-remote-windows-do
podman-remote-%: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build podman for a specific GOOS
$(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe"))
- CGO_ENABLED=0 GOOS=$* $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "${REMOTETAGS}" -o bin/$@$(BINSFX) ./cmd/podman
+ CGO_ENABLED=0 GOOS=$* $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "${REMOTETAGS}" -o bin/$@$(BINSFX) ./cmd/podman
local-cross: $(CROSS_BUILD_TARGETS) ## Cross local compilation
@@ -217,7 +216,7 @@ bin/podman.cross.%: .gopathok
TARGET="$*"; \
GOOS="$${TARGET%%.*}" \
GOARCH="$${TARGET##*.}" \
- $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags '$(BUILDTAGS_CROSS)' -o "$@" ./cmd/podman
+ $(GO) build $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags '$(BUILDTAGS_CROSS)' -o "$@" ./cmd/podman
# Update nix/nixpkgs.json its latest stable commit
.PHONY: nixpkgs
@@ -264,46 +263,6 @@ clean: ## Clean artifacts
docs/build
make -C docs clean
-.PHONY: libpodimage
-libpodimage: ## Build the libpod image
- ${CONTAINER_RUNTIME} build -t ${LIBPOD_IMAGE} .
-
-.PHONY: dbuild
-dbuild: libpodimage
- ${CONTAINER_RUNTIME} run --name=${LIBPOD_INSTANCE} --privileged -v ${PWD}:/go/src/${PROJECT} --rm ${LIBPOD_IMAGE} make all
-
-.PHONY: dbuild-podman-remote
-dbuild-podman-remote: libpodimage
- ${CONTAINER_RUNTIME} run --name=${LIBPOD_INSTANCE} --privileged -v ${PWD}:/go/src/${PROJECT} --rm ${LIBPOD_IMAGE} $(GOBUILD) -ldflags '$(LDFLAGS_PODMAN)' -tags "$(REMOTETAGS)" -o bin/podman-remote ./cmd/podman
-
-.PHONY: dbuild-podman-remote-darwin
-dbuild-podman-remote-darwin: libpodimage
- ${CONTAINER_RUNTIME} run --name=${LIBPOD_INSTANCE} --privileged -v ${PWD}:/go/src/${PROJECT} --rm ${LIBPOD_IMAGE} env GOOS=darwin $(GOBUILD) -ldflags '$(LDFLAGS_PODMAN)' -tags "${REMOTETAGS}" -o bin/podman-remote-darwin ./cmd/podman
-
-.PHONY: test
-test: libpodimage ## Run tests on built image
- ${CONTAINER_RUNTIME} run -e STORAGE_OPTIONS="--storage-driver=vfs" -e TESTFLAGS -e OCI_RUNTIME -e CGROUP_MANAGER=cgroupfs -e TRAVIS -t --privileged --rm -v ${CURDIR}:/go/src/${PROJECT} ${LIBPOD_IMAGE} make clean all localunit install.catatonit localintegration
-
-.PHONY: integration
-integration: libpodimage ## Execute integration tests
- ${CONTAINER_RUNTIME} run -e STORAGE_OPTIONS="--storage-driver=vfs" -e TESTFLAGS -e OCI_RUNTIME -e CGROUP_MANAGER=cgroupfs -e TRAVIS -t --privileged --rm -v ${CURDIR}:/go/src/${PROJECT} ${LIBPOD_IMAGE} make clean all install.catatonit localintegration
-
-.PHONY: integration.fedora
-integration.fedora:
- DIST=Fedora sh .papr_prepare.sh
-
-.PHONY: integration.centos
-integration.centos:
- DIST=CentOS sh .papr_prepare.sh
-
-.PHONY: shell
-shell: libpodimage ## Run the built image and attach a shell
- ${CONTAINER_RUNTIME} run -e STORAGE_OPTIONS="--storage-driver=vfs" -e CGROUP_MANAGER=cgroupfs -e TESTFLAGS -e OCI_RUNTIME -e TRAVIS -it --privileged --rm -v ${CURDIR}:/go/src/${PROJECT} ${LIBPOD_IMAGE} sh
-
-.PHONY: testunit
-testunit: libpodimage ## Run unittest on the built image
- ${CONTAINER_RUNTIME} run -e STORAGE_OPTIONS="--storage-driver=vfs" -e TESTFLAGS -e CGROUP_MANAGER=cgroupfs -e OCI_RUNTIME -e TRAVIS -t --privileged --rm -v ${CURDIR}:/go/src/${PROJECT} ${LIBPOD_IMAGE} make localunit
-
.PHONY: localunit
localunit: test/goecho/goecho varlink_generate
hack/check_root.sh make localunit
@@ -322,6 +281,9 @@ localunit: test/goecho/goecho varlink_generate
$(GO) tool cover -func=${COVERAGE_PATH}/coverprofile > ${COVERAGE_PATH}/functions
cat ${COVERAGE_PATH}/functions | sed -n 's/\(total:\).*\([0-9][0-9].[0-9]\)/\1 \2/p'
+.PHONY: test
+test: localunit localintegration remoteintegration localsystem remotesystem ## Run unit, integration, and system tests.
+
.PHONY: ginkgo
ginkgo:
$(GOBIN)/ginkgo -v $(TESTFLAGS) -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/. hack/.
@@ -622,7 +584,7 @@ endef
.PHONY: .install.ginkgo
.install.ginkgo: .gopathok
if [ ! -x "$(GOBIN)/ginkgo" ]; then \
- $(GO_BUILD) -o ${GOPATH}/bin/ginkgo ./vendor/github.com/onsi/ginkgo/ginkgo ; \
+ $(GO) install $(BUILDFLAGS) ./vendor/github.com/onsi/ginkgo/ginkgo ; \
fi
.PHONY: .install.gitvalidation
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index cfbcf6140..7e3dc7fb4 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -509,7 +509,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
"volume", "v", containerConfig.Volumes(),
"Bind mount a volume into the container",
)
- createFlags.StringSliceVar(
+ createFlags.StringArrayVar(
&cf.VolumesFrom,
"volumes-from", []string{},
"Mount volumes from the specified container(s)",
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 9049ffb9f..4a8b311f0 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -1070,11 +1070,11 @@ change propagation properties of source mount. Say `/` is source mount for
**--volumes-from**[=*CONTAINER*[:*OPTIONS*]]
-Mount volumes from the specified container(s).
-*OPTIONS* is a comma delimited list with the following available elements:
+Mount volumes from the specified container(s). Used to share volumes between
+containers. The *options* is a comma delimited list with the following available elements:
-* [rw|ro]
-* z
+* **rw**|**ro**
+* **z**
Mounts already mounted volumes from a source container onto another
container. You must supply the source's container-id or container-name.
@@ -1083,9 +1083,8 @@ the target container. You can share volumes even if the source container
is not running.
By default, Podman mounts the volumes in the same mode (read-write or
-read-only) as it is mounted in the source container. Optionally, you
-can change this by suffixing the container-id with either the `ro` or
-`rw` keyword.
+read-only) as it is mounted in the source container.
+You can change this by adding a `ro` or `rw` _option_.
Labeling systems like SELinux require that proper labels are placed on volume
content mounted into a container. Without a label, the security system might
diff --git a/docs/source/markdown/podman-login.1.md b/docs/source/markdown/podman-login.1.md
index efc7f05e2..9b4ff74ed 100644
--- a/docs/source/markdown/podman-login.1.md
+++ b/docs/source/markdown/podman-login.1.md
@@ -18,7 +18,7 @@ Podman will first search for the username and password in the **${XDG\_RUNTIME\_
Podman will then use any existing credentials found in **$HOME/.docker/config.json**.
If those credentials are not present, Podman will create **${XDG\_RUNTIME\_DIR}/containers/auth.json** (if the file does not exist) and
will then store the username and password from STDIN as a base64 encoded string in it.
-For more details about format and configurations of the auth,json file, please refer to containers-auth.json(5)
+For more details about format and configurations of the auth.json file, please refer to containers-auth.json(5)
**podman [GLOBAL OPTIONS]**
@@ -108,7 +108,7 @@ Login Succeeded!
```
## SEE ALSO
-podman(1), podman-logout(1), containers-auth.json(5)
+podman(1), podman-logout(1), containers-auth.json(5), containers-registries.conf(5)
## HISTORY
August 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 1a7b36a5e..47aa8827f 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -1100,7 +1100,7 @@ will convert /foo into a shared mount point. Alternatively, one can directly
change propagation properties of source mount. Say, if _/_ is source mount for
_/foo_, then use **mount --make-shared /** to convert _/_ into a shared mount.
-**--volumes-from**[=*container-id*[:*options*]]
+**--volumes-from**[=*CONTAINER*[:*OPTIONS*]]
Mount volumes from the specified container(s). Used to share volumes between
containers. The *options* is a comma delimited list with the following available elements:
@@ -1108,19 +1108,23 @@ containers. The *options* is a comma delimited list with the following available
* **rw**|**ro**
* **z**
-You can share volumes even if the source container is not running.
+Mounts already mounted volumes from a source container onto another
+container. You must supply the source's container-id or container-name.
+To share a volume, use the --volumes-from option when running
+the target container. You can share volumes even if the source container
+is not running.
By default, Podman mounts the volumes in the same mode (read-write or
read-only) as it is mounted in the source container.
-You can change this by adding a **ro** or **rw** _option_.
+You can change this by adding a `ro` or `rw` _option_.
Labeling systems like SELinux require that proper labels are placed on volume
content mounted into a container. Without a label, the security system might
prevent the processes running inside the container from using the content. By
default, Podman does not change the labels set by the OS.
-To change a label in the container context, you can add **z** to the volume mount.
-This suffix tells Podman to relabel file objects on the shared volumes. The **z**
+To change a label in the container context, you can add `z` to the volume mount.
+This suffix tells Podman to relabel file objects on the shared volumes. The `z`
option tells Podman that two containers share the volume content. As a result,
podman labels the content with a shared content label. Shared volume labels allow
all containers to read/write content.
diff --git a/hack/install_bats.sh b/hack/install_bats.sh
index d30e3daf8..01de8b7c6 100755
--- a/hack/install_bats.sh
+++ b/hack/install_bats.sh
@@ -4,13 +4,19 @@ set -e
die() { echo "${1:-No error message given} (from $(basename $0))"; exit 1; }
+if [[ "$(type -t bats)" != "" ]]; then
+ # bats is already installed.
+ exit 0
+fi
+
buildDir=$(mktemp -d)
git clone https://github.com/bats-core/bats-core $buildDir
pushd $buildDir
pwd
git reset --hard ${VERSION}
-./install.sh /usr/local
+echo "Installing bats to /usr/local (requires root)"
+sudo ./install.sh /usr/local
popd
rm -rf $buildDir
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index f5f54c7cc..fce26acb0 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -980,11 +980,6 @@ func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) {
capList = capabilities.AllCapabilities()
}
- user := c.config.User
- if session.Config.User != "" {
- user = session.Config.User
- }
-
if err := c.createExecBundle(session.ID()); err != nil {
return nil, err
}
@@ -995,7 +990,7 @@ func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) {
opts.Env = session.Config.Environment
opts.Terminal = session.Config.Terminal
opts.Cwd = session.Config.WorkDir
- opts.User = user
+ opts.User = session.Config.User
opts.PreserveFDs = session.Config.PreserveFDs
opts.DetachKeys = session.Config.DetachKeys
opts.ExitCommand = session.Config.ExitCommand
diff --git a/libpod/kube.go b/libpod/kube.go
index 9d5cbe68b..f83e99d82 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -77,6 +77,24 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
}
pod.Spec.HostAliases = extraHost
+ // vendor/k8s.io/api/core/v1/types.go: v1.Container cannot save restartPolicy
+ // so set it at here
+ for _, ctr := range allContainers {
+ if !ctr.IsInfra() {
+ switch ctr.Config().RestartPolicy {
+ case RestartPolicyAlways:
+ pod.Spec.RestartPolicy = v1.RestartPolicyAlways
+ case RestartPolicyOnFailure:
+ pod.Spec.RestartPolicy = v1.RestartPolicyOnFailure
+ case RestartPolicyNo:
+ pod.Spec.RestartPolicy = v1.RestartPolicyNever
+ default: // some pod create from cmdline, such as "", so set it to Never
+ pod.Spec.RestartPolicy = v1.RestartPolicyNever
+ }
+ break
+ }
+ }
+
if p.SharesPID() {
// unfortunately, go doesn't have a nice way to specify a pointer to a bool
b := true
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 164068638..570cdd38f 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -50,7 +50,11 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
entryPoint = config.Entrypoint
entryCmd = config.Entrypoint
}
+ } else { // so use the InfraCommand
+ entrypointSet = true
+ entryCmd = entryPoint
}
+
if len(config.Cmd) > 0 {
// We can't use the default pause command, since we're
// sourcing from the image. If we didn't already set an
diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json
index 6ef89ff82..cd885fce2 100644
--- a/nix/nixpkgs.json
+++ b/nix/nixpkgs.json
@@ -1,7 +1,7 @@
{
"url": "https://github.com/nixos/nixpkgs",
- "rev": "5f212d693fe1c82f9c7e20cd57bc69802b36a321",
- "date": "2020-08-22T01:42:23+02:00",
- "sha256": "1h3819ppllcpw07j884bjh07sma07vrrk1md92sf93cg43nmzncf",
+ "rev": "d5a689edda8219a1e20fd3871174b994cf0a94a3",
+ "date": "2020-09-13T01:58:20+02:00",
+ "sha256": "0m6nmi1fx0glfbg52kqdjgidxylk4p5xnx9v35wlsfi1j2xhkia4",
"fetchSubmodules": false
}
diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go
index f6d4a518e..d24b7d959 100644
--- a/pkg/api/handlers/compat/containers_logs.go
+++ b/pkg/api/handlers/compat/containers_logs.go
@@ -105,6 +105,18 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
var frame strings.Builder
header := make([]byte, 8)
+
+ writeHeader := true
+ // Docker does not write stream headers iff the container has a tty.
+ if !utils.IsLibpodRequest(r) {
+ inspectData, err := ctnr.Inspect(false)
+ if err != nil {
+ utils.InternalServerError(w, errors.Wrapf(err, "Failed to obtain logs for Container '%s'", name))
+ return
+ }
+ writeHeader = !inspectData.Config.Tty
+ }
+
for line := range logChannel {
if _, found := r.URL.Query()["until"]; found {
if line.Time.After(until) {
@@ -138,10 +150,13 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
}
frame.WriteString(line.Msg)
- binary.BigEndian.PutUint32(header[4:], uint32(frame.Len()))
- if _, err := w.Write(header[0:8]); err != nil {
- log.Errorf("unable to write log output header: %q", err)
+ if writeHeader {
+ binary.BigEndian.PutUint32(header[4:], uint32(frame.Len()))
+ if _, err := w.Write(header[0:8]); err != nil {
+ log.Errorf("unable to write log output header: %q", err)
+ }
}
+
if _, err := io.WriteString(w, frame.String()); err != nil {
log.Errorf("unable to write frame string: %q", err)
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 659cc799c..aa6aeede2 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -299,6 +299,18 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
+ var ctrRestartPolicy string
+ switch podYAML.Spec.RestartPolicy {
+ case v1.RestartPolicyAlways:
+ ctrRestartPolicy = libpod.RestartPolicyAlways
+ case v1.RestartPolicyOnFailure:
+ ctrRestartPolicy = libpod.RestartPolicyOnFailure
+ case v1.RestartPolicyNever:
+ ctrRestartPolicy = libpod.RestartPolicyNo
+ default: // Default to Always
+ ctrRestartPolicy = libpod.RestartPolicyAlways
+ }
+
containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
for _, container := range podYAML.Spec.Containers {
pullPolicy := util.PullImageMissing
@@ -326,6 +338,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
+ conf.RestartPolicy = ctrRestartPolicy
ctr, err := createconfig.CreateContainerFromCreateConfig(ctx, ic.Libpod, conf, pod)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 50b8342a3..332a7c2eb 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -306,7 +306,22 @@ func (ir *ImageEngine) Config(_ context.Context) (*config.Config, error) {
}
func (ir *ImageEngine) Build(_ context.Context, containerFiles []string, opts entities.BuildOptions) (*entities.BuildReport, error) {
- return images.Build(ir.ClientCxt, containerFiles, opts)
+ report, err := images.Build(ir.ClientCxt, containerFiles, opts)
+ if err != nil {
+ return nil, err
+ }
+ // For remote clients, if the option for writing to a file was
+ // selected, we need to write to the *client's* filesystem.
+ if len(opts.IIDFile) > 0 {
+ f, err := os.Create(opts.IIDFile)
+ if err != nil {
+ return nil, err
+ }
+ if _, err := f.WriteString(report.ID); err != nil {
+ return nil, err
+ }
+ }
+ return report, nil
}
func (ir *ImageEngine) Tree(ctx context.Context, nameOrID string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) {
diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go
index 7f55317ff..b225f79ee 100644
--- a/pkg/specgen/generate/storage.go
+++ b/pkg/specgen/generate/storage.go
@@ -195,9 +195,9 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
splitVol := strings.SplitN(volume, ":", 2)
if len(splitVol) == 2 {
splitOpts := strings.Split(splitVol[1], ",")
+ setRORW := false
+ setZ := false
for _, opt := range splitOpts {
- setRORW := false
- setZ := false
switch opt {
case "z":
if setZ {
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 0b6e919d0..06054bcb4 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -179,8 +179,6 @@ var _ = Describe("Podman build", func() {
})
It("podman build basic alpine and print id to external file", func() {
- SkipIfRemote()
-
// Switch to temp dir and restore it afterwards
cwd, err := os.Getwd()
Expect(err).To(BeNil())
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index 055546f88..6841aa5a2 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -283,6 +283,34 @@ var _ = Describe("Podman exec", func() {
Expect(strings.Contains(exec.OutputToString(), fmt.Sprintf("%s(%s)", gid, groupName))).To(BeTrue())
})
+ It("podman exec preserves container groups with --user and --group-add", func() {
+ SkipIfRemote()
+ dockerfile := `FROM fedora-minimal
+RUN groupadd -g 4000 first
+RUN groupadd -g 4001 second
+RUN useradd -u 1000 auser`
+ imgName := "testimg"
+ podmanTest.BuildImage(dockerfile, imgName, "false")
+
+ ctrName := "testctr"
+ ctr := podmanTest.Podman([]string{"run", "-t", "-i", "-d", "--name", ctrName, "--user", "auser:first", "--group-add", "second", imgName, "sleep", "300"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ exec := podmanTest.Podman([]string{"exec", "-t", ctrName, "id"})
+ exec.WaitWithDefaultTimeout()
+ Expect(exec.ExitCode()).To(Equal(0))
+ output := exec.OutputToString()
+ Expect(strings.Contains(output, "4000(first)")).To(BeTrue())
+ Expect(strings.Contains(output, "4001(second)")).To(BeTrue())
+ Expect(strings.Contains(output, "1000(auser)")).To(BeTrue())
+
+ // Kill the container just so the test does not take 15 seconds to stop.
+ kill := podmanTest.Podman([]string{"kill", ctrName})
+ kill.WaitWithDefaultTimeout()
+ Expect(kill.ExitCode()).To(Equal(0))
+ })
+
It("podman exec --detach", func() {
ctrName := "testctr"
ctr := podmanTest.Podman([]string{"run", "-t", "-i", "-d", "--name", ctrName, ALPINE, "top"})
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index e886c6000..a3a841dc6 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -3,6 +3,7 @@ package integration
import (
"os"
"path/filepath"
+ "strconv"
. "github.com/containers/podman/v2/test/utils"
"github.com/ghodss/yaml"
@@ -201,6 +202,39 @@ var _ = Describe("Podman generate kube", func() {
// Expect(err).To(BeNil())
})
+ It("podman generate kube on pod with restartPolicy", func() {
+ // podName, set, expect
+ testSli := [][]string{
+ {"testPod1", "", "Never"}, // some pod create from cmdline, so set it to Never
+ {"testPod2", "always", "Always"},
+ {"testPod3", "on-failure", "OnFailure"},
+ {"testPod4", "no", "Never"},
+ }
+
+ for k, v := range testSli {
+ podName := v[0]
+ podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession.ExitCode()).To(Equal(0))
+
+ ctrName := "ctr" + strconv.Itoa(k)
+ ctr1Session := podmanTest.Podman([]string{"create", "--name", ctrName, "--pod", podName,
+ "--restart", v[1], ALPINE, "top"})
+ ctr1Session.WaitWithDefaultTimeout()
+ Expect(ctr1Session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", podName})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ pod := new(v1.Pod)
+ err := yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ Expect(string(pod.Spec.RestartPolicy)).To(Equal(v[2]))
+ }
+ })
+
It("podman generate kube on pod with ports", func() {
podName := "test"
podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName, "-p", "4000:4000", "-p", "5000:5000"})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index f58862ab2..7a5aebcc2 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -46,6 +46,7 @@ metadata:
{{ end }}
spec:
+ restartPolicy: {{ .RestartPolicy }}
hostname: {{ .Hostname }}
hostAliases:
{{ range .HostAliases }}
@@ -165,6 +166,7 @@ spec:
{{- end }}
{{- end }}
spec:
+ restartPolicy: {{ .RestartPolicy }}
hostname: {{ .Hostname }}
containers:
{{ with .Ctrs }}
@@ -274,13 +276,14 @@ func generateDeploymentKubeYaml(deployment *Deployment, fileName string) error {
// Pod describes the options a kube yaml can be configured at pod level
type Pod struct {
- Name string
- Hostname string
- HostAliases []HostAlias
- Ctrs []*Ctr
- Volumes []*Volume
- Labels map[string]string
- Annotations map[string]string
+ Name string
+ RestartPolicy string
+ Hostname string
+ HostAliases []HostAlias
+ Ctrs []*Ctr
+ Volumes []*Volume
+ Labels map[string]string
+ Annotations map[string]string
}
type HostAlias struct {
@@ -293,13 +296,14 @@ type HostAlias struct {
// if no containers are added, it will add the default container
func getPod(options ...podOption) *Pod {
p := Pod{
- Name: defaultPodName,
- Hostname: "",
- HostAliases: nil,
- Ctrs: make([]*Ctr, 0),
- Volumes: make([]*Volume, 0),
- Labels: make(map[string]string),
- Annotations: make(map[string]string),
+ Name: defaultPodName,
+ RestartPolicy: "Never",
+ Hostname: "",
+ HostAliases: nil,
+ Ctrs: make([]*Ctr, 0),
+ Volumes: make([]*Volume, 0),
+ Labels: make(map[string]string),
+ Annotations: make(map[string]string),
}
for _, option := range options {
option(&p)
@@ -312,6 +316,12 @@ func getPod(options ...podOption) *Pod {
type podOption func(*Pod)
+func withPodName(name string) podOption {
+ return func(pod *Pod) {
+ pod.Name = name
+ }
+}
+
func withHostname(h string) podOption {
return func(pod *Pod) {
pod.Hostname = h
@@ -333,6 +343,12 @@ func withCtr(c *Ctr) podOption {
}
}
+func withRestartPolicy(policy string) podOption {
+ return func(pod *Pod) {
+ pod.RestartPolicy = policy
+ }
+}
+
func withLabel(k, v string) podOption {
return func(pod *Pod) {
pod.Labels[k] = v
@@ -649,6 +665,30 @@ var _ = Describe("Podman generate kube", func() {
Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello world]`))
})
+ It("podman play kube test restartPolicy", func() {
+ // podName, set, expect
+ testSli := [][]string{
+ {"testPod1", "", "always"}, // Default eqaul to always
+ {"testPod2", "Always", "always"},
+ {"testPod3", "OnFailure", "on-failure"},
+ {"testPod4", "Never", "no"},
+ }
+ for _, v := range testSli {
+ pod := getPod(withPodName(v[0]), withRestartPolicy(v[1]))
+ err := generatePodKubeYaml(pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{.HostConfig.RestartPolicy.Name}}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(Equal(v[2]))
+ }
+ })
+
It("podman play kube test hostname", func() {
pod := getPod()
err := generatePodKubeYaml(pod, kubeYaml)
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index ed62e8a4b..168150bff 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -345,6 +345,12 @@ var _ = Describe("Podman pod create", func() {
check1.WaitWithDefaultTimeout()
Expect(check1.ExitCode()).To(Equal(0))
Expect(check1.OutputToString()).To(Equal("/pause"))
+
+ // check the Path and Args
+ check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
+ check2.WaitWithDefaultTimeout()
+ Expect(check2.ExitCode()).To(Equal(0))
+ Expect(check2.OutputToString()).To(Equal("/pause:[/pause]"))
})
It("podman create pod with --infra-command", func() {
@@ -362,6 +368,12 @@ var _ = Describe("Podman pod create", func() {
check1.WaitWithDefaultTimeout()
Expect(check1.ExitCode()).To(Equal(0))
Expect(check1.OutputToString()).To(Equal("/pause1"))
+
+ // check the Path and Args
+ check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
+ check2.WaitWithDefaultTimeout()
+ Expect(check2.ExitCode()).To(Equal(0))
+ Expect(check2.OutputToString()).To(Equal("/pause1:[/pause1]"))
})
It("podman create pod with --infra-image", func() {
@@ -383,6 +395,12 @@ entrypoint ["/fromimage"]
check1.WaitWithDefaultTimeout()
Expect(check1.ExitCode()).To(Equal(0))
Expect(check1.OutputToString()).To(Equal("/fromimage"))
+
+ // check the Path and Args
+ check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
+ check2.WaitWithDefaultTimeout()
+ Expect(check2.ExitCode()).To(Equal(0))
+ Expect(check2.OutputToString()).To(Equal("/fromimage:[/fromimage]"))
})
It("podman create pod with --infra-command --infra-image", func() {
@@ -404,5 +422,11 @@ entrypoint ["/fromimage"]
check1.WaitWithDefaultTimeout()
Expect(check1.ExitCode()).To(Equal(0))
Expect(check1.OutputToString()).To(Equal("/fromcommand"))
+
+ // check the Path and Args
+ check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
+ check2.WaitWithDefaultTimeout()
+ Expect(check2.ExitCode()).To(Equal(0))
+ Expect(check2.OutputToString()).To(Equal("/fromcommand:[/fromcommand]"))
})
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index cbfb6bf59..4376bf309 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -733,23 +733,85 @@ USER mail`
err := os.MkdirAll(vol, 0755)
Expect(err).To(BeNil())
- volFile := filepath.Join(vol, "test.txt")
+ filename := "test.txt"
+ volFile := filepath.Join(vol, filename)
data := "Testing --volumes-from!!!"
err = ioutil.WriteFile(volFile, []byte(data), 0755)
Expect(err).To(BeNil())
+ mountpoint := "/myvol/"
- session := podmanTest.Podman([]string{"create", "--volume", vol + ":/myvol", redis, "sh"})
+ session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ctrID := session.OutputToString()
- session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "echo", "'testing read-write!' >> myvol/test.txt"})
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "cat", mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(data))
- session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z", ALPINE, "ls"})
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "sh", "-c", "echo test >> " + mountpoint + filename})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"start", "--attach", ctrID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(data + "test"))
+ })
+
+ It("podman run --volumes-from flag options", func() {
+ vol := filepath.Join(podmanTest.TempDir, "vol-test")
+ err := os.MkdirAll(vol, 0755)
+ Expect(err).To(BeNil())
+
+ filename := "test.txt"
+ volFile := filepath.Join(vol, filename)
+ data := "Testing --volumes-from!!!"
+ err = ioutil.WriteFile(volFile, []byte(data), 0755)
+ Expect(err).To(BeNil())
+ mountpoint := "/myvol/"
+
+ session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ctrID := session.OutputToString()
+
+ // check that the read only option works
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro", ALPINE, "touch", mountpoint + "abc.txt"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system"))
+
+ // check that both z and ro options work
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,z", ALPINE, "cat", mountpoint + filename})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(Equal(data))
+
+ // check that multiple ro/rw are not working
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,rw", ALPINE, "cat", mountpoint + filename})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("cannot set ro or rw options more than once"))
+
+ // check that multiple z options are not working
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z,z,ro", ALPINE, "cat", mountpoint + filename})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("cannot set :z more than once in mount options"))
+
+ // create new read only volume
+ session = podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":ro", ALPINE, "cat", mountpoint + filename})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ctrID = session.OutputToString()
+
+ // check if the original volume was mounted as read only that --volumes-from also mount it as read only
+ session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "touch", mountpoint + "abc.txt"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system"))
})
It("podman run --volumes-from flag with built-in volumes", func() {