# HG changeset patch # User Georges Racinet <georges.racinet@octobus.net> # Date 1622107167 -7200 # Thu May 27 11:19:27 2021 +0200 # Node ID 11c9bbd5cb5b63fec80d2d604793c86573d107da # Parent 240bb4b143aabc85c384c8cfaeddb9d36a8f9f76 registry-pull-heptapod-push-docker: facility to check consistency Nowadays, the Docker images are produced by a pipeline with a Docker tag based on the Mercurial changeset ID in omnibus-heptapod, on top of the `testing` tag. The subsequent heptapod-tests pipeline uses the image with the precise changeset ID. The new `--verify-hg-tag` resolves the expected changeset ID from tag and perform the comparison of images, to make sure that the `testing` image is the one the functional tests ran against. diff --git a/registry-pull-heptapod-push-docker b/registry-pull-heptapod-push-docker --- a/registry-pull-heptapod-push-docker +++ b/registry-pull-heptapod-push-docker @@ -1,13 +1,21 @@ #!/usr/bin/env python3 import argparse import logging +import os import subprocess +import sys logger = logging.getLogger(os.path.basename(__file__)) DEFAULT_IMAGE_TAG = 'testing' HEPTAPOD_REGISTRY_IMAGE_REPOSITORY="registry.heptapod.net:443/heptapod/omnibus-heptapod" TARGET_IMAGE_REPOSITORY="octobus/heptapod" +HEPTAPOD_DOCKER_DIR = os.path.dirname(__file__) +OMNIBUS_HEPTAPOD_DIR = os.path.join( + HEPTAPOD_DOCKER_DIR, + os.path.pardir, + 'omnibus-heptapod' +) parser = argparse.ArgumentParser( description="Pull Heptapod image from registry.h.n and tag it " @@ -16,6 +24,10 @@ parser.add_argument("--push", help="Push to Docker Hub", action="store_true") parser.add_argument("--tag", help="TAG of the image to pull *and* the image to push", default=DEFAULT_IMAGE_TAG) +parser.add_argument("--verify-hg-tag", help="Verify that the image pulled is the" + "same as the one with Docker tag based on hash from Omnibus hg tag. " + "This assumes you have a clone of omnibus-heptapod " + "at %r" % OMNIBUS_HEPTAPOD_DIR) parser.add_argument("-l", "--log-level", default="info") cl_args = parser.parse_args() logging.basicConfig(level=getattr(logging, cl_args.log_level.upper())) @@ -29,13 +41,55 @@ def image_tag(image_repo, tag): return ':'.join((image_repo, tag)) + +def omnibus_short_hg_sha(rev): + subprocess.check_call(("hg", "pull", "-R", OMNIBUS_HEPTAPOD_DIR)) + return subprocess.check_output(("hg", "log", "-T", "{node|short}", + "-R", OMNIBUS_HEPTAPOD_DIR, + "-r", rev)).decode().strip() + +def docker_image_id(image_tag): + """Display image ID. + + The image ID is not the same as the image digest (both are sha256 sums), + but is the one displayed in CI jobs, making for easy comparisons. + """ + image_id = subprocess.check_output(("docker", "inspect", + "--format='{{.Id}}'", + image_tag)).decode().strip() + logger.info("Docker image ID for %r is %r", image_tag, image_id) + return image_id + + heptapod_registry_image = image_tag(HEPTAPOD_REGISTRY_IMAGE_REPOSITORY, cl_args.tag) target_image = image_tag(TARGET_IMAGE_REPOSITORY, cl_args.tag) docker_pull(heptapod_registry_image) +hg_tag = cl_args.verify_hg_tag +if hg_tag is not None: + hg_sha = omnibus_short_hg_sha(hg_tag) + sha_image = image_tag(HEPTAPOD_REGISTRY_IMAGE_REPOSITORY, hg_sha) + docker_pull(sha_image) + if docker_image_id(heptapod_registry_image) == docker_image_id(sha_image): + logger.info("Docker images for %r and %r (%r) " + "are identical, all is well", + cl_args.tag, hg_sha, hg_tag) + else: + logger.error("Docker images for %r and %r (%r) " + "are different. Aborting.", + cl_args.tag, hg_sha, hg_tag) + sys.exit(1) + logger.info("Tagging the pull image as %r", target_image) subprocess.check_call(("docker", "tag", heptapod_registry_image, target_image)) if cl_args.push: logger.info("Pushing to %r", target_image) subprocess.check_call(("docker", "push", target_image)) + +if hg_tag is None: + logger.warning("No image consistency was requested. " + "If the image is supposed to come from an Omnibus Mercurial tag, " + "and you have a clone of Heptapod Omnibus at %r" + "you can re-run with `--verify-hg-tag`, it's cheap.", + OMNIBUS_HEPTAPOD_DIR)