summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml36
-rwxr-xr-xAPI.md71
-rw-r--r--Makefile2
-rw-r--r--changelog.txt202
-rw-r--r--cmd/podman/cliconfig/config.go4
-rw-r--r--cmd/podman/commands.go2
-rw-r--r--cmd/podman/container.go2
-rw-r--r--cmd/podman/main_remote.go20
-rw-r--r--cmd/podman/ps.go2
-rw-r--r--cmd/podman/shared/intermediate_varlink.go3
-rw-r--r--cmd/podman/varlink.go34
-rw-r--r--cmd/podman/varlink/io.podman.varlink5
-rwxr-xr-xcontrib/cirrus/rootless_test.sh2
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--docs/podman-create.1.md67
-rw-r--r--docs/podman-run.1.md67
-rw-r--r--docs/podman-varlink.1.md19
-rwxr-xr-xhack/tree_status.sh4
-rw-r--r--libpod/container_internal.go2
-rw-r--r--libpod/lock/in_memory_locks.go16
-rw-r--r--libpod/lock/lock.go7
-rw-r--r--libpod/lock/shm/shm_lock.c55
-rw-r--r--libpod/lock/shm/shm_lock.go17
-rw-r--r--libpod/lock/shm/shm_lock.h1
-rw-r--r--libpod/lock/shm_lock_manager_linux.go19
-rw-r--r--libpod/pod_internal.go2
-rw-r--r--libpod/runtime.go2
-rw-r--r--libpod/runtime_pod_linux.go126
-rw-r--r--pkg/adapter/client.go35
-rw-r--r--pkg/adapter/client_config.go4
-rw-r--r--pkg/adapter/containers.go5
-rw-r--r--pkg/adapter/containers_remote.go35
-rw-r--r--pkg/adapter/errors.go31
-rw-r--r--pkg/adapter/info_remote.go7
-rw-r--r--pkg/adapter/pods_remote.go6
-rw-r--r--pkg/adapter/runtime_remote.go13
-rw-r--r--pkg/systemdgen/systemdgen_test.go120
-rw-r--r--pkg/varlinkapi/attach.go1
-rw-r--r--pkg/varlinkapi/containers.go17
-rw-r--r--pkg/varlinkapi/pods.go6
-rw-r--r--pkg/varlinkapi/system.go17
-rw-r--r--test/e2e/common_test.go7
-rw-r--r--test/e2e/create_test.go2
-rw-r--r--test/e2e/diff_test.go3
-rw-r--r--test/e2e/info_test.go1
-rw-r--r--test/e2e/kill_test.go2
-rw-r--r--test/e2e/libpod_suite_remoteclient_test.go74
-rw-r--r--test/e2e/libpod_suite_test.go3
-rw-r--r--test/e2e/logs_test.go2
-rw-r--r--test/e2e/negative_test.go38
-rw-r--r--test/e2e/pod_create_test.go2
-rw-r--r--test/e2e/pod_inspect_test.go2
-rw-r--r--test/e2e/pod_kill_test.go2
-rw-r--r--test/e2e/pod_pause_test.go2
-rw-r--r--test/e2e/pod_prune_test.go2
-rw-r--r--test/e2e/pod_ps_test.go2
-rw-r--r--test/e2e/pod_restart_test.go2
-rw-r--r--test/e2e/pod_rm_test.go2
-rw-r--r--test/e2e/pod_start_test.go2
-rw-r--r--test/e2e/pod_stop_test.go2
-rw-r--r--test/e2e/ps_test.go2
-rw-r--r--test/e2e/refresh_test.go74
-rw-r--r--test/e2e/rm_test.go2
-rw-r--r--test/e2e/run_test.go1
-rw-r--r--test/e2e/save_test.go10
-rw-r--r--test/e2e/stop_test.go2
-rw-r--r--test/e2e/tag_test.go2
-rw-r--r--test/e2e/wait_test.go2
-rw-r--r--test/utils/utils.go6
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/varlink/go/varlink/bridge.go11
-rw-r--r--vendor/github.com/varlink/go/varlink/bridge_windows.go11
-rw-r--r--version/version.go2
73 files changed, 1047 insertions, 320 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 0745b1e7b..514889969 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -176,10 +176,40 @@ vendor_task:
failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh |& ${TIMESTAMP}'
+# This task runs `make varlink_api_generate` followed by ./hack/tree_status.sh to check
+# whether the git tree is clean.
+varlink_api_task:
+
+ depends_on:
+ - "gating"
+
+ env:
+ CIRRUS_WORKING_DIR: "/usr/src/libpod"
+ # Used by tree_status.sh
+ SUGGESTION: 'remove API.md, then "make varlink_api_generate" and commit changes.'
+
+ # Runs within Cirrus's "community cluster"
+ container:
+ image: "quay.io/libpod/gate:latest"
+ cpu: 4
+ memory: 12
+
+ timeout_in: 10m
+
+ vendor_script:
+ - '/usr/local/bin/entrypoint.sh varlink_api_generate'
+ - 'cd /go/src/github.com/containers/libpod && ./hack/tree_status.sh'
+
+ on_failure:
+ failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
+
+
build_each_commit_task:
depends_on:
- "gating"
+ - "vendor"
+ - "varlink_api"
# $CIRRUS_BASE_BRANCH is only set when testing a PR
only_if: $CIRRUS_BRANCH != 'master'
@@ -232,6 +262,8 @@ testing_task:
depends_on:
- "gating"
+ - "varlink_api"
+ - "vendor"
- "build_each_commit"
gce_instance:
@@ -275,6 +307,8 @@ special_testing_task:
depends_on:
- "gating"
+ - "varlink_api"
+ - "vendor"
- "build_each_commit"
gce_instance:
@@ -388,6 +422,8 @@ success_task:
depends_on: # ignores any dependent task conditions
- "gating"
+ - "varlink_api"
+ - "vendor"
- "build_each_commit_task"
- "testing"
- "rootless_testing_task"
diff --git a/API.md b/API.md
index 738449f43..db84f695c 100755
--- a/API.md
+++ b/API.md
@@ -45,6 +45,10 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func ExportImage(name: string, destination: string, compress: bool, tags: []string) string](#ExportImage)
+[func GenerateKube(name: string, service: bool) KubePodService](#GenerateKube)
+
+[func GenerateSystemd(name: string, restart: string, timeout: int, useName: bool) string](#GenerateSystemd)
+
[func GetAttachSockets(name: string) Sockets](#GetAttachSockets)
[func GetContainer(id: string) Container](#GetContainer)
@@ -57,6 +61,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func GetContainersByContext(all: bool, latest: bool, args: []string) []string](#GetContainersByContext)
+[func GetContainersByStatus(status: []string) Container](#GetContainersByStatus)
+
[func GetContainersLogs(names: []string, follow: bool, latest: bool, since: string, tail: int, timestamps: bool) LogLine](#GetContainersLogs)
[func GetEvents(filter: []string, since: string, until: string) Event](#GetEvents)
@@ -73,6 +79,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func GetPodsByContext(all: bool, latest: bool, args: []string) []string](#GetPodsByContext)
+[func GetPodsByStatus(statuses: []string) []string](#GetPodsByStatus)
+
[func GetVersion() string, string, string, string, string, int](#GetVersion)
[func GetVolumes(args: []string, all: bool) Volume](#GetVolumes)
@@ -87,6 +95,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func ImportImage(source: string, reference: string, message: string, changes: []string, delete: bool) string](#ImportImage)
+[func InitContainer(name: string) string](#InitContainer)
+
[func InspectContainer(name: string) string](#InspectContainer)
[func InspectImage(name: string) string](#InspectImage)
@@ -153,6 +163,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func TagImage(name: string, tagged: string) string](#TagImage)
+[func Top(nameOrID: string, descriptors: []string) []string](#Top)
+
[func TopPod(pod: string, latest: bool, descriptors: []string) []string](#TopPod)
[func UnmountContainer(name: string, force: bool) ](#UnmountContainer)
@@ -211,6 +223,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[type InfoStore](#InfoStore)
+[type KubePodService](#KubePodService)
+
[type ListPodContainerInfo](#ListPodContainerInfo)
[type ListPodData](#ListPodData)
@@ -245,10 +259,14 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[error ContainerNotFound](#ContainerNotFound)
+[error ErrCtrStopped](#ErrCtrStopped)
+
[error ErrorOccurred](#ErrorOccurred)
[error ImageNotFound](#ImageNotFound)
+[error InvalidState](#InvalidState)
+
[error NoContainerRunning](#NoContainerRunning)
[error NoContainersInPod](#NoContainersInPod)
@@ -445,6 +463,17 @@ a booleon option to force compression. It also takes in a string array of tags
tags of the same image to a tarball (each tag should be of the form <image>:<tag>). Upon completion, the ID
of the image is returned. If the image cannot be found in local storage, an [ImageNotFound](#ImageNotFound)
error will be returned. See also [ImportImage](ImportImage).
+### <a name="GenerateKube"></a>func GenerateKube
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method GenerateKube(name: [string](https://godoc.org/builtin#string), service: [bool](https://godoc.org/builtin#bool)) [KubePodService](#KubePodService)</div>
+GenerateKube generates a Kubernetes v1 Pod description of a Podman container or pod
+and its containers. The description is in YAML. See also [ReplayKube](ReplayKube).
+### <a name="GenerateSystemd"></a>func GenerateSystemd
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method GenerateSystemd(name: [string](https://godoc.org/builtin#string), restart: [string](https://godoc.org/builtin#string), timeout: [int](https://godoc.org/builtin#int), useName: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
+
### <a name="GetAttachSockets"></a>func GetAttachSockets
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -522,6 +551,11 @@ method GetContainersByContext(all: [bool](https://godoc.org/builtin#bool), lates
GetContainersByContext allows you to get a list of container ids depending on all, latest, or a list of
container names. The definition of latest container means the latest by creation date. In a multi-
user environment, results might differ from what you expect.
+### <a name="GetContainersByStatus"></a>func GetContainersByStatus
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method GetContainersByStatus(status: [[]string](#[]string)) [Container](#Container)</div>
+
### <a name="GetContainersLogs"></a>func GetContainersLogs
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -621,6 +655,11 @@ method GetPodsByContext(all: [bool](https://godoc.org/builtin#bool), latest: [bo
GetPodsByContext allows you to get a list pod ids depending on all, latest, or a list of
pod names. The definition of latest pod means the latest by creation date. In a multi-
user environment, results might differ from what you expect.
+### <a name="GetPodsByStatus"></a>func GetPodsByStatus
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method GetPodsByStatus(statuses: [[]string](#[]string)) [[]string](#[]string)</div>
+GetPodsByStatus searches for pods whose status is included in statuses
### <a name="GetVersion"></a>func GetVersion
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -669,6 +708,16 @@ the IDs of the removed images are returned.
method ImportImage(source: [string](https://godoc.org/builtin#string), reference: [string](https://godoc.org/builtin#string), message: [string](https://godoc.org/builtin#string), changes: [[]string](#[]string), delete: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div>
ImportImage imports an image from a source (like tarball) into local storage. The image can have additional
descriptions added to it using the message and changes options. See also [ExportImage](ExportImage).
+### <a name="InitContainer"></a>func InitContainer
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method InitContainer(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
+InitContainer initializes the given container. It accepts a container name or
+ID, and will initialize the container matching that ID if possible, and error
+if not. Containers can only be initialized when they are in the Created or
+Exited states. Initialization prepares a container to be started, but does not
+start the container. It is intended to be used to debug a container's state
+prior to starting it.
### <a name="InspectContainer"></a>func InspectContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -1039,6 +1088,11 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.StopPod '{"name": "135d71
method TagImage(name: [string](https://godoc.org/builtin#string), tagged: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div>
TagImage takes the name or ID of an image in local storage as well as the desired tag name. If the image cannot
be found, an [ImageNotFound](#ImageNotFound) error will be returned; otherwise, the ID of the image is returned on success.
+### <a name="Top"></a>func Top
+<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
+
+method Top(nameOrID: [string](https://godoc.org/builtin#string), descriptors: [[]string](#[]string)) [[]string](#[]string)</div>
+
### <a name="TopPod"></a>func TopPod
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
@@ -1445,6 +1499,8 @@ quiet [](#)
readonly [](#)
+readonlytmpfs [](#)
+
restart [](#)
rm [](#)
@@ -1666,6 +1722,13 @@ graph_root [string](https://godoc.org/builtin#string)
graph_status [InfoGraphStatus](#InfoGraphStatus)
run_root [string](https://godoc.org/builtin#string)
+### <a name="KubePodService"></a>type KubePodService
+
+
+
+pod [string](https://godoc.org/builtin#string)
+
+service [string](https://godoc.org/builtin#string)
### <a name="ListPodContainerInfo"></a>type ListPodContainerInfo
ListPodContainerInfo is a returned struct for describing containers
@@ -1917,6 +1980,9 @@ force [bool](https://godoc.org/builtin#bool)
### <a name="ContainerNotFound"></a>type ContainerNotFound
ContainerNotFound means the container could not be found by the provided name or ID in local storage.
+### <a name="ErrCtrStopped"></a>type ErrCtrStopped
+
+Container is already stopped
### <a name="ErrorOccurred"></a>type ErrorOccurred
ErrorOccurred is a generic error for an error that occurs during the execution. The actual error message
@@ -1924,6 +1990,9 @@ is includes as part of the error's text.
### <a name="ImageNotFound"></a>type ImageNotFound
ImageNotFound means the image could not be found by the provided name or ID in local storage.
+### <a name="InvalidState"></a>type InvalidState
+
+InvalidState indicates that a container or pod was in an improper state for the requested operation
### <a name="NoContainerRunning"></a>type NoContainerRunning
NoContainerRunning means none of the containers requested are running in a command that requires a running container.
@@ -1933,7 +2002,7 @@ NoContainersInPod means a pod has no containers on which to perform the operatio
the pod ID.
### <a name="PodContainerError"></a>type PodContainerError
-PodContainerError means a container associated with a pod failed to preform an operation. It contains
+PodContainerError means a container associated with a pod failed to perform an operation. It contains
a container ID of the container that failed.
### <a name="PodNotFound"></a>type PodNotFound
diff --git a/Makefile b/Makefile
index 0085537d0..86d0d99d2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
GO ?= go
DESTDIR ?= /
-EPOCH_TEST_COMMIT ?= 7b7397481960c85379d8eb1ed21e76da2ce8a4fc
+EPOCH_TEST_COMMIT ?= a9fc570dd844bf1ebd1f106f1b8091882b4a2b29
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
diff --git a/changelog.txt b/changelog.txt
index 92a17f8d0..c72117d7f 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,205 @@
+- Changelog for v1.3.0 (2019-05-06)
+ * Update release notes for 1.3.0 release
+ * Bump to Buildah v1.8.2
+ * Document events logger options in libpod.conf manpage
+ * Try and fix restart-policy tests
+ * fix logout message if login only with docker
+ * Fix manpage typos
+ * Small code fix
+ * Fix 'restart' event in journald
+ * change from sysregistries to sysregistriesv2
+ * Address review comments on restart policy
+ * Add a test for restart policy
+ * Add a restart event, and make one during restart policy
+ * Restart policy should not run if a container is running
+ * Restart policy conflicts with the --rm flag
+ * Move to using constants for valid restart policy types
+ * Add manpage information for restart policy
+ * Add support for retry count with --restart flag
+ * Sending signals to containers prevents restart policy
+ * Add container restart policy to Libpod & Podman
+ * Add a StoppedByUser field to the DB
+ * top: fallback to execing ps(1)
+ * clean up shared/parse/parse.go
+ * Generate systemd unit files for containers
+ * Fix podman-in-podman volume test
+ * Cirrus: Add pipefail confirmation check
+ * Cirrus: timestamp all output script output
+ * Update c/storage to v1.12.6
+ * Fix typo in init manpage
+ * Add an InvalidState varlink error for Init
+ * Bump Buildah to v1.8.1, ImageBuilder to v1.1.0
+ * Add variable for global flags to runlabel
+ * docs: Fix typo "healthcheck" pt2
+ * cirrus lib.sh: refactor req_env_var()
+ * Remove two bits of dead code
+ * http-proxy: improve docs
+ * Small fixes for #2950
+ * container: drop rootless check
+ * Add basic structure of podman init command
+ * Move handling of ReadOnlyTmpfs into new mounts code
+ * Begin adding volume tests
+ * Ensure that named volumes have their options parsed
+ * Add options parsing for tmpfs mounts
+ * Use EqualValues instead of reflect equality
+ * Hit a number of to-do comments in unified volumes code
+ * Fix options for non-bind and non-tmpfs volumes
+ * Migrate unit tests from cmd/podman into pkg/spec
+ * Migrate to unified volume handling code
+ * Always pass pod into MakeContainerConfig
+ * Remove non-config fields from CreateConfig
+ * Add a new function for converting a CreateConfig
+ * podman-remote port
+ * install.md contains hints for rootless setup on arch linux
+ * auto pass http_proxy into container
+ * enable podman-remote on windows
+ * Use 'sudo tee' in tutorial so install works as non-root
+ * Refactor container cleanup to use latest functions
+ * Move --mount in run man page
+ * Add details on rootless Podman to the readme
+ * podman-remote stop
+ * correct upstream vndr issues
+ * runtime: pass down the context
+ * system: add new subcommand "migrate"
+ * Vendor in latest buildah code
+ * remove manual install of libsystemd-dev
+ * Vendor in latest containers/storage
+ * Add --read-only-tmpfs options
+ * Fix remote-client testing reports
+ * podman-remote prune containers
+ * Do not hard fail on non-decodable events
+ * update psgo to v1.2.1
+ * Add System event type and renumber, refresh events
+ * enable podman remote top
+ * fix login supports credHelpers config
+ * Cirrus: Collect audit log on success and failure
+ * Add a debug message indicating that a refresh occurred
+ * image: rework parent/child/history matching
+ * images: add context to GetParent/IsParent/Remove/Prune...
+ * build podman-remote with Dockerfile.
+ * point to 3rd party tools for `docker-compose` format
+ * Update vendor of container/storage
+ * journald event logging
+ * podman remote-client restart containers
+ * Cirrus: Use freshly built images
+ * Cirrus: Bump up runc commit
+ * Cirrus: fix obsolete Ubuntu package
+ * Cirrus: Install libsystemd-dev on Ubuntu
+ * pull: special case all-tags semantics
+ * Fix test compile
+ * Trim whitespace from ps -q before comparing
+ * Enhance tests for stop to check results
+ * Add extra CI tests for stopping all containers
+ * Fix podman stop --all attempting to stop created ctrs
+ * Cirrus: Temp. override container-selinux on F29
+ * Refactor of 'podman prune' to better support remote
+ * bats - various small updates
+ * podman-remote pause|unpause
+ * Internal names do not match external names
+ * Add header to play kube output
+ * Clean up after play kube failure
+ * rootless: not close more FDs than needed
+ * Fix COPR builds to start working again
+ * Fix podman command --change CMD
+ * podman-remote start
+ * Vendor in latest Buildah
+ * Added remote pod prune
+ * Add podman pod prune
+ * podman-remote container commands
+ * Fix segfaults attribute to missing options
+ * Call the runtime with WithRenumber() when asked
+ * Add File mounts to play kube
+ * cmd, pkg: drop commented code
+ * pod: drop dead code
+ * rootless, mount: not create namespace
+ * Incorporate image and default environment variables in play kube
+ * Validate ENV/LABEL Change options in varlink
+ * oci: fix umount of /sys/kernel
+ * Revert "rootless: set controlling terminal for podman in the userns"
+ * Remove old crio reference from man pages
+ * create: fix segfault if container name already exists
+ * adding uidmap to install steps for ubuntu
+ * podman-remote generate kube
+ * rootless: do not block SIGTSTP
+ * rootless: set controlling terminal for podman in the userns
+ * Use GetContainer instead of LookupContainer for full ID
+ * pull: exit with error if the image is not found
+ * Use the same SELinux label for CRIU log files
+ * pull: remove cryptic error message
+ * new uidmap BATS test: fix
+ * adding additional update, needed for install
+ * Fix README.md -> rootless.md link
+ * Fixes for podman-remote run and attach
+ * remote-client checkpoint/restore
+ * Expand debugging for container cleanup errors
+ * spec: mask /sys/kernel when bind mounting /sys
+ * Add --include-volumes flag to 'podman commit'
+ * oci: add /sys/kernel to the masked paths
+ * userns: prevent /sys/kernel/* paths in the container
+ * imagefilter dangling handling corrected
+ * rootless: fix segfault on refresh if there are containers
+ * Add demo script and cast to images
+ * Initial remote flag clean up
+ * (minor): fix misspelled 'Healthcheck'
+ * BATS tests: start supporting podman-remote
+ * Add the ability to attach remotely to a container
+ * Print header for 'podman images' even with no images
+ * podman-remote ps
+ * Re-run (make vendor) to drop the now unnecessary collation code and tables
+ * Potentially breaking: Make hooks sort order locale-independent
+ * Implement podman-remote rm
+ * ps: now works with --size and nonroot
+ * Update invalid name errors to report the correct regex
+ * cirrus: enable remote tests for rootless
+ * test: fix remote tests for rootless
+ * test: enable userns e2e tests for rootless
+ * CI check for --help vs man pages: usability fix
+ * podman-remote create|run
+ * Correct varlink pull panic
+ * add image rmi event
+ * Revert "Switch to golangci-lint"
+ * Document shortcomings with rootless podman
+ * podman: enable kube for rootless
+ * kube: correctly set the default for MemorySwappiness
+ * rootless: enable healthcheck tests
+ * Respect image entrypoint in play kube
+ * Increase CI resources to help avoid hitting timeouts
+ * podman-remote image tree
+ * Added port forwarding and IP address hint.
+ * fix bug podman cp directory
+ * Fix E2E tests
+ * Drop LocalVolumes from our the database
+ * Major rework of --volumes-from flag
+ * Volume force-remove now removed dependent containers
+ * Add handling for new named volumes code in pkg/spec
+ * Create non-existing named volumes at container create
+ * Switch Libpod over to new explicit named volumes
+ * Add named volumes for each container to database
+ * Add varcheck linter
+ * Add deadcode linter
+ * Update lint to use golangci-lint
+ * Update registrar unit tests to match them of cri-o
+ * Update run tests to be skipped when not supported
+ * Fix Dockerfile dependencies for packer tests
+ * Update Dockerfile to use golang:1.12 image
+ * Fix a potential segfault in podman search
+ * Improve podman pod rm -a test
+ * Cirrus: Update F28 -> F29 container image
+ * --size does not work with rootless at present
+ * add remote-client diff
+ * Cirrus: Support special-case modes of testing
+ * rootless: use a single user namespace
+ * rootless: remove SkipStorageSetup()
+ * Update cri-o annotations
+ * Update README with current version
+ * docs/podman*.md: fix numerous option typos and spacing errors
+ * docs/podman-rm.1.md: delete "Not yet implemented" msg for volume removal
+ * docs/podman-inspect.1.md: add missing option hyphen for "-t"
+ * Bump gitvalidation epoch
+ * Bump to v1.3.0-dev
+ * Fix location of libpod.conf
+ * Capitalize global options help information
+
- Changelog for v1.2.0 (2019-03-30)
* Update release notes for v1.2.0
* Remove wait event
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index b770aaca0..aaa4513d8 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -32,6 +32,10 @@ type MainFlags struct {
CpuProfile string
LogLevel string
TmpDir string
+
+ RemoteUserName string
+ RemoteHost string
+ VarlinkAddress string
}
type AttachValues struct {
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 14451d944..3a409f503 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -39,13 +39,11 @@ func getImageSubCommands() []*cobra.Command {
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{
- _checkpointCommand,
_cleanupCommand,
_commitCommand,
_execCommand,
_mountCommand,
_refreshCommand,
- _restoreCommand,
_runlabelCommand,
_statsCommand,
_umountCommand,
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index bbf01d1f8..530175a55 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -51,6 +51,7 @@ var (
// Commands that are universally implemented.
containerCommands = []*cobra.Command{
_attachCommand,
+ _checkpointCommand,
_containerExistsCommand,
_contInspectSubCommand,
_diffCommand,
@@ -64,6 +65,7 @@ var (
_portCommand,
_pruneContainersCommand,
_restartCommand,
+ _restoreCommand,
_runCommand,
_rmCommand,
_startCommand,
diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go
index a3335050a..c8bb3ad3e 100644
--- a/cmd/podman/main_remote.go
+++ b/cmd/podman/main_remote.go
@@ -3,17 +3,17 @@
package main
import (
- "os"
-
- "github.com/containers/libpod/pkg/rootless"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
const remote = true
func init() {
- // remote client specific flags can go here.
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteUserName, "username", "", "username on the remote host")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteHost, "remote-host", "", "remote host")
+ // TODO maybe we allow the altering of this for bridge connections?
+ //rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.VarlinkAddress, "varlink-address", adapter.DefaultAddress, "address of the varlink socket")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", "Log messages above specified level: debug, info, warn, error, fatal or panic")
}
func setSyslog() error {
@@ -29,16 +29,6 @@ func profileOff(cmd *cobra.Command) error {
}
func setupRootless(cmd *cobra.Command, args []string) error {
- if rootless.IsRootless() {
- became, ret, err := rootless.BecomeRootInUserNS()
- if err != nil {
- logrus.Errorf(err.Error())
- os.Exit(1)
- }
- if became {
- os.Exit(ret)
- }
- }
return nil
}
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index 623f17050..eb5181126 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -497,7 +497,7 @@ func psDisplay(c *cliconfig.PsValues, runtime *adapter.LocalRuntime) error {
} else {
// Print namespace information
- ns := shared.GetNamespaces(container.Pid)
+ ns := runtime.GetNamespaces(container)
fmt.Fprintf(w, "\n%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s", container.ID, container.Names, container.Pid, ns.Cgroup, ns.IPC, ns.MNT, ns.NET, ns.PIDNS, ns.User, ns.UTS)
}
diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go
index 5e21245e3..4742d4909 100644
--- a/cmd/podman/shared/intermediate_varlink.go
+++ b/cmd/podman/shared/intermediate_varlink.go
@@ -3,8 +3,6 @@
package shared
import (
- "fmt"
-
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/varlink"
"github.com/containers/libpod/pkg/rootless"
@@ -209,7 +207,6 @@ func boolFromVarlink(v *bool, flagName string, defaultValue bool) CRBool {
cr.Val = defaultValue
cr.Changed = false
} else {
- fmt.Println(flagName, cr.Val)
cr.Val = *v
cr.Changed = true
}
diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go
index 978678a84..215542d2c 100644
--- a/cmd/podman/varlink.go
+++ b/cmd/podman/varlink.go
@@ -3,11 +3,17 @@
package main
import (
+ "fmt"
+ "os"
+ "path/filepath"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
iopodman "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/libpod/pkg/varlinkapi"
"github.com/containers/libpod/version"
"github.com/pkg/errors"
@@ -45,13 +51,31 @@ func init() {
}
func varlinkCmd(c *cliconfig.VarlinkValues) error {
- args := c.InputArgs
- if len(args) < 1 {
- return errors.Errorf("you must provide a varlink URI")
+ varlinkURI := adapter.DefaultAddress
+ if rootless.IsRootless() {
+ xdg, err := util.GetRootlessRuntimeDir()
+ if err != nil {
+ return err
+ }
+ socketDir := filepath.Join(xdg, "podman/io.podman")
+ if _, err := os.Stat(filepath.Dir(socketDir)); os.IsNotExist(err) {
+ if err := os.Mkdir(filepath.Dir(socketDir), 0755); err != nil {
+ return err
+ }
+ }
+ varlinkURI = fmt.Sprintf("unix:%s", socketDir)
}
+ args := c.InputArgs
+
if len(args) > 1 {
- return errors.Errorf("too many arguments. Requires exactly 1")
+ return errors.Errorf("too many arguments. you may optionally provide 1")
+ }
+
+ if len(args) > 0 {
+ varlinkURI = args[0]
}
+
+ logrus.Debugf("Using varlink socket: %s", varlinkURI)
timeout := time.Duration(c.Timeout) * time.Millisecond
// Create a single runtime for varlink
@@ -81,7 +105,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error {
}
// Run the varlink server at the given address
- if err = service.Listen(args[0], timeout); err != nil {
+ if err = service.Listen(varlinkURI, timeout); err != nil {
switch err.(type) {
case varlink.ServiceTimeoutError:
logrus.Infof("varlink service expired (use --timeout to increase session time beyond %d ms, 0 means never timeout)", c.Int64("timeout"))
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index ace81646c..faaecdb6b 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -1254,4 +1254,7 @@ error ErrorOccurred (reason: string)
error RuntimeError (reason: string)
# The Podman endpoint requires that you use a streaming connection.
-error WantsMoreRequired (reason: string) \ No newline at end of file
+error WantsMoreRequired (reason: string)
+
+# Container is already stopped
+error ErrCtrStopped (id: string)
diff --git a/contrib/cirrus/rootless_test.sh b/contrib/cirrus/rootless_test.sh
index 8351214f3..eab06bac0 100755
--- a/contrib/cirrus/rootless_test.sh
+++ b/contrib/cirrus/rootless_test.sh
@@ -14,8 +14,6 @@ then
exit 1
fi
-export PODMAN_VARLINK_ADDRESS=unix:/tmp/podman-$(id -u)
-
echo "."
echo "Hello, my name is $USER and I live in $PWD can I be your friend?"
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index f3ee01bca..d69b673e0 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -39,7 +39,7 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
-Version: 1.3.0
+Version: 1.3.1
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 3a44c70af..cf36106e8 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -244,26 +244,6 @@ inside of the container.
Read in a line delimited file of environment variables
-**--http-proxy**=*true*|*false*
-
-By default proxy environment variables are passed into the container if set
-for the podman process. This can be disabled by setting the `--http-proxy`
-option to `false`. The environment variables passed in include `http_proxy`,
-`https_proxy`, `ftp_proxy`, `no_proxy`, and also the upper case versions of
-those. This option is only needed when the host system must use a proxy but
-the container should not use any proxy. Proxy environment variables specified
-for the container in any other way will override the values that would have
-been passed thru from the host. (Other ways to specify the proxy for the
-container include passing the values with the `--env` flag, or hardcoding the
-proxy environment at container build time.)
-
-For example, to disable passing these environment variables from host to
-container:
-
-`--http-proxy=false`
-
-Defaults to `true`
-
**--expose**=[]
Expose a port, or a range of ports (e.g. --expose=3300-3310) to set up port redirection
@@ -281,20 +261,27 @@ Add additional groups to run as
**--healthcheck**=""
-Set or alter a healthcheck for a container. The value must be of the format of:
+Set or alter a healthcheck command for a container. The command is a command to be executed inside your
+container that determines your container health. The command is required for other healthcheck options
+to be applied. A value of `none` disables existing healthchecks.
+
+**--healthcheck-interval**=""
+
+Set an interval for the healthchecks (a value of `disable` results in no automatic timer setup) (default "30s")
- `[OPTIONS] CMD command`
+**--healthcheck-retries=**
- where options can be any of the follow:
- * --interval=DURATION (default: 30s)
- * --timeout=DURATION (default: 30s)
- * --start-period=DURATION (default: 0s)
- * --retries=N (default: 3)
+The number of retries allowed before a healthcheck is considered to be unhealthy. The default value is `3`.
-Note: options are *not* required.
+**--healthcheck-start-period**=""
-The command is a command to be executed inside your container that determines your container health. The
-command is required.
+The initialization time needed for a container to bootstrap. The value can be expressed in time format like
+`2m3s`. The default value is `0s`
+
+**--healthcheck-timeout**=""
+
+The maximum time allowed to complete the healthcheck before an interval is considered failed. Like start-period, the
+value can be expressed in a time format such as `1m22s`. The default value is `30s`.
**--hostname**=""
@@ -306,6 +293,26 @@ Sets the container host name that is available inside the container.
Print usage statement
+**--http-proxy**=*true*|*false*
+
+By default proxy environment variables are passed into the container if set
+for the podman process. This can be disabled by setting the `--http-proxy`
+option to `false`. The environment variables passed in include `http_proxy`,
+`https_proxy`, `ftp_proxy`, `no_proxy`, and also the upper case versions of
+those. This option is only needed when the host system must use a proxy but
+the container should not use any proxy. Proxy environment variables specified
+for the container in any other way will override the values that would have
+been passed thru from the host. (Other ways to specify the proxy for the
+container include passing the values with the `--env` flag, or hardcoding the
+proxy environment at container build time.)
+
+For example, to disable passing these environment variables from host to
+container:
+
+`--http-proxy=false`
+
+Defaults to `true`
+
**--image-volume**, **builtin-volume**=*bind*|*tmpfs*|*ignore*
Tells podman how to handle the builtin image volumes. The options are: 'bind', 'tmpfs', or 'ignore' (default 'bind').
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index a200b12fb..1840e0f0b 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -251,26 +251,6 @@ inside of the container.
Read in a line delimited file of environment variables
-**--http-proxy**=*true*|*false*
-
-By default proxy environment variables are passed into the container if set
-for the podman process. This can be disabled by setting the `--http-proxy`
-option to `false`. The environment variables passed in include `http_proxy`,
-`https_proxy`, `ftp_proxy`, `no_proxy`, and also the upper case versions of
-those. This option is only needed when the host system must use a proxy but
-the container should not use any proxy. Proxy environment variables specified
-for the container in any other way will override the values that would have
-been passed thru from the host. (Other ways to specify the proxy for the
-container include passing the values with the `--env` flag, or hardcoding the
-proxy environment at container build time.)
-
-For example, to disable passing these environment variables from host to
-container:
-
-`--http-proxy=false`
-
-Defaults to `true`
-
**--expose**=[]
Expose a port, or a range of ports (e.g. --expose=3300-3310) to set up port redirection
@@ -289,20 +269,27 @@ Add additional groups to run as
**--healthcheck**=""
-Set or alter a healthcheck for a container. The value must be of the format of:
+Set or alter a healthcheck command for a container. The command is a command to be executed inside your
+container that determines your container health. The command is required for other healthcheck options
+to be applied. A value of `none` disables existing healthchecks.
+
+**--healthcheck-interval**=""
+
+Set an interval for the healthchecks (a value of `disable` results in no automatic timer setup) (default "30s")
- `[OPTIONS] CMD command`
+**--healthcheck-retries=**
- where options can be any of the follow:
- * --interval=DURATION (default: 30s)
- * --timeout=DURATION (default: 30s)
- * --start-period=DURATION (default: 0s)
- * --retries=N (default: 3)
+The number of retries allowed before a healthcheck is considered to be unhealthy. The default value is `3`.
-Note: options are *not* required.
+**--healthcheck-start-period**=""
-The command is a command to be executed inside your container that determines your container health. The
-command is required.
+The initialization time needed for a container to bootstrap. The value can be expressed in time format like
+`2m3s`. The default value is `0s`
+
+**--healthcheck-timeout**=""
+
+The maximum time allowed to complete the healthcheck before an interval is considered failed. Like start-period, the
+value can be expressed in a time format such as `1m22s`. The default value is `30s`.
**--hostname**=""
@@ -314,6 +301,26 @@ Sets the container host name that is available inside the container.
Print usage statement
+**--http-proxy**=*true*|*false*
+
+By default proxy environment variables are passed into the container if set
+for the podman process. This can be disabled by setting the `--http-proxy`
+option to `false`. The environment variables passed in include `http_proxy`,
+`https_proxy`, `ftp_proxy`, `no_proxy`, and also the upper case versions of
+those. This option is only needed when the host system must use a proxy but
+the container should not use any proxy. Proxy environment variables specified
+for the container in any other way will override the values that would have
+been passed thru from the host. (Other ways to specify the proxy for the
+container include passing the values with the `--env` flag, or hardcoding the
+proxy environment at container build time.)
+
+For example, to disable passing these environment variables from host to
+container:
+
+`--http-proxy=false`
+
+Defaults to `true`
+
**--image-volume**, **builtin-volume**=*bind*|*tmpfs*|*ignore*
Tells podman how to handle the builtin image volumes.
diff --git a/docs/podman-varlink.1.md b/docs/podman-varlink.1.md
index 7eeb3dd66..0501d853f 100644
--- a/docs/podman-varlink.1.md
+++ b/docs/podman-varlink.1.md
@@ -7,8 +7,10 @@ podman\-varlink - Runs the varlink backend interface
**podman varlink** [*options*] *uri*
## DESCRIPTION
-Starts the varlink service listening on *uri* that allows varlink clients to interact with podman. This should generally be done
-with systemd. See _Configuration_ below.
+Starts the varlink service listening on *uri* that allows varlink clients to interact with podman. If no *uri* is provided, a default
+URI will be used depending on the user calling the varlink service. The default for the root user is `unix:/run/podman/io.podman`. Regular
+users will have a default *uri* of `$XDG_RUNTIME_DIR/podman/io.podman`. For example, `unix:/run/user/1000/podman/io.podman`
+The varlink service should generally be done with systemd. See _Configuration_ below.
## GLOBAL OPTIONS
@@ -23,16 +25,23 @@ second. A value of `0` means no timeout and the session will not expire.
## EXAMPLES
-Run the podman varlink service manually and accept the default timeout.
+Run the podman varlink service accepting all default options.
```
-$ podman varlink unix:/run/podman/io.podman
+$ podman varlink
+```
+
+
+Run the podman varlink service with an alternate URI and accept the default timeout.
+
+```
+$ podman varlink unix:/tmp/io.podman
```
Run the podman varlink service manually with a 5 second timeout.
```
-$ podman varlink --timeout 5000 unix:/run/podman/io.podman
+$ podman varlink --timeout 5000
```
## CONFIGURATION
diff --git a/hack/tree_status.sh b/hack/tree_status.sh
index 78fb4c6a3..ac874a347 100755
--- a/hack/tree_status.sh
+++ b/hack/tree_status.sh
@@ -1,12 +1,14 @@
#!/bin/bash
set -e
+SUGGESTION="${SUGGESTION:-sync the vendor.conf and commit all changes.}"
+
STATUS=$(git status --porcelain)
if [[ -z $STATUS ]]
then
echo "tree is clean"
else
- echo "tree is dirty, please commit all changes and sync the vendor.conf"
+ echo "tree is dirty, please $SUGGESTION"
echo ""
echo "$STATUS"
exit 1
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 0b4e5763e..e6ffaa6d7 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -516,7 +516,7 @@ func (c *Container) refresh() error {
}
// We need to pick up a new lock
- lock, err := c.runtime.lockManager.RetrieveLock(c.config.LockID)
+ lock, err := c.runtime.lockManager.AllocateAndRetrieveLock(c.config.LockID)
if err != nil {
return errors.Wrapf(err, "error acquiring lock for container %s", c.ID())
}
diff --git a/libpod/lock/in_memory_locks.go b/libpod/lock/in_memory_locks.go
index 7c9605917..f3c842f89 100644
--- a/libpod/lock/in_memory_locks.go
+++ b/libpod/lock/in_memory_locks.go
@@ -90,6 +90,22 @@ func (m *InMemoryManager) RetrieveLock(id uint32) (Locker, error) {
return m.locks[id], nil
}
+// AllocateAndRetrieveLock allocates a lock with the given ID (if not already in
+// use) and returns it.
+func (m *InMemoryManager) AllocateAndRetrieveLock(id uint32) (Locker, error) {
+ if id >= m.numLocks {
+ return nil, errors.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks)
+ }
+
+ if m.locks[id].allocated {
+ return nil, errors.Errorf("given lock ID %d is already in use, cannot reallocate", id)
+ }
+
+ m.locks[id].allocated = true
+
+ return m.locks[id], nil
+}
+
// FreeAllLocks frees all locks.
// This function is DANGEROUS. Please read the full comment in locks.go before
// trying to use it.
diff --git a/libpod/lock/lock.go b/libpod/lock/lock.go
index d6841646b..4e1e2e215 100644
--- a/libpod/lock/lock.go
+++ b/libpod/lock/lock.go
@@ -24,6 +24,13 @@ type Manager interface {
// The underlying lock MUST be the same as another other lock with the
// same UUID.
RetrieveLock(id uint32) (Locker, error)
+ // AllocateAndRetrieveLock marks the lock with the given UUID as in use
+ // and retrieves it.
+ // RetrieveAndAllocateLock will error if the lock in question has
+ // already been allocated.
+ // This is mostly used after a system restart to repopulate the list of
+ // locks in use.
+ AllocateAndRetrieveLock(id uint32) (Locker, error)
// PLEASE READ FULL DESCRIPTION BEFORE USING.
// FreeAllLocks frees all allocated locks, in preparation for lock
// reallocation.
diff --git a/libpod/lock/shm/shm_lock.c b/libpod/lock/shm/shm_lock.c
index d11fce71a..047d3c417 100644
--- a/libpod/lock/shm/shm_lock.c
+++ b/libpod/lock/shm/shm_lock.c
@@ -354,6 +354,61 @@ int64_t allocate_semaphore(shm_struct_t *shm) {
return -1 * ENOSPC;
}
+// Allocate the semaphore with the given ID.
+// Returns an error if the semaphore with this ID does not exist, or has already
+// been allocated.
+// Returns 0 on success, or negative errno values on failure.
+int32_t allocate_given_semaphore(shm_struct_t *shm, uint32_t sem_index) {
+ int bitmap_index, index_in_bitmap, ret_code;
+ bitmap_t test_map;
+
+ if (shm == NULL) {
+ return -1 * EINVAL;
+ }
+
+ // Check if the lock index is valid
+ if (sem_index >= shm->num_locks) {
+ return -1 * EINVAL;
+ }
+
+ bitmap_index = sem_index / BITMAP_SIZE;
+ index_in_bitmap = sem_index % BITMAP_SIZE;
+
+ // This should never happen if the sem_index test above succeeded, but better
+ // safe than sorry
+ if (bitmap_index >= shm->num_bitmaps) {
+ return -1 * EFAULT;
+ }
+
+ test_map = 0x1 << index_in_bitmap;
+
+ // Lock the mutex controlling access to our shared memory
+ ret_code = take_mutex(&(shm->segment_lock));
+ if (ret_code != 0) {
+ return -1 * ret_code;
+ }
+
+ // Check if the semaphore is allocated
+ if ((test_map & shm->locks[bitmap_index].bitmap) != 0) {
+ ret_code = release_mutex(&(shm->segment_lock));
+ if (ret_code != 0) {
+ return -1 * ret_code;
+ }
+
+ return -1 * EEXIST;
+ }
+
+ // The semaphore is not allocated, allocate it
+ shm->locks[bitmap_index].bitmap = shm->locks[bitmap_index].bitmap | test_map;
+
+ ret_code = release_mutex(&(shm->segment_lock));
+ if (ret_code != 0) {
+ return -1 * ret_code;
+ }
+
+ return 0;
+}
+
// Deallocate a given semaphore
// Returns 0 on success, negative ERRNO values on failure
int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index) {
diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go
index e70ea8743..c21e9a221 100644
--- a/libpod/lock/shm/shm_lock.go
+++ b/libpod/lock/shm/shm_lock.go
@@ -134,6 +134,23 @@ func (locks *SHMLocks) AllocateSemaphore() (uint32, error) {
return uint32(retCode), nil
}
+// AllocateGivenSemaphore allocates the given semaphore from the shared-memory
+// segment for use by a container or pod.
+// If the semaphore is already in use or the index is invalid an error will be
+// returned.
+func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error {
+ if !locks.valid {
+ return errors.Wrapf(syscall.EINVAL, "locks have already been closed")
+ }
+
+ retCode := C.allocate_given_semaphore(locks.lockStruct, C.uint32_t(sem))
+ if retCode < 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
// DeallocateSemaphore frees a semaphore in a shared-memory segment so it can be
// reallocated to another container or pod.
// The given semaphore must be already allocated, or an error will be returned.
diff --git a/libpod/lock/shm/shm_lock.h b/libpod/lock/shm/shm_lock.h
index 58e4297e2..759f8178a 100644
--- a/libpod/lock/shm/shm_lock.h
+++ b/libpod/lock/shm/shm_lock.h
@@ -39,6 +39,7 @@ shm_struct_t *setup_lock_shm(char *path, uint32_t num_locks, int *error_code);
shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code);
int32_t close_lock_shm(shm_struct_t *shm);
int64_t allocate_semaphore(shm_struct_t *shm);
+int32_t allocate_given_semaphore(shm_struct_t *shm, uint32_t sem_index);
int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index);
int32_t deallocate_all_semaphores(shm_struct_t *shm);
int32_t lock_semaphore(shm_struct_t *shm, uint32_t sem_index);
diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go
index 8678958ee..5f31939f8 100644
--- a/libpod/lock/shm_lock_manager_linux.go
+++ b/libpod/lock/shm_lock_manager_linux.go
@@ -57,6 +57,25 @@ func (m *SHMLockManager) AllocateLock() (Locker, error) {
return lock, nil
}
+// AllocateAndRetrieveLock allocates the lock with the given ID and returns it.
+// If the lock is already allocated, error.
+func (m *SHMLockManager) AllocateAndRetrieveLock(id uint32) (Locker, error) {
+ lock := new(SHMLock)
+ lock.lockID = id
+ lock.manager = m
+
+ if id >= m.locks.GetMaxLocks() {
+ return nil, errors.Wrapf(syscall.EINVAL, "lock ID %d is too large - max lock size is %d",
+ id, m.locks.GetMaxLocks()-1)
+ }
+
+ if err := m.locks.AllocateGivenSemaphore(id); err != nil {
+ return nil, err
+ }
+
+ return lock, nil
+}
+
// RetrieveLock retrieves a lock from the manager given its ID.
func (m *SHMLockManager) RetrieveLock(id uint32) (Locker, error) {
lock := new(SHMLock)
diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go
index 25e4e77d7..1fcb5b1a6 100644
--- a/libpod/pod_internal.go
+++ b/libpod/pod_internal.go
@@ -56,7 +56,7 @@ func (p *Pod) refresh() error {
}
// Retrieve the pod's lock
- lock, err := p.runtime.lockManager.RetrieveLock(p.config.LockID)
+ lock, err := p.runtime.lockManager.AllocateAndRetrieveLock(p.config.LockID)
if err != nil {
return errors.Wrapf(err, "error retrieving lock for pod %s", p.ID())
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 34b6ac74f..e6b84014e 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -922,7 +922,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
if os.IsNotExist(errors.Cause(err)) {
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
- return err
+ return errors.Wrapf(err, "failed to get new shm lock manager")
}
} else if errors.Cause(err) == syscall.ERANGE && runtime.doRenumber {
logrus.Debugf("Number of locks does not match - removing old locks")
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 0011c771a..5867b1f87 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -149,10 +149,10 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
}
// Go through and lock all containers so we can operate on them all at once
- dependencies := make(map[string][]string)
for _, ctr := range ctrs {
- ctr.lock.Lock()
- defer ctr.lock.Unlock()
+ ctrLock := ctr.lock
+ ctrLock.Lock()
+ defer ctrLock.Unlock()
// Sync all containers
if err := ctr.syncContainer(); err != nil {
@@ -177,23 +177,12 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if len(ctr.state.ExecSessions) != 0 && !force {
return errors.Wrapf(ErrCtrStateInvalid, "pod %s contains container %s which has active exec sessions", p.ID(), ctr.ID())
}
-
- deps, err := r.state.ContainerInUse(ctr)
- if err != nil {
- return err
- }
- dependencies[ctr.ID()] = deps
}
- // Check if containers have dependencies
- // If they do, and the dependencies are not in the pod, error
- for ctr, deps := range dependencies {
- for _, dep := range deps {
- if _, ok := dependencies[dep]; !ok {
- return errors.Wrapf(ErrCtrExists, "container %s depends on container %s not in pod %s", ctr, dep, p.ID())
- }
- }
- }
+ // We maintain the invariant that container dependencies must all exist
+ // within the container's pod.
+ // No need to check dependencies as such - we're removing all containers
+ // in the pod at once, no dependency issues.
// First loop through all containers and stop them
// Do not remove in this loop to ensure that we don't remove unless all
@@ -220,18 +209,40 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
}
}
- // Start removing containers
- // We can remove containers even if they have dependencies now
- // As we have guaranteed their dependencies are in the pod
+ // Remove all containers in the pod from the state.
+ if err := r.state.RemovePodContainers(p); err != nil {
+ return err
+ }
+
+ var removalErr error
+
+ // Clean up after our removed containers.
+ // Errors here are nonfatal - the containers have already been evicted.
+ // We'll do our best to clean up after them, but we have to keep going
+ // and remove the pod as well.
+ // From here until we remove the pod from the state, no error returns.
for _, ctr := range ctrs {
+ // The container no longer exists in the state, mark invalid.
+ ctr.valid = false
+
+ ctr.newContainerEvent(events.Remove)
+
// Clean up network namespace, cgroups, mounts
if err := ctr.cleanup(ctx); err != nil {
- return err
+ if removalErr == nil {
+ removalErr = err
+ } else {
+ logrus.Errorf("Unable to clean up container %s: %v", ctr.ID(), err)
+ }
}
// Stop container's storage
if err := ctr.teardownStorage(); err != nil {
- return err
+ if removalErr == nil {
+ removalErr = err
+ } else {
+ logrus.Errorf("Unable to tear down container %s storage: %v", ctr.ID(), err)
+ }
}
// Delete the container from runtime (only if we are not
@@ -239,26 +250,24 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
if ctr.state.State != ContainerStateConfigured &&
ctr.state.State != ContainerStateExited {
if err := ctr.delete(ctx); err != nil {
- return err
+ if removalErr == nil {
+ removalErr = err
+ } else {
+ logrus.Errorf("Unable to remove container %s from OCI runtime: %v", ctr.ID(), err)
+ }
}
}
// Free the container's lock
if err := ctr.lock.Free(); err != nil {
- return err
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error freeing container %s lock", ctr.ID())
+ } else {
+ logrus.Errorf("Unable to free container %s lock: %v", ctr.ID(), err)
+ }
}
}
- // Remove containers from the state
- if err := r.state.RemovePodContainers(p); err != nil {
- return err
- }
-
- // Mark containers invalid
- for _, ctr := range ctrs {
- ctr.valid = false
- }
-
// Remove pod cgroup, if present
if p.state.CgroupPath != "" {
logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath)
@@ -266,10 +275,11 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
switch p.runtime.config.CgroupManager {
case SystemdCgroupsManager:
if err := deleteSystemdCgroup(p.state.CgroupPath); err != nil {
- // The pod is already almost gone.
- // No point in hard-failing if we fail
- // this bit of cleanup.
- logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID())
+ } else {
+ logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ }
}
case CgroupfsCgroupsManager:
// Delete the cgroupfs cgroup
@@ -280,34 +290,60 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon")
conmonCgroup, err := cgroups.Load(v1CGroups, cgroups.StaticPath(conmonCgroupPath))
if err != nil && err != cgroups.ErrCgroupDeleted {
- return err
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error retrieving pod %s conmon cgroup", p.ID())
+ } else {
+ logrus.Debugf("Error retrieving pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
+ }
}
if err == nil {
if err := conmonCgroup.Delete(); err != nil {
- logrus.Errorf("Error deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error removing pod %s conmon cgroup", p.ID())
+ } else {
+ logrus.Errorf("Error deleting pod %s conmon cgroup %s: %v", p.ID(), conmonCgroupPath, err)
+ }
}
}
cgroup, err := cgroups.Load(v1CGroups, cgroups.StaticPath(p.state.CgroupPath))
if err != nil && err != cgroups.ErrCgroupDeleted {
- return err
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error retrieving pod %s cgroup", p.ID())
+ } else {
+ logrus.Errorf("Error retrieving pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ }
}
if err == nil {
if err := cgroup.Delete(); err != nil {
- logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID())
+ } else {
+ logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err)
+ }
}
}
default:
- return errors.Wrapf(ErrInvalidArg, "unknown cgroups manager %s specified", p.runtime.config.CgroupManager)
+ // This should be caught much earlier, but let's still
+ // keep going so we make sure to evict the pod before
+ // ending up with an inconsistent state.
+ if removalErr == nil {
+ removalErr = errors.Wrapf(ErrInternal, "unrecognized cgroup manager %s when removing pod %s cgroups", p.runtime.config.CgroupManager, p.ID())
+ } else {
+ logrus.Errorf("Unknown cgroups manager %s specified - cannot remove pod %s cgroup", p.runtime.config.CgroupManager, p.ID())
+ }
}
}
// Remove pod from state
if err := r.state.RemovePod(p); err != nil {
+ if removalErr != nil {
+ logrus.Errorf("%v", removalErr)
+ }
return err
}
// Mark pod invalid
p.valid = false
p.newPodEvent(events.Remove)
- return nil
+ return removalErr
}
diff --git a/pkg/adapter/client.go b/pkg/adapter/client.go
index 6512a5952..f672a92a6 100644
--- a/pkg/adapter/client.go
+++ b/pkg/adapter/client.go
@@ -3,30 +3,45 @@
package adapter
import (
+ "fmt"
"os"
- "github.com/sirupsen/logrus"
+ "github.com/pkg/errors"
"github.com/varlink/go/varlink"
)
-// DefaultAddress is the default address of the varlink socket
-const DefaultAddress = "unix:/run/podman/io.podman"
+type VarlinkConnectionInfo struct {
+ RemoteUserName string
+ RemoteHost string
+ VarlinkAddress string
+}
// Connect provides a varlink connection
func (r RemoteRuntime) Connect() (*varlink.Connection, error) {
- var err error
- var connection *varlink.Connection
- if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" {
- logrus.Infof("Connecting with varlink bridge")
- logrus.Debugf("%s", bridge)
+ var (
+ err error
+ connection *varlink.Connection
+ )
+
+ logLevel := r.cmd.LogLevel
+
+ // I'm leaving this here for now as a document of the birdge format. It can be removed later once the bridge
+ // function is more flushed out.
+ //bridge := `ssh -T root@192.168.122.1 "/usr/bin/varlink -A '/usr/bin/podman varlink \$VARLINK_ADDRESS' bridge"`
+ if len(r.cmd.RemoteHost) > 0 {
+ // The user has provided a remote host endpoint
+ if len(r.cmd.RemoteUserName) < 1 {
+ return nil, errors.New("you must provide a username when providing a remote host name")
+ }
+ bridge := fmt.Sprintf(`ssh -T %s@%s /usr/bin/varlink -A \'/usr/bin/podman --log-level=%s varlink \\\$VARLINK_ADDRESS\' bridge`, r.cmd.RemoteUserName, r.cmd.RemoteHost, logLevel)
+ connection, err = varlink.NewBridge(bridge)
+ } else if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" {
connection, err = varlink.NewBridge(bridge)
} else {
address := os.Getenv("PODMAN_VARLINK_ADDRESS")
if address == "" {
address = DefaultAddress
}
- logrus.Infof("Connecting with varlink address")
- logrus.Debugf("%s", address)
connection, err = varlink.NewConnection(address)
}
if err != nil {
diff --git a/pkg/adapter/client_config.go b/pkg/adapter/client_config.go
new file mode 100644
index 000000000..d165ef1cc
--- /dev/null
+++ b/pkg/adapter/client_config.go
@@ -0,0 +1,4 @@
+package adapter
+
+// DefaultAddress is the default address of the varlink socket
+const DefaultAddress = "unix:/run/podman/io.podman"
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index f17050d42..ff7b6377a 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -1025,3 +1025,8 @@ func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (stri
}
return systemdgen.CreateSystemdUnitAsString(name, ctr.ID(), c.RestartPolicy, ctr.Config().StaticDir, timeout)
}
+
+// GetNamespaces returns namespace information about a container for PS
+func (r *LocalRuntime) GetNamespaces(container shared.PsContainerOutput) *shared.Namespace {
+ return shared.GetNamespaces(container.Pid)
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 201249fc3..63b0f9d2f 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -234,15 +234,25 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
if err != nil {
- return ok, failures, err
+ return ok, failures, TranslateError(err)
}
for _, id := range ids {
- stopped, err := iopodman.StopContainer().Call(r.Conn, id, int64(cli.Timeout))
- if err != nil {
+ if _, err := iopodman.StopContainer().Call(r.Conn, id, int64(cli.Timeout)); err != nil {
+ transError := TranslateError(err)
+ if errors.Cause(transError) == libpod.ErrCtrStopped {
+ ok = append(ok, id)
+ continue
+ }
+ if errors.Cause(transError) == libpod.ErrCtrStateInvalid && cli.All {
+ ok = append(ok, id)
+ continue
+ }
failures[id] = err
} else {
- ok = append(ok, stopped)
+ // We should be using ID here because in varlink, only successful returns
+ // include the string id
+ ok = append(ok, id)
}
}
return ok, failures, nil
@@ -310,7 +320,7 @@ func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillVa
func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmValues) ([]string, map[string]error, error) {
ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
if err != nil {
- return nil, nil, err
+ return nil, nil, TranslateError(err)
}
var (
@@ -961,3 +971,18 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
return iopodman.GenerateSystemd().Call(r.Conn, c.InputArgs[0], c.RestartPolicy, int64(c.StopTimeout), c.Name)
}
+
+// GetNamespaces returns namespace information about a container for PS
+func (r *LocalRuntime) GetNamespaces(container shared.PsContainerOutput) *shared.Namespace {
+ ns := shared.Namespace{
+ PID: container.PID,
+ Cgroup: container.Cgroup,
+ IPC: container.IPC,
+ MNT: container.MNT,
+ NET: container.NET,
+ PIDNS: container.PIDNS,
+ User: container.User,
+ UTS: container.UTS,
+ }
+ return &ns
+}
diff --git a/pkg/adapter/errors.go b/pkg/adapter/errors.go
new file mode 100644
index 000000000..7fbbabd93
--- /dev/null
+++ b/pkg/adapter/errors.go
@@ -0,0 +1,31 @@
+// +build remoteclient
+
+package adapter
+
+import (
+ iopodman "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod"
+ "github.com/pkg/errors"
+)
+
+// TranslateMapErrors translates the errors a typical podman output struct
+// from varlink errors to libpod errors
+func TranslateMapErrors(failures map[string]error) map[string]error {
+ for k, v := range failures {
+ failures[k] = TranslateError(v)
+ }
+ return failures
+}
+
+// TranslateError converts a single varlink error to a libpod error
+func TranslateError(err error) error {
+ switch err.(type) {
+ case *iopodman.ContainerNotFound:
+ return errors.Wrap(libpod.ErrNoSuchCtr, err.Error())
+ case *iopodman.ErrCtrStopped:
+ return errors.Wrap(libpod.ErrCtrStopped, err.Error())
+ case *iopodman.InvalidState:
+ return errors.Wrap(libpod.ErrCtrStateInvalid, err.Error())
+ }
+ return err
+}
diff --git a/pkg/adapter/info_remote.go b/pkg/adapter/info_remote.go
index 3b691ed17..3b2d02a5a 100644
--- a/pkg/adapter/info_remote.go
+++ b/pkg/adapter/info_remote.go
@@ -20,12 +20,7 @@ func (r RemoteRuntime) Info() ([]libpod.InfoData, error) {
registries := make(map[string]interface{})
insecureRegistries := make(map[string]interface{})
- conn, err := r.Connect()
- if err != nil {
- return nil, err
- }
- defer conn.Close()
- info, err := iopodman.GetInfo().Call(conn)
+ info, err := iopodman.GetInfo().Call(r.Conn)
if err != nil {
return nil, err
}
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index 7cf38aac0..e2c97c36a 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -172,11 +172,15 @@ func (r *LocalRuntime) StartPods(ctx context.Context, cli *cliconfig.PodStartVal
// CreatePod creates a pod for the remote client over a varlink connection
func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateValues, labels map[string]string) (string, error) {
+ var share []string
+ if cli.Share != "" {
+ share = strings.Split(cli.Share, ",")
+ }
pc := iopodman.PodCreate{
Name: cli.Name,
CgroupParent: cli.CgroupParent,
Labels: labels,
- Share: strings.Split(cli.Share, ","),
+ Share: share,
Infra: cli.Infra,
InfraCommand: cli.InfraCommand,
InfraImage: cli.InfraCommand,
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index 4986d16f7..8803a26fb 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -38,6 +38,7 @@ type RemoteImageRuntime struct{}
type RemoteRuntime struct {
Conn *varlink.Connection
Remote bool
+ cmd cliconfig.MainFlags
}
// LocalRuntime describes a typical libpod runtime
@@ -47,17 +48,17 @@ type LocalRuntime struct {
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it
func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
- runtime := RemoteRuntime{}
+ runtime := RemoteRuntime{
+ Remote: true,
+ cmd: c.GlobalFlags,
+ }
conn, err := runtime.Connect()
if err != nil {
return nil, err
}
-
+ runtime.Conn = conn
return &LocalRuntime{
- &RemoteRuntime{
- Conn: conn,
- Remote: true,
- },
+ &runtime,
}, nil
}
diff --git a/pkg/systemdgen/systemdgen_test.go b/pkg/systemdgen/systemdgen_test.go
new file mode 100644
index 000000000..f2f49e750
--- /dev/null
+++ b/pkg/systemdgen/systemdgen_test.go
@@ -0,0 +1,120 @@
+package systemdgen
+
+import (
+ "testing"
+)
+
+func TestValidateRestartPolicy(t *testing.T) {
+ type args struct {
+ restart string
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {"good-on", args{restart: "no"}, false},
+ {"good-on-success", args{restart: "on-success"}, false},
+ {"good-on-failure", args{restart: "on-failure"}, false},
+ {"good-on-abnormal", args{restart: "on-abnormal"}, false},
+ {"good-on-watchdog", args{restart: "on-watchdog"}, false},
+ {"good-on-abort", args{restart: "on-abort"}, false},
+ {"good-always", args{restart: "always"}, false},
+ {"fail", args{restart: "foobar"}, true},
+ {"failblank", args{restart: ""}, true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if err := ValidateRestartPolicy(tt.args.restart); (err != nil) != tt.wantErr {
+ t.Errorf("ValidateRestartPolicy() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
+
+func TestCreateSystemdUnitAsString(t *testing.T) {
+ goodID := `[Unit]
+Description=639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401 Podman Container
+[Service]
+Restart=always
+ExecStart=/usr/bin/podman start 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
+ExecStop=/usr/bin/podman stop -t 10 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
+KillMode=none
+Type=forking
+PIDFile=/var/lib/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid
+[Install]
+WantedBy=multi-user.target`
+
+ goodName := `[Unit]
+Description=foobar Podman Container
+[Service]
+Restart=always
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+KillMode=none
+Type=forking
+PIDFile=/var/lib/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid
+[Install]
+WantedBy=multi-user.target`
+
+ type args struct {
+ name string
+ cid string
+ restart string
+ pidPath string
+ stopTimeout int
+ }
+ tests := []struct {
+ name string
+ args args
+ want string
+ wantErr bool
+ }{
+
+ {"good with id",
+ args{
+ "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ "always",
+ "/var/lib/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/",
+ 10,
+ },
+ goodID,
+ false,
+ },
+ {"good with name",
+ args{
+ "foobar",
+ "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ "always",
+ "/var/lib/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/",
+ 10,
+ },
+ goodName,
+ false,
+ },
+ {"bad restart policy",
+ args{
+ "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ "never",
+ "/var/lib/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/",
+ 10,
+ },
+ "",
+ true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := CreateSystemdUnitAsString(tt.args.name, tt.args.cid, tt.args.restart, tt.args.pidPath, tt.args.stopTimeout)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("CreateSystemdUnitAsString() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if got != tt.want {
+ t.Errorf("CreateSystemdUnitAsString() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go
index 6c62d3514..2234899a5 100644
--- a/pkg/varlinkapi/attach.go
+++ b/pkg/varlinkapi/attach.go
@@ -60,6 +60,7 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys st
if !start && state != libpod.ContainerStateRunning {
return call.ReplyErrorOccurred("container must be running to attach")
}
+ call.Reply(nil)
reader, writer, _, pw, streams := setupStreams(call)
go func() {
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index c8be41636..8611a1a7d 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -119,6 +119,9 @@ func (i *LibpodAPI) GetContainersByContext(call iopodman.VarlinkCall, all, lates
ctrs, err := shortcuts.GetContainersByContext(all, latest, input, i.Runtime)
if err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ return call.ReplyContainerNotFound("", err.Error())
+ }
return call.ReplyErrorOccurred(err.Error())
}
@@ -359,7 +362,11 @@ func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error
if state == libpod.ContainerStateRunning || state == libpod.ContainerStatePaused {
return call.ReplyErrorOccurred("container is already running or paused")
}
- if err := ctr.Start(getContext(), false); err != nil {
+ recursive := false
+ if ctr.PodID() != "" {
+ recursive = true
+ }
+ if err := ctr.Start(getContext(), recursive); err != nil {
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyStartContainer(ctr.ID())
@@ -386,7 +393,13 @@ func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeou
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
}
- if err := ctr.StopWithTimeout(uint(timeout)); err != nil && err != libpod.ErrCtrStopped {
+ if err := ctr.StopWithTimeout(uint(timeout)); err != nil {
+ if errors.Cause(err) == libpod.ErrCtrStopped {
+ return call.ReplyErrCtrStopped(ctr.ID())
+ }
+ if errors.Cause(err) == libpod.ErrCtrStateInvalid {
+ return call.ReplyInvalidState(ctr.ID(), err.Error())
+ }
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyStopContainer(ctr.ID())
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index f34375bf5..c0fd8b1f7 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"github.com/containers/libpod/pkg/adapter/shortcuts"
- "github.com/containers/libpod/pkg/rootless"
"syscall"
"github.com/containers/libpod/cmd/podman/shared"
@@ -37,12 +36,9 @@ func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCrea
if !create.Infra {
return call.ReplyErrorOccurred("you must have an infra container to publish port bindings to the host")
}
- if rootless.IsRootless() {
- return call.ReplyErrorOccurred("rootless networking does not allow port binding to the host")
- }
portBindings, err := shared.CreatePortBindings(create.Publish)
if err != nil {
- return err
+ return call.ReplyErrorOccurred(err.Error())
}
options = append(options, libpod.WithInfraContainerPorts(portBindings))
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
index 7f436a954..59bfec75b 100644
--- a/pkg/varlinkapi/system.go
+++ b/pkg/varlinkapi/system.go
@@ -86,15 +86,18 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error {
Graph_status: graphStatus,
}
- registriesInterface := info[2].Data["registries"]
- insecureRegistriesInterface := info[3].Data["registries"]
- if registriesInterface != nil {
- registries = registriesInterface.([]string)
+ if len(info) > 2 {
+ registriesInterface := info[2].Data["registries"]
+ if registriesInterface != nil {
+ registries = registriesInterface.([]string)
+ }
}
- if insecureRegistriesInterface != nil {
- insecureRegistries = insecureRegistriesInterface.([]string)
+ if len(info) > 3 {
+ insecureRegistriesInterface := info[3].Data["registries"]
+ if insecureRegistriesInterface != nil {
+ insecureRegistries = insecureRegistriesInterface.([]string)
+ }
}
-
podmanInfo.Store = infoStore
podmanInfo.Podman = pmaninfo
podmanInfo.Registries = registries
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index a6fc211f6..3c7675b35 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -264,9 +264,14 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
}
if remote {
p.PodmanTest.RemotePodmanBinary = podmanRemoteBinary
+ uuid := stringid.GenerateNonCryptoID()
if !rootless.IsRootless() {
- uuid := stringid.GenerateNonCryptoID()
p.VarlinkEndpoint = fmt.Sprintf("unix:/run/podman/io.podman-%s", uuid)
+ } else {
+ runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
+ socket := fmt.Sprintf("io.podman-%s", uuid)
+ fqpath := filepath.Join(runtimeDir, socket)
+ p.VarlinkEndpoint = fmt.Sprintf("unix:%s", fqpath)
}
}
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 105cba37c..f3367337e 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go
index fba65823e..920b920c0 100644
--- a/test/e2e/diff_test.go
+++ b/test/e2e/diff_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
@@ -63,6 +61,7 @@ var _ = Describe("Podman diff", func() {
})
It("podman diff container and committed image", func() {
+ SkipIfRemote()
session := podmanTest.Podman([]string{"run", "--name=diff-test", ALPINE, "touch", "/tmp/diff-test"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go
index c960fb311..ca4012dde 100644
--- a/test/e2e/info_test.go
+++ b/test/e2e/info_test.go
@@ -24,6 +24,7 @@ var _ = Describe("Podman Info", func() {
}
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
+ podmanTest.DelayForVarlink()
})
AfterEach(func() {
diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go
index 618ca5aa0..3286180a4 100644
--- a/test/e2e/kill_test.go
+++ b/test/e2e/kill_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go
index 1e477fe2f..05c355711 100644
--- a/test/e2e/libpod_suite_remoteclient_test.go
+++ b/test/e2e/libpod_suite_remoteclient_test.go
@@ -3,13 +3,17 @@
package integration
import (
+ "bytes"
"fmt"
"github.com/containers/libpod/pkg/rootless"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
+ "strconv"
"strings"
+ "syscall"
+ "time"
"github.com/onsi/ginkgo"
)
@@ -50,33 +54,76 @@ func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
return pti
}
+func (p *PodmanTestIntegration) ResetVarlinkAddress() {
+ os.Unsetenv("PODMAN_VARLINK_ADDRESS")
+}
+
+func (p *PodmanTestIntegration) SetVarlinkAddress(addr string) {
+ os.Setenv("PODMAN_VARLINK_ADDRESS", addr)
+}
+
func (p *PodmanTestIntegration) StartVarlink() {
if os.Geteuid() == 0 {
os.MkdirAll("/run/podman", 0755)
}
varlinkEndpoint := p.VarlinkEndpoint
- if addr := os.Getenv("PODMAN_VARLINK_ADDRESS"); addr != "" {
- varlinkEndpoint = addr
- }
+ p.SetVarlinkAddress(p.VarlinkEndpoint)
args := []string{"varlink", "--timeout", "0", varlinkEndpoint}
podmanOptions := getVarlinkOptions(p, args)
command := exec.Command(p.PodmanBinary, podmanOptions...)
fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
command.Start()
+ command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+ p.VarlinkCommand = command
p.VarlinkSession = command.Process
}
func (p *PodmanTestIntegration) StopVarlink() {
+ var out bytes.Buffer
+ var pids []int
varlinkSession := p.VarlinkSession
- varlinkSession.Kill()
- varlinkSession.Wait()
if !rootless.IsRootless() {
- socket := strings.Split(p.VarlinkEndpoint, ":")[1]
- if err := os.Remove(socket); err != nil {
- fmt.Println(err)
+ if err := varlinkSession.Kill(); err != nil {
+ fmt.Fprintf(os.Stderr, "error on varlink stop-kill %q", err)
}
+ if _, err := varlinkSession.Wait(); err != nil {
+ fmt.Fprintf(os.Stderr, "error on varlink stop-wait %q", err)
+ }
+
+ } else {
+ p.ResetVarlinkAddress()
+ parentPid := fmt.Sprintf("%d", p.VarlinkSession.Pid)
+ pgrep := exec.Command("pgrep", "-P", parentPid)
+ fmt.Printf("running: pgrep %s\n", parentPid)
+ pgrep.Stdout = &out
+ err := pgrep.Run()
+ if err != nil {
+ fmt.Fprint(os.Stderr, "unable to find varlink pid")
+ }
+
+ for _, s := range strings.Split(out.String(), "\n") {
+ if len(s) == 0 {
+ continue
+ }
+ p, err := strconv.Atoi(s)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unable to convert %s to int", s)
+ }
+ if p != 0 {
+ pids = append(pids, p)
+ }
+ }
+
+ pids = append(pids, p.VarlinkSession.Pid)
+ for _, pid := range pids {
+ syscall.Kill(pid, syscall.SIGKILL)
+ }
+ }
+ socket := strings.Split(p.VarlinkEndpoint, ":")[1]
+ if err := os.Remove(socket); err != nil {
+ fmt.Println(err)
}
}
@@ -110,3 +157,14 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
command.Wait()
return nil
}
+
+func (p *PodmanTestIntegration) DelayForVarlink() {
+ for i := 0; i < 5; i++ {
+ session := p.Podman([]string{"info"})
+ session.WaitWithDefaultTimeout()
+ if session.ExitCode() == 0 || i == 4 {
+ break
+ }
+ time.Sleep(1 * time.Second)
+ }
+}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 10ca9ac47..0a85c625d 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -79,4 +79,5 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
restore.Wait(90)
return nil
}
-func (p *PodmanTestIntegration) StopVarlink() {}
+func (p *PodmanTestIntegration) StopVarlink() {}
+func (p *PodmanTestIntegration) DelayForVarlink() {}
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index d051e3dba..2c82182cf 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/negative_test.go b/test/e2e/negative_test.go
new file mode 100644
index 000000000..3cb54a20a
--- /dev/null
+++ b/test/e2e/negative_test.go
@@ -0,0 +1,38 @@
+package integration
+
+import (
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman negative command-line", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("podman snuffleupagus exits non-zero", func() {
+ session := podmanTest.Podman([]string{"snuffleupagus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ })
+})
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index de0734e9f..84966f77b 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 671d203a6..d1a023153 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go
index c1f7503e3..23a8ea97e 100644
--- a/test/e2e/pod_kill_test.go
+++ b/test/e2e/pod_kill_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go
index 59a4da176..ab828853b 100644
--- a/test/e2e/pod_pause_test.go
+++ b/test/e2e/pod_pause_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_prune_test.go b/test/e2e/pod_prune_test.go
index c20f602ad..8a4ba2399 100644
--- a/test/e2e/pod_prune_test.go
+++ b/test/e2e/pod_prune_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 2fa26d7ad..8513c6c2e 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_restart_test.go b/test/e2e/pod_restart_test.go
index ffb6cb94c..7b19ecc94 100644
--- a/test/e2e/pod_restart_test.go
+++ b/test/e2e/pod_restart_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index 5da3d563b..7417a1298 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go
index de52af2a0..967fbc2da 100644
--- a/test/e2e/pod_start_test.go
+++ b/test/e2e/pod_start_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_stop_test.go b/test/e2e/pod_stop_test.go
index fa285fa80..9fd9e3ef4 100644
--- a/test/e2e/pod_stop_test.go
+++ b/test/e2e/pod_stop_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 957c69aa8..7edb350f3 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/refresh_test.go b/test/e2e/refresh_test.go
deleted file mode 100644
index 56c1d255e..000000000
--- a/test/e2e/refresh_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// +build !remoteclient
-
-package integration
-
-import (
- "os"
- "time"
-
- . "github.com/containers/libpod/test/utils"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
-)
-
-var _ = Describe("Podman refresh", func() {
- var (
- tmpdir string
- err error
- podmanTest *PodmanTestIntegration
- )
-
- BeforeEach(func() {
- tmpdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
- podmanTest = PodmanTestCreate(tmpdir)
- podmanTest.Setup()
- podmanTest.RestoreAllArtifacts()
- })
-
- AfterEach(func() {
- podmanTest.Cleanup()
- f := CurrentGinkgoTestDescription()
- processTestResult(f)
-
- })
-
- Specify("Refresh with no containers succeeds", func() {
- session := podmanTest.Podman([]string{"container", "refresh"})
- session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Equal(0))
- })
-
- Specify("Refresh with created container succeeds", func() {
- createSession := podmanTest.Podman([]string{"create", ALPINE, "ls"})
- createSession.WaitWithDefaultTimeout()
- Expect(createSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- 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.NumberOfContainersRunning()).To(Equal(0))
- })
-
- Specify("Refresh with running container restarts container", func() {
- createSession := podmanTest.Podman([]string{"run", "-dt", ALPINE, "top"})
- createSession.WaitWithDefaultTimeout()
- Expect(createSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
-
- // HACK: ensure container starts before we move on
- time.Sleep(1 * time.Second)
-
- refreshSession := podmanTest.Podman([]string{"container", "refresh"})
- refreshSession.WaitWithDefaultTimeout()
- Expect(refreshSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
- })
-})
diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go
index 9bf742a63..29150d67c 100644
--- a/test/e2e/rm_test.go
+++ b/test/e2e/rm_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 030722b47..0e1f0d865 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -273,6 +273,7 @@ var _ = Describe("Podman run", func() {
})
It("podman run notify_socket", func() {
+ SkipIfRemote()
host := GetHostDistributionInfo()
if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" {
Skip("this test requires a working runc")
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index c3edc7c7e..ffb5182d6 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
+ "github.com/containers/libpod/pkg/rootless"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -75,6 +76,9 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with oci format", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
outdir := filepath.Join(podmanTest.TempDir, "save")
save := podmanTest.Podman([]string{"save", "--format", "oci-dir", "-o", outdir, ALPINE})
@@ -83,6 +87,9 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with v2s2 docker format", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
outdir := filepath.Join(podmanTest.TempDir, "save")
save := podmanTest.Podman([]string{"save", "--format", "docker-dir", "-o", outdir, ALPINE})
@@ -91,6 +98,9 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with docker format and compression", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
outdir := filepath.Join(podmanTest.TempDir, "save")
save := podmanTest.Podman([]string{"save", "--compress", "--format", "docker-dir", "-o", outdir, ALPINE})
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index 717eea441..e201204df 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/tag_test.go b/test/e2e/tag_test.go
index ff0ac31c4..26d6dfa75 100644
--- a/test/e2e/tag_test.go
+++ b/test/e2e/tag_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/wait_test.go b/test/e2e/wait_test.go
index 5bf0331e5..28a4c1e40 100644
--- a/test/e2e/wait_test.go
+++ b/test/e2e/wait_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 1e0391d2e..beadab549 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -4,7 +4,6 @@ import (
"bufio"
"encoding/json"
"fmt"
- "github.com/containers/libpod/pkg/rootless"
"io/ioutil"
"os"
"os/exec"
@@ -42,6 +41,7 @@ type PodmanTest struct {
RemotePodmanBinary string
VarlinkSession *os.Process
VarlinkEndpoint string
+ VarlinkCommand *exec.Cmd
}
// PodmanSession wraps the gexec.session so we can extend it
@@ -69,9 +69,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
podmanBinary := p.PodmanBinary
if p.RemoteTest {
podmanBinary = p.RemotePodmanBinary
- if !rootless.IsRootless() {
- env = append(env, fmt.Sprintf("PODMAN_VARLINK_ADDRESS=%s", p.VarlinkEndpoint))
- }
+ env = append(env, fmt.Sprintf("PODMAN_VARLINK_ADDRESS=%s", p.VarlinkEndpoint))
}
if env == nil {
diff --git a/vendor.conf b/vendor.conf
index d5e2b60bd..2f7e36d85 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -93,8 +93,8 @@ k8s.io/api kubernetes-1.10.13-beta.0 https://github.com/kubernetes/api
k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apimachinery
k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
-github.com/varlink/go 64e07fabffa33e385817b41971cf2674f692f391
github.com/containers/buildah v1.8.2
+github.com/varlink/go 0f1d566d194b9d6d48e0d47c5e4d822628919066
# TODO: Gotty has not been updated since 2012. Can we find replacement?
github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512
github.com/fsouza/go-dockerclient v1.3.0
diff --git a/vendor/github.com/varlink/go/varlink/bridge.go b/vendor/github.com/varlink/go/varlink/bridge.go
index 0ea5de682..c478dcd88 100644
--- a/vendor/github.com/varlink/go/varlink/bridge.go
+++ b/vendor/github.com/varlink/go/varlink/bridge.go
@@ -6,6 +6,7 @@ import (
"bufio"
"io"
"net"
+ "os"
"os/exec"
)
@@ -30,12 +31,13 @@ func (p PipeCon) Close() error {
return nil
}
-// NewConnection returns a new connection to the given address.
-func NewBridge(bridge string) (*Connection, error) {
+// NewBridgeWithStderr returns a new connection with the given bridge.
+func NewBridgeWithStderr(bridge string, stderr io.Writer) (*Connection, error) {
//var err error
c := Connection{}
cmd := exec.Command("sh", "-c", bridge)
+ cmd.Stderr = stderr
r, err := cmd.StdoutPipe()
if err != nil {
return nil, err
@@ -56,3 +58,8 @@ func NewBridge(bridge string) (*Connection, error) {
return &c, nil
}
+
+// NewBridge returns a new connection with the given bridge.
+func NewBridge(bridge string) (*Connection, error) {
+ return NewBridgeWithStderr(bridge, os.Stderr)
+}
diff --git a/vendor/github.com/varlink/go/varlink/bridge_windows.go b/vendor/github.com/varlink/go/varlink/bridge_windows.go
index 751224ec8..42953b871 100644
--- a/vendor/github.com/varlink/go/varlink/bridge_windows.go
+++ b/vendor/github.com/varlink/go/varlink/bridge_windows.go
@@ -4,6 +4,7 @@ import (
"bufio"
"io"
"net"
+ "os"
"os/exec"
)
@@ -28,12 +29,13 @@ func (p PipeCon) Close() error {
return nil
}
-// NewConnection returns a new connection to the given address.
-func NewBridge(bridge string) (*Connection, error) {
+// NewBridgeWithStderr returns a new connection with the given bridge.
+func NewBridgeWithStderr(bridge string, stderr io.Writer) (*Connection, error) {
//var err error
c := Connection{}
cmd := exec.Command("cmd", "/C", bridge)
+ cmd.Stderr = stderr
r, err := cmd.StdoutPipe()
if err != nil {
return nil, err
@@ -54,3 +56,8 @@ func NewBridge(bridge string) (*Connection, error) {
return &c, nil
}
+
+// NewBridge returns a new connection with the given bridge.
+func NewBridge(bridge string) (*Connection, error) {
+ return NewBridgeWithStderr(bridge, os.Stderr)
+} \ No newline at end of file
diff --git a/version/version.go b/version/version.go
index 29a576317..c63f8b820 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.3.0-dev"
+const Version = "1.3.1-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility