Skip to content

Commit

Permalink
[pre-commit.ci] auto fixes from pre-commit.com hooks
Browse files Browse the repository at this point in the history
for more information, see https://pre-commit.ci
  • Loading branch information
pre-commit-ci[bot] committed Oct 5, 2023
1 parent 1041f48 commit b2980f4
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 84 deletions.
87 changes: 46 additions & 41 deletions src/pushsource/_impl/backend/errata_source/errata_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,24 @@
USE_XMLRPC_CLIENT = os.environ.get("PUSHSOURCE_ERRATA_USE_XMLRPC_API") == "1"


def get_errata_client(threads, url, keytab_path=None, principal=None,
force_xmlrpc=USE_XMLRPC_CLIENT, **retry_kwargs):
keytab_path = os.environ.get("PUSHSOURCE_ERRATA_KEYTAB_PATH") \
if not keytab_path else keytab_path
principal = os.environ.get("PUSHSOURCE_ERRATA_PRINCIPAL") \
if not principal else principal
def get_errata_client(
threads,
url,
keytab_path=None,
principal=None,
force_xmlrpc=USE_XMLRPC_CLIENT,
**retry_kwargs,
):
keytab_path = (
os.environ.get("PUSHSOURCE_ERRATA_KEYTAB_PATH")
if not keytab_path
else keytab_path
)
principal = (
os.environ.get("PUSHSOURCE_ERRATA_PRINCIPAL") if not principal else principal
)
if keytab_path and principal and not force_xmlrpc:
return ErrataHTTPClient(threads, url, keytab_path, principal,
**retry_kwargs)
return ErrataHTTPClient(threads, url, keytab_path, principal, **retry_kwargs)
return ErrataClient(threads, url, **retry_kwargs)


Expand All @@ -47,10 +56,9 @@ class ErrataRaw(object):
class ErrataClientBase(object):
def __init__(self, threads, url, **retry_args):
self._executor = (
Executors.thread_pool(name="pushsource-errata-client",
max_workers=threads)
.with_retry(**retry_args)
.with_cancel_on_shutdown()
Executors.thread_pool(name="pushsource-errata-client", max_workers=threads)
.with_retry(**retry_args)
.with_cancel_on_shutdown()
)
self._url = url
self._tls = threading.local()
Expand Down Expand Up @@ -93,17 +101,13 @@ def _log_queried_et(self, response, advisory_id):
def get_raw_f(self, advisory_id):
"""Returns Future[ErrataRaw] holding all ET responses for a particular advisory."""
all_responses = f_zip(
self._executor.submit(self._get_advisory_cdn_metadata,
advisory_id),
self._executor.submit(self._get_advisory_cdn_file_list,
advisory_id),
self._executor.submit(self._get_advisory_cdn_docker_file_list,
advisory_id),
self._executor.submit(self._get_advisory_cdn_metadata, advisory_id),
self._executor.submit(self._get_advisory_cdn_file_list, advisory_id),
self._executor.submit(self._get_advisory_cdn_docker_file_list, advisory_id),
self._executor.submit(self._get_ftp_paths, advisory_id),
)
all_responses = f_map(
all_responses,
partial(self._log_queried_et, advisory_id=advisory_id)
all_responses, partial(self._log_queried_et, advisory_id=advisory_id)
)
return f_map(all_responses, lambda tup: ErrataRaw(*tup))

Expand Down Expand Up @@ -156,7 +160,6 @@ def _call_et(self, method, advisory_id):


class ErrataClient(ErrataClientBase):

def __init__(self, threads, url, **retry_args):
deprecation_notice = (
"The XMLRPC Errata Client has been deprecated and will be removed. "
Expand Down Expand Up @@ -197,32 +200,29 @@ def _do_call(self, method, advisory_id):


class ErrataHTTPClient(ErrataClientBase):
def __init__(self, threads, url, keytab_path: str, principal: str,
**retry_args):

def __init__(self, threads, url, keytab_path: str, principal: str, **retry_args):
super().__init__(threads, url, **retry_args)

self.keytab_path = keytab_path
self.principal = principal

self.get_advisory_data = partial(
self._call_et, "/api/v1/erratum/{id}"
)
self.get_advisory_data = partial(self._call_et, "/api/v1/erratum/{id}")
self._get_advisory_cdn_metadata = partial(
self._call_et, "/api/v1/push_metadata/cdn_metadata/{id}.json"
)
self._get_advisory_cdn_file_list = partial(
self._call_et, "/api/v1/push_metadata/cdn_file_list/{id}.json"
)
self._get_advisory_cdn_docker_file_list = partial(
self._call_et,
"/api/v1/push_metadata/cdn_docker_file_list/{id}.json"
self._call_et, "/api/v1/push_metadata/cdn_docker_file_list/{id}.json"
)
self._get_ftp_paths = partial(
self._call_et, "/api/v1/push_metadata/ftp_paths/{id}.json")
self._call_et, "/api/v1/push_metadata/ftp_paths/{id}.json"
)

with tempfile.NamedTemporaryFile(prefix="ccache_pushsource_errata_",
delete=False) as file:
with tempfile.NamedTemporaryFile(
prefix="ccache_pushsource_errata_", delete=False
) as file:
self.ccache_filename = file.name

def authenticate(self):
Expand All @@ -234,17 +234,19 @@ def authenticate(self):

result = subprocess.run(
["klist", "-c", f"FILE:{self.ccache_filename}"],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
check=False
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
check=False,
)
regex_res = re.search(r"Default principal: (.*)\n", result.stdout)

# if Kerberos ticket is not found, or the principal is incorrect
if result.returncode or not regex_res or regex_res.group(
1) != self.principal:
if result.returncode or not regex_res or regex_res.group(1) != self.principal:
LOG.info(
"Errata TGT doesn't exist, running kinit for principal %s",
self.principal)
self.principal,
)
result = subprocess.run(
[
"kinit",
Expand All @@ -255,8 +257,10 @@ def authenticate(self):
"-c",
f"FILE:{self.ccache_filename}",
],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True, check=False
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
check=False,
)
if result.returncode:
LOG.warning("kinit has failed: '%s'", result.stdout)
Expand All @@ -278,8 +282,9 @@ def _errata_service(self):
LOG.debug("Creating HTTP client for Errata Tool: %s", self._url)
name = gssapi.Name(self.principal, gssapi.NameType.user)
creds = gssapi.Credentials.acquire(
name=name, usage="initiate",
store={"ccache": f"FILE:{self.ccache_filename}"}
name=name,
usage="initiate",
store={"ccache": f"FILE:{self.ccache_filename}"},
).creds

session = requests.Session()
Expand Down
10 changes: 7 additions & 3 deletions src/pushsource/_impl/backend/errata_source/errata_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,12 @@ def __init__(
"""
self._url = force_https(url)
self._errata = list_argument(errata)
self._client = get_errata_client(threads=threads, url=self._errata_service_url, keytab_path=keytab_path, principal=principal)
self._client = get_errata_client(
threads=threads,
url=self._errata_service_url,
keytab_path=keytab_path,
principal=principal,
)
self._client.authenticate()

self._rpm_filter_arch = list_argument(rpm_filter_arch, retain_none=True)
Expand Down Expand Up @@ -239,8 +244,7 @@ def _push_items_from_container_manifests(self, erratum, docker_file_list):
if advisory_data:
# This dictionary key is different based on erratum type
erratum_type = list(advisory_data["errata"].keys())[0]
product_name = advisory_data["errata"][erratum_type]["product"][
"name"]
product_name = advisory_data["errata"][erratum_type]["product"]["name"]
else:
product_name = None

Expand Down
2 changes: 1 addition & 1 deletion tests/baseline/test_baseline.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def fake_errata_tool():
"pushsource._impl.backend.errata_source.errata_client.requests.Session"
) as mock_http_proxy:
with patch(
"pushsource._impl.backend.errata_source.errata_client.xmlrpc_client.ServerProxy"
"pushsource._impl.backend.errata_source.errata_client.xmlrpc_client.ServerProxy"
) as mock_xmlrpc_client:
mock_http_proxy.side_effect = controller.proxy
mock_xmlrpc_client.side_effect = controller.proxy
Expand Down
5 changes: 3 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ def fake_kerberos_auth(mocker):
mocker.patch("gssapi.Credentials.acquire")
mocker.patch("requests_gssapi.HTTPSPNEGOAuth", return_value=None)


@fixture
def fake_errata_tool(fake_kerberos_auth):
controller = FakeErrataToolController()
with patch(
"pushsource._impl.backend.errata_source.errata_client.requests.Session"
"pushsource._impl.backend.errata_source.errata_client.requests.Session"
) as mock_http_proxy:
with patch(
"pushsource._impl.backend.errata_source.errata_client.xmlrpc_client.ServerProxy"
"pushsource._impl.backend.errata_source.errata_client.xmlrpc_client.ServerProxy"
) as mock_xmlrpc_client:
mock_http_proxy.side_effect = controller.proxy
mock_xmlrpc_client.side_effect = controller.proxy
Expand Down
31 changes: 18 additions & 13 deletions tests/errata/fake_errata_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

DATADIR = os.path.join(os.path.dirname(__file__), "data")


class FakeErrataToolController(object):
def __init__(self):
self._data = self._load()
Expand All @@ -28,7 +29,7 @@ def _load_errata(cls):
if filename.endswith(".json"):
path = os.path.join(root, filename)
with open(path) as fh:
out[filename.rstrip('.json')] = json.load(fh)
out[filename.rstrip(".json")] = json.load(fh)
return out

@classmethod
Expand All @@ -39,8 +40,7 @@ def _load(cls):
if filename.endswith(".yaml"):
path = os.path.join(root, filename)
with open(path) as fh:
data = yaml.load(fh,
Loader=yaml.FullLoader) # nosec B506
data = yaml.load(fh, Loader=yaml.FullLoader) # nosec B506
advisory_id = data["advisory_id"]
if advisory_id in out:
raise ValueError(
Expand All @@ -56,14 +56,19 @@ def __init__(self, controller):
self.auth = None
self.url_map = [
(".*/api/v1/erratum/(.*)", self.get_advisory_data),
(".*/api/v1/push_metadata/cdn_metadata/(.*).json",
self.get_advisory_cdn_metadata),
(".*/api/v1/push_metadata/cdn_file_list/(.*).json",
self.get_advisory_cdn_file_list),
(".*/api/v1/push_metadata/cdn_docker_file_list/(.*).json",
self.get_advisory_cdn_docker_file_list),
(".*/api/v1/push_metadata/ftp_paths/(.*).json",
self.get_ftp_paths)
(
".*/api/v1/push_metadata/cdn_metadata/(.*).json",
self.get_advisory_cdn_metadata,
),
(
".*/api/v1/push_metadata/cdn_file_list/(.*).json",
self.get_advisory_cdn_file_list,
),
(
".*/api/v1/push_metadata/cdn_docker_file_list/(.*).json",
self.get_advisory_cdn_docker_file_list,
),
(".*/api/v1/push_metadata/ftp_paths/(.*).json", self.get_ftp_paths),
]

def _get_data(self, advisory_id, key):
Expand Down Expand Up @@ -97,8 +102,8 @@ def get(self, url, *args, **kwargs):
response_object.status_code = 200
except Fault:
response_object.json.return_value = {
"error": "Bad errata id given: %s".format(
match.group(1))}
"error": "Bad errata id given: %s".format(match.group(1))
}
response_object.status_code = 404
response_object.raise_for_status.side_effect = requests.HTTPError()
return response_object
Expand Down
26 changes: 15 additions & 11 deletions tests/errata/test_errata_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import pytest
import requests

from pushsource._impl.backend.errata_source.errata_client import ErrataHTTPClient, get_errata_client
from pushsource._impl.backend.errata_source.errata_client import (
ErrataHTTPClient,
get_errata_client,
)


@pytest.fixture(autouse=True)
Expand All @@ -17,7 +20,6 @@ def fake_temporary_file(mocker):
)



@mock.patch.dict(
"os.environ",
{
Expand All @@ -40,8 +42,8 @@ def test_init_env_vars():
def test_get_session(mock_auth, mock_session, mock_acquire, mock_name, caplog):
caplog.set_level(logging.DEBUG)

client = ErrataHTTPClient(1,
"https://errata.example.com/", "/path/to/keytab", "[email protected]"
client = ErrataHTTPClient(
1, "https://errata.example.com/", "/path/to/keytab", "[email protected]"
)
assert not hasattr(client._tls, "session")

Expand All @@ -59,8 +61,9 @@ def test_get_session(mock_auth, mock_session, mock_acquire, mock_name, caplog):
assert session == mock_session.return_value
assert client._tls.session == mock_session.return_value

assert caplog.messages == ["Creating HTTP client for Errata Tool: "
"https://errata.example.com/"]
assert caplog.messages == [
"Creating HTTP client for Errata Tool: " "https://errata.example.com/"
]


@mock.patch("gssapi.Name")
Expand All @@ -72,8 +75,8 @@ def test_get_session_already_exists(
):
caplog.set_level(logging.DEBUG)

client = ErrataHTTPClient(1,
"https://errata.example.com/", "/path/to/keytab", "[email protected]"
client = ErrataHTTPClient(
1, "https://errata.example.com/", "/path/to/keytab", "[email protected]"
)
assert not hasattr(client._tls, "session")
session_mock = client._tls.session = mock.MagicMock()
Expand All @@ -91,8 +94,8 @@ def test_get_session_already_exists(
def test_get_advisory_data(caplog):
caplog.set_level(logging.DEBUG)

client = ErrataHTTPClient(1,
"https://errata.example.com/", "/path/to/keytab", "[email protected]"
client = ErrataHTTPClient(
1, "https://errata.example.com/", "/path/to/keytab", "[email protected]"
)
client._tls.session = requests.Session()
with requests_mock.Mocker() as m:
Expand All @@ -108,4 +111,5 @@ def test_get_advisory_data(caplog):
assert caplog.messages == [
"Calling Errata Tool /api/v1/erratum/{id}(RHSA-123456789)",
"GET https://errata.example.com/api/v1/erratum/RHSA-123456789 200",
"Errata Tool completed call /api/v1/erratum/{id}(RHSA-123456789)"]
"Errata Tool completed call /api/v1/erratum/{id}(RHSA-123456789)",
]
11 changes: 7 additions & 4 deletions tests/errata/test_errata_client_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@
from pushsource._impl.backend.errata_source import errata_client
import requests


def test_errata_client_info_logs(caplog):
"""Errata client logs one INFO message per advisory queried."""

caplog.set_level(logging.INFO)

client = errata_client.ErrataHTTPClient(threads=1,
url="https://errata.example.com/",
keytab_path="/path/to/keytab",
principal="[email protected]")
client = errata_client.ErrataHTTPClient(
threads=1,
url="https://errata.example.com/",
keytab_path="/path/to/keytab",
principal="[email protected]",
)
with patch(
"pushsource._impl.backend.errata_source.errata_client.requests.Session"
) as mock_proxy:
Expand Down
Loading

0 comments on commit b2980f4

Please sign in to comment.