oci: use pickleable errors (#42160)

This commit is contained in:
Harmen Stoppels 2024-01-19 09:37:33 +01:00 committed by Massimiliano Culpo
parent dd58e922e7
commit b107de072b
3 changed files with 33 additions and 39 deletions

View file

@ -716,8 +716,9 @@ def _config_from_tag(image_ref: ImageReference, tag: str) -> Optional[dict]:
def _update_index_oci(image_ref: ImageReference, tmpdir: str, pool: MaybePool) -> None: def _update_index_oci(image_ref: ImageReference, tmpdir: str, pool: MaybePool) -> None:
response = spack.oci.opener.urlopen(urllib.request.Request(url=image_ref.tags_url())) request = urllib.request.Request(url=image_ref.tags_url())
spack.oci.opener.ensure_status(response, 200) response = spack.oci.opener.urlopen(request)
spack.oci.opener.ensure_status(request, response, 200)
tags = json.load(response)["tags"] tags = json.load(response)["tags"]
# Fetch all image config files in parallel # Fetch all image config files in parallel

View file

@ -134,7 +134,7 @@ def upload_blob(
return True return True
# Otherwise, do another PUT request. # Otherwise, do another PUT request.
spack.oci.opener.ensure_status(response, 202) spack.oci.opener.ensure_status(request, response, 202)
assert "Location" in response.headers assert "Location" in response.headers
# Can be absolute or relative, joining handles both # Can be absolute or relative, joining handles both
@ -143,19 +143,16 @@ def upload_blob(
) )
f.seek(0) f.seek(0)
response = _urlopen( request = Request(
Request( url=upload_url,
url=upload_url, method="PUT",
method="PUT", data=f,
data=f, headers={"Content-Type": "application/octet-stream", "Content-Length": str(file_size)},
headers={
"Content-Type": "application/octet-stream",
"Content-Length": str(file_size),
},
)
) )
spack.oci.opener.ensure_status(response, 201) response = _urlopen(request)
spack.oci.opener.ensure_status(request, response, 201)
# print elapsed time and # MB/s # print elapsed time and # MB/s
_log_upload_progress(digest, file_size, time.time() - start) _log_upload_progress(digest, file_size, time.time() - start)
@ -189,16 +186,16 @@ def upload_manifest(
if not tag: if not tag:
ref = ref.with_digest(digest) ref = ref.with_digest(digest)
response = _urlopen( request = Request(
Request( url=ref.manifest_url(),
url=ref.manifest_url(), method="PUT",
method="PUT", data=data,
data=data, headers={"Content-Type": oci_manifest["mediaType"]},
headers={"Content-Type": oci_manifest["mediaType"]},
)
) )
spack.oci.opener.ensure_status(response, 201) response = _urlopen(request)
spack.oci.opener.ensure_status(request, response, 201)
return digest, size return digest, size

View file

@ -310,19 +310,15 @@ def http_error_401(self, req: Request, fp, code, msg, headers):
# Login failed, avoid infinite recursion where we go back and # Login failed, avoid infinite recursion where we go back and
# forth between auth server and registry # forth between auth server and registry
if hasattr(req, "login_attempted"): if hasattr(req, "login_attempted"):
raise urllib.error.HTTPError( raise spack.util.web.DetailedHTTPError(
req.full_url, code, f"Failed to login to {req.full_url}: {msg}", headers, fp req, code, f"Failed to login: {msg}", headers, fp
) )
# On 401 Unauthorized, parse the WWW-Authenticate header # On 401 Unauthorized, parse the WWW-Authenticate header
# to determine what authentication is required # to determine what authentication is required
if "WWW-Authenticate" not in headers: if "WWW-Authenticate" not in headers:
raise urllib.error.HTTPError( raise spack.util.web.DetailedHTTPError(
req.full_url, req, code, "Cannot login to registry, missing WWW-Authenticate header", headers, fp
code,
"Cannot login to registry, missing WWW-Authenticate header",
headers,
fp,
) )
header_value = headers["WWW-Authenticate"] header_value = headers["WWW-Authenticate"]
@ -330,8 +326,8 @@ def http_error_401(self, req: Request, fp, code, msg, headers):
try: try:
challenge = get_bearer_challenge(parse_www_authenticate(header_value)) challenge = get_bearer_challenge(parse_www_authenticate(header_value))
except ValueError as e: except ValueError as e:
raise urllib.error.HTTPError( raise spack.util.web.DetailedHTTPError(
req.full_url, req,
code, code,
f"Cannot login to registry, malformed WWW-Authenticate header: {header_value}", f"Cannot login to registry, malformed WWW-Authenticate header: {header_value}",
headers, headers,
@ -340,8 +336,8 @@ def http_error_401(self, req: Request, fp, code, msg, headers):
# If there is no bearer challenge, we can't handle it # If there is no bearer challenge, we can't handle it
if not challenge: if not challenge:
raise urllib.error.HTTPError( raise spack.util.web.DetailedHTTPError(
req.full_url, req,
code, code,
f"Cannot login to registry, unsupported authentication scheme: {header_value}", f"Cannot login to registry, unsupported authentication scheme: {header_value}",
headers, headers,
@ -356,8 +352,8 @@ def http_error_401(self, req: Request, fp, code, msg, headers):
timeout=req.timeout, timeout=req.timeout,
) )
except ValueError as e: except ValueError as e:
raise urllib.error.HTTPError( raise spack.util.web.DetailedHTTPError(
req.full_url, req,
code, code,
f"Cannot login to registry, failed to obtain bearer token: {e}", f"Cannot login to registry, failed to obtain bearer token: {e}",
headers, headers,
@ -412,13 +408,13 @@ def create_opener():
return opener return opener
def ensure_status(response: HTTPResponse, status: int): def ensure_status(request: urllib.request.Request, response: HTTPResponse, status: int):
"""Raise an error if the response status is not the expected one.""" """Raise an error if the response status is not the expected one."""
if response.status == status: if response.status == status:
return return
raise urllib.error.HTTPError( raise spack.util.web.DetailedHTTPError(
response.geturl(), response.status, response.reason, response.info(), None request, response.status, response.reason, response.info(), None
) )