Skip to content

Commit a034018

Browse files
committed
Added support for Distributor when creating repository
Previously it wasn't possible to create repository with distributor because of inconsintent naming of various fields which resulted in Bad requests. This is now fixed and distributors can be created along repository. Only mininal configuration is currently supported.
1 parent 7cf6636 commit a034018

File tree

3 files changed

+159
-23
lines changed

3 files changed

+159
-23
lines changed

src/pubtools/pulplib/_impl/client/client.py

+64-14
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from more_executors import Executors
1111
from more_executors.futures import f_map, f_flat_map, f_return, f_proxy, f_sequence
1212
from io import StringIO
13-
13+
from ..compat_attr import evolve
1414
from ..model.repository.repo_lock import LOCK_CLAIM_STR
1515
from ..page import Page
1616
from ..criteria import Criteria
@@ -1083,6 +1083,13 @@ def create_repository(self, repo):
10831083
body["importer_type_id"] = importer[0]["importer_type_id"] if importer else None
10841084
body["importer_config"] = importer[0]["config"] if importer else None
10851085

1086+
# re-key distributor dict keys due to pulp API inconsistency
1087+
for item in body["distributors"]:
1088+
item["distributor_id"] = item["id"]
1089+
item["distributor_config"] = item["config"]
1090+
del item["config"]
1091+
del item["id"]
1092+
10861093
def log_existing_repo(exception):
10871094
if (
10881095
getattr(exception, "response", None) is not None
@@ -1094,25 +1101,49 @@ def log_existing_repo(exception):
10941101
raise exception
10951102

10961103
def check_repo(repo_on_server):
1104+
# evolve some fields that don't have to be set before repository creation
1105+
# but they're typically set automatically after creation call which results in
1106+
# inequality between `repo_on_server` and `repo`
1107+
dists = [evolve(item, repo_id=repo_id) for item in repo.distributors]
1108+
repo_updated = evolve(
1109+
repo, relative_url=repo_on_server.relative_url, distributors=dists
1110+
)
10971111
try:
10981112
assert (
1099-
repo_on_server == repo
1113+
repo_on_server == repo_updated
11001114
), "Repo exists on server with unexpected values"
11011115
except AssertionError:
11021116
if importer:
1103-
for attr in ["type_id", "config"]:
1104-
expected = getattr(repo.importer, attr)
1105-
current = getattr(repo_on_server.importer, attr)
1106-
if expected != current:
1107-
LOG.error(
1108-
"Repository %s contains wrong importer %s\n"
1109-
"\t expected: %s\n"
1110-
"\t current: %s\n",
1111-
repo_id,
1112-
attr,
1113-
expected,
1114-
current,
1117+
self._check_resource(
1118+
"importer",
1119+
["type_id", "config"],
1120+
repo_updated.importer,
1121+
repo_on_server.importer,
1122+
repo_updated.id,
1123+
)
1124+
1125+
extra_dist = set()
1126+
for expected_item in repo_updated.distributors:
1127+
for current_item in repo_on_server.distributors:
1128+
if expected_item.type_id == current_item.type_id:
1129+
self._check_resource(
1130+
"distributor",
1131+
["id", "type_id", "last_publish"],
1132+
expected_item,
1133+
current_item,
1134+
repo_updated.id,
11151135
)
1136+
extra_dist.discard(current_item.type_id)
1137+
else:
1138+
extra_dist.add(current_item.type_id)
1139+
1140+
for item in extra_dist:
1141+
LOG.error(
1142+
"Repository %s contains unexpected distributor with type: %s",
1143+
repo_id,
1144+
item,
1145+
)
1146+
11161147
LOG.exception(
11171148
"Repository %s exists on server and contains unexpected values",
11181149
repo_id,
@@ -1131,3 +1162,22 @@ def check_repo(repo_on_server):
11311162
out = f_flat_map(out, check_repo)
11321163

11331164
return f_proxy(out)
1165+
1166+
@staticmethod
1167+
def _check_resource(
1168+
resource_type, fields, expected_resource, current_resource, repo_id
1169+
):
1170+
for attr in fields:
1171+
expected = getattr(expected_resource, attr)
1172+
current = getattr(current_resource, attr)
1173+
if expected != current:
1174+
LOG.error(
1175+
"Repository %s contains wrong %s %s\n"
1176+
"\t expected: %s\n"
1177+
"\t current: %s\n",
1178+
repo_id,
1179+
resource_type,
1180+
attr,
1181+
expected,
1182+
current,
1183+
)

tests/fake/test_fake_create_repo.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
1-
from pubtools.pulplib import FakeController, Repository
1+
from pubtools.pulplib import FakeController, Repository, Distributor
22

33

44
def test_create_repository():
55
"""Client.create_repository() with fake client adds new repositories to controller."""
66
controller = FakeController()
77

88
client = controller.client
9-
repo_1 = client.create_repository(Repository(id="repo1"))
10-
repo_2 = client.create_repository(Repository(id="repo2"))
9+
repo_1 = client.create_repository(
10+
Repository(
11+
id="repo1",
12+
distributors=[Distributor(id="dist1", type_id="yum_distributor")],
13+
)
14+
)
15+
repo_2 = client.create_repository(
16+
Repository(
17+
id="repo2",
18+
distributors=[Distributor(id="dist2", type_id="yum_distributor")],
19+
)
20+
)
1121

1222
# adding already existing repository has no effect
13-
_ = client.create_repository(Repository(id="repo1"))
23+
_ = client.create_repository(
24+
Repository(
25+
id="repo1",
26+
distributors=[Distributor(id="dist1", type_id="yum_distributor")],
27+
)
28+
)
1429
# The change should be reflected in the controller,
1530
# with two repositories present
1631
assert controller.repositories == [repo_1.result(), repo_2.result()]

tests/repository/test_yum_repository.py

+76-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22
import logging
33
import requests
44

5-
from pubtools.pulplib import Repository, YumRepository, DetachedException, YumImporter
5+
import pubtools.pulplib._impl.compat_attr as attr
6+
from pubtools.pulplib import (
7+
Repository,
8+
YumRepository,
9+
DetachedException,
10+
YumImporter,
11+
Distributor,
12+
)
613

714

815
def test_from_data_gives_yum_repository():
@@ -216,7 +223,16 @@ def test_related_repositories_detached_client():
216223

217224

218225
def test_create_repository(client, requests_mocker):
219-
repo = YumRepository(id="yum_repo_new")
226+
repo = YumRepository(
227+
id="yum_repo_new",
228+
distributors=[
229+
Distributor(
230+
id="fake_id",
231+
type_id="yum_distributor",
232+
relative_url="yum_repo_new/foo/bar",
233+
)
234+
],
235+
)
220236

221237
# create request
222238
requests_mocker.post(
@@ -237,13 +253,44 @@ def test_create_repository(client, requests_mocker):
237253
"config": {},
238254
}
239255
],
256+
"distributors": [
257+
{
258+
"id": "fake_id",
259+
"distributor_type_id": "yum_distributor",
260+
"config": {"relative_url": "yum_repo_new/foo/bar"},
261+
"repo_id": "yum_repo_new",
262+
}
263+
],
240264
}
241265
],
242266
)
243267

244-
out = client.create_repository(repo)
268+
out = client.create_repository(repo).result()
245269
# check return value of create_repository() call
246-
assert out.result() == repo
270+
# relative_url wasn't set before request for `repo`
271+
assert repo.relative_url is None
272+
# but it's set after creation
273+
assert out.relative_url == "yum_repo_new/foo/bar"
274+
275+
# repo_id of distributor isn't set before creation call
276+
assert repo.distributors[0].repo_id is None
277+
# but it's set after creation
278+
assert out.distributors[0].repo_id == "yum_repo_new"
279+
# evolve original repo object with new values
280+
repo = attr.evolve(
281+
repo,
282+
relative_url="yum_repo_new/foo/bar",
283+
distributors=[
284+
Distributor(
285+
id="fake_id",
286+
type_id="yum_distributor",
287+
relative_url="yum_repo_new/foo/bar",
288+
repo_id="yum_repo_new",
289+
)
290+
],
291+
)
292+
# and do full assert
293+
assert out == repo
247294

248295
hist = requests_mocker.request_history
249296
# there should be exactly 2 requests sent - create and search
@@ -256,6 +303,14 @@ def test_create_repository(client, requests_mocker):
256303
# are automatically added for yum repository
257304
assert create_query["importer_type_id"] == "yum_importer"
258305
assert create_query["importer_config"] == {}
306+
# check distributor data
307+
assert len(create_query["distributors"]) == 1
308+
assert create_query["distributors"][0]["distributor_id"] == "fake_id"
309+
assert create_query["distributors"][0]["distributor_type_id"] == "yum_distributor"
310+
assert (
311+
create_query["distributors"][0]["distributor_config"]["relative_url"]
312+
== "yum_repo_new/foo/bar"
313+
)
259314

260315
# check the search request for created repo
261316
search_query = hist[1].json()
@@ -331,7 +386,9 @@ def test_create_repository_already_exists(client, requests_mocker, caplog):
331386

332387
def test_create_repository_wrong_data(client, requests_mocker, caplog):
333388
repo = YumRepository(
334-
id="yum_repo_existing", importer=YumImporter(config={"new": "value"})
389+
id="yum_repo_existing",
390+
importer=YumImporter(config={"new": "value"}),
391+
distributors=[Distributor(id="test_dist", type_id="yum_distributor")],
335392
)
336393

337394
requests_mocker.post(
@@ -353,6 +410,18 @@ def test_create_repository_wrong_data(client, requests_mocker, caplog):
353410
"config": {"current": "value"},
354411
}
355412
],
413+
"distributors": [
414+
{
415+
"id": "fake_id_1",
416+
"distributor_type_id": "yum_distributor",
417+
"config": {},
418+
},
419+
{
420+
"id": "fake_id_2",
421+
"distributor_type_id": "iso_distributor",
422+
"config": {},
423+
},
424+
],
356425
}
357426
],
358427
)
@@ -363,6 +432,8 @@ def test_create_repository_wrong_data(client, requests_mocker, caplog):
363432
for text in (
364433
"Repository yum_repo_existing already exists",
365434
"Repository yum_repo_existing contains wrong importer config",
435+
"Repository yum_repo_existing contains wrong distributor id",
436+
"Repository yum_repo_existing contains unexpected distributor with type: iso_distributor",
366437
"Repository yum_repo_existing exists on server and contains unexpected values",
367438
):
368439
assert text in caplog.text

0 commit comments

Comments
 (0)