| 
          #!/usr/bin/env python | 
        
        
           | 
          # -*- coding: utf-8 -*- | 
        
        
           | 
          import argparse | 
        
        
           | 
          import os | 
        
        
           | 
          import re | 
        
        
           | 
          
 | 
        
        
           | 
          import requests | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          def parse_args(): | 
        
        
           | 
              parser = argparse.ArgumentParser( | 
        
        
           | 
                  description="Display a summary of a docker image's key tags and how they relate." | 
        
        
           | 
              ) | 
        
        
           | 
              parser.add_argument( | 
        
        
           | 
                  "image_name", type=str, help="The name/repo of the image." | 
        
        
           | 
              ) | 
        
        
           | 
              return parser.parse_args() | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          def get_docker_api_response(docker_api_path, headers=None): | 
        
        
           | 
              api_username = os.getenv("API_USERNAME") | 
        
        
           | 
              api_key = os.getenv("API_KEY") | 
        
        
           | 
              auth = requests.auth.HTTPBasicAuth(api_username, api_key) | 
        
        
           | 
              return requests.get( | 
        
        
           | 
                  f"https://dockerhub/api/docker/{docker_api_path}", | 
        
        
           | 
                  auth=auth, | 
        
        
           | 
                  headers=headers, | 
        
        
           | 
              ) | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          def get_image_tags(image_name): | 
        
        
           | 
              return get_docker_api_response(f"{image_name}/v2/{image_name}/tags/list").json()[ | 
        
        
           | 
                  "tags" | 
        
        
           | 
              ] | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          def get_image_tag_digest(image_name, image_tag): | 
        
        
           | 
              docker_content_digest = get_docker_api_response( | 
        
        
           | 
                  f"{image_name}/v2/{image_name}/manifests/{image_tag}", | 
        
        
           | 
                  headers={"Accept": "application/vnd.docker.distribution.manifest.v2+json"}, | 
        
        
           | 
              ).headers["Docker-Content-Digest"] | 
        
        
           | 
              print(f"Digest for {image_name}:{image_tag} is {docker_content_digest}.") | 
        
        
           | 
              return docker_content_digest | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          def get_image_tag_summary(image_name, image_tags, experimental_tag_digest, latest_tag_digest): | 
        
        
           | 
              semantic_version_tags = [tag for tag in image_tags if re.match(r"^\d+.\d+.\d+$", tag)] | 
        
        
           | 
              semantic_version_tags.sort(key=lambda x: [int(y) for y in x.split(".")]) | 
        
        
           | 
              image_tag_summary = { | 
        
        
           | 
                  "most_recent_sementic_version": semantic_version_tags[-1], | 
        
        
           | 
                  "experimental_version": None, | 
        
        
           | 
                  "latest_version": None, | 
        
        
           | 
              } | 
        
        
           | 
              experimental_tag_semantic_version = None | 
        
        
           | 
              latest_tag_semantic_version = None | 
        
        
           | 
              for semantic_version_tag in semantic_version_tags[::-1]: | 
        
        
           | 
                  semantic_version_tag_digest = get_image_tag_digest(image_name, semantic_version_tag) | 
        
        
           | 
                  if semantic_version_tag_digest == experimental_tag_digest: | 
        
        
           | 
                      image_tag_summary["experimental_version"] = semantic_version_tag | 
        
        
           | 
                  if semantic_version_tag_digest == latest_tag_digest: | 
        
        
           | 
                      image_tag_summary["latest_version"] = semantic_version_tag | 
        
        
           | 
                  if image_tag_summary["experimental_version"] and image_tag_summary["latest_version"]: | 
        
        
           | 
                      break | 
        
        
           | 
              return image_tag_summary | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          def main(): | 
        
        
           | 
              args = parse_args() | 
        
        
           | 
              image_tags = get_image_tags(args.image_name) | 
        
        
           | 
              experimental_tag_digest = get_image_tag_digest(args.image_name, "experimental") | 
        
        
           | 
              latest_tag_digest = get_image_tag_digest(args.image_name, "latest") | 
        
        
           | 
              print( | 
        
        
           | 
                  get_image_tag_summary( | 
        
        
           | 
                      args.image_name, image_tags, experimental_tag_digest, latest_tag_digest | 
        
        
           | 
                  ) | 
        
        
           | 
              ) | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          if __name__ == "__main__": | 
        
        
           | 
              main() |