summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/python/podman/client.py2
-rw-r--r--contrib/python/podman/libs/images.py34
-rw-r--r--contrib/python/test/test_images.py35
-rwxr-xr-xcontrib/python/test/test_runner.sh50
4 files changed, 84 insertions, 37 deletions
diff --git a/contrib/python/podman/client.py b/contrib/python/podman/client.py
index c6112aae8..89fcf5c15 100644
--- a/contrib/python/podman/client.py
+++ b/contrib/python/podman/client.py
@@ -38,7 +38,7 @@ class Client(object):
@contextlib.contextmanager
def _podman(uri, interface):
- """Context manager for API children to access varlink."""
+ """Context manager for API workers to access varlink."""
client = VarlinkClient(address=uri)
try:
iface = client.open(interface)
diff --git a/contrib/python/podman/libs/images.py b/contrib/python/podman/libs/images.py
index f28cb64aa..3beadec1d 100644
--- a/contrib/python/podman/libs/images.py
+++ b/contrib/python/podman/libs/images.py
@@ -30,23 +30,18 @@ class Image(collections.UserDict):
return super().__getitem__(key)
def _split_token(self, values=None, sep='='):
- mapped = {}
- if values:
- for var in values:
- k, v = var.split(sep, 1)
- mapped[k] = v
- return mapped
+ return dict([v.split(sep, 1) for v in values if values])
def create(self, *args, **kwargs):
"""Create container from image.
Pulls defaults from image.inspect()
"""
- # Inialize config from parameters
with self._client() as podman:
details = self.inspect()
# TODO: remove network settings once defaults implemented in service
+ # Inialize config from parameters, then add image information
config = Config(image_id=self.id, **kwargs)
config['command'] = details.containerconfig['cmd']
config['env'] = self._split_token(details.containerconfig['env'])
@@ -75,9 +70,8 @@ class Image(collections.UserDict):
for r in podman.HistoryImage(self.id)['history']:
yield collections.namedtuple('HistoryDetail', r.keys())(**r)
+ # Convert all keys to lowercase.
def _lower_hook(self):
- """Convert all keys to lowercase."""
-
@functools.wraps(self._lower_hook)
def wrapped(input):
return {k.lower(): v for (k, v) in input.items()}
@@ -127,14 +121,26 @@ class Images(object):
for img in results['images']:
yield Image(self._client, img['id'], img)
- def build(self, *args, **kwargs):
+ def build(self, dockerfile=None, tags=None, **kwargs):
"""Build container from image.
See podman-build.1.md for kwargs details.
"""
+ if dockerfile is None:
+ raise ValueError('"dockerfile" is a required argument.')
+ elif not hasattr(dockerfile, '__iter__'):
+ raise ValueError('"dockerfile" is required to be an iter.')
+
+ if tags is None:
+ raise ValueError('"tags" is a required argument.')
+ elif not hasattr(tags, '__iter__'):
+ raise ValueError('"tags" is required to be an iter.')
+
+ config = Config(dockerfile=dockerfile, tags=tags, **kwargs)
with self._client() as podman:
- # TODO: Need arguments
- podman.BuildImage()
+ result = podman.BuildImage(config)
+ return self.get(result['image']['id']), \
+ (line for line in result['image']['logs'])
def delete_unused(self):
"""Delete Images not associated with a container."""
@@ -163,4 +169,6 @@ class Images(object):
def get(self, id):
"""Get Image from id."""
- return next((i for i in self.list() if i.id == id), None)
+ with self._client() as podman:
+ result = podman.GetImage(id)
+ return Image(self._client, result['image']['id'], result['image'])
diff --git a/contrib/python/test/test_images.py b/contrib/python/test/test_images.py
index f9eaee139..c8c1814dc 100644
--- a/contrib/python/test/test_images.py
+++ b/contrib/python/test/test_images.py
@@ -1,6 +1,7 @@
import itertools
import os
import unittest
+from datetime import datetime, timezone
from test.podman_testcase import PodmanTestCase
import podman
@@ -34,6 +35,7 @@ class TestImages(PodmanTestCase):
i for i in self.images
if 'docker.io/library/alpine:latest' in i['repoTags']
] or []), None)
+
return self.images
def test_list(self):
@@ -42,15 +44,29 @@ class TestImages(PodmanTestCase):
self.assertIsNotNone(self.alpine_image)
def test_build(self):
- with self.assertRaisesNotImplemented():
- self.pclient.images.build()
+ path = os.path.join(self.tmpdir, 'ctnr', 'Dockerfile')
+ img, logs = self.pclient.images.build(
+ dockerfile=[path],
+ tags=['alpine-unittest'],
+ )
+ self.assertIsNotNone(img)
+ self.assertIn('localhost/alpine-unittest:latest', img.repoTags)
+ self.assertLess(
+ podman.datetime_parse(img.created), datetime.now(timezone.utc))
+ self.assertTrue(logs)
def test_create(self):
+ img_details = self.alpine_image.inspect()
+
actual = self.alpine_image.container()
self.assertIsNotNone(actual)
self.assertEqual(actual.status, 'configured')
- cntr = actual.start()
- self.assertIn(cntr.status, ['running', 'exited'])
+ ctnr = actual.start()
+ self.assertIn(ctnr.status, ['running', 'exited'])
+
+ ctnr_details = ctnr.inspect()
+ for e in img_details.containerconfig['env']:
+ self.assertIn(e, ctnr_details.config['env'])
def test_export(self):
path = os.path.join(self.tmpdir, 'alpine_export.tar')
@@ -60,6 +76,10 @@ class TestImages(PodmanTestCase):
self.assertTrue(actual)
self.assertTrue(os.path.isfile(path))
+ def test_get(self):
+ actual = self.pclient.images.get(self.alpine_image.id)
+ self.assertEqual(actual, self.alpine_image)
+
def test_history(self):
for count, record in enumerate(self.alpine_image.history()):
self.assertEqual(record.id, self.alpine_image.id)
@@ -102,8 +122,11 @@ class TestImages(PodmanTestCase):
before = self.loadCache()
# create unused image, so we have something to delete
source = os.path.join(self.tmpdir, 'alpine_gold.tar')
- new_img = self.pclient.images.import_image(source, 'alpine2:latest',
- 'unittest.test_import')
+ new_img = self.pclient.images.import_image(
+ source,
+ 'alpine2:latest',
+ 'unittest.test_import',
+ )
after = self.loadCache()
self.assertEqual(len(before) + 1, len(after))
diff --git a/contrib/python/test/test_runner.sh b/contrib/python/test/test_runner.sh
index 1cccbe1f5..4e5844831 100755
--- a/contrib/python/test/test_runner.sh
+++ b/contrib/python/test/test_runner.sh
@@ -6,6 +6,13 @@ if [[ $(id -u) != 0 ]]; then
exit 2
fi
+# setup path to find new binaries _NOT_ system binaries
+if [[ ! -x ../../bin/podman ]]; then
+ echo 1>&2 Cannot find podman binary from libpod root directory. Run \"make binaries\"
+ exit 1
+fi
+export PATH=../../bin:$PATH
+
while getopts "vh" arg; do
case $arg in
v ) VERBOSE='-v' ;;
@@ -14,8 +21,16 @@ while getopts "vh" arg; do
done
shift $((OPTIND-1))
+function cleanup {
+ # aggressive cleanup as tests may crash leaving crap around
+ umount '^(shm|nsfs)'
+ umount '\/run\/netns'
+ rm -r "$1"
+}
+
# Create temporary directory for storage
export TMPDIR=`mktemp -d /tmp/podman.XXXXXXXXXX`
+trap "cleanup $TMPDIR" EXIT
function umount {
# xargs -r always ran once, so write any mount points to file first
@@ -25,26 +40,16 @@ function umount {
fi
}
-function cleanup {
- umount '^(shm|nsfs)'
- umount '\/run\/netns'
- rm -fr ${TMPDIR}
-}
-trap cleanup EXIT
-
-# setup path to find new binaries _NOT_ system binaries
-if [[ ! -x ../../bin/podman ]]; then
- echo 1>&2 Cannot find podman binary from libpod root directory, Or, run \"make binaries\"
- exit 1
-fi
-export PATH=../../bin:$PATH
-
function showlog {
- [ -s "$1" ] && (echo $1 =====; cat "$1"; echo)
+ [[ -s $1 ]] && cat <<-EOT
+$1 =====
+$(cat "$1")
+
+EOT
}
-# Need a location to store the podman socket
-mkdir -p ${TMPDIR}/{podman,crio,crio-run,cni/net.d}
+# Need locations to store stuff
+mkdir -p ${TMPDIR}/{podman,crio,crio-run,cni/net.d,ctnr}
# Cannot be done in python unittest fixtures. EnvVar not picked up.
export REGISTRIES_CONFIG_PATH=${TMPDIR}/registry.conf
@@ -85,6 +90,17 @@ cat >$CNI_CONFIG_PATH/87-podman-bridge.conflist <<-EOT
}
EOT
+cat >$TMPDIR/ctnr/hello.sh <<-EOT
+echo 'Hello, World'
+EOT
+
+cat >$TMPDIR/ctnr/Dockerfile <<-EOT
+FROM alpine:latest
+COPY ./hello.sh /tmp/hello.sh
+RUN chmod 755 /tmp/hello.sh
+ENTRYPOINT ["/tmp/hello.sh"]
+EOT
+
export PODMAN_HOST="unix:${TMPDIR}/podman/io.projectatomic.podman"
PODMAN_ARGS="--storage-driver=vfs\
--root=${TMPDIR}/crio\