summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/multi-arch-build.yaml107
-rw-r--r--Makefile12
-rw-r--r--cmd/podman/common/create.go9
-rw-r--r--cmd/podman/containers/create.go2
-rw-r--r--cmd/podman/root.go8
-rw-r--r--libpod/container_internal.go1
-rw-r--r--libpod/runtime_ctr.go26
-rw-r--r--pkg/api/handlers/libpod/containers_create.go1
-rw-r--r--pkg/specgen/generate/container_create.go10
-rw-r--r--pkg/specgen/generate/kube/kube.go13
-rw-r--r--test/README.md2
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/container_create_volume_test.go127
-rw-r--r--test/e2e/pod_create_test.go16
-rw-r--r--test/e2e/run_exit_test.go6
-rw-r--r--test/system/250-systemd.bats39
-rw-r--r--test/system/255-auto-update.bats11
-rw-r--r--test/system/270-socket-activation.bats17
-rw-r--r--test/system/helpers.systemd.bash30
19 files changed, 301 insertions, 138 deletions
diff --git a/.github/workflows/multi-arch-build.yaml b/.github/workflows/multi-arch-build.yaml
index 9bd98078b..f364cd6c6 100644
--- a/.github/workflows/multi-arch-build.yaml
+++ b/.github/workflows/multi-arch-build.yaml
@@ -1,6 +1,6 @@
---
-# Please see contrib/podmanimage/README.md for details on the intentions
+# Please see contrib/<reponame>image/README.md for details on the intentions
# of this workflow.
#
# BIG FAT WARNING: This workflow is duplicated across containers/skopeo,
@@ -11,7 +11,7 @@
name: build multi-arch images
on:
- # Upstream podman tends to be very active, with many merges per day.
+ # Upstream tends to be very active, with many merges per day.
# Only run this daily via cron schedule, or manually, not by branch push.
schedule:
- cron: '0 8 * * *'
@@ -20,19 +20,23 @@ on:
jobs:
multi:
- name: multi-arch Podman build
+ name: multi-arch image build
env:
- PODMAN_QUAY_REGISTRY: quay.io/podman
+ REPONAME: podman # No easy way to parse this out of $GITHUB_REPOSITORY
+ # Server/namespace value used to format FQIN
+ REPONAME_QUAY_REGISTRY: quay.io/podman
CONTAINERS_QUAY_REGISTRY: quay.io/containers
# list of architectures for build
PLATFORMS: linux/amd64,linux/s390x,linux/ppc64le,linux/arm64
+ # Command to execute in container to obtain project version number
+ VERSION_CMD: "podman --version"
# build several images (upstream, testing, stable) in parallel
strategy:
# By default, failure of one matrix item cancels all others
fail-fast: false
matrix:
- # Builds are located under contrib/podmanimage/<source> directory
+ # Builds are located under contrib/<reponame>image/<source> directory
source:
- upstream
- testing
@@ -57,14 +61,14 @@ jobs:
driver-opts: network=host
install: true
- - name: Build and locally push Podman
+ - name: Build and locally push image
uses: docker/build-push-action@v2
with:
- context: contrib/podmanimage/${{ matrix.source }}
- file: ./contrib/podmanimage/${{ matrix.source }}/Dockerfile
+ context: contrib/${{ env.REPONAME }}image/${{ matrix.source }}
+ file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
- tags: localhost:5000/podman/${{ matrix.source }}
+ tags: localhost:5000/${{ env.REPONAME }}/${{ matrix.source }}
# Simple verification that stable images work, and
# also grab version number use in forming the FQIN.
@@ -73,41 +77,41 @@ jobs:
id: sniff_test
run: |
podman pull --tls-verify=false \
- localhost:5000/podman/${{ matrix.source }}
- VERSION_OUTPUT="$(podman run \
- localhost:5000/podman/${{ matrix.source }} \
- podman --storage-driver=vfs version)"
+ localhost:5000/$REPONAME/${{ matrix.source }}
+ VERSION_OUTPUT=$(podman run \
+ localhost:5000/$REPONAME/${{ matrix.source }} \
+ $VERSION_CMD)
echo "$VERSION_OUTPUT"
- VERSION=$(grep -Em1 '^Version: ' <<<"$VERSION_OUTPUT" | awk '{print $2}')
+ VERSION=$(awk -r -e "/^${REPONAME} version /"'{print $3}' <<<"$VERSION_OUTPUT")
test -n "$VERSION"
- echo "::set-output name=version::${VERSION}"
+ echo "::set-output name=version::$VERSION"
- - name: Generate podman reg. image FQIN(s)
- id: podman_reg
+ - name: Generate image FQIN(s) to push
+ id: gen_fqin
run: |
if [[ "${{ matrix.source }}" == 'stable' ]]; then
- # The `podman version` in image just built
+ # The command version in image just built
VERSION='v${{ steps.sniff_test.outputs.version }}'
# workaround vim syntax-highlight bug: '
# Image tags previously pushed to quay
ALLTAGS=$(skopeo list-tags \
- docker://$PODMAN_QUAY_REGISTRY/stable | \
+ docker://$REPONAME_QUAY_REGISTRY/stable | \
jq -r '.Tags[]')
- # New version? Push quay.io/podman/stable:vX.X.X and :latest
+ # New version? Push quay.io/$REPONAME/stable:vX.X.X and :latest
if ! fgrep -qx "$VERSION" <<<"$ALLTAGS"; then
# Assume version-tag is also the most up to date (i.e. "latest")
- FQIN="$PODMAN_QUAY_REGISTRY/stable:$VERSION,$PODMAN_QUAY_REGISTRY/stable:latest"
+ FQIN="$REPONAME_QUAY_REGISTRY/stable:$VERSION,$REPONAME_QUAY_REGISTRY/stable:latest"
else # Not a new version-tagged image
# Assume other contents changed, so this is the "new" latest.
- FQIN="$PODMAN_QUAY_REGISTRY/stable:latest"
+ FQIN="$REPONAME_QUAY_REGISTRY/stable:latest"
fi
elif [[ "${{ matrix.source }}" == 'testing' ]]; then
# Assume some contents changed, always push latest testing.
- FQIN="$PODMAN_QUAY_REGISTRY/testing:latest"
+ FQIN="$REPONAME_QUAY_REGISTRY/testing:latest"
elif [[ "${{ matrix.source }}" == 'upstream' ]]; then
# Assume some contents changed, always push latest upstream.
- FQIN="$PODMAN_QUAY_REGISTRY/upstream:latest"
+ FQIN="$REPONAME_QUAY_REGISTRY/upstream:latest"
else
echo "::error::Unknown matrix item '${{ matrix.source }}'"
exit 1
@@ -126,14 +130,14 @@ jobs:
VERSION='v${{ steps.sniff_test.outputs.version }}'
# workaround vim syntax-highlight bug: '
ALLTAGS=$(skopeo list-tags \
- docker://$CONTAINERS_QUAY_REGISTRY/podman | \
+ docker://$CONTAINERS_QUAY_REGISTRY/$REPONAME | \
jq -r '.Tags[]')
- # New version? Push quay.io/containers/podman:vX.X.X and latest
+ # New version? Push quay.io/containers/$REPONAME:vX.X.X and latest
if ! fgrep -qx "$VERSION" <<<"$ALLTAGS"; then
- FQIN="$CONTAINERS_QUAY_REGISTRY/podman:$VERSION,$CONTAINERS_QUAY_REGISTRY/podman:latest"
+ FQIN="$CONTAINERS_QUAY_REGISTRY/$REPONAME:$VERSION,$CONTAINERS_QUAY_REGISTRY/$REPONAME:latest"
else # Not a new version-tagged image, only update latest.
- FQIN="$CONTAINERS_QUAY_REGISTRY/podman:latest"
+ FQIN="$CONTAINERS_QUAY_REGISTRY/$REPONAME:latest"
fi
echo "::warning::Pushing $FQIN"
echo "::set-output name=fqin::${FQIN}"
@@ -153,40 +157,39 @@ jobs:
DELIMITER
EOF
- # Separate steps to login and push for podman and containers quay
- # repositories are required, because 2 sets of credentials are used and `docker
- # login` as well as `podman login` do not support having 2 different
- # credential sets for 1 registry.
- # At the same time reuse of non-shell steps is not supported by Github Actions
- # via anchors or composite actions
+ # Separate steps to login and push for $REPONAME_QUAY_REGISTRY and
+ # $CONTAINERS_QUAY_REGISTRY are required, because 2 sets of credentials
+ # are used and namespaced within the registry. At the same time, reuse
+ # of non-shell steps is not supported by Github Actions nor are YAML
+ # anchors/aliases, nor composite actions.
- # Push to 'podman' Quay repo for stable, testing. and upstream
- - name: Login to 'podman' Quay registry
+ # Push to $REPONAME_QUAY_REGISTRY for stable, testing. and upstream
+ - name: Login to ${{ env.REPONAME_QUAY_REGISTRY }}
uses: docker/login-action@v1
- if: steps.podman_reg.outputs.push == 'true'
+ if: steps.gen_fqin.outputs.push == 'true'
with:
- registry: ${{ env.PODMAN_QUAY_REGISTRY }}
+ registry: ${{ env.REPONAME_QUAY_REGISTRY }}
# N/B: Secrets are not passed to workflows that are triggered
# by a pull request from a fork
- username: ${{ secrets.PODMAN_QUAY_USERNAME }}
- password: ${{ secrets.PODMAN_QUAY_PASSWORD }}
+ username: ${{ secrets.REPONAME_QUAY_USERNAME }}
+ password: ${{ secrets.REPONAME_QUAY_PASSWORD }}
- - name: Push images to 'podman' Quay
+ - name: Push images to ${{ steps.gen_fqin.outputs.fqin }}
uses: docker/build-push-action@v2
- if: steps.podman_reg.outputs.push == 'true'
+ if: steps.gen_fqin.outputs.push == 'true'
with:
- cache-from: type=registry,ref=localhost:5000/podman/${{ matrix.source }}
+ cache-from: type=registry,ref=localhost:5000/${{ env.REPONAME }}/${{ matrix.source }}
cache-to: type=inline
- context: contrib/podmanimage/${{ matrix.source }}
- file: ./contrib/podmanimage/${{ matrix.source }}/Dockerfile
+ context: contrib/${{ env.REPONAME }}image/${{ matrix.source }}
+ file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
- tags: ${{ steps.podman_reg.outputs.fqin }}
+ tags: ${{ steps.gen_fqin.outputs.fqin }}
labels: |
${{ env.LABELS }}
- # Push to 'containers' Quay repo only stable podman
- - name: Login to 'containers' Quay registry
+ # Push to $CONTAINERS_QUAY_REGISTRY only stable
+ - name: Login to ${{ env.CONTAINERS_QUAY_REGISTRY }}
if: steps.containers_reg.outputs.push == 'true'
uses: docker/login-action@v1
with:
@@ -194,14 +197,14 @@ jobs:
username: ${{ secrets.CONTAINERS_QUAY_USERNAME }}
password: ${{ secrets.CONTAINERS_QUAY_PASSWORD }}
- - name: Push images to 'containers' Quay
+ - name: Push images to ${{ steps.containers_reg.outputs.fqin }}
if: steps.containers_reg.outputs.push == 'true'
uses: docker/build-push-action@v2
with:
- cache-from: type=registry,ref=localhost:5000/podman/${{ matrix.source }}
+ cache-from: type=registry,ref=localhost:5000/${{ env.REPONAME }}/${{ matrix.source }}
cache-to: type=inline
- context: contrib/podmanimage/${{ matrix.source }}
- file: ./contrib/podmanimage/${{ matrix.source }}/Dockerfile
+ context: contrib/${{ env.REPONAME }}image/${{ matrix.source }}
+ file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile
platforms: ${{ env.PLATFORMS }}
push: true
tags: ${{ steps.containers_reg.outputs.fqin }}
diff --git a/Makefile b/Makefile
index 8e66f629a..832671337 100644
--- a/Makefile
+++ b/Makefile
@@ -261,7 +261,7 @@ codespell:
codespell -S bin,vendor,.git,go.sum,changelog.txt,.cirrus.yml,"RELEASE_NOTES.md,*.xz,*.gz,*.tar,*.tgz,bin2img,*ico,*.png,*.1,*.5,copyimg,*.orig,apidoc.go" -L uint,iff,od,seeked,splitted,marge,ERRO,hist,ether -w
.PHONY: validate
-validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check tests-included
+validate: gofmt lint .gitvalidation validate.completions man-page-check swagger-check tests-included tests-expect-exit
.PHONY: build-all-new-commits
build-all-new-commits:
@@ -605,6 +605,16 @@ test-binaries: test/checkseccomp/checkseccomp test/goecho/goecho install.cataton
tests-included:
contrib/cirrus/pr-should-include-tests
+.PHONY: tests-expect-exit
+tests-expect-exit:
+ @if egrep 'Expect.*ExitCode' test/e2e/*.go | egrep -v ', ".*"\)'; then \
+ echo "^^^ Unhelpful use of Expect(ExitCode())"; \
+ echo " Please use '.Should(Exit(...))' pattern instead."; \
+ echo " If that's not possible, please add an annotation (description) to your assertion:"; \
+ echo " Expect(...).To(..., \"Friendly explanation of this check\")"; \
+ exit 1; \
+ fi
+
###
### Release/Packaging targets
###
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go
index 64d1956eb..96414add4 100644
--- a/cmd/podman/common/create.go
+++ b/cmd/podman/common/create.go
@@ -655,15 +655,6 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
)
_ = cmd.RegisterFlagCompletionFunc(stopTimeoutFlagName, completion.AutocompleteNone)
- storageOptFlagName := "storage-opt"
- createFlags.StringSliceVar(
- &cf.StorageOpt,
- storageOptFlagName, []string{},
- "Storage driver options per container",
- )
- //FIXME: What should we suggest here? The flag is not in the man page.
- _ = cmd.RegisterFlagCompletionFunc(storageOptFlagName, completion.AutocompleteNone)
-
subgidnameFlagName := "subgidname"
createFlags.StringVar(
&cf.SubUIDName,
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index df0fa6f9d..c63c074f7 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -146,6 +146,8 @@ func replaceContainer(name string) error {
}
func createInit(c *cobra.Command) error {
+ cliVals.StorageOpt = registry.PodmanConfig().StorageOpts
+
if c.Flag("shm-size").Changed {
cliVals.ShmSize = c.Flag("shm-size").Value.String()
}
diff --git a/cmd/podman/root.go b/cmd/podman/root.go
index 9e5d2a236..2633e4040 100644
--- a/cmd/podman/root.go
+++ b/cmd/podman/root.go
@@ -342,10 +342,6 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
pFlags.StringVar(&opts.StorageDriver, storageDriverFlagName, "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
_ = cmd.RegisterFlagCompletionFunc(storageDriverFlagName, completion.AutocompleteNone) //TODO: what can we recommend here?
- storageOptFlagName := "storage-opt"
- pFlags.StringArrayVar(&opts.StorageOpts, storageOptFlagName, []string{}, "Used to pass an option to the storage driver")
- _ = cmd.RegisterFlagCompletionFunc(storageOptFlagName, completion.AutocompleteNone)
-
tmpdirFlagName := "tmpdir"
pFlags.StringVar(&opts.Engine.TmpDir, tmpdirFlagName, "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n")
_ = cmd.RegisterFlagCompletionFunc(tmpdirFlagName, completion.AutocompleteDefault)
@@ -365,6 +361,10 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) {
}
}
}
+ storageOptFlagName := "storage-opt"
+ pFlags.StringArrayVar(&opts.StorageOpts, storageOptFlagName, []string{}, "Used to pass an option to the storage driver")
+ _ = cmd.RegisterFlagCompletionFunc(storageOptFlagName, completion.AutocompleteNone)
+
// Override default --help information of `--help` global flag
var dummyHelp bool
pFlags.BoolVar(&dummyHelp, "help", false, "Help for podman")
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 2555f15ec..e7694227a 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -420,7 +420,6 @@ func (c *Container) setupStorage(ctx context.Context) error {
if c.config.Rootfs == "" && (c.config.RootfsImageID == "" || c.config.RootfsImageName == "") {
return errors.Wrapf(define.ErrInvalidArg, "must provide image ID and image name to use an image")
}
-
options := storage.ContainerOptions{
IDMappingOptions: storage.IDMappingOptions{
HostUIDMapping: true,
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 6c69d1b72..ce4c5d758 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -47,6 +47,32 @@ func (r *Runtime) NewContainer(ctx context.Context, rSpec *spec.Spec, options ..
return r.newContainer(ctx, rSpec, options...)
}
+func (r *Runtime) PrepareVolumeOnCreateContainer(ctx context.Context, ctr *Container) error {
+ // Copy the content from the underlying image into the newly created
+ // volume if configured to do so.
+ if !r.config.Containers.PrepareVolumeOnCreate {
+ return nil
+ }
+
+ defer func() {
+ if err := ctr.cleanupStorage(); err != nil {
+ logrus.Errorf("error cleaning up container storage %s: %v", ctr.ID(), err)
+ }
+ }()
+
+ mountPoint, err := ctr.mountStorage()
+ if err == nil {
+ // Finish up mountStorage
+ ctr.state.Mounted = true
+ ctr.state.Mountpoint = mountPoint
+ if err = ctr.save(); err != nil {
+ logrus.Errorf("Error saving container %s state: %v", ctr.ID(), err)
+ }
+ }
+
+ return err
+}
+
// RestoreContainer re-creates a container from an imported checkpoint
func (r *Runtime) RestoreContainer(ctx context.Context, rSpec *spec.Spec, config *ContainerConfig) (*Container, error) {
r.lock.Lock()
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index b92588346..65951861b 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -22,6 +22,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
+
warn, err := generate.CompleteSpec(r.Context(), runtime, &sg)
if err != nil {
utils.InternalServerError(w, err)
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index b569f8390..4e3a86ae4 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -153,7 +153,15 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
if err != nil {
return nil, err
}
- return rt.NewContainer(ctx, runtimeSpec, options...)
+
+ ctr, err := rt.NewContainer(ctx, runtimeSpec, options...)
+ if err != nil {
+ return ctr, err
+ }
+
+ // Copy the content from the underlying image into the newly created
+ // volume if configured to do so.
+ return ctr, rt.PrepareVolumeOnCreateContainer(ctx, ctr)
}
func extractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption {
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index 37cacdaa3..fb7eb99a2 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -276,10 +276,11 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
return nil, err
}
+ volume.MountPath = dest
switch volumeSource.Type {
case KubeVolumeTypeBindMount:
mount := spec.Mount{
- Destination: dest,
+ Destination: volume.MountPath,
Source: volumeSource.Source,
Type: "bind",
Options: options,
@@ -287,7 +288,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
s.Mounts = append(s.Mounts, mount)
case KubeVolumeTypeNamed:
namedVolume := specgen.NamedVolume{
- Dest: dest,
+ Dest: volume.MountPath,
Name: volumeSource.Source,
Options: options,
}
@@ -330,12 +331,16 @@ func parseMountPath(mountPath string, readOnly bool) (string, []string, error) {
options = strings.Split(splitVol[1], ",")
}
if err := parse.ValidateVolumeCtrDir(dest); err != nil {
- return "", options, errors.Wrapf(err, "error in parsing MountPath")
+ return "", options, errors.Wrapf(err, "parsing MountPath")
}
if readOnly {
options = append(options, "ro")
}
- return dest, options, nil
+ opts, err := parse.ValidateVolumeOpts(options)
+ if err != nil {
+ return "", opts, errors.Wrapf(err, "parsing MountOptions")
+ }
+ return dest, opts, nil
}
func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, restartPolicy string) error {
diff --git a/test/README.md b/test/README.md
index d7710cc95..769bdbfd7 100644
--- a/test/README.md
+++ b/test/README.md
@@ -84,7 +84,7 @@ file itself. Consider the following actual test:
It("podman inspect bogus pod", func() {
session := podmanTest.Podman([]string{"pod", "inspect", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session).To(ExitWithError())
})
```
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 5a6cf7ffb..2e48e1763 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -811,7 +811,7 @@ func generateNetworkConfig(p *PodmanTestIntegration) (string, string) {
func (p *PodmanTestIntegration) removeCNINetwork(name string) {
session := p.Podman([]string{"network", "rm", "-f", name})
session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(BeNumerically("<=", 1))
+ Expect(session.ExitCode()).To(BeNumerically("<=", 1), "Exit code must be 0 or 1")
}
func (p *PodmanSessionIntegration) jq(jqCommand string) (string, error) {
diff --git a/test/e2e/container_create_volume_test.go b/test/e2e/container_create_volume_test.go
new file mode 100644
index 000000000..001698239
--- /dev/null
+++ b/test/e2e/container_create_volume_test.go
@@ -0,0 +1,127 @@
+package integration
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+
+ . "github.com/containers/podman/v3/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+func buildDataVolumeImage(pTest *PodmanTestIntegration, image, data, dest string) {
+ // Create a dummy file for data volume
+ dummyFile := filepath.Join(pTest.TempDir, data)
+ err := ioutil.WriteFile(dummyFile, []byte(data), 0644)
+ Expect(err).To(BeNil())
+
+ // Create a data volume container image but no CMD binary in it
+ containerFile := fmt.Sprintf(`FROM scratch
+CMD doesnotexist.sh
+ADD %s %s/
+VOLUME %s/`, data, dest, dest)
+ pTest.BuildImage(containerFile, image, "false")
+}
+
+func createContainersConfFile(pTest *PodmanTestIntegration) {
+ configPath := filepath.Join(pTest.TempDir, "containers.conf")
+ containersConf := []byte(fmt.Sprintf("[containers]\nprepare_volume_on_create = true\n"))
+ err := ioutil.WriteFile(configPath, containersConf, os.ModePerm)
+ Expect(err).To(BeNil())
+
+ // Set custom containers.conf file
+ os.Setenv("CONTAINERS_CONF", configPath)
+ if IsRemote() {
+ pTest.RestartRemoteService()
+ }
+}
+
+func checkDataVolumeContainer(pTest *PodmanTestIntegration, image, cont, dest, data string) {
+ create := pTest.Podman([]string{"create", "--name", cont, image})
+ create.WaitWithDefaultTimeout()
+ Expect(create).Should(Exit(0))
+
+ inspect := pTest.InspectContainer(cont)
+ Expect(len(inspect)).To(Equal(1))
+ Expect(len(inspect[0].Mounts)).To(Equal(1))
+ Expect(inspect[0].Mounts[0].Destination).To(Equal(dest))
+
+ mntName, mntSource := inspect[0].Mounts[0].Name, inspect[0].Mounts[0].Source
+
+ volList := pTest.Podman([]string{"volume", "list", "--quiet"})
+ volList.WaitWithDefaultTimeout()
+ Expect(volList).Should(Exit(0))
+ Expect(len(volList.OutputToStringArray())).To(Equal(1))
+ Expect(volList.OutputToStringArray()[0]).To(Equal(mntName))
+
+ // Check the mount source directory
+ files, err := ioutil.ReadDir(mntSource)
+ Expect(err).To(BeNil())
+
+ if data == "" {
+ Expect(len(files)).To(Equal(0))
+ } else {
+ Expect(len(files)).To(Equal(1))
+ Expect(files[0].Name()).To(Equal(data))
+ }
+}
+
+var _ = Describe("Podman create data volume", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+ os.Unsetenv("CONTAINERS_CONF")
+ })
+
+ It("podman create with volume data copy turned off", func() {
+ imgName, volData, volDest := "dataimg", "dummy", "/test"
+
+ buildDataVolumeImage(podmanTest, imgName, volData, volDest)
+
+ // Create a container with the default containers.conf and
+ // check that the volume is not copied from the image.
+ checkDataVolumeContainer(podmanTest, imgName, "ctr-nocopy", volDest, "")
+ })
+
+ It("podman create with volume data copy turned on", func() {
+ imgName, volData, volDest := "dataimg", "dummy", "/test"
+
+ buildDataVolumeImage(podmanTest, imgName, volData, volDest)
+
+ // Create a container with the custom containers.conf and
+ // check that the volume is copied from the image.
+ createContainersConfFile(podmanTest)
+
+ checkDataVolumeContainer(podmanTest, imgName, "ctr-copy", volDest, volData)
+ })
+
+ It("podman run with volume data copy turned on", func() {
+ // Create a container with the custom containers.conf and
+ // check that the container is run successfully
+ createContainersConfFile(podmanTest)
+
+ session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "echo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ })
+})
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index 63f55fb88..4c6788b9d 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -566,11 +566,11 @@ ENTRYPOINT ["sleep","99999"]
ns := "ns:/proc/self/ns/"
podCreate := podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
podCreate.WaitWithDefaultTimeout()
- Expect(podCreate.ExitCode()).To(Equal(0))
+ Expect(podCreate).Should(Exit(0))
podInspect := podmanTest.Podman([]string{"pod", "inspect", podName})
podInspect.WaitWithDefaultTimeout()
- Expect(podInspect.ExitCode()).To(Equal(0))
+ Expect(podInspect).Should(Exit(0))
podJSON := podInspect.InspectPodToJSON()
Expect(podJSON.InfraConfig.PidNS).To(Equal("path"))
@@ -579,11 +579,11 @@ ENTRYPOINT ["sleep","99999"]
podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
podCreate.WaitWithDefaultTimeout()
- Expect(podCreate.ExitCode()).To(Equal(0))
+ Expect(podCreate).Should(Exit(0))
podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
podInspect.WaitWithDefaultTimeout()
- Expect(podInspect.ExitCode()).To(Equal(0))
+ Expect(podInspect).Should(Exit(0))
podJSON = podInspect.InspectPodToJSON()
Expect(podJSON.InfraConfig.PidNS).To(Equal("pod"))
@@ -592,11 +592,11 @@ ENTRYPOINT ["sleep","99999"]
podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
podCreate.WaitWithDefaultTimeout()
- Expect(podCreate.ExitCode()).To(Equal(0))
+ Expect(podCreate).Should(Exit(0))
podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
podInspect.WaitWithDefaultTimeout()
- Expect(podInspect.ExitCode()).To(Equal(0))
+ Expect(podInspect).Should(Exit(0))
podJSON = podInspect.InspectPodToJSON()
Expect(podJSON.InfraConfig.PidNS).To(Equal("host"))
@@ -605,11 +605,11 @@ ENTRYPOINT ["sleep","99999"]
podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
podCreate.WaitWithDefaultTimeout()
- Expect(podCreate.ExitCode()).To(Equal(0))
+ Expect(podCreate).Should(Exit(0))
podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
podInspect.WaitWithDefaultTimeout()
- Expect(podInspect.ExitCode()).To(Equal(0))
+ Expect(podInspect).Should(Exit(0))
podJSON = podInspect.InspectPodToJSON()
Expect(podJSON.InfraConfig.PidNS).To(Equal("private"))
diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go
index 21f1a8650..e86718577 100644
--- a/test/e2e/run_exit_test.go
+++ b/test/e2e/run_exit_test.go
@@ -49,11 +49,7 @@ var _ = Describe("Podman run exit", func() {
It("podman run exit ExecErrorCodeNotFound", func() {
result := podmanTest.Podman([]string{"run", ALPINE, "foobar"})
result.WaitWithDefaultTimeout()
- Expect(result.ExitCode()).To(Not(Equal(define.ExecErrorCodeGeneric)))
- // TODO This is failing we believe because of a race condition
- // Between conmon and podman closing the socket early.
- // Test with the following, once the race condition is solved
- // Expect(result).Should(Exit(define.ExecErrorCodeNotFound))
+ Expect(result).Should(Exit(define.ExecErrorCodeNotFound))
})
It("podman run exit 0", func() {
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index aafe385c8..ee951ff21 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -4,17 +4,10 @@
#
load helpers
+load helpers.systemd
SERVICE_NAME="podman_test_$(random_string)"
-SYSTEMCTL="systemctl"
-UNIT_DIR="/usr/lib/systemd/system"
-if is_rootless; then
- UNIT_DIR="$HOME/.config/systemd/user"
- mkdir -p $UNIT_DIR
-
- SYSTEMCTL="$SYSTEMCTL --user"
-fi
UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service"
function setup() {
@@ -24,38 +17,28 @@ function setup() {
}
function teardown() {
- run '?' $SYSTEMCTL stop "$SERVICE_NAME"
+ run '?' systemctl stop "$SERVICE_NAME"
rm -f "$UNIT_FILE"
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
run_podman rmi -a
basic_teardown
}
-# Helper to setup xdg runtime for rootless
-function xdg_rootless() {
- # podman initializes this if unset, but systemctl doesn't
- if is_rootless; then
- if [ -z "$XDG_RUNTIME_DIR" ]; then
- export XDG_RUNTIME_DIR=/run/user/$(id -u)
- fi
- fi
-}
-
# Helper to start a systemd service running a container
function service_setup() {
run_podman generate systemd --new $cname
echo "$output" > "$UNIT_FILE"
run_podman rm $cname
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
- run $SYSTEMCTL start "$SERVICE_NAME"
+ run systemctl start "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Error starting systemd unit $SERVICE_NAME, output: $output"
fi
- run $SYSTEMCTL status "$SERVICE_NAME"
+ run systemctl status "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Non-zero status of systemd unit $SERVICE_NAME, output: $output"
fi
@@ -63,20 +46,18 @@ function service_setup() {
# Helper to stop a systemd service running a container
function service_cleanup() {
- run $SYSTEMCTL stop "$SERVICE_NAME"
+ run systemctl stop "$SERVICE_NAME"
if [ $status -ne 0 ]; then
die "Error stopping systemd unit $SERVICE_NAME, output: $output"
fi
rm -f "$UNIT_FILE"
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
}
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate - systemd - basic" {
- xdg_rootless
-
cname=$(random_string)
# See #7407 for --pull=always.
run_podman create --pull=always --name $cname --label "io.containers.autoupdate=registry" $IMAGE top
@@ -100,8 +81,6 @@ function service_cleanup() {
}
@test "podman autoupdate local" {
- xdg_rootless
-
cname=$(random_string)
run_podman create --name $cname --label "io.containers.autoupdate=local" $IMAGE top
@@ -128,8 +107,6 @@ function service_cleanup() {
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate systemd - envar" {
- xdg_rootless
-
cname=$(random_string)
FOO=value BAR=%s run_podman create --name $cname --env FOO -e BAR --env MYVAR=myval \
$IMAGE sh -c 'printenv && sleep 100'
diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats
index a73ed94e8..25eaba45b 100644
--- a/test/system/255-auto-update.bats
+++ b/test/system/255-auto-update.bats
@@ -4,14 +4,12 @@
#
load helpers
+load helpers.systemd
-UNIT_DIR="/usr/lib/systemd/system"
SNAME_FILE=$BATS_TMPDIR/services
function setup() {
skip_if_remote "systemd tests are meaningless over remote"
- skip_if_rootless
-
basic_setup
}
@@ -29,7 +27,7 @@ function teardown() {
rm -f $SNAME_FILE
run_podman ? rmi quay.io/libpod/alpine:latest
- run_podman ? rmi quay.io/libpod/alpine_nginx:latest
+ run_podman ? rmi quay.io/libpod/busybox:latest
run_podman ? rmi quay.io/libpod/localtest:latest
basic_teardown
}
@@ -58,8 +56,7 @@ function generate_service() {
fi
run_podman run -d --name $cname $label $target_img top -d 120
- run_podman generate systemd --new $cname
- echo "$output" > "$UNIT_DIR/container-$cname.service"
+ (cd $UNIT_DIR; run_podman generate systemd --new --files --name $cname)
echo "container-$cname" >> $SNAME_FILE
run_podman rm -f $cname
@@ -185,7 +182,7 @@ function _confirm_update() {
do
local img_base="alpine"
if [[ $auto_update == "registry" ]]; then
- img_base="alpine_nginx"
+ img_base="busybox"
elif [[ $auto_update == "local" ]]; then
img_base="localtest"
fi
diff --git a/test/system/270-socket-activation.bats b/test/system/270-socket-activation.bats
index 25206c6a7..031ba161b 100644
--- a/test/system/270-socket-activation.bats
+++ b/test/system/270-socket-activation.bats
@@ -4,21 +4,12 @@
#
load helpers
+load helpers.systemd
SERVICE_NAME="podman_test_$(random_string)"
-SYSTEMCTL="systemctl"
-UNIT_DIR="/usr/lib/systemd/system"
SERVICE_SOCK_ADDR="/run/podman/podman.sock"
-
if is_rootless; then
- UNIT_DIR="$HOME/.config/systemd/user"
- mkdir -p $UNIT_DIR
-
- SYSTEMCTL="$SYSTEMCTL --user"
- if [ -z "$XDG_RUNTIME_DIR" ]; then
- export XDG_RUNTIME_DIR=/run/user/$(id -u)
- fi
SERVICE_SOCK_ADDR="$XDG_RUNTIME_DIR/podman/podman.sock"
fi
@@ -66,13 +57,13 @@ EOF
rm -f $pause_pid
fi
fi
- $SYSTEMCTL start "$SERVICE_NAME.socket"
+ systemctl start "$SERVICE_NAME.socket"
}
function teardown() {
- $SYSTEMCTL stop "$SERVICE_NAME.socket"
+ systemctl stop "$SERVICE_NAME.socket"
rm -f "$SERVICE_FILE" "$SOCKET_FILE"
- $SYSTEMCTL daemon-reload
+ systemctl daemon-reload
basic_teardown
}
diff --git a/test/system/helpers.systemd.bash b/test/system/helpers.systemd.bash
new file mode 100644
index 000000000..4bde912a4
--- /dev/null
+++ b/test/system/helpers.systemd.bash
@@ -0,0 +1,30 @@
+# -*- bash -*-
+#
+# BATS helpers for systemd-related functionality
+#
+
+# podman initializes this if unset, but systemctl doesn't
+if [ -z "$XDG_RUNTIME_DIR" ]; then
+ if is_rootless; then
+ export XDG_RUNTIME_DIR=/run/user/$(id -u)
+ fi
+fi
+
+# For tests which write systemd unit files
+UNIT_DIR="/run/systemd/system"
+_DASHUSER=
+if is_rootless; then
+ UNIT_DIR="${XDG_RUNTIME_DIR}/systemd/user"
+ # Why isn't systemd smart enough to figure this out on its own?
+ _DASHUSER="--user"
+fi
+
+mkdir -p $UNIT_DIR
+
+systemctl() {
+ command systemctl $_DASHUSER "$@"
+}
+
+journalctl() {
+ command journalctl $_DASHUSER "$@"
+}