blob: 1c0bde5f0b7a7fb366f03ee3a89e1f3f8d74d21b [file] [log] [blame]
Mohammed Naser8613c862023-04-24 17:26:51 -04001#!/usr/bin/env python3
2
3import argparse
4import functools
5
6from docker_image import reference
7from oslo_config import cfg
8from oslo_log import log as logging
9from ruyaml import YAML
10import requests
11
12LOG = logging.getLogger(__name__)
13CONF = cfg.CONF
14
15
Mohammed Naser21066a12024-01-02 11:14:53 -050016def get_digest(image_ref, token=None):
17 headers = {}
18 if token:
19 headers["Authorization"] = f"Bearer {token}"
20
21 try:
22 headers["Accept"] = "application/vnd.docker.distribution.manifest.v2+json"
23
24 r = requests.get(
25 f"https://{image_ref.domain()}/v2/{image_ref.path()}/manifests/{image_ref['tag']}",
26 timeout=5,
27 headers=headers,
28 )
29 r.raise_for_status()
30 return r.headers["Docker-Content-Digest"]
31 except requests.exceptions.HTTPError:
32 headers["Accept"] = "application/vnd.oci.image.index.v1+json"
33
34 r = requests.get(
35 f"https://{image_ref.domain()}/v2/{image_ref.path()}/manifests/{image_ref['tag']}",
36 timeout=5,
37 headers=headers,
38 )
39 r.raise_for_status()
40 return r.headers["Docker-Content-Digest"]
41
42
Mohammed Naser8613c862023-04-24 17:26:51 -040043@functools.cache
44def get_pinned_image(image_src):
45 image_ref = reference.Reference.parse(image_src)
46
Mohammed Naser21066a12024-01-02 11:14:53 -050047 if image_ref.domain() in ("registry.k8s.io", "us-docker.pkg.dev"):
48 digest = get_digest(image_ref)
49
Mohammed Naser8613c862023-04-24 17:26:51 -040050 if image_ref.domain() == "quay.io":
51 r = requests.get(
52 f"https://quay.io/api/v1/repository/{image_ref.path()}/tag/",
Mohammed Naser21066a12024-01-02 11:14:53 -050053 timeout=5,
Mohammed Naser8613c862023-04-24 17:26:51 -040054 params={"specificTag": image_ref["tag"]},
55 )
56 r.raise_for_status()
57 digest = r.json()["tags"][0]["manifest_digest"]
58
Mohammed Naser49e66372023-07-10 14:57:00 -040059 if image_ref.domain() == "docker.io":
60 # Get token for docker.io
61 r = requests.get(
62 "https://auth.docker.io/token",
Mohammed Naser21066a12024-01-02 11:14:53 -050063 timeout=5,
Mohammed Naser16baaab2023-07-10 15:07:11 -040064 params={
65 "service": "registry.docker.io",
66 "scope": f"repository:{image_ref.path()}:pull",
67 },
Mohammed Naser49e66372023-07-10 14:57:00 -040068 )
69 r.raise_for_status()
70 token = r.json()["token"]
71
72 r = requests.get(
73 f"https://registry-1.docker.io/v2/{image_ref.path()}/manifests/{image_ref['tag']}",
Mohammed Naser21066a12024-01-02 11:14:53 -050074 timeout=5,
Mohammed Naser16baaab2023-07-10 15:07:11 -040075 headers={
76 "Accept": "application/vnd.docker.distribution.manifest.v2+json",
77 "Authorization": f"Bearer {token}",
78 },
Mohammed Naser49e66372023-07-10 14:57:00 -040079 )
80 r.raise_for_status()
81 digest = r.headers["Docker-Content-Digest"]
82
Mohammed Naser21066a12024-01-02 11:14:53 -050083 if image_ref.domain() == "ghcr.io":
84 # Get token for docker.io
85 r = requests.get(
86 "https://ghcr.io/token",
87 timeout=5,
88 params={
89 "service": "ghcr.io",
90 "scope": f"repository:{image_ref.path()}:pull",
91 },
92 )
93 r.raise_for_status()
94 token = r.json()["token"]
95
96 digest = get_digest(image_ref, token=token)
97
98 return f"{image_ref.domain()}/{image_ref.path()}:{image_ref['tag']}@{digest}"
Mohammed Naser8613c862023-04-24 17:26:51 -040099
100
101def main():
102 logging.register_options(CONF)
103 logging.setup(CONF, "atmosphere-bump-images")
104
105 parser = argparse.ArgumentParser("bump-images")
106 parser.add_argument(
107 "src", help="Path for default values file", type=argparse.FileType("r")
108 )
109 parser.add_argument("dst", help="Path for output file", type=argparse.FileType("w"))
110
111 args = parser.parse_args()
112
113 yaml = YAML(typ="rt")
114 data = yaml.load(args.src)
115
Mohammed Naser21066a12024-01-02 11:14:53 -0500116 for image in data["_atmosphere_images"]:
117 image_src = data["_atmosphere_images"][image]
Mohammed Naser8613c862023-04-24 17:26:51 -0400118 pinned_image = get_pinned_image(image_src)
119
120 LOG.info("Pinning image %s from %s to %s", image, image_src, pinned_image)
ricolinb8ab0172023-06-01 15:41:02 +0800121 data["_atmosphere_images"][image] = pinned_image
Mohammed Naser8613c862023-04-24 17:26:51 -0400122
123 yaml.dump(data, args.dst)
124
125
126if __name__ == "__main__":
127 main()