Skip to content

Commit fd8f70e

Browse files
committed
Add domain support
1 parent 7ab0488 commit fd8f70e

File tree

7 files changed

+303
-12
lines changed

7 files changed

+303
-12
lines changed

pulp_deb/app/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ class PulpDebPluginAppConfig(PulpPluginAppConfig):
88
label = "deb"
99
version = "3.6.0.dev"
1010
python_package_name = "pulp_deb"
11+
domain_compatible = True

pulp_deb/app/urls.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
from .viewsets import CopyViewSet
88

9-
V3_API_ROOT = settings.V3_API_ROOT_NO_FRONT_SLASH
9+
if settings.DOMAIN_ENABLED:
10+
V3_API_ROOT = settings.V3_DOMAIN_API_ROOT_NO_FRONT_SLASH
11+
else:
12+
V3_API_ROOT = settings.V3_API_ROOT_NO_FRONT_SLASH
1013

1114
urlpatterns = [
1215
path(f"{V3_API_ROOT}deb/copy/", CopyViewSet.as_view({"post": "create"})),

pulp_deb/tests/conftest.py

+19-8
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ def apt_repository_versions_api(apt_client):
5959
def deb_distribution_factory(apt_distribution_api, gen_object_with_cleanup):
6060
"""Fixture that generates a deb distribution with cleanup from a given publication."""
6161

62-
def _deb_distribution_factory(publication=None, repository=None, checkpoint=None):
62+
def _deb_distribution_factory(
63+
publication=None, repository=None, checkpoint=None, pulp_domain=None
64+
):
6365
"""Create a deb distribution.
6466
6567
:param publication: The publication the distribution is based on.
@@ -72,6 +74,8 @@ def _deb_distribution_factory(publication=None, repository=None, checkpoint=None
7274
body["repository"] = repository.pulp_href
7375
if checkpoint is not None:
7476
body["checkpoint"] = checkpoint
77+
if pulp_domain:
78+
body["pulp_domain"] = pulp_domain
7579
return gen_object_with_cleanup(apt_distribution_api, body)
7680

7781
return _deb_distribution_factory
@@ -81,12 +85,14 @@ def _deb_distribution_factory(publication=None, repository=None, checkpoint=None
8185
def deb_publication_factory(apt_publication_api, gen_object_with_cleanup):
8286
"""Fixture that generates a deb publication with cleanup from a given repository."""
8387

84-
def _deb_publication_factory(repo, **kwargs):
88+
def _deb_publication_factory(repo, pulp_domain=None, **kwargs):
8589
"""Create a deb publication.
8690
8791
:param repo: The repository the publication is based on.
8892
:returns: The created publication.
8993
"""
94+
if pulp_domain:
95+
kwargs["pulp_domain"] = pulp_domain
9096
publication_data = DebAptPublication(repository=repo.pulp_href, **kwargs)
9197
return gen_object_with_cleanup(apt_publication_api, publication_data)
9298

@@ -97,12 +103,14 @@ def _deb_publication_factory(repo, **kwargs):
97103
def deb_repository_factory(apt_repository_api, gen_object_with_cleanup):
98104
"""Fixture that generates a deb repository with cleanup."""
99105

100-
def _deb_repository_factory(**kwargs):
106+
def _deb_repository_factory(pulp_domain=None, **kwargs):
101107
"""Create a deb repository.
102108
103109
:returns: The created repository.
104110
"""
105-
return gen_object_with_cleanup(apt_repository_api, gen_repo(**kwargs))
111+
return gen_object_with_cleanup(
112+
apt_repository_api, gen_repo(pulp_domain=pulp_domain, **kwargs)
113+
)
106114

107115
return _deb_repository_factory
108116

@@ -111,13 +119,15 @@ def _deb_repository_factory(**kwargs):
111119
def deb_remote_factory(apt_remote_api, gen_object_with_cleanup):
112120
"""Fixture that generates a deb remote with cleanup."""
113121

114-
def _deb_remote_factory(url, **kwargs):
122+
def _deb_remote_factory(url, pulp_domain=None, **kwargs):
115123
"""Creats a remote from the given url.
116124
117125
:param url: The name of the local data repository.
118126
:returns: The created remote.
119127
"""
120-
return gen_object_with_cleanup(apt_remote_api, gen_deb_remote(url=str(url), **kwargs))
128+
return gen_object_with_cleanup(
129+
apt_remote_api, gen_deb_remote(url=str(url), pulp_domain=pulp_domain, **kwargs)
130+
)
121131

122132
return _deb_remote_factory
123133

@@ -183,6 +193,7 @@ def _deb_init_and_sync(
183193
repository=None,
184194
remote=None,
185195
url=None,
196+
pulp_domain=None,
186197
remote_args={},
187198
repo_args={},
188199
sync_args={},
@@ -206,9 +217,9 @@ def _deb_init_and_sync(
206217
else:
207218
url = deb_get_fixture_server_url(url)
208219
if repository is None:
209-
repository = deb_repository_factory(**repo_args)
220+
repository = deb_repository_factory(pulp_domain=pulp_domain, **repo_args)
210221
if remote is None:
211-
remote = deb_remote_factory(url=url, **remote_args)
222+
remote = deb_remote_factory(url=url, pulp_domain=pulp_domain, **remote_args)
212223

213224
task = deb_sync_repository(remote, repository, **sync_args)
214225

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import pytest
2+
import json
3+
import uuid
4+
5+
from pulpcore.client.pulp_deb.exceptions import ApiException
6+
7+
8+
def test_domain_create(
9+
deb_domain_factory,
10+
deb_init_and_sync,
11+
apt_package_api,
12+
apt_repository_api,
13+
):
14+
"""Test repo-creation in a domain."""
15+
domain_name = deb_domain_factory().name
16+
17+
# create and sync in default domain (not specified)
18+
deb_init_and_sync()
19+
20+
# check that newly created domain doesn't have a repo or any packages
21+
assert apt_repository_api.list(pulp_domain=domain_name).count == 0
22+
assert apt_package_api.list(pulp_domain=domain_name).count == 0
23+
24+
25+
def test_domain_sync(
26+
deb_domain_factory,
27+
deb_init_and_sync,
28+
apt_repository_api,
29+
apt_package_api,
30+
deb_cleanup_domains,
31+
):
32+
"""Test repo-sync in a domain."""
33+
domain = deb_domain_factory()
34+
try:
35+
domain_name = domain.name
36+
repo, _ = deb_init_and_sync(pulp_domain=domain_name)
37+
repos = apt_repository_api.list(name=repo.name, pulp_domain=domain_name)
38+
print(f"repos = {repos}")
39+
assert len(repos) == 1
40+
assert repos[0].pulp_href == repo.pulp_href
41+
assert apt_repository_api.list(pulp_domain=domain_name).count == 1
42+
assert (
43+
apt_package_api.list(
44+
repository_version=repo.latest_version_href, pulp_domain=domain_name
45+
).count
46+
== 2
47+
)
48+
finally:
49+
deb_cleanup_domains([domain], content_api_client=apt_package_api, cleanup_repositories=True)
50+
51+
52+
@pytest.mark.parallel
53+
def test_object_creation(
54+
deb_domain_factory,
55+
deb_repository_factory,
56+
apt_repository_api,
57+
deb_remote_factory,
58+
deb_sync_repository,
59+
deb_get_fixture_server_url,
60+
):
61+
"""Test basic object creation in a separate domain."""
62+
domain = deb_domain_factory()
63+
domain_name = domain.name
64+
65+
repo = deb_repository_factory(pulp_domain=domain_name)
66+
assert f"{domain_name}/api/v3/" in repo.pulp_href
67+
68+
repos = apt_repository_api.list(pulp_domain=domain_name)
69+
assert repos.count == 1
70+
assert repo.pulp_href == repos.results[0].pulp_href
71+
72+
# list repos on default domain
73+
default_repos = apt_repository_api.list(name=repo.name)
74+
assert default_repos.count == 0
75+
76+
# try to create an object with cross domain relations
77+
url = deb_get_fixture_server_url()
78+
default_remote = deb_remote_factory(url)
79+
with pytest.raises(ApiException) as e:
80+
repo_body = {"name": str(uuid.uuid4()), "remote": default_remote.pulp_href}
81+
apt_repository_api.create(repo_body, pulp_domain=domain_name)
82+
assert e.value.status == 400
83+
assert json.loads(e.value.body) == {
84+
"non_field_errors": [f"Objects must all be apart of the {domain_name} domain."]
85+
}
86+
87+
with pytest.raises(ApiException) as e:
88+
deb_sync_repository(remote=default_remote, repo=repo)
89+
assert e.value.status == 400
90+
assert json.loads(e.value.body) == {
91+
"non_field_errors": [f"Objects must all be apart of the {domain_name} domain."]
92+
}
93+
94+
95+
@pytest.mark.parallel
96+
def test_content_promotion(
97+
deb_domain_factory,
98+
deb_cleanup_domains,
99+
deb_publication_factory,
100+
deb_distribution_factory,
101+
deb_delete_repository,
102+
deb_init_and_sync,
103+
deb_get_repository_by_href,
104+
):
105+
"""Tests Content promotion path with domains: Sync->Publish->Distribute"""
106+
domain = deb_domain_factory()
107+
108+
try:
109+
# Sync
110+
repo, _, task = deb_init_and_sync(pulp_domain=domain.name, return_task=True)
111+
assert len(task.created_resources) == 1
112+
113+
repo = deb_get_repository_by_href(repo.pulp_href)
114+
assert repo.latest_version_href[-2] == "1"
115+
116+
# Publish
117+
publication = deb_publication_factory(repo=repo, pulp_domain=domain.name)
118+
assert publication.repository == repo.pulp_href
119+
120+
# Distribute
121+
distribution = deb_distribution_factory(publication=publication, pulp_domain=domain.name)
122+
assert distribution.publication == publication.pulp_href
123+
# url structure should be host/CONTENT_ORIGIN/DOMAIN_PATH/BASE_PATH
124+
assert domain.name == distribution.base_url.rstrip("/").split("/")[-2]
125+
126+
# check that content can be downloaded from base_url
127+
# for pkg in ("", ""):
128+
# pkg_path = get_package_repo_path(pkg)
129+
# download_content_unit(distribution.base_path, pkg_path, domain=domain.name)
130+
131+
# cleanup to delete the domain
132+
deb_delete_repository(repo)
133+
finally:
134+
deb_cleanup_domains([domain], cleanup_repositories=True)
135+
136+
137+
@pytest.mark.parallel
138+
def test_domain_rbac(
139+
deb_domain_factory, deb_cleanup_domains, apt_repository_api, deb_repository_factory, gen_user
140+
):
141+
"""Test domain level roles."""
142+
domain = deb_domain_factory()
143+
144+
try:
145+
deb_viewer = "deb.aptrepository_viewer"
146+
deb_creator = "deb.aptrepository_creator"
147+
user_a = gen_user(username="a", domain_roles=[(deb_viewer, domain.pulp_href)])
148+
user_b = gen_user(username="b", domain_roles=[(deb_creator, domain.pulp_href)])
149+
150+
# create two repos in different domains with admin user
151+
deb_repository_factory()
152+
deb_repository_factory(pulp_domain=domain.name)
153+
154+
with user_b:
155+
repo = deb_repository_factory(pulp_domain=domain.name)
156+
repos = apt_repository_api.list(pulp_domain=domain.name)
157+
assert repos.count == 1
158+
assert repos.results[0].pulp_href == repo.pulp_href
159+
160+
# try to create a repository in default domain
161+
with pytest.raises(ApiException) as e:
162+
deb_repository_factory()
163+
assert e.value.status == 403
164+
165+
with user_a:
166+
repos = apt_repository_api.list(pulp_domain=domain.name)
167+
assert repos.count == 2
168+
169+
# try to read repos in the default domain
170+
repos = apt_repository_api.list()
171+
assert repos.count == 0
172+
173+
# try to create a repo
174+
with pytest.raises(ApiException) as e:
175+
deb_repository_factory(pulp_domain=domain.name)
176+
assert e.value.status == 403
177+
finally:
178+
deb_cleanup_domains([domain], cleanup_repositories=True)
179+
180+
181+
# @pytest.mark.parallel
182+
# def test_cross_domain_copy_all(
183+
# deb_domain_factory,
184+
# ):
185+
# """Test attempting to copy between different domains."""
186+
# domain_1 = None
187+
# domain_2 = None

pulp_deb/tests/functional/conftest.py

+81
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66
import stat
77
import subprocess
8+
import uuid
89

910
from pulp_deb.tests.functional.constants import DEB_SIGNING_SCRIPT_STRING
1011
from pulpcore.client.pulp_deb import (
@@ -555,3 +556,83 @@ def _deb_get_content_types(content_api_name, content_type, repo, version_href=No
555556
return api.list(repository_version=latest_version_href).results
556557

557558
return _deb_get_content_types
559+
560+
561+
@pytest.fixture
562+
def deb_setup_domain(
563+
gen_object_with_cleanup,
564+
domains_api_client,
565+
deb_remote_factory,
566+
deb_repository_factory,
567+
deb_get_fixture_server,
568+
deb_sync_repository,
569+
monitor_task,
570+
):
571+
def _deb_setup_domain(sync=True, pulp_domain=None, url=None):
572+
if url == None:
573+
url = deb_get_fixture_server()
574+
elif url.startswith("http"):
575+
url = url
576+
else:
577+
url = deb_get_fixture_server(url)
578+
579+
if not pulp_domain:
580+
body = {
581+
"name": str(uuid.uuid4()),
582+
"storage_class": "pulpcore.app.models.storage.FileSystem",
583+
"storage_settings": {"MEDIA_ROOT": "/var/lib/pulp/media/"},
584+
}
585+
pulp_domain = gen_object_with_cleanup(domains_api_client, body)
586+
587+
remote = deb_remote_factory(url, pulp_domain=pulp_domain.name)
588+
repo = deb_repository_factory(pulp_domain=pulp_domain.name)
589+
590+
if sync:
591+
deb_sync_repository(remote, repo)
592+
593+
594+
@pytest.fixture
595+
def deb_cleanup_domains(pulpcore_bindings, monitor_task, apt_repository_api):
596+
def _deb_cleanup_domains(
597+
domains,
598+
content_api_client=None,
599+
cleanup_repositories=False,
600+
repository_api_client=apt_repository_api,
601+
):
602+
for domain in domains:
603+
# clean up each domain specified
604+
if domain:
605+
if cleanup_repositories:
606+
# delete repos from the domain
607+
for repo in repository_api_client.list(pulp_domain=domain.name).results:
608+
monitor_task(repository_api_client.delete(repo.pulp_href).task)
609+
# let orphan cleanup reap the resulting abandoned content
610+
monitor_task(
611+
pulpcore_bindings.OrphansCleanupApi.cleanup(
612+
{"orphan_protection_time": 0}, pulp_domain=domain.name
613+
).task
614+
)
615+
616+
if content_api_client:
617+
# if we have a client, check that each domain is empty of that kind-of entity
618+
for domain in domains:
619+
if domain:
620+
assert content_api_client.list(pulp_domain=domain.name).count == 0
621+
622+
return _deb_cleanup_domains
623+
624+
625+
@pytest.fixture
626+
def deb_domain_factory(pulpcore_bindings, gen_object_with_cleanup):
627+
"""Fixture to create a domain."""
628+
629+
def _deb_domain_factory(name=None):
630+
name = str(uuid.uuid4()) if name is None else name
631+
body = {
632+
"name": name,
633+
"storage_class": "pulpcore.app.models.storage.FileSystem",
634+
"storage_settings": {"MEDIA_ROOT": "/var/lib/pulp/media/"},
635+
}
636+
return gen_object_with_cleanup(pulpcore_bindings.DomainsApi, body)
637+
638+
return _deb_domain_factory

0 commit comments

Comments
 (0)