From 42bea22a302bd1138a723c7a5e759f8b3e114722 Mon Sep 17 00:00:00 2001 From: Matthias Dellweg Date: Tue, 5 Nov 2024 12:58:05 +0100 Subject: [PATCH] WIP --- pulp-glue/pulp_glue/common/openapi.py | 37 ++++++++++++++++++++++----- pulp_cli/config.py | 4 +-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/pulp-glue/pulp_glue/common/openapi.py b/pulp-glue/pulp_glue/common/openapi.py index 2e2e3666..79368b07 100644 --- a/pulp-glue/pulp_glue/common/openapi.py +++ b/pulp-glue/pulp_glue/common/openapi.py @@ -1,16 +1,19 @@ # copyright (c) 2020, Matthias Dellweg # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) +import asyncio import base64 import datetime import json import os +import ssl import typing as t from collections import defaultdict from contextlib import suppress from io import BufferedReader from urllib.parse import urljoin +import aiohttp import requests import urllib3 @@ -174,6 +177,9 @@ def __init__( self._safe_calls_only: bool = safe_calls_only self._headers = headers or {} self._verify = verify + # Shall we make that a parameter? + self._ssl_context: t.Optional[t.Union[ssl.SSLContext, bool]] = None + self._auth_provider = auth_provider self._cert = cert self._key = key @@ -225,6 +231,22 @@ def base_url(self) -> str: def cid(self) -> t.Optional[str]: return self._headers.get("Correlation-Id") + @property + def ssl_context(self) -> t.Union[ssl.SSLContext, bool]: + if self._ssl_context is None: + if self._verify is False: + self._ssl_context = False + else: + if isinstance(self._verify, str): + self._ssl_context = ssl.create_default_context(cafile=self._verify) + else: + self._ssl_context = ssl.create_default_context() + if self._cert is not None: + self._ssl_context.load_cert_chain(self._cert, self._key) + # Type inference is failing here. + self._ssl_context = t.cast(t.Union[ssl.SSLContext | bool], self._ssl_context) + return self._ssl_context + def load_api(self, refresh_cache: bool = False) -> None: # TODO: Find a way to invalidate caches on upstream change xdg_cache_home: str = os.environ.get("XDG_CACHE_HOME") or "~/.cache" @@ -242,7 +264,7 @@ def load_api(self, refresh_cache: bool = False) -> None: self._parse_api(data) except Exception: # Try again with a freshly downloaded version - data = self._download_api() + data = asyncio.run(self._download_api()) self._parse_api(data) # Write to cache as it seems to be valid os.makedirs(os.path.dirname(apidoc_cache), exist_ok=True) @@ -262,15 +284,18 @@ def _parse_api(self, data: bytes) -> None: if method in {"get", "put", "post", "delete", "options", "head", "patch", "trace"} } - def _download_api(self) -> bytes: + async def _download_api(self) -> bytes: try: - response: requests.Response = self._session.get(urljoin(self._base_url, self._doc_path)) - except requests.RequestException as e: + connector = aiohttp.TCPConnector(ssl=self.ssl_context) + async with aiohttp.ClientSession(connector=connector, headers=self._headers) as session: + async with session.get(urljoin(self._base_url, self._doc_path)) as response: + response.raise_for_status() + data = await response.read() + except aiohttp.ClientError as e: raise OpenAPIError(str(e)) - response.raise_for_status() if "Correlation-ID" in response.headers: self._set_correlation_id(response.headers["Correlation-ID"]) - return response.content + return data def _set_correlation_id(self, correlation_id: str) -> None: if "Correlation-ID" in self._headers: diff --git a/pulp_cli/config.py b/pulp_cli/config.py index 5c5668bc..1d4a2eeb 100644 --- a/pulp_cli/config.py +++ b/pulp_cli/config.py @@ -70,10 +70,10 @@ click.option("--password", default=None, help=_("Password on pulp server")), click.option("--client-id", default=None, help=_("OAuth2 client ID")), click.option("--client-secret", default=None, help=_("OAuth2 client secret")), - click.option("--cert", default="", help=_("Path to client certificate")), + click.option("--cert", default=None, help=_("Path to client certificate")), click.option( "--key", - default="", + default=None, help=_("Path to client private key. Not required if client cert contains this."), ), click.option("--verify-ssl/--no-verify-ssl", default=True, help=_("Verify SSL connection")),