pulpcore 3.84.0__py3-none-any.whl → 3.85.1__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_certguard/app/models.py +7 -26
- pulp_certguard/app/serializers.py +0 -2
- pulp_certguard/rhsm/__init__.py +4 -0
- pulp_certguard/rhsm/rhsm_check_path.py +198 -0
- pulp_certguard/tests/unit/certdata.py +249 -0
- pulp_certguard/tests/unit/test_rhsm_check_path.py +213 -0
- pulp_file/app/__init__.py +1 -1
- pulp_file/app/migrations/0001_initial_squashed_0016_add_domain.py +0 -20
- pulp_file/app/migrations/0017_alter_filealternatecontentsource_alternatecontentsource_ptr_and_more.py +1 -1
- pulpcore/app/apps.py +2 -12
- pulpcore/app/entrypoint.py +22 -22
- pulpcore/app/migrations/0001_squashed_0090_char_to_text_field.py +0 -95
- pulpcore/app/migrations/0091_systemid.py +1 -1
- pulp_file/app/migrations/0006_delete_filefilesystemexporter.py → pulpcore/app/migrations/0136_delete_basedistribution.py +3 -3
- pulpcore/app/migrations/0137_appstatus.py +33 -0
- pulpcore/app/migrations/0138_vulnerabilityreport.py +33 -0
- pulpcore/app/models/__init__.py +4 -1
- pulpcore/app/models/publication.py +0 -41
- pulpcore/app/models/status.py +145 -0
- pulpcore/app/models/task.py +1 -0
- pulpcore/app/models/vulnerability_report.py +34 -0
- pulpcore/app/serializers/__init__.py +1 -0
- pulpcore/app/serializers/content.py +13 -1
- pulpcore/app/serializers/repository.py +8 -1
- pulpcore/app/serializers/vulnerability_report.py +27 -0
- pulpcore/app/settings.py +14 -47
- pulpcore/app/tasks/__init__.py +2 -0
- pulpcore/app/tasks/vulnerability_report.py +159 -0
- pulpcore/app/viewsets/__init__.py +1 -0
- pulpcore/app/viewsets/vulnerability_report.py +20 -0
- pulpcore/constants.py +4 -0
- pulpcore/content/__init__.py +23 -22
- pulpcore/content/handler.py +5 -2
- pulpcore/migrations.py +37 -11
- pulpcore/openapi/__init__.py +8 -0
- pulpcore/plugin/models/__init__.py +2 -0
- pulpcore/plugin/serializers/__init__.py +2 -0
- pulpcore/plugin/tasking.py +2 -0
- pulpcore/plugin/viewsets/__init__.py +2 -0
- pulpcore/pytest_plugin.py +21 -21
- pulpcore/tasking/worker.py +38 -35
- pulpcore/tests/functional/api/test_auth.py +18 -3
- pulpcore/tests/functional/api/test_openapi_schema.py +32 -15
- pulpcore/tests/functional/api/using_plugin/test_checkpoint.py +23 -1
- pulpcore/tests/functional/api/using_plugin/test_proxy.py +1 -1
- pulpcore/tests/unit/content/test_heartbeat.py +11 -8
- pulpcore/tests/unit/test_vulnerability_report.py +74 -0
- {pulpcore-3.84.0.dist-info → pulpcore-3.85.1.dist-info}/METADATA +12 -17
- {pulpcore-3.84.0.dist-info → pulpcore-3.85.1.dist-info}/RECORD +54 -152
- pulp_certguard/app/utils.py +0 -28
- pulp_certguard/tests/unit/test_models.py +0 -9
- pulp_file/app/migrations/0001_initial.py +0 -59
- pulp_file/app/migrations/0002_file_related_names.py +0 -55
- pulp_file/app/migrations/0003_auto_20191014_1721.py +0 -18
- pulp_file/app/migrations/0004_filefilesystemexporter.py +0 -21
- pulp_file/app/migrations/0005_filerepository.py +0 -24
- pulp_file/app/migrations/0007_filefilesystemexporter.py +0 -25
- pulp_file/app/migrations/0008_add_manifest_field.py +0 -19
- pulp_file/app/migrations/0009_move_data_to_new_master_distribution_model.py +0 -77
- pulp_file/app/migrations/0010_auto_publish.py +0 -23
- pulp_file/app/migrations/0011_fix_auto_publish.py +0 -36
- pulp_file/app/migrations/0012_delete_filefilesystemexporter.py +0 -28
- pulp_file/app/migrations/0013_file_acs.py +0 -24
- pulp_file/app/migrations/0014_new_rbac_permissions.py +0 -33
- pulp_file/app/migrations/0015_allow_null_manifest.py +0 -23
- pulp_file/app/migrations/0016_add_domain.py +0 -25
- pulpcore/app/migrations/0001_initial.py +0 -451
- pulpcore/app/migrations/0002_increase_artifact_size_field.py +0 -18
- pulpcore/app/migrations/0003_remove_upload_completed.py +0 -17
- pulpcore/app/migrations/0004_add_duplicated_reserved_resources.py +0 -45
- pulpcore/app/migrations/0005_progressreport_code.py +0 -19
- pulpcore/app/migrations/0006_repository_plugin_managed.py +0 -18
- pulpcore/app/migrations/0007_delete_progress_proxies.py +0 -19
- pulpcore/app/migrations/0008_published_metadata_as_content.py +0 -44
- pulpcore/app/migrations/0009_remove_task_non_fatal_errors.py +0 -17
- pulpcore/app/migrations/0010_pulp_fields.py +0 -570
- pulpcore/app/migrations/0011_relative_path.py +0 -28
- pulpcore/app/migrations/0012_auto_20191104_2000.py +0 -31
- pulpcore/app/migrations/0013_repository_pulp_type.py +0 -18
- pulpcore/app/migrations/0014_remove_repository_plugin_managed.py +0 -17
- pulpcore/app/migrations/0015_auto_20191112_1426.py +0 -33
- pulpcore/app/migrations/0016_charfield_to_textfield.py +0 -68
- pulpcore/app/migrations/0017_remove_task_parent.py +0 -17
- pulpcore/app/migrations/0018_auto_20191127_2350.py +0 -20
- pulpcore/app/migrations/0019_add_signing_service_model.py +0 -27
- pulpcore/app/migrations/0020_change_publishedartifact_constraints.py +0 -17
- pulpcore/app/migrations/0021_add_signing_service_foreign_key.py +0 -24
- pulpcore/app/migrations/0022_rename_last_version.py +0 -27
- pulpcore/app/migrations/0023_change_exporter_models.py +0 -82
- pulpcore/app/migrations/0024_use_local_storage_for_uploads.py +0 -19
- pulpcore/app/migrations/0025_task_parent_task.py +0 -19
- pulpcore/app/migrations/0026_task_group.py +0 -32
- pulpcore/app/migrations/0027_export_backend.py +0 -31
- pulpcore/app/migrations/0028_import_importer_pulpimporter_pulpimporterrepository.py +0 -85
- pulpcore/app/migrations/0029_export_delete.py +0 -19
- pulpcore/app/migrations/0030_taskgroup_all_tasks_dispatched.py +0 -24
- pulpcore/app/migrations/0031_import_export_validate_params.py +0 -19
- pulpcore/app/migrations/0032_export_to_chunks.py +0 -27
- pulpcore/app/migrations/0033_increase_remote_artifact_size_field.py +0 -18
- pulpcore/app/migrations/0034_groupprogressreport.py +0 -32
- pulpcore/app/migrations/0035_content_upstream_id.py +0 -18
- pulpcore/app/migrations/0036_unprotect_last_export.py +0 -19
- pulpcore/app/migrations/0037_pulptemporaryfile.py +0 -28
- pulpcore/app/migrations/0038_repository_remote.py +0 -19
- pulpcore/app/migrations/0039_change_download_concurrency.py +0 -25
- pulpcore/app/migrations/0040_set_admin_is_staff.py +0 -28
- pulpcore/app/migrations/0041_accesspolicy.py +0 -29
- pulpcore/app/migrations/0042_rbac_for_tasks.py +0 -56
- pulpcore/app/migrations/0043_toc_attribute.py +0 -19
- pulpcore/app/migrations/0044_temp_file_artifact_field.py +0 -20
- pulpcore/app/migrations/0045_accesspolicy_permissions_allow_null.py +0 -19
- pulpcore/app/migrations/0046_task__resource_job_id.py +0 -35
- pulpcore/app/migrations/0047_improve_orphan_cleanup.py +0 -59
- pulpcore/app/migrations/0048_fips_checksums.py +0 -38
- pulpcore/app/migrations/0049_add_file_field_to_uploadchunk.py +0 -24
- pulpcore/app/migrations/0050_namespace_access_policies.py +0 -28
- pulpcore/app/migrations/0051_timeoutfields.py +0 -34
- pulpcore/app/migrations/0052_tasking_logging_cid.py +0 -18
- pulpcore/app/migrations/0053_remote_headers.py +0 -19
- pulpcore/app/migrations/0054_add_public_key.py +0 -104
- pulpcore/app/migrations/0055_label.py +0 -31
- pulpcore/app/migrations/0056_remote_rate_limit.py +0 -18
- pulpcore/app/migrations/0057_add_label_indexes.py +0 -23
- pulpcore/app/migrations/0058_accesspolicy_customized.py +0 -18
- pulpcore/app/migrations/0059_proxy_creds.py +0 -23
- pulpcore/app/migrations/0060_data_migration_proxy_creds.py +0 -45
- pulpcore/app/migrations/0061_call_handle_artifact_checksums_command.py +0 -87
- pulpcore/app/migrations/0062_add_new_distribution_mastermodel.py +0 -36
- pulpcore/app/migrations/0063_repository_retained_versions.py +0 -18
- pulpcore/app/migrations/0064_add_new_style_task_columns.py +0 -109
- pulpcore/app/migrations/0064_repository_user_hidden.py +0 -18
- pulpcore/app/migrations/0065_merge_20210615_1211.py +0 -14
- pulpcore/app/migrations/0066_download_concurrency_and_retry_changes.py +0 -24
- pulpcore/app/migrations/0067_add_protect_to_task_reservation.py +0 -19
- pulpcore/app/migrations/0068_add_timestamp_of_interest.py +0 -23
- pulpcore/app/migrations/0069_update_json_fields.py +0 -63
- pulpcore/app/migrations/0070_rename_retained_versions.py +0 -18
- pulpcore/app/migrations/0071_filesystemexport_filesystemexporter.py +0 -35
- pulpcore/app/migrations/0072_add_method_to_filesystem_exporter.py +0 -18
- pulpcore/app/migrations/0073_encrypt_remote_fields.py +0 -139
- pulpcore/app/migrations/0074_acs.py +0 -47
- pulpcore/app/migrations/0075_rbaccontentguard.py +0 -25
- pulpcore/app/migrations/0076_remove_reserved_resource.py +0 -39
- pulpcore/app/migrations/0077_move_remote_url_credentials.py +0 -41
- pulpcore/app/migrations/0078_grouprole_role_userrole.py +0 -70
- pulpcore/app/migrations/0079_rename_permissions_assignment_accesspolicy_creation_hooks.py +0 -18
- pulpcore/app/migrations/0080_proxy_group_model.py +0 -37
- pulpcore/app/migrations/0081_reapplabel_group_permissions.py +0 -59
- pulpcore/app/migrations/0082_add_manage_roles_permissions.py +0 -17
- pulpcore/app/migrations/0083_alter_group_options.py +0 -17
- pulpcore/app/migrations/0084_alter_rbaccontentguard_options.py +0 -17
- pulpcore/app/migrations/0085_contentredirectcontentguard.py +0 -26
- pulpcore/app/migrations/0086_task_json_fields.py +0 -77
- pulpcore/app/migrations/0087_taskschedule.py +0 -34
- pulpcore/app/migrations/0088_accesspolicy_queryset_scoping.py +0 -18
- pulpcore/app/migrations/0089_alter_contentredirectcontentguard_options.py +0 -17
- pulpcore/app/migrations/0090_char_to_text_field.py +0 -79
- pulpcore/tests/unit/migration/test_0077_move_remote_url_credentials.py +0 -35
- {pulpcore-3.84.0.dist-info → pulpcore-3.85.1.dist-info}/WHEEL +0 -0
- {pulpcore-3.84.0.dist-info → pulpcore-3.85.1.dist-info}/entry_points.txt +0 -0
- {pulpcore-3.84.0.dist-info → pulpcore-3.85.1.dist-info}/licenses/LICENSE +0 -0
- {pulpcore-3.84.0.dist-info → pulpcore-3.85.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
from cryptography import x509
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from . import certdata
|
|
5
|
+
|
|
6
|
+
from pulp_certguard.rhsm import check_path
|
|
7
|
+
from pulp_certguard.rhsm.rhsm_check_path import (
|
|
8
|
+
bitstream,
|
|
9
|
+
Entitlement,
|
|
10
|
+
HuffmannNode,
|
|
11
|
+
cert_version,
|
|
12
|
+
split_count,
|
|
13
|
+
V1_PATH_OID_REGEX,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture(scope="session")
|
|
18
|
+
def ent_v1() -> x509.Certificate:
|
|
19
|
+
return x509.load_pem_x509_certificate(certdata.ENTITLEMENT_CERT_V1_0.encode())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture(scope="session")
|
|
23
|
+
def ent_v3_0() -> x509.Certificate:
|
|
24
|
+
return x509.load_pem_x509_certificate(certdata.ENTITLEMENT_CERT_V3_0.encode())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture(scope="session")
|
|
28
|
+
def ent_v3_2() -> x509.Certificate:
|
|
29
|
+
return x509.load_pem_x509_certificate(certdata.ENTITLEMENT_CERT_V3_2.encode())
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.fixture(scope="session", params=["3.0", "3.2"])
|
|
33
|
+
def ent_v3_version(request: pytest.FixtureRequest) -> str:
|
|
34
|
+
return request.param
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@pytest.fixture(scope="session")
|
|
38
|
+
def ent_v3(ent_v3_version: str) -> x509.Certificate:
|
|
39
|
+
ver = ent_v3_version.replace(".", "_")
|
|
40
|
+
attribute = f"ENTITLEMENT_CERT_V{ver}"
|
|
41
|
+
return x509.load_pem_x509_certificate(getattr(certdata, attribute).encode())
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class TestSplitCount:
|
|
45
|
+
"""
|
|
46
|
+
If the first byte is < 128, that is the count itself.
|
|
47
|
+
Otherwise the 7 lsb describe the number of bytes to combine to the count.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
@pytest.mark.parametrize(
|
|
51
|
+
"header, count",
|
|
52
|
+
[
|
|
53
|
+
pytest.param(b"\x00", 0, id="short zero"),
|
|
54
|
+
pytest.param(b"\x0a", 10, id="short ten"),
|
|
55
|
+
pytest.param(b"\x7f", 127, id="short max"),
|
|
56
|
+
pytest.param(b"\x80", 0, id="zero bytes zero"),
|
|
57
|
+
pytest.param(b"\x81\x00", 0, id="one byte zero"),
|
|
58
|
+
pytest.param(b"\x81\x01", 1, id="one byte one"),
|
|
59
|
+
pytest.param(b"\x81\xff", 255, id="one byte max"),
|
|
60
|
+
pytest.param(b"\x84\x00\x00\x00\x00", 0, id="four bytes zero"),
|
|
61
|
+
pytest.param(b"\x84\x00\x00\x00\x01", 1, id="four bytes one"),
|
|
62
|
+
pytest.param(b"\x84\x00\x00\x01\x00", 256, id="four bytes 256"),
|
|
63
|
+
pytest.param(b"\x84\x00\x00\x01\x04", 260, id="four bytes 260"),
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
def test_returns_count_from(self, header: bytes, count: int) -> None:
|
|
67
|
+
assert split_count(header + b"\xde\xad\xbe\xaf") == (count, b"\xde\xad\xbe\xaf")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class TestBitstream:
|
|
71
|
+
def test_0000_produces_16_false(self) -> None:
|
|
72
|
+
assert list(bitstream(b"\x00\x00")) == [False] * 16
|
|
73
|
+
|
|
74
|
+
def test_0001_produces_15_false_true(self) -> None:
|
|
75
|
+
assert list(bitstream(b"\x00\x01")) == [False] * 15 + [True]
|
|
76
|
+
|
|
77
|
+
def test_fff0_produces_12_true_4_false(self) -> None:
|
|
78
|
+
assert list(bitstream(b"\xff\xf0")) == [True] * 12 + [False] * 4
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_product_certificate_has_subject() -> None:
|
|
82
|
+
cert = x509.load_pem_x509_certificate(certdata.PRODUCT_CERT_V1_0.encode())
|
|
83
|
+
assert cert.subject.rfc4514_string() == "CN=100000000000002"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class TestV1EntitlementCertificate:
|
|
87
|
+
def test_has_subject(self, ent_v1: x509.Certificate) -> None:
|
|
88
|
+
assert ent_v1.subject.rfc4514_string() == "CN=ff80808138574bd20138574d85a50b2f"
|
|
89
|
+
|
|
90
|
+
def test_has_4_paths(self, ent_v1: x509.Certificate) -> None:
|
|
91
|
+
assert (
|
|
92
|
+
len(
|
|
93
|
+
[ext for ext in ent_v1.extensions if V1_PATH_OID_REGEX.match(ext.oid.dotted_string)]
|
|
94
|
+
)
|
|
95
|
+
== 4
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def test_has_version_1_0(self, ent_v1: x509.Certificate) -> None:
|
|
99
|
+
assert cert_version(ent_v1) == "1.0"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class TestV3EntitlementCertificate:
|
|
103
|
+
def test_cert_version(self, ent_v3_version: str, ent_v3: x509.Certificate) -> None:
|
|
104
|
+
assert cert_version(ent_v3) == ent_v3_version
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class TestEntitlement:
|
|
108
|
+
@pytest.fixture(scope="class")
|
|
109
|
+
def entitlement(self, ent_v3: x509.Certificate) -> Entitlement:
|
|
110
|
+
return Entitlement(ent_v3)
|
|
111
|
+
|
|
112
|
+
@pytest.fixture(scope="class")
|
|
113
|
+
def word_tree(self, ent_v3: x509.Certificate) -> "HuffmannNode[str]":
|
|
114
|
+
lex_data, _, _ = Entitlement._split_payload(Entitlement._read_payload(ent_v3))
|
|
115
|
+
return Entitlement._build_word_tree(lex_data)
|
|
116
|
+
|
|
117
|
+
def test_has_node_count_10(self, ent_v3: x509.Certificate) -> None:
|
|
118
|
+
_, node_count, _ = Entitlement._split_payload(Entitlement._read_payload(ent_v3))
|
|
119
|
+
assert node_count == 10
|
|
120
|
+
|
|
121
|
+
def test_00_decodes_to_empty(self, word_tree: "HuffmannNode[str]") -> None:
|
|
122
|
+
assert word_tree.decode(iter([False, False])) == ""
|
|
123
|
+
|
|
124
|
+
def test_100_decodes_to_path(self, word_tree: "HuffmannNode[str]") -> None:
|
|
125
|
+
assert word_tree.decode(iter([True, False, False])) == "path"
|
|
126
|
+
|
|
127
|
+
def test_path_tree_root_contains_foo_and_path(self, entitlement: Entitlement) -> None:
|
|
128
|
+
assert {"foo", "path"} == entitlement._path_tree.keys()
|
|
129
|
+
|
|
130
|
+
def test_path_tree_contains_foo_path_never(self, entitlement: Entitlement) -> None:
|
|
131
|
+
assert entitlement._path_tree["foo"]["path"]["never"] == {}
|
|
132
|
+
|
|
133
|
+
def test_path_tree_contains_foo_path_var_always(self, entitlement: Entitlement) -> None:
|
|
134
|
+
assert entitlement._path_tree["foo"]["path"]["always"]["$releasever"] == {}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class TestCheckPathV1:
|
|
138
|
+
@pytest.mark.parametrize(
|
|
139
|
+
"path",
|
|
140
|
+
(
|
|
141
|
+
"/foo/path/never",
|
|
142
|
+
"/foo/path/never/",
|
|
143
|
+
"//foo/path/never/",
|
|
144
|
+
"/foo/path/never/bar/a/b/c",
|
|
145
|
+
"/foo/path/never/bar//a/b/c",
|
|
146
|
+
"/foo//path/never/bar//a/b/c",
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
def test_matches_foo_path_never(self, ent_v1: x509.Certificate, path: str) -> None:
|
|
150
|
+
assert check_path(ent_v1, path)
|
|
151
|
+
|
|
152
|
+
@pytest.mark.parametrize(
|
|
153
|
+
"path",
|
|
154
|
+
(
|
|
155
|
+
pytest.param("/path/never", id="misses the first part"),
|
|
156
|
+
pytest.param("foo", id="is only the middle part"),
|
|
157
|
+
"/foo",
|
|
158
|
+
"/foo/",
|
|
159
|
+
pytest.param("/foo/path/", id="misses the last part"),
|
|
160
|
+
pytest.param("baz/foo/path/never", id="prepended parts"),
|
|
161
|
+
pytest.param("/path/to//bar/awesomeos", id="substituted an empty string"),
|
|
162
|
+
pytest.param("/path/to/foo/bar/awesomeo", id="misses the last character"),
|
|
163
|
+
pytest.param("/path/to/foo/bar/awesomeos1", id="adds characters at the end"),
|
|
164
|
+
),
|
|
165
|
+
)
|
|
166
|
+
def test_rejects_a_path_that(self, ent_v1: x509.Certificate, path: str) -> None:
|
|
167
|
+
assert not check_path(ent_v1, path)
|
|
168
|
+
|
|
169
|
+
@pytest.mark.parametrize(
|
|
170
|
+
"path",
|
|
171
|
+
(
|
|
172
|
+
"/path/to/foo/bar/awesomeos",
|
|
173
|
+
"/path/to/foo/bar/awesomeos/",
|
|
174
|
+
"/path/to/foo/bar/awesomeos/a/b/c",
|
|
175
|
+
"/path/to//bar/foo/awesomeos",
|
|
176
|
+
),
|
|
177
|
+
)
|
|
178
|
+
def test_matches_path_with_substituted_variables(
|
|
179
|
+
self, ent_v1: x509.Certificate, path: str
|
|
180
|
+
) -> None:
|
|
181
|
+
assert check_path(ent_v1, path)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class TestCheckPathV3:
|
|
185
|
+
@pytest.mark.parametrize(
|
|
186
|
+
"path",
|
|
187
|
+
(
|
|
188
|
+
pytest.param("/foo/path/never", id="exact path without vars"),
|
|
189
|
+
pytest.param("/foo/path/never/a/b/c", id="exact path with extra segments"),
|
|
190
|
+
pytest.param(
|
|
191
|
+
"////foo///path//never///", id="exact path without vars and extra slashes"
|
|
192
|
+
),
|
|
193
|
+
pytest.param("foo/path/always/c-3po", id="exact path with variable"),
|
|
194
|
+
pytest.param("/path/to/awesomeos/x86_64", id="another exact path without vars"),
|
|
195
|
+
pytest.param("/path/to/c-3po/r2-d2/awesomeos", id="another exact path with vars"),
|
|
196
|
+
),
|
|
197
|
+
)
|
|
198
|
+
def test_matches(self, ent_v3: x509.Certificate, path: str) -> None:
|
|
199
|
+
assert check_path(ent_v3, path)
|
|
200
|
+
|
|
201
|
+
@pytest.mark.parametrize(
|
|
202
|
+
"path",
|
|
203
|
+
(
|
|
204
|
+
pytest.param("/a/path/to/wherever", id="lunatic path"),
|
|
205
|
+
pytest.param("", id="empty path"),
|
|
206
|
+
pytest.param("////", id="just slashes"),
|
|
207
|
+
pytest.param("foo", id="to short path"),
|
|
208
|
+
pytest.param("path/never", id="path with front segment missing"),
|
|
209
|
+
pytest.param("content/foo/path/never", id="path with extra front segment"),
|
|
210
|
+
),
|
|
211
|
+
)
|
|
212
|
+
def test_rejects(self, ent_v3: x509.Certificate, path: str) -> None:
|
|
213
|
+
assert not check_path(ent_v3, path)
|
pulp_file/app/__init__.py
CHANGED
|
@@ -7,28 +7,8 @@ import pulpcore.app.util
|
|
|
7
7
|
|
|
8
8
|
class Migration(migrations.Migration):
|
|
9
9
|
|
|
10
|
-
replaces = [
|
|
11
|
-
("file", "0001_initial"),
|
|
12
|
-
("file", "0002_file_related_names"),
|
|
13
|
-
("file", "0003_auto_20191014_1721"),
|
|
14
|
-
("file", "0004_filefilesystemexporter"),
|
|
15
|
-
("file", "0005_filerepository"),
|
|
16
|
-
("file", "0006_delete_filefilesystemexporter"),
|
|
17
|
-
("file", "0007_filefilesystemexporter"),
|
|
18
|
-
("file", "0008_add_manifest_field"),
|
|
19
|
-
("file", "0009_move_data_to_new_master_distribution_model"),
|
|
20
|
-
("file", "0010_auto_publish"),
|
|
21
|
-
("file", "0011_fix_auto_publish"),
|
|
22
|
-
("file", "0012_delete_filefilesystemexporter"),
|
|
23
|
-
("file", "0013_file_acs"),
|
|
24
|
-
("file", "0014_new_rbac_permissions"),
|
|
25
|
-
("file", "0015_allow_null_manifest"),
|
|
26
|
-
("file", "0016_add_domain"),
|
|
27
|
-
]
|
|
28
|
-
|
|
29
10
|
dependencies = [
|
|
30
11
|
("core", "0102_add_domain_relations"),
|
|
31
|
-
("core", "0091_systemid"),
|
|
32
12
|
]
|
|
33
13
|
|
|
34
14
|
operations = [
|
pulpcore/app/apps.py
CHANGED
|
@@ -5,6 +5,7 @@ from gettext import gettext as _
|
|
|
5
5
|
from importlib import import_module
|
|
6
6
|
|
|
7
7
|
from django import apps
|
|
8
|
+
from django.conf import settings
|
|
8
9
|
from django.core.exceptions import ImproperlyConfigured
|
|
9
10
|
from django.db import connection, transaction
|
|
10
11
|
from django.db.models.signals import post_migrate
|
|
@@ -67,15 +68,6 @@ class PulpPluginAppConfig(apps.AppConfig):
|
|
|
67
68
|
|
|
68
69
|
def __init__(self, app_name, app_module):
|
|
69
70
|
super().__init__(app_name, app_module)
|
|
70
|
-
# begin Compatilibity layer for DEFAULT_FILE_STORAGE deprecation
|
|
71
|
-
# Remove on pulpcore=3.85 or pulpcore=4.0
|
|
72
|
-
# * Workaround for getting the up-to-date settings instance, otherwise is doesnt
|
|
73
|
-
# get the patch in settings.py
|
|
74
|
-
# * Update code in signal handlers to use module-level imports again
|
|
75
|
-
from django.conf import settings
|
|
76
|
-
|
|
77
|
-
self.settings = settings
|
|
78
|
-
# end
|
|
79
71
|
|
|
80
72
|
try:
|
|
81
73
|
self.version
|
|
@@ -247,7 +239,7 @@ class PulpAppConfig(PulpPluginAppConfig):
|
|
|
247
239
|
label = "core"
|
|
248
240
|
|
|
249
241
|
# The version of this app
|
|
250
|
-
version = "3.
|
|
242
|
+
version = "3.85.1"
|
|
251
243
|
|
|
252
244
|
# The python package name providing this app
|
|
253
245
|
python_package_name = "pulpcore"
|
|
@@ -322,7 +314,6 @@ def _populate_system_id(sender, apps, verbosity, **kwargs):
|
|
|
322
314
|
|
|
323
315
|
|
|
324
316
|
def _ensure_default_domain(sender, **kwargs):
|
|
325
|
-
settings = sender.settings
|
|
326
317
|
table_names = connection.introspection.table_names()
|
|
327
318
|
if "core_domain" in table_names:
|
|
328
319
|
from pulpcore.app.util import get_default_domain
|
|
@@ -402,7 +393,6 @@ def adjust_roles(apps, role_prefix, desired_roles, verbosity=1):
|
|
|
402
393
|
|
|
403
394
|
|
|
404
395
|
def _populate_artifact_serving_distribution(sender, apps, verbosity, **kwargs):
|
|
405
|
-
settings = sender.settings
|
|
406
396
|
if (
|
|
407
397
|
settings.STORAGES["default"]["BACKEND"] == "pulpcore.app.models.storage.FileSystem"
|
|
408
398
|
or not settings.REDIRECT_TO_OBJECT_STORAGE
|
pulpcore/app/entrypoint.py
CHANGED
|
@@ -7,7 +7,8 @@ import click
|
|
|
7
7
|
import django
|
|
8
8
|
from django.conf import settings
|
|
9
9
|
from django.db import connection
|
|
10
|
-
from django.db.utils import InterfaceError, DatabaseError
|
|
10
|
+
from django.db.utils import IntegrityError, InterfaceError, DatabaseError
|
|
11
|
+
from gunicorn.arbiter import Arbiter
|
|
11
12
|
from gunicorn.workers.sync import SyncWorker
|
|
12
13
|
|
|
13
14
|
from pulpcore.app.apps import pulp_plugin_configs
|
|
@@ -27,26 +28,21 @@ class PulpApiWorker(SyncWorker):
|
|
|
27
28
|
|
|
28
29
|
def heartbeat(self):
|
|
29
30
|
try:
|
|
30
|
-
self.
|
|
31
|
-
name=self.name, defaults={"versions": self.versions}
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
if not created:
|
|
35
|
-
self.api_app_status.save_heartbeat()
|
|
36
|
-
|
|
37
|
-
if self.api_app_status.versions != self.versions:
|
|
38
|
-
self.api_app_status.versions = self.versions
|
|
39
|
-
self.api_app_status.save(update_fields=["versions"])
|
|
40
|
-
|
|
31
|
+
self.app_status.save_heartbeat()
|
|
41
32
|
logger.debug(self.beat_msg)
|
|
42
33
|
except (InterfaceError, DatabaseError):
|
|
43
34
|
connection.close_if_unusable_or_obsolete()
|
|
44
|
-
|
|
35
|
+
try:
|
|
36
|
+
self.app_status.save_heartbeat()
|
|
37
|
+
logger.debug(self.beat_msg)
|
|
38
|
+
except (InterfaceError, DatabaseError):
|
|
39
|
+
logger.error(self.fail_beat_msg)
|
|
40
|
+
exit(Arbiter.WORKER_BOOT_ERROR)
|
|
45
41
|
|
|
46
42
|
def init_process(self):
|
|
47
43
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pulpcore.app.settings")
|
|
48
44
|
django.setup()
|
|
49
|
-
from pulpcore.app.models import
|
|
45
|
+
from pulpcore.app.models import AppStatus
|
|
50
46
|
|
|
51
47
|
if settings.API_APP_TTL < 2 * self.timeout:
|
|
52
48
|
logger.warning(
|
|
@@ -56,9 +52,6 @@ class PulpApiWorker(SyncWorker):
|
|
|
56
52
|
self.timeout,
|
|
57
53
|
)
|
|
58
54
|
|
|
59
|
-
self.ApiAppStatus = ApiAppStatus
|
|
60
|
-
self.api_app_status = None
|
|
61
|
-
|
|
62
55
|
self.name = "{pid}@{hostname}".format(pid=self.pid, hostname=socket.gethostname())
|
|
63
56
|
self.versions = {app.label: app.version for app in pulp_plugin_configs()}
|
|
64
57
|
self.beat_msg = (
|
|
@@ -67,9 +60,16 @@ class PulpApiWorker(SyncWorker):
|
|
|
67
60
|
)
|
|
68
61
|
)
|
|
69
62
|
self.fail_beat_msg = (
|
|
70
|
-
"Api App '{name}' failed to write a heartbeat to the database
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
"Api App '{name}' failed to write a heartbeat to the database."
|
|
64
|
+
).format(name=self.name)
|
|
65
|
+
try:
|
|
66
|
+
self.app_status = AppStatus.objects.create(
|
|
67
|
+
name=self.name, app_type="api", versions=self.versions
|
|
68
|
+
)
|
|
69
|
+
except IntegrityError:
|
|
70
|
+
logger.error(f"An API app with name {self.name} already exists in the database.")
|
|
71
|
+
exit(Arbiter.WORKER_BOOT_ERROR)
|
|
72
|
+
|
|
73
73
|
super().init_process()
|
|
74
74
|
|
|
75
75
|
def run(self):
|
|
@@ -77,8 +77,8 @@ class PulpApiWorker(SyncWorker):
|
|
|
77
77
|
super().run()
|
|
78
78
|
finally:
|
|
79
79
|
# cleanup
|
|
80
|
-
if self.
|
|
81
|
-
self.
|
|
80
|
+
if self.app_status:
|
|
81
|
+
self.app_status.delete()
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
class PulpcoreApiApplication(PulpcoreGunicornApplication):
|
|
@@ -20,105 +20,10 @@ import uuid
|
|
|
20
20
|
|
|
21
21
|
class Migration(migrations.Migration):
|
|
22
22
|
|
|
23
|
-
replaces = [
|
|
24
|
-
("core", "0001_initial"),
|
|
25
|
-
("core", "0002_increase_artifact_size_field"),
|
|
26
|
-
("core", "0003_remove_upload_completed"),
|
|
27
|
-
("core", "0004_add_duplicated_reserved_resources"),
|
|
28
|
-
("core", "0005_progressreport_code"),
|
|
29
|
-
("core", "0006_repository_plugin_managed"),
|
|
30
|
-
("core", "0007_delete_progress_proxies"),
|
|
31
|
-
("core", "0008_published_metadata_as_content"),
|
|
32
|
-
("core", "0009_remove_task_non_fatal_errors"),
|
|
33
|
-
("core", "0010_pulp_fields"),
|
|
34
|
-
("core", "0011_relative_path"),
|
|
35
|
-
("core", "0012_auto_20191104_2000"),
|
|
36
|
-
("core", "0013_repository_pulp_type"),
|
|
37
|
-
("core", "0014_remove_repository_plugin_managed"),
|
|
38
|
-
("core", "0015_auto_20191112_1426"),
|
|
39
|
-
("core", "0016_charfield_to_textfield"),
|
|
40
|
-
("core", "0017_remove_task_parent"),
|
|
41
|
-
("core", "0018_auto_20191127_2350"),
|
|
42
|
-
("core", "0019_add_signing_service_model"),
|
|
43
|
-
("core", "0020_change_publishedartifact_constraints"),
|
|
44
|
-
("core", "0021_add_signing_service_foreign_key"),
|
|
45
|
-
("core", "0022_rename_last_version"),
|
|
46
|
-
("core", "0023_change_exporter_models"),
|
|
47
|
-
("core", "0024_use_local_storage_for_uploads"),
|
|
48
|
-
("core", "0025_task_parent_task"),
|
|
49
|
-
("core", "0026_task_group"),
|
|
50
|
-
("core", "0027_export_backend"),
|
|
51
|
-
("core", "0028_import_importer_pulpimporter_pulpimporterrepository"),
|
|
52
|
-
("core", "0029_export_delete"),
|
|
53
|
-
("core", "0030_taskgroup_all_tasks_dispatched"),
|
|
54
|
-
("core", "0031_import_export_validate_params"),
|
|
55
|
-
("core", "0032_export_to_chunks"),
|
|
56
|
-
("core", "0033_increase_remote_artifact_size_field"),
|
|
57
|
-
("core", "0034_groupprogressreport"),
|
|
58
|
-
("core", "0035_content_upstream_id"),
|
|
59
|
-
("core", "0036_unprotect_last_export"),
|
|
60
|
-
("core", "0037_pulptemporaryfile"),
|
|
61
|
-
("core", "0038_repository_remote"),
|
|
62
|
-
("core", "0039_change_download_concurrency"),
|
|
63
|
-
("core", "0040_set_admin_is_staff"),
|
|
64
|
-
("core", "0041_accesspolicy"),
|
|
65
|
-
("core", "0042_rbac_for_tasks"),
|
|
66
|
-
("core", "0043_toc_attribute"),
|
|
67
|
-
("core", "0044_temp_file_artifact_field"),
|
|
68
|
-
("core", "0045_accesspolicy_permissions_allow_null"),
|
|
69
|
-
("core", "0046_task__resource_job_id"),
|
|
70
|
-
("core", "0047_improve_orphan_cleanup"),
|
|
71
|
-
("core", "0048_fips_checksums"),
|
|
72
|
-
("core", "0049_add_file_field_to_uploadchunk"),
|
|
73
|
-
("core", "0050_namespace_access_policies"),
|
|
74
|
-
("core", "0051_timeoutfields"),
|
|
75
|
-
("core", "0052_tasking_logging_cid"),
|
|
76
|
-
("core", "0053_remote_headers"),
|
|
77
|
-
("core", "0054_add_public_key"),
|
|
78
|
-
("core", "0055_label"),
|
|
79
|
-
("core", "0056_remote_rate_limit"),
|
|
80
|
-
("core", "0057_add_label_indexes"),
|
|
81
|
-
("core", "0058_accesspolicy_customized"),
|
|
82
|
-
("core", "0059_proxy_creds"),
|
|
83
|
-
("core", "0060_data_migration_proxy_creds"),
|
|
84
|
-
("core", "0061_call_handle_artifact_checksums_command"),
|
|
85
|
-
("core", "0062_add_new_distribution_mastermodel"),
|
|
86
|
-
("core", "0063_repository_retained_versions"),
|
|
87
|
-
("core", "0064_repository_user_hidden"),
|
|
88
|
-
("core", "0064_add_new_style_task_columns"),
|
|
89
|
-
("core", "0065_merge_20210615_1211"),
|
|
90
|
-
("core", "0066_download_concurrency_and_retry_changes"),
|
|
91
|
-
("core", "0067_add_protect_to_task_reservation"),
|
|
92
|
-
("core", "0068_add_timestamp_of_interest"),
|
|
93
|
-
("core", "0069_update_json_fields"),
|
|
94
|
-
("core", "0070_rename_retained_versions"),
|
|
95
|
-
("core", "0071_filesystemexport_filesystemexporter"),
|
|
96
|
-
("core", "0072_add_method_to_filesystem_exporter"),
|
|
97
|
-
("core", "0073_encrypt_remote_fields"),
|
|
98
|
-
("core", "0074_acs"),
|
|
99
|
-
("core", "0075_rbaccontentguard"),
|
|
100
|
-
("core", "0076_remove_reserved_resource"),
|
|
101
|
-
("core", "0077_move_remote_url_credentials"),
|
|
102
|
-
("core", "0078_grouprole_role_userrole"),
|
|
103
|
-
("core", "0079_rename_permissions_assignment_accesspolicy_creation_hooks"),
|
|
104
|
-
("core", "0080_proxy_group_model"),
|
|
105
|
-
("core", "0081_reapplabel_group_permissions"),
|
|
106
|
-
("core", "0082_add_manage_roles_permissions"),
|
|
107
|
-
("core", "0083_alter_group_options"),
|
|
108
|
-
("core", "0084_alter_rbaccontentguard_options"),
|
|
109
|
-
("core", "0085_contentredirectcontentguard"),
|
|
110
|
-
("core", "0086_task_json_fields"),
|
|
111
|
-
("core", "0087_taskschedule"),
|
|
112
|
-
("core", "0088_accesspolicy_queryset_scoping"),
|
|
113
|
-
("core", "0089_alter_contentredirectcontentguard_options"),
|
|
114
|
-
("core", "0090_char_to_text_field"),
|
|
115
|
-
]
|
|
116
|
-
|
|
117
23
|
initial = True
|
|
118
24
|
|
|
119
25
|
dependencies = [
|
|
120
26
|
("auth", "0012_alter_user_first_name_max_length"),
|
|
121
|
-
("auth", "__first__"),
|
|
122
27
|
("contenttypes", "0002_remove_content_type_name"),
|
|
123
28
|
]
|
|
124
29
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated by Django
|
|
1
|
+
# Generated by Django 4.2.16 on 2024-12-05 12:37
|
|
2
2
|
|
|
3
3
|
from django.db import migrations
|
|
4
4
|
|
|
@@ -6,11 +6,11 @@ from django.db import migrations
|
|
|
6
6
|
class Migration(migrations.Migration):
|
|
7
7
|
|
|
8
8
|
dependencies = [
|
|
9
|
-
(
|
|
9
|
+
("core", "0135_task_pulp_task_resources_index"),
|
|
10
10
|
]
|
|
11
11
|
|
|
12
12
|
operations = [
|
|
13
13
|
migrations.DeleteModel(
|
|
14
|
-
name=
|
|
14
|
+
name="BaseDistribution",
|
|
15
15
|
),
|
|
16
16
|
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Generated by Django 4.2.23 on 2025-08-07 08:46
|
|
2
|
+
|
|
3
|
+
import django.contrib.postgres.fields.hstore
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
import django_lifecycle.mixins
|
|
6
|
+
import pulpcore.app.models.base
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Migration(migrations.Migration):
|
|
10
|
+
|
|
11
|
+
dependencies = [
|
|
12
|
+
('core', '0136_delete_basedistribution'),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.CreateModel(
|
|
17
|
+
name='AppStatus',
|
|
18
|
+
fields=[
|
|
19
|
+
('pulp_id', models.UUIDField(default=pulpcore.app.models.base.pulp_uuid, editable=False, primary_key=True, serialize=False)),
|
|
20
|
+
('pulp_created', models.DateTimeField(auto_now_add=True)),
|
|
21
|
+
('pulp_last_updated', models.DateTimeField(auto_now=True, null=True)),
|
|
22
|
+
('app_type', models.CharField(choices=[('api', 'api'), ('content', 'content'), ('worker', 'worker')], max_length=10)),
|
|
23
|
+
('name', models.TextField(db_index=True, unique=True)),
|
|
24
|
+
('versions', django.contrib.postgres.fields.hstore.HStoreField(default=dict)),
|
|
25
|
+
('ttl', models.DurationField()),
|
|
26
|
+
('last_heartbeat', models.DateTimeField(auto_now=True)),
|
|
27
|
+
],
|
|
28
|
+
options={
|
|
29
|
+
'abstract': False,
|
|
30
|
+
},
|
|
31
|
+
bases=(django_lifecycle.mixins.LifecycleModelMixin, models.Model),
|
|
32
|
+
),
|
|
33
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Generated by Django 4.2.19 on 2025-08-07 00:07
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
import django_lifecycle.mixins
|
|
6
|
+
import pulpcore.app.models.base
|
|
7
|
+
import pulpcore.app.util
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Migration(migrations.Migration):
|
|
11
|
+
|
|
12
|
+
dependencies = [
|
|
13
|
+
('core', '0137_appstatus'),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
operations = [
|
|
17
|
+
migrations.CreateModel(
|
|
18
|
+
name='VulnerabilityReport',
|
|
19
|
+
fields=[
|
|
20
|
+
('pulp_id', models.UUIDField(default=pulpcore.app.models.base.pulp_uuid, editable=False, primary_key=True, serialize=False)),
|
|
21
|
+
('pulp_created', models.DateTimeField(auto_now_add=True)),
|
|
22
|
+
('pulp_last_updated', models.DateTimeField(auto_now=True, null=True)),
|
|
23
|
+
('vulns', models.JSONField()),
|
|
24
|
+
('content', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='core.content')),
|
|
25
|
+
('pulp_domain', models.ForeignKey(default=pulpcore.app.util.get_domain_pk, on_delete=django.db.models.deletion.CASCADE, to='core.domain')),
|
|
26
|
+
('repo_versions', models.ManyToManyField(blank=True, to='core.repositoryversion')),
|
|
27
|
+
],
|
|
28
|
+
options={
|
|
29
|
+
'default_related_name': '%(app_label)s_%(model_name)s',
|
|
30
|
+
},
|
|
31
|
+
bases=(django_lifecycle.mixins.LifecycleModelMixin, models.Model),
|
|
32
|
+
),
|
|
33
|
+
]
|
pulpcore/app/models/__init__.py
CHANGED
|
@@ -69,7 +69,7 @@ from .repository import (
|
|
|
69
69
|
RepositoryVersionContentDetails,
|
|
70
70
|
)
|
|
71
71
|
|
|
72
|
-
from .status import ApiAppStatus, ContentAppStatus
|
|
72
|
+
from .status import AppStatus, ApiAppStatus, ContentAppStatus
|
|
73
73
|
|
|
74
74
|
from .task import (
|
|
75
75
|
CreatedResource,
|
|
@@ -87,6 +87,8 @@ from .upload import (
|
|
|
87
87
|
UploadChunk,
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
+
from .vulnerability_report import VulnerabilityReport
|
|
91
|
+
|
|
90
92
|
# Moved here to avoid a circular import with Task
|
|
91
93
|
from .progress import GroupProgressReport, ProgressReport
|
|
92
94
|
|
|
@@ -170,4 +172,5 @@ __all__ = [
|
|
|
170
172
|
"OpenPGPSignature",
|
|
171
173
|
"OpenPGPUserAttribute",
|
|
172
174
|
"OpenPGPUserID",
|
|
175
|
+
"VulnerabilityReport",
|
|
173
176
|
]
|
|
@@ -576,47 +576,6 @@ class CompositeContentGuard(ContentGuard, AutoAddObjPermsMixin):
|
|
|
576
576
|
)
|
|
577
577
|
|
|
578
578
|
|
|
579
|
-
class BaseDistribution(MasterModel):
|
|
580
|
-
"""
|
|
581
|
-
A distribution defines how a publication is distributed by the Content App.
|
|
582
|
-
|
|
583
|
-
This abstract model can be used by plugin writers to create concrete distributions that are
|
|
584
|
-
stored in separate tables from the Distributions provided by pulpcore.
|
|
585
|
-
|
|
586
|
-
The `name` must be unique.
|
|
587
|
-
|
|
588
|
-
The ``base_path`` must have no overlapping components. So if a Distribution with ``base_path``
|
|
589
|
-
of ``a/path/foo`` existed, you could not make a second Distribution with a ``base_path`` of
|
|
590
|
-
``a/path`` or ``a`` because both are subpaths of ``a/path/foo``.
|
|
591
|
-
|
|
592
|
-
Note:
|
|
593
|
-
This class is no longer supported and cannot be removed from Pulp 3 due to possible
|
|
594
|
-
problems with old migrations for plugins. Until the migrations are squashed, this class
|
|
595
|
-
should be preserved.
|
|
596
|
-
|
|
597
|
-
Fields:
|
|
598
|
-
name (models.TextField): The name of the distribution. Examples: "rawhide" and "stable".
|
|
599
|
-
base_path (models.TextField): The base (relative) path component of the published url.
|
|
600
|
-
|
|
601
|
-
Relations:
|
|
602
|
-
content_guard (models.ForeignKey): An optional content-guard.
|
|
603
|
-
remote (models.ForeignKey): A remote that the content app can use to find content not
|
|
604
|
-
yet stored in Pulp.
|
|
605
|
-
"""
|
|
606
|
-
|
|
607
|
-
name = models.TextField(db_index=True, unique=True)
|
|
608
|
-
base_path = models.TextField(unique=True)
|
|
609
|
-
|
|
610
|
-
content_guard = models.ForeignKey(ContentGuard, null=True, on_delete=models.SET_NULL)
|
|
611
|
-
remote = models.ForeignKey(Remote, null=True, on_delete=models.SET_NULL)
|
|
612
|
-
|
|
613
|
-
def __init__(self, *args, **kwargs):
|
|
614
|
-
raise Exception(
|
|
615
|
-
"BaseDistribution is no longer supported. "
|
|
616
|
-
"Please use pulpcore.plugin.models.Distribution instead."
|
|
617
|
-
)
|
|
618
|
-
|
|
619
|
-
|
|
620
579
|
class Distribution(MasterModel):
|
|
621
580
|
"""
|
|
622
581
|
A Distribution defines how the Content App distributes a publication or repository_version.
|