Skip to content

Commit 6367063

Browse files
authored
Merge pull request #335 from gerrod3/new_sync_filters
Added new sync filtering options
2 parents 0c003d1 + 1552b36 commit 6367063

File tree

10 files changed

+360
-8
lines changed

10 files changed

+360
-8
lines changed

CHANGES/339.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added new sync filter `keep_latest_packages` to specify how many latest versions of packages to sync

CHANGES/341.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added new sync filters `package_types` and `exclude_platforms` to specify package types to sync

docs/workflows/sync.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ You can also use version specifiers to "exclude" certain versions of a project,
104104
"scipy"
105105
]'
106106

107+
You can also filter packages by their type, platform and amount synced through the "package_types",
108+
"exclude_platforms", and "keep_latest_packages" fields respectively, like so::
109+
110+
$ pulp python remote create \
111+
--name 'complex-filters' \
112+
--url 'https://pypi.org/' \
113+
--includes '["django"]' \
114+
--package-types '["sdist", "bdist-wheel"]' # only sync sdist and bdist-wheel package types \
115+
--exclude-platforms '["windows"]' # exclude any packages built for windows \
116+
--keep-latest-packages 5 # keep the five latest versions
117+
107118
Reference: `Python Remote Usage <../restapi.html#tag/remotes>`_
108119

109120
.. _mirror-workflow:
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Generated by Django 2.2.19 on 2021-03-26 13:31
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+
('python', '0002_pythonpackagecontent_python_version'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='pythonremote',
16+
name='exclude_platforms',
17+
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=10), choices=[('windows', 'windows'), ('macos', 'macos'), ('freebsd', 'freebsd'), ('linux', 'linux')], default=list, size=None),
18+
),
19+
migrations.AddField(
20+
model_name='pythonremote',
21+
name='keep_latest_packages',
22+
field=models.IntegerField(default=0),
23+
),
24+
migrations.AddField(
25+
model_name='pythonremote',
26+
name='package_types',
27+
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15), choices=[('bdist_dmg', 'bdist_dmg'), ('bdist_dumb', 'bdist_dumb'), ('bdist_egg', 'bdist_egg'), ('bdist_msi', 'bdist_msi'), ('bdist_rpm', 'bdist_rpm'), ('bdist_wheel', 'bdist_wheel'), ('bdist_wininst', 'bdist_wininst'), ('sdist', 'sdist')], default=list, size=None),
28+
),
29+
]

pulp_python/app/models.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from logging import getLogger
22

33
from aiohttp.web import json_response
4-
from django.contrib.postgres.fields import JSONField
4+
from django.contrib.postgres.fields import ArrayField, JSONField
55
from django.db import models
66

77
from pulpcore.plugin.models import (
@@ -29,6 +29,11 @@
2929
("sdist", "sdist"),
3030
)
3131

32+
PLATFORMS = (("windows", "windows"),
33+
("macos", "macos"),
34+
("freebsd", "freebsd"),
35+
("linux", "linux"))
36+
3237

3338
class PythonDistribution(PublicationDistribution):
3439
"""
@@ -157,6 +162,11 @@ class PythonRemote(Remote):
157162
prereleases = models.BooleanField(default=False)
158163
includes = JSONField(default=list)
159164
excludes = JSONField(default=list)
165+
package_types = ArrayField(models.CharField(max_length=15, blank=True),
166+
choices=PACKAGE_TYPES, default=list)
167+
keep_latest_packages = models.IntegerField(default=0)
168+
exclude_platforms = ArrayField(models.CharField(max_length=10, blank=True),
169+
choices=PLATFORMS, default=list)
160170

161171
class Meta:
162172
default_related_name = "%(app_label)s_%(model_name)s"

pulp_python/app/serializers.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,16 @@ class Meta:
237237
model = python_models.PythonPackageContent
238238

239239

240+
class MultipleChoiceArrayField(serializers.MultipleChoiceField):
241+
"""
242+
A wrapper to make sure this DRF serializer works properly with ArrayFields.
243+
"""
244+
245+
def to_internal_value(self, data):
246+
"""Converts set to list."""
247+
return list(super().to_internal_value(data))
248+
249+
240250
class PythonRemoteSerializer(core_serializers.RemoteSerializer):
241251
"""
242252
A Serializer for PythonRemote.
@@ -267,6 +277,26 @@ class PythonRemoteSerializer(core_serializers.RemoteSerializer):
267277
choices=core_models.Remote.POLICY_CHOICES,
268278
default=core_models.Remote.ON_DEMAND
269279
)
280+
package_types = MultipleChoiceArrayField(
281+
required=False,
282+
help_text=_("The package types to sync for Python content. Leave blank to get every"
283+
"package type."),
284+
choices=python_models.PACKAGE_TYPES,
285+
default=list
286+
)
287+
keep_latest_packages = serializers.IntegerField(
288+
required=False,
289+
help_text=_("The amount of latest versions of a package to keep on sync, includes"
290+
"pre-releases if synced. Default 0 keeps all versions."),
291+
default=0
292+
)
293+
exclude_platforms = MultipleChoiceArrayField(
294+
required=False,
295+
help_text=_("List of platforms to exclude syncing Python packages for. Possible values"
296+
"include: windows, macos, freebsd, and linux."),
297+
choices=python_models.PLATFORMS,
298+
default=list
299+
)
270300

271301
def validate_includes(self, value):
272302
"""Validates the includes"""
@@ -292,7 +322,8 @@ def validate_excludes(self, value):
292322

293323
class Meta:
294324
fields = core_serializers.RemoteSerializer.Meta.fields + (
295-
"includes", "excludes", "prereleases"
325+
"includes", "excludes", "prereleases", "package_types", "keep_latest_packages",
326+
"exclude_platforms",
296327
)
297328
model = python_models.PythonRemote
298329

pulp_python/app/tasks/sync.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ def create_bandersnatch_config(remote):
7474
config["blocklist"]["packages"] = "\n".join(remote.excludes)
7575
if not remote.prereleases:
7676
config["plugins"]["enabled"] += "prerelease_release\n"
77+
if remote.package_types:
78+
rrfm = "regex_release_file_metadata"
79+
config["plugins"]["enabled"] += rrfm
80+
if not config.has_section(rrfm):
81+
config.add_section(rrfm)
82+
config[rrfm]["any:release_file.packagetype"] = "\n".join(remote.package_types)
83+
if remote.keep_latest_packages:
84+
config["plugins"]["enabled"] += "latest_release\n"
85+
if not config.has_section("latest_release"):
86+
config.add_section("latest_release")
87+
config["latest_release"]["keep"] = str(remote.keep_latest_packages)
88+
if remote.exclude_platforms:
89+
config["plugins"]["enabled"] += "exclude_platform\n"
90+
if not config.has_section("blocklist"):
91+
config.add_section("blocklist")
92+
config["blocklist"]["platforms"] = "\n".join(remote.exclude_platforms)
7793

7894

7995
class PythonBanderStage(Stage):

pulp_python/app/viewsets.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,22 @@ def from_bandersnatch(self, request):
160160
enabled = bander_config.get("plugins", "enabled")
161161
enabled_all = "all" in enabled
162162
data["prereleases"] = not (enabled_all or "prerelease_release" in enabled)
163-
if bander_config.has_option("allowlist", "packages") and \
164-
(enabled_all or "allowlist_project" in enabled):
165-
data["includes"] = bander_config.get("allowlist", "packages").split()
166-
if bander_config.has_option("blocklist", "packages") and \
167-
(enabled_all or "blocklist_project" in enabled):
168-
data["excludes"] = bander_config.get("blocklist", "packages").split()
163+
# TODO refactor to use a translation object
164+
plugin_filters = { # plugin : (section_name, bander_option, pulp_option)
165+
"allowlist_project": ("allowlist", "packages", "includes"),
166+
"blocklist_project": ("blocklist", "packages", "excludes"),
167+
"regex_release_file_metadata": (
168+
"regex_release_file_metadata",
169+
"any:release_file.packagetype",
170+
"package_types",
171+
),
172+
"latest_release": ("latest_release", "keep", "keep_latest_packages"),
173+
"exclude_platform": ("blocklist", "platforms", "exclude_platforms"),
174+
}
175+
for plugin, options in plugin_filters.items():
176+
if (enabled_all or plugin in enabled) and \
177+
bander_config.has_option(options[0], options[1]):
178+
data[options[2]] = bander_config.get(options[0], options[1]).split()
169179
remote = python_serializers.PythonRemoteSerializer(data=data, context={"request": request})
170180
remote.is_valid(raise_exception=True)
171181
remote.save()

0 commit comments

Comments
 (0)