pyinfra/scripts/checkversions

84 lines
2.1 KiB
Python
Executable file

#!/usr/bin/env python3
import contextlib
import json
from typing import Iterator
from typing import Literal
from typing import Protocol
from urllib import request
from urllib.parse import urlencode
DOCKER_URLS = {
"auth": "https://auth.docker.io",
"registry": "https://registry-1.docker.io",
}
HttpMethods = Literal["GET", "POST", "PUT", "DELETE"]
def http_request(
method: HttpMethods, url: str, body: dict | None = None, *,
headers: dict | None = None,
) -> dict:
if not headers:
headers = {}
if not body:
body = {}
req = request.Request(
method=method,
url=url,
data=json.dumps(body).encode("utf-8"),
headers=headers,
)
res = request.urlopen(req)
return json.load(res)
class HttpReqFunc(Protocol):
def __call__(
self, method: HttpMethods, url: str, *, body: dict | None = None,
headers: dict | None = None,
) -> dict: ...
def generate_token_params(image: str) -> str:
return urlencode(
dict(
service="registry.docker.io",
scope=f"repository:{image}:pull",
),
)
@contextlib.contextmanager
def authorized_requests(image_name: str) -> Iterator[HttpReqFunc]:
token_query_params = generate_token_params(image_name)
token_uri = f"{DOCKER_URLS['auth']}/token?{token_query_params}"
auth_token = http_request(
"GET",
token_uri,
).get("token")
def wrapped_http_request(*args, **kwargs) -> dict:
headers = kwargs.pop("headers", dict())
headers["Authorization"] = f"Bearer {auth_token}"
return http_request(*args, **kwargs, headers=headers)
yield wrapped_http_request
def main() -> int:
image_names = ["library/traefik"]
for image_name in image_names:
with authorized_requests(image_name) as make_request:
info = make_request(
"GET",
f"{DOCKER_URLS['registry']}/v2/{image_name}/tags/list?n=50&last=v3.1.0",
)
print(info)
return 0
if __name__ == "__main__":
raise SystemExit(main())