def validate(self, data): """Validates that all the fields make sense.""" data = super().validate(data) if "containerfile" in data: if "containerfile_artifact" in data: raise serializers.ValidationError( _("Only one of 'containerfile' and 'containerfile_artifact' may be specified.") ) data["containerfile_artifact"] = Artifact.init_and_validate(data.pop("containerfile")) elif "containerfile_artifact" not in data: raise serializers.ValidationError(_("'containerfile' or 'containerfile_artifact' must " "be specified.")) artifacts = {} if 'artifacts' in data: for url, relative_path in data['artifacts'].items(): if os.path.isabs(relative_path): raise serializers.ValidationError(_("Relative path cannot start with '/'. " "{0}").format(relative_path)) artifactfield = RelatedField(view_name='artifacts-detail', queryset=Artifact.objects.all(), source='*', initial=url) try: artifact = artifactfield.run_validation(data=url) artifacts[artifact.pk] = relative_path except serializers.ValidationError as e: # Append the URL of missing Artifact to the error message e.detail[0] = "%s %s" % (e.detail[0], url) raise e data['artifacts'] = artifacts return data
class AptPublicationSerializer(PublicationSerializer): """ A Serializer for AptPublication. """ simple = BooleanField( help_text="Activate simple publishing mode (all packages in one release component).", default=False, ) structured = BooleanField(help_text="Activate structured publishing mode.", default=False) signing_service = RelatedField( help_text="Sign Release files with this signing key", many=False, queryset=AptReleaseSigningService.objects.all(), view_name="signing-services-detail", required=False, ) def validate(self, data): """ Check that the publishing modes are compatible. """ data = super().validate(data) if not data["simple"] and not data["structured"]: raise ValidationError("one of simple or structured publishing mode must be selected") return data class Meta: fields = PublicationSerializer.Meta.fields + ("simple", "structured", "signing_service") model = AptPublication
class TagOperationSerializer(serializers.Serializer): """ A base serializer for tagging and untagging manifests. """ repository = RelatedField(required=True, view_name='repositories-detail', queryset=Repository.objects.all(), help_text='A URI of the repository.') tag = serializers.CharField(required=True, help_text='A tag name') def validate(self, data): """ Validate data passed through a request call. Check if a repository has got a reference to a latest repository version. A new dictionary object is initialized by the passed data and altered by a latest repository version. """ new_data = {} new_data.update(data) latest_version = RepositoryVersion.latest(data['repository']) if not latest_version: raise serializers.ValidationError( _("The latest repository version of '{}' was not found".format( data['repository']))) new_data['latest_version'] = latest_version return new_data
class RpmRepositorySerializer(RepositorySerializer): """ Serializer for Rpm Repositories. """ metadata_signing_service = RelatedField( help_text="A reference to an associated signing service.", view_name="signing-services-detail", queryset=AsciiArmoredDetachedSigningService.objects.all(), many=False, required=False, allow_null=True, ) retain_package_versions = serializers.IntegerField( help_text=_( "The number of versions of each package to keep in the repository; " "older versions will be purged. The default is '0', which will disable " "this feature and keep all versions of each package." ), min_value=0, required=False, ) class Meta: fields = RepositorySerializer.Meta.fields + ( "metadata_signing_service", "retain_package_versions", ) model = RpmRepository
class FileContentSerializer(ContentSerializer): """ Serializer for File Content. """ relative_path = serializers.CharField( help_text="Relative location of the file within the repository") artifact = RelatedField( view_name='artifacts-detail', help_text="Artifact file representing the physical content", queryset=Artifact.objects.all()) def validate(self, data): """Validate the FileContent data.""" artifact = data['artifact'] content = FileContent.objects.filter( digest=artifact.sha256, relative_path=data['relative_path']) if content.exists(): raise serializers.ValidationError( _("There is already a file content with relative " "path '{path}' and artifact '{artifact}'.").format( path=data["relative_path"], artifact=self.initial_data["artifact"])) return data class Meta: fields = tuple(set(ContentSerializer.Meta.fields) - {'artifacts'}) + ('relative_path', 'artifact') model = FileContent
class CollectionVersionSignatureSerializer(NoArtifactContentSerializer): """ A serializer for signature models. """ signed_collection = DetailRelatedField( help_text=_("The content this signature is pointing to."), view_name_pattern=r"content(-.*/.*)-detail", queryset=CollectionVersion.objects.all(), ) pubkey_fingerprint = serializers.CharField(help_text=_("The fingerprint of the public key.")) signing_service = RelatedField( help_text=_("The signing service used to create the signature."), view_name="signing-services-detail", queryset=SigningService.objects.all(), allow_null=True, ) class Meta: model = CollectionVersionSignature fields = NoArtifactContentSerializer.Meta.fields + ( "signed_collection", "pubkey_fingerprint", "signing_service", )
class PackageCategorySerializer(NoArtifactContentSerializer): """ PackageCategory serializer. """ id = serializers.CharField(help_text=_("Category id."), ) name = serializers.CharField(help_text=_("Category name."), allow_blank=True) description = serializers.CharField(help_text=_("Category description."), allow_blank=True) display_order = serializers.IntegerField( help_text=_("Category display order."), allow_null=True) group_ids = serializers.JSONField(help_text=_("Category group list."), allow_null=True) desc_by_lang = serializers.JSONField( help_text=_("Category description by language."), allow_null=True) name_by_lang = serializers.JSONField( help_text=_("Category name by language."), allow_null=True) digest = serializers.CharField(help_text=_("Category digest."), ) packagegroups = RelatedField( help_text=_("PackageGroups related to this category."), allow_null=True, required=False, queryset=PackageGroup.objects.all(), many=True, view_name='content-rpm/packagegroups-detail') class Meta: fields = NoArtifactContentSerializer.Meta.fields + ( 'id', 'name', 'description', 'display_order', 'group_ids', 'desc_by_lang', 'name_by_lang', 'digest', 'packagegroups') model = PackageCategory
class FileContentSerializer(ContentSerializer): """ Serializer for File Content. """ relative_path = serializers.CharField( help_text="Relative location of the file within the repository") artifact = RelatedField( view_name='artifacts-detail', help_text="Artifact file representing the physical content", queryset=Artifact.objects.all()) class Meta: fields = tuple(set(ContentSerializer.Meta.fields) - {'artifacts'}) + ('relative_path', 'artifact') model = FileContent
class CollectionVersionSignatureSerializer(NoArtifactContentUploadSerializer): """ A serializer for signature models. """ signed_collection = DetailRelatedField( help_text=_("The content this signature is pointing to."), view_name_pattern=r"content(-.*/.*)-detail", queryset=CollectionVersion.objects.all(), ) pubkey_fingerprint = serializers.CharField( help_text=_("The fingerprint of the public key."), read_only=True, ) signing_service = RelatedField( help_text=_("The signing service used to create the signature."), view_name="signing-services-detail", read_only=True, allow_null=True, ) def __init__(self, *args, **kwargs): """Ensure `file` field is required.""" super().__init__(*args, **kwargs) self.fields["file"].required = True def validate(self, data): """ Verify the signature is valid before creating it. """ data = super().validate(data) if "request" not in self.context: # Validate is called twice, first on the viewset, and second on the create task # data should be set up properly on the second time, when request isn't in context data = verify_signature_upload(data) return data class Meta: model = CollectionVersionSignature fields = NoArtifactContentUploadSerializer.Meta.fields + ( "signed_collection", "pubkey_fingerprint", "signing_service", )
class CookbookPackageContentSerializer(ContentSerializer): """Serializer for the cookbook content.""" name = serializers.CharField(help_text=_("name of the cookbook")) version = serializers.CharField(help_text=_("version of the cookbook"), required=False) dependencies = serializers.JSONField( help_text=_("dependencies of the cookbook"), read_only=True) artifact = RelatedField(view_name='artifacts-detail', help_text=_("tar archive containing the cookbook"), queryset=Artifact.objects.all()) artifacts = None class Meta: fields = tuple(field for field in ContentSerializer.Meta.fields if field != 'artifacts') \ + ('name', 'version', 'dependencies', 'artifact') model = CookbookPackageContent
class CookbookPublicationSerializer(PublicationSerializer): """ Serializer for Cookbook Publications. """ distributions = RelatedField( help_text=_( "This publication is currently being served as defined by these distributions." ), source="cookbook_cookbookdistribution", many=True, read_only=True, view_name="distributions-cookbook/cookbook-detail", ) class Meta: fields = PublicationSerializer.Meta.fields + ("distributions",) model = CookbookPublication
class ContainerRepositorySerializer(RepositorySerializer): """ Serializer for Container Repositories. """ manifest_signing_service = RelatedField( help_text="A reference to an associated signing service.", view_name="signing-services-detail", queryset=models.ManifestSigningService.objects.all(), many=False, required=False, allow_null=True, ) class Meta: fields = RepositorySerializer.Meta.fields + ( "manifest_signing_service", ) model = models.ContainerRepository
class AnsibleRoleVersionSerializer(ContentSerializer): """ A serializer for Ansible Role versions. """ _href = NestedIdentityField( view_name='versions-detail', parent_lookup_kwargs={'role_pk': 'role__pk'}, ) artifact = RelatedField( view_name='artifacts-detail', help_text="Artifact file representing the physical content", queryset=Artifact.objects.all()) version = serializers.CharField() class Meta: fields = ('_href', 'type', 'version', 'artifact') model = AnsibleRoleVersion
class PackageGroupSerializer(NoArtifactContentSerializer): """ PackageGroup serializer. """ id = serializers.CharField(help_text=_("PackageGroup id."), ) default = serializers.BooleanField(help_text=_("PackageGroup default."), required=False) user_visible = serializers.BooleanField( help_text=_("PackageGroup user visibility."), required=False) display_order = serializers.IntegerField( help_text=_("PackageGroup display order."), allow_null=True) name = serializers.CharField(help_text=_("PackageGroup name."), allow_null=True) description = serializers.CharField( help_text=_("PackageGroup description."), allow_null=True) packages = serializers.JSONField(help_text=_("PackageGroup package list."), allow_null=True) biarch_only = serializers.BooleanField( help_text=_("PackageGroup biarch only."), required=False) desc_by_lang = serializers.JSONField( help_text=_("PackageGroup description by language."), allow_null=True) name_by_lang = serializers.JSONField( help_text=_("PackageGroup name by language."), allow_null=True) digest = serializers.CharField(help_text=_("PackageGroup digest."), allow_null=True) related_packages = RelatedField( help_text=_("Packages related to this PackageGroup."), allow_null=True, required=False, queryset=Package.objects.all(), many=True, view_name='content-rpm/packages-detail') class Meta: fields = NoArtifactContentSerializer.Meta.fields + ( 'id', 'default', 'user_visible', 'display_order', 'name', 'description', 'packages', 'biarch_only', 'desc_by_lang', 'name_by_lang', 'digest', 'related_packages') model = PackageGroup
class AnsibleRepositorySignatureSerializer(serializers.Serializer): """ A serializer for the signing action. """ content_units = serializers.ListField( required=True, help_text=_( "List of collection version hrefs to sign, use * to sign all content in repository" ), ) signing_service = RelatedField( required=True, view_name="signing-services-detail", queryset=SigningService.objects.all(), help_text=_("A signing service to use to sign the collections"), ) def validate_content_units(self, value): """Make sure the list is correctly formatted.""" if len(value) > 1 and "*" in value: raise serializers.ValidationError("Cannot supply content units and '*'.") return value
class DockerDistributionSerializer(ModelSerializer): """ A serializer for DockerDistribution. """ _href = 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 = 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 = 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 = 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 = 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
class OCIBuildImageSerializer(serializers.Serializer): """ Serializer for building an OCI container image from a Containerfile. The Containerfile can either be specified via an artifact url, or a new file can be uploaded. A repository must be specified, to which the container image content will be added. """ containerfile_artifact = RelatedField( many=False, lookup_field="pk", view_name="artifacts-detail", queryset=Artifact.objects.all(), help_text=_("Artifact representing the Containerfile that should be used to run buildah."), ) containerfile = serializers.FileField( help_text=_("An uploaded Containerfile that should be used to run buildah."), required=False, ) tag = serializers.CharField( required=False, default="latest", help_text="A tag name for the new image being built." ) artifacts = serializers.JSONField( required=False, help_text="A JSON string where each key is an artifact href and the value is it's " "relative path (name) inside the /pulp_working_directory of the build container " "executing the Containerfile.", ) def __init__(self, *args, **kwargs): """Initializer for OCIBuildImageSerializer.""" super().__init__(*args, **kwargs) self.fields["containerfile_artifact"].required = False def validate(self, data): """Validates that all the fields make sense.""" data = super().validate(data) if "containerfile" in data: if "containerfile_artifact" in data: raise serializers.ValidationError( _("Only one of 'containerfile' and 'containerfile_artifact' may be specified.") ) data["containerfile_artifact"] = Artifact.init_and_validate(data.pop("containerfile")) elif "containerfile_artifact" not in data: raise serializers.ValidationError( _("'containerfile' or 'containerfile_artifact' must " "be specified.") ) artifacts = {} if "artifacts" in data: for url, relative_path in data["artifacts"].items(): if os.path.isabs(relative_path): raise serializers.ValidationError( _("Relative path cannot start with '/'. " "{0}").format(relative_path) ) artifactfield = RelatedField( view_name="artifacts-detail", queryset=Artifact.objects.all(), source="*", initial=url, ) try: artifact = artifactfield.run_validation(data=url) artifacts[artifact.pk] = relative_path except serializers.ValidationError as e: # Append the URL of missing Artifact to the error message e.detail[0] = "%s %s" % (e.detail[0], url) raise e data["artifacts"] = artifacts return data class Meta: fields = ( "containerfile_artifact", "containerfile", "repository", "tag", "artifacts", )
class ContainerDistributionSerializer(DistributionSerializer): """ A serializer for ContainerDistribution. """ registry_path = RegistryPathField( source="base_path", read_only=True, help_text=_( "The Registry hostame/name/ to use with docker pull command defined by " "this distribution." ), ) content_guard = DetailRelatedField( required=False, help_text=_("An optional content-guard. If none is specified, a default one will be used."), view_name=r"contentguards-container/content-redirect-detail", queryset=models.ContentRedirectContentGuard.objects.all(), allow_null=False, ) namespace = RelatedField( required=False, read_only=True, view_name="pulp_container/namespaces-detail", help_text=_("Namespace this distribution belongs to."), ) description = serializers.CharField( help_text=_("An optional description."), required=False, allow_null=True ) repository_version = RepositoryVersionRelatedField( required=False, help_text=_("RepositoryVersion to be served"), allow_null=True ) def validate(self, data): """ Validate the ContainterDistribution. Make sure there is an instance of ContentRedirectContentGuard always present in validated data. Validate that the distribution is not serving a repository versions of a push repository. """ validated_data = super().validate(data) if "content_guard" not in validated_data: validated_data["content_guard"] = ContentRedirectContentGuardSerializer.get_or_create( {"name": "content redirect"} ) if "repository_version" in validated_data: repository = validated_data["repository_version"].repository.cast() if repository.PUSH_ENABLED: raise serializers.ValidationError( _( "A container push repository cannot be distributed by specifying a " "repository version." ) ) if "base_path" in validated_data: base_path = validated_data["base_path"] namespace_name = base_path.split("/")[0] if "namespace" in validated_data: if validated_data["namespace"].name != namespace_name: raise serializers.ValidationError( _("Selected namespace does not match first component of base_path.") ) else: validated_data["namespace"] = ContainerNamespaceSerializer.get_or_create( {"name": namespace_name} ) return validated_data class Meta: model = models.ContainerDistribution fields = tuple(set(DistributionSerializer.Meta.fields) - {"base_url"}) + ( "repository_version", "registry_path", "namespace", "private", "description", )
class RpmRepositorySerializer(RepositorySerializer): """ Serializer for Rpm Repositories. """ autopublish = serializers.BooleanField( help_text=_( "Whether to automatically create publications for new repository versions, " "and update any distributions pointing to this repository."), default=False, required=False, ) metadata_signing_service = RelatedField( help_text="A reference to an associated signing service.", view_name="signing-services-detail", queryset=AsciiArmoredDetachedSigningService.objects.all(), many=False, required=False, allow_null=True, ) retain_package_versions = serializers.IntegerField( help_text= _("The number of versions of each package to keep in the repository; " "older versions will be purged. The default is '0', which will disable " "this feature and keep all versions of each package."), min_value=0, required=False, ) metadata_checksum_type = serializers.ChoiceField( help_text=_("The checksum type for metadata."), choices=CHECKSUM_CHOICES, default=CHECKSUM_TYPES.SHA256, ) package_checksum_type = serializers.ChoiceField( help_text=_("The checksum type for packages."), choices=CHECKSUM_CHOICES, default=CHECKSUM_TYPES.SHA256, ) gpgcheck = serializers.IntegerField( max_value=1, min_value=0, default=0, required=False, help_text=_("An option specifying whether a client should perform " "a GPG signature check on packages."), ) repo_gpgcheck = serializers.IntegerField( max_value=1, min_value=0, default=0, required=False, help_text=_("An option specifying whether a client should perform " "a GPG signature check on the repodata."), ) sqlite_metadata = serializers.BooleanField( default=False, required=False, help_text=_( "An option specifying whether Pulp should generate SQLite metadata." ), ) def validate(self, data): """Validate data.""" for field in ("metadata_checksum_type", "package_checksum_type"): if field in data and data[ field] not in settings.ALLOWED_CONTENT_CHECKSUMS: raise serializers.ValidationError( {field: _(ALLOWED_CHECKSUM_ERROR_MSG)}) validated_data = super().validate(data) return validated_data class Meta: fields = RepositorySerializer.Meta.fields + ( "autopublish", "metadata_signing_service", "retain_package_versions", "metadata_checksum_type", "package_checksum_type", "gpgcheck", "repo_gpgcheck", "sqlite_metadata", ) model = RpmRepository
class PackageSerializer(ContentSerializer): """ A Serializer for Package. Add serializers for the new fields defined in Package and add those fields to the Meta class keeping fields from the parent class as well. Provide help_text. """ artifact = RelatedField( view_name='artifacts-detail', help_text="Artifact file representing the physical content", queryset=Artifact.objects.all()) name = serializers.CharField(help_text=_("Name of the package"), ) epoch = serializers.CharField( help_text=_("The package's epoch"), allow_blank=True, required=False, ) version = serializers.CharField( help_text=_("The version of the package. For example, '2.8.0'"), ) release = serializers.CharField(help_text=_( "The release of a particular version of the package. e.g. '1.el7' or '3.f24'" ), ) arch = serializers.CharField(help_text=_( "The target architecture for a package." "For example, 'x86_64', 'i686', or 'noarch'"), ) pkgId = serializers.CharField( help_text=_("Checksum of the package file"), ) checksum_type = serializers.CharField( help_text=_("Type of checksum, e.g. 'sha256', 'md5'"), ) summary = serializers.CharField( help_text=_("Short description of the packaged software"), allow_blank=True, required=False, ) description = serializers.CharField( help_text=_("In-depth description of the packaged software"), allow_blank=True, required=False, ) url = serializers.CharField( help_text=_("URL with more information about the packaged software"), allow_blank=True, required=False, ) changelogs = serializers.CharField( help_text=_("Changelogs that package contains"), default="[]", required=False) files = serializers.CharField(help_text=_("Files that package contains"), default="[]", required=False) requires = serializers.CharField( help_text=_("Capabilities the package requires"), default="[]", required=False) provides = serializers.CharField( help_text=_("Capabilities the package provides"), default="[]", required=False) conflicts = serializers.CharField( help_text=_("Capabilities the package conflicts"), default="[]", required=False) obsoletes = serializers.CharField( help_text=_("Capabilities the package obsoletes"), default="[]", required=False) suggests = serializers.CharField( help_text=_("Capabilities the package suggests"), default="[]", required=False) enhances = serializers.CharField( help_text=_("Capabilities the package enhances"), default="[]", required=False) recommends = serializers.CharField( help_text=_("Capabilities the package recommends"), default="[]", required=False) supplements = serializers.CharField( help_text=_("Capabilities the package supplements"), default="[]", required=False) location_base = serializers.CharField( help_text=_("Base location of this package"), allow_blank=True, required=False) location_href = serializers.CharField( help_text=_("Relative location of package to the repodata"), ) rpm_buildhost = serializers.CharField( help_text=_("Hostname of the system that built the package"), allow_blank=True, required=False) rpm_group = serializers.CharField(help_text=_( "RPM group (See: http://fedoraproject.org/wiki/RPMGroups)"), allow_blank=True, required=False) rpm_license = serializers.CharField(help_text=_( "License term applicable to the package software (GPLv2, etc.)"), allow_blank=True, required=False) rpm_packager = serializers.CharField( help_text=_("Person or persons responsible for creating the package"), allow_blank=True, required=False) rpm_sourcerpm = serializers.CharField(help_text=_( "Name of the source package (srpm) the package was built from"), allow_blank=True, required=False) rpm_vendor = serializers.CharField( help_text=_("Name of the organization that produced the package"), allow_blank=True, required=False) rpm_header_start = serializers.IntegerField( help_text=_("First byte of the header"), ) rpm_header_end = serializers.IntegerField( help_text=_("Last byte of the header"), ) size_archive = serializers.IntegerField(help_text=_( "Size, in bytes, of the archive portion of the original package file")) size_installed = serializers.IntegerField(help_text=_( "Total size, in bytes, of every file installed by this package")) size_package = serializers.IntegerField( help_text=_("Size, in bytes, of the package")) time_build = serializers.IntegerField( help_text=_("Time the package was built in seconds since the epoch")) time_file = serializers.IntegerField( help_text=_("The 'file' time attribute in the primary XML - " "file mtime in seconds since the epoch.")) def create(self, validated_data): """ Create a Package. Overriding default create() to deal with artifact properly. Args: validated_data (dict): Data used to create the Package Returns: models.Package: The created Package """ artifact = validated_data.pop('artifact') package = Package.objects.create(**validated_data) ca = ContentArtifact(artifact=artifact, content=package, relative_path=package.filename) ca.save() return package class Meta: fields = tuple(set(ContentSerializer.Meta.fields) - {'artifacts'}) + ( 'artifact', 'name', 'epoch', 'version', 'release', 'arch', 'pkgId', 'checksum_type', 'summary', 'description', 'url', 'changelogs', 'files', 'requires', 'provides', 'conflicts', 'obsoletes', 'suggests', 'enhances', 'recommends', 'supplements', 'location_base', 'location_href', 'rpm_buildhost', 'rpm_group', 'rpm_license', 'rpm_packager', 'rpm_sourcerpm', 'rpm_vendor', 'rpm_header_start', 'rpm_header_end', 'size_archive', 'size_installed', 'size_package', 'time_build', 'time_file') model = Package
class RepositorySignSerializer(serializers.Serializer): """ Serializer for container images signing. """ manifest_signing_service = RelatedField( required=False, many=False, view_name="signing-services-detail", queryset=models.ManifestSigningService.objects.all(), help_text= _("A signing service to sign with. This will override a signing service set on the repo." ), allow_null=True, ) # Ask for the future_base_path for synced repos - this should match future/existing distribution # otherwise client verification can fail, it looks at 'docker-reference' in the signature json future_base_path = serializers.CharField( required=False, help_text=_( "Future base path content will be distributed at for sync repos"), ) tags_list = serializers.ListField(help_text=_("A list of tags to sign."), required=False) def validate(self, data): """Ensure that future_base_path is provided for synced repos.""" data = super().validate(data) repository = Repository.objects.get( pk=self.context["repository_pk"]).cast() try: signing_service = repository.manifest_signing_service except KeyError: signing_service = None if "manifest_signing_service" not in data and not signing_service: raise serializers.ValidationError({ "manifest_signing_service": _("This field is required since a signing_service is not set on the repo." ) }) if repository.PUSH_ENABLED: if "future_base_path" in data: raise serializers.ValidationError({ "future_base_path": _("This field cannot be set since this is a push repo type." ) }) data["future_base_path"] = repository.distributions.first( ).base_path else: if "future_base_path" not in data: raise serializers.ValidationError({ "future_base_path": _("This field is required since this is a sync repo type.") }) return data
class PackageEnvironmentSerializer(NoArtifactContentSerializer): """ PackageEnvironment serializer. """ id = serializers.CharField( help_text=_("Environment id."), ) name = serializers.CharField( help_text=_("Environment name."), allow_null=True ) description = serializers.CharField( help_text=_("Environment description."), allow_null=True ) display_order = serializers.IntegerField( help_text=_("Environment display order."), allow_null=True ) group_ids = serializers.JSONField( help_text=_("Environment group list."), allow_null=True ) option_ids = serializers.JSONField( help_text=_("Environment option ids"), allow_null=True ) desc_by_lang = serializers.JSONField( help_text=_("Environment description by language."), allow_null=True ) name_by_lang = serializers.JSONField( help_text=_("Environment name by language."), allow_null=True ) digest = serializers.CharField( help_text=_("Environment digest."), allow_null=True ) packagegroups = RelatedField( help_text=_("Groups related to this Environment."), allow_null=True, required=False, queryset=PackageGroup.objects.all(), many=True, view_name='content-rpm/packagegroups-detail' ) optionalgroups = RelatedField( help_text=_("Groups optionally related to this Environment."), allow_null=True, required=False, queryset=PackageGroup.objects.all(), many=True, view_name='content-rpm/packagegroups-detail' ) class Meta: fields = ( 'id', 'name', 'description', 'display_order', 'group_ids', 'option_ids', 'desc_by_lang', 'name_by_lang', 'digest', 'packagegroups', 'optionalgroups' ) model = PackageEnvironment