summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/e2e/inspect_test.go26
-rw-r--r--test/e2e/ps_test.go17
-rw-r--r--test/e2e/run_networking_test.go24
-rw-r--r--test/e2e/volume_ls_test.go27
-rw-r--r--test/python/dockerpy/README.md40
-rw-r--r--test/python/dockerpy/__init__.py (renamed from test/test_dockerpy/__init__.py)0
-rw-r--r--test/python/dockerpy/tests/__init__.py0
-rw-r--r--test/python/dockerpy/tests/common.py105
-rw-r--r--test/python/dockerpy/tests/constant.py13
-rw-r--r--test/python/dockerpy/tests/test_containers.py (renamed from test/test_dockerpy/test_containers.py)43
-rw-r--r--test/python/dockerpy/tests/test_images.py (renamed from test/test_dockerpy/test_images.py)84
-rw-r--r--test/python/dockerpy/tests/test_info_version.py (renamed from test/test_dockerpy/test_info_version.py)12
-rw-r--r--test/system/015-help.bats18
-rw-r--r--test/system/030-run.bats41
-rw-r--r--test/system/200-pod.bats41
-rw-r--r--test/system/250-systemd.bats8
-rw-r--r--test/system/410-selinux.bats19
-rw-r--r--test/test_dockerpy/README.md30
-rw-r--r--test/test_dockerpy/common.py85
-rw-r--r--test/test_dockerpy/constant.py13
20 files changed, 450 insertions, 196 deletions
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index 2fad38a36..ed7876d8a 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -7,6 +7,7 @@ import (
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
+ "github.com/opencontainers/selinux/go-selinux"
)
var _ = Describe("Podman inspect", func() {
@@ -263,4 +264,29 @@ var _ = Describe("Podman inspect", func() {
Expect(len(baseJSON)).To(Equal(1))
Expect(baseJSON[0].Name).To(Equal(ctrName))
})
+
+ It("podman inspect - HostConfig.SecurityOpt ", func() {
+ if !selinux.GetEnabled() {
+ Skip("SELinux not enabled")
+ }
+
+ ctrName := "hugo"
+ create := podmanTest.PodmanNoCache([]string{
+ "create", "--name", ctrName,
+ "--security-opt", "seccomp=unconfined",
+ "--security-opt", "label=type:spc_t",
+ "--security-opt", "label=level:s0",
+ ALPINE, "sh"})
+
+ create.WaitWithDefaultTimeout()
+ Expect(create.ExitCode()).To(Equal(0))
+
+ baseInspect := podmanTest.Podman([]string{"inspect", ctrName})
+ baseInspect.WaitWithDefaultTimeout()
+ Expect(baseInspect.ExitCode()).To(Equal(0))
+ baseJSON := baseInspect.InspectContainerToJSON()
+ Expect(len(baseJSON)).To(Equal(1))
+ Expect(baseJSON[0].HostConfig.SecurityOpt).To(Equal([]string{"label=type:spc_t,label=level:s0", "seccomp=unconfined"}))
+ })
+
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 0dc8e01af..cfc0a415e 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -449,4 +449,21 @@ var _ = Describe("Podman ps", func() {
Expect(len(output)).To(Equal(1))
Expect(output[0]).To(Equal(ctrName))
})
+
+ It("podman ps test with port shared with pod", func() {
+ podName := "testPod"
+ pod := podmanTest.Podman([]string{"pod", "create", "-p", "8080:80", "--name", podName})
+ pod.WaitWithDefaultTimeout()
+ Expect(pod.ExitCode()).To(Equal(0))
+
+ ctrName := "testCtr"
+ session := podmanTest.Podman([]string{"run", "--name", ctrName, "-dt", "--pod", podName, ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ ps := podmanTest.Podman([]string{"ps", "--filter", fmt.Sprintf("name=%s", ctrName), "--format", "{{.Ports}}"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps.ExitCode()).To(Equal(0))
+ Expect(ps.OutputToString()).To(ContainSubstring("0.0.0.0:8080->80/tcp"))
+ })
})
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index afba12ccd..cdfbd5530 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -184,6 +184,30 @@ var _ = Describe("Podman run networking", func() {
Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal(""))
})
+ It("podman run -p 127.0.0.1::8080/udp", func() {
+ name := "testctr"
+ session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8080/udp", "--name", name, ALPINE, "/bin/sh"})
+ session.WaitWithDefaultTimeout()
+ inspectOut := podmanTest.InspectContainer(name)
+ Expect(len(inspectOut)).To(Equal(1))
+ Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8080/udp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostPort).To(Not(Equal("8080")))
+ Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostIP).To(Equal("127.0.0.1"))
+ })
+
+ It("podman run -p :8080", func() {
+ name := "testctr"
+ session := podmanTest.Podman([]string{"create", "-t", "-p", ":8080", "--name", name, ALPINE, "/bin/sh"})
+ session.WaitWithDefaultTimeout()
+ inspectOut := podmanTest.InspectContainer(name)
+ Expect(len(inspectOut)).To(Equal(1))
+ Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1))
+ Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Not(Equal("8080")))
+ Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal(""))
+ })
+
It("podman run network expose host port 80 to container port 8000", func() {
SkipIfRootless()
session := podmanTest.Podman([]string{"run", "-dt", "-p", "80:8000", ALPINE, "/bin/sh"})
diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go
index 7664e64bb..d2d75af9e 100644
--- a/test/e2e/volume_ls_test.go
+++ b/test/e2e/volume_ls_test.go
@@ -1,6 +1,7 @@
package integration
import (
+ "fmt"
"os"
. "github.com/containers/libpod/test/utils"
@@ -82,4 +83,30 @@ var _ = Describe("Podman volume ls", func() {
Expect(len(session.OutputToStringArray())).To(Equal(2))
Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName))
})
+
+ It("podman volume ls with --filter dangling", func() {
+ volName1 := "volume1"
+ session := podmanTest.Podman([]string{"volume", "create", volName1})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ volName2 := "volume2"
+ session2 := podmanTest.Podman([]string{"volume", "create", volName2})
+ session2.WaitWithDefaultTimeout()
+ Expect(session2.ExitCode()).To(Equal(0))
+
+ ctr := podmanTest.Podman([]string{"create", "-v", fmt.Sprintf("%s:/test", volName2), ALPINE, "sh"})
+ ctr.WaitWithDefaultTimeout()
+ Expect(ctr.ExitCode()).To(Equal(0))
+
+ lsNoDangling := podmanTest.Podman([]string{"volume", "ls", "--filter", "dangling=false", "--quiet"})
+ lsNoDangling.WaitWithDefaultTimeout()
+ Expect(lsNoDangling.ExitCode()).To(Equal(0))
+ Expect(lsNoDangling.OutputToString()).To(ContainSubstring(volName2))
+
+ lsDangling := podmanTest.Podman([]string{"volume", "ls", "--filter", "dangling=true", "--quiet"})
+ lsDangling.WaitWithDefaultTimeout()
+ Expect(lsDangling.ExitCode()).To(Equal(0))
+ Expect(lsDangling.OutputToString()).To(ContainSubstring(volName1))
+ })
})
diff --git a/test/python/dockerpy/README.md b/test/python/dockerpy/README.md
new file mode 100644
index 000000000..22908afc6
--- /dev/null
+++ b/test/python/dockerpy/README.md
@@ -0,0 +1,40 @@
+# Dockerpy regression test
+
+Python test suite to validate Podman endpoints using dockerpy library
+
+## Running Tests
+
+To run the tests locally in your sandbox (Fedora 32):
+
+```shell script
+# dnf install python3-docker
+```
+
+### Run the entire test suite
+
+```shell
+# cd test/python/dockerpy
+# PYTHONPATH=/usr/bin/python python -m unittest discover .
+```
+
+Passing the -v option to your test script will instruct unittest.main() to enable a higher level of verbosity, and produce detailed output:
+
+```shell
+# cd test/python/dockerpy
+# PYTHONPATH=/usr/bin/python python -m unittest -v discover .
+```
+
+### Run a specific test class
+
+```shell
+# cd test/python/dockerpy
+# PYTHONPATH=/usr/bin/python python -m unittest -v tests.test_images
+```
+
+### Run a specific test within the test class
+
+```shell
+# cd test/python/dockerpy
+# PYTHONPATH=/usr/bin/python python -m unittest tests.test_images.TestImages.test_import_image
+
+```
diff --git a/test/test_dockerpy/__init__.py b/test/python/dockerpy/__init__.py
index e69de29bb..e69de29bb 100644
--- a/test/test_dockerpy/__init__.py
+++ b/test/python/dockerpy/__init__.py
diff --git a/test/python/dockerpy/tests/__init__.py b/test/python/dockerpy/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/test/python/dockerpy/tests/__init__.py
diff --git a/test/python/dockerpy/tests/common.py b/test/python/dockerpy/tests/common.py
new file mode 100644
index 000000000..f83f4076f
--- /dev/null
+++ b/test/python/dockerpy/tests/common.py
@@ -0,0 +1,105 @@
+import os
+import pathlib
+import subprocess
+import sys
+import time
+
+from docker import APIClient
+
+from . import constant
+
+alpineDict = {
+ "name": "docker.io/library/alpine:latest",
+ "shortName": "alpine",
+ "tarballName": "alpine.tar"
+}
+
+
+def get_client():
+ client = APIClient(base_url="http://localhost:8080", timeout=15)
+ return client
+
+
+client = get_client()
+
+
+def podman():
+ binary = os.getenv("PODMAN_BINARY")
+ if binary is None:
+ binary = "../../../bin/podman"
+ return binary
+
+
+def restore_image_from_cache(TestClass):
+ alpineImage = os.path.join(constant.ImageCacheDir,
+ alpineDict["tarballName"])
+ if not os.path.exists(alpineImage):
+ os.makedirs(constant.ImageCacheDir, exist_ok=True)
+ client.pull(constant.ALPINE)
+ image = client.get_image(constant.ALPINE)
+ tarball = open(alpineImage, mode="wb")
+ for frame in image:
+ tarball.write(frame)
+ tarball.close()
+ else:
+ subprocess.run(
+ [podman(), "load", "-i", alpineImage],
+ shell=False,
+ stdin=subprocess.DEVNULL,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ check=True,
+ )
+
+
+def flush_image_cache(TestCase):
+ for f in pathlib.Path(constant.ImageCacheDir).glob("*"):
+ f.unlink(f)
+
+
+def run_top_container():
+ c = client.create_container(image=constant.ALPINE,
+ command='/bin/sleep 5',
+ name=constant.TOP)
+ client.start(container=c.get("Id"))
+ return c.get("Id")
+
+
+def enable_sock(TestClass):
+ TestClass.podman = subprocess.Popen(
+ [
+ podman(), "system", "service", "tcp:localhost:8080",
+ "--log-level=debug", "--time=0"
+ ],
+ shell=False,
+ stdin=subprocess.DEVNULL,
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ )
+ time.sleep(2)
+
+
+def terminate_connection(TestClass):
+ TestClass.podman.terminate()
+ stdout, stderr = TestClass.podman.communicate(timeout=0.5)
+ if stdout:
+ print("\nService Stdout:\n" + stdout.decode('utf-8'))
+ if stderr:
+ print("\nService Stderr:\n" + stderr.decode('utf-8'))
+
+ if TestClass.podman.returncode > 0:
+ sys.stderr.write("podman exited with error code {}\n".format(
+ TestClass.podman.returncode))
+ sys.exit(2)
+
+
+def remove_all_containers():
+ containers = client.containers(quiet=True)
+ for c in containers:
+ client.remove_container(container=c.get("Id"), force=True)
+
+
+def remove_all_images():
+ allImages = client.images()
+ for image in allImages:
+ client.remove_image(image, force=True)
diff --git a/test/python/dockerpy/tests/constant.py b/test/python/dockerpy/tests/constant.py
new file mode 100644
index 000000000..b44442d02
--- /dev/null
+++ b/test/python/dockerpy/tests/constant.py
@@ -0,0 +1,13 @@
+BB = "docker.io/library/busybox:latest"
+NGINX = "docker.io/library/nginx:latest"
+ALPINE = "docker.io/library/alpine:latest"
+ALPINE_SHORTNAME = "alpine"
+ALPINELISTTAG = "docker.io/library/alpine:3.10.2"
+ALPINELISTDIGEST = "docker.io/library/alpine@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb"
+ALPINEAMD64DIGEST = "docker.io/library/alpine@sha256:acd3ca9941a85e8ed16515bfc5328e4e2f8c128caa72959a58a127b7801ee01f"
+ALPINEAMD64ID = "961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4"
+ALPINEARM64DIGEST = "docker.io/library/alpine@sha256:db7f3dcef3d586f7dd123f107c93d7911515a5991c4b9e51fa2a43e46335a43e"
+ALPINEARM64ID = "915beeae46751fc564998c79e73a1026542e945ca4f73dc841d09ccc6c2c0672"
+infra = "k8s.gcr.io/pause:3.2"
+TOP = "top"
+ImageCacheDir = "/tmp/podman/imagecachedir"
diff --git a/test/test_dockerpy/test_containers.py b/test/python/dockerpy/tests/test_containers.py
index 34fe82c18..6b89688d4 100644
--- a/test/test_dockerpy/test_containers.py
+++ b/test/python/dockerpy/tests/test_containers.py
@@ -1,18 +1,15 @@
-
-import unittest
-import docker
-import requests
import os
-from docker import Client
-from . import constant
-from . import common
import time
+import unittest
+
+import requests
+
+from . import common, constant
client = common.get_client()
-class TestContainers(unittest.TestCase):
- podman = None
+class TestContainers(unittest.TestCase):
topContainerId = ""
def setUp(self):
@@ -33,6 +30,7 @@ class TestContainers(unittest.TestCase):
@classmethod
def tearDownClass(cls):
common.terminate_connection(cls)
+ common.flush_image_cache(cls)
return super().tearDownClass()
def test_inspect_container(self):
@@ -42,16 +40,15 @@ class TestContainers(unittest.TestCase):
self.assertEqual(error.exception.response.status_code, 404)
# Inspect valid container by name
container = client.inspect_container(constant.TOP)
- self.assertIn(TestContainers.topContainerId , container["Id"])
+ self.assertIn(TestContainers.topContainerId, container["Id"])
# Inspect valid container by Id
container = client.inspect_container(TestContainers.topContainerId)
- self.assertIn(constant.TOP , container["Name"])
+ self.assertIn(constant.TOP, container["Name"])
def test_create_container(self):
# Run a container with detach mode
container = client.create_container(image="alpine", detach=True)
- self.assertEqual(len(container),2)
-
+ self.assertEqual(len(container), 2)
def test_start_container(self):
# Start bogus container
@@ -65,9 +62,9 @@ class TestContainers(unittest.TestCase):
# self.assertEqual(error.exception.response.status_code, 304)
# Create a new container and validate the count
- client.create_container(image=constant.ALPINE,name="container2")
- containers = client.containers(quiet=True,all=True)
- self.assertEqual(len(containers),2)
+ client.create_container(image=constant.ALPINE, name="container2")
+ containers = client.containers(quiet=True, all=True)
+ self.assertEqual(len(containers), 2)
def test_stop_container(self):
# Stop bogus container
@@ -82,7 +79,10 @@ class TestContainers(unittest.TestCase):
# Stop a running container and validate the state
client.stop(TestContainers.topContainerId)
container = client.inspect_container(constant.TOP)
- self.assertIn(container["State"]["Status"],"stopped exited",)
+ self.assertIn(
+ container["State"]["Status"],
+ "stopped exited",
+ )
def test_restart_container(self):
# Restart bogus container
@@ -109,12 +109,12 @@ class TestContainers(unittest.TestCase):
# Remove container by ID with force
client.remove_container(TestContainers.topContainerId, force=True)
containers = client.containers()
- self.assertEqual(len(containers),0)
+ self.assertEqual(len(containers), 0)
def test_remove_container_without_force(self):
# Validate current container count
containers = client.containers()
- self.assertTrue(len(containers),1)
+ self.assertTrue(len(containers), 1)
# Remove running container should throw error
with self.assertRaises(requests.HTTPError) as error:
@@ -125,7 +125,7 @@ class TestContainers(unittest.TestCase):
client.stop(TestContainers.topContainerId)
client.remove_container(TestContainers.topContainerId)
containers = client.containers()
- self.assertEqual(len(containers),0)
+ self.assertEqual(len(containers), 0)
def test_pause_container(self):
# Pause bogus container
@@ -151,7 +151,6 @@ class TestContainers(unittest.TestCase):
client.pause(TestContainers.topContainerId)
self.assertEqual(error.exception.response.status_code, 500)
-
def test_unpause_container(self):
# Unpause bogus container
with self.assertRaises(requests.HTTPError) as error:
@@ -173,7 +172,7 @@ class TestContainers(unittest.TestCase):
# Add container and validate the count
client.create_container(image="alpine", detach=True)
containers = client.containers(all=True)
- self.assertEqual(len(containers),2)
+ self.assertEqual(len(containers), 2)
# Not working for now......checking
# # List container with filter by id
diff --git a/test/test_dockerpy/test_images.py b/test/python/dockerpy/tests/test_images.py
index c88353b79..5eae61c2f 100644
--- a/test/test_dockerpy/test_images.py
+++ b/test/python/dockerpy/tests/test_images.py
@@ -1,17 +1,18 @@
-
+import os
+import stat
import unittest
+from os import remove
+from stat import ST_SIZE
+
import docker
import requests
-import os
-from docker import Client
-from . import constant
-from . import common
+
+from . import common, constant
client = common.get_client()
-class TestImages(unittest.TestCase):
- podman = None
+class TestImages(unittest.TestCase):
def setUp(self):
super().setUp()
common.restore_image_from_cache(self)
@@ -25,13 +26,12 @@ class TestImages(unittest.TestCase):
super().setUpClass()
common.enable_sock(cls)
-
@classmethod
def tearDownClass(cls):
common.terminate_connection(cls)
+ common.flush_image_cache(cls)
return super().tearDownClass()
-
# Inspect Image
def test_inspect_image(self):
@@ -43,46 +43,46 @@ class TestImages(unittest.TestCase):
# Tag Image
- # Validates if invalid image name is given a bad response is encountered.
+# Validates if invalid image name is given a bad response is encountered.
+
def test_tag_invalid_image(self):
with self.assertRaises(requests.HTTPError):
- client.tag("dummy","demo")
-
-
+ client.tag("dummy", "demo")
# Validates if the image is tagged successfully.
def test_tag_valid_image(self):
- client.tag(constant.ALPINE,"demo",constant.ALPINE_SHORTNAME)
+ client.tag(constant.ALPINE, "demo", constant.ALPINE_SHORTNAME)
alpine_image = client.inspect_image(constant.ALPINE)
for x in alpine_image["RepoTags"]:
- if("demo:alpine" in x):
+ if ("demo:alpine" in x):
self.assertTrue
self.assertFalse
# Validates if name updates when the image is retagged.
@unittest.skip("dosent work now")
def test_retag_valid_image(self):
- client.tag(constant.ALPINE_SHORTNAME, "demo","rename")
+ client.tag(constant.ALPINE_SHORTNAME, "demo", "rename")
alpine_image = client.inspect_image(constant.ALPINE)
self.assertNotIn("demo:test", alpine_image["RepoTags"])
# List Image
- # List All Images
+# List All Images
+
def test_list_images(self):
allImages = client.images()
self.assertEqual(len(allImages), 1)
# Add more images
client.pull(constant.BB)
allImages = client.images()
- self.assertEqual(len(allImages) , 2)
-
+ self.assertEqual(len(allImages), 2)
- # List images with filter
- filters = {'reference':'alpine'}
- allImages = client.images(filters = filters)
- self.assertEqual(len(allImages) , 1)
+ # List images with filter
+ filters = {'reference': 'alpine'}
+ allImages = client.images(filters=filters)
+ self.assertEqual(len(allImages), 1)
# Search Image
+
def test_search_image(self):
response = client.search("alpine")
for i in response:
@@ -94,22 +94,25 @@ class TestImages(unittest.TestCase):
# Image Exist (No docker-py support yet)
# Remove Image
+
def test_remove_image(self):
# Check for error with wrong image name
with self.assertRaises(requests.HTTPError):
client.remove_image("dummy")
allImages = client.images()
- self.assertEqual(len(allImages) , 1)
+ self.assertEqual(len(allImages), 1)
alpine_image = client.inspect_image(constant.ALPINE)
client.remove_image(alpine_image)
allImages = client.images()
- self.assertEqual(len(allImages) , 0)
+ self.assertEqual(len(allImages), 0)
# Image History
+
def test_image_history(self):
# Check for error with wrong image name
with self.assertRaises(requests.HTTPError):
- client.remove_image("dummy")
+ client.history("dummy")
+
imageHistory = client.history(constant.ALPINE)
alpine_image = client.inspect_image(constant.ALPINE)
for h in imageHistory:
@@ -119,28 +122,37 @@ class TestImages(unittest.TestCase):
# Prune Image (No docker-py support yet)
+ def test_get_image_dummy(self):
+ # FIXME: seems to be an error in the library
+ self.skipTest("Documentation and library do not match")
+ # Check for error with wrong image name
+ with self.assertRaises(docker.errors.ImageNotFound):
+ client.get_image("dummy")
+
# Export Image
def test_export_image(self):
client.pull(constant.BB)
- file = os.path.join(constant.ImageCacheDir , "busybox.tar")
if not os.path.exists(constant.ImageCacheDir):
os.makedirs(constant.ImageCacheDir)
- # Check for error with wrong image name
- with self.assertRaises(requests.HTTPError):
- client.get_image("dummy")
- response = client.get_image(constant.BB)
- image_tar = open(file,mode="wb")
- image_tar.write(response.data)
- image_tar.close()
- os.stat(file)
+
+ image = client.get_image(constant.BB)
+
+ file = os.path.join(constant.ImageCacheDir, "busybox.tar")
+ tarball = open(file, mode="wb")
+ for frame in image:
+ tarball.write(frame)
+ tarball.close()
+ sz = os.path.getsize(file)
+ self.assertGreater(sz, 0)
+
# Import|Load Image
def test_import_image(self):
allImages = client.images()
self.assertEqual(len(allImages), 1)
- file = os.path.join(constant.ImageCacheDir , "busybox.tar")
+ file = os.path.join(constant.ImageCacheDir, "alpine.tar")
client.import_image_from_file(filename=file)
allImages = client.images()
self.assertEqual(len(allImages), 2)
diff --git a/test/test_dockerpy/test_info_version.py b/test/python/dockerpy/tests/test_info_version.py
index be1a2aab9..e3ee18ec7 100644
--- a/test/test_dockerpy/test_info_version.py
+++ b/test/python/dockerpy/tests/test_info_version.py
@@ -1,11 +1,10 @@
import unittest
-import docker
-from docker import Client
-from . import constant
-from . import common
+
+from . import common, constant
client = common.get_client()
+
class TestInfo_Version(unittest.TestCase):
podman = None
@@ -31,16 +30,15 @@ class TestInfo_Version(unittest.TestCase):
common.terminate_connection(cls)
return super().tearDownClass()
-
def test_Info(self):
self.assertIsNotNone(client.info())
def test_info_container_details(self):
info = client.info()
- self.assertEqual(info["Containers"],1)
+ self.assertEqual(info["Containers"], 1)
client.create_container(image=constant.ALPINE)
info = client.info()
- self.assertEqual(info["Containers"],2)
+ self.assertEqual(info["Containers"], 2)
def test_version(self):
self.assertIsNotNone(client.version())
diff --git a/test/system/015-help.bats b/test/system/015-help.bats
index 14af8e1a4..3d05b44fe 100644
--- a/test/system/015-help.bats
+++ b/test/system/015-help.bats
@@ -34,13 +34,16 @@ function check_help() {
dprint "$command_string --help"
run_podman "$@" $cmd --help
+ local full_help="$output"
# The line immediately after 'Usage:' gives us a 1-line synopsis
- usage=$(echo "$output" | grep -A1 '^Usage:' | tail -1)
+ usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1)
[ -n "$usage" ] || die "podman $cmd: no Usage message found"
# e.g. 'podman ps' should not show 'podman container ps' in usage
- is "$usage" " $command_string .*" "Usage string matches command"
+ # Trailing space in usage handles 'podman system renumber' which
+ # has no ' [flags]'
+ is "$usage " " $command_string .*" "Usage string matches command"
# If usage ends in '[command]', recurse into subcommands
if expr "$usage" : '.*\[command\]$' >/dev/null; then
@@ -59,6 +62,17 @@ function check_help() {
die "'flags' must precede arguments in usage: $usage"
fi
+ # Cross-check: if usage includes '[flags]', there must be a
+ # longer 'Flags:' section in the full --help output; vice-versa,
+ # if 'Flags:' is in full output, usage line must have '[flags]'.
+ if expr "$usage" : '.*\[flag' >/dev/null; then
+ if ! expr "$full_help" : ".*Flags:" >/dev/null; then
+ die "$command_string: Usage includes '[flags]' but has no 'Flags:' subsection"
+ fi
+ elif expr "$full_help" : ".*Flags:" >/dev/null; then
+ die "$command_string: --help has 'Flags:' section but no '[flags]' in synopsis"
+ fi
+
# If usage lists no arguments (strings in ALL CAPS), confirm
# by running with 'invalid-arg' and expecting failure.
if ! expr "$usage" : '.*[A-Z]' >/dev/null; then
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index eeecea2e5..bc6347012 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -201,4 +201,45 @@ echo $rand | 0 | $rand
"podman will not overwrite existing cidfile"
}
+@test "podman run docker-archive" {
+ # Create an image that, when run, outputs a random magic string
+ expect=$(random_string 20)
+ run_podman run --name myc --entrypoint="[\"/bin/echo\",\"$expect\"]" $IMAGE
+ is "$output" "$expect" "podman run --entrypoint echo-randomstring"
+
+ # Save it as a tar archive
+ run_podman commit myc myi
+ archive=$PODMAN_TMPDIR/archive.tar
+ run_podman save myi -o $archive
+ is "$output" "" "podman save"
+
+ # Clean up image and container from container storage...
+ run_podman rmi myi
+ run_podman rm myc
+
+ # ... then confirm we can run from archive. This re-imports the image
+ # and runs it, producing our random string as the last line.
+ run_podman run docker-archive:$archive
+ is "${lines[0]}" "Getting image source signatures" "podman run docker-archive, first line of output"
+ is "$output" ".*Copying blob" "podman run docker-archive"
+ is "$output" ".*Copying config" "podman run docker-archive"
+ is "$output" ".*Writing manifest" "podman run docker-archive"
+ is "${lines[-1]}" "$expect" "podman run docker-archive: expected random string output"
+
+ # Clean up container as well as re-imported image
+ run_podman rm -a
+ run_podman rmi myi
+
+ # Repeat the above, with podman-create and podman-start.
+ run_podman create docker-archive:$archive
+ cid=${lines[-1]}
+
+ run_podman start --attach $cid
+ is "$output" "$expect" "'podman run' of 'podman-create docker-archive'"
+
+ # Clean up.
+ run_podman rm $cid
+ run_podman rmi myi
+}
+
# vim: filetype=sh
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 9a6b39057..0e9d9132e 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -150,6 +150,18 @@ function random_ip() {
pod_id_file=${PODMAN_TMPDIR}/pod-id-file
+ # Randomly-assigned ports in the 5xxx and 6xxx range
+ for port_in in $(shuf -i 5000-5999);do
+ if ! { exec 3<> /dev/tcp/127.0.0.1/$port_in; } &>/dev/null; then
+ break
+ fi
+ done
+ for port_out in $(shuf -i 6000-6999);do
+ if ! { exec 3<> /dev/tcp/127.0.0.1/$port_out; } &>/dev/null; then
+ break
+ fi
+ done
+
# Create a pod with all the desired options
# FIXME: --ip=$ip fails:
# Error adding network: failed to allocate all requested IPs
@@ -161,6 +173,7 @@ function random_ip() {
--dns "$dns_server" \
--dns-search "$dns_search" \
--dns-opt "$dns_opt" \
+ --publish "$port_out:$port_in" \
--label "${labelname}=${labelvalue}"
pod_id="$output"
@@ -199,6 +212,34 @@ function random_ip() {
run_podman pod ps --no-trunc --filter "label=${labelname}=${labelvalue}" --format '{{.ID}}'
is "$output" "$pod_id" "pod ps --filter label=..."
+ # Test local port forwarding, as well as 'ps' output showing ports
+ # Run 'nc' in a container, waiting for input on the published port.
+ c_name=$(random_string 15)
+ run_podman run -d --pod mypod --name $c_name $IMAGE nc -l -p $port_in
+ cid="$output"
+
+ # Try running another container also listening on the same port.
+ run_podman 1 run --pod mypod --name dsfsdfsdf $IMAGE nc -l -p $port_in
+ is "$output" "nc: bind: Address in use" \
+ "two containers cannot bind to same port"
+
+ # While the container is still running, run 'podman ps' (no --format)
+ # and confirm that the output includes the published port
+ run_podman ps --filter id=$cid
+ is "${lines[1]}" "${cid:0:12} $IMAGE nc -l -p $port_in .* 0.0.0.0:$port_out->$port_in/tcp $c_name" \
+ "output of 'podman ps'"
+
+ # send a random string to the container. This will cause the container
+ # to output the string to its logs, then exit.
+ teststring=$(random_string 30)
+ echo "$teststring" | nc 127.0.0.1 $port_out
+
+ # Confirm that the container log output is the string we sent it.
+ run_podman logs $cid
+ is "$output" "$teststring" "test string received on container"
+
+ # Clean up
+ run_podman rm $cid
run_podman pod rm -f mypod
}
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 4bee13414..b7035cdda 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -41,7 +41,7 @@ function teardown() {
fi
cname=$(random_string)
- run_podman create --name $cname --detach $IMAGE top
+ run_podman create --name $cname --label "io.containers.autoupdate=image" --detach $IMAGE top
run_podman generate systemd --new $cname
echo "$output" > "$UNIT_FILE"
@@ -64,6 +64,12 @@ function teardown() {
run_podman logs $cname
is "$output" ".*Load average:.*" "running container 'top'-like output"
+ # Exercise `podman auto-update`.
+ # TODO: this will at least run auto-update code but won't perform an update
+ # since the image didn't change. We need to improve on that and run
+ # an image from a local registry instead.
+ run_podman auto-update
+
# All good. Stop service, clean up.
run $SYSTEMCTL stop "$SERVICE_NAME"
if [ $status -ne 0 ]; then
diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats
index 8a0477eff..1769730f0 100644
--- a/test/system/410-selinux.bats
+++ b/test/system/410-selinux.bats
@@ -63,4 +63,23 @@ function check_label() {
check_label "--security-opt label=level:s0:c1,c2" "container_t" "s0:c1,c2"
}
+# pr #6752
+@test "podman selinux: inspect multiple labels" {
+ if [ ! -e /usr/sbin/selinuxenabled ] || ! /usr/sbin/selinuxenabled; then
+ skip "selinux disabled or not available"
+ fi
+
+ 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'
+ run_podman inspect --format='{{ .HostConfig.SecurityOpt }}' myc
+ is "$output" "\[label=type:spc_t,label=level:s0 seccomp=unconfined]" \
+ "'podman inspect' preserves all --security-opts"
+
+ run_podman exec myc touch /stop
+ run_podman rm -f myc
+}
+
# vim: filetype=sh
diff --git a/test/test_dockerpy/README.md b/test/test_dockerpy/README.md
deleted file mode 100644
index 32e426d58..000000000
--- a/test/test_dockerpy/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Dockerpy regression test
-
-Python test suite to validate Podman endpoints using dockerpy library
-
-Running tests
-=============
-To run the tests locally in your sandbox:
-
-#### Run the entire test
-
-```
-sudo PYTHONPATH=/usr/bin/python python -m dockerpy.images
-```
-
-Passing the -v option to your test script will instruct unittest.main() to enable a higher level of verbosity, and produce detailed output:
-
-```
-sudo PYTHONPATH=/usr/bin/python python -m unittest -v dockerpy.images
-```
-#### Run a specific test class
-
-```
-sudo PYTHONPATH=/usr/bin/python python -m unittest -v dockerpy.images.TestImages
-```
-
-#### Run a specific test within the test class
-
-```
-sudo PYTHONPATH=/usr/bin/python python -m unittest -v dockerpy.images.TestImages.test_list_images
-```
diff --git a/test/test_dockerpy/common.py b/test/test_dockerpy/common.py
deleted file mode 100644
index 975b13dc6..000000000
--- a/test/test_dockerpy/common.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import docker
-import subprocess
-import os
-import sys
-import time
-from docker import Client
-from . import constant
-
-alpineDict = {
- "name": "docker.io/library/alpine:latest",
- "shortName": "alpine",
- "tarballName": "alpine.tar"}
-
-def get_client():
- client = docker.Client(base_url="http://localhost:8080",timeout=15)
- return client
-
-client = get_client()
-
-def podman():
- binary = os.getenv("PODMAN_BINARY")
- if binary is None:
- binary = "bin/podman"
- return binary
-
-def restore_image_from_cache(TestClass):
- alpineImage = os.path.join(constant.ImageCacheDir , alpineDict["tarballName"])
- if not os.path.exists(alpineImage):
- os.makedirs(constant.ImageCacheDir)
- client.pull(constant.ALPINE)
- response = client.get_image(constant.ALPINE)
- image_tar = open(alpineImage,mode="wb")
- image_tar.write(response.data)
- image_tar.close()
- else :
- TestClass.podman = subprocess.run(
- [
- podman(), "load", "-i", alpineImage
- ],
- shell=False,
- stdin=subprocess.DEVNULL,
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL,
- )
-
-def run_top_container():
- c = client.create_container(image=constant.ALPINE,command='/bin/sleep 5',name=constant.TOP)
- client.start(container=c.get("Id"))
- return c.get("Id")
-
-def enable_sock(TestClass):
- TestClass.podman = subprocess.Popen(
- [
- podman(), "system", "service", "tcp:localhost:8080",
- "--log-level=debug", "--time=0"
- ],
- shell=False,
- stdin=subprocess.DEVNULL,
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL,
- )
- time.sleep(2)
-
-def terminate_connection(TestClass):
- TestClass.podman.terminate()
- stdout, stderr = TestClass.podman.communicate(timeout=0.5)
- if stdout:
- print("\nService Stdout:\n" + stdout.decode('utf-8'))
- if stderr:
- print("\nService Stderr:\n" + stderr.decode('utf-8'))
-
- if TestClass.podman.returncode > 0:
- sys.stderr.write("podman exited with error code {}\n".format(
- TestClass.podman.returncode))
- sys.exit(2)
-
-def remove_all_containers():
- containers = client.containers(quiet=True)
- for c in containers:
- client.remove_container(container=c.get("Id"), force=True)
-
-def remove_all_images():
- allImages = client.images()
- for image in allImages:
- client.remove_image(image,force=True)
diff --git a/test/test_dockerpy/constant.py b/test/test_dockerpy/constant.py
deleted file mode 100644
index 8a3f1d984..000000000
--- a/test/test_dockerpy/constant.py
+++ /dev/null
@@ -1,13 +0,0 @@
-BB = "docker.io/library/busybox:latest"
-NGINX = "docker.io/library/nginx:latest"
-ALPINE = "docker.io/library/alpine:latest"
-ALPINE_SHORTNAME = "alpine"
-ALPINELISTTAG = "docker.io/library/alpine:3.10.2"
-ALPINELISTDIGEST = "docker.io/library/alpine@sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb"
-ALPINEAMD64DIGEST = "docker.io/library/alpine@sha256:acd3ca9941a85e8ed16515bfc5328e4e2f8c128caa72959a58a127b7801ee01f"
-ALPINEAMD64ID = "961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4"
-ALPINEARM64DIGEST = "docker.io/library/alpine@sha256:db7f3dcef3d586f7dd123f107c93d7911515a5991c4b9e51fa2a43e46335a43e"
-ALPINEARM64ID = "915beeae46751fc564998c79e73a1026542e945ca4f73dc841d09ccc6c2c0672"
-infra = "k8s.gcr.io/pause:3.2"
-TOP = "top"
-ImageCacheDir = "/tmp/podman/imagecachedir"