pubtools-pyxis 1.3.4__tar.gz → 1.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pubtools-pyxis-1.3.4/pubtools_pyxis.egg-info → pubtools_pyxis-1.3.6}/PKG-INFO +31 -3
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/CHANGELOG.rst +11 -0
- pubtools_pyxis-1.3.6/requirements-test.txt +8 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/requirements.txt +1 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/setup.py +11 -3
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/pyxis_authentication.py +14 -10
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/pyxis_client.py +48 -29
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/pyxis_ops.py +152 -20
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/pyxis_session.py +18 -11
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/utils.py +3 -2
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src/pubtools_pyxis.egg-info}/PKG-INFO +31 -3
- pubtools_pyxis-1.3.6/src/pubtools_pyxis.egg-info/SOURCES.txt +40 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools_pyxis.egg-info/entry_points.txt +7 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools_pyxis.egg-info/requires.txt +1 -0
- pubtools_pyxis-1.3.6/tests/test_pyxis_authentication.py +124 -0
- pubtools_pyxis-1.3.6/tests/test_pyxis_client.py +325 -0
- pubtools_pyxis-1.3.6/tests/test_pyxis_ops.py +1012 -0
- pubtools_pyxis-1.3.6/tests/test_pyxis_session.py +58 -0
- pubtools-pyxis-1.3.4/pubtools/__init__.py +0 -1
- pubtools-pyxis-1.3.4/pubtools_pyxis.egg-info/SOURCES.txt +0 -37
- pubtools-pyxis-1.3.4/requirements-test.txt +0 -5
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/LICENSE +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/MANIFEST.in +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/README.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/Makefile +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/README.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/conf.py +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/delete_signatures.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/entrypoints_reference.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/get_indices.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/get_repo_metadata.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/get_signatures.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/index.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/modules_reference.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/ops_helpers.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/pyxis_authentication.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/pyxis_client.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/pyxis_session.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/docs/source/upload_signatures.rst +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6}/setup.cfg +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/__init__.py +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools/_pyxis/constants.py +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools_pyxis.egg-info/dependency_links.txt +0 -0
- {pubtools-pyxis-1.3.4 → pubtools_pyxis-1.3.6/src}/pubtools_pyxis.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pubtools-pyxis
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.6
|
|
4
4
|
Summary: Pubtools-pyxis
|
|
5
5
|
Home-page: https://github.com/release-engineering/pubtools-pyxis
|
|
6
6
|
Author: Lubomir Gallovic
|
|
@@ -15,8 +15,25 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
|
15
15
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
16
16
|
Requires-Python: >=3.6
|
|
17
17
|
Description-Content-Type: text/x-rst
|
|
18
|
-
Provides-Extra: reST
|
|
19
18
|
License-File: LICENSE
|
|
19
|
+
Requires-Dist: setuptools
|
|
20
|
+
Requires-Dist: more-executors>=2.3.0
|
|
21
|
+
Requires-Dist: requests
|
|
22
|
+
Requires-Dist: requests-kerberos
|
|
23
|
+
Requires-Dist: urllib3<2
|
|
24
|
+
Provides-Extra: rest
|
|
25
|
+
Requires-Dist: Sphinx; extra == "rest"
|
|
26
|
+
Dynamic: author
|
|
27
|
+
Dynamic: author-email
|
|
28
|
+
Dynamic: classifier
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
Dynamic: provides-extra
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
20
37
|
|
|
21
38
|
===============
|
|
22
39
|
pubtools-pyxis
|
|
@@ -128,6 +145,17 @@ Get signatures:
|
|
|
128
145
|
ChangeLog
|
|
129
146
|
=========
|
|
130
147
|
|
|
148
|
+
1.3.6 (2025-03-06)
|
|
149
|
+
------------------
|
|
150
|
+
|
|
151
|
+
* Splitted entrypoitnts to `console_scripts` and `mod`.
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
1.3.5 (2023-03-14)
|
|
155
|
+
------------------
|
|
156
|
+
|
|
157
|
+
* Delete signatures in parallel
|
|
158
|
+
|
|
131
159
|
1.3.4 (2023-03-01)
|
|
132
160
|
------------------
|
|
133
161
|
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
ChangeLog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
1.3.6 (2025-03-06)
|
|
5
|
+
------------------
|
|
6
|
+
|
|
7
|
+
* Splitted entrypoitnts to `console_scripts` and `mod`.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
1.3.5 (2023-03-14)
|
|
11
|
+
------------------
|
|
12
|
+
|
|
13
|
+
* Delete signatures in parallel
|
|
14
|
+
|
|
4
15
|
1.3.4 (2023-03-01)
|
|
5
16
|
------------------
|
|
6
17
|
|
|
@@ -7,7 +7,7 @@ import sys
|
|
|
7
7
|
|
|
8
8
|
# import pkg_resources
|
|
9
9
|
import sys
|
|
10
|
-
from setuptools import setup,
|
|
10
|
+
from setuptools import setup, find_namespace_packages
|
|
11
11
|
from setuptools.command.test import test as TestCommand
|
|
12
12
|
|
|
13
13
|
|
|
@@ -71,7 +71,7 @@ if os.environ.get("READTHEDOCS", None):
|
|
|
71
71
|
|
|
72
72
|
setup(
|
|
73
73
|
name="pubtools-pyxis",
|
|
74
|
-
version="1.3.
|
|
74
|
+
version="1.3.6",
|
|
75
75
|
description="Pubtools-pyxis",
|
|
76
76
|
long_description=long_description,
|
|
77
77
|
long_description_content_type='text/x-rst',
|
|
@@ -80,7 +80,8 @@ setup(
|
|
|
80
80
|
url="https://github.com/release-engineering/pubtools-pyxis",
|
|
81
81
|
classifiers=classifiers,
|
|
82
82
|
python_requires='>=3.6',
|
|
83
|
-
packages=
|
|
83
|
+
packages=find_namespace_packages(where="src"),
|
|
84
|
+
package_dir={"": "src"},
|
|
84
85
|
data_files=[],
|
|
85
86
|
install_requires=get_requirements(),
|
|
86
87
|
dependency_links=DEPENDENCY_LINKS,
|
|
@@ -91,6 +92,13 @@ setup(
|
|
|
91
92
|
"pubtools-pyxis-upload-signatures = pubtools._pyxis.pyxis_ops:upload_signatures_main",
|
|
92
93
|
"pubtools-pyxis-get-signatures = pubtools._pyxis.pyxis_ops:get_signatures_main",
|
|
93
94
|
"pubtools-pyxis-delete-signatures = pubtools._pyxis.pyxis_ops:delete_signatures_main"
|
|
95
|
+
],
|
|
96
|
+
"mod": [
|
|
97
|
+
"pubtools-pyxis-get-operator-indices = pubtools._pyxis.pyxis_ops:get_operator_indices_mod",
|
|
98
|
+
"pubtools-pyxis-get-repo-metadata = pubtools._pyxis.pyxis_ops:get_repo_metadata_mod",
|
|
99
|
+
"pubtools-pyxis-upload-signatures = pubtools._pyxis.pyxis_ops:upload_signatures_mod",
|
|
100
|
+
"pubtools-pyxis-get-signatures = pubtools._pyxis.pyxis_ops:get_signatures_mod",
|
|
101
|
+
"pubtools-pyxis-delete-signatures = pubtools._pyxis.pyxis_ops:delete_signatures_mod"
|
|
94
102
|
]
|
|
95
103
|
},
|
|
96
104
|
include_package_data=True,
|
|
@@ -3,15 +3,17 @@ import subprocess
|
|
|
3
3
|
|
|
4
4
|
from requests_kerberos import HTTPKerberosAuth, OPTIONAL
|
|
5
5
|
|
|
6
|
+
from .pyxis_session import PyxisSession
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
class PyxisAuth:
|
|
8
10
|
"""Base Auth class."""
|
|
9
11
|
|
|
10
|
-
def __init__(self):
|
|
12
|
+
def __init__(self) -> None:
|
|
11
13
|
"""Initialize."""
|
|
12
14
|
raise NotImplementedError # pragma: no cover"
|
|
13
15
|
|
|
14
|
-
def apply_to_session(self, pyxis_session):
|
|
16
|
+
def apply_to_session(self, pyxis_session: PyxisSession) -> None:
|
|
15
17
|
"""Set up initialization in the Pyxis session."""
|
|
16
18
|
raise NotImplementedError # pragma: no cover"
|
|
17
19
|
|
|
@@ -20,7 +22,7 @@ class PyxisSSLAuth(PyxisAuth):
|
|
|
20
22
|
"""SSL Auth provider to PyxisClient."""
|
|
21
23
|
|
|
22
24
|
# pylint: disable=super-init-not-called
|
|
23
|
-
def __init__(self, crt_path, key_path):
|
|
25
|
+
def __init__(self, crt_path: str, key_path: str) -> None:
|
|
24
26
|
"""
|
|
25
27
|
Initialize.
|
|
26
28
|
|
|
@@ -33,7 +35,7 @@ class PyxisSSLAuth(PyxisAuth):
|
|
|
33
35
|
self.crt_path = crt_path
|
|
34
36
|
self.key_path = key_path
|
|
35
37
|
|
|
36
|
-
def apply_to_session(self, pyxis_session):
|
|
38
|
+
def apply_to_session(self, pyxis_session: PyxisSession) -> None:
|
|
37
39
|
"""
|
|
38
40
|
Set up PyxisSession with SSL auth.
|
|
39
41
|
|
|
@@ -47,7 +49,9 @@ class PyxisSSLAuth(PyxisAuth):
|
|
|
47
49
|
class PyxisKrbAuth(PyxisAuth):
|
|
48
50
|
"""Kerberos authentication support for PyxisClient."""
|
|
49
51
|
|
|
50
|
-
def __init__(
|
|
52
|
+
def __init__(
|
|
53
|
+
self, krb_princ: str, service: str, ccache_file: str, ktfile: str | None = None
|
|
54
|
+
) -> None:
|
|
51
55
|
"""
|
|
52
56
|
Initialize.
|
|
53
57
|
|
|
@@ -56,17 +60,17 @@ class PyxisKrbAuth(PyxisAuth):
|
|
|
56
60
|
Kerberos principal for obtaining ticket.
|
|
57
61
|
service (str)
|
|
58
62
|
URL of the service to apply the authentication to.
|
|
59
|
-
ktfile (str)
|
|
60
|
-
Kerberos client keytab file.
|
|
61
63
|
ccache_file (str)
|
|
62
64
|
Path to a file used for ccache. Only necessary if kinit will be used.
|
|
65
|
+
ktfile (str)
|
|
66
|
+
Kerberos client keytab file.
|
|
63
67
|
"""
|
|
64
68
|
self.krb_princ = krb_princ
|
|
65
69
|
self.service = service
|
|
66
70
|
self.ktfile = ktfile
|
|
67
71
|
self.ccache_file = ccache_file
|
|
68
72
|
|
|
69
|
-
def _krb_auth(self):
|
|
73
|
+
def _krb_auth(self) -> HTTPKerberosAuth:
|
|
70
74
|
retcode = subprocess.Popen(
|
|
71
75
|
["klist", "-s"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
72
76
|
).wait()
|
|
@@ -102,7 +106,7 @@ class PyxisKrbAuth(PyxisAuth):
|
|
|
102
106
|
force_preemptive=True,
|
|
103
107
|
)
|
|
104
108
|
|
|
105
|
-
def apply_to_session(self, pyxis_session):
|
|
109
|
+
def apply_to_session(self, pyxis_session: PyxisSession) -> None:
|
|
106
110
|
"""Set up PyxisSession with Kerberos auth.
|
|
107
111
|
|
|
108
112
|
Args:
|
|
@@ -3,27 +3,29 @@ from concurrent.futures import as_completed
|
|
|
3
3
|
from functools import partial
|
|
4
4
|
import math
|
|
5
5
|
import threading
|
|
6
|
+
from typing import Callable, Any
|
|
6
7
|
|
|
7
8
|
from more_executors import Executors
|
|
8
9
|
from requests.exceptions import HTTPError
|
|
10
|
+
from requests import Response
|
|
9
11
|
|
|
10
12
|
from .constants import DEFAULT_REQUEST_THREADS_LIMIT
|
|
11
13
|
from .pyxis_session import PyxisSession
|
|
14
|
+
from .pyxis_authentication import PyxisAuth
|
|
12
15
|
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
class PyxisClient(object):
|
|
17
|
+
class PyxisClient:
|
|
16
18
|
"""Pyxis requests wrapper."""
|
|
17
19
|
|
|
18
20
|
def __init__(
|
|
19
21
|
self,
|
|
20
|
-
hostname,
|
|
21
|
-
retries=5,
|
|
22
|
-
auth=None,
|
|
23
|
-
backoff_factor=5,
|
|
24
|
-
verify=True,
|
|
25
|
-
threads=DEFAULT_REQUEST_THREADS_LIMIT,
|
|
26
|
-
):
|
|
22
|
+
hostname: str,
|
|
23
|
+
retries: int = 5,
|
|
24
|
+
auth: PyxisAuth | None = None,
|
|
25
|
+
backoff_factor: int = 5,
|
|
26
|
+
verify: bool = True,
|
|
27
|
+
threads: int = DEFAULT_REQUEST_THREADS_LIMIT,
|
|
28
|
+
) -> None:
|
|
27
29
|
"""
|
|
28
30
|
Initialize.
|
|
29
31
|
|
|
@@ -53,7 +55,7 @@ class PyxisClient(object):
|
|
|
53
55
|
self.threads_limit = threads
|
|
54
56
|
|
|
55
57
|
@property
|
|
56
|
-
def pyxis_session(self):
|
|
58
|
+
def pyxis_session(self) -> PyxisSession | Any:
|
|
57
59
|
"""
|
|
58
60
|
Return a thread-local session for Pyxis requests.
|
|
59
61
|
|
|
@@ -64,13 +66,15 @@ class PyxisClient(object):
|
|
|
64
66
|
self.thread_local.pyxis_session = self._make_session()
|
|
65
67
|
return self.thread_local.pyxis_session
|
|
66
68
|
|
|
67
|
-
def _make_session(self):
|
|
69
|
+
def _make_session(self) -> PyxisSession:
|
|
68
70
|
session = self._session_factory()
|
|
69
71
|
if self._auth:
|
|
70
72
|
self._auth.apply_to_session(session)
|
|
71
73
|
return session
|
|
72
74
|
|
|
73
|
-
def get_operator_indices(
|
|
75
|
+
def get_operator_indices(
|
|
76
|
+
self, ocp_versions_range: str, organization: str | None = None
|
|
77
|
+
) -> list[str] | Any:
|
|
74
78
|
"""Get a list of index images satisfying versioning and organization conditions.
|
|
75
79
|
|
|
76
80
|
Args:
|
|
@@ -91,8 +95,12 @@ class PyxisClient(object):
|
|
|
91
95
|
return resp.json()["data"]
|
|
92
96
|
|
|
93
97
|
def get_repository_metadata(
|
|
94
|
-
self,
|
|
95
|
-
|
|
98
|
+
self,
|
|
99
|
+
repo_name: str,
|
|
100
|
+
custom_registry: str | None = None,
|
|
101
|
+
only_internal: bool = False,
|
|
102
|
+
only_partner: bool = False,
|
|
103
|
+
) -> dict[Any, Any] | Any:
|
|
96
104
|
"""Get metadata of a Comet repository.
|
|
97
105
|
|
|
98
106
|
If checking only one registry hasn't been specified, check both with precedence on
|
|
@@ -130,19 +138,19 @@ class PyxisClient(object):
|
|
|
130
138
|
resp.raise_for_status()
|
|
131
139
|
return resp.json()
|
|
132
140
|
|
|
133
|
-
def upload_signatures(self, signatures):
|
|
141
|
+
def upload_signatures(self, signatures: list[str]) -> list[Any]:
|
|
134
142
|
"""
|
|
135
143
|
Upload signatures from given JSON string.
|
|
136
144
|
|
|
137
145
|
Args:
|
|
138
|
-
signatures
|
|
146
|
+
signatures [str]
|
|
139
147
|
JSON with signatures to upload. See Pyxis API for details.
|
|
140
148
|
|
|
141
149
|
Returns:
|
|
142
150
|
list: List of uploaded signatures including auto-populated fields.
|
|
143
151
|
"""
|
|
144
152
|
|
|
145
|
-
def _send_post_request(data):
|
|
153
|
+
def _send_post_request(data: dict[Any, Any]) -> Response:
|
|
146
154
|
response = self.pyxis_session.post("signatures", json=data)
|
|
147
155
|
# SEE CLOUDDST-9698
|
|
148
156
|
# Pyxis returns 500 error due to a potential sidecar config issue
|
|
@@ -156,11 +164,13 @@ class PyxisClient(object):
|
|
|
156
164
|
|
|
157
165
|
return self._do_parallel_requests(_send_post_request, signatures)
|
|
158
166
|
|
|
159
|
-
def _clear_session(self):
|
|
167
|
+
def _clear_session(self) -> None:
|
|
160
168
|
self.thread_local.pyxis_session.close()
|
|
161
169
|
delattr(self.thread_local, "pyxis_session")
|
|
162
170
|
|
|
163
|
-
def _do_parallel_requests(
|
|
171
|
+
def _do_parallel_requests(
|
|
172
|
+
self, make_request: Callable[[Any], Any], data_items: list[Any]
|
|
173
|
+
) -> list[Any] | Any:
|
|
164
174
|
"""
|
|
165
175
|
Call given function with given data items in parallel, collect responses.
|
|
166
176
|
|
|
@@ -189,7 +199,7 @@ class PyxisClient(object):
|
|
|
189
199
|
|
|
190
200
|
return [f.result() for f in as_completed(futures)]
|
|
191
201
|
|
|
192
|
-
def _handle_json_response(self, response):
|
|
202
|
+
def _handle_json_response(self, response: Response) -> dict[Any, Any] | Any:
|
|
193
203
|
"""
|
|
194
204
|
Get JSON from given response or raise an informative exception.
|
|
195
205
|
|
|
@@ -202,8 +212,14 @@ class PyxisClient(object):
|
|
|
202
212
|
except ValueError: # Python 2.x compat
|
|
203
213
|
data = {}
|
|
204
214
|
|
|
215
|
+
tolerate_codes = []
|
|
205
216
|
# Uploaded data already exists in Pyxis
|
|
206
|
-
if response.
|
|
217
|
+
if response.request.method == "POST":
|
|
218
|
+
tolerate_codes = [409]
|
|
219
|
+
# Data already removed from Pyxis
|
|
220
|
+
elif response.request.method == "DELETE":
|
|
221
|
+
tolerate_codes = [404]
|
|
222
|
+
if response.status_code in tolerate_codes:
|
|
207
223
|
return data
|
|
208
224
|
|
|
209
225
|
try:
|
|
@@ -216,11 +232,13 @@ class PyxisClient(object):
|
|
|
216
232
|
extra_msg = data["detail"] if "detail" in data else response.text
|
|
217
233
|
|
|
218
234
|
# re-raise the exception with an extra message
|
|
219
|
-
raise HTTPError("{0}\n{1}".format(e, extra_msg))
|
|
235
|
+
raise HTTPError("{0}\n{1}".format(e, extra_msg), response=response)
|
|
220
236
|
|
|
221
237
|
return data
|
|
222
238
|
|
|
223
|
-
def get_container_signatures(
|
|
239
|
+
def get_container_signatures(
|
|
240
|
+
self, manifest_digests: str | None = None, references: str | None = None
|
|
241
|
+
) -> list[str]:
|
|
224
242
|
"""Get a list of signature metadata matching given fields.
|
|
225
243
|
|
|
226
244
|
Args:
|
|
@@ -248,7 +266,7 @@ class PyxisClient(object):
|
|
|
248
266
|
|
|
249
267
|
return resp
|
|
250
268
|
|
|
251
|
-
def _get_items_from_all_pages(self, endpoint, **kwargs):
|
|
269
|
+
def _get_items_from_all_pages(self, endpoint: str, **kwargs: Any) -> list[Any]:
|
|
252
270
|
"""
|
|
253
271
|
Get response from all pages of pyxis.
|
|
254
272
|
|
|
@@ -277,16 +295,17 @@ class PyxisClient(object):
|
|
|
277
295
|
all_resp.extend(resp.json()["data"])
|
|
278
296
|
return all_resp
|
|
279
297
|
|
|
280
|
-
def delete_container_signatures(self, signature_ids):
|
|
298
|
+
def delete_container_signatures(self, signature_ids: list[str]) -> list[Any]:
|
|
281
299
|
"""Delete signatures matching given fields.
|
|
282
300
|
|
|
283
301
|
Args:
|
|
284
302
|
signature_ids ([str])
|
|
285
303
|
Internal Pyxis signature IDs of signatures which should be removed.
|
|
286
304
|
"""
|
|
287
|
-
delete_endpoint = "signatures/id/{id}"
|
|
288
305
|
|
|
289
|
-
|
|
306
|
+
def _send_delete_request(signature_id: str) -> Response:
|
|
307
|
+
delete_endpoint = "signatures/id/{id}"
|
|
290
308
|
resp = self.pyxis_session.delete(delete_endpoint.format(id=signature_id))
|
|
291
|
-
|
|
292
|
-
|
|
309
|
+
return resp
|
|
310
|
+
|
|
311
|
+
return self._do_parallel_requests(_send_delete_request, signature_ids)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import sys
|
|
3
3
|
import tempfile
|
|
4
|
+
from argparse import ArgumentParser, Namespace
|
|
5
|
+
from typing import Any
|
|
4
6
|
|
|
5
7
|
from .constants import DEFAULT_REQUEST_THREADS_LIMIT
|
|
6
|
-
from .pyxis_authentication import PyxisKrbAuth, PyxisSSLAuth
|
|
8
|
+
from .pyxis_authentication import PyxisKrbAuth, PyxisSSLAuth, PyxisAuth
|
|
7
9
|
from .pyxis_client import PyxisClient
|
|
8
10
|
from .utils import setup_arg_parser
|
|
9
11
|
|
|
@@ -108,9 +110,15 @@ DELETE_SIGNATURES_ARGS[("--ids",)] = {
|
|
|
108
110
|
"required": True,
|
|
109
111
|
"type": str,
|
|
110
112
|
}
|
|
113
|
+
DELETE_SIGNATURES_ARGS[("--request-threads",)] = {
|
|
114
|
+
"help": "Maximum number of threads to use for parallel requests",
|
|
115
|
+
"required": False,
|
|
116
|
+
"default": DEFAULT_REQUEST_THREADS_LIMIT,
|
|
117
|
+
"type": int,
|
|
118
|
+
}
|
|
111
119
|
|
|
112
120
|
|
|
113
|
-
def setup_pyxis_client(args, ccache_file):
|
|
121
|
+
def setup_pyxis_client(args: Namespace, ccache_file: str) -> PyxisClient:
|
|
114
122
|
"""
|
|
115
123
|
Set up a PyxisClient instance according to specified parameters.
|
|
116
124
|
|
|
@@ -125,11 +133,11 @@ def setup_pyxis_client(args, ccache_file):
|
|
|
125
133
|
"""
|
|
126
134
|
# If both auths are specified, Kerberos is preferred
|
|
127
135
|
if args.pyxis_krb_principal:
|
|
128
|
-
auth = PyxisKrbAuth(
|
|
136
|
+
auth: PyxisAuth = PyxisKrbAuth(
|
|
129
137
|
args.pyxis_krb_principal,
|
|
130
138
|
args.pyxis_server,
|
|
131
|
-
args.pyxis_krb_ktfile,
|
|
132
139
|
ccache_file,
|
|
140
|
+
args.pyxis_krb_ktfile,
|
|
133
141
|
)
|
|
134
142
|
elif args.pyxis_ssl_crtfile and args.pyxis_ssl_keyfile:
|
|
135
143
|
auth = PyxisSSLAuth(args.pyxis_ssl_crtfile, args.pyxis_ssl_keyfile)
|
|
@@ -150,12 +158,12 @@ def setup_pyxis_client(args, ccache_file):
|
|
|
150
158
|
return PyxisClient(args.pyxis_server, auth=auth, verify=not args.pyxis_insecure)
|
|
151
159
|
|
|
152
160
|
|
|
153
|
-
def set_get_operator_indices_args():
|
|
161
|
+
def set_get_operator_indices_args() -> ArgumentParser:
|
|
154
162
|
"""Set up argparser without extra parameters, this method is used for auto doc generation."""
|
|
155
163
|
return setup_arg_parser(GET_OPERATORS_INDICES_ARGS)
|
|
156
164
|
|
|
157
165
|
|
|
158
|
-
def
|
|
166
|
+
def _get_operator_indices(sysargs: list[str] | None = None) -> list[str] | Any:
|
|
159
167
|
"""
|
|
160
168
|
Entrypoint for getting operator indices.
|
|
161
169
|
|
|
@@ -173,17 +181,41 @@ def get_operator_indices_main(sysargs=None):
|
|
|
173
181
|
resp = pyxis_client.get_operator_indices(
|
|
174
182
|
args.ocp_versions_range, args.organization
|
|
175
183
|
)
|
|
184
|
+
return resp
|
|
185
|
+
|
|
176
186
|
|
|
187
|
+
def get_operator_indices_main(sysargs: list[str] | None = None) -> int:
|
|
188
|
+
"""
|
|
189
|
+
Entrypoint for getting operator indices.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
int: Exit code (0 for success).
|
|
193
|
+
"""
|
|
194
|
+
try:
|
|
195
|
+
resp = _get_operator_indices(sysargs)
|
|
177
196
|
json.dump(resp, sys.stdout, sort_keys=True, indent=4, separators=(",", ": "))
|
|
178
|
-
return
|
|
197
|
+
return 0
|
|
198
|
+
except Exception as e:
|
|
199
|
+
print(f"Error getting operator indices: {e}", file=sys.stderr)
|
|
200
|
+
return 1
|
|
201
|
+
|
|
179
202
|
|
|
203
|
+
def get_operator_indices_mod(sysargs: list[str] | None = None) -> list[str] | Any:
|
|
204
|
+
"""
|
|
205
|
+
Entrypoint for getting operator indices in module mode.
|
|
180
206
|
|
|
181
|
-
|
|
207
|
+
This function is used when running the script as a module.
|
|
208
|
+
It does not return an exit code, but rather prints the result directly.
|
|
209
|
+
"""
|
|
210
|
+
return _get_operator_indices(sysargs)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def set_get_repo_metadata_args() -> ArgumentParser:
|
|
182
214
|
"""Set up argparser without extra parameters, this method is used for auto doc generation."""
|
|
183
215
|
return setup_arg_parser(GET_REPO_METADATA_ARGS)
|
|
184
216
|
|
|
185
217
|
|
|
186
|
-
def
|
|
218
|
+
def _get_repo_metadata(sysargs: list[str] | None = None) -> dict[Any, Any] | Any:
|
|
187
219
|
"""
|
|
188
220
|
Entrypoint for getting repository metadata.
|
|
189
221
|
|
|
@@ -210,17 +242,42 @@ def get_repo_metadata_main(sysargs=None):
|
|
|
210
242
|
args.only_internal_registry,
|
|
211
243
|
args.only_partner_registry,
|
|
212
244
|
)
|
|
245
|
+
return res
|
|
213
246
|
|
|
247
|
+
|
|
248
|
+
def get_repo_metadata_main(sysargs: list[str] | None = None) -> dict[Any, Any] | Any:
|
|
249
|
+
"""
|
|
250
|
+
Entrypoint for getting repository metadata.
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
int: Exit code (0 for success).
|
|
254
|
+
"""
|
|
255
|
+
try:
|
|
256
|
+
res = _get_repo_metadata(sysargs)
|
|
214
257
|
json.dump(res, sys.stdout, sort_keys=True, indent=4, separators=(",", ": "))
|
|
215
|
-
return
|
|
258
|
+
return 0
|
|
259
|
+
except Exception as e:
|
|
260
|
+
print(f"Error getting repository metadata: {e}", file=sys.stderr)
|
|
261
|
+
return 1
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def get_repo_metadata_mod(sysargs: list[str] | None = None) -> dict[Any, Any] | Any:
|
|
265
|
+
"""
|
|
266
|
+
Entrypoint for getting repository metadata in module mode.
|
|
267
|
+
|
|
268
|
+
This function is used when running the script as a module.
|
|
269
|
+
It does not return an exit code, but rather prints the result directly.
|
|
270
|
+
"""
|
|
271
|
+
return _get_repo_metadata(sysargs)
|
|
272
|
+
# No return value, output is printed directly
|
|
216
273
|
|
|
217
274
|
|
|
218
|
-
def set_upload_signatures_args():
|
|
275
|
+
def set_upload_signatures_args() -> ArgumentParser:
|
|
219
276
|
"""Set up argparser without extra parameters, this method is used for auto doc generation."""
|
|
220
277
|
return setup_arg_parser(UPLOAD_SIGNATURES_ARGS)
|
|
221
278
|
|
|
222
279
|
|
|
223
|
-
def
|
|
280
|
+
def _upload_signatures(sysargs: list[str] | None = None) -> list[Any]:
|
|
224
281
|
"""
|
|
225
282
|
Entrypoint for uploading signatures from JSON or a file.
|
|
226
283
|
|
|
@@ -238,13 +295,37 @@ def upload_signatures_main(sysargs=None):
|
|
|
238
295
|
with tempfile.NamedTemporaryFile() as tmpfile:
|
|
239
296
|
pyxis_client = setup_pyxis_client(args, tmpfile.name)
|
|
240
297
|
resp = pyxis_client.upload_signatures(signatures_json)
|
|
298
|
+
return resp
|
|
299
|
+
|
|
241
300
|
|
|
301
|
+
def upload_signatures_main(sysargs: list[str] | None = None) -> int:
|
|
302
|
+
"""
|
|
303
|
+
Entrypoint for uploading signatures from JSON or a file.
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
int: Exit code (0 for success).
|
|
307
|
+
"""
|
|
308
|
+
try:
|
|
309
|
+
resp = _upload_signatures(sysargs)
|
|
242
310
|
json.dump(resp, sys.stdout, sort_keys=True, indent=4, separators=(",", ": "))
|
|
311
|
+
return 0
|
|
312
|
+
except Exception as e:
|
|
313
|
+
print(f"Error uploading signatures: {e}", file=sys.stderr)
|
|
314
|
+
return 1
|
|
243
315
|
|
|
244
|
-
|
|
316
|
+
|
|
317
|
+
def upload_signatures_mod(sysargs: list[str] | None = None) -> list[Any]:
|
|
318
|
+
"""
|
|
319
|
+
Entrypoint for uploading signatures from JSON or a file in module mode.
|
|
320
|
+
|
|
321
|
+
This function is used when running the script as a module.
|
|
322
|
+
It does not return an exit code, but rather prints the result directly.
|
|
323
|
+
"""
|
|
324
|
+
return _upload_signatures(sysargs)
|
|
325
|
+
# No return value, output is printed directly
|
|
245
326
|
|
|
246
327
|
|
|
247
|
-
def deserialize_list_from_arg(value, csv_input=False):
|
|
328
|
+
def deserialize_list_from_arg(value: str, csv_input: bool = False) -> list[Any] | Any:
|
|
248
329
|
"""
|
|
249
330
|
Conditionally load contents of a file if specified in argument value.
|
|
250
331
|
|
|
@@ -269,17 +350,17 @@ def deserialize_list_from_arg(value, csv_input=False):
|
|
|
269
350
|
return json.load(f)
|
|
270
351
|
|
|
271
352
|
|
|
272
|
-
def serialize_to_csv_from_list(list_value):
|
|
353
|
+
def serialize_to_csv_from_list(list_value: list[Any]) -> str:
|
|
273
354
|
"""Convert a list to comma separated string."""
|
|
274
355
|
return ",".join(list_value)
|
|
275
356
|
|
|
276
357
|
|
|
277
|
-
def set_get_signatures_args():
|
|
358
|
+
def set_get_signatures_args() -> ArgumentParser:
|
|
278
359
|
"""Set up argparser without extra parameters, this method is used for auto doc generation."""
|
|
279
360
|
return setup_arg_parser(GET_SIGNATURES_ARGS)
|
|
280
361
|
|
|
281
362
|
|
|
282
|
-
def
|
|
363
|
+
def _get_signatures(sysargs: list[str] | None = None) -> list[str]:
|
|
283
364
|
"""
|
|
284
365
|
Entrypoint for getting container signature metadata.
|
|
285
366
|
|
|
@@ -309,17 +390,42 @@ def get_signatures_main(sysargs=None):
|
|
|
309
390
|
res = pyxis_client.get_container_signatures(
|
|
310
391
|
csv_manifest_digests, csv_references
|
|
311
392
|
)
|
|
393
|
+
return res
|
|
394
|
+
|
|
312
395
|
|
|
396
|
+
def get_signatures_main(sysargs: list[str] | None = None) -> int:
|
|
397
|
+
"""
|
|
398
|
+
Entrypoint for getting container signature metadata.
|
|
399
|
+
|
|
400
|
+
Returns:
|
|
401
|
+
int: Exit code (0 for success).
|
|
402
|
+
"""
|
|
403
|
+
try:
|
|
404
|
+
res = _get_signatures(sysargs)
|
|
313
405
|
json.dump(res, sys.stdout, sort_keys=True, indent=4, separators=(",", ": "))
|
|
314
|
-
return
|
|
406
|
+
return 0
|
|
407
|
+
except Exception as e:
|
|
408
|
+
print(f"Error getting signatures: {e}", file=sys.stderr)
|
|
409
|
+
return 1
|
|
315
410
|
|
|
316
411
|
|
|
317
|
-
def
|
|
412
|
+
def get_signatures_mod(sysargs: list[str] | None = None) -> list[str]:
|
|
413
|
+
"""
|
|
414
|
+
Entrypoint for getting container signature metadata in module mode.
|
|
415
|
+
|
|
416
|
+
This function is used when running the script as a module.
|
|
417
|
+
It does not return an exit code, but rather prints the result directly.
|
|
418
|
+
"""
|
|
419
|
+
return _get_signatures(sysargs)
|
|
420
|
+
# No return value, output is printed directly
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def set_delete_signatures_args() -> ArgumentParser:
|
|
318
424
|
"""Set up argparser without extra parameters, this method is used for auto doc generation."""
|
|
319
425
|
return setup_arg_parser(DELETE_SIGNATURES_ARGS)
|
|
320
426
|
|
|
321
427
|
|
|
322
|
-
def
|
|
428
|
+
def _delete_signatures(sysargs: list[str] | None = None) -> None:
|
|
323
429
|
"""
|
|
324
430
|
Entrypoint for removing existing signatures.
|
|
325
431
|
|
|
@@ -338,3 +444,29 @@ def delete_signatures_main(sysargs=None):
|
|
|
338
444
|
with tempfile.NamedTemporaryFile() as tmpfile:
|
|
339
445
|
pyxis_client = setup_pyxis_client(args, tmpfile.name)
|
|
340
446
|
pyxis_client.delete_container_signatures(signature_ids)
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def delete_signatures_main(sysargs: list[str] | None = None) -> int:
|
|
450
|
+
"""
|
|
451
|
+
Entrypoint for removing existing signatures.
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
int: Exit code (0 for success).
|
|
455
|
+
"""
|
|
456
|
+
try:
|
|
457
|
+
_delete_signatures(sysargs)
|
|
458
|
+
return 0
|
|
459
|
+
except Exception as e:
|
|
460
|
+
print(f"Error deleting signatures: {e}", file=sys.stderr)
|
|
461
|
+
return 1
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def delete_signatures_mod(sysargs: list[str] | None = None) -> None:
|
|
465
|
+
"""
|
|
466
|
+
Entrypoint for removing existing signatures in module mode.
|
|
467
|
+
|
|
468
|
+
This function is used when running the script as a module.
|
|
469
|
+
It does not return an exit code, but rather prints the result directly.
|
|
470
|
+
"""
|
|
471
|
+
return _delete_signatures(sysargs)
|
|
472
|
+
# No return value, output is printed directly
|