Skip to content

Commit

Permalink
Split Distribution into two objects
Browse files Browse the repository at this point in the history
The Distribution contained options which should not be mixed.
Specifically the repository and repository_version options go together
and the publication goes by itself.

This PR splits that object into two new objects
RepositoryVersionDistribution and PublicationDistribution. Each receives
a viewset, serializer, and filterset to match. Each also is a full
Detail model and can be used by plugins without additional code from
them.

https://pulp.plan.io/issues/4785
closes #4785
  • Loading branch information
Brian Bouterse committed May 9, 2019
1 parent be43e1a commit c37854b
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 129 deletions.
26 changes: 18 additions & 8 deletions pulpcore/app/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 2.2.1 on 2019-05-08 18:30
# Generated by Django 2.2.1 on 2019-05-08 21:46

from django.conf import settings
import django.core.validators
Expand Down Expand Up @@ -376,6 +376,18 @@ class Migration(migrations.Migration):
},
bases=('core.progressreport',),
),
migrations.CreateModel(
name='RepositoryVersionDistribution',
fields=[
('basedistribution_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='_repository_version_distributions', serialize=False, to='core.BaseDistribution')),
('repository', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_repository_version_distributions', to='core.Repository')),
('repository_version', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_repository_version_distributions', to='core.RepositoryVersion')),
],
options={
'default_related_name': '_repository_version_distributions',
},
bases=('core.basedistribution',),
),
migrations.CreateModel(
name='RemoteArtifact',
fields=[
Expand Down Expand Up @@ -425,19 +437,17 @@ class Migration(migrations.Migration):
],
options={
'default_related_name': 'published_artifact',
'unique_together': {('publication', 'content_artifact'), ('publication', 'relative_path')},
'unique_together': {('publication', 'relative_path'), ('publication', 'content_artifact')},
},
),
migrations.CreateModel(
name='Distribution',
name='PublicationDistribution',
fields=[
('basedistribution_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='_distributions', serialize=False, to='core.BaseDistribution')),
('publication', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Publication')),
('repository', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.Repository')),
('repository_version', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_distributions', to='core.RepositoryVersion')),
('basedistribution_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='_publication_distributions', serialize=False, to='core.BaseDistribution')),
('publication', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='_publication_distributions', to='core.Publication')),
],
options={
'default_related_name': '_distributions',
'default_related_name': '_publication_distributions',
},
bases=('core.basedistribution',),
),
Expand Down
5 changes: 3 additions & 2 deletions pulpcore/app/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
from .publication import ( # noqa
ContentGuard,
BaseDistribution,
Distribution,
Publication,
PublicationDistribution,
PublishedArtifact,
PublishedMetadata
PublishedMetadata,
RepositoryVersionDistribution,
)
from .repository import ( # noqa
Exporter,
Expand Down
29 changes: 22 additions & 7 deletions pulpcore/app/models/publication.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,23 +232,38 @@ class BaseDistribution(MasterModel):
remote = models.ForeignKey(Remote, null=True, on_delete=models.SET_NULL)


class Distribution(BaseDistribution):
class PublicationDistribution(BaseDistribution):
"""
A distribution defines how a publication is distributed by Pulp's content app.
The use of repository, repository_version, or publication are mutually exclusive, and this
model's serializer will raise a ValidationError if they are used together.
Define how Pulp's content app will serve a :term:`Publication`.
Relations:
publication (models.ForeignKey): Publication to be served.
"""

TYPE = 'publication_distributions'

publication = models.ForeignKey(Publication, null=True, on_delete=models.SET_NULL)

class Meta:
default_related_name = '_publication_distributions'


class RepositoryVersionDistribution(BaseDistribution):
"""
Define how Pulp's content app will serve a :term:`RepositoryVersion` or :term:`Repository`.
The ``repository`` and ``repository_version`` fields cannot be used together.
Relations:
repository (models.ForeignKey): The latest RepositoryVersion for this Repository will be
served.
repository_version (models.ForeignKey): RepositoryVersion to be served.
"""

publication = models.ForeignKey(Publication, null=True, on_delete=models.SET_NULL)
TYPE = 'repository_version_distributions'

repository = models.ForeignKey(Repository, null=True, on_delete=models.SET_NULL)
repository_version = models.ForeignKey(RepositoryVersion, null=True, on_delete=models.SET_NULL)

class Meta:
default_related_name = '_distributions'
default_related_name = '_repository_version_distributions'
3 changes: 2 additions & 1 deletion pulpcore/app/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
from .publication import ( # noqa
BaseDistributionSerializer,
ContentGuardSerializer,
DistributionSerializer,
PublicationSerializer,
PublicationDistributionSerializer,
RepositoryVersionDistributionSerializer,
)
from .repository import ( # noqa
ExporterSerializer,
Expand Down
133 changes: 68 additions & 65 deletions pulpcore/app/serializers/publication.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

class PublicationSerializer(MasterModelSerializer):
_href = DetailIdentityField()
_distributions = DetailRelatedField(
_publication_distributions = DetailRelatedField(
help_text=_('This publication is currently being served as'
'defined by these distributions.'),
many=True,
Expand Down Expand Up @@ -71,8 +71,8 @@ class Meta:
abstract = True
model = models.Publication
fields = MasterModelSerializer.Meta.fields + (
'_publication_distributions',
'publisher',
'_distributions',
'repository_version',
'repository'
)
Expand Down Expand Up @@ -100,20 +100,35 @@ class Meta:

class BaseDistributionSerializer(MasterModelSerializer):
_href = DetailIdentityField()
base_path = serializers.CharField(
help_text=_('The base (relative) path component of the published url. Avoid paths that \
overlap with other distribution base paths (e.g. "foo" and "foo/bar")'),
validators=[validators.MaxLengthValidator(
models.BaseDistribution._meta.get_field('base_path').max_length,
message=_('`base_path` length must be less than {} characters').format(
models.BaseDistribution._meta.get_field('base_path').max_length
)),
UniqueValidator(queryset=models.BaseDistribution.objects.all()),
]
)
base_url = BaseURLField(
source='base_path', read_only=True,
help_text=_('The URL for accessing the publication as defined by this distribution.')
)
content_guard = DetailRelatedField(
required=False,
help_text=_('An optional content-guard.'),
queryset=models.ContentGuard.objects.all(),
allow_null=True
)
name = serializers.CharField(
help_text=_('A unique distribution name. Ex, `rawhide` and `stable`.'),
help_text=_('A unique name. Ex, `rawhide` and `stable`.'),
validators=[validators.MaxLengthValidator(
models.Distribution._meta.get_field('name').max_length,
message=_('Distribution name length must be less than {} characters').format(
models.Distribution._meta.get_field('name').max_length
models.BaseDistribution._meta.get_field('name').max_length,
message=_('`name` length must be less than {} characters').format(
models.BaseDistribution._meta.get_field('name').max_length
)),
UniqueValidator(queryset=models.Distribution.objects.all())]
UniqueValidator(queryset=models.BaseDistribution.objects.all())]
)
remote = DetailRelatedField(
required=False,
Expand All @@ -124,61 +139,13 @@ class BaseDistributionSerializer(MasterModelSerializer):

class Meta:
fields = ModelSerializer.Meta.fields + (
'base_path',
'base_url',
'content_guard',
'name',
'remote',
)


class DistributionSerializer(BaseDistributionSerializer):
base_path = serializers.CharField(
help_text=_('The base (relative) path component of the published url. Avoid paths that \
overlap with other distribution base paths (e.g. "foo" and "foo/bar")'),
validators=[validators.MaxLengthValidator(
models.Distribution._meta.get_field('base_path').max_length,
message=_('Distribution base_path length must be less than {} characters').format(
models.Distribution._meta.get_field('base_path').max_length
)),
UniqueValidator(queryset=models.Distribution.objects.all()),
]
)
base_url = BaseURLField(
source='base_path', read_only=True,
help_text=_('The URL for accessing the publication as defined by this distribution.')
)
publication = DetailRelatedField(
required=False,
help_text=_('Publication to be served'),
queryset=models.Publication.objects.exclude(complete=False),
allow_null=True
)
repository = RelatedField(
required=False,
help_text=_('The latest RepositoryVersion for this Repository will be served.'),
queryset=models.Repository.objects.all(),
view_name='repositories-detail',
allow_null=True
)
repository_version = NestedRelatedField(
required=False,
help_text=_('RepositoryVersion to be served'),
queryset=models.RepositoryVersion.objects.exclude(complete=False),
view_name='versions-detail',
allow_null=True,
lookup_field='number',
parent_lookup_kwargs={'repository_pk': 'repository__pk'},
)

class Meta:
model = models.Distribution
fields = BaseDistributionSerializer.Meta.fields + (
'base_path',
'base_url',
'publication',
'repository',
'repository_version',
)

def _validate_path_overlap(self, path):
# look for any base paths nested in path
search = path.split("/")[0]
Expand Down Expand Up @@ -208,14 +175,50 @@ def validate_base_path(self, path):
def validate(self, data):
super().validate(data)

mutex_keys = ['publication', 'repository', 'repository_version']
in_use_keys = []
for mkey in mutex_keys:
if mkey in data:
in_use_keys.append(mkey)

if len(in_use_keys) > 1:
msg = _("The attributes {keys} must be used exclusively.".format(keys=in_use_keys))
if 'repository' in data and 'repository_version' in data:
msg = _("The attributes 'repository' and 'repository_version' must be used"
"exclusively.")
raise serializers.ValidationError(msg)

return data


class PublicationDistributionSerializer(BaseDistributionSerializer):
publication = DetailRelatedField(
required=False,
help_text=_('Publication to be served'),
queryset=models.Publication.objects.exclude(complete=False),
allow_null=True
)

class Meta:
model = models.PublicationDistribution
fields = BaseDistributionSerializer.Meta.fields + (
'publication',
)


class RepositoryVersionDistributionSerializer(BaseDistributionSerializer):
repository = RelatedField(
required=False,
help_text=_('The latest RepositoryVersion for this Repository will be served.'),
queryset=models.Repository.objects.all(),
view_name='repositories-detail',
allow_null=True
)
repository_version = NestedRelatedField(
required=False,
help_text=_('RepositoryVersion to be served'),
queryset=models.RepositoryVersion.objects.exclude(complete=False),
view_name='versions-detail',
allow_null=True,
lookup_field='number',
parent_lookup_kwargs={'repository_pk': 'repository__pk'},
)

class Meta:
model = models.RepositoryVersionDistribution
fields = BaseDistributionSerializer.Meta.fields + (
'repository',
'repository_version',
)
3 changes: 2 additions & 1 deletion pulpcore/app/viewsets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
from .publication import ( # noqa
ContentGuardFilter,
ContentGuardViewSet,
DistributionViewSet,
PublicationDistributionViewSet,
PublicationViewSet,
RepositoryVersionDistributionViewSet,
)
from .repository import ( # noqa
ExporterViewSet,
Expand Down
Loading

0 comments on commit c37854b

Please sign in to comment.