class PythonDistributionSerializer(core_serializers.DistributionSerializer): """ Serializer for Pulp distributions for the Python type. """ publication = core_serializers.DetailRelatedField( required=False, help_text=_("Publication to be served"), view_name_pattern=r"publications(-.*/.*)?-detail", queryset=core_models.Publication.objects.exclude(complete=False), allow_null=True, ) base_url = serializers.SerializerMethodField(read_only=True) allow_uploads = serializers.BooleanField( default=True, help_text=_("Allow packages to be uploaded to this index.")) remote = core_serializers.DetailRelatedField( required=False, help_text= _('Remote that can be used to fetch content when using pull-through caching.' ), view_name_pattern=r"remotes(-.*/.*)?-detail", queryset=core_models.Remote.objects.all(), allow_null=True) def get_base_url(self, obj): """Gets the base url.""" return f"{settings.PYPI_API_HOSTNAME}/pypi/{obj.base_path}/" class Meta: fields = core_serializers.DistributionSerializer.Meta.fields + ( 'publication', "allow_uploads", "remote") model = python_models.PythonDistribution
class ManifestSerializer(platform.ContentSerializer): """ Serializer for Manifests. """ digest = serializers.CharField(help_text="sha256 of the Manifest file") schema_version = serializers.IntegerField( help_text="Docker schema version") media_type = serializers.CharField( help_text="Docker media type of the file") blobs = platform.DetailRelatedField( many=True, help_text="Blobs that are referenced by this Manifest", view_name='docker-blobs-detail', queryset=models.ManifestBlob.objects.all()) config_blob = platform.DetailRelatedField( many=False, help_text="Blob that contains configuration for this Manifest", view_name='docker-blobs-detail', queryset=models.ManifestBlob.objects.all()) _artifact = MinimalArtifactSerializer( many=False, help_text="File related to this content") class Meta: fields = tuple( set(platform.ContentSerializer.Meta.fields) - {'_artifacts'}) + ('digest', 'schema_version', 'media_type', 'blobs', 'config_blob', '_artifact') model = models.ImageManifest
class MavenDistributionSerializer(platform.BaseDistributionSerializer): """ Serializer for Maven Distributions. """ remote = platform.DetailRelatedField( required=False, help_text= _("Remote that can be used to fetch content when using pull-through caching." ), queryset=models.MavenRemote.objects.all(), allow_null=True, ) class Meta: fields = platform.BaseDistributionSerializer.Meta.fields + ("remote", ) model = models.MavenDistribution
class PythonPublicationSerializer(core_serializers.PublicationSerializer): """ A Serializer for PythonPublication. """ distributions = core_serializers.DetailRelatedField( help_text=_('This publication is currently being hosted as configured by these ' 'distributions.'), source="python_pythondistribution", view_name="filedistributions-detail", many=True, read_only=True, ) class Meta: fields = core_serializers.PublicationSerializer.Meta.fields + ('distributions',) model = python_models.PythonPublication
class PythonDistributionSerializer(core_serializers.DistributionSerializer): """ Serializer for Pulp distributions for the Python type. """ publication = core_serializers.DetailRelatedField( required=False, help_text=_("Publication to be served"), view_name_pattern=r"publications(-.*/.*)?-detail", queryset=core_models.Publication.objects.exclude(complete=False), allow_null=True, ) class Meta: fields = core_serializers.DistributionSerializer.Meta.fields + ( 'publication', ) model = python_models.PythonDistribution
class PythonDistributionSerializer(core_serializers.DistributionSerializer): """ Serializer for Pulp distributions for the Python type. """ publication = core_serializers.DetailRelatedField( required=False, help_text=_("Publication to be served"), view_name_pattern=r"publications(-.*/.*)?-detail", queryset=core_models.Publication.objects.exclude(complete=False), allow_null=True, ) base_url = serializers.SerializerMethodField(read_only=True) allow_uploads = serializers.BooleanField( default=True, help_text=_("Allow packages to be uploaded to this index.")) def get_base_url(self, obj): """Gets the base url.""" return f"{settings.PYPI_API_HOSTNAME}/pypi/{obj.base_path}/" def validate(self, data): """ Ensure publication and repository are not set at the same time. This is needed here till https://pulp.plan.io/issues/8761 is resolved. """ data = super().validate(data) repository_provided = data.get("repository", None) publication_provided = data.get("publication", None) if repository_provided and publication_provided: raise serializers.ValidationError( _("Only one of the attributes 'repository' and 'publication' " "may be used simultaneously.")) if repository_provided or publication_provided: data["repository"] = repository_provided data["publication"] = publication_provided return data class Meta: fields = core_serializers.DistributionSerializer.Meta.fields + ( 'publication', "allow_uploads") model = python_models.PythonDistribution
class ManifestTagSerializer(platform.ContentSerializer): """ Serializer for ManifestTags. """ name = serializers.CharField(help_text="Tag name") manifest = platform.DetailRelatedField( many=False, help_text="Manifest that is tagged", view_name='docker-manifests-detail', queryset=models.ImageManifest.objects.all()) _artifact = MinimalArtifactSerializer( many=False, help_text="File related to this content") class Meta: fields = tuple( set(platform.ContentSerializer.Meta.fields) - {'_artifacts'}) + ('name', 'manifest', '_artifact') model = models.ManifestTag
class DockerDistributionSerializer(platform.ModelSerializer): """ A serializer for DockerDistribution. """ _href = platform.IdentityField(view_name='docker-distributions-detail') name = serializers.CharField( help_text=_('A unique distribution name. Ex, `rawhide` and `stable`.'), validators=[ validators.MaxLengthValidator( models.DockerDistribution._meta.get_field('name').max_length, message=_( 'Distribution name length must be less than {} characters' ).format( models.DockerDistribution._meta.get_field( 'name').max_length)), UniqueValidator(queryset=models.DockerDistribution.objects.all()) ]) 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.DockerDistribution._meta.get_field( 'base_path').max_length, message= _('Distribution base_path length must be less than {} characters' ).format( models.DockerDistribution._meta.get_field( 'base_path').max_length)), UniqueValidator(queryset=models.DockerDistribution.objects.all()), ]) publisher = platform.DetailRelatedField( required=False, help_text=_( 'Publications created by this publisher and repository are automatically' 'served as defined by this distribution'), queryset=models.DockerPublisher.objects.all(), allow_null=True) publication = platform.RelatedField( required=False, help_text=_( 'The publication being served as defined by this distribution'), queryset=Publication.objects.exclude(complete=False), view_name='publications-detail', allow_null=True) repository = platform.RelatedField( required=False, help_text=_( 'Publications created by this repository and publisher are automatically' 'served as defined by this distribution'), queryset=Repository.objects.all(), view_name='repositories-detail', allow_null=True) registry_path = RegistryPathField( source='base_path', read_only=True, help_text=_( 'The Registry hostame:port/name/ to use with docker pull command defined by ' 'this distribution.')) class Meta: model = models.DockerDistribution fields = platform.ModelSerializer.Meta.fields + ( 'name', 'base_path', 'publisher', 'publication', 'registry_path', 'repository', 'content_guard', ) def _validate_path_overlap(self, path): # look for any base paths nested in path search = path.split("/")[0] q = Q(base_path=search) for subdir in path.split("/")[1:]: search = "/".join((search, subdir)) q |= Q(base_path=search) # look for any base paths that nest path q |= Q(base_path__startswith='{}/'.format(path)) qs = models.DockerDistribution.objects.filter(q) if self.instance is not None: qs = qs.exclude(pk=self.instance.pk) match = qs.first() if match: raise serializers.ValidationError( detail=_("Overlaps with existing distribution '" "{}'").format(match.name)) return path def validate_base_path(self, path): """ Validate that path is valid. Args: path (str): the path at which the registry will be served at """ self._validate_relative_path(path) return self._validate_path_overlap(path) def validate(self, data): """ Validates that the data dict has valid DockerDistribution info. Args: data (dict): dict representing a DockerDistribution """ super().validate(data) if 'publisher' in data: publisher = data['publisher'] elif self.instance: publisher = self.instance.publisher else: publisher = None if 'repository' in data: repository = data['repository'] elif self.instance: repository = self.instance.repository else: repository = None if publisher and not repository: raise serializers.ValidationError({ 'repository': _("Repository must be set if " "publisher is set.") }) if repository and not publisher: raise serializers.ValidationError({ 'publisher': _("Publisher must be set if " "repository is set.") }) return data