summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/10-images.at3
-rw-r--r--test/apiv2/20-containers.at18
-rw-r--r--test/apiv2/40-pods.at4
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py103
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_volume.py67
-rw-r--r--test/e2e/checkpoint_test.go129
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/containers_conf_test.go2
-rw-r--r--test/e2e/generate_kube_test.go122
-rw-r--r--test/e2e/image_scp_test.go22
-rw-r--r--test/e2e/images_test.go21
-rw-r--r--test/e2e/libpod_suite_remote_test.go16
-rw-r--r--test/e2e/libpod_suite_test.go14
-rw-r--r--test/e2e/logs_test.go69
-rw-r--r--test/e2e/manifest_test.go19
-rw-r--r--test/e2e/network_create_test.go6
-rw-r--r--test/e2e/play_kube_test.go70
-rw-r--r--test/e2e/pod_rm_test.go17
-rw-r--r--test/e2e/push_test.go4
-rw-r--r--test/e2e/run_networking_test.go37
-rw-r--r--test/e2e/run_test.go63
-rw-r--r--test/e2e/run_volume_test.go12
-rw-r--r--test/e2e/search_test.go38
-rw-r--r--test/e2e/system_connection_test.go29
-rw-r--r--test/e2e/system_dial_stdio_test.go53
-rw-r--r--test/e2e/system_reset_test.go2
-rw-r--r--test/e2e/system_service_test.go8
-rw-r--r--test/e2e/systemd_test.go17
-rw-r--r--test/e2e/trust_test.go63
-rw-r--r--test/e2e/unshare_test.go2
-rw-r--r--test/e2e/version_test.go10
-rw-r--r--test/registries.conf6
-rw-r--r--test/system/001-basic.bats19
-rw-r--r--test/system/015-help.bats6
-rw-r--r--test/system/030-run.bats5
-rw-r--r--test/system/035-logs.bats28
-rw-r--r--test/system/045-start.bats4
-rw-r--r--test/system/070-build.bats29
-rw-r--r--test/system/130-kill.bats15
-rw-r--r--test/system/160-volumes.bats38
-rw-r--r--test/system/200-pod.bats30
-rw-r--r--test/system/250-systemd.bats2
-rw-r--r--test/system/270-socket-activation.bats51
-rw-r--r--test/system/272-system-connection.bats156
-rw-r--r--test/system/410-selinux.bats70
-rw-r--r--test/system/500-networking.bats8
-rw-r--r--test/upgrade/test-upgrade.bats4
-rw-r--r--test/utils/podmantest_test.go2
-rw-r--r--test/utils/utils.go16
49 files changed, 1311 insertions, 220 deletions
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index d3fde9f9d..b7bcaf81d 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -218,6 +218,9 @@ if ! grep -q '400 Bad Request' "${TMPD}/headers.txt"; then
BUILD_TEST_ERROR="1"
fi
+t POST libpod/images/prune 200
+t POST libpod/images/prune 200 length=0 []
+
cleanBuildTest
if [[ "${BUILD_TEST_ERROR}" ]]; then
exit 1
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index afff68c22..748a0750f 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -379,3 +379,21 @@ t GET containers/$cid/json 200 \
.HostConfig.Tmpfs['"/mnt/scratch"']~.*mode=755.*
t DELETE containers/$cid?v=true 204
+
+# compat api: tmpfs without mount options
+payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch"}]}'
+t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+t GET containers/$cid/json 200 \
+ .HostConfig.Tmpfs['"/mnt/scratch"']~.*tmpcopyup.* \
+
+t DELETE containers/$cid?v=true 204
+
+# compat api: bind mount without mount options
+payload='{"Mounts":[{"Type":"bind","Source":"/tmp","Target":"/mnt"}]}'
+t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+t GET containers/$cid/json 200 \
+ .HostConfig.Binds[0]~/tmp:/mnt:.* \
+
+t DELETE containers/$cid?v=true 204
diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at
index 985b26411..f45e85f61 100644
--- a/test/apiv2/40-pods.at
+++ b/test/apiv2/40-pods.at
@@ -110,11 +110,11 @@ t GET libpod/pods/fakename/top 404 \
.cause="no such pod"
t GET libpod/pods/foo/top 200 \
- .Processes[0][-1]="/pause " \
+ .Processes[0][-1]="/pause" \
.Titles[-1]="COMMAND"
t GET libpod/pods/foo/top?ps_args=args,pid 200 \
- .Processes[0][0]="/pause " \
+ .Processes[0][0]="/pause" \
.Processes[0][1]="1" \
.Titles[0]="COMMAND" \
.Titles[1]="PID" \
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py
index 853e9da88..101044bbb 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_container.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py
@@ -1,8 +1,11 @@
+import multiprocessing
+import queue
import random
+import threading
import unittest
-import json
import requests
+import time
from dateutil.parser import parse
from .fixtures import APITestCase
@@ -16,7 +19,10 @@ class ContainerTestCase(APITestCase):
self.assertEqual(len(obj), 1)
def test_list_filters(self):
- r = requests.get(self.podman_url + "/v1.40/containers/json?filters%3D%7B%22status%22%3A%5B%22running%22%5D%7D")
+ r = requests.get(
+ self.podman_url
+ + "/v1.40/containers/json?filters%3D%7B%22status%22%3A%5B%22running%22%5D%7D"
+ )
self.assertEqual(r.status_code, 200, r.text)
payload = r.json()
containerAmnt = len(payload)
@@ -33,18 +39,18 @@ class ContainerTestCase(APITestCase):
self.assertId(r.content)
_ = parse(r.json()["Created"])
-
r = requests.post(
self.podman_url + "/v1.40/containers/create?name=topcontainer",
- json={"Cmd": ["top"],
- "Image": "alpine:latest",
- "Healthcheck": {
- "Test": ["CMD", "pidof", "top"],
- "Interval": 5000000000,
- "Timeout": 2000000000,
- "Retries": 3,
- "StartPeriod": 5000000000
- }
+ json={
+ "Cmd": ["top"],
+ "Image": "alpine:latest",
+ "Healthcheck": {
+ "Test": ["CMD", "pidof", "top"],
+ "Interval": 5000000000,
+ "Timeout": 2000000000,
+ "Retries": 3,
+ "StartPeriod": 5000000000,
+ },
},
)
self.assertEqual(r.status_code, 201, r.text)
@@ -67,7 +73,7 @@ class ContainerTestCase(APITestCase):
self.assertEqual(r.status_code, 200, r.text)
self.assertId(r.content)
out = r.json()
- hc = out["Config"]["Healthcheck"]["Test"]
+ hc = out["Config"]["Healthcheck"]["Test"]
self.assertListEqual(["CMD", "pidof", "top"], hc)
r = requests.post(self.podman_url + f"/v1.40/containers/{container_id}/start")
@@ -84,7 +90,9 @@ class ContainerTestCase(APITestCase):
self.assertIn(r.status_code, (200, 409), r.text)
if r.status_code == 200:
self.assertId(r.content)
- r = requests.get(self.uri(self.resolve_container("/containers/{}/stats?stream=false&one-shot=true")))
+ r = requests.get(
+ self.uri(self.resolve_container("/containers/{}/stats?stream=false&one-shot=true"))
+ )
self.assertIn(r.status_code, (200, 409), r.text)
if r.status_code == 200:
self.assertId(r.content)
@@ -136,9 +144,15 @@ class ContainerTestCase(APITestCase):
payload = r.json()
container_id = payload["Id"]
self.assertIsNotNone(container_id)
- r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=0")
+ r = requests.get(
+ self.podman_url
+ + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=0"
+ )
self.assertEqual(r.status_code, 200, r.text)
- r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=1")
+ r = requests.get(
+ self.podman_url
+ + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=1"
+ )
self.assertEqual(r.status_code, 200, r.text)
def test_commit(self):
@@ -257,6 +271,63 @@ class ContainerTestCase(APITestCase):
r = requests.delete(self.podman_url + f"/v1.40/containers/{container_id}")
self.assertEqual(r.status_code, 204, r.text)
+ def test_top_no_stream(self):
+ uri = self.uri(self.resolve_container("/containers/{}/top"))
+ q = queue.Queue()
+
+ def _impl(fifo):
+ fifo.put(requests.get(uri, params={"stream": False}, timeout=2))
+
+ top = threading.Thread(target=_impl, args=(q,))
+ top.start()
+ time.sleep(2)
+ self.assertFalse(top.is_alive(), f"GET {uri} failed to return in 2s")
+
+ qr = q.get(False)
+ self.assertEqual(qr.status_code, 200, qr.text)
+
+ qr.close()
+ top.join()
+
+ def test_top_stream(self):
+ uri = self.uri(self.resolve_container("/containers/{}/top"))
+ q = queue.Queue()
+
+ stop_thread = False
+
+ def _impl(fifo, stop):
+ try:
+ with requests.get(uri, params={"stream": True, "delay": 1}, stream=True) as r:
+ r.raise_for_status()
+ fifo.put(r)
+ for buf in r.iter_lines(chunk_size=None):
+ if stop():
+ break
+ fifo.put(buf)
+ except Exception:
+ pass
+
+ top = threading.Thread(target=_impl, args=(q, (lambda: stop_thread)))
+ top.start()
+ time.sleep(4)
+ self.assertTrue(top.is_alive(), f"GET {uri} exited too soon")
+ stop_thread = True
+
+ for _ in range(10):
+ try:
+ qr = q.get_nowait()
+ if qr is not None:
+ self.assertEqual(qr.status_code, 200)
+ qr.close()
+ break
+ except queue.Empty:
+ pass
+ finally:
+ time.sleep(1)
+ else:
+ self.fail("Server failed to respond in 10s")
+ top.join()
+
if __name__ == "__main__":
unittest.main()
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_volume.py b/test/apiv2/python/rest_api/test_v2_0_0_volume.py
index f5231e17c..2156318b0 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_volume.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_volume.py
@@ -7,7 +7,7 @@ from .fixtures import APITestCase
class VolumeTestCase(APITestCase):
- def test_volume(self):
+ def test_volume_crud(self):
name = f"Volume_{random.getrandbits(160):x}"
ls = requests.get(self.podman_url + "/v1.40/volumes")
@@ -70,6 +70,71 @@ class VolumeTestCase(APITestCase):
self.assertIn(name, payload["VolumesDeleted"])
self.assertGreater(payload["SpaceReclaimed"], 0)
+ def test_volume_label(self):
+ name = f"Volume_{random.getrandbits(160):x}"
+ expected = {
+ "Production": "False",
+ "Database": "Foxbase",
+ }
+
+ create = requests.post(
+ self.podman_url + "/v4.0.0/libpod/volumes/create",
+ json={"name": name, "label": expected},
+ )
+ self.assertEqual(create.status_code, 201, create.text)
+
+ inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json")
+ self.assertEqual(inspect.status_code, 200, inspect.text)
+
+ volume = inspect.json()
+ self.assertIn("Labels", volume)
+ self.assertNotIn("Label", volume)
+ self.assertDictEqual(expected, volume["Labels"])
+
+ def test_volume_labels(self):
+ name = f"Volume_{random.getrandbits(160):x}"
+ expected = {
+ "Production": "False",
+ "Database": "Foxbase",
+ }
+
+ create = requests.post(
+ self.podman_url + "/v4.0.0/libpod/volumes/create",
+ json={"name": name, "labels": expected},
+ )
+ self.assertEqual(create.status_code, 201, create.text)
+
+ inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json")
+ self.assertEqual(inspect.status_code, 200, inspect.text)
+
+ volume = inspect.json()
+ self.assertIn("Labels", volume)
+ self.assertDictEqual(expected, volume["Labels"])
+
+ def test_volume_label_override(self):
+ name = f"Volume_{random.getrandbits(160):x}"
+ create = requests.post(
+ self.podman_url + "/v4.0.0/libpod/volumes/create",
+ json={
+ "Name": name,
+ "Label": {
+ "Database": "dbase",
+ },
+ "Labels": {
+ "Database": "sqlserver",
+ },
+ },
+ )
+ self.assertEqual(create.status_code, 201, create.text)
+
+ inspect = requests.get(self.podman_url + f"/v4.0.0/libpod/volumes/{name}/json")
+ self.assertEqual(inspect.status_code, 200, inspect.text)
+
+ volume = inspect.json()
+ self.assertIn("Labels", volume)
+ self.assertNotIn("Label", volume)
+ self.assertDictEqual({"Database": "sqlserver"}, volume["Labels"])
+
if __name__ == "__main__":
unittest.main()
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 73ca5e1a6..be6b782b5 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -5,11 +5,15 @@ import (
"net"
"os"
"os/exec"
+ "path/filepath"
"strings"
+ "time"
+ "github.com/checkpoint-restore/go-criu/v5/stats"
"github.com/containers/podman/v3/pkg/checkpoint/crutils"
"github.com/containers/podman/v3/pkg/criu"
. "github.com/containers/podman/v3/test/utils"
+ "github.com/containers/podman/v3/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
@@ -247,16 +251,19 @@ var _ = Describe("Podman checkpoint", func() {
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+ if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
+ Fail("Container failed to get ready")
+ }
IP := podmanTest.Podman([]string{"inspect", "-l", "--format={{.NetworkSettings.IPAddress}}"})
IP.WaitWithDefaultTimeout()
Expect(IP).Should(Exit(0))
// Open a network connection to the redis server
- conn, err := net.Dial("tcp", IP.OutputToString()+":6379")
- if err != nil {
- os.Exit(1)
- }
+ conn, err := net.DialTimeout("tcp4", IP.OutputToString()+":6379", time.Duration(3)*time.Second)
+ Expect(err).To(BeNil())
+
// This should fail as the container has established TCP connections
result := podmanTest.Podman([]string{"container", "checkpoint", "-l"})
result.WaitWithDefaultTimeout()
@@ -933,18 +940,23 @@ var _ = Describe("Podman checkpoint", func() {
})
It("podman checkpoint and restore container with different port mappings", func() {
- localRunString := getRunString([]string{"-p", "1234:6379", "--rm", redis})
+ randomPort, err := utils.GetRandomPort()
+ Expect(err).ShouldNot(HaveOccurred())
+ localRunString := getRunString([]string{"-p", fmt.Sprintf("%d:6379", randomPort), "--rm", redis})
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
cid := session.OutputToString()
fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
- // Open a network connection to the redis server via initial port mapping
- conn, err := net.Dial("tcp", "localhost:1234")
- if err != nil {
- os.Exit(1)
+ if !WaitContainerReady(podmanTest, cid, "Ready to accept connections", 20, 1) {
+ Fail("Container failed to get ready")
}
+
+ fmt.Fprintf(os.Stderr, "Trying to connect to redis server at localhost:%d", randomPort)
+ // Open a network connection to the redis server via initial port mapping
+ conn, err := net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
+ Expect(err).ShouldNot(HaveOccurred())
conn.Close()
// Checkpoint the container
@@ -958,7 +970,9 @@ var _ = Describe("Podman checkpoint", func() {
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Restore container with different port mapping
- result = podmanTest.Podman([]string{"container", "restore", "-p", "1235:6379", "-i", fileName})
+ newRandomPort, err := utils.GetRandomPort()
+ Expect(err).ShouldNot(HaveOccurred())
+ result = podmanTest.Podman([]string{"container", "restore", "-p", fmt.Sprintf("%d:6379", newRandomPort), "-i", fileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@@ -967,13 +981,12 @@ var _ = Describe("Podman checkpoint", func() {
// Open a network connection to the redis server via initial port mapping
// This should fail
- conn, err = net.Dial("tcp", "localhost:1234")
+ conn, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", randomPort), time.Duration(3)*time.Second)
Expect(err.Error()).To(ContainSubstring("connection refused"))
// Open a network connection to the redis server via new port mapping
- conn, err = net.Dial("tcp", "localhost:1235")
- if err != nil {
- os.Exit(1)
- }
+ fmt.Fprintf(os.Stderr, "Trying to reconnect to redis server at localhost:%d", newRandomPort)
+ conn, err = net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", newRandomPort), time.Duration(3)*time.Second)
+ Expect(err).ShouldNot(HaveOccurred())
conn.Close()
result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
@@ -1145,4 +1158,90 @@ var _ = Describe("Podman checkpoint", func() {
os.Remove(fileName)
})
}
+
+ It("podman checkpoint container with export (migration) and --ipc host", func() {
+ localRunString := getRunString([]string{"--rm", "--ipc", "host", ALPINE, "top"})
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ cid := session.OutputToString()
+ fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
+
+ result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
+ result.WaitWithDefaultTimeout()
+
+ // As the container has been started with '--rm' it will be completely
+ // cleaned up after checkpointing.
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(0))
+
+ result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(0))
+
+ // Remove exported checkpoint
+ os.Remove(fileName)
+ })
+
+ It("podman checkpoint container with export and statistics", func() {
+ localRunString := getRunString([]string{
+ "--rm",
+ ALPINE,
+ "top",
+ })
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ cid := session.OutputToString()
+ fileName := "/tmp/checkpoint-" + cid + ".tar.gz"
+
+ result := podmanTest.Podman([]string{
+ "container",
+ "checkpoint",
+ "-l", "-e",
+ fileName,
+ })
+ result.WaitWithDefaultTimeout()
+
+ // As the container has been started with '--rm' it will be completely
+ // cleaned up after checkpointing.
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.NumberOfContainers()).To(Equal(0))
+
+ // Extract checkpoint archive
+ destinationDirectory, err := CreateTempDirInTempDir()
+ Expect(err).ShouldNot(HaveOccurred())
+
+ tarsession := SystemExec(
+ "tar",
+ []string{
+ "xf",
+ fileName,
+ "-C",
+ destinationDirectory,
+ },
+ )
+ Expect(tarsession).Should(Exit(0))
+
+ _, err = os.Stat(filepath.Join(destinationDirectory, stats.StatsDump))
+ Expect(err).ShouldNot(HaveOccurred())
+
+ Expect(os.RemoveAll(destinationDirectory)).To(BeNil())
+
+ // Remove exported checkpoint
+ os.Remove(fileName)
+ })
})
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 7228682f3..e598f7ab9 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -685,7 +685,7 @@ func SkipIfContainerized(reason string) {
// PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment
func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, cwd string, env []string) *PodmanSessionIntegration {
- podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil)
+ podmanSession := p.PodmanAsUserBase(args, uid, gid, cwd, env, false, false, nil, nil)
return &PodmanSessionIntegration{podmanSession}
}
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index fac200c3c..2faad8d91 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -445,7 +445,7 @@ var _ = Describe("Podman run", func() {
Expect(session.ErrorToString()).To(ContainSubstring("invalid image_copy_tmp_dir"))
})
- It("podman system sevice --help shows (default 20)", func() {
+ It("podman system service --help shows (default 20)", func() {
SkipIfRemote("this test is only for local")
result := podmanTest.Podman([]string{"system", "service", "--help"})
result.WaitWithDefaultTimeout()
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 3e6f1e8c4..cd382eba9 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"strconv"
+ "strings"
"github.com/containers/podman/v3/libpod/define"
@@ -66,6 +67,10 @@ var _ = Describe("Podman generate kube", func() {
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
Expect(pod.Spec.HostNetwork).To(Equal(false))
+ Expect(pod.Spec.SecurityContext).To(BeNil())
+ Expect(pod.Spec.DNSConfig).To(BeNil())
+ Expect(pod.Spec.Containers[0].WorkingDir).To(Equal(""))
+ Expect(pod.Spec.Containers[0].Env).To(BeNil())
numContainers := 0
for range pod.Spec.Containers {
@@ -102,6 +107,7 @@ var _ = Describe("Podman generate kube", func() {
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
Expect(kube.OutputToString()).To(ContainSubstring("type: spc_t"))
+
})
It("podman generate service kube on container with --security-opt type", func() {
@@ -119,20 +125,28 @@ var _ = Describe("Podman generate kube", func() {
Expect(kube.OutputToString()).To(ContainSubstring("type: foo_bar_t"))
})
- It("podman generate service kube on container", func() {
- session := podmanTest.RunTopContainer("top")
+ It("podman generate service kube on container - targetPort should match port name", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "test-ctr", "-p", "3890:3890", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "-s", "top"})
+ kube := podmanTest.Podman([]string{"generate", "kube", "-s", "test-ctr"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // TODO - test generated YAML - service produces multiple
- // structs.
- // pod := new(v1.Pod)
- // err := yaml.Unmarshal([]byte(kube.OutputToString()), pod)
- // Expect(err).To(BeNil())
+ // Separate out the Service and Pod yaml
+ arr := strings.Split(string(kube.Out.Contents()), "---")
+ Expect(len(arr)).To(Equal(2))
+
+ svc := new(v1.Service)
+ err := yaml.Unmarshal([]byte(arr[0]), svc)
+ Expect(err).To(BeNil())
+ Expect(len(svc.Spec.Ports)).To(Equal(1))
+ Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(3890))
+
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal([]byte(arr[1]), pod)
+ Expect(err).To(BeNil())
})
It("podman generate kube on pod", func() {
@@ -315,21 +329,28 @@ var _ = Describe("Podman generate kube", func() {
})
It("podman generate service kube on pod", func() {
- _, rc, _ := podmanTest.CreatePod(map[string][]string{"--name": {"toppod"}})
- Expect(rc).To(Equal(0))
-
- session := podmanTest.RunTopContainerInPod("topcontainer", "toppod")
+ session := podmanTest.Podman([]string{"create", "--pod", "new:test-pod", "-p", "4000:4000/udp", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "-s", "toppod"})
+ kube := podmanTest.Podman([]string{"generate", "kube", "-s", "test-pod"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // TODO: How do we test unmarshal with a service? We have two
- // structs that need to be unmarshalled...
- // _, err := yaml.Marshal(kube.OutputToString())
- // Expect(err).To(BeNil())
+ // Separate out the Service and Pod yaml
+ arr := strings.Split(string(kube.Out.Contents()), "---")
+ Expect(len(arr)).To(Equal(2))
+
+ svc := new(v1.Service)
+ err := yaml.Unmarshal([]byte(arr[0]), svc)
+ Expect(err).To(BeNil())
+ Expect(len(svc.Spec.Ports)).To(Equal(1))
+ Expect(svc.Spec.Ports[0].TargetPort.IntValue()).To(Equal(4000))
+ Expect(svc.Spec.Ports[0].Protocol).To(Equal(v1.ProtocolUDP))
+
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal([]byte(arr[1]), pod)
+ Expect(err).To(BeNil())
})
It("podman generate kube on pod with restartPolicy", func() {
@@ -451,6 +472,10 @@ var _ = Describe("Podman generate kube", func() {
foundOtherPort := 0
for _, ctr := range pod.Spec.Containers {
for _, port := range ctr.Ports {
+ // Since we are using tcp here, the generated kube yaml shouldn't
+ // have anything for protocol under the ports as tcp is the default
+ // for k8s
+ Expect(port.Protocol).To(BeEmpty())
if port.HostPort == 4000 {
foundPort4000 = foundPort4000 + 1
} else if port.HostPort == 5000 {
@@ -463,6 +488,24 @@ var _ = Describe("Podman generate kube", func() {
Expect(foundPort4000).To(Equal(1))
Expect(foundPort5000).To(Equal(1))
Expect(foundOtherPort).To(Equal(0))
+
+ // Create container with UDP port and check the generated kube yaml
+ ctrWithUDP := podmanTest.Podman([]string{"create", "--pod", "new:test-pod", "-p", "6666:66/udp", ALPINE, "top"})
+ ctrWithUDP.WaitWithDefaultTimeout()
+ Expect(ctrWithUDP).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "test-pod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ containers := pod.Spec.Containers
+ Expect(len(containers)).To(Equal(1))
+ Expect(len(containers[0].Ports)).To(Equal(1))
+ Expect(containers[0].Ports[0].Protocol).To(Equal(v1.ProtocolUDP))
})
It("podman generate and reimport kube on pod", func() {
@@ -803,7 +846,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(containers[0].Args).To(Equal([]string{"10s"}))
})
- It("podman generate kube - no command", func() {
+ It("podman generate kube - use command from image unless explicitly set in the podman command", func() {
session := podmanTest.Podman([]string{"create", "--name", "test", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -812,8 +855,8 @@ var _ = Describe("Podman generate kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // Now make sure that the container's command is not set to the
- // entrypoint and it's arguments to "10s".
+ // Now make sure that the container's command in the kube yaml is not set to the
+ // image command.
pod := new(v1.Pod)
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
@@ -831,8 +874,8 @@ var _ = Describe("Podman generate kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // Now make sure that the container's command is not set to the
- // entrypoint and it's arguments to "10s".
+ // Now make sure that the container's command in the kube yaml is set to the
+ // command passed via the cli to podman create.
pod = new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
@@ -842,10 +885,10 @@ var _ = Describe("Podman generate kube", func() {
Expect(containers[0].Command).To(Equal(cmd))
})
- It("podman generate kube - use entrypoint from image", func() {
+ It("podman generate kube - use entrypoint from image unless --entrypoint is set", func() {
// Build an image with an entrypoint.
containerfile := `FROM quay.io/libpod/alpine:latest
-ENTRYPOINT /bin/sleep`
+ENTRYPOINT ["sleep"]`
targetPath, err := CreateTempDirInTempDir()
Expect(err).To(BeNil())
@@ -866,17 +909,34 @@ ENTRYPOINT /bin/sleep`
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- // Now make sure that the container's command is set to the
- // entrypoint and it's arguments to "10s".
+ // Now make sure that the container's command in the kube yaml is NOT set to the
+ // entrypoint but the arguments should be set to "10s".
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
containers := pod.Spec.Containers
Expect(len(containers)).To(Equal(1))
-
- Expect(containers[0].Command).To(Equal([]string{"/bin/sh", "-c", "/bin/sleep"}))
Expect(containers[0].Args).To(Equal([]string{"10s"}))
+
+ session = podmanTest.Podman([]string{"create", "--pod", "new:testpod-2", "--entrypoint", "echo", image, "hello"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube = podmanTest.Podman([]string{"generate", "kube", "testpod-2"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ // Now make sure that the container's command in the kube yaml is set to the
+ // entrypoint defined by the --entrypoint flag and the arguments should be set to "hello".
+ pod = new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ containers = pod.Spec.Containers
+ Expect(len(containers)).To(Equal(1))
+ Expect(containers[0].Command).To(Equal([]string{"echo"}))
+ Expect(containers[0].Args).To(Equal([]string{"hello"}))
})
It("podman generate kube - --privileged container", func() {
@@ -942,7 +1002,7 @@ USER test1`
pod := new(v1.Pod)
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
- Expect(*pod.Spec.Containers[0].SecurityContext.RunAsUser).To(Equal(int64(10001)))
+ Expect(pod.Spec.Containers[0].SecurityContext.RunAsUser).To(BeNil())
})
It("podman generate kube on named volume", func() {
@@ -1024,7 +1084,7 @@ USER test1`
top1.WaitWithDefaultTimeout()
Expect(top1).Should(Exit(0))
- top2 := podmanTest.Podman([]string{"run", "-dt", "--name", "top2", "--pod", "pod1", "--label", "io.containers.autoupdate=registry", "--label", "io.containers.autoupdate.authfile=/some/authfile.json", ALPINE, "top"})
+ top2 := podmanTest.Podman([]string{"run", "-dt", "--name", "top2", "--workdir", "/root", "--pod", "pod1", "--label", "io.containers.autoupdate=registry", "--label", "io.containers.autoupdate.authfile=/some/authfile.json", ALPINE, "top"})
top2.WaitWithDefaultTimeout()
Expect(top2).Should(Exit(0))
@@ -1035,6 +1095,8 @@ USER test1`
pod := new(v1.Pod)
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
+ Expect(pod.Spec.Containers[0].WorkingDir).To(Equal(""))
+ Expect(pod.Spec.Containers[1].WorkingDir).To(Equal("/root"))
for _, ctr := range []string{"top1", "top2"} {
v, ok := pod.GetAnnotations()["io.containers.autoupdate/"+ctr]
diff --git a/test/e2e/image_scp_test.go b/test/e2e/image_scp_test.go
index 9fd8d7e27..acea2993d 100644
--- a/test/e2e/image_scp_test.go
+++ b/test/e2e/image_scp_test.go
@@ -22,12 +22,14 @@ var _ = Describe("podman image scp", func() {
)
BeforeEach(func() {
+
ConfPath.Value, ConfPath.IsSet = os.LookupEnv("CONTAINERS_CONF")
conf, err := ioutil.TempFile("", "containersconf")
if err != nil {
panic(err)
}
os.Setenv("CONTAINERS_CONF", conf.Name())
+
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -38,6 +40,7 @@ var _ = Describe("podman image scp", func() {
AfterEach(func() {
podmanTest.Cleanup()
+
os.Remove(os.Getenv("CONTAINERS_CONF"))
if ConfPath.IsSet {
os.Setenv("CONTAINERS_CONF", ConfPath.Value)
@@ -58,6 +61,25 @@ var _ = Describe("podman image scp", func() {
Expect(scp).To(Exit(0))
})
+ It("podman image scp root to rootless transfer", func() {
+ SkipIfNotRootless("this is a rootless only test, transfering from root to rootless using PodmanAsUser")
+ if IsRemote() {
+ Skip("this test is only for non-remote")
+ }
+ env := os.Environ()
+ img := podmanTest.PodmanAsUser([]string{"image", "pull", ALPINE}, 0, 0, "", env) // pull image to root
+ img.WaitWithDefaultTimeout()
+ Expect(img).To(Exit(0))
+ scp := podmanTest.PodmanAsUser([]string{"image", "scp", "root@localhost::" + ALPINE, "1000:1000@localhost::"}, 0, 0, "", env) //transfer from root to rootless (us)
+ scp.WaitWithDefaultTimeout()
+ Expect(scp).To(Exit(0))
+
+ list := podmanTest.Podman([]string{"image", "list"}) // our image should now contain alpine loaded in from root
+ list.WaitWithDefaultTimeout()
+ Expect(list).To(Exit(0))
+ Expect(list.LineInOutputStartsWith("quay.io/libpod/alpine")).To(BeTrue())
+ })
+
It("podman image scp bogus image", func() {
if IsRemote() {
Skip("this test is only for non-remote")
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index b4ec7447e..56af64f04 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -446,4 +446,25 @@ RUN > file2
})
+ It("podman builder prune", func() {
+ dockerfile := `FROM quay.io/libpod/alpine:latest
+RUN > file
+`
+ dockerfile2 := `FROM quay.io/libpod/alpine:latest
+RUN > file2
+`
+ podmanTest.BuildImageWithLabel(dockerfile, "foobar.com/workdir:latest", "false", "abc")
+ podmanTest.BuildImageWithLabel(dockerfile2, "foobar.com/workdir:latest", "false", "xyz")
+ // --force used to to avoid y/n question
+ result := podmanTest.Podman([]string{"builder", "prune", "--filter", "label=abc", "--force"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(len(result.OutputToStringArray())).To(Equal(1))
+
+ //check if really abc is removed
+ result = podmanTest.Podman([]string{"image", "list", "--filter", "label=abc"})
+ Expect(len(result.OutputToStringArray())).To(Equal(0))
+
+ })
+
})
diff --git a/test/e2e/libpod_suite_remote_test.go b/test/e2e/libpod_suite_remote_test.go
index 3115c246f..ad511cc9e 100644
--- a/test/e2e/libpod_suite_remote_test.go
+++ b/test/e2e/libpod_suite_remote_test.go
@@ -38,11 +38,25 @@ func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration
return &PodmanSessionIntegration{podmanSession}
}
+// PodmanSystemdScope runs the podman command in a new systemd scope
+func (p *PodmanTestIntegration) PodmanSystemdScope(args []string) *PodmanSessionIntegration {
+ var remoteArgs = []string{"--remote", "--url", p.RemoteSocket}
+ remoteArgs = append(remoteArgs, args...)
+
+ wrapper := []string{"systemd-run", "--scope"}
+ if rootless.IsRootless() {
+ wrapper = []string{"systemd-run", "--scope", "--user"}
+ }
+
+ podmanSession := p.PodmanAsUserBase(remoteArgs, 0, 0, "", nil, false, false, wrapper, nil)
+ return &PodmanSessionIntegration{podmanSession}
+}
+
// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
var remoteArgs = []string{"--remote", "--url", p.RemoteSocket}
remoteArgs = append(remoteArgs, args...)
- podmanSession := p.PodmanAsUserBase(remoteArgs, 0, 0, "", nil, false, false, extraFiles)
+ podmanSession := p.PodmanAsUserBase(remoteArgs, 0, 0, "", nil, false, false, nil, extraFiles)
return &PodmanSessionIntegration{podmanSession}
}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index cc03ccc96..6d2d3fee8 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -8,6 +8,8 @@ import (
"os"
"path/filepath"
"strings"
+
+ "github.com/containers/podman/v3/pkg/rootless"
)
func IsRemote() bool {
@@ -23,9 +25,19 @@ func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration
return &PodmanSessionIntegration{podmanSession}
}
+// PodmanSystemdScope runs the podman command in a new systemd scope
+func (p *PodmanTestIntegration) PodmanSystemdScope(args []string) *PodmanSessionIntegration {
+ wrapper := []string{"systemd-run", "--scope"}
+ if rootless.IsRootless() {
+ wrapper = []string{"systemd-run", "--scope", "--user"}
+ }
+ podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, wrapper, nil)
+ return &PodmanSessionIntegration{podmanSession}
+}
+
// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
- podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, extraFiles)
+ podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, nil, extraFiles)
return &PodmanSessionIntegration{podmanSession}
}
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 314e09b9a..3beabec4b 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -13,6 +13,19 @@ import (
. "github.com/onsi/gomega/gexec"
)
+func isEventBackendJournald(podmanTest *PodmanTestIntegration) bool {
+ if !podmanTest.RemoteTest {
+ // If not remote test, '--events-backend' is set to 'file' or 'none'
+ return false
+ }
+ info := podmanTest.Podman([]string{"info", "--format", "{{.Host.EventLogger}}"})
+ info.WaitWithDefaultTimeout()
+ if info.OutputToString() == "journald" {
+ return true
+ }
+ return false
+}
+
var _ = Describe("Podman logs", func() {
var (
tempdir string
@@ -38,8 +51,18 @@ var _ = Describe("Podman logs", func() {
})
for _, log := range []string{"k8s-file", "journald", "json-file"} {
+ // This is important to move the 'log' var to the correct scope under Ginkgo flow.
+ log := log
+
+ skipIfJournaldInContainer := func() {
+ if log == "journald" {
+ SkipIfInContainer("journalctl inside a container doesn't work correctly")
+ }
+ }
It("all lines: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -53,6 +76,8 @@ var _ = Describe("Podman logs", func() {
})
It("tail two lines: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -65,6 +90,8 @@ var _ = Describe("Podman logs", func() {
})
It("tail zero lines: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -77,6 +104,8 @@ var _ = Describe("Podman logs", func() {
})
It("tail 99 lines: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -89,6 +118,8 @@ var _ = Describe("Podman logs", func() {
})
It("tail 800 lines: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "i=1; while [ \"$i\" -ne 1000 ]; do echo \"line $i\"; i=$((i + 1)); done"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -101,6 +132,8 @@ var _ = Describe("Podman logs", func() {
})
It("tail 2 lines with timestamps: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -113,6 +146,8 @@ var _ = Describe("Podman logs", func() {
})
It("since time 2017-08-07: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -125,6 +160,8 @@ var _ = Describe("Podman logs", func() {
})
It("since duration 10m: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -137,6 +174,8 @@ var _ = Describe("Podman logs", func() {
})
It("until duration 10m: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -149,6 +188,7 @@ var _ = Describe("Podman logs", func() {
})
It("until time NOW: "+log, func() {
+ skipIfJournaldInContainer()
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
logc.WaitWithDefaultTimeout()
@@ -165,13 +205,17 @@ var _ = Describe("Podman logs", func() {
})
It("latest and container name should fail: "+log, func() {
+ skipIfJournaldInContainer()
+
results := podmanTest.Podman([]string{"logs", "-l", "foobar"})
results.WaitWithDefaultTimeout()
Expect(results).To(ExitWithError())
})
It("two containers showing short container IDs: "+log, func() {
+ skipIfJournaldInContainer()
SkipIfRemote("FIXME: podman-remote logs does not support showing two containers at the same time")
+
log1 := podmanTest.Podman([]string{"run", "--log-driver", log, "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"})
log1.WaitWithDefaultTimeout()
Expect(log1).Should(Exit(0))
@@ -192,6 +236,8 @@ var _ = Describe("Podman logs", func() {
})
It("podman logs on a created container should result in 0 exit code: "+log, func() {
+ skipIfJournaldInContainer()
+
session := podmanTest.Podman([]string{"create", "--log-driver", log, "-t", "--name", "log", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).To(Exit(0))
@@ -202,6 +248,8 @@ var _ = Describe("Podman logs", func() {
})
It("streaming output: "+log, func() {
+ skipIfJournaldInContainer()
+
containerName := "logs-f"
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", containerName, "-dt", ALPINE, "sh", "-c", "echo podman-1; sleep 1; echo podman-2"})
@@ -210,6 +258,14 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "-f", containerName})
results.WaitWithDefaultTimeout()
+
+ if log == "journald" && !isEventBackendJournald(podmanTest) {
+ // --follow + journald log-driver is only supported with journald events-backend(PR #10431)
+ Expect(results).To(Exit(125))
+ Expect(results.ErrorToString()).To(ContainSubstring("using --follow with the journald --log-driver but without the journald --events-backend"))
+ return
+ }
+
Expect(results).To(Exit(0))
Expect(results.OutputToString()).To(ContainSubstring("podman-1"))
@@ -233,6 +289,8 @@ var _ = Describe("Podman logs", func() {
})
It("follow output stopped container: "+log, func() {
+ skipIfJournaldInContainer()
+
containerName := "logs-f"
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", containerName, "-d", ALPINE, "true"})
@@ -241,10 +299,17 @@ var _ = Describe("Podman logs", func() {
results := podmanTest.Podman([]string{"logs", "-f", containerName})
results.WaitWithDefaultTimeout()
+ if log == "journald" && !isEventBackendJournald(podmanTest) {
+ // --follow + journald log-driver is only supported with journald events-backend(PR #10431)
+ Expect(results).To(Exit(125))
+ return
+ }
Expect(results).To(Exit(0))
})
It("using container with container log-size: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--log-opt=max-size=10k", "-d", ALPINE, "sh", "-c", "echo podman podman podman"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -266,6 +331,8 @@ var _ = Describe("Podman logs", func() {
})
It("Make sure logs match expected length: "+log, func() {
+ skipIfJournaldInContainer()
+
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "-t", "--name", "test", ALPINE, "sh", "-c", "echo 1; echo 2"})
logc.WaitWithDefaultTimeout()
Expect(logc).To(Exit(0))
@@ -284,6 +351,8 @@ var _ = Describe("Podman logs", func() {
})
It("podman logs test stdout and stderr: "+log, func() {
+ skipIfJournaldInContainer()
+
cname := "log-test"
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", cname, ALPINE, "sh", "-c", "echo stdout; echo stderr >&2"})
logc.WaitWithDefaultTimeout()
diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go
index 27aaaba48..5978214ff 100644
--- a/test/e2e/manifest_test.go
+++ b/test/e2e/manifest_test.go
@@ -93,6 +93,25 @@ var _ = Describe("Podman manifest", func() {
Expect(session.OutputToString()).To(ContainSubstring(imageListARM64InstanceDigest))
})
+ It("podman manifest tag", func() {
+ session := podmanTest.Podman([]string{"manifest", "create", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"manifest", "add", "foobar", "quay.io/libpod/busybox"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"tag", "foobar", "foobar2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"manifest", "inspect", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session2 := podmanTest.Podman([]string{"manifest", "inspect", "foobar2"})
+ session2.WaitWithDefaultTimeout()
+ Expect(session2).Should(Exit(0))
+ Expect(session2.OutputToString()).To(Equal(session.OutputToString()))
+ })
+
It("podman manifest add --all", func() {
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index ae9f112b5..c9e13e7d2 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -43,7 +43,7 @@ var _ = Describe("Podman network create", func() {
It("podman network create with name and subnet", func() {
netName := "subnet-" + stringid.GenerateNonCryptoID()
- nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", netName})
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ip-range", "10.11.12.0/26", netName})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeCNINetwork(netName)
Expect(nc).Should(Exit(0))
@@ -61,7 +61,11 @@ var _ = Describe("Podman network create", func() {
result := results[0]
Expect(result.Name).To(Equal(netName))
Expect(result.Subnets).To(HaveLen(1))
+ Expect(result.Subnets[0].Subnet.String()).To(Equal("10.11.12.0/24"))
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.11.12.1"))
+ Expect(result.Subnets[0].LeaseRange).ToNot(BeNil())
+ Expect(result.Subnets[0].LeaseRange.StartIP.String()).To(Equal("10.11.12.1"))
+ Expect(result.Subnets[0].LeaseRange.EndIP.String()).To(Equal("10.11.12.63"))
// Once a container executes a new network, the nic will be created. We should clean those up
// best we can
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 079bb53b5..b0b927445 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -11,13 +11,13 @@ import (
"text/template"
"time"
- "github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
"github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ "github.com/onsi/gomega/format"
. "github.com/onsi/gomega/gexec"
"github.com/opencontainers/selinux/go-selinux"
)
@@ -1119,24 +1119,6 @@ var _ = Describe("Podman play kube", func() {
Expect(label).To(ContainSubstring("unconfined_u:system_r:spc_t:s0"))
})
- It("podman play kube should use default infra_image", func() {
- err := writeYaml(checkInfraImagePodYaml, kubeYaml)
- Expect(err).To(BeNil())
-
- kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
- kube.WaitWithDefaultTimeout()
- Expect(kube).Should(Exit(0))
-
- podInspect := podmanTest.Podman([]string{"inspect", "check-infra-image", "--format", "{{ .InfraContainerID }}"})
- podInspect.WaitWithDefaultTimeout()
- infraContainerID := podInspect.OutputToString()
-
- conInspect := podmanTest.Podman([]string{"inspect", infraContainerID, "--format", "{{ .ImageName }}"})
- conInspect.WaitWithDefaultTimeout()
- infraContainerImage := conInspect.OutputToString()
- Expect(infraContainerImage).To(Equal(config.DefaultInfraImage))
- })
-
It("podman play kube --no-host", func() {
err := writeYaml(checkInfraImagePodYaml, kubeYaml)
Expect(err).To(BeNil())
@@ -2420,14 +2402,19 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
err := generateKubeYaml("pod", pod, kubeYaml)
Expect(err).To(BeNil())
- kube := podmanTest.Podman([]string{"play", "kube", "--log-driver", "journald", kubeYaml})
+ kube := podmanTest.Podman([]string{"play", "kube", "--log-opt=max-size=10k", "--log-driver", "journald", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .HostConfig.LogConfig.Type }}'"})
+ cid := getCtrNameInPod(pod)
+ inspect := podmanTest.Podman([]string{"inspect", cid, "--format", "'{{ .HostConfig.LogConfig.Type }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
Expect(inspect.OutputToString()).To(ContainSubstring("journald"))
+ inspect = podmanTest.Podman([]string{"container", "inspect", "--format", "{{.HostConfig.LogConfig.Size}}", cid})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).To(Exit(0))
+ Expect(inspect.OutputToString()).To(Equal("10kB"))
})
It("podman play kube test only creating the containers", func() {
@@ -2852,4 +2839,45 @@ invalid kube kind
Expect(ls).Should(Exit(0))
Expect(len(ls.OutputToStringArray())).To(Equal(1))
})
+
+ Describe("verify environment variables", func() {
+ var maxLength int
+ BeforeEach(func() {
+ maxLength = format.MaxLength
+ format.MaxLength = 0
+ })
+ AfterEach(func() {
+ format.MaxLength = maxLength
+ })
+
+ It("values containing equal sign", func() {
+ javaToolOptions := `-XX:+IgnoreUnrecognizedVMOptions -XX:+IdleTuningGcOnIdle -Xshareclasses:name=openj9_system_scc,cacheDir=/opt/java/.scc,readonly,nonFatal`
+ openj9JavaOptions := `-XX:+IgnoreUnrecognizedVMOptions -XX:+IdleTuningGcOnIdle -Xshareclasses:name=openj9_system_scc,cacheDir=/opt/java/.scc,readonly,nonFatal -Dosgi.checkConfiguration=false`
+
+ containerfile := fmt.Sprintf(`FROM %s
+ENV JAVA_TOOL_OPTIONS=%q
+ENV OPENJ9_JAVA_OPTIONS=%q
+`,
+ ALPINE, javaToolOptions, openj9JavaOptions)
+
+ image := "podman-kube-test:env"
+ podmanTest.BuildImage(containerfile, image, "false")
+ ctnr := getCtr(withImage(image))
+ pod := getPod(withCtr(ctnr))
+ Expect(generateKubeYaml("pod", pod, kubeYaml)).Should(Succeed())
+
+ play := podmanTest.Podman([]string{"play", "kube", "--start", kubeYaml})
+ play.WaitWithDefaultTimeout()
+ Expect(play).Should(Exit(0))
+
+ inspect := podmanTest.Podman([]string{"container", "inspect", "--format=json", getCtrNameInPod(pod)})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+
+ contents := string(inspect.Out.Contents())
+ Expect(contents).To(ContainSubstring(javaToolOptions))
+ Expect(contents).To(ContainSubstring(openj9JavaOptions))
+ })
+ })
+
})
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index 6a8ac72fb..7dc3dfa7f 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -301,4 +301,21 @@ var _ = Describe("Podman pod rm", func() {
Expect(session).Should(Exit(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
+
+ It("podman pod rm with exited containers", func() {
+ _, ec, podid := podmanTest.CreatePod(nil)
+ Expect(ec).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"run", "--pod", podid, ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--pod", podid, ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ result := podmanTest.Podman([]string{"pod", "rm", podid})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ })
})
diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go
index b7e8309fb..7b35acd35 100644
--- a/test/e2e/push_test.go
+++ b/test/e2e/push_test.go
@@ -146,7 +146,7 @@ var _ = Describe("Podman push", func() {
session = podmanTest.Podman([]string{"logs", "registry"})
session.WaitWithDefaultTimeout()
- push := podmanTest.Podman([]string{"push", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"})
+ push := podmanTest.Podman([]string{"push", "--tls-verify=true", "--format=v2s2", "--creds=podmantest:test", ALPINE, "localhost:5000/tlstest"})
push.WaitWithDefaultTimeout()
Expect(push).To(ExitWithError())
@@ -163,7 +163,7 @@ var _ = Describe("Podman push", func() {
if !IsRemote() {
// remote does not support --cert-dir
- push = podmanTest.Podman([]string{"push", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"})
+ push = podmanTest.Podman([]string{"push", "--tls-verify=true", "--creds=podmantest:test", "--cert-dir=fakedir", ALPINE, "localhost:5000/certdirtest"})
push.WaitWithDefaultTimeout()
Expect(push).To(ExitWithError())
}
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index ca242a17c..c64cfd2d5 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -357,6 +357,26 @@ var _ = Describe("Podman run networking", func() {
Expect(ncBusy).To(ExitWithError())
})
+ It("podman run slirp4netns verify net.ipv6.conf.default.accept_dad=0", func() {
+ session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:enable_ipv6=true", ALPINE, "ip", "addr"})
+ session.Wait(30)
+ Expect(session).Should(Exit(0))
+ // check the ipv6 setup id done without delay (https://github.com/containers/podman/issues/11062)
+ Expect(session.OutputToString()).To(ContainSubstring("inet6 fd00::"))
+
+ const ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/all/accept_dad"
+
+ cat := SystemExec("cat", []string{ipv6ConfDefaultAcceptDadSysctl})
+ cat.Wait(30)
+ Expect(cat).Should(Exit(0))
+ sysctlValue := cat.OutputToString()
+
+ session = podmanTest.Podman([]string{"run", "--network", "slirp4netns:enable_ipv6=true", ALPINE, "cat", ipv6ConfDefaultAcceptDadSysctl})
+ session.Wait(30)
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(sysctlValue))
+ })
+
It("podman run network expose host port 18082 to container port 8000 using slirp4netns port handler", func() {
session := podmanTest.Podman([]string{"run", "--network", "slirp4netns:port_handler=slirp4netns", "-dt", "-p", "18082:8000", ALPINE, "/bin/sh"})
session.Wait(30)
@@ -474,6 +494,23 @@ var _ = Describe("Podman run networking", func() {
Expect(containerConfig[0].NetworkSettings.Ports["80/tcp"][0].HostPort).ToNot(Equal(80))
})
+ It("podman run forward sctp protocol", func() {
+ SkipIfRootless("sctp protocol only works as root")
+ session := podmanTest.Podman([]string{"--log-level=info", "run", "--name=test", "-p", "80/sctp", "-p", "81/sctp", ALPINE})
+ session.Wait(90)
+ Expect(session).Should(Exit(0))
+ // we can only check logrus on local podman
+ if !IsRemote() {
+ // check that the info message for sctp protocol is only displayed once
+ Expect(strings.Count(session.ErrorToString(), "Port reservation for SCTP is not supported")).To(Equal(1), "`Port reservation for SCTP is not supported` is not displayed exactly one time in the logrus logs")
+ }
+ results := podmanTest.Podman([]string{"inspect", "test"})
+ results.Wait(30)
+ Expect(results).Should(Exit(0))
+ Expect(results.OutputToString()).To(ContainSubstring(`"80/sctp":`))
+ Expect(results.OutputToString()).To(ContainSubstring(`"81/sctp":`))
+ })
+
It("podman run hostname test", func() {
session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "HOSTNAME"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index b6743f4b7..ed2d8938d 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"net"
"os"
+ "os/exec"
"path/filepath"
"strconv"
"strings"
@@ -12,6 +13,7 @@ import (
"time"
"github.com/containers/podman/v3/pkg/cgroups"
+ "github.com/containers/podman/v3/pkg/rootless"
. "github.com/containers/podman/v3/test/utils"
"github.com/containers/storage/pkg/stringid"
"github.com/mrunalp/fileutils"
@@ -186,6 +188,12 @@ var _ = Describe("Podman run", func() {
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(3))
+
+ // Now registries.conf will be consulted where localhost:5000
+ // is set to be insecure.
+ run = podmanTest.Podman([]string{"run", ALPINE})
+ run.WaitWithDefaultTimeout()
+ Expect(run).Should(Exit(0))
})
It("podman run a container with a --rootfs", func() {
@@ -226,6 +234,49 @@ var _ = Describe("Podman run", func() {
stdoutLines := session.OutputToStringArray()
Expect(stdoutLines).Should(HaveLen(1))
Expect(stdoutLines[0]).Should(Equal(uniqueString))
+
+ SkipIfRemote("External overlay only work locally")
+ if os.Getenv("container") != "" {
+ Skip("Overlay mounts not supported when running in a container")
+ }
+ if rootless.IsRootless() {
+ if _, err := exec.LookPath("fuse-overlayfs"); err != nil {
+ Skip("Fuse-Overlayfs required for rootless overlay mount test")
+ }
+ }
+ // Test --rootfs with an external overlay
+ // use --rm to remove container and confirm if we did not leak anything
+ osession := podmanTest.Podman([]string{"run", "-i", "--rm", "--security-opt", "label=disable",
+ "--rootfs", rootfs + ":O", "cat", testFilePath})
+ osession.WaitWithDefaultTimeout()
+ Expect(osession).Should(Exit(0))
+
+ // Test podman start stop with overlay
+ osession = podmanTest.Podman([]string{"run", "--name", "overlay-foo", "--security-opt", "label=disable",
+ "--rootfs", rootfs + ":O", "echo", "hello"})
+ osession.WaitWithDefaultTimeout()
+ Expect(osession).Should(Exit(0))
+
+ osession = podmanTest.Podman([]string{"stop", "overlay-foo"})
+ osession.WaitWithDefaultTimeout()
+ Expect(osession).Should(Exit(0))
+
+ startsession := podmanTest.Podman([]string{"start", "--attach", "overlay-foo"})
+ startsession.WaitWithDefaultTimeout()
+ Expect(startsession).Should(Exit(0))
+ Expect(startsession.OutputToString()).To(Equal("hello"))
+
+ // remove container for above test overlay-foo
+ osession = podmanTest.Podman([]string{"rm", "overlay-foo"})
+ osession.WaitWithDefaultTimeout()
+ Expect(osession).Should(Exit(0))
+
+ // Test --rootfs with an external overlay with --uidmap
+ osession = podmanTest.Podman([]string{"run", "--uidmap", "0:1000:1000", "--rm", "--security-opt", "label=disable",
+ "--rootfs", rootfs + ":O", "echo", "hello"})
+ osession.WaitWithDefaultTimeout()
+ Expect(osession).Should(Exit(0))
+ Expect(osession.OutputToString()).To(Equal("hello"))
})
It("podman run a container with --init", func() {
@@ -1147,6 +1198,14 @@ USER mail`, BB)
Expect(session.OutputToString()).To(ContainSubstring("devpts"))
})
+ It("podman run --mount type=devpts,target=/dev/pts with uid, gid and mode", func() {
+ // runc doesn't seem to honor uid= so avoid testing it
+ session := podmanTest.Podman([]string{"run", "-t", "--mount", "type=devpts,target=/dev/pts,uid=1000,gid=1001,mode=123", fedoraMinimal, "stat", "-c%g-%a", "/dev/pts/0"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("1001-123"))
+ })
+
It("podman run --pod automatically", func() {
session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8686"})
session.WaitWithDefaultTimeout()
@@ -1322,13 +1381,13 @@ USER mail`, BB)
}
}
- container := podmanTest.Podman([]string{"run", "--rm", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"})
+ container := podmanTest.PodmanSystemdScope([]string{"run", "--rm", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"})
container.WaitWithDefaultTimeout()
Expect(container).Should(Exit(0))
checkLines(container.OutputToStringArray())
// check that --cgroups=split is honored also when a container runs in a pod
- container = podmanTest.Podman([]string{"run", "--rm", "--pod", "new:split-test-pod", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"})
+ container = podmanTest.PodmanSystemdScope([]string{"run", "--rm", "--pod", "new:split-test-pod", "--cgroups=split", ALPINE, "cat", "/proc/self/cgroup"})
container.WaitWithDefaultTimeout()
Expect(container).Should(Exit(0))
checkLines(container.OutputToStringArray())
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index f1baa7780..634a498b9 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -222,7 +222,7 @@ var _ = Describe("Podman run with volumes", func() {
Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
})
- // Container should start when workdir is overlayed volume
+ // Container should start when workdir is overlay volume
It("podman run with volume mounted as overlay and used as workdir", func() {
SkipIfRemote("Overlay volumes only work locally")
if os.Getenv("container") != "" {
@@ -236,7 +236,7 @@ var _ = Describe("Podman run with volumes", func() {
mountPath := filepath.Join(podmanTest.TempDir, "secrets")
os.Mkdir(mountPath, 0755)
- //Container should be able to start with custom overlayed volume
+ //Container should be able to start with custom overlay volume
session := podmanTest.Podman([]string{"run", "--rm", "-v", mountPath + ":/data:O", "--workdir=/data", ALPINE, "echo", "hello"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -262,15 +262,15 @@ var _ = Describe("Podman run with volumes", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- // create file on overlayed volume
- session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlayed"})
+ // create file on overlay volume
+ session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data:O", ALPINE, "sh", "-c", "echo hello >> " + "/data/overlay"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- // volume should contain only `test` not `overlayed`
+ // volume should contain only `test` not `overlay`
session = podmanTest.Podman([]string{"run", "--volume", volName + ":/data", ALPINE, "sh", "-c", "ls /data"})
session.WaitWithDefaultTimeout()
- Expect(session.OutputToString()).To(Not(ContainSubstring("overlayed")))
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlay")))
Expect(session.OutputToString()).To(ContainSubstring("test"))
})
diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go
index f82c3d9d1..10e991d9f 100644
--- a/test/e2e/search_test.go
+++ b/test/e2e/search_test.go
@@ -2,6 +2,7 @@ package integration
import (
"bytes"
+ "encoding/json"
"fmt"
"io/ioutil"
"os"
@@ -9,6 +10,7 @@ import (
"strconv"
"text/template"
+ "github.com/containers/podman/v3/pkg/domain/entities"
. "github.com/containers/podman/v3/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -105,7 +107,18 @@ registries = ['{{.Host}}:{{.Port}}']`
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
output := string(search.Out.Contents())
- match, _ := regexp.MatchString(`(?m)^quay.io\s+quay.io/libpod/whalesay\s+Static image used for automated testing.+$`, output)
+ match, _ := regexp.MatchString(`(?m)NAME\s+DESCRIPTION$`, output)
+ Expect(match).To(BeTrue())
+ match, _ = regexp.MatchString(`(?m)quay.io/libpod/whalesay\s+Static image used for automated testing.+$`, output)
+ Expect(match).To(BeTrue())
+ })
+
+ It("podman search image with --compatible", func() {
+ search := podmanTest.Podman([]string{"search", "--compatible", "quay.io/libpod/whalesay"})
+ search.WaitWithDefaultTimeout()
+ Expect(search).Should(Exit(0))
+ output := string(search.Out.Contents())
+ match, _ := regexp.MatchString(`(?m)NAME\s+DESCRIPTION\s+STARS\s+OFFICIAL\s+AUTOMATED$`, output)
Expect(match).To(BeTrue())
})
@@ -123,6 +136,15 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search).Should(Exit(0))
Expect(search.IsJSONOutputValid()).To(BeTrue())
Expect(search.OutputToString()).To(ContainSubstring("docker.io/library/alpine"))
+
+ // Test for https://github.com/containers/podman/issues/11894
+ contents := make([]entities.ImageSearchReport, 0)
+ err := json.Unmarshal(search.Out.Contents(), &contents)
+ Expect(err).ToNot(HaveOccurred())
+ Expect(len(contents)).To(BeNumerically(">", 0), "No results from image search")
+ for _, element := range contents {
+ Expect(element.Description).ToNot(HaveSuffix("..."))
+ }
})
It("podman search format json list tags", func() {
@@ -135,13 +157,17 @@ registries = ['{{.Host}}:{{.Port}}']`
Expect(search.OutputToString()).To(ContainSubstring("2.7"))
})
- It("podman search no-trunc flag", func() {
- search := podmanTest.Podman([]string{"search", "--no-trunc", "alpine"})
+ // Test for https://github.com/containers/podman/issues/11894
+ It("podman search no-trunc=false flag", func() {
+ search := podmanTest.Podman([]string{"search", "--no-trunc=false", "alpine", "--format={{.Description}}"})
search.WaitWithDefaultTimeout()
Expect(search).Should(Exit(0))
- Expect(len(search.OutputToStringArray())).To(BeNumerically(">", 1))
- Expect(search.LineInOutputContains("docker.io/library/alpine")).To(BeTrue())
- Expect(search.LineInOutputContains("...")).To(BeFalse())
+
+ for _, line := range search.OutputToStringArray() {
+ if len(line) > 44 {
+ Expect(line).To(HaveSuffix("..."), line+" should have been truncated")
+ }
+ }
})
It("podman search limit flag", func() {
diff --git a/test/e2e/system_connection_test.go b/test/e2e/system_connection_test.go
index 6cdb78c5e..d80e6d5a0 100644
--- a/test/e2e/system_connection_test.go
+++ b/test/e2e/system_connection_test.go
@@ -181,6 +181,31 @@ var _ = Describe("podman system connection", func() {
}
})
+ It("remove --all", func() {
+ cmd := []string{"system", "connection", "add",
+ "--default",
+ "--identity", "~/.ssh/id_rsa",
+ "QA",
+ "ssh://root@server.fubar.com:2222/run/podman/podman.sock",
+ }
+ session := podmanTest.Podman(cmd)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ cmd = []string{"system", "connection", "remove", "--all"}
+ session = podmanTest.Podman(cmd)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.Out).Should(Say(""))
+
+ cmd = []string{"system", "connection", "list"}
+ session = podmanTest.Podman(cmd)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.Out).Should(Say(""))
+ Expect(session.Err).Should(Say(""))
+ })
+
It("default", func() {
for _, name := range []string{"devl", "qe"} {
cmd := []string{"system", "connection", "add",
@@ -208,13 +233,13 @@ var _ = Describe("podman system connection", func() {
session = podmanTest.Podman(cmd)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.Out).Should(Say("Name *Identity *URI"))
+ Expect(session.Out).Should(Say("Name *URI *Identity *Default"))
cmd = []string{"system", "connection", "list", "--format", "{{.Name}}"}
session = podmanTest.Podman(cmd)
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).Should(Equal("devl* qe"))
+ Expect(session.OutputToString()).Should(Equal("devl qe"))
})
It("failed default", func() {
diff --git a/test/e2e/system_dial_stdio_test.go b/test/e2e/system_dial_stdio_test.go
new file mode 100644
index 000000000..afe3d5acd
--- /dev/null
+++ b/test/e2e/system_dial_stdio_test.go
@@ -0,0 +1,53 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+
+ . "github.com/containers/podman/v3/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("podman system dial-stdio", 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()
+ timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
+ GinkgoWriter.Write([]byte(timedResult))
+ })
+
+ It("podman system dial-stdio help", func() {
+ session := podmanTest.Podman([]string{"system", "dial-stdio", "--help"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("Examples: podman system dial-stdio"))
+ })
+
+ It("podman system dial-stdio while service is not running", func() {
+ if IsRemote() {
+ Skip("this test is only for non-remote")
+ }
+ session := podmanTest.Podman([]string{"system", "dial-stdio"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("Error: failed to open connection to podman"))
+ })
+})
diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go
index 102526a46..93ab166cd 100644
--- a/test/e2e/system_reset_test.go
+++ b/test/e2e/system_reset_test.go
@@ -60,6 +60,8 @@ var _ = Describe("podman system reset", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ Expect(session.ErrorToString()).To(Not(ContainSubstring("Failed to add pause process")))
+
// If remote then the API service should have exited
// On local tests this is a noop
podmanTest.StartRemoteService()
diff --git a/test/e2e/system_service_test.go b/test/e2e/system_service_test.go
index 684ac56b4..9a4d687c3 100644
--- a/test/e2e/system_service_test.go
+++ b/test/e2e/system_service_test.go
@@ -65,7 +65,7 @@ var _ = Describe("podman system service", func() {
pprofPort := randomPort()
session := podmanTest.Podman([]string{
- "system", "service", "--log-level=info", "--time=0",
+ "system", "service", "--log-level=debug", "--time=0",
"--pprof-address=localhost:" + pprofPort, address.String(),
})
defer session.Kill()
@@ -91,7 +91,7 @@ var _ = Describe("podman system service", func() {
Expect(body).ShouldNot(BeEmpty())
session.Interrupt().Wait(2 * time.Second)
- Eventually(session, 2).Should(Exit(1))
+ Eventually(session).Should(Exit(1))
})
It("are not available", func() {
@@ -103,7 +103,7 @@ var _ = Describe("podman system service", func() {
}
session := podmanTest.Podman([]string{
- "system", "service", "--log-level=info", "--time=0", address.String(),
+ "system", "service", "--log-level=debug", "--time=0", address.String(),
})
defer session.Kill()
@@ -113,7 +113,7 @@ var _ = Describe("podman system service", func() {
Expect(session.Err.Contents()).ShouldNot(ContainSubstring(magicComment))
session.Interrupt().Wait(2 * time.Second)
- Eventually(session, 2).Should(Exit(1))
+ Eventually(session).Should(Exit(1))
})
})
})
diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go
index a1b25b723..98def3d8f 100644
--- a/test/e2e/systemd_test.go
+++ b/test/e2e/systemd_test.go
@@ -4,7 +4,6 @@ import (
"io/ioutil"
"os"
"strings"
- "time"
. "github.com/containers/podman/v3/test/utils"
. "github.com/onsi/ginkgo"
@@ -82,27 +81,13 @@ WantedBy=multi-user.target
run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", ubi_init, "/sbin/init"})
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))
- ctrID := run.OutputToString()
logs := podmanTest.Podman([]string{"logs", ctrName})
logs.WaitWithDefaultTimeout()
Expect(logs).Should(Exit(0))
// Give container 10 seconds to start
- started := false
- for i := 0; i < 10; i++ {
- runningCtrs := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
- runningCtrs.WaitWithDefaultTimeout()
- Expect(runningCtrs).Should(Exit(0))
-
- if strings.Contains(runningCtrs.OutputToString(), ctrID) {
- started = true
- break
- }
-
- time.Sleep(1 * time.Second)
- }
-
+ started := podmanTest.WaitContainerReady(ctrName, "Reached target Multi-User System.", 30, 1)
Expect(started).To(BeTrue())
systemctl := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "systemctl", "status", "--no-pager"})
diff --git a/test/e2e/trust_test.go b/test/e2e/trust_test.go
index 7f97f280a..b591e1c02 100644
--- a/test/e2e/trust_test.go
+++ b/test/e2e/trust_test.go
@@ -14,7 +14,8 @@ import (
var _ = Describe("Podman trust", func() {
var (
- tempdir string
+ tempdir string
+
err error
podmanTest *PodmanTestIntegration
)
@@ -38,21 +39,17 @@ var _ = Describe("Podman trust", func() {
})
It("podman image trust show", func() {
- path, err := os.Getwd()
- if err != nil {
- os.Exit(1)
- }
- session := podmanTest.Podman([]string{"image", "trust", "show", "--registrypath", filepath.Dir(path), "--policypath", filepath.Join(filepath.Dir(path), "policy.json")})
+ session := podmanTest.Podman([]string{"image", "trust", "show", "--registrypath", filepath.Join(INTEGRATION_ROOT, "test"), "--policypath", filepath.Join(INTEGRATION_ROOT, "test/policy.json")})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
outArray := session.OutputToStringArray()
Expect(len(outArray)).To(Equal(3))
- // image order is not guaranteed. All we can do is check that
- // these strings appear in output, we can't cross-check them.
- Expect(session.OutputToString()).To(ContainSubstring("accept"))
- Expect(session.OutputToString()).To(ContainSubstring("reject"))
- Expect(session.OutputToString()).To(ContainSubstring("signed"))
+ // Repository order is not guaranteed. So, check that
+ // all expected lines appear in output; we also check total number of lines, so that handles all of them.
+ Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^default\s+accept\s*$`))
+ Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^docker.io/library/hello-world\s+reject\s*$`))
+ Expect(string(session.Out.Contents())).To(MatchRegexp(`(?m)^registry.access.redhat.com\s+signedBy\s+security@redhat.com, security@redhat.com\s+https://access.redhat.com/webassets/docker/content/sigstore\s*$`))
})
It("podman image trust set", func() {
@@ -76,24 +73,52 @@ var _ = Describe("Podman trust", func() {
})
It("podman image trust show --json", func() {
- session := podmanTest.Podman([]string{"image", "trust", "show", "--json"})
+ session := podmanTest.Podman([]string{"image", "trust", "show", "--registrypath", filepath.Join(INTEGRATION_ROOT, "test"), "--policypath", filepath.Join(INTEGRATION_ROOT, "test/policy.json"), "--json"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.IsJSONOutputValid()).To(BeTrue())
var teststruct []map[string]string
json.Unmarshal(session.Out.Contents(), &teststruct)
- Expect(teststruct[0]["name"]).To(Equal("* (default)"))
- Expect(teststruct[0]["repo_name"]).To(Equal("default"))
- Expect(teststruct[0]["type"]).To(Equal("accept"))
- Expect(teststruct[1]["type"]).To(Equal("insecureAcceptAnything"))
+ Expect(len(teststruct)).To(Equal(3))
+ // To ease comparison, group the unordered array of repos by repo (and we expect only one entry by repo, so order within groups doesn’t matter)
+ repoMap := map[string][]map[string]string{}
+ for _, e := range teststruct {
+ key := e["name"]
+ repoMap[key] = append(repoMap[key], e)
+ }
+ Expect(repoMap).To(Equal(map[string][]map[string]string{
+ "* (default)": {{
+ "name": "* (default)",
+ "repo_name": "default",
+ "sigstore": "",
+ "transport": "",
+ "type": "accept",
+ }},
+ "docker.io/library/hello-world": {{
+ "name": "docker.io/library/hello-world",
+ "repo_name": "docker.io/library/hello-world",
+ "sigstore": "",
+ "transport": "",
+ "type": "reject",
+ }},
+ "registry.access.redhat.com": {{
+ "name": "registry.access.redhat.com",
+ "repo_name": "registry.access.redhat.com",
+ "sigstore": "https://access.redhat.com/webassets/docker/content/sigstore",
+ "transport": "",
+ "type": "signedBy",
+ "gpg_id": "security@redhat.com, security@redhat.com",
+ }},
+ }))
})
It("podman image trust show --raw", func() {
- session := podmanTest.Podman([]string{"image", "trust", "show", "--raw"})
+ session := podmanTest.Podman([]string{"image", "trust", "show", "--policypath", filepath.Join(INTEGRATION_ROOT, "test/policy.json"), "--raw"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ contents, err := ioutil.ReadFile(filepath.Join(INTEGRATION_ROOT, "test/policy.json"))
+ Expect(err).ShouldNot(HaveOccurred())
Expect(session.IsJSONOutputValid()).To(BeTrue())
- Expect(session.OutputToString()).To(ContainSubstring("default"))
- Expect(session.OutputToString()).To(ContainSubstring("insecureAcceptAnything"))
+ Expect(string(session.Out.Contents())).To(Equal(string(contents) + "\n"))
})
})
diff --git a/test/e2e/unshare_test.go b/test/e2e/unshare_test.go
index 79ce68e89..cf1b8db53 100644
--- a/test/e2e/unshare_test.go
+++ b/test/e2e/unshare_test.go
@@ -51,7 +51,7 @@ var _ = Describe("Podman unshare", func() {
})
It("podman unshare --rootles-cni", func() {
- session := podmanTest.Podman([]string{"unshare", "--rootless-cni", "ip", "addr"})
+ session := podmanTest.Podman([]string{"unshare", "--rootless-netns", "ip", "addr"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("tap0"))
diff --git a/test/e2e/version_test.go b/test/e2e/version_test.go
index 75986e671..9398248b8 100644
--- a/test/e2e/version_test.go
+++ b/test/e2e/version_test.go
@@ -31,7 +31,6 @@ var _ = Describe("Podman version", func() {
f := CurrentGinkgoTestDescription()
processTestResult(f)
podmanTest.SeedImages()
-
})
It("podman version", func() {
@@ -96,4 +95,13 @@ var _ = Describe("Podman version", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
})
+
+ It("podman help", func() {
+ session := podmanTest.Podman([]string{"help"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.Out.Contents()).Should(
+ ContainSubstring("Display the Podman version information"),
+ )
+ })
})
diff --git a/test/registries.conf b/test/registries.conf
index 0559c9e52..8e4671760 100644
--- a/test/registries.conf
+++ b/test/registries.conf
@@ -15,3 +15,9 @@ location="mirror.gcr.io"
[[registry]]
prefix="docker.io/library"
location="quay.io/libpod"
+
+# For testing #11933 to make sure that registries.conf is consulted unless
+# --tls-verify is used during container creation.
+[[registry]]
+location="localhost:5000"
+insecure=true
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index ccc05bb15..03f07d602 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -93,6 +93,25 @@ function setup() {
is "$output" "Error: unknown flag: --remote" "podman version --remote"
}
+@test "podman-remote: defaults" {
+ skip_if_remote "only applicable on a local run"
+
+ # By default, podman should include '--remote' in its help output
+ run_podman --help
+ is "$output" ".* --remote " "podman --help includes the --remote option"
+
+ # When it detects CONTAINER_HOST or _CONNECTION, --remote is not an option
+ CONTAINER_HOST=foobar run_podman --help
+ if grep -- " --remote " <<<"$output"; then
+ die "podman --help, with CONTAINER_HOST set, is showing --remote"
+ fi
+
+ CONTAINER_CONNECTION=foobar run_podman --help
+ if grep -- " --remote " <<<"$output"; then
+ die "podman --help, with CONTAINER_CONNECTION set, is showing --remote"
+ fi
+}
+
# Check that just calling "podman-remote" prints the usage message even
# without a running endpoint. Use "podman --remote" for this as this works the same.
@test "podman-remote: check for command usage message without a running endpoint" {
diff --git a/test/system/015-help.bats b/test/system/015-help.bats
index b2c6e2575..a87081687 100644
--- a/test/system/015-help.bats
+++ b/test/system/015-help.bats
@@ -86,6 +86,12 @@ function check_help() {
run_podman 125 "$@" $cmd -l nonexistent-container
is "$output" "Error: .*--latest and \(containers\|pods\|arguments\) cannot be used together" \
"'$command_string' with both -l and container"
+
+ # Combine -l and -a, too (but spell it as --all, because "-a"
+ # means "attach" in podman container start)
+ run_podman 125 "$@" $cmd --all --latest
+ is "$output" "Error: \(--all and --latest cannot be used together\|--all, --latest and containers cannot be used together\|--all, --latest and arguments cannot be used together\|unknown flag\)" \
+ "'$command_string' with both --all and --latest"
fi
fi
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 44c2ee509..2c8d08b99 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -67,6 +67,11 @@ echo $rand | 0 | $rand
is "$output" ".*invalidflag" "failed when passing undefined flags to the runtime"
}
+@test "podman run --memory=0 runtime option" {
+ run_podman run --memory=0 --rm $IMAGE echo hello
+ is "$output" "hello" "failed to run when --memory is set to 0"
+}
+
# 'run --preserve-fds' passes a number of additional file descriptors into the container
@test "podman run --preserve-fds" {
skip_if_remote "preserve-fds is meaningless over remote"
diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats
index 44b66676e..7fb3e62e4 100644
--- a/test/system/035-logs.bats
+++ b/test/system/035-logs.bats
@@ -30,6 +30,17 @@ load helpers
run_podman rm $cid
}
+function _additional_events_backend() {
+ local driver=$1
+ # Since PR#10431, 'logs -f' with journald driver is only supported with journald events backend.
+ if [[ $driver = "journald" ]]; then
+ run_podman info --format '{{.Host.EventLogger}}' >/dev/null
+ if [[ $output != "journald" ]]; then
+ echo "--events-backend journald"
+ fi
+ fi
+}
+
function _log_test_multi() {
local driver=$1
@@ -42,10 +53,12 @@ function _log_test_multi() {
etc='.*'
fi
+ local events_backend=$(_additional_events_backend $driver)
+
# Simple helper to make the container starts, below, easier to read
local -a cid
doit() {
- run_podman run --log-driver=$driver --rm -d --name "$1" $IMAGE sh -c "$2";
+ run_podman ${events_backend} run --log-driver=$driver --rm -d --name "$1" $IMAGE sh -c "$2";
cid+=($(echo "${output:0:12}"))
}
@@ -57,7 +70,7 @@ function _log_test_multi() {
doit c1 "echo a;sleep 10;echo d;sleep 3"
doit c2 "sleep 1;echo b;sleep 2;echo c;sleep 3"
- run_podman logs -f c1 c2
+ run_podman ${events_backend} logs -f c1 c2
is "$output" \
"${cid[0]} a$etc
${cid[1]} b$etc
@@ -187,15 +200,20 @@ function _log_test_follow() {
contentA=$(random_string)
contentB=$(random_string)
contentC=$(random_string)
+ local events_backend=$(_additional_events_backend $driver)
+
+ if [[ -n "${events_backend}" ]]; then
+ skip_if_remote "remote does not support --events-backend"
+ fi
# Note: it seems we need at least three log lines to hit #11461.
- run_podman run --log-driver=$driver --name $cname $IMAGE sh -c "echo $contentA; echo $contentB; echo $contentC"
- run_podman logs -f $cname
+ run_podman ${events_backend} run --log-driver=$driver --name $cname $IMAGE sh -c "echo $contentA; echo $contentB; echo $contentC"
+ run_podman ${events_backend} logs -f $cname
is "$output" "$contentA
$contentB
$contentC" "logs -f on exitted container works"
- run_podman rm -t 0 -f $cname
+ run_podman ${events_backend} rm -t 0 -f $cname
}
@test "podman logs - --follow k8s-file" {
diff --git a/test/system/045-start.bats b/test/system/045-start.bats
index 7e4bbde8d..2ea057cd3 100644
--- a/test/system/045-start.bats
+++ b/test/system/045-start.bats
@@ -36,10 +36,6 @@ load helpers
expected="Error: either start all containers or the container(s) provided in the arguments"
run_podman 125 start --all 12333
is "$output" "$expected" "start --all, with args, throws error"
- if ! is_remote; then
- run_podman 125 start --all --latest
- is "$output" "$expected" "podman start --all --latest"
- fi
}
@test "podman start --filter - start only containers that match the filter" {
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index d3dc14d81..3c47b1f5b 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -39,6 +39,8 @@ EOF
cat >$dockerfile <<EOF
FROM $IMAGE
RUN echo $rand_content > /$rand_filename
+VOLUME /a/b/c
+VOLUME ['/etc/foo', '/etc/bar']
EOF
run_podman buildx build --load -t build_test --format=docker $tmpdir
@@ -47,6 +49,33 @@ EOF
run_podman run --rm build_test cat /$rand_filename
is "$output" "$rand_content" "reading generated file in image"
+ # Make sure the volumes are created at surprising yet Docker-compatible
+ # destinations (see bugzilla.redhat.com/show_bug.cgi?id=2014149).
+ run_podman run --rm build_test find /[ /etc/bar\] -print
+ is "$output" "/\[
+/\[/etc
+/\[/etc/foo,
+/etc/bar]" "weird VOLUME gets converted to directories with brackets and comma"
+
+ # Now confirm that each volume got a unique device ID
+ run_podman run --rm build_test stat -c '%D' / /a /a/b /a/b/c /\[ /\[/etc /\[/etc/foo, /etc /etc/bar\]
+ # First, the non-volumes should all be the same...
+ is "${lines[0]}" "${lines[1]}" "devnum( / ) = devnum( /a )"
+ is "${lines[0]}" "${lines[2]}" "devnum( / ) = devnum( /a/b )"
+ is "${lines[0]}" "${lines[4]}" "devnum( / ) = devnum( /[ )"
+ is "${lines[0]}" "${lines[5]}" "devnum( / ) = devnum( /[etc )"
+ is "${lines[0]}" "${lines[7]}" "devnum( / ) = devnum( /etc )"
+ is "${lines[6]}" "${lines[8]}" "devnum( /[etc/foo, ) = devnum( /etc/bar] )"
+ # ...then, each volume should be different
+ if [[ "${lines[0]}" = "${lines[3]}" ]]; then
+ die "devnum( / ) (${lines[0]}) = devnum( volume0 ) (${lines[3]}) -- they should differ"
+ fi
+ if [[ "${lines[0]}" = "${lines[6]}" ]]; then
+ die "devnum( / ) (${lines[0]}) = devnum( volume1 ) (${lines[6]}) -- they should differ"
+ fi
+ # FIXME: is this expected? I thought /a/b/c and /[etc/foo, would differ
+ is "${lines[3]}" "${lines[6]}" "devnum( volume0 ) = devnum( volume1 )"
+
run_podman rmi -f build_test
}
diff --git a/test/system/130-kill.bats b/test/system/130-kill.bats
index d85f0a6a9..1ff3a7b61 100644
--- a/test/system/130-kill.bats
+++ b/test/system/130-kill.bats
@@ -6,9 +6,22 @@
load helpers
@test "podman kill - test signal handling in containers" {
+
+ # Prepare for 'logs -f'
+ run_podman info --format '{{.Host.LogDriver}}'
+ log_driver=$output
+ run_podman info --format '{{.Host.EventLogger}}'
+ event_logger=$output
+ opt_log_driver=
+ if [ $log_driver = "journald" ] && [ $event_logger != "journald" ]; then
+ # Since PR#10431, 'logs -f' with journald driver is only supported with journald events backend.
+ # Set '--log driver' temporally because remote doesn't support '--events-backend'.
+ opt_log_driver="--log-driver k8s-file"
+ fi
+
# Start a container that will handle all signals by emitting 'got: N'
local -a signals=(1 2 3 4 5 6 8 10 12 13 14 15 16 20 21 22 23 24 25 26 64)
- run_podman run -d $IMAGE sh -c \
+ run_podman run -d ${opt_log_driver} $IMAGE sh -c \
"for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done;
echo READY;
while ! test -e /stop; do sleep 0.05; done;
diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats
index 490d635e5..43462de36 100644
--- a/test/system/160-volumes.bats
+++ b/test/system/160-volumes.bats
@@ -97,6 +97,14 @@ Labels.l | $mylabel
run_podman volume rm $myvolume
}
+# Removing volumes with --force
+@test "podman volume rm --force" {
+ run_podman run -d --volume myvol:/myvol $IMAGE top
+ cid=$output
+ run_podman 2 volume rm myvol
+ is "$output" "Error: volume myvol is being used by the following container(s): $cid: volume is being used" "should error since container is running"
+ run_podman volume rm myvol --force
+}
# Running scripts (executables) from a volume
@test "podman volume: exec/noexec" {
@@ -202,6 +210,36 @@ EOF
run_podman volume rm my_vol2
}
+# Podman volume user test
+@test "podman volume user test" {
+ is_rootless || skip "only meaningful when run rootless"
+ user="1000:2000"
+ newuser="100:200"
+ tmpdir=${PODMAN_TMPDIR}/volume_$(random_string)
+ mkdir $tmpdir
+ touch $tmpdir/test1
+
+ run_podman run --name user --user $user -v $tmpdir:/data:U $IMAGE stat -c "%u:%g" /data
+ is "$output" "$user" "user should be changed"
+
+ # Now chown the source directory and make sure recursive chown happens
+ run_podman unshare chown -R $newuser $tmpdir
+ run_podman start --attach user
+ is "$output" "$user" "user should be the same"
+
+ # Now chown the file in source directory and make sure recursive chown
+ # doesn't happen
+ run_podman unshare chown -R $newuser $tmpdir/test1
+ run_podman start --attach user
+ is "$output" "$user" "user should be the same"
+ # test1 should still be chowned to $newuser
+ run_podman unshare stat -c "%u:%g" $tmpdir/test1
+ is "$output" "$newuser" "user should not be changed"
+
+ run_podman unshare rm $tmpdir/test1
+ run_podman rm user
+}
+
# Confirm that container sees the correct id
@test "podman volume with --userns=keep-id" {
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 86f3610ab..09a419914 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -60,6 +60,10 @@ function teardown() {
run_podman pod rm -f -t 0 $podid
}
+function rm_podman_pause_image() {
+ run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
+ run_podman rmi -f "localhost/podman-pause:$output"
+}
@test "podman pod - communicating between pods" {
podname=pod$(random_string)
@@ -100,19 +104,14 @@ function teardown() {
# Clean up. First the nc -l container...
run_podman rm $cid1
- # ...then, from pause container, find the image ID of the pause image...
- run_podman pod inspect --format '{{(index .Containers 0).ID}}' $podname
- pause_cid="$output"
- run_podman container inspect --format '{{.Image}}' $pause_cid
- pause_iid="$output"
-
# ...then rm the pod, then rmi the pause image so we don't leave strays.
run_podman pod rm $podname
- run_podman rmi $pause_iid
# Pod no longer exists
run_podman 1 pod exists $podid
run_podman 1 pod exists $podname
+
+ rm_podman_pause_image
}
@test "podman pod - communicating via /dev/shm " {
@@ -133,6 +132,10 @@ function teardown() {
# Pod no longer exists
run_podman 1 pod exists $podid
run_podman 1 pod exists $podname
+
+ # Pause image hasn't been pulled
+ run_podman 1 image exists k8s.gcr.io/pause:3.5
+ rm_podman_pause_image
}
# Random byte
@@ -303,16 +306,25 @@ EOF
run_podman rm $cid
run_podman pod rm -t 0 -f mypod
run_podman rmi $infra_image
-
}
@test "podman pod create should fail when infra-name is already in use" {
local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
- run_podman pod create --infra-name "$infra_name"
+ local pod_name="$(random_string 10 | tr A-Z a-z)"
+
+ # Note that the internal pause image is built even when --infra-image is
+ # set to the K8s one.
+ run_podman pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5"
run_podman '?' pod create --infra-name "$infra_name"
if [ $status -eq 0 ]; then
die "Podman should fail when user try to create two pods with the same infra-name value"
fi
+ run_podman pod rm -f $pod_name
+ run_podman images -a
+
+ # Pause image hasn't been pulled
+ run_podman 1 image exists k8s.gcr.io/pause:3.5
+ rm_podman_pause_image
}
# vim: filetype=sh
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 3607c1028..98241c309 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -153,7 +153,7 @@ function service_cleanup() {
cname3=$(random_string)
run_podman create --restart=on-failure:42 --name $cname3 $IMAGE
run_podman generate systemd --new $cname3
- is "$output" ".*Restart=on-failure.*" "on-failure:xx is parsed correclty"
+ is "$output" ".*Restart=on-failure.*" "on-failure:xx is parsed correctly"
is "$output" ".*StartLimitBurst=42.*" "on-failure:xx is parsed correctly"
run_podman rm -t 0 -f $cname $cname2 $cname3
diff --git a/test/system/270-socket-activation.bats b/test/system/270-socket-activation.bats
index dd439d3ae..6d582be18 100644
--- a/test/system/270-socket-activation.bats
+++ b/test/system/270-socket-activation.bats
@@ -8,14 +8,16 @@ load helpers.systemd
SERVICE_NAME="podman_test_$(random_string)"
-SERVICE_SOCK_ADDR="/run/podman/podman.sock"
+SERVICE_SOCK_ADDR="/run/podman/$SERVICE_NAME.sock"
if is_rootless; then
- SERVICE_SOCK_ADDR="$XDG_RUNTIME_DIR/podman/podman.sock"
+ SERVICE_SOCK_ADDR="$XDG_RUNTIME_DIR/podman/$SERVICE_NAME.sock"
fi
SERVICE_FILE="$UNIT_DIR/$SERVICE_NAME.service"
SOCKET_FILE="$UNIT_DIR/$SERVICE_NAME.socket"
+# URL to use for ping
+_PING=http://placeholder-hostname/libpod/_ping
function setup() {
skip_if_remote "systemd tests are meaningless over remote"
@@ -25,8 +27,8 @@ function setup() {
cat > $SERVICE_FILE <<EOF
[Unit]
Description=Podman API Service
-Requires=podman.socket
-After=podman.socket
+Requires=$SERVICE_NAME.socket
+After=$SERVICE_NAME.socket
Documentation=man:podman-system-service(1)
StartLimitIntervalSec=0
@@ -42,7 +44,7 @@ Description=Podman API Socket
Documentation=man:podman-system-service(1)
[Socket]
-ListenStream=%t/podman/podman.sock
+ListenStream=%t/podman/$SERVICE_NAME.sock
SocketMode=0660
[Install]
@@ -51,10 +53,10 @@ EOF
# ensure pause die before each test runs
if is_rootless; then
- local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
- if [ -f $pause_pid ]; then
- kill -9 $(cat $pause_pid) 2> /dev/null
- rm -f $pause_pid
+ local pause_pid_file="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
+ if [ -f $pause_pid_file ]; then
+ kill -9 $(< $pause_pid_file) 2> /dev/null
+ rm -f $pause_pid_file
fi
fi
systemctl start "$SERVICE_NAME.socket"
@@ -68,7 +70,9 @@ function teardown() {
}
@test "podman system service - socket activation - no container" {
- run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
+ run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR $_PING
+ echo "curl output: $output"
+ is "$status" "0" "curl exit status"
is "$output" "OK" "podman service responds normally"
}
@@ -76,29 +80,36 @@ function teardown() {
run_podman run -d $IMAGE sleep 90
cid="$output"
- run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
+ run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR $_PING
+ echo "curl output: $output"
+ is "$status" "0" "curl exit status"
is "$output" "OK" "podman service responds normally"
- run_podman stop -t 0 $cid
- run_podman rm -f $cid
+ run_podman rm -f -t 0 $cid
}
@test "podman system service - socket activation - kill rootless pause" {
if ! is_rootless; then
- skip "root podman no need pause process"
+ skip "there is no pause process when running rootful"
fi
run_podman run -d $IMAGE sleep 90
cid="$output"
- local pause_pid="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
- if [ -f $pause_pid ]; then
- kill -9 $(cat $pause_pid) 2> /dev/null
+ local pause_pid_file="$XDG_RUNTIME_DIR/libpod/tmp/pause.pid"
+ if [ ! -f $pause_pid_file ]; then
+ # This seems unlikely, but not impossible
+ die "Pause pid file does not exist: $pause_pid_file"
fi
- run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR http://podman/libpod/_ping
+
+ echo "kill -9 $(< pause_pid_file)"
+ kill -9 $(< $pause_pid_file)
+
+ run curl -s --max-time 3 --unix-socket $SERVICE_SOCK_ADDR $_PING
+ echo "curl output: $output"
+ is "$status" "0" "curl exit status"
is "$output" "OK" "podman service responds normally"
- run_podman stop -t 0 $cid
- run_podman rm -f $cid
+ run_podman rm -f -t 0 $cid
}
# vim: filetype=sh
diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats
new file mode 100644
index 000000000..14c4f6664
--- /dev/null
+++ b/test/system/272-system-connection.bats
@@ -0,0 +1,156 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# tests for podman system connection
+#
+
+load helpers
+
+# This will be set if we start a local service
+_SERVICE_PID=
+
+function setup() {
+ if ! is_remote; then
+ skip "only applicable when running remote"
+ fi
+
+ basic_setup
+}
+
+function teardown() {
+ if ! is_remote; then
+ return
+ fi
+
+ # In case test function failed to clean up
+ if [[ -n $_SERVICE_PID ]]; then
+ run kill $_SERVICE_PID
+ fi
+
+ # Aaaaargh! When running as root, 'system service' creates a tmpfs
+ # mount on $root/overlay. This in turn causes cleanup to fail.
+ mount \
+ | grep $PODMAN_TMPDIR \
+ | awk '{print $3}' \
+ | xargs -l1 --no-run-if-empty umount
+
+ # Remove all system connections
+ run_podman system connection rm --all
+
+ basic_teardown
+}
+
+# Helper function: invokes $PODMAN (which is podman-remote) _without_ --url opt
+#
+# Needed because, in CI, PODMAN="/path/to/podman-remote --url /path/to/socket"
+# which of course overrides podman's detection and use of a connection.
+function _run_podman_remote() {
+ PODMAN=${PODMAN%%--url*} run_podman "$@"
+}
+
+# Very basic test, does not actually connect at any time
+@test "podman system connection - basic add / ls / remove" {
+ run_podman system connection ls
+ is "$output" "" "system connection ls: no connections"
+
+ c1="c1_$(random_string 15)"
+ c2="c2_$(random_string 15)"
+
+ run_podman system connection add $c1 tcp://localhost:12345
+ run_podman system connection add --default $c2 tcp://localhost:54321
+ run_podman system connection ls
+ is "$output" \
+ ".*$c1[ ]\+tcp://localhost:12345[ ]\+false
+$c2[ ]\+tcp://localhost:54321[ ]\+true" \
+ "system connection ls"
+
+ # Remove default connection; the remaining one should still not be default
+ run_podman system connection rm $c2
+ run_podman system connection ls
+ is "$output" ".*$c1[ ]\+tcp://localhost:12345[ ]\+false" \
+ "system connection ls (after removing default connection)"
+
+ run_podman system connection rm $c1
+}
+
+# Test tcp socket; requires starting a local server
+@test "podman system connection - tcp" {
+ # Start server
+ _SERVICE_PORT=$(random_free_port 63000-64999)
+
+ # Add the connection, and run podman info *before* starting the service.
+ # This should fail.
+ run_podman system connection add myconnect tcp://localhost:$_SERVICE_PORT
+ # IMPORTANT NOTE: in CI, podman-remote is tested by setting PODMAN
+ # to "podman-remote --url sdfsdf". This of course overrides the default
+ # podman-remote action. Our solution: strip off the "--url xyz" part
+ # when invoking podman.
+ _run_podman_remote 125 info
+ is "$output" \
+ "Cannot connect to Podman. Please verify.*dial tcp.*connection refused" \
+ "podman info, without active service"
+
+ # Start service. Now podman info should work fine. The %%-remote*
+ # converts "podman-remote --opts" to just "podman", which is what
+ # we need for the server.
+ ${PODMAN%%-remote*} --root ${PODMAN_TMPDIR}/root \
+ --runroot ${PODMAN_TMPDIR}/runroot \
+ system service -t 99 tcp:localhost:$_SERVICE_PORT &
+ _SERVICE_PID=$!
+ wait_for_port localhost $_SERVICE_PORT
+
+ # FIXME: #12023, RemoteSocket is always /run/something
+# run_podman info --format '{{.Host.RemoteSocket.Path}}'
+# is "$output" "tcp:localhost:$_SERVICE_PORT" \
+# "podman info works, and talks to the correct server"
+
+ _run_podman_remote info --format '{{.Store.GraphRoot}}'
+ is "$output" "${PODMAN_TMPDIR}/root" \
+ "podman info, talks to the right service"
+
+ # Add another connection; make sure it does not get set as default
+ _run_podman_remote system connection add fakeconnect tcp://localhost:$(( _SERVICE_PORT + 1))
+ _run_podman_remote info --format '{{.Store.GraphRoot}}'
+ # (Don't bother checking output; we just care about exit status)
+
+ # Stop server. Use 'run' to avoid failing on nonzero exit status
+ run kill $_SERVICE_PID
+ run wait $_SERVICE_PID
+ _SERVICE_PID=
+
+ run_podman system connection rm fakeconnect
+ run_podman system connection rm myconnect
+}
+
+# If we have ssh access to localhost (unlikely in CI), test that.
+@test "podman system connection - ssh" {
+ rand=$(random_string 20)
+ echo $rand >$PODMAN_TMPDIR/testfile
+
+ # Can we actually ssh to localhost?
+ run ssh -q -o BatchMode=yes \
+ -o UserKnownHostsFile=/dev/null \
+ -o StrictHostKeyChecking=no \
+ -o CheckHostIP=no \
+ localhost \
+ cat $PODMAN_TMPDIR/testfile
+ test "$status" -eq 0 || skip "cannot ssh to localhost"
+ is "$output" "$rand" "weird! ssh worked, but could not cat local file"
+
+ # OK, ssh works.
+ # Create a new connection, over ssh, but using existing socket file
+ # (Remember, we're already podman-remote, there's a service running)
+ run_podman info --format '{{.Host.RemoteSocket.Path}}'
+ local socketpath="$output"
+ run_podman system connection add --socket-path "$socketpath" \
+ mysshcon ssh://localhost
+ is "$output" "" "output from system connection add"
+
+ # debug logs will confirm that we use ssh connection
+ _run_podman_remote --log-level=debug info --format '{{.Host.RemoteSocket.Path}}'
+ is "$output" ".*msg=\"SSH Agent Key .*" "we are truly using ssh"
+
+ # Clean up
+ run_podman system connection rm mysshconn
+}
+
+# vim: filetype=sh
diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats
index ed9e73a3e..dbdfd4b9d 100644
--- a/test/system/410-selinux.bats
+++ b/test/system/410-selinux.bats
@@ -27,9 +27,9 @@ function check_label() {
is "$type" "$1" "SELinux type"
if [ -n "$2" ]; then
- # e.g. from the above example -> "s0:c45,c745"
- range=$(cut -d: -f4,5 <<<"$context")
- is "$range" "$2^@" "SELinux range"
+ # e.g. from the above example -> "s0:c45,c745"
+ range=$(cut -d: -f4,5 <<<"$context")
+ is "$range" "$2^@" "SELinux range"
fi
}
@@ -66,9 +66,9 @@ function check_label() {
# FIXME this test fails when run rootless with runc:
# Error: container_linux.go:367: starting container process caused: process_linux.go:495: container init caused: readonly path /proc/asound: operation not permitted: OCI permission denied
if is_rootless; then
- runtime=$(podman_runtime)
- test "$runtime" == "crun" \
- || skip "runtime is $runtime; this test requires crun"
+ runtime=$(podman_runtime)
+ test "$runtime" == "crun" \
+ || skip "runtime is $runtime; this test requires crun"
fi
check_label "--pid=host" "spc_t"
@@ -96,10 +96,10 @@ function check_label() {
skip_if_no_selinux
run_podman run -d --name myc \
- --security-opt seccomp=unconfined \
- --security-opt label=type:spc_t \
- --security-opt label=level:s0 \
- $IMAGE sh -c 'while test ! -e /stop; do sleep 0.1; done'
+ --security-opt seccomp=unconfined \
+ --security-opt label=type:spc_t \
+ --security-opt label=level:s0 \
+ $IMAGE sh -c 'while test ! -e /stop; do sleep 0.1; done'
run_podman inspect --format='{{ .HostConfig.SecurityOpt }}' myc
is "$output" "[label=type:spc_t,label=level:s0 seccomp=unconfined]" \
"'podman inspect' preserves all --security-opts"
@@ -118,7 +118,7 @@ function check_label() {
skip_if_rootless_cgroupsv1
if [[ $(podman_runtime) == "runc" ]]; then
- skip "some sort of runc bug, not worth fixing (#11784)"
+ skip "some sort of runc bug, not worth fixing (#11784)"
fi
run_podman run -d --name myctr $IMAGE top
@@ -136,7 +136,7 @@ function check_label() {
# net NS: do not share context
run_podman run --rm --net container:myctr $IMAGE cat -v /proc/self/attr/current
if [[ "$output" = "$context_c1" ]]; then
- die "run --net : context ($output) is same as running container (it should not be)"
+ die "run --net : context ($output) is same as running container (it should not be)"
fi
# The 'myctr2' above was not run with --rm, so it still exists, and
@@ -158,8 +158,8 @@ function check_label() {
# We don't need a fullblown pause container; avoid pulling the k8s one
run_podman pod create --name myselinuxpod \
- --infra-image $IMAGE \
- --infra-command /home/podman/pause
+ --infra-image $IMAGE \
+ --infra-command /home/podman/pause
# Get baseline
run_podman run --rm --pod myselinuxpod $IMAGE cat -v /proc/self/attr/current
@@ -190,7 +190,7 @@ function check_label() {
# Even after #7902, labels (':c123,c456') should be different
run_podman run --rm --pod myselinuxpod $IMAGE cat -v /proc/self/attr/current
if [[ "$output" = "$context_c1" ]]; then
- die "context ($output) is the same on two separate containers, it should have been different"
+ die "context ($output) is the same on two separate containers, it should have been different"
fi
run_podman pod rm myselinuxpod
@@ -203,12 +203,12 @@ function check_label() {
# runc and crun emit different diagnostics
runtime=$(podman_runtime)
case "$runtime" in
- # crun 0.20.1 changes the error message
- # from /proc/thread-self/attr/exec`: .* unable to assign
- # to /proc/self/attr/keycreate`: .* unable to process
- crun) expect="\`/proc/.*\`: OCI runtime error: unable to \(assign\|process\) security attribute" ;;
- runc) expect="OCI runtime error: .*: failed to set /proc/self/attr/keycreate on procfs" ;;
- *) skip "Unknown runtime '$runtime'";;
+ # crun 0.20.1 changes the error message
+ # from /proc/thread-self/attr/exec`: .* unable to assign
+ # to /proc/self/attr/keycreate`: .* unable to process
+ crun) expect="\`/proc/.*\`: OCI runtime error: unable to \(assign\|process\) security attribute" ;;
+ runc) expect="OCI runtime error: .*: failed to set /proc/self/attr/keycreate on procfs" ;;
+ *) skip "Unknown runtime '$runtime'";;
esac
# The '.*' in the error below is for dealing with podman-remote, which
@@ -223,7 +223,7 @@ function check_label() {
LABEL="system_u:object_r:tmp_t:s0"
RELABEL="system_u:object_r:container_file_t:s0"
tmpdir=$PODMAN_TMPDIR/vol
- touch $tmpdir
+ mkdir -p $tmpdir
chcon -vR ${LABEL} $tmpdir
ls -Z $tmpdir
@@ -239,12 +239,36 @@ function check_label() {
run ls -dZ $tmpdir
is "$output" "${RELABEL} $tmpdir" "Privileged Relabel Correctly"
- run_podman run -v $tmpdir:/test:Z $IMAGE cat /proc/self/attr/current
+ run_podman run --name label -v $tmpdir:/test:Z $IMAGE cat /proc/self/attr/current
level=$(secon -l $output)
run ls -dZ $tmpdir
is "$output" "system_u:object_r:container_file_t:$level $tmpdir" \
"Confined Relabel Correctly"
+ if is_rootless; then
+ run_podman unshare touch $tmpdir/test1
+ # Relabel entire directory
+ run_podman unshare chcon system_u:object_r:usr_t:s0 $tmpdir
+ run_podman start --attach label
+ newlevel=$(secon -l $output)
+ is "$level" "$newlevel" "start should relabel with same SELinux labels"
+ run ls -dZ $tmpdir
+ is "$output" "system_u:object_r:container_file_t:$level $tmpdir" \
+ "Confined Relabel Correctly"
+ run ls -dZ $tmpdir/test1
+ is "$output" "system_u:object_r:container_file_t:$level $tmpdir/test1" \
+ "Start did not Relabel"
+
+ # Relabel only file in subdir
+ run_podman unshare chcon system_u:object_r:usr_t:s0 $tmpdir/test1
+ run_podman start --attach label
+ newlevel=$(secon -l $output)
+ is "$level" "$newlevel" "start should use same SELinux labels"
+
+ run ls -dZ $tmpdir/test1
+ is "$output" "system_u:object_r:usr_t:s0 $tmpdir/test1" \
+ "Start did not Relabel"
+ fi
run_podman run -v $tmpdir:/test:z $IMAGE cat /proc/self/attr/current
run ls -dZ $tmpdir
is "$output" "${RELABEL} $tmpdir" "Shared Relabel Correctly"
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index cb73cf24d..b3471b425 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -444,6 +444,14 @@ load helpers
die "MAC address did not change after podman network disconnect/connect"
fi
+ # FIXME FIXME FIXME: #11825: bodhi tests are failing, remote+rootless only,
+ # with "dnsmasq: failed to create inotify". This error has never occurred
+ # in CI, and Ed has been unable to reproduce it on 1minutetip. This next
+ # line is a suggestion from Paul Holzinger for trying to shed light on
+ # the system context before the failure. This output will be invisible
+ # if the test passes.
+ for foo in /proc/\*/fd/*; do readlink -f $foo; done |grep '^/proc/.*inotify' |cut -d/ -f3 | xargs -I '{}' -- ps --no-headers -o '%p %U %a' -p '{}' |uniq -c |sort -n
+
# connect a second network
run_podman network connect $netname2 $cid
diff --git a/test/upgrade/test-upgrade.bats b/test/upgrade/test-upgrade.bats
index 5cb302a85..f6f32242b 100644
--- a/test/upgrade/test-upgrade.bats
+++ b/test/upgrade/test-upgrade.bats
@@ -97,8 +97,10 @@ podman \$opts run --name myfailedcontainer --label mylabel=$LABEL_FAILED \
podman \$opts run -d --name myrunningcontainer --label mylabel=$LABEL_RUNNING \
--network bridge \
-p $HOST_PORT:80 \
+ -p 127.0.0.1:8080-8082:8080-8082 \
-v $pmroot/var/www:/var/www \
-w /var/www \
+ --mac-address aa:bb:cc:dd:ee:ff \
$IMAGE /bin/busybox-extras httpd -f -p 80
podman \$opts pod create --name mypod
@@ -185,7 +187,7 @@ EOF
is "${lines[1]}" "mycreatedcontainer--Created----$LABEL_CREATED" "created"
is "${lines[2]}" "mydonecontainer--Exited (0).*----<no value>" "done"
is "${lines[3]}" "myfailedcontainer--Exited (17) .*----$LABEL_FAILED" "fail"
- is "${lines[4]}" "myrunningcontainer--Up .*--0.0.0.0:$HOST_PORT->80/tcp--$LABEL_RUNNING" "running"
+ is "${lines[4]}" "myrunningcontainer--Up .*--0\.0\.0\.0:$HOST_PORT->80\/tcp, 127\.0\.0\.1\:8080-8082->8080-8082\/tcp--$LABEL_RUNNING" "running"
# For debugging: dump containers and IDs
if [[ -n "$PODMAN_UPGRADE_TEST_DEBUG" ]]; then
diff --git a/test/utils/podmantest_test.go b/test/utils/podmantest_test.go
index 9bd1c4a66..1bb9ecb6b 100644
--- a/test/utils/podmantest_test.go
+++ b/test/utils/podmantest_test.go
@@ -23,7 +23,7 @@ var _ = Describe("PodmanTest test", func() {
FakeOutputs["check"] = []string{"check"}
os.Setenv("HOOK_OPTION", "hook_option")
env := os.Environ()
- session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env, true, false, nil)
+ session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, "", env, true, false, nil, nil)
os.Unsetenv("HOOK_OPTION")
session.WaitWithDefaultTimeout()
Expect(session.Command.Process).ShouldNot(BeNil())
diff --git a/test/utils/utils.go b/test/utils/utils.go
index bfefc58ec..d4d5e6e2f 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -66,27 +66,31 @@ func (p *PodmanTest) MakeOptions(args []string, noEvents, noCache bool) []string
// PodmanAsUserBase exec podman as user. uid and gid is set for credentials usage. env is used
// to record the env for debugging
-func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, noEvents, noCache bool, extraFiles []*os.File) *PodmanSession {
+func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string, env []string, noEvents, noCache bool, wrapper []string, extraFiles []*os.File) *PodmanSession {
var command *exec.Cmd
podmanOptions := p.MakeOptions(args, noEvents, noCache)
podmanBinary := p.PodmanBinary
if p.RemoteTest {
podmanBinary = p.RemotePodmanBinary
}
+
+ runCmd := append(wrapper, podmanBinary)
if p.RemoteTest {
podmanOptions = append([]string{"--remote", "--url", p.RemoteSocket}, podmanOptions...)
}
if env == nil {
- fmt.Printf("Running: %s %s\n", podmanBinary, strings.Join(podmanOptions, " "))
+ fmt.Printf("Running: %s %s\n", strings.Join(runCmd, " "), strings.Join(podmanOptions, " "))
} else {
- fmt.Printf("Running: (env: %v) %s %s\n", env, podmanBinary, strings.Join(podmanOptions, " "))
+ fmt.Printf("Running: (env: %v) %s %s\n", env, strings.Join(runCmd, " "), strings.Join(podmanOptions, " "))
}
if uid != 0 || gid != 0 {
pythonCmd := fmt.Sprintf("import os; import sys; uid = %d; gid = %d; cwd = '%s'; os.setgid(gid); os.setuid(uid); os.chdir(cwd) if len(cwd)>0 else True; os.execv(sys.argv[1], sys.argv[1:])", gid, uid, cwd)
- nsEnterOpts := append([]string{"-c", pythonCmd, podmanBinary}, podmanOptions...)
+ runCmd = append(runCmd, podmanOptions...)
+ nsEnterOpts := append([]string{"-c", pythonCmd}, runCmd...)
command = exec.Command("python", nsEnterOpts...)
} else {
- command = exec.Command(podmanBinary, podmanOptions...)
+ runCmd = append(runCmd, podmanOptions...)
+ command = exec.Command(runCmd[0], runCmd[1:]...)
}
if env != nil {
command.Env = env
@@ -106,7 +110,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
// PodmanBase exec podman with default env.
func (p *PodmanTest) PodmanBase(args []string, noEvents, noCache bool) *PodmanSession {
- return p.PodmanAsUserBase(args, 0, 0, "", nil, noEvents, noCache, nil)
+ return p.PodmanAsUserBase(args, 0, 0, "", nil, noEvents, noCache, nil, nil)
}
// WaitForContainer waits on a started container