diff options
Diffstat (limited to 'tests/docker/docker.py')
| -rwxr-xr-x | tests/docker/docker.py | 112 |
1 files changed, 106 insertions, 6 deletions
diff --git a/tests/docker/docker.py b/tests/docker/docker.py index 306e14cf69..b279836154 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -26,9 +26,13 @@ import tempfile import re import signal from tarfile import TarFile, TarInfo -from StringIO import StringIO +try: + from StringIO import StringIO +except ImportError: + from io import StringIO from shutil import copy, rmtree from pwd import getpwuid +from datetime import datetime,timedelta FILTERED_ENV_NAMES = ['ftp_proxy', 'http_proxy', 'https_proxy'] @@ -49,7 +53,9 @@ def _guess_docker_command(): commands = [["docker"], ["sudo", "-n", "docker"]] for cmd in commands: try: - if subprocess.call(cmd + ["images"], + # docker version will return the client details in stdout + # but still report a status of 1 if it can't contact the daemon + if subprocess.call(cmd + ["version"], stdout=DEVNULL, stderr=DEVNULL) == 0: return cmd except OSError: @@ -179,8 +185,17 @@ class Docker(object): stderr=subprocess.STDOUT, **kwargs) + def inspect_tag(self, tag): + try: + return self._output(["inspect", tag]) + except subprocess.CalledProcessError: + return None + + def get_image_creation_time(self, info): + return json.loads(info)[0]["Created"] + def get_image_dockerfile_checksum(self, tag): - resp = self._output(["inspect", tag]) + resp = self.inspect_tag(tag) labels = json.loads(resp)[0]["Config"].get("Labels", {}) return labels.get("com.qemu.dockerfile-checksum", "") @@ -201,8 +216,10 @@ class Docker(object): tmp_df.write("\n") tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" % - _text_checksum("\n".join([dockerfile] + - extra_files_cksum))) + _text_checksum(_dockerfile_preprocess(dockerfile))) + for f, c in extra_files_cksum: + tmp_df.write("LABEL com.qemu.%s-checksum=%s" % (f, c)) + tmp_df.flush() self._do_check(["build", "-t", tag, "-f", tmp_df.name] + argv + \ @@ -317,7 +334,7 @@ class BuildCommand(SubCommand): _copy_binary_with_libs(args.include_executable, docker_dir) for filename in args.extra_files or []: _copy_with_mkdir(filename, docker_dir) - cksum += [_file_checksum(filename)] + cksum += [(filename, _file_checksum(filename))] argv += ["--build-arg=" + k.lower() + "=" + v for k, v in os.environ.iteritems() @@ -409,6 +426,89 @@ class ProbeCommand(SubCommand): return +class CcCommand(SubCommand): + """Compile sources with cc in images""" + name = "cc" + + def args(self, parser): + parser.add_argument("--image", "-i", required=True, + help="The docker image in which to run cc") + parser.add_argument("--cc", default="cc", + help="The compiler executable to call") + parser.add_argument("--user", + help="The user-id to run under") + parser.add_argument("--source-path", "-s", nargs="*", dest="paths", + help="""Extra paths to (ro) mount into container for + reading sources""") + + def run(self, args, argv): + if argv and argv[0] == "--": + argv = argv[1:] + cwd = os.getcwd() + cmd = ["--rm", "-w", cwd, + "-v", "%s:%s:rw" % (cwd, cwd)] + if args.paths: + for p in args.paths: + cmd += ["-v", "%s:%s:ro,z" % (p, p)] + if args.user: + cmd += ["-u", args.user] + cmd += [args.image, args.cc] + cmd += argv + return Docker().command("run", cmd, args.quiet) + + +class CheckCommand(SubCommand): + """Check if we need to re-build a docker image out of a dockerfile. + Arguments: <tag> <dockerfile>""" + name = "check" + + def args(self, parser): + parser.add_argument("tag", + help="Image Tag") + parser.add_argument("dockerfile", default=None, + help="Dockerfile name", nargs='?') + parser.add_argument("--checktype", choices=["checksum", "age"], + default="checksum", help="check type") + parser.add_argument("--olderthan", default=60, type=int, + help="number of minutes") + + def run(self, args, argv): + tag = args.tag + + dkr = Docker() + info = dkr.inspect_tag(tag) + if info is None: + print("Image does not exist") + return 1 + + if args.checktype == "checksum": + if not args.dockerfile: + print("Need a dockerfile for tag:%s" % (tag)) + return 1 + + dockerfile = open(args.dockerfile, "rb").read() + + if dkr.image_matches_dockerfile(tag, dockerfile): + if not args.quiet: + print("Image is up to date") + return 0 + else: + print("Image needs updating") + return 1 + elif args.checktype == "age": + timestr = dkr.get_image_creation_time(info).split(".")[0] + created = datetime.strptime(timestr, "%Y-%m-%dT%H:%M:%S") + past = datetime.now() - timedelta(minutes=args.olderthan) + if created < past: + print ("Image created @ %s more than %d minutes old" % + (timestr, args.olderthan)) + return 1 + else: + if not args.quiet: + print ("Image less than %d minutes old" % (args.olderthan)) + return 0 + + def main(): parser = argparse.ArgumentParser(description="A Docker helper", usage="%s <subcommand> ..." % os.path.basename(sys.argv[0])) |