# 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)