diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e9bf895..eb74dff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## udocker (1.3.9) + +* add support to access non-config metadata from containers +* added support for multiplatform manifests and indices solves #392 + ## udocker (1.3.8) * build udockertools 1.2.9 and set it as default diff --git a/codemeta.json b/codemeta.json index ff1105a4..5b83cd6f 100644 --- a/codemeta.json +++ b/codemeta.json @@ -6,7 +6,7 @@ "@type": "SoftwareSourceCode", "identifier": "udocker", "name": "udocker", - "version": "1.3.8", + "version": "1.3.9", "description": "A basic user tool to execute simple docker containers in batch or interactive systems without root privileges", "license": "Apache Software License 2.0, OSI Approved :: Apache Software License", "author": [ diff --git a/docs/installation_manual.md b/docs/installation_manual.md index 4be9a7a9..225fce10 100644 --- a/docs/installation_manual.md +++ b/docs/installation_manual.md @@ -32,18 +32,18 @@ udocker requires: Download a release tarball from : ```bash -wget https://github.com/indigo-dc/udocker/releases/download/1.3.8/udocker-1.3.8.tar.gz -tar zxvf udocker-1.3.8.tar.gz -export PATH=`pwd`/udocker-1.3.8/udocker:$PATH +wget https://github.com/indigo-dc/udocker/releases/download/1.3.9/udocker-1.3.9.tar.gz +tar zxvf udocker-1.3.9.tar.gz +export PATH=`pwd`/udocker-1.3.9/udocker:$PATH ``` Alternatively use `curl` instead of `wget` as follows: ```bash -curl -L https://github.com/indigo-dc/udocker/releases/download/1.3.8/udocker-1.3.8.tar.gz \ - > udocker-1.3.8.tar.gz -tar zxvf udocker-1.3.8.tar.gz -export PATH=`pwd`/udocker-1.3.8/udocker:$PATH +curl -L https://github.com/indigo-dc/udocker/releases/download/1.3.9/udocker-1.3.9.tar.gz \ + > udocker-1.3.9.tar.gz +tar zxvf udocker-1.3.9.tar.gz +export PATH=`pwd`/udocker-1.3.9/udocker:$PATH ``` udocker executes containers using external tools and libraries that @@ -345,8 +345,8 @@ The udocker tool should be installed as shown in section 2.1: ```bash cd /sw -wget https://github.com/indigo-dc/udocker/releases/download/1.3.8/udocker-1.3.8.tar.gz -tar zxvf udocker-1.3.8.tar.gz +wget https://github.com/indigo-dc/udocker/releases/download/1.3.9/udocker-1.3.9.tar.gz +tar zxvf udocker-1.3.9.tar.gz ``` Directing users to the central udocker installation can be done using the diff --git a/udocker/__init__.py b/udocker/__init__.py index 22f0d443..e372d648 100644 --- a/udocker/__init__.py +++ b/udocker/__init__.py @@ -31,5 +31,5 @@ "Singularity http://singularity.lbl.gov" ] __license__ = "Licensed under the Apache License, Version 2.0" -__version__ = "1.3.8" +__version__ = "1.3.9" __date__ = "2023" diff --git a/udocker/cli.py b/udocker/cli.py index 65bbd485..53ef7fb4 100644 --- a/udocker/cli.py +++ b/udocker/cli.py @@ -532,6 +532,7 @@ def do_pull(self, cmdp): --httpproxy=socks5h://host:port :use http proxy --index=https://index.docker.io/v1 :docker index --registry=https://registry-1.docker.io :docker registry + --platform=os/arch :docker platform Examples: pull fedora:latest @@ -540,6 +541,7 @@ def do_pull(self, cmdp): index_url = cmdp.get("--index=") registry_url = cmdp.get("--registry=") http_proxy = cmdp.get("--httpproxy=") + platform = cmdp.get("--platform=") (imagerepo, tag) = self._check_imagespec(cmdp.get("P1")) if (not imagerepo) or cmdp.missing_options(): # syntax error return self.STATUS_ERROR @@ -547,7 +549,7 @@ def do_pull(self, cmdp): self._set_repository(registry_url, index_url, imagerepo, http_proxy) v2_auth_token = self.keystore.get(self.dockerioapi.registry_url) self.dockerioapi.set_v2_login_token(v2_auth_token) - if self.dockerioapi.get(imagerepo, tag): + if self.dockerioapi.get(imagerepo, tag, platform): return self.STATUS_OK Msg().err("Error: no files downloaded") @@ -690,6 +692,10 @@ def _get_run_options(self, cmdp, exec_engine=None): "nobanner": { "fl": ("--nobanner",), "act": 'R', "p2": "CMD_OPT", "p3": False + }, + "platform": { + "fl": ("--platform=",), "act": 'R', + "p2": "CMD_OPT", "p3": False } } for option, cmdp_args in list(cmd_options.items()): diff --git a/udocker/container/structure.py b/udocker/container/structure.py index 0fcdaa02..8b555e80 100644 --- a/udocker/container/structure.py +++ b/udocker/container/structure.py @@ -4,7 +4,6 @@ import os import subprocess -from udocker.genstr import is_genstr from udocker.config import Config from udocker.msg import Msg from udocker.helper.unique import Unique @@ -45,33 +44,39 @@ def get_container_attr(self): return (container_dir, container_json) - def get_container_meta(self, param, default, container_json): - """Get the container metadata from the container""" - confidx = "" - if "config" in container_json: - confidx = "config" - elif "container_config" in container_json: - confidx = "container_config" - if container_json[confidx] and param in container_json[confidx]: - if container_json[confidx][param] is None: - pass - elif (is_genstr(container_json[confidx][param]) and - (isinstance(default, (list, tuple)))): - return container_json[confidx][param].strip().split() - elif (is_genstr(default) and ( - isinstance(container_json[confidx][param], (list, tuple)))): - return " ".join(container_json[confidx][param]) - elif (is_genstr(default) and ( - isinstance(container_json[confidx][param], dict))): - return self._dict_to_str(container_json[confidx][param]) - elif (isinstance(default, list) and ( - isinstance(container_json[confidx][param], dict))): - return self._dict_to_list(container_json[confidx][param]) - else: - return container_json[confidx][param] + def get_container_meta(self, param, default, cntjson): + """Get the metadata configuration from the container""" + cidx = "" + if "config" in cntjson: + cidx = "config" + elif "container_config" in cntjson: + cidx = "container_config" + + meta_item = None + if cntjson[cidx] and param in cntjson[cidx]: + meta_item = cntjson[cidx][param] + elif param in cntjson: + meta_item = cntjson[param] + + if meta_item is None: + pass + elif (isinstance(meta_item, str) and + (isinstance(default, (list, tuple)))): + return meta_item.strip().split() + elif (isinstance(default, str) and + (isinstance(meta_item, (list, tuple)))): + return " ".join(meta_item) + elif (isinstance(default, str) and + (isinstance(meta_item, dict))): + return self._dict_to_str(meta_item) + elif (isinstance(default, list) and + (isinstance(meta_item, dict))): + return self._dict_to_list(meta_item) + else: + return meta_item + return default - # DEBUG def _dict_to_str(self, in_dict): """Convert dict to str""" out_str = "" diff --git a/udocker/docker.py b/udocker/docker.py index 08c617fb..355a556b 100644 --- a/udocker/docker.py +++ b/udocker/docker.py @@ -14,6 +14,7 @@ from udocker.utils.fileutil import FileUtil from udocker.utils.curl import GetURL from udocker.utils.chksum import ChkSUM +from udocker.helper.hostinfo import HostInfo class DockerIoAPI(object): @@ -96,7 +97,11 @@ def _get_url(self, *args, **kwargs): kwargs["RETRY"]) if "/v1/" in url: auth_header = self._get_v1_auth(www_authenticate) - auth_kwargs.update({"header": [auth_header]}) + # OCI and multiplatform, prevent removal of header attributes + try: + auth_kwargs["header"].append(auth_header) + except KeyError: + auth_kwargs.update({"header": [auth_header]}) (hdr, buf) = self._get_url(*args, **auth_kwargs) return (hdr, buf) @@ -356,18 +361,71 @@ def get_v2_image_tags(self, imagerepo, tags_only=False): except (IOError, OSError, AttributeError, ValueError, TypeError): return [] - def get_v2_image_manifest(self, imagerepo, tag): - """Get the image manifest which contains JSON metadata + def _get_v2_digest_from_image_index(self, image_index, platform): + """Get OCI or docker manifest from an image index""" + if isinstance(image_index, dict): + index_list = image_index + else: + try: + index_list = json.loads(image_index.decode()) + except (OSError, AttributeError, ValueError, TypeError): + return "" + (p_os, p_architecture, p_variant) = HostInfo().parse_platform(platform) + try: + for manifest in index_list["manifests"]: + manifest_p = manifest["platform"] + if (p_os and + (manifest_p["os"]).lower() != p_os): + continue + if (p_architecture and + (manifest_p["architecture"]).lower() != p_architecture): + continue + if (p_variant and + (manifest_p["variant"]).lower() != p_variant): + continue + return manifest["digest"] + except (KeyError, AttributeError, ValueError, TypeError): + pass + return "" + + def get_v2_image_manifest(self, imagerepo, tag, platform=""): + """API v2 Get the image manifest which contains JSON metadata that is common to all layers in this image tag """ - url = self.registry_url + "/v2/" + imagerepo + \ - "/manifests/" + tag + reqhdr = [ + 'Accept: application/vnd.docker.distribution.manifest.v2+json', + 'Accept: application/vnd.docker.distribution.manifest.v1+prettyjws', + 'Accept: application/json', + 'Accept: application/vnd.docker.distribution.manifest.list.v2+json', + 'Accept: application/vnd.oci.image.manifest.v1+json', + 'Accept: application/vnd.oci.image.index.v1+json', + ] + url = self.registry_url + "/v2/" + imagerepo + "/manifests/" + tag Msg().out("Debug: manifest url", url, l=Msg.DBG) - (hdr, buf) = self._get_url(url) + (hdr, buf) = self._get_url(url, header=reqhdr) + try: - return (hdr.data, json.loads(buf.getvalue().decode())) - except (IOError, OSError, AttributeError, ValueError, TypeError): - return (hdr.data, []) + content_type = hdr.data['content-type'] + if "docker.distribution.manifest.v1" in content_type: + return (hdr.data, json.loads(buf.getvalue().decode())) + if "docker.distribution.manifest.v2" in content_type: + return (hdr.data, json.loads(buf.getvalue().decode())) + if "oci.image.manifest.v1+json" in content_type: + return (hdr.data, json.loads(buf.getvalue().decode())) + if ("docker.distribution.manifest.list.v2" in content_type + or "oci.image.index.v1+json" in content_type): + image_index = json.loads(buf.getvalue().decode()) + digest = self._get_v2_digest_from_image_index(image_index, + platform) + if not digest: + Msg().err("no image found in manifest for platform (%s)" % + HostInfo().platform_to_str(platform)) + else: + return self.get_v2_image_manifest(imagerepo, + digest, platform) + except (OSError, KeyError, AttributeError, ValueError, TypeError): + pass + return (hdr.data, []) def get_v2_image_layer(self, imagerepo, layer_id): """Get one image layer data file (tarball)""" @@ -396,10 +454,11 @@ def get_v2_layers_all(self, imagerepo, fslayers): files.append(blob) return files - def get_v2(self, imagerepo, tag): + def get_v2(self, imagerepo, tag, platform=""): """Pull container with v2 API""" files = [] - (hdr_data, manifest) = self.get_v2_image_manifest(imagerepo, tag) + (hdr_data, manifest) = self.get_v2_image_manifest(imagerepo, tag, + platform) status = self.curl.get_status_code(hdr_data["X-ND-HTTPSTATUS"]) if status == 401: Msg().err("Error: manifest not found or not authorized") @@ -407,6 +466,9 @@ def get_v2(self, imagerepo, tag): if status != 200: Msg().err("Error: pulling manifest:") return [] + if not manifest: + Msg().err("no manifest for given image and platform") + return [] try: if not (self.localrepo.setup_tag(tag) and self.localrepo.set_version("v2")): @@ -518,7 +580,7 @@ def _parse_imagerepo(self, imagerepo): self.index_url = index_url return (imagerepo, remoterepo) - def get(self, imagerepo, tag): + def get(self, imagerepo, tag, platform=""): """Pull a docker image from a v2 registry or v1 index""" Msg().out("Debug: get imagerepo: %s tag: %s" % (imagerepo, tag), l=Msg.DBG) (imagerepo, remoterepo) = self._parse_imagerepo(imagerepo) @@ -528,7 +590,9 @@ def get(self, imagerepo, tag): self.localrepo.setup_imagerepo(imagerepo) new_repo = True if self.is_v2(): - files = self.get_v2(remoterepo, tag) # try v2 + if not platform: + platform = HostInfo().platform() + files = self.get_v2(remoterepo, tag, platform) # try v2 else: files = self.get_v1(remoterepo, tag) # try v1 if new_repo and not files: diff --git a/udocker/helper/hostinfo.py b/udocker/helper/hostinfo.py index 87a40a91..af7cb083 100644 --- a/udocker/helper/hostinfo.py +++ b/udocker/helper/hostinfo.py @@ -78,6 +78,57 @@ def oskernel_isgreater(self, version): return True + def parse_platform(self, platform_in): + """Convert a platform string or dict into (os, architecture, variant)""" + if isinstance(platform_in, dict): + p_os = "" + p_architecture = "" + p_variant = "" + for (key, val) in platform_in.items(): + if key == "os": + p_os = val.lower() + elif key == "architecture": + p_architecture = val.lower() + elif key == "variant": + p_variant = val.lower() + return (p_os, p_architecture, p_variant) + if isinstance(platform_in, str): + try: + (p_os, p_architecture, p_variant) = platform_in.lower().split("/") + return (p_os, p_architecture, p_variant) + except ValueError: + try: + (p_os, p_architecture) = platform_in.split("/") + return (p_os, p_architecture, "") + except ValueError: + return (platform_in.strip(), "", "") + return ("", "", "") + + def platform_to_str(self, platform_in): + """Parse platform and return a string with os/architecture/variant""" + parsed_platform = self.parse_platform(platform_in) + if parsed_platform[2]: + return "%s/%s/%s" % parsed_platform + if parsed_platform[1]: + return "%s/%s" % parsed_platform[0:2] + return parsed_platform[0] + + def platform(self, return_str=True): + """get docker platform os/architecture/variant""" + translate_architecture = {"i386":"386", "i486":"486", "i586":"586", "i686":"686"} + architecture = self.arch() + host_platform = self.osversion() + "/" + \ + translate_architecture.get(architecture, architecture) + if return_str: + return host_platform.lower() + return self.parse_platform(host_platform) + + def is_same_platform(self, platform_in): + """Compare some platform against the host platform""" + if self.parse_platform(platform_in) == self.platform(return_str=False): + return True + return False + def cmd_has_option(self, executable, search_option, arg=None): """Check if executable has a given cli option""" if not executable: diff --git a/udocker/tools.py b/udocker/tools.py index 707f6d35..5440b77d 100644 --- a/udocker/tools.py +++ b/udocker/tools.py @@ -276,7 +276,7 @@ def _install_logic(self, force=False): def install(self, force=False): """Get the udocker tools tarball and install the binaries""" if self.is_available() and not force: - Msg().out("Info: already installed, installation skipped", l=Msg.INF) + Msg().out("Debug: already installed, installation skipped", l=Msg.DBG) return True if not self._autoinstall and not force: diff --git a/utils/udocker_test-run.sh b/utils/udocker_test-run.sh index 5a19a1a5..19391feb 100755 --- a/utils/udocker_test-run.sh +++ b/utils/udocker_test-run.sh @@ -76,7 +76,10 @@ function result print_fail; echo " $STRING" FAILED_TESTS+=("$STRING") fi - echo "|______________________________________________________________________________|" + echo "\____________________________________________________________________________________________________________________________________/" + echo "" + echo " ____________________________________________________________________________________________________________________________________ " + echo "/ \ " } function result_inv @@ -88,7 +91,10 @@ function result_inv print_fail; echo " $STRING" FAILED_TESTS+=("$STRING") fi - echo "|______________________________________________________________________________|" + echo "\____________________________________________________________________________________________________________________________________/" + echo "" + echo " ____________________________________________________________________________________________________________________________________ " + echo "/ \ " } function udocker @@ -109,27 +115,27 @@ then exit 1 fi -echo "|______________________________________________________________________________|" +echo "\____________________________________________________________________________________________________________________________________/" udocker rm c7 -udocker rm ub18 +udocker rm ub22 udocker rm jv ## Use openjdk:8-jdk-alpine for regression of issue #363 -echo "|______________________________________________________________________________|" +echo "\____________________________________________________________________________________________________________________________________/" udocker rmi centos:7 -udocker rmi ubuntu:18.04 +udocker rmi ubuntu:22.04 udocker rmi openjdk:8-jdk-alpine -echo "|______________________________________________________________________________|" +echo "\____________________________________________________________________________________________________________________________________/" udocker pull centos:7; return=$? -udocker pull ubuntu:18.04; return=$? +udocker pull ubuntu:22.04; return=$? udocker pull openjdk:8-jdk-alpine; return=$? -echo "|______________________________________________________________________________|" +echo "\____________________________________________________________________________________________________________________________________/" udocker images; return=$? udocker create --name=c7 centos:7; return=$? -udocker create --name=ub18 ubuntu:18.04; return=$? +udocker create --name=ub22 ubuntu:22.04; return=$? udocker create --name=jv openjdk:8-jdk-alpine; return=$? udocker ps; return=$? @@ -154,12 +160,12 @@ STRING="T004: udocker run c7 ls --version == execmode = P1" udocker run c7 ls --version; return=$? result -STRING="T005: udocker setup ub18 == execmode = P1" -udocker setup ub18; return=$? +STRING="T005: udocker setup ub22 == execmode = P1" +udocker setup ub22; return=$? result -STRING="T006: udocker run ub18 ls --version == execmode = P1" -udocker run ub18 ls --version; return=$? +STRING="T006: udocker run ub22 ls --version == execmode = P1" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = P2" @@ -179,12 +185,12 @@ STRING="T010: udocker run c7 ls --version == execmode = P2" udocker run c7 ls --version; return=$? result -STRING="T011: udocker setup --execmode=P2 ub18 == execmode = P2" -udocker setup --execmode=P2 ub18; return=$? +STRING="T011: udocker setup --execmode=P2 ub22 == execmode = P2" +udocker setup --execmode=P2 ub22; return=$? result -STRING="T012: udocker run ub18 ls --version == execmode = P2" -udocker run ub18 ls --version; return=$? +STRING="T012: udocker run ub22 ls --version == execmode = P2" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = F1" @@ -196,12 +202,12 @@ STRING="T014: udocker run c7 ls --version == execmode = F1" udocker run c7 ls --version; return=$? result -STRING="T015: udocker setup --execmode=F1 ub18 == execmode = F1" -udocker setup --execmode=F1 ub18; return=$? +STRING="T015: udocker setup --execmode=F1 ub22 == execmode = F1" +udocker setup --execmode=F1 ub22; return=$? result -STRING="T016: udocker run ub18 ls --version == execmode = F1" -udocker run ub18 ls --version; return=$? +STRING="T016: udocker run ub22 ls --version == execmode = F1" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = F2" @@ -213,12 +219,12 @@ STRING="T018: udocker run c7 ls --version == execmode = F2" udocker run c7 ls --version; return=$? result -STRING="T019: udocker setup --execmode=F2 ub18 == execmode = F2" -udocker setup --execmode=F2 ub18; return=$? +STRING="T019: udocker setup --execmode=F2 ub22 == execmode = F2" +udocker setup --execmode=F2 ub22; return=$? result -STRING="T020: udocker run ub18 ls --version == execmode = F2" -udocker run ub18 ls --version; return=$? +STRING="T020: udocker run ub22 ls --version == execmode = F2" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = F3" @@ -238,12 +244,12 @@ STRING="T024: udocker run c7 ls --version == execmode = F3" udocker run c7 ls --version; return=$? result -STRING="T025: udocker setup --execmode=F3 ub18 == execmode = F3" -udocker setup --execmode=F3 ub18; return=$? +STRING="T025: udocker setup --execmode=F3 ub22 == execmode = F3" +udocker setup --execmode=F3 ub22; return=$? result -STRING="T026: udocker run ub18 ls --version == execmode = F3" -udocker run ub18 ls --version; return=$? +STRING="T026: udocker run ub22 ls --version == execmode = F3" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = F4" @@ -263,12 +269,12 @@ STRING="T030: udocker run c7 ls --version == execmode = F4" udocker run c7 ls --version; return=$? result -STRING="T031: udocker setup --execmode=F4 ub18 == execmode = F4" -udocker setup --execmode=F4 ub18; return=$? +STRING="T031: udocker setup --execmode=F4 ub22 == execmode = F4" +udocker setup --execmode=F4 ub22; return=$? result -STRING="T032: udocker run ub18 ls --version == execmode = F4" -udocker run ub18 ls --version; return=$? +STRING="T032: udocker run ub22 ls --version == execmode = F4" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = R1" @@ -288,12 +294,12 @@ STRING="T036: udocker run c7 ls --version == execmode = R1" udocker run c7 ls --version; return=$? result -STRING="T037: udocker setup --execmode=R1 ub18 == execmode = R1" -udocker setup --execmode=R1 ub18; return=$? +STRING="T037: udocker setup --execmode=R1 ub22 == execmode = R1" +udocker setup --execmode=R1 ub22; return=$? result -STRING="T038: udocker run ub18 ls --version == execmode = R1" -udocker run ub18 ls --version; return=$? +STRING="T038: udocker run ub22 ls --version == execmode = R1" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = R2" @@ -313,12 +319,12 @@ STRING="T042: udocker run c7 ls --version == execmode = R2" udocker run c7 ls --version; return=$? result -STRING="T043: udocker setup --execmode=R2 ub18 == execmode = R2" -udocker setup --execmode=R2 ub18; return=$? +STRING="T043: udocker setup --execmode=R2 ub22 == execmode = R2" +udocker setup --execmode=R2 ub22; return=$? result -STRING="T044: udocker run ub18 ls --version == execmode = R2" -udocker run ub18 ls --version; return=$? +STRING="T044: udocker run ub22 ls --version == execmode = R2" +udocker run ub22 ls --version; return=$? result echo "===================================== execmode = R3" @@ -338,12 +344,12 @@ STRING="T048: udocker run c7 ls --version == execmode = R3" udocker run c7 ls --version; return=$? result -STRING="T049: udocker setup --execmode=R3 ub18 == execmode = R3" -udocker setup --execmode=R3 ub18; return=$? +STRING="T049: udocker setup --execmode=R3 ub22 == execmode = R3" +udocker setup --execmode=R3 ub22; return=$? result -STRING="T050: udocker run ub18 ls --version == execmode = R3" -udocker run ub18 ls --version; return=$? +STRING="T050: udocker run ub22 ls --version == execmode = R3" +udocker run ub22 ls --version; return=$? result # Report failed tests diff --git a/utils/udocker_test.sh b/utils/udocker_test.sh index 0c29c488..cf9f59b5 100755 --- a/utils/udocker_test.sh +++ b/utils/udocker_test.sh @@ -38,7 +38,7 @@ TAR_IMAGE="centos7.tar" TAR_CONT="centos7-cont.tar" TAR_IMAGE_URL="https://download.ncg.ingrid.pt/webdav/udocker_test/${TAR_IMAGE}" TAR_CONT_URL="https://download.ncg.ingrid.pt/webdav/udocker_test/${TAR_CONT}" -DOCKER_IMG="ubuntu:18.04" +DOCKER_IMG="ubuntu:22.04" CONT="ubuntu" export UDOCKER_DIR=${DEFAULT_UDIR} @@ -94,7 +94,10 @@ function result print_fail; echo " $STRING" FAILED_TESTS+=("$STRING") fi - echo "|______________________________________________________________________________|" + echo "\____________________________________________________________________________________________________________________________________/" + echo "" + echo " ____________________________________________________________________________________________________________________________________ " + echo "/ \ " } function result_inv @@ -106,7 +109,10 @@ function result_inv print_fail; echo " $STRING" FAILED_TESTS+=("$STRING") fi - echo "|______________________________________________________________________________|" + echo "\____________________________________________________________________________________________________________________________________/" + echo "" + echo " ____________________________________________________________________________________________________________________________________ " + echo "/ \ " } function udocker @@ -188,6 +194,7 @@ result STRING="T017: udocker verify ${DOCKER_IMG}" udocker verify ${DOCKER_IMG}; return=$? result +## TODO: Add test to check layers after pull STRING="T018: udocker images" udocker images; return=$? @@ -197,9 +204,8 @@ STRING="T019: udocker inspect (image)" udocker inspect ${DOCKER_IMG}; return=$? result -STRING="T020: udocker create ${DOCKER_IMG}" -CONT_ID=`udocker create ${DOCKER_IMG}`; return=$? -echo "ContainerID = ${CONT_ID}" +STRING="T020: udocker -q create ${DOCKER_IMG}" +CONT_ID=`udocker -q create ${DOCKER_IMG}`; return=$? result STRING="T021: udocker create --name=${CONT} ${DOCKER_IMG}" @@ -329,11 +335,23 @@ STRING="T048: udocker run py3slim python3 --version /dev/null udocker rm mycont udocker rm clone_cont udocker rm myclone +udocker rm py3slim +udocker rm redis udocker rmi mycentos1 udocker rmi centos:7 udocker rmi docker.io/python:3-slim +udocker rmi public.ecr.aws/docker/library/redis echo "|______________________________________________________________________________|" # Report failed tests