pulpcore 3.80.2__py3-none-any.whl → 3.82.0__py3-none-any.whl
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.
Potentially problematic release.
This version of pulpcore might be problematic. Click here for more details.
- pulp_certguard/app/__init__.py +1 -1
- pulp_file/app/__init__.py +1 -1
- pulp_file/pytest_plugin.py +22 -104
- pulp_file/tests/functional/api/test_bad_sync.py +62 -2
- pulpcore/app/apps.py +1 -1
- pulpcore/app/entrypoint.py +4 -1
- pulpcore/app/files.py +15 -5
- pulpcore/app/migrations/0132_task_profile_options.py +19 -0
- pulpcore/app/models/fields.py +2 -2
- pulpcore/app/models/task.py +1 -0
- pulpcore/app/netutil.py +20 -0
- pulpcore/app/replica.py +3 -9
- pulpcore/app/serializers/content.py +1 -1
- pulpcore/app/serializers/domain.py +1 -0
- pulpcore/app/serializers/fields.py +10 -0
- pulpcore/app/serializers/publication.py +4 -0
- pulpcore/app/settings.py +2 -0
- pulpcore/content/__init__.py +2 -1
- pulpcore/content/entrypoint.py +4 -1
- pulpcore/content/handler.py +14 -13
- pulpcore/download/base.py +9 -2
- pulpcore/middleware.py +25 -0
- pulpcore/openapi/__init__.py +13 -0
- pulpcore/tasking/_util.py +11 -6
- pulpcore/tasking/tasks.py +2 -0
- pulpcore/tests/functional/api/test_tasking.py +19 -0
- pulpcore/tests/functional/api/using_plugin/test_content_delivery.py +34 -0
- {pulpcore-3.80.2.dist-info → pulpcore-3.82.0.dist-info}/METADATA +22 -22
- {pulpcore-3.80.2.dist-info → pulpcore-3.82.0.dist-info}/RECORD +33 -31
- {pulpcore-3.80.2.dist-info → pulpcore-3.82.0.dist-info}/WHEEL +0 -0
- {pulpcore-3.80.2.dist-info → pulpcore-3.82.0.dist-info}/entry_points.txt +0 -0
- {pulpcore-3.80.2.dist-info → pulpcore-3.82.0.dist-info}/licenses/LICENSE +0 -0
- {pulpcore-3.80.2.dist-info → pulpcore-3.82.0.dist-info}/top_level.txt +0 -0
pulp_certguard/app/__init__.py
CHANGED
pulp_file/app/__init__.py
CHANGED
pulp_file/pytest_plugin.py
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import uuid
|
|
3
|
-
import subprocess
|
|
4
|
-
from collections import defaultdict
|
|
5
|
-
from pathlib import Path
|
|
6
3
|
|
|
7
|
-
import aiofiles
|
|
8
4
|
import pytest
|
|
9
|
-
from aiohttp import web
|
|
10
5
|
|
|
11
6
|
from pulpcore.tests.functional.utils import BindingsNamespace, generate_iso, generate_manifest
|
|
12
7
|
|
|
@@ -37,9 +32,9 @@ def file_random_content_unit(file_content_unit_with_name_factory):
|
|
|
37
32
|
|
|
38
33
|
|
|
39
34
|
@pytest.fixture
|
|
40
|
-
def file_content_unit_with_name_factory(file_bindings,
|
|
35
|
+
def file_content_unit_with_name_factory(file_bindings, random_artifact_factory, monitor_task):
|
|
41
36
|
def _file_content_unit_with_name_factory(name):
|
|
42
|
-
artifact_attrs = {"artifact":
|
|
37
|
+
artifact_attrs = {"artifact": random_artifact_factory().pulp_href, "relative_path": name}
|
|
43
38
|
return file_bindings.ContentFilesApi.read(
|
|
44
39
|
monitor_task(
|
|
45
40
|
file_bindings.ContentFilesApi.create(**artifact_attrs).task
|
|
@@ -74,14 +69,13 @@ def file_distribution_factory(file_bindings, gen_object_with_cleanup):
|
|
|
74
69
|
return _file_distribution_factory
|
|
75
70
|
|
|
76
71
|
|
|
77
|
-
@pytest.fixture
|
|
78
|
-
def file_fixtures_root(
|
|
79
|
-
fixture_dir =
|
|
80
|
-
fixture_dir.mkdir()
|
|
72
|
+
@pytest.fixture(scope="class")
|
|
73
|
+
def file_fixtures_root(tmp_path_factory):
|
|
74
|
+
fixture_dir = tmp_path_factory.mktemp("fixtures")
|
|
81
75
|
return fixture_dir
|
|
82
76
|
|
|
83
77
|
|
|
84
|
-
@pytest.fixture
|
|
78
|
+
@pytest.fixture(scope="class")
|
|
85
79
|
def write_3_iso_file_fixture_data_factory(file_fixtures_root):
|
|
86
80
|
def _write_3_iso_file_fixture_data_factory(name, overwrite=False, seed=None):
|
|
87
81
|
file_fixtures_root.joinpath(name).mkdir(exist_ok=overwrite)
|
|
@@ -96,12 +90,12 @@ def write_3_iso_file_fixture_data_factory(file_fixtures_root):
|
|
|
96
90
|
return _write_3_iso_file_fixture_data_factory
|
|
97
91
|
|
|
98
92
|
|
|
99
|
-
@pytest.fixture
|
|
93
|
+
@pytest.fixture(scope="class")
|
|
100
94
|
def basic_manifest_path(write_3_iso_file_fixture_data_factory):
|
|
101
95
|
return write_3_iso_file_fixture_data_factory("basic")
|
|
102
96
|
|
|
103
97
|
|
|
104
|
-
@pytest.fixture
|
|
98
|
+
@pytest.fixture(scope="class")
|
|
105
99
|
def copy_manifest_only_factory(file_fixtures_root):
|
|
106
100
|
def _copy_manifest_only(name):
|
|
107
101
|
file_fixtures_root.joinpath(f"{name}-manifest").mkdir()
|
|
@@ -114,12 +108,12 @@ def copy_manifest_only_factory(file_fixtures_root):
|
|
|
114
108
|
return _copy_manifest_only
|
|
115
109
|
|
|
116
110
|
|
|
117
|
-
@pytest.fixture
|
|
111
|
+
@pytest.fixture(scope="class")
|
|
118
112
|
def basic_manifest_only_path(copy_manifest_only_factory):
|
|
119
113
|
return copy_manifest_only_factory("basic")
|
|
120
114
|
|
|
121
115
|
|
|
122
|
-
@pytest.fixture
|
|
116
|
+
@pytest.fixture(scope="class")
|
|
123
117
|
def large_manifest_path(file_fixtures_root):
|
|
124
118
|
one_megabyte = 1048576
|
|
125
119
|
file_fixtures_root.joinpath("large").mkdir()
|
|
@@ -128,7 +122,7 @@ def large_manifest_path(file_fixtures_root):
|
|
|
128
122
|
return "/large/PULP_MANIFEST"
|
|
129
123
|
|
|
130
124
|
|
|
131
|
-
@pytest.fixture
|
|
125
|
+
@pytest.fixture(scope="class")
|
|
132
126
|
def range_header_manifest_path(file_fixtures_root):
|
|
133
127
|
"""A path to a File repository manifest that contains 8 unique files each 4mb in size."""
|
|
134
128
|
one_megabyte = 1048576
|
|
@@ -147,7 +141,7 @@ def range_header_manifest_path(file_fixtures_root):
|
|
|
147
141
|
return "/range/PULP_MANIFEST"
|
|
148
142
|
|
|
149
143
|
|
|
150
|
-
@pytest.fixture
|
|
144
|
+
@pytest.fixture(scope="class")
|
|
151
145
|
def manifest_path_with_commas(file_fixtures_root):
|
|
152
146
|
file_fixtures_root.joinpath("comma_test").mkdir()
|
|
153
147
|
file_fixtures_root.joinpath("comma_test/comma,folder").mkdir()
|
|
@@ -161,15 +155,15 @@ def manifest_path_with_commas(file_fixtures_root):
|
|
|
161
155
|
return "/comma_test/PULP_MANIFEST"
|
|
162
156
|
|
|
163
157
|
|
|
164
|
-
@pytest.fixture
|
|
158
|
+
@pytest.fixture(scope="class")
|
|
165
159
|
def invalid_manifest_path(file_fixtures_root, basic_manifest_path):
|
|
166
|
-
file_path_to_corrupt = file_fixtures_root /
|
|
160
|
+
file_path_to_corrupt = file_fixtures_root / "basic/1.iso"
|
|
167
161
|
with open(file_path_to_corrupt, "w") as f:
|
|
168
162
|
f.write("this is not the right data")
|
|
169
163
|
return basic_manifest_path
|
|
170
164
|
|
|
171
165
|
|
|
172
|
-
@pytest.fixture
|
|
166
|
+
@pytest.fixture(scope="class")
|
|
173
167
|
def duplicate_filename_paths(write_3_iso_file_fixture_data_factory):
|
|
174
168
|
return (
|
|
175
169
|
write_3_iso_file_fixture_data_factory("file"),
|
|
@@ -177,24 +171,24 @@ def duplicate_filename_paths(write_3_iso_file_fixture_data_factory):
|
|
|
177
171
|
)
|
|
178
172
|
|
|
179
173
|
|
|
180
|
-
@pytest.fixture
|
|
174
|
+
@pytest.fixture(scope="class")
|
|
181
175
|
def file_fixture_server_ssl_client_cert_req(
|
|
182
176
|
ssl_ctx_req_client_auth, file_fixtures_root, gen_fixture_server
|
|
183
177
|
):
|
|
184
178
|
return gen_fixture_server(file_fixtures_root, ssl_ctx_req_client_auth)
|
|
185
179
|
|
|
186
180
|
|
|
187
|
-
@pytest.fixture
|
|
181
|
+
@pytest.fixture(scope="class")
|
|
188
182
|
def file_fixture_server_ssl(ssl_ctx, file_fixtures_root, gen_fixture_server):
|
|
189
183
|
return gen_fixture_server(file_fixtures_root, ssl_ctx)
|
|
190
184
|
|
|
191
185
|
|
|
192
|
-
@pytest.fixture
|
|
186
|
+
@pytest.fixture(scope="class")
|
|
193
187
|
def file_fixture_server(file_fixtures_root, gen_fixture_server):
|
|
194
188
|
return gen_fixture_server(file_fixtures_root, None)
|
|
195
189
|
|
|
196
190
|
|
|
197
|
-
@pytest.fixture
|
|
191
|
+
@pytest.fixture(scope="class")
|
|
198
192
|
def file_remote_factory(file_fixture_server, file_bindings, gen_object_with_cleanup):
|
|
199
193
|
def _file_remote_factory(
|
|
200
194
|
manifest_path=None, url=None, policy="immediate", pulp_domain=None, **body
|
|
@@ -213,7 +207,7 @@ def file_remote_factory(file_fixture_server, file_bindings, gen_object_with_clea
|
|
|
213
207
|
return _file_remote_factory
|
|
214
208
|
|
|
215
209
|
|
|
216
|
-
@pytest.fixture
|
|
210
|
+
@pytest.fixture(scope="class")
|
|
217
211
|
def file_remote_ssl_factory(
|
|
218
212
|
file_fixture_server_ssl,
|
|
219
213
|
file_bindings,
|
|
@@ -235,7 +229,7 @@ def file_remote_ssl_factory(
|
|
|
235
229
|
return _file_remote_ssl_factory
|
|
236
230
|
|
|
237
231
|
|
|
238
|
-
@pytest.fixture
|
|
232
|
+
@pytest.fixture(scope="class")
|
|
239
233
|
def file_remote_client_cert_req_factory(
|
|
240
234
|
file_fixture_server_ssl_client_cert_req,
|
|
241
235
|
file_bindings,
|
|
@@ -290,83 +284,7 @@ def file_publication_factory(file_bindings, gen_object_with_cleanup):
|
|
|
290
284
|
return _file_publication_factory
|
|
291
285
|
|
|
292
286
|
|
|
293
|
-
@pytest.fixture
|
|
294
|
-
def gen_bad_response_fixture_server(gen_threaded_aiohttp_server):
|
|
295
|
-
"""
|
|
296
|
-
This server will perform 3 bad responses for each file requested.
|
|
297
|
-
|
|
298
|
-
1st response will be incomplete, sending only half of the data.
|
|
299
|
-
2nd response will have corrupted data, with one byte changed.
|
|
300
|
-
3rd response will return error 429.
|
|
301
|
-
4th response will be correct.
|
|
302
|
-
"""
|
|
303
|
-
|
|
304
|
-
def _gen_fixture_server(fixtures_root, ssl_ctx):
|
|
305
|
-
record = []
|
|
306
|
-
num_requests = defaultdict(int)
|
|
307
|
-
|
|
308
|
-
async def handler(request):
|
|
309
|
-
nonlocal num_requests
|
|
310
|
-
record.append(request)
|
|
311
|
-
relative_path = request.raw_path[1:] # Strip off leading "/"
|
|
312
|
-
file_path = Path(fixtures_root) / Path(relative_path)
|
|
313
|
-
# Max retries is 3. So on fourth request, send full data
|
|
314
|
-
num_requests[relative_path] += 1
|
|
315
|
-
if "PULP_MANIFEST" in relative_path or num_requests[relative_path] % 4 == 0:
|
|
316
|
-
return web.FileResponse(file_path)
|
|
317
|
-
|
|
318
|
-
# On third request send 429 error, TooManyRequests
|
|
319
|
-
if num_requests[relative_path] % 4 == 3:
|
|
320
|
-
raise web.HTTPTooManyRequests
|
|
321
|
-
|
|
322
|
-
size = file_path.stat().st_size
|
|
323
|
-
response = web.StreamResponse(headers={"content-length": f"{size}"})
|
|
324
|
-
await response.prepare(request)
|
|
325
|
-
async with aiofiles.open(file_path, "rb") as f:
|
|
326
|
-
# Send only partial content causing aiohttp.ClientPayloadError if request num == 1
|
|
327
|
-
chunk = await f.read(size // 2)
|
|
328
|
-
await response.write(chunk)
|
|
329
|
-
# Send last chunk with modified last byte if request num == 2
|
|
330
|
-
if num_requests[relative_path] % 4 == 2:
|
|
331
|
-
chunk2 = await f.read()
|
|
332
|
-
await response.write(chunk2[:-1])
|
|
333
|
-
await response.write(bytes([chunk2[-1] ^ 1]))
|
|
334
|
-
else:
|
|
335
|
-
request.transport.close()
|
|
336
|
-
|
|
337
|
-
return response
|
|
338
|
-
|
|
339
|
-
app = web.Application()
|
|
340
|
-
app.add_routes([web.get("/{tail:.*}", handler)])
|
|
341
|
-
return gen_threaded_aiohttp_server(app, ssl_ctx, record)
|
|
342
|
-
|
|
343
|
-
return _gen_fixture_server
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
@pytest.fixture
|
|
347
|
-
def bad_response_fixture_server(file_fixtures_root, gen_bad_response_fixture_server):
|
|
348
|
-
return gen_bad_response_fixture_server(file_fixtures_root, None)
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
@pytest.fixture
|
|
352
|
-
def wget_recursive_download_on_host():
|
|
353
|
-
def _wget_recursive_download_on_host(url, destination):
|
|
354
|
-
subprocess.check_output(
|
|
355
|
-
[
|
|
356
|
-
"wget",
|
|
357
|
-
"--recursive",
|
|
358
|
-
"--no-parent",
|
|
359
|
-
"--no-host-directories",
|
|
360
|
-
"--directory-prefix",
|
|
361
|
-
destination,
|
|
362
|
-
url,
|
|
363
|
-
]
|
|
364
|
-
)
|
|
365
|
-
|
|
366
|
-
return _wget_recursive_download_on_host
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
@pytest.fixture
|
|
287
|
+
@pytest.fixture(scope="class")
|
|
370
288
|
def generate_server_and_remote(
|
|
371
289
|
file_bindings, gen_fixture_server, file_fixtures_root, gen_object_with_cleanup
|
|
372
290
|
):
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
import uuid
|
|
3
|
-
|
|
4
|
-
from
|
|
5
|
+
import aiofiles
|
|
6
|
+
from aiohttp import web
|
|
5
7
|
|
|
6
8
|
from pulpcore.client.pulp_file import RepositorySyncURL
|
|
7
9
|
|
|
@@ -28,6 +30,64 @@ def perform_sync(
|
|
|
28
30
|
yield _perform_sync
|
|
29
31
|
|
|
30
32
|
|
|
33
|
+
@pytest.fixture(scope="class")
|
|
34
|
+
def gen_bad_response_fixture_server(gen_threaded_aiohttp_server):
|
|
35
|
+
"""
|
|
36
|
+
This server will perform 3 bad responses for each file requested.
|
|
37
|
+
|
|
38
|
+
1st response will be incomplete, sending only half of the data.
|
|
39
|
+
2nd response will have corrupted data, with one byte changed.
|
|
40
|
+
3rd response will return error 429.
|
|
41
|
+
4th response will be correct.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def _gen_fixture_server(fixtures_root, ssl_ctx):
|
|
45
|
+
record = []
|
|
46
|
+
num_requests = defaultdict(int)
|
|
47
|
+
|
|
48
|
+
async def handler(request):
|
|
49
|
+
nonlocal num_requests
|
|
50
|
+
record.append(request)
|
|
51
|
+
relative_path = request.raw_path[1:] # Strip off leading "/"
|
|
52
|
+
file_path = fixtures_root / relative_path
|
|
53
|
+
# Max retries is 3. So on fourth request, send full data
|
|
54
|
+
num_requests[relative_path] += 1
|
|
55
|
+
if "PULP_MANIFEST" in relative_path or num_requests[relative_path] % 4 == 0:
|
|
56
|
+
return web.FileResponse(file_path)
|
|
57
|
+
|
|
58
|
+
# On third request send 429 error, TooManyRequests
|
|
59
|
+
if num_requests[relative_path] % 4 == 3:
|
|
60
|
+
raise web.HTTPTooManyRequests
|
|
61
|
+
|
|
62
|
+
size = file_path.stat().st_size
|
|
63
|
+
response = web.StreamResponse(headers={"content-length": f"{size}"})
|
|
64
|
+
await response.prepare(request)
|
|
65
|
+
async with aiofiles.open(file_path, "rb") as f:
|
|
66
|
+
# Send only partial content causing aiohttp.ClientPayloadError if request num == 1
|
|
67
|
+
chunk = await f.read(size // 2)
|
|
68
|
+
await response.write(chunk)
|
|
69
|
+
# Send last chunk with modified last byte if request num == 2
|
|
70
|
+
if num_requests[relative_path] % 4 == 2:
|
|
71
|
+
chunk2 = await f.read()
|
|
72
|
+
await response.write(chunk2[:-1])
|
|
73
|
+
await response.write(bytes([chunk2[-1] ^ 1]))
|
|
74
|
+
else:
|
|
75
|
+
request.transport.close()
|
|
76
|
+
|
|
77
|
+
return response
|
|
78
|
+
|
|
79
|
+
app = web.Application()
|
|
80
|
+
app.add_routes([web.get("/{tail:.*}", handler)])
|
|
81
|
+
return gen_threaded_aiohttp_server(app, ssl_ctx, record)
|
|
82
|
+
|
|
83
|
+
return _gen_fixture_server
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@pytest.fixture(scope="class")
|
|
87
|
+
def bad_response_fixture_server(file_fixtures_root, gen_bad_response_fixture_server):
|
|
88
|
+
return gen_bad_response_fixture_server(file_fixtures_root, None)
|
|
89
|
+
|
|
90
|
+
|
|
31
91
|
@pytest.mark.parallel
|
|
32
92
|
def test_bad_response_retry(bad_response_fixture_server, large_manifest_path, perform_sync):
|
|
33
93
|
"""
|
pulpcore/app/apps.py
CHANGED
pulpcore/app/entrypoint.py
CHANGED
|
@@ -11,6 +11,7 @@ from django.db.utils import InterfaceError, DatabaseError
|
|
|
11
11
|
from gunicorn.workers.sync import SyncWorker
|
|
12
12
|
|
|
13
13
|
from pulpcore.app.apps import pulp_plugin_configs
|
|
14
|
+
from pulpcore.app.netutil import has_ipv6
|
|
14
15
|
from pulpcore.app.pulpcore_gunicorn_application import PulpcoreGunicornApplication
|
|
15
16
|
|
|
16
17
|
logger = getLogger(__name__)
|
|
@@ -102,7 +103,9 @@ class PulpcoreApiApplication(PulpcoreGunicornApplication):
|
|
|
102
103
|
# https://github.com/benoitc/gunicorn/blob/master/gunicorn/config.py
|
|
103
104
|
|
|
104
105
|
|
|
105
|
-
@click.option(
|
|
106
|
+
@click.option(
|
|
107
|
+
"--bind", "-b", default=[f"{ '[::]' if has_ipv6() else '0.0.0.0' }:24817"], multiple=True
|
|
108
|
+
)
|
|
106
109
|
@click.option("--workers", "-w", type=int)
|
|
107
110
|
# @click.option("--threads", "-w", type=int) # We don't use a threaded worker...
|
|
108
111
|
@click.option("--name", "-n", "proc_name")
|
pulpcore/app/files.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import concurrent.futures
|
|
3
|
+
from concurrent.futures import ThreadPoolExecutor, ALL_COMPLETED
|
|
2
4
|
from gettext import gettext as _
|
|
3
5
|
|
|
4
6
|
from django.core.files.uploadedfile import TemporaryUploadedFile
|
|
@@ -39,9 +41,13 @@ class PulpTemporaryUploadedFile(TemporaryUploadedFile):
|
|
|
39
41
|
instance = cls(name, "", size, "", "")
|
|
40
42
|
instance.file = file
|
|
41
43
|
# Default 1MB
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
with ThreadPoolExecutor(max_workers=6) as executor:
|
|
45
|
+
while data := file.read(1048576):
|
|
46
|
+
futures = [
|
|
47
|
+
executor.submit(instance.hashers[hasher].update, data)
|
|
48
|
+
for hasher in models.Artifact.DIGEST_FIELDS
|
|
49
|
+
]
|
|
50
|
+
concurrent.futures.wait(futures, timeout=None, return_when=ALL_COMPLETED)
|
|
45
51
|
|
|
46
52
|
# calling the method read() moves the file's pointer to the end of the file object,
|
|
47
53
|
# thus, it is necessary to reset the file's pointer position back to 0 in case of
|
|
@@ -82,11 +88,15 @@ class HashingFileUploadHandler(TemporaryFileUploadHandler):
|
|
|
82
88
|
self.file = PulpTemporaryUploadedFile(
|
|
83
89
|
file_name, content_type, 0, charset, content_type_extra
|
|
84
90
|
)
|
|
91
|
+
self.threadpool = ThreadPoolExecutor(max_workers=6)
|
|
85
92
|
|
|
86
93
|
def receive_data_chunk(self, raw_data, start):
|
|
94
|
+
futures = [
|
|
95
|
+
self.threadpool.submit(self.file.hashers[hasher].update, raw_data)
|
|
96
|
+
for hasher in models.Artifact.DIGEST_FIELDS
|
|
97
|
+
]
|
|
87
98
|
self.file.write(raw_data)
|
|
88
|
-
|
|
89
|
-
self.file.hashers[hasher].update(raw_data)
|
|
99
|
+
concurrent.futures.wait(futures, timeout=None, return_when=ALL_COMPLETED)
|
|
90
100
|
|
|
91
101
|
|
|
92
102
|
class TemporaryDownloadedFile(TemporaryUploadedFile):
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Generated by Django 4.2.10 on 2025-06-26 19:44
|
|
2
|
+
|
|
3
|
+
import django.contrib.postgres.fields
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('core', '0131_distribution_checkpoint_publication_checkpoint'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name='task',
|
|
16
|
+
name='profile_options',
|
|
17
|
+
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), null=True, size=None),
|
|
18
|
+
),
|
|
19
|
+
]
|
pulpcore/app/models/fields.py
CHANGED
|
@@ -90,7 +90,7 @@ class ArtifactFileField(FileField):
|
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
class EncryptedTextField(TextField):
|
|
93
|
-
"""A field
|
|
93
|
+
"""A field that encrypts text using settings.DB_ENCRYPTION_KEY."""
|
|
94
94
|
|
|
95
95
|
def __init__(self, *args, **kwargs):
|
|
96
96
|
if kwargs.get("primary_key"):
|
|
@@ -114,7 +114,7 @@ class EncryptedTextField(TextField):
|
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
class EncryptedJSONField(JSONField):
|
|
117
|
-
"""A Field
|
|
117
|
+
"""A Field that encrypts the JSON text using settings.DP_ENCRYPTION_KEY."""
|
|
118
118
|
|
|
119
119
|
def __init__(self, *args, **kwargs):
|
|
120
120
|
if kwargs.get("primary_key"):
|
pulpcore/app/models/task.py
CHANGED
|
@@ -147,6 +147,7 @@ class Task(BaseModel, AutoAddObjPermsMixin):
|
|
|
147
147
|
pulp_domain = models.ForeignKey("Domain", default=get_domain_pk, on_delete=models.CASCADE)
|
|
148
148
|
versions = HStoreField(default=dict)
|
|
149
149
|
|
|
150
|
+
profile_options = ArrayField(models.TextField(), null=True)
|
|
150
151
|
profile_artifacts = models.ManyToManyField("Artifact", through=ProfileArtifact)
|
|
151
152
|
|
|
152
153
|
immediate = models.BooleanField(default=False, null=True)
|
pulpcore/app/netutil.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
network utility functions
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import socket
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def has_ipv6():
|
|
9
|
+
"""
|
|
10
|
+
check if host can use IPv6
|
|
11
|
+
"""
|
|
12
|
+
# if python has IPv6 support we need to check if we can bind an IPv6 socket
|
|
13
|
+
if socket.has_ipv6:
|
|
14
|
+
try:
|
|
15
|
+
with socket.socket(socket.AF_INET6) as sock:
|
|
16
|
+
sock.bind(("::1", 0))
|
|
17
|
+
return True
|
|
18
|
+
except OSError:
|
|
19
|
+
pass
|
|
20
|
+
return False
|
pulpcore/app/replica.py
CHANGED
|
@@ -90,15 +90,9 @@ class Replicator:
|
|
|
90
90
|
params = {"q": q}
|
|
91
91
|
else:
|
|
92
92
|
params = {}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
distributions = self.distribution_ctx_cls(self.pulp_ctx).list(list_size, offset, params)
|
|
97
|
-
for distro in distributions:
|
|
98
|
-
yield distro
|
|
99
|
-
if len(distributions) < list_size:
|
|
100
|
-
break
|
|
101
|
-
offset += list_size
|
|
93
|
+
yield from self.distribution_ctx_cls(self.pulp_ctx).list_iterator(
|
|
94
|
+
parameters=params, batch_size=100
|
|
95
|
+
)
|
|
102
96
|
|
|
103
97
|
def labels(self, upstream_object):
|
|
104
98
|
upstream_labels = getattr(upstream_object, "pulp_labels", {})
|
|
@@ -11,7 +11,7 @@ from pulpcore.app.util import get_domain
|
|
|
11
11
|
|
|
12
12
|
class NoArtifactContentSerializer(base.ModelSerializer):
|
|
13
13
|
pulp_href = base.DetailIdentityField(view_name_pattern=r"contents(-.*/.*)-detail")
|
|
14
|
-
pulp_labels =
|
|
14
|
+
pulp_labels = fields.PulpLabelsField(
|
|
15
15
|
help_text=_(
|
|
16
16
|
"A dictionary of arbitrary key/value pairs used to describe a specific "
|
|
17
17
|
"Content instance."
|
|
@@ -342,6 +342,7 @@ class StorageSettingsSerializer(serializers.Serializer):
|
|
|
342
342
|
STORAGE_MAPPING = {
|
|
343
343
|
"pulpcore.app.models.storage.FileSystem": FileSystemSettingsSerializer,
|
|
344
344
|
"pulpcore.app.models.storage.PulpSFTPStorage": SFTPSettingsSerializer,
|
|
345
|
+
"storages.backends.s3.S3Storage": AmazonS3SettingsSerializer,
|
|
345
346
|
"storages.backends.s3boto3.S3Boto3Storage": AmazonS3SettingsSerializer,
|
|
346
347
|
"storages.backends.azure_storage.AzureStorage": AzureSettingsSerializer,
|
|
347
348
|
"storages.backends.gcloud.GoogleCloudStorage": GoogleSettingsSerializer,
|
|
@@ -435,3 +435,13 @@ def pulp_labels_validator(value):
|
|
|
435
435
|
)
|
|
436
436
|
|
|
437
437
|
return value
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
class PulpLabelsField(serializers.HStoreField):
|
|
441
|
+
"""
|
|
442
|
+
Custom field for handling pulp labels that ensures proper dictionary format.
|
|
443
|
+
Converts JSON strings to dictionaries during validation.
|
|
444
|
+
"""
|
|
445
|
+
|
|
446
|
+
def get_value(self, dictionary):
|
|
447
|
+
return dictionary.get(self.field_name, empty)
|
|
@@ -78,6 +78,10 @@ class PublicationSerializer(ModelSerializer):
|
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
class ContentGuardSerializer(ModelSerializer):
|
|
81
|
+
"""
|
|
82
|
+
Base class for content guard serializers.
|
|
83
|
+
"""
|
|
84
|
+
|
|
81
85
|
pulp_href = DetailIdentityField(view_name_pattern=r"contentguards(-.*/.*)-detail")
|
|
82
86
|
|
|
83
87
|
name = serializers.CharField(
|
pulpcore/app/settings.py
CHANGED
|
@@ -173,6 +173,7 @@ MIDDLEWARE = [
|
|
|
173
173
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
174
174
|
"pulpcore.middleware.DomainMiddleware",
|
|
175
175
|
"pulpcore.middleware.APIRootRewriteMiddleware",
|
|
176
|
+
"pulpcore.middleware.TaskProfilerMiddleware",
|
|
176
177
|
]
|
|
177
178
|
|
|
178
179
|
AUTHENTICATION_BACKENDS = [
|
|
@@ -436,6 +437,7 @@ storage_validator = (
|
|
|
436
437
|
Validator("REDIRECT_TO_OBJECT_STORAGE", eq=False)
|
|
437
438
|
| Validator(*storage_keys, eq="pulpcore.app.models.storage.FileSystem")
|
|
438
439
|
| Validator(*storage_keys, eq="storages.backends.azure_storage.AzureStorage")
|
|
440
|
+
| Validator(*storage_keys, eq="storages.backends.s3.S3Storage")
|
|
439
441
|
| Validator(*storage_keys, eq="storages.backends.s3boto3.S3Boto3Storage")
|
|
440
442
|
| Validator(*storage_keys, eq="storages.backends.gcloud.GoogleCloudStorage")
|
|
441
443
|
)
|
pulpcore/content/__init__.py
CHANGED
|
@@ -25,13 +25,14 @@ from pulpcore.app.models import ContentAppStatus # noqa: E402: module level not
|
|
|
25
25
|
from pulpcore.app.util import get_worker_name # noqa: E402: module level not at top of file
|
|
26
26
|
|
|
27
27
|
from .handler import Handler # noqa: E402: module level not at top of file
|
|
28
|
-
from .instrumentation import instrumentation # noqa: E402: module level not at top of file
|
|
29
28
|
from .authentication import authenticate, guid # noqa: E402: module level not at top of file
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
log = logging.getLogger(__name__)
|
|
33
32
|
|
|
34
33
|
if settings.OTEL_ENABLED:
|
|
34
|
+
from .instrumentation import instrumentation # noqa: E402: module level not at top of file
|
|
35
|
+
|
|
35
36
|
app = web.Application(middlewares=[guid, authenticate, instrumentation()])
|
|
36
37
|
else:
|
|
37
38
|
app = web.Application(middlewares=[guid, authenticate])
|
pulpcore/content/entrypoint.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import click
|
|
2
|
+
from pulpcore.app.netutil import has_ipv6
|
|
2
3
|
from pulpcore.app.pulpcore_gunicorn_application import PulpcoreGunicornApplication
|
|
3
4
|
from django.conf import settings
|
|
4
5
|
|
|
@@ -19,7 +20,9 @@ class PulpcoreContentApplication(PulpcoreGunicornApplication):
|
|
|
19
20
|
return pulpcore.content.server
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
@click.option(
|
|
23
|
+
@click.option(
|
|
24
|
+
"--bind", "-b", default=[f"{ '[::]' if has_ipv6() else '0.0.0.0' }:24816"], multiple=True
|
|
25
|
+
)
|
|
23
26
|
@click.option("--workers", "-w", type=int)
|
|
24
27
|
# @click.option("--threads", "-w", type=int) # We don't use a threaded worker...
|
|
25
28
|
@click.option("--name", "-n", "proc_name")
|
pulpcore/content/handler.py
CHANGED
|
@@ -1279,19 +1279,20 @@ class Handler:
|
|
|
1279
1279
|
# "backstop" the prepare() call here, so the write() will be allowed.
|
|
1280
1280
|
if not response.prepared:
|
|
1281
1281
|
await response.prepare(request)
|
|
1282
|
-
if
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1282
|
+
if request.method == "GET":
|
|
1283
|
+
if range_start or range_stop:
|
|
1284
|
+
start_byte_pos = 0
|
|
1285
|
+
end_byte_pos = len(data)
|
|
1286
|
+
if range_start:
|
|
1287
|
+
start_byte_pos = max(0, range_start - data_size_handled)
|
|
1288
|
+
if range_stop:
|
|
1289
|
+
end_byte_pos = min(len(data), range_stop - data_size_handled)
|
|
1290
|
+
|
|
1291
|
+
data_for_client = data[start_byte_pos:end_byte_pos]
|
|
1292
|
+
await response.write(data_for_client)
|
|
1293
|
+
data_size_handled = data_size_handled + len(data)
|
|
1294
|
+
else:
|
|
1295
|
+
await response.write(data)
|
|
1295
1296
|
if remote.policy != Remote.STREAMED:
|
|
1296
1297
|
await original_handle_data(data)
|
|
1297
1298
|
|
pulpcore/download/base.py
CHANGED
|
@@ -2,6 +2,8 @@ from gettext import gettext as _
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from collections import namedtuple
|
|
5
|
+
import concurrent.futures
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor, ALL_COMPLETED
|
|
5
7
|
import logging
|
|
6
8
|
import os
|
|
7
9
|
import tempfile
|
|
@@ -34,6 +36,8 @@ Args:
|
|
|
34
36
|
values are header content. None when not using the HttpDownloader or sublclass.
|
|
35
37
|
"""
|
|
36
38
|
|
|
39
|
+
THREADPOOL = ThreadPoolExecutor()
|
|
40
|
+
|
|
37
41
|
|
|
38
42
|
class BaseDownloader:
|
|
39
43
|
"""
|
|
@@ -200,8 +204,11 @@ class BaseDownloader:
|
|
|
200
204
|
Args:
|
|
201
205
|
data (bytes): The data to have its size and digest values recorded.
|
|
202
206
|
"""
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
global THREADPOOL
|
|
208
|
+
futures = [
|
|
209
|
+
THREADPOOL.submit(algorithm.update, data) for algorithm in self._digests.values()
|
|
210
|
+
]
|
|
211
|
+
concurrent.futures.wait(futures, timeout=None, return_when=ALL_COMPLETED)
|
|
205
212
|
self._size += len(data)
|
|
206
213
|
|
|
207
214
|
@property
|
pulpcore/middleware.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import time
|
|
2
|
+
from contextvars import ContextVar
|
|
2
3
|
|
|
3
4
|
from django.http.response import Http404
|
|
4
5
|
from django.conf import settings
|
|
@@ -13,6 +14,8 @@ from pulpcore.app.util import (
|
|
|
13
14
|
set_domain,
|
|
14
15
|
)
|
|
15
16
|
|
|
17
|
+
x_task_diagnostics_var = ContextVar("x_profile_task")
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
class DomainMiddleware:
|
|
18
21
|
"""
|
|
@@ -143,3 +146,25 @@ class DjangoMetricsMiddleware:
|
|
|
143
146
|
match = getattr(request, "resolver_match", "")
|
|
144
147
|
route = getattr(match, "route", "")
|
|
145
148
|
return route
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class TaskProfilerMiddleware:
|
|
152
|
+
"""
|
|
153
|
+
Middleware that looks for the presence of X-TASK-DIAGNOSTICS header and provides its value
|
|
154
|
+
as a ContextVar to the dispatch() method in the tasking system. It enables generating
|
|
155
|
+
profiling data of tasks dispatched via API.
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
def __init__(self, get_response):
|
|
159
|
+
self.get_response = get_response
|
|
160
|
+
|
|
161
|
+
def __call__(self, request):
|
|
162
|
+
if "HTTP_X_TASK_DIAGNOSTICS" in request.META:
|
|
163
|
+
task_diagnostics = request.META["HTTP_X_TASK_DIAGNOSTICS"]
|
|
164
|
+
ctx_token = x_task_diagnostics_var.set(task_diagnostics.split(","))
|
|
165
|
+
try:
|
|
166
|
+
return self.get_response(request)
|
|
167
|
+
finally:
|
|
168
|
+
x_task_diagnostics_var.reset(ctx_token)
|
|
169
|
+
else:
|
|
170
|
+
return self.get_response(request)
|
pulpcore/openapi/__init__.py
CHANGED
|
@@ -201,6 +201,19 @@ class PulpAutoSchema(AutoSchema):
|
|
|
201
201
|
name = name + "Response"
|
|
202
202
|
return name
|
|
203
203
|
|
|
204
|
+
def get_override_parameters(self):
|
|
205
|
+
parameters = super().get_override_parameters()
|
|
206
|
+
parameters.append(
|
|
207
|
+
OpenApiParameter(
|
|
208
|
+
name="X-Task-Diagnostics",
|
|
209
|
+
location=OpenApiParameter.HEADER,
|
|
210
|
+
required=False,
|
|
211
|
+
type={"type": "array", "items": {"type": "string"}},
|
|
212
|
+
description="List of profilers to use on tasks.",
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
return parameters
|
|
216
|
+
|
|
204
217
|
def map_parsers(self):
|
|
205
218
|
"""
|
|
206
219
|
Get request parsers.
|
pulpcore/tasking/_util.py
CHANGED
|
@@ -127,21 +127,26 @@ def perform_task(task_pk, task_working_dir_rel_path):
|
|
|
127
127
|
set_domain(task.pulp_domain)
|
|
128
128
|
os.chdir(task_working_dir_rel_path)
|
|
129
129
|
|
|
130
|
-
if
|
|
131
|
-
|
|
130
|
+
if task.profile_options:
|
|
131
|
+
profilers = set(task.profile_options) & set(settings.TASK_DIAGNOSTICS)
|
|
132
|
+
if unavailable_profilers := set(task.profile_options) - set(settings.TASK_DIAGNOSTICS):
|
|
133
|
+
_logger.warning(
|
|
134
|
+
"Requested task diagnostic profilers are not available: %s", unavailable_profilers
|
|
135
|
+
)
|
|
136
|
+
_execute_task_and_profile(task, profilers)
|
|
132
137
|
else:
|
|
133
138
|
execute_task(task)
|
|
134
139
|
|
|
135
140
|
|
|
136
|
-
def _execute_task_and_profile(task):
|
|
141
|
+
def _execute_task_and_profile(task, profile_options):
|
|
137
142
|
with tempfile.TemporaryDirectory(dir=settings.WORKING_DIRECTORY) as temp_dir:
|
|
138
143
|
_execute_task = execute_task
|
|
139
144
|
|
|
140
|
-
if
|
|
145
|
+
if "memory" in profile_options:
|
|
141
146
|
_execute_task = _memory_diagnostic_decorator(temp_dir, _execute_task)
|
|
142
|
-
if
|
|
147
|
+
if "pyinstrument" in profile_options:
|
|
143
148
|
_execute_task = _pyinstrument_diagnostic_decorator(temp_dir, _execute_task)
|
|
144
|
-
if
|
|
149
|
+
if "memray" in profile_options:
|
|
145
150
|
_execute_task = _memray_diagnostic_decorator(temp_dir, _execute_task)
|
|
146
151
|
|
|
147
152
|
_execute_task(task)
|
pulpcore/tasking/tasks.py
CHANGED
|
@@ -26,6 +26,7 @@ from pulpcore.constants import (
|
|
|
26
26
|
TASK_DISPATCH_LOCK,
|
|
27
27
|
IMMEDIATE_TIMEOUT,
|
|
28
28
|
)
|
|
29
|
+
from pulpcore.middleware import x_task_diagnostics_var
|
|
29
30
|
from pulpcore.tasking.kafka import send_task_notification
|
|
30
31
|
|
|
31
32
|
_logger = logging.getLogger(__name__)
|
|
@@ -246,6 +247,7 @@ def dispatch(
|
|
|
246
247
|
versions=versions,
|
|
247
248
|
immediate=immediate,
|
|
248
249
|
deferred=deferred,
|
|
250
|
+
profile_options=x_task_diagnostics_var.get(None),
|
|
249
251
|
)
|
|
250
252
|
if newest_created and task.pulp_created <= newest_created:
|
|
251
253
|
# Let this workaround not row forever into the future.
|
|
@@ -33,6 +33,25 @@ def test_retrieving_task_profile_artifacts(gen_user, pulpcore_bindings, task):
|
|
|
33
33
|
assert pulpcore_bindings.TasksApi.profile_artifacts(task.pulp_href).urls is not None
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
@pytest.mark.parallel
|
|
37
|
+
def test_profiling_task_using_header(gen_user, pulpcore_bindings, monitor_task, pulp_settings):
|
|
38
|
+
# Check that no profile artifacts are created by default
|
|
39
|
+
task_href = pulpcore_bindings.OrphansCleanupApi.cleanup({"orphan_protection_time": 10000}).task
|
|
40
|
+
task = monitor_task(task_href)
|
|
41
|
+
assert pulpcore_bindings.TasksApi.profile_artifacts(task.pulp_href).urls == {}
|
|
42
|
+
|
|
43
|
+
# Check that profile artifacts are created when X-TASK-DIAGNOSTICS headers is passed
|
|
44
|
+
task_href = pulpcore_bindings.OrphansCleanupApi.cleanup(
|
|
45
|
+
{"orphan_protection_time": 10000}, x_task_diagnostics=["memory"]
|
|
46
|
+
).task
|
|
47
|
+
task = monitor_task(task_href)
|
|
48
|
+
profile_artifacts_urls = pulpcore_bindings.TasksApi.profile_artifacts(task.pulp_href).urls
|
|
49
|
+
if "memory" in pulp_settings.TASK_DIAGNOSTICS:
|
|
50
|
+
assert "memory_profile" in profile_artifacts_urls
|
|
51
|
+
else:
|
|
52
|
+
assert "memory_profile" not in profile_artifacts_urls
|
|
53
|
+
|
|
54
|
+
|
|
36
55
|
@pytest.mark.parallel
|
|
37
56
|
def test_multi_resource_locking(dispatch_task, monitor_task):
|
|
38
57
|
task_href1 = dispatch_task(
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Tests related to content delivery."""
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
|
+
import requests
|
|
4
5
|
import subprocess
|
|
5
6
|
import uuid
|
|
7
|
+
from random import sample
|
|
6
8
|
from urllib.parse import urljoin
|
|
7
9
|
|
|
8
10
|
import pytest
|
|
@@ -244,3 +246,35 @@ def test_handling_remote_artifact_on_demand_streaming_failure(
|
|
|
244
246
|
# WHEN/THEN (second request)
|
|
245
247
|
actual_checksum = download_from_distribution(content_name, distribution)
|
|
246
248
|
assert actual_checksum == expected_checksum
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@pytest.mark.parallel
|
|
252
|
+
def test_head_request_large_on_demand_file(
|
|
253
|
+
file_repo_with_auto_publish,
|
|
254
|
+
file_remote_factory,
|
|
255
|
+
file_bindings,
|
|
256
|
+
range_header_manifest_path,
|
|
257
|
+
distribution_base_url,
|
|
258
|
+
file_distribution_factory,
|
|
259
|
+
monitor_task,
|
|
260
|
+
):
|
|
261
|
+
"""Test that a HEAD request to a large on-demand file properly saves the file."""
|
|
262
|
+
# range_header_manifest_path has 8 files, each 4MB
|
|
263
|
+
remote = file_remote_factory(manifest_path=range_header_manifest_path, policy="on_demand")
|
|
264
|
+
body = RepositorySyncURL(remote=remote.pulp_href)
|
|
265
|
+
monitor_task(
|
|
266
|
+
file_bindings.RepositoriesFileApi.sync(file_repo_with_auto_publish.pulp_href, body).task
|
|
267
|
+
)
|
|
268
|
+
repo = file_bindings.RepositoriesFileApi.read(file_repo_with_auto_publish.pulp_href)
|
|
269
|
+
content = file_bindings.ContentFilesApi.list(repository_version=repo.latest_version_href)
|
|
270
|
+
content_href_filenames = sample([(c.pulp_href, c.relative_path) for c in content.results], k=3)
|
|
271
|
+
|
|
272
|
+
distro = file_distribution_factory(repository=repo.pulp_href)
|
|
273
|
+
for _, content_filename in content_href_filenames:
|
|
274
|
+
url = urljoin(distribution_base_url(distro.base_url), content_filename)
|
|
275
|
+
response = requests.head(url)
|
|
276
|
+
assert response.status_code == 200
|
|
277
|
+
# Give some time for the file to be saved
|
|
278
|
+
for content_href, _ in content_href_filenames:
|
|
279
|
+
content = file_bindings.ContentFilesApi.read(content_href)
|
|
280
|
+
assert content.artifact is not None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pulpcore
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.82.0
|
|
4
4
|
Summary: Pulp Django Application and Related Modules
|
|
5
5
|
Author-email: Pulp Team <pulp-list@redhat.com>
|
|
6
6
|
Project-URL: Homepage, https://pulpproject.org
|
|
@@ -21,17 +21,17 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
21
21
|
Requires-Python: >=3.9
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE
|
|
24
|
-
Requires-Dist: aiodns
|
|
25
|
-
Requires-Dist: aiofiles
|
|
26
|
-
Requires-Dist: aiohttp<3.
|
|
24
|
+
Requires-Dist: aiodns<3.6,>=3.3.0
|
|
25
|
+
Requires-Dist: aiofiles<=24.1.0,>=22.1
|
|
26
|
+
Requires-Dist: aiohttp<3.13,>=3.8.3
|
|
27
27
|
Requires-Dist: asyncio-throttle<=1.0.2,>=1.0
|
|
28
28
|
Requires-Dist: async-timeout<4.0.4,>=4.0.3; python_version < "3.11"
|
|
29
|
-
Requires-Dist: backoff<2.
|
|
30
|
-
Requires-Dist: click
|
|
31
|
-
Requires-Dist: cryptography<
|
|
29
|
+
Requires-Dist: backoff<2.3,>=2.1.2
|
|
30
|
+
Requires-Dist: click<8.2,>=8.1.0
|
|
31
|
+
Requires-Dist: cryptography<46.0,>=38.0.1
|
|
32
32
|
Requires-Dist: Django~=4.2.0
|
|
33
33
|
Requires-Dist: django-filter<=25.1,>=23.1
|
|
34
|
-
Requires-Dist: django-guid
|
|
34
|
+
Requires-Dist: django-guid<3.6,>=3.3.0
|
|
35
35
|
Requires-Dist: django-import-export<3.4.0,>=2.9
|
|
36
36
|
Requires-Dist: django-lifecycle<=1.2.4,>=1.0
|
|
37
37
|
Requires-Dist: djangorestframework<=3.16.0,>=3.14.0
|
|
@@ -40,28 +40,28 @@ Requires-Dist: drf-access-policy<1.5.1,>=1.1.2
|
|
|
40
40
|
Requires-Dist: drf-nested-routers<=0.94.2,>=0.93.4
|
|
41
41
|
Requires-Dist: drf-spectacular==0.27.2
|
|
42
42
|
Requires-Dist: dynaconf<3.3.0,>=3.2.5
|
|
43
|
-
Requires-Dist: gunicorn<23.1.0,>=
|
|
43
|
+
Requires-Dist: gunicorn<23.1.0,>=22.0
|
|
44
44
|
Requires-Dist: importlib-metadata<=6.0.1,>=6.0.1
|
|
45
45
|
Requires-Dist: jinja2<=3.1.6,>=3.1
|
|
46
46
|
Requires-Dist: json_stream<2.4,>=2.3.2
|
|
47
|
-
Requires-Dist: jq<1.
|
|
47
|
+
Requires-Dist: jq<1.10.0,>=1.6.0
|
|
48
48
|
Requires-Dist: PyOpenSSL<26.0
|
|
49
|
-
Requires-Dist: opentelemetry-api<1.
|
|
50
|
-
Requires-Dist: opentelemetry-sdk<1.
|
|
51
|
-
Requires-Dist: opentelemetry-exporter-otlp-proto-http<1.
|
|
49
|
+
Requires-Dist: opentelemetry-api<1.35,>=1.27.0
|
|
50
|
+
Requires-Dist: opentelemetry-sdk<1.35,>=1.27.0
|
|
51
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http<1.35,>=1.27.0
|
|
52
52
|
Requires-Dist: protobuf<6.0,>=4.21.1
|
|
53
|
-
Requires-Dist: pulp-glue<0.
|
|
53
|
+
Requires-Dist: pulp-glue<0.34,>=0.28.0
|
|
54
54
|
Requires-Dist: pygtrie<=2.5.0,>=2.5
|
|
55
55
|
Requires-Dist: psycopg[binary]<3.3,>=3.1.8
|
|
56
|
-
Requires-Dist: pyparsing
|
|
56
|
+
Requires-Dist: pyparsing<3.3,>=3.1.0
|
|
57
57
|
Requires-Dist: python-gnupg<=0.5.4,>=0.5
|
|
58
|
-
Requires-Dist: PyYAML
|
|
59
|
-
Requires-Dist: redis<5.
|
|
60
|
-
Requires-Dist: tablib<3.6.0
|
|
61
|
-
Requires-Dist: url-normalize
|
|
62
|
-
Requires-Dist: uuid6<=
|
|
58
|
+
Requires-Dist: PyYAML<6.1,>=5.1.1
|
|
59
|
+
Requires-Dist: redis<5.3,>=4.3.0
|
|
60
|
+
Requires-Dist: tablib<3.6,>=3.5.0
|
|
61
|
+
Requires-Dist: url-normalize<2.3,>=1.4.3
|
|
62
|
+
Requires-Dist: uuid6<=2025.0.0,>=2023.5.2
|
|
63
63
|
Requires-Dist: whitenoise<6.10.0,>=5.0
|
|
64
|
-
Requires-Dist: yarl<1.
|
|
64
|
+
Requires-Dist: yarl<1.21,>=1.8
|
|
65
65
|
Provides-Extra: sftp
|
|
66
66
|
Requires-Dist: django-storages[sftp]==1.14.6; extra == "sftp"
|
|
67
67
|
Provides-Extra: s3
|
|
@@ -74,7 +74,7 @@ Provides-Extra: prometheus
|
|
|
74
74
|
Requires-Dist: django-prometheus; extra == "prometheus"
|
|
75
75
|
Provides-Extra: kafka
|
|
76
76
|
Requires-Dist: cloudevents==1.11.0; extra == "kafka"
|
|
77
|
-
Requires-Dist: confluent-kafka<2.
|
|
77
|
+
Requires-Dist: confluent-kafka<2.11.0,>=2.4.0; extra == "kafka"
|
|
78
78
|
Provides-Extra: diagnostics
|
|
79
79
|
Requires-Dist: pyinstrument~=5.0; extra == "diagnostics"
|
|
80
80
|
Requires-Dist: memray~=1.17; extra == "diagnostics"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
pulp_certguard/__init__.py,sha256=llnEd00PrsAretsgAOHiNKFbmvIdXe3iDVPmSaKz7gU,71
|
|
2
2
|
pulp_certguard/pytest_plugin.py,sha256=qhRbChzqN2PROtD-65KuoTfKr5k9T3GPsz9daFgpqpM,852
|
|
3
|
-
pulp_certguard/app/__init__.py,sha256=
|
|
3
|
+
pulp_certguard/app/__init__.py,sha256=asgxMyJ-_usTvtv9VipyiO0urYAshXR_2kfO8CtupGw,297
|
|
4
4
|
pulp_certguard/app/models.py,sha256=xy5IWxf0LQxayIDmQw25Y2YhB_NrlTGvuvdY-YW7QBU,8119
|
|
5
5
|
pulp_certguard/app/serializers.py,sha256=3jxWu82vU3xA578Qbyz-G4Q9Zlh3MFLGRHzX62M0RF8,1826
|
|
6
6
|
pulp_certguard/app/utils.py,sha256=O6T1Npdb8fu3XqIkDJd8PQdEFJWPUeQ-i_aHXBl7MEc,816
|
|
@@ -48,8 +48,8 @@ pulp_certguard/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
48
48
|
pulp_certguard/tests/unit/test_models.py,sha256=TBI0yKsrdbnJSPeBFfxSqhXK7zaNvR6qg5JehGH3Pds,229
|
|
49
49
|
pulp_file/__init__.py,sha256=0vOCXofR6Eyxkg4y66esnOGPeESCe23C1cNBHj56w44,61
|
|
50
50
|
pulp_file/manifest.py,sha256=1WwIOJrPSkFcmkRm7CkWifVOCoZvo_nnANgce6uuG7U,3796
|
|
51
|
-
pulp_file/pytest_plugin.py,sha256=
|
|
52
|
-
pulp_file/app/__init__.py,sha256=
|
|
51
|
+
pulp_file/pytest_plugin.py,sha256=l1PvTxUi5D3uJy4SnHWNhr-otWEYNcm-kc5nSqVJg0Y,10646
|
|
52
|
+
pulp_file/app/__init__.py,sha256=H2wrrNOzI22OucPfAe9Od3DtsHVRpfwIA0kcylz6Efc,292
|
|
53
53
|
pulp_file/app/modelresource.py,sha256=v-m-_bBEsfr8wG0TI5ffx1TuKUy2-PsirhuQz4XXF-0,1063
|
|
54
54
|
pulp_file/app/models.py,sha256=QsrVg_2uKqnR89sLN2Y7Zy260_nLIcUfa94uZowlmFw,4571
|
|
55
55
|
pulp_file/app/replica.py,sha256=OtNWVmdFUgNTYhPttftVNQnSrnvx2_hnrJgtW_G0Vrg,1894
|
|
@@ -82,7 +82,7 @@ pulp_file/tests/functional/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
|
82
82
|
pulp_file/tests/functional/api/__init__.py,sha256=IxizGLz9A_3Sh2ZGHpRlqMyZ1gIVAepBpJB474OJefE,62
|
|
83
83
|
pulp_file/tests/functional/api/test_acs.py,sha256=L9MuroKKGSuxe2SzmHWCTeUUe3WSClKSn5UBiedViPg,9277
|
|
84
84
|
pulp_file/tests/functional/api/test_auto_publish.py,sha256=GGcXqIZhANsMd5R2MYNtjCsqp1vHT6q13AoEv-3dBE0,4514
|
|
85
|
-
pulp_file/tests/functional/api/test_bad_sync.py,sha256=
|
|
85
|
+
pulp_file/tests/functional/api/test_bad_sync.py,sha256=IKdMNDL3jRDA2SiaVsJHFU7PWCIBa-kpKM-ILNTKPaw,4448
|
|
86
86
|
pulp_file/tests/functional/api/test_content_labels.py,sha256=9jvG3SPQ_40OrdgEu7xHQYmNNmqWseGoTHITe6OsWLw,6798
|
|
87
87
|
pulp_file/tests/functional/api/test_crud_content_unit.py,sha256=YUug-4ZCADnxYUj3aB8e8lyJ7_rrXPPfRcXW3IlBKI8,14772
|
|
88
88
|
pulp_file/tests/functional/api/test_crud_remotes.py,sha256=ukQOUGssEiwYNm7A8ti5b_cv91eec8FsbGghCNgNXhs,3459
|
|
@@ -104,31 +104,32 @@ pulpcore/backends.py,sha256=Ax_MJpbvtNDg_rhkHaiQRm39DBSS2dH8UpMRJN2T0oE,4482
|
|
|
104
104
|
pulpcore/constants.py,sha256=06lih8sVRzHCrBXGmoT3Q-9ZkKZUEEYZ8EoeFfxEq04,4673
|
|
105
105
|
pulpcore/filters.py,sha256=dD5oRRkWg65s3LoObr-ipRvRsxZK_3Zr0lKMNr9Sg5o,16682
|
|
106
106
|
pulpcore/metrics.py,sha256=Mfq-nnRjRf3vBHFO-ux-4d1I3yE7TgeptwgiSgGz4rA,2230
|
|
107
|
-
pulpcore/middleware.py,sha256=
|
|
107
|
+
pulpcore/middleware.py,sha256=10Jxc4Iq03gZD3n39t63OmBCpdftcke8bxEd-LioJlA,5973
|
|
108
108
|
pulpcore/migrations.py,sha256=gzUTxcXnbYkM0_vN8Rfr_XWuwsGWedVZAwNy9JqJ8sQ,2476
|
|
109
109
|
pulpcore/pytest_plugin.py,sha256=skubiEUIevVURr4LnmmVMt_ZeH5vT9mI0yiPUYerMnQ,38090
|
|
110
110
|
pulpcore/responses.py,sha256=mIGKmdCfTSoZxbFu4yIH1xbdLx1u5gqt3D99LTamcJg,6125
|
|
111
111
|
pulpcore/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
112
|
pulpcore/app/access_policy.py,sha256=5vCKy6WoHtIt1_-eS5vMaZ7CmR4G-CIpsrB8yT-d88Q,6079
|
|
113
|
-
pulpcore/app/apps.py,sha256=
|
|
113
|
+
pulpcore/app/apps.py,sha256=0CaBE8E7gFLpu-mv5pv13EjHBBNa7Tj3r9oNT5Tiw8Y,17860
|
|
114
114
|
pulpcore/app/authentication.py,sha256=1LIJW6HIQQlZrliHy__jdzkDEh6Oj7xKgd0V-vRcDus,2855
|
|
115
115
|
pulpcore/app/checks.py,sha256=jbfTF7nmftBbky4AQXHigpyCaGydKasvRUXsd72JZVg,1946
|
|
116
|
-
pulpcore/app/entrypoint.py,sha256=
|
|
117
|
-
pulpcore/app/files.py,sha256=
|
|
116
|
+
pulpcore/app/entrypoint.py,sha256=YIfQpM5UxybBTasiEY5ptq--UmqPqjdIGnwmqVsDC7E,4972
|
|
117
|
+
pulpcore/app/files.py,sha256=BHq2T6cizPXfepQuEw_RfPXBqzcDRRVK3sedGDrgSJ4,6315
|
|
118
118
|
pulpcore/app/global_access_conditions.py,sha256=Jezc1Hf0bQFaZvZFEDPpBrJmK0EvIa6zHRHHZYkez2Y,30398
|
|
119
119
|
pulpcore/app/importexport.py,sha256=x1gGrHgirfMLsv92GEwBIQe12aItJJW9JH8TPij-rms,8795
|
|
120
120
|
pulpcore/app/loggers.py,sha256=7tteVBBIf4W7jk4tB7QNpFGjCZueDDrPAavHj46LdJI,79
|
|
121
121
|
pulpcore/app/manage.py,sha256=5YGD5ly3dJcLjX4jKIo3BBPFi_aqEPqi-CCoogV8lm8,286
|
|
122
122
|
pulpcore/app/mime_types.py,sha256=xQh9gd5jHKxS0RrYqUjg98pST-Cyfcrk_Et1l2eby_w,6706
|
|
123
123
|
pulpcore/app/modelresource.py,sha256=SlnKD_K-ZFtR5Gt8hpoF5odEX2y-1v2bb6UkJcOqnd8,4847
|
|
124
|
+
pulpcore/app/netutil.py,sha256=qO99WtWPLjAKPh_APw92Y3mUtxPH91NfeRuWLii1MLA,412
|
|
124
125
|
pulpcore/app/openpgp.py,sha256=MYwCTGz7J9-Zr5aSBrz7KGWWWNC1EI-aItGb5dr7XPE,17246
|
|
125
126
|
pulpcore/app/pulp_hashlib.py,sha256=NoVCO8duLz9rggPcilg0smi6fTDnsn-zS9dXgO831Pg,1327
|
|
126
127
|
pulpcore/app/pulpcore_gunicorn_application.py,sha256=caqbDg9dhzECbx9Ss76biuEARhquj9gQaSL6v3XLy2w,2612
|
|
127
128
|
pulpcore/app/redis_connection.py,sha256=VTdG0ulXuyESjYV6SJdG_jLzkLZH-MlLcD6pielwRSk,952
|
|
128
|
-
pulpcore/app/replica.py,sha256=
|
|
129
|
+
pulpcore/app/replica.py,sha256=rGE14OBaR_FKxmHL7NMxf_OizMyS-90IPsMRo_j9YRI,11474
|
|
129
130
|
pulpcore/app/response.py,sha256=hYH_jSBrxmRsBr2bknmXE1qfs2g8JjDTXYcQ5ZWlF_c,1950
|
|
130
131
|
pulpcore/app/role_util.py,sha256=84HSt8_9fxB--dtfSyg_TumVgOdyBbyP6rBaiAfTpOU,22393
|
|
131
|
-
pulpcore/app/settings.py,sha256=
|
|
132
|
+
pulpcore/app/settings.py,sha256=HxZj3R15UG_AhwhNIs1VFXZqPuBHW3shjHkPwqvZMqo,22548
|
|
132
133
|
pulpcore/app/urls.py,sha256=0gdI74CAdycJStXSw1gknviDGe3J3k0UhS4J8RYa5dg,8120
|
|
133
134
|
pulpcore/app/util.py,sha256=nYF6nZXgqVk4U1QeZEpWYX-wqitGSGAJip6W78IfXUk,24432
|
|
134
135
|
pulpcore/app/wsgi.py,sha256=7rpZ_1NHEN_UfeNZCj8206bas1WeqRkHnGdxpd7rdDI,492
|
|
@@ -283,6 +284,7 @@ pulpcore/app/migrations/0129_content_pulp_labels.py,sha256=3Ee8lpGfo02t-1tnOH1CJ
|
|
|
283
284
|
pulpcore/app/migrations/0130_upstreampulp_policy.py,sha256=PLpgBU6iXTl7gruCe12aA5Zk4eG6heyrC6Rh1jeaxps,709
|
|
284
285
|
pulpcore/app/migrations/0131_distribution_checkpoint_publication_checkpoint.py,sha256=MXZXQapnSXVfV9FFiIaoMb6M7qAnAJwtEmN6hSlJ8RQ,561
|
|
285
286
|
pulpcore/app/migrations/0132_alter_content_options.py,sha256=hrhUTsRqQJgwC6wU9Ys5AvyVz2YCzklj2OuVf6hyBfs,477
|
|
287
|
+
pulpcore/app/migrations/0132_task_profile_options.py,sha256=ljdIm5-NXl_8s87HzkthvUxr7eHhLaETrr5qNtAVKDE,518
|
|
286
288
|
pulpcore/app/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
287
289
|
pulpcore/app/models/__init__.py,sha256=9JKMGKbEV6nJPep_K36rnWnS1QWMKBFSty-Hkr65JVk,3459
|
|
288
290
|
pulpcore/app/models/access_policy.py,sha256=o4L41RGoZ5UMmh5UeeenmadD5MJgShguphgd4eAVxQA,6071
|
|
@@ -292,7 +294,7 @@ pulpcore/app/models/base.py,sha256=YbbH4LEEKIlFOWX_73bsYFlum8eOPmxHkESuKQTIapY,9
|
|
|
292
294
|
pulpcore/app/models/content.py,sha256=8NE__k2suNvI1L9eNeWvIqB6i_fmpBHRJEt_B50S1zc,35713
|
|
293
295
|
pulpcore/app/models/domain.py,sha256=c9EUAKPEKKpeNxwDGhdw6UyD5cyZGrIA3qzjsN-RIc0,3685
|
|
294
296
|
pulpcore/app/models/exporter.py,sha256=rAa-abuyJqV-o1BNaoSxrYlxoUGBMqZQ0laMCVou84w,4325
|
|
295
|
-
pulpcore/app/models/fields.py,sha256=
|
|
297
|
+
pulpcore/app/models/fields.py,sha256=NJMASz5iQc95GSqzWFiWqsJhdaLM75udfci3IptvTlY,6451
|
|
296
298
|
pulpcore/app/models/generic.py,sha256=PWeVttDRysgy9aReSkJ0TUORwyTf1-lE68fp8wMGhik,962
|
|
297
299
|
pulpcore/app/models/importer.py,sha256=HECnV3oAPSAgFugYE72RNvh5l1wUs_S69NL80BMp0uc,3082
|
|
298
300
|
pulpcore/app/models/openpgp.py,sha256=3R5p8ZBPq63NzaE2_EwCXEMYPUQu7QUWanMcKCOoWkM,7874
|
|
@@ -303,7 +305,7 @@ pulpcore/app/models/repository.py,sha256=xBMKsryirkpZyrQHnFbwolNbvyX1jHljcqC1ofv
|
|
|
303
305
|
pulpcore/app/models/role.py,sha256=dZklNd2VeAw4cT6dyJ7SyTBt9sZvdqakY86wXGAY3vU,3287
|
|
304
306
|
pulpcore/app/models/status.py,sha256=72oUOJ7BnCAw3uDbc-XuI72oAyP2llCoBic4zb2JP78,3683
|
|
305
307
|
pulpcore/app/models/storage.py,sha256=2b-DQWaO31NqjV6FiISALegND-sQZAU7BVAsduUvm3o,6780
|
|
306
|
-
pulpcore/app/models/task.py,sha256=
|
|
308
|
+
pulpcore/app/models/task.py,sha256=2w0fXHeErSrVssCfP8LeUuYjKgupAbhfR_IkWG8wmus,14950
|
|
307
309
|
pulpcore/app/models/upload.py,sha256=3njXT2rrVJwBjEDegvqcLD9_7cPnnl974lhbAhikEp8,3004
|
|
308
310
|
pulpcore/app/protobuf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
309
311
|
pulpcore/app/protobuf/analytics_pb2.py,sha256=-4CkbSW8JUAEIjZJBTPAJ5QezFJOdCPiDhx8_KA1bMU,2168
|
|
@@ -311,15 +313,15 @@ pulpcore/app/serializers/__init__.py,sha256=M1g5Si6hRi1flhQ-F1n6G-uFEzIZ7BUqHZ8i
|
|
|
311
313
|
pulpcore/app/serializers/access_policy.py,sha256=NNtuzDW5H4RGfy5LbRFEHWDTDzXdL-Kihe9uquXnxBU,2818
|
|
312
314
|
pulpcore/app/serializers/acs.py,sha256=wBbGE5YHR7dJWuicbDtiPQUJ7xEgz1zKHGkJEaMfpDU,5834
|
|
313
315
|
pulpcore/app/serializers/base.py,sha256=ojWmsr2U2Mx8qpSFxqHLNQyfU2Z9q7hY1NUwVs9s3HE,21418
|
|
314
|
-
pulpcore/app/serializers/content.py,sha256=
|
|
315
|
-
pulpcore/app/serializers/domain.py,sha256
|
|
316
|
+
pulpcore/app/serializers/content.py,sha256=TKEh774Q-0l1AfUeMmVxPM5lk5UiYZxgkt9NU1RjZ9M,11966
|
|
317
|
+
pulpcore/app/serializers/domain.py,sha256=y2qXdf2gSvWH5UtYULhX390u6wWmegg-GD9g5QwqZJA,22758
|
|
316
318
|
pulpcore/app/serializers/exporter.py,sha256=TxAgHDt34YUGPusawn7B8HL3bBymp46__6CnfhXSgGs,11179
|
|
317
|
-
pulpcore/app/serializers/fields.py,sha256=
|
|
319
|
+
pulpcore/app/serializers/fields.py,sha256=kWA6wYNA8dYmDJfFE_3eVUQRj4vCceqjzYPEEP53rxA,16481
|
|
318
320
|
pulpcore/app/serializers/importer.py,sha256=PVSNs5U0dfAm-XlRKpMqOXK0VmUErxJauNJCNro6ONA,8200
|
|
319
321
|
pulpcore/app/serializers/openpgp.py,sha256=3Svxskj_-HmOVbjay7QI82zXnKTsbtaSlZZ03CoT-MQ,8966
|
|
320
322
|
pulpcore/app/serializers/orphans.py,sha256=Vhyaj0fqYT4pkiYoNjgmsy1u5BiR_aHwZm2y7rk9cbk,1967
|
|
321
323
|
pulpcore/app/serializers/progress.py,sha256=j4IQDLb_XOrLzTud4Fq8T-8kkOqLewReMVkbS5uCEIg,2575
|
|
322
|
-
pulpcore/app/serializers/publication.py,sha256=
|
|
324
|
+
pulpcore/app/serializers/publication.py,sha256=Qg9ZbvyyS4VoYqLSVXdJ3ceTUP2IAJQgY-K9sJJcXNc,16502
|
|
323
325
|
pulpcore/app/serializers/purge.py,sha256=CnjKWUvkuI207QMbqwmNs7FqMdOMUh1cujagby3vVM0,779
|
|
324
326
|
pulpcore/app/serializers/reclaim.py,sha256=-ewdNqu-Ck1B_IUWJHG0pvN5zCMMEK9RiWI45g7D0ro,1710
|
|
325
327
|
pulpcore/app/serializers/repair.py,sha256=uKrxTnhoarxyyGCixPRn9pmG19gRRVUTM7nPwCVp6_8,554
|
|
@@ -371,13 +373,13 @@ pulpcore/app/viewsets/upload.py,sha256=Mfy9Vcm5KcqARooH4iExzoXVkL6boDddEqAnGWDWz
|
|
|
371
373
|
pulpcore/app/viewsets/user.py,sha256=86eMawpaVrvp6ilQmb1C4j7SKpesPB5HgMovYL9rY3Q,13813
|
|
372
374
|
pulpcore/cache/__init__.py,sha256=GkYD4PgIMaVL83ywfAsLBC9JNNDUpmTtbitW9zZSslk,131
|
|
373
375
|
pulpcore/cache/cache.py,sha256=d8GMlvjeGG9MOMdi5_9029WpGCKH8Y5q9b2lt3wSREo,17371
|
|
374
|
-
pulpcore/content/__init__.py,sha256=
|
|
376
|
+
pulpcore/content/__init__.py,sha256=lJDgxeIHXI__7LOQciRQSTItebgsxpoEGbd19Q7jNdI,4015
|
|
375
377
|
pulpcore/content/authentication.py,sha256=lEZBkXBBBkIdtFMCSpHDD7583M0bO-zsZNYXTmpr4k8,3235
|
|
376
|
-
pulpcore/content/entrypoint.py,sha256=
|
|
377
|
-
pulpcore/content/handler.py,sha256
|
|
378
|
+
pulpcore/content/entrypoint.py,sha256=DiQTQzfcUiuyl37uvy6Wpa_7kr8t79ekpMHr31MDL2s,2132
|
|
379
|
+
pulpcore/content/handler.py,sha256=B0G2MwOtCedMfwFA5qcHsvg884GhsG_xw4ybYAmLthY,56781
|
|
378
380
|
pulpcore/content/instrumentation.py,sha256=H0N0GWzvOPGGjFi6eIbGW3mcvagfnAfazccTh-BZVmE,1426
|
|
379
381
|
pulpcore/download/__init__.py,sha256=s3Wh2GKdsmbUooVIR6wSvhYVIhpaTbtfR3Ar1OJhC7s,154
|
|
380
|
-
pulpcore/download/base.py,sha256=
|
|
382
|
+
pulpcore/download/base.py,sha256=4KCAYnV8jSOX078ETwlfwNZGY3xCBF9yy866tyGKAzE,13095
|
|
381
383
|
pulpcore/download/factory.py,sha256=NQ1c7lqf8cCTZvhBeDaDjCE2qBAvPRzSDbtP2yN8SFk,9679
|
|
382
384
|
pulpcore/download/file.py,sha256=nrPqcqB1k7MOaIhTKB2KS_Vc6O10--c-t1Tgf-Ct8fg,2235
|
|
383
385
|
pulpcore/download/http.py,sha256=EVNlO10sZYzx8GmIg8ulHY-jw1V1sNXgvwS7RrU-VPE,12333
|
|
@@ -385,7 +387,7 @@ pulpcore/exceptions/__init__.py,sha256=ZgqOLvuNEAEPkC8lUVEJIFyUJZJOy94whdzXYoMP2
|
|
|
385
387
|
pulpcore/exceptions/base.py,sha256=3iNTD8BsAfe7vpUaOzXl2f_WJPd4wfqEuf2GkFheBhs,2863
|
|
386
388
|
pulpcore/exceptions/plugin.py,sha256=CrfzjCP1YZk_W6p1yRFrUfqTv0Iptzu2aBxzlebXeLU,613
|
|
387
389
|
pulpcore/exceptions/validation.py,sha256=4iyDMxKzejHIzEuebDRXkvA_GNCdaommW9Ycsaa1v3Y,2481
|
|
388
|
-
pulpcore/openapi/__init__.py,sha256=
|
|
390
|
+
pulpcore/openapi/__init__.py,sha256=8R96t7rvAFgIU_-Bv79X_cW0NV10Au9vHzUmp5jaFpw,18443
|
|
389
391
|
pulpcore/openapi/hooks.py,sha256=uRFFW6khHNrntK6R99SUEDfP4LzmYJfsX7i8XGO4iaI,1426
|
|
390
392
|
pulpcore/plugin/__init__.py,sha256=q0qu_15BTEY_EqPB9DSDk8rdnZMvld3cZsFXEnOVjuo,131
|
|
391
393
|
pulpcore/plugin/access_policy.py,sha256=KHbWBXEOP59V8J_R52Pw2Q_Amodg-1bJYh6tyt5vDgk,4968
|
|
@@ -423,11 +425,11 @@ pulpcore/plugin/stages/models.py,sha256=0b7xs9d64WTG2yHog1Zo_Z_-pomFAe-gC4u9wksY
|
|
|
423
425
|
pulpcore/plugin/viewsets/__init__.py,sha256=G2zE-NRWz6PFYp8OMZrv01RYBQELFWfW702bRvxXs3k,2281
|
|
424
426
|
pulpcore/plugin/viewsets/content.py,sha256=MHvmLOxsKSQfk6y5t1s9CVxkce9YNeU-dYb1Ldyf83I,6432
|
|
425
427
|
pulpcore/tasking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
426
|
-
pulpcore/tasking/_util.py,sha256=
|
|
428
|
+
pulpcore/tasking/_util.py,sha256=fPW4k1nUa_NZ0ywy_A15Fuiejo5stY58abPbZTXw5t8,9904
|
|
427
429
|
pulpcore/tasking/entrypoint.py,sha256=Npnn41e39soGvJ7CTaZXT5MjIhOO7UtQmpmNaZtfKYg,1120
|
|
428
430
|
pulpcore/tasking/kafka.py,sha256=76z4DzeXM1WL5uu1HlKnduWeLO3-b-czvGBXdWR6054,3845
|
|
429
431
|
pulpcore/tasking/storage.py,sha256=zQkwlpC_FDQtmZGZ8vKwHqxvD6CLO_gAS4Q7wijZE-k,3106
|
|
430
|
-
pulpcore/tasking/tasks.py,sha256=
|
|
432
|
+
pulpcore/tasking/tasks.py,sha256=OhiKVl_WKc7m-7V-bWTh9hM3GgQlcnPCIeLw97FXAYM,14448
|
|
431
433
|
pulpcore/tasking/worker.py,sha256=c9RgSYg4J_Jn_q70MVF_2egDeASFgXlLrP00lqWKtnQ,23822
|
|
432
434
|
pulpcore/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
433
435
|
pulpcore/tests/functional/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -454,7 +456,7 @@ pulpcore/tests/functional/api/test_scoping.py,sha256=uiLOsx5_7puRMcvrpPKEYQziqlu
|
|
|
454
456
|
pulpcore/tests/functional/api/test_signing_service.py,sha256=yr1HXBrNoliBHJNAGAN4PAN0eBKPIvAQP-uMoMSrO_I,222
|
|
455
457
|
pulpcore/tests/functional/api/test_status.py,sha256=Vmmj-ueGxJw1JFSQtr5feTM8vjgyyROvxsRm-OgzLUQ,5370
|
|
456
458
|
pulpcore/tests/functional/api/test_task_purge.py,sha256=Av4DrUdCqf-JegfoP1pkY4B-teoUzYd1LBZKAhDa-08,7273
|
|
457
|
-
pulpcore/tests/functional/api/test_tasking.py,sha256=
|
|
459
|
+
pulpcore/tests/functional/api/test_tasking.py,sha256=jozm0Bpv1AavPDSu0QOZMCzre9Zgpw7_M9HCiaoTRmA,22511
|
|
458
460
|
pulpcore/tests/functional/api/test_upload.py,sha256=oLP1ZmQgPzgK5jAQwGeXS8uLFHgAzVeLW0GfANMWexI,6794
|
|
459
461
|
pulpcore/tests/functional/api/test_users_groups.py,sha256=YFG0xtyJuIRraczR7ERl_UNS7dlJfKd2eUmXgD1lLBU,2926
|
|
460
462
|
pulpcore/tests/functional/api/test_workers.py,sha256=u3oQnErjf6qPCg08XMRZzecGetLLDWmvHvoZIk-AUAA,4659
|
|
@@ -462,7 +464,7 @@ pulpcore/tests/functional/api/using_plugin/__init__.py,sha256=QyyfzgjLOi4n32G3o9
|
|
|
462
464
|
pulpcore/tests/functional/api/using_plugin/test_checkpoint.py,sha256=gx1oiHOVUH5QZfF33k_DXSw-AVbYQp39uKii1D96BoI,7965
|
|
463
465
|
pulpcore/tests/functional/api/using_plugin/test_content_access.py,sha256=Ym800bU-M48RCDfQMkVa1UQt_sfgy5ciU0FxorCk9Ds,2551
|
|
464
466
|
pulpcore/tests/functional/api/using_plugin/test_content_cache.py,sha256=OB3gDbPDptQBjyYnr_jHyU9bcI_-ANAoUp9EDiskwug,7312
|
|
465
|
-
pulpcore/tests/functional/api/using_plugin/test_content_delivery.py,sha256=
|
|
467
|
+
pulpcore/tests/functional/api/using_plugin/test_content_delivery.py,sha256=oatcqaiOv7o_BqsgQ3uXCWnY1RWa5cmzUvPBHzJuI8o,11384
|
|
466
468
|
pulpcore/tests/functional/api/using_plugin/test_content_directory.py,sha256=w4uY258etnP8-LbrbZ_EZTolciYTt7cY1HJK9Ll7mS0,1931
|
|
467
469
|
pulpcore/tests/functional/api/using_plugin/test_content_path.py,sha256=fvqeptqo-mrUAiKIjlypuvHG1XsFeKKP81ocTmo4hv0,3334
|
|
468
470
|
pulpcore/tests/functional/api/using_plugin/test_content_promotion.py,sha256=Co4ytrfpzklwgDdEthv45dsmrceRpqIQfLJlZWM6EBY,2388
|
|
@@ -529,9 +531,9 @@ pulpcore/tests/unit/stages/test_artifactdownloader.py,sha256=qB1ANdFmNtUnljg8fCd
|
|
|
529
531
|
pulpcore/tests/unit/stages/test_stages.py,sha256=H1a2BQLjdZlZvcb_qULp62huZ1xy6ItTcthktVyGU0w,4735
|
|
530
532
|
pulpcore/tests/unit/viewsets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
531
533
|
pulpcore/tests/unit/viewsets/test_viewset_base.py,sha256=W9o3V6758bZctR6krMPPQytb0xJuF-jb4uBWTNDoD_U,4837
|
|
532
|
-
pulpcore-3.
|
|
533
|
-
pulpcore-3.
|
|
534
|
-
pulpcore-3.
|
|
535
|
-
pulpcore-3.
|
|
536
|
-
pulpcore-3.
|
|
537
|
-
pulpcore-3.
|
|
534
|
+
pulpcore-3.82.0.dist-info/licenses/LICENSE,sha256=dhnHU8rJXUdAIgIjveSKAyYG_KzN5eVG-bxETIGrNW0,17988
|
|
535
|
+
pulpcore-3.82.0.dist-info/METADATA,sha256=WRDG4YKlKA1AR0LuMwR56Gsp7DRzkbqsXMUcurqx6jI,4320
|
|
536
|
+
pulpcore-3.82.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
537
|
+
pulpcore-3.82.0.dist-info/entry_points.txt,sha256=OZven4wzXzQA5b5q9MpP4HUpIPPQCSvIOvkKtNInrK0,452
|
|
538
|
+
pulpcore-3.82.0.dist-info/top_level.txt,sha256=6h-Lm3FKQSaT_nL1KSxu_hBnzKE15bcvf_BoU-ea4CI,34
|
|
539
|
+
pulpcore-3.82.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|