Skip to content

Commit 2b6eec1

Browse files
committed
Add better flat repo handling for structure publish
1 parent 04d1103 commit 2b6eec1

File tree

3 files changed

+115
-58
lines changed

3 files changed

+115
-58
lines changed

pulp_deb/app/tasks/synchronizing.py

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -624,16 +624,19 @@ def _to_d_artifact(self, relative_path, data=None):
624624
)
625625

626626
async def _handle_distribution(self, distribution):
627+
is_flat = distribution.endswith("/")
628+
stored_distribution = "flat-repo" if is_flat else distribution
629+
627630
log.info(_('Downloading Release file for distribution: "{}"').format(distribution))
628631
# Create release_file
629-
if distribution[-1] == "/":
630-
release_file_dir = distribution.strip("/")
632+
if is_flat:
633+
upstream_file_dir = distribution.strip("/")
631634
else:
632-
release_file_dir = os.path.join("dists", distribution)
635+
upstream_file_dir = os.path.join("dists", distribution)
633636
release_file_dc = DeclarativeContent(
634-
content=ReleaseFile(distribution=distribution, relative_path=release_file_dir),
637+
content=ReleaseFile(distribution=stored_distribution, relative_path=upstream_file_dir),
635638
d_artifacts=[
636-
self._to_d_artifact(os.path.join(release_file_dir, filename))
639+
self._to_d_artifact(os.path.join(upstream_file_dir, filename))
637640
for filename in ReleaseFile.SUPPORTED_ARTIFACTS
638641
],
639642
)
@@ -665,7 +668,7 @@ async def _handle_distribution(self, distribution):
665668
release_fields = {
666669
"codename": release_file.codename,
667670
"suite": release_file.suite,
668-
"distribution": distribution,
671+
"distribution": stored_distribution,
669672
}
670673

671674
if "version" in release_file_dict:
@@ -680,17 +683,17 @@ async def _handle_distribution(self, distribution):
680683
await self.put(DeclarativeContent(content=Release(**release_fields)))
681684

682685
# Create release architectures
683-
if release_file.architectures:
684-
architectures = _filter_split_architectures(
685-
release_file.architectures, self.remote.architectures, distribution
686-
)
687-
elif distribution[-1] == "/":
686+
if is_flat:
688687
message = (
689688
"The ReleaseFile content unit architecrures are unset for the flat repo with "
690689
"distribution '{}'. ReleaseArchitecture content creation is deferred!"
691690
)
692691
log.warning(_(message).format(distribution))
693692
architectures = []
693+
elif release_file.architectures:
694+
architectures = _filter_split_architectures(
695+
release_file.architectures, self.remote.architectures, distribution
696+
)
694697

695698
for architecture in architectures:
696699
release_architecture_dc = DeclarativeContent(
@@ -719,9 +722,16 @@ async def _handle_distribution(self, distribution):
719722
for unit in release_file_dict[digest_name]:
720723
file_references[unit["Name"]].update(unit)
721724

722-
if distribution[-1] == "/":
725+
if is_flat:
723726
# Handle flat repo
724-
sub_tasks = [self._handle_flat_repo(file_references, release_file, distribution)]
727+
sub_tasks = [
728+
self._handle_flat_repo(
729+
file_references,
730+
release_file,
731+
distribution=stored_distribution,
732+
upstream_dist_path=upstream_file_dir,
733+
)
734+
]
725735
else:
726736
# Handle components
727737
sub_tasks = [
@@ -833,7 +843,9 @@ async def _handle_component(
833843
)
834844
await asyncio.gather(*pending_tasks)
835845

836-
async def _handle_flat_repo(self, file_references, release_file, distribution):
846+
async def _handle_flat_repo(
847+
self, file_references, release_file, distribution, upstream_dist_path
848+
):
837849
# We are creating a component so the flat repo can be published as a structured repo!
838850
release_component_dc = DeclarativeContent(
839851
content=ReleaseComponent(component="flat-repo-component", distribution=distribution)
@@ -849,6 +861,7 @@ async def _handle_flat_repo(self, file_references, release_file, distribution):
849861
architecture="",
850862
file_references=file_references,
851863
distribution=distribution,
864+
is_flat=True,
852865
)
853866
)
854867

@@ -868,15 +881,19 @@ async def _handle_package_index(
868881
infix="",
869882
distribution=None,
870883
hybrid_format=False,
884+
is_flat=False,
871885
):
886+
if is_flat:
887+
release_file_package_index_dir = ""
888+
else:
889+
release_file_package_index_dir = os.path.join(
890+
release_component.plain_component,
891+
infix,
892+
f"binary-{architecture}",
893+
)
872894
# Create package_index
873895
release_base_path = os.path.dirname(release_file.relative_path)
874-
# Package index directory relative to the release file:
875-
release_file_package_index_dir = (
876-
os.path.join(release_component.plain_component, infix, "binary-{}".format(architecture))
877-
if release_file.distribution[-1] != "/"
878-
else ""
879-
)
896+
880897
# Package index directory relative to the repository root:
881898
package_index_dir = os.path.join(release_base_path, release_file_package_index_dir)
882899
d_artifacts = []
@@ -948,7 +965,7 @@ async def _handle_package_index(
948965
):
949966
# Sanity check the architecture from the package paragraph:
950967
package_paragraph_architecture = package_paragraph["Architecture"]
951-
if release_file.distribution[-1] == "/":
968+
if is_flat:
952969
if (
953970
self.remote.architectures
954971
and package_paragraph_architecture != "all"
@@ -1035,32 +1052,22 @@ async def _handle_package_index(
10351052
)
10361053
)
10371054
await self.put(package_release_component_dc)
1038-
if release_file.distribution[-1] == "/":
1055+
if is_flat:
10391056
package_architectures.add(package.architecture)
10401057

10411058
# For flat repos we may still need to create ReleaseArchitecture content:
1042-
if release_file.distribution[-1] == "/":
1059+
if is_flat:
10431060
if release_file.architectures:
10441061
for architecture in package_architectures:
1045-
if architecture not in release_file.architectures.split():
1046-
message = (
1047-
"The flat repo with distribution '{}' contains packages with "
1048-
"architecture '{}' but this is not included in the ReleaseFile's "
1049-
"architectures field '{}'!"
1050-
)
1051-
log.warning(
1052-
_(message).format(
1053-
release_file.distribution, architecture, release_file.architectures
1054-
)
1055-
)
1056-
message = "Creating additional ReleaseArchitecture for architecture '{}'!"
1057-
log.warning(_(message).format(architecture))
1058-
release_architecture_dc = DeclarativeContent(
1059-
content=ReleaseArchitecture(
1060-
architecture=architecture, distribution=distribution
1061-
)
1062+
log.debug(
1063+
f"Flat Repo Architecture handling: Creating ReleaseArchitecture for architecture {architecture}."
1064+
)
1065+
release_architecture_dc = DeclarativeContent(
1066+
content=ReleaseArchitecture(
1067+
architecture=architecture, distribution="flat-repo"
10621068
)
1063-
await self.put(release_architecture_dc)
1069+
)
1070+
await self.put(release_architecture_dc)
10641071
else:
10651072
package_architectures_string = " ".join(package_architectures)
10661073
message = (
@@ -1076,7 +1083,7 @@ async def _handle_package_index(
10761083
for architecture in package_architectures:
10771084
release_architecture_dc = DeclarativeContent(
10781085
content=ReleaseArchitecture(
1079-
architecture=architecture, distribution=distribution
1086+
architecture=architecture, distribution="flat-repo"
10801087
)
10811088
)
10821089
await self.put(release_architecture_dc)

pulp_deb/tests/functional/api/test_publish.py

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from pulp_deb.tests.functional.constants import (
77
DEB_FIXTURE_ALT_SINGLE_DIST,
8+
DEB_FIXTURE_BASE,
89
DEB_FIXTURE_COMPLEX_REPOSITORY_NAME,
910
DEB_FIXTURE_DISTRIBUTIONS,
1011
DEB_FIXTURE_FLAT_REPOSITORY_NAME,
@@ -320,14 +321,16 @@ def test_publish_empty_repository(
320321

321322
@pytest.mark.parallel
322323
@pytest.mark.parametrize(
323-
"expected_data", [DEB_PUBLISH_FLAT_VERBATIM, DEB_PUBLISH_FLAT_NESTED_VERBATIM]
324+
"expected_data, flat_dist",
325+
[(DEB_PUBLISH_FLAT_VERBATIM, "/"), (DEB_PUBLISH_FLAT_NESTED_VERBATIM, "nest/fjalar/")],
324326
)
325327
def test_publish_flat_repository_verbatim(
326328
create_publication_and_verify_repo_version,
327329
deb_distribution_factory,
328330
verify_distribution,
329331
verify_publication_data,
330332
expected_data,
333+
flat_dist,
331334
):
332335
"""Test whether a particular flat repository can be published verbatim.
333336
@@ -336,7 +339,7 @@ def test_publish_flat_repository_verbatim(
336339
* `Publish a flat repository verbatim.`_
337340
* `Publish a nested flat repository verbatim.`_
338341
"""
339-
remote_args = {"distributions": expected_data["distribution"]}
342+
remote_args = {"distributions": flat_dist}
340343

341344
# Create a publication
342345
publication, _, _, _ = create_publication_and_verify_repo_version(
@@ -351,12 +354,12 @@ def test_publish_flat_repository_verbatim(
351354

352355
@pytest.mark.parallel
353356
@pytest.mark.parametrize(
354-
"expected_data, publication_args",
357+
"expected_data, publication_args, flat_dist",
355358
[
356-
(DEB_PUBLISH_FLAT_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED),
357-
(DEB_PUBLISH_FLAT_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE),
358-
(DEB_PUBLISH_FLAT_NESTED_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED),
359-
(DEB_PUBLISH_FLAT_NESTED_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE),
359+
(DEB_PUBLISH_FLAT_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED, "/"),
360+
(DEB_PUBLISH_FLAT_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE, "/"),
361+
(DEB_PUBLISH_FLAT_NESTED_STRUCTURED, DEB_PUBLICATION_ARGS_ONLY_STRUCTURED, "nest/fjalar/"),
362+
(DEB_PUBLISH_FLAT_NESTED_SIMPLE, DEB_PUBLICATION_ARGS_ONLY_SIMPLE, "nest/fjalar/"),
360363
],
361364
)
362365
def test_publish_flat_repository(
@@ -366,6 +369,7 @@ def test_publish_flat_repository(
366369
verify_distribution,
367370
verify_publication_data,
368371
publication_args,
372+
flat_dist,
369373
):
370374
"""Test whether a particular flat repository can be published.
371375
@@ -376,7 +380,7 @@ def test_publish_flat_repository(
376380
* `Publish a nested flat repository structured.`_
377381
* `Publish a nested flat repository simple.`_
378382
"""
379-
remote_args = {"distributions": expected_data["distribution"]}
383+
remote_args = {"distributions": flat_dist}
380384

381385
# Create a publication
382386
publication, _, _, _ = create_publication_and_verify_repo_version(
@@ -391,6 +395,51 @@ def test_publish_flat_repository(
391395
verify_distribution(distribution, expected_data)
392396

393397

398+
@pytest.mark.parallel
399+
@pytest.mark.parametrize(
400+
"remote_args, remote_name",
401+
[
402+
({"distributions": "/"}, DEB_FIXTURE_FLAT_REPOSITORY_NAME),
403+
({"distributions": "debian-flat/"}, DEB_FIXTURE_BASE),
404+
],
405+
)
406+
def test_published_flat_repo_content(
407+
create_publication_and_verify_repo_version,
408+
deb_distribution_factory,
409+
download_content_unit,
410+
remote_args,
411+
remote_name,
412+
):
413+
"""
414+
Test that published flat repository results in a normalized Release file and package indices.
415+
"""
416+
publication, _, _, _ = create_publication_and_verify_repo_version(
417+
remote_args=remote_args,
418+
remote_name=remote_name,
419+
)
420+
421+
distribution = deb_distribution_factory(publication)
422+
base_url = distribution.base_path
423+
424+
expected_release_path = os.path.join("dists", "flat-repo", "Release")
425+
expected_pkg_index_path = os.path.join(
426+
"dists", "flat-repo", "flat-repo-component", "binary-ppc64", "Packages"
427+
)
428+
429+
release_file = download_content_unit(base_url, expected_release_path)
430+
release_file_str = release_file.decode("utf-8")
431+
assert (
432+
"flat-repo" in release_file_str
433+
), f"Expected the published Release file to contain 'flat-repo' as distribution, got: {release_file}"
434+
435+
pkg_index = download_content_unit(base_url, expected_pkg_index_path)
436+
from debian import deb822
437+
438+
pkgs = list(deb822.Packages.iter_paragraphs(pkg_index, use_apt_pkg=False))
439+
ppc64_pkgs = [pkg for pkg in pkgs if pkg.get("Architecture") == "ppc64"]
440+
assert ppc64_pkgs, "No packages with architecture 'ppc64' found in the published package index."
441+
442+
394443
@pytest.mark.skip("Skip - ignore_missing_package_indices sync parameter does currently not work")
395444
@pytest.mark.parallel
396445
def test_publish_missing_architecture(

pulp_deb/tests/functional/constants.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def _clean_dict(d):
3737
DEB_FIXTURE_UPDATE_REPOSITORY_NAME = "/debian-update/"
3838
DEB_FIXTURE_INVALID_REPOSITORY_NAME = "/debian-invalid/"
3939
DEB_FIXTURE_FLAT_REPOSITORY_NAME = "/debian-flat/"
40+
DEB_FIXTURE_BASE = "/"
4041
DEB_FIXTURE_COMPLEX_REPOSITORY_NAME = "/debian-complex-dists"
4142
DEB_FIXTURE_MISSING_ARCHITECTURE_REPOSITORY_NAME = "/debian-missing-architecture/"
4243

@@ -249,7 +250,7 @@ def _clean_dict(d):
249250
}
250251

251252
DEB_PUBLISH_FLAT_STRUCTURED = {
252-
"distribution": "/",
253+
"distribution": "flat-repo",
253254
"codename": "ragnarok",
254255
"suite": "mythology",
255256
"components": ["flat-repo-component"],
@@ -260,7 +261,7 @@ def _clean_dict(d):
260261
}
261262

262263
DEB_PUBLISH_FLAT_SIMPLE = {
263-
"distribution": "/",
264+
"distribution": "flat-repo",
264265
"codename": "ragnarok",
265266
"suite": "mythology",
266267
"components": ["flat-repo-component"],
@@ -271,7 +272,7 @@ def _clean_dict(d):
271272
}
272273

273274
DEB_PUBLISH_FLAT_VERBATIM = {
274-
"distribution": "/",
275+
"distribution": "flat-repo",
275276
"codename": "ragnarok",
276277
"suite": "mythology",
277278
"components": ["flat-repo-component"],
@@ -282,18 +283,18 @@ def _clean_dict(d):
282283
}
283284

284285
DEB_PUBLISH_FLAT_NESTED_STRUCTURED = {
285-
"distribution": "nest/fjalar/",
286+
"distribution": "flat-repo",
286287
"codename": "ragnarok",
287288
"suite": "mythology",
288289
"components": ["flat-repo-component"],
289290
"release_file_folder_sync": "nest/fjalar/",
290-
"release_file_folder_dist": "dists/nest/fjalar",
291+
"release_file_folder_dist": "dists/flat-repo",
291292
"package_index_paths_sync": ["nest/fjalar/Packages"],
292-
"package_index_paths_dist": ["dists/nest/fjalar/flat-repo-component/binary-ppc64/Packages"],
293+
"package_index_paths_dist": ["dists/flat-repo/flat-repo-component/binary-ppc64/Packages"],
293294
}
294295

295296
DEB_PUBLISH_FLAT_NESTED_SIMPLE = {
296-
"distribution": "nest/fjalar/",
297+
"distribution": "flat-repo",
297298
"codename": "ragnarok",
298299
"suite": "mythology",
299300
"components": ["flat-repo-component"],
@@ -304,7 +305,7 @@ def _clean_dict(d):
304305
}
305306

306307
DEB_PUBLISH_FLAT_NESTED_VERBATIM = {
307-
"distribution": "nest/fjalar/",
308+
"distribution": "flat-repo",
308309
"codename": "ragnarok",
309310
"suite": "mythology",
310311
"components": ["flat-repo-component"],

0 commit comments

Comments
 (0)