class ContainerNamespaceDetailSerializer(ContainerNamespaceSerializer): groups = GroupPermissionField() class Meta: model = models.ContainerNamespace fields = namespace_fields + ('groups', ) read_only_fields = ('name', 'my_permissions',)
class ContainerRepositorySerializer(serializers.ModelSerializer): pulp = serializers.SerializerMethodField() groups = GroupPermissionField() namespace = serializers.SerializerMethodField() id = serializers.SerializerMethodField() created = serializers.SerializerMethodField() updated = serializers.SerializerMethodField() # This serializer is purposfully refraining from using pulp fields directly # in the top level response body. This is because future versions of hub will have to # support indexing other registries and the API responses for a container # repository should make sense for containers hosted by pulp and containers # hosted by other registries. class Meta: model = models.ContainerDistribution read_only_fields = ( 'id', 'name', # this field will return null on instances where hub is indexing a # different repo 'pulp', 'namespace', 'description', 'created', 'updated') write_fields = ('groups', ) fields = read_only_fields + write_fields def get_id(self, distro): return distro.pulp_id def get_created(self, distro): return distro.repository.pulp_created def get_updated(self, distro): return distro.repository.pulp_last_updated def get_namespace(self, distro): return distro.namespace.name def get_pulp(self, distro): repo = distro.repository return { 'repository': { 'pulp_id': repo.pulp_id, 'pulp_type': repo.pulp_type, 'version': repo.latest_version().number, 'name': repo.name, 'description': repo.description, 'pulp_created': repo.pulp_created, }, 'distribution': { 'pulp_id': distro.pulp_id, 'name': distro.name, 'pulp_created': distro.pulp_created, 'base_path': distro.base_path, } }
class NamespaceSerializer(serializers.ModelSerializer): links = NamespaceLinkSerializer(many=True, required=False) groups = GroupPermissionField() class Meta: model = models.Namespace fields = ('id', 'name', 'company', 'email', 'avatar_url', 'description', 'links', 'groups', 'resources') # replace with a NamespaceNameSerializer and validate_name() ? def validate_name(self, name): if not name: raise ValidationError( detail={'name': "Attribute 'name' is required"}) if not re.match(r'^[a-z0-9_]+$', name): raise ValidationError( detail={ 'name': 'Name can only contain lower case letters, underscores and numbers' }) if len(name) <= 2: raise ValidationError( detail={'name': 'Name must be longer than 2 characters'}) if name.startswith('_'): raise ValidationError( detail={'name': "Name cannot begin with '_'"}) return name @transaction.atomic def create(self, validated_data): links_data = validated_data.pop('links', []) instance = models.Namespace.objects.create(**validated_data) # create NamespaceLink objects if needed new_links = [] for link_data in links_data: link_data["namespace"] = instance ns_link, created = models.NamespaceLink.objects.get_or_create( **link_data) new_links.append(ns_link) instance.links.set(new_links) return instance @transaction.atomic def update(self, instance, validated_data): links = validated_data.pop('links', None) if links is not None: instance.set_links(links) instance = super().update(instance, validated_data) instance.save() return instance
class SyncListSerializer(serializers.ModelSerializer): namespaces = serializers.SlugRelatedField( many=True, slug_field="name", queryset=models.Namespace.objects.all()) collections = SyncListCollectionSummarySerializer(many=True) groups = GroupPermissionField() def _get_repository(self, repository_id): try: repository = AnsibleRepository.objects.get(pulp_id=repository_id) return repository except AnsibleRepository.DoesNotExist: errmsg = 'Repository "{pulp_id}" not found while creating synclist' raise ValidationError(errmsg.format(pulp_id=repository_id)) def to_internal_value(self, data): repository_data = data.get("repository", None) if repository_data: data["repository"] = self._get_repository(repository_data) upstream_repository_data = data.get("upstream_repository", None) if upstream_repository_data: data["upstream_repository"] = self._get_repository( upstream_repository_data) else: # If not specified, use the default upstream repo data["upstream_repository"] = AnsibleRepository.objects.get( name=default_repo_name) return super().to_internal_value(data) @transaction.atomic def _create_repository(self, name): repository, created = AnsibleRepository.objects.get_or_create( name=name) if created: repository.save() return repository def _update_distribution(self, name_slug, repository): # Now the distro try: distribution, create = AnsibleDistribution.objects.get_or_create( name=name_slug, base_path=name_slug, ) except Exception as exc: log.exception(exc) raise # Now update the Distribution to point to the new Repository distribution.repository = repository distribution.save() return distribution @transaction.atomic def create(self, validated_data): collections_data = validated_data.pop("collections") namespaces_data = validated_data.pop("namespaces") repository = validated_data.pop("repository", None) name = validated_data.get("name") if not repository: repository = self._create_repository(name) try: instance = models.SyncList.objects.create(repository=repository, **validated_data) except IntegrityError as exc: raise ValidationError("Synclist already exists: %s" % exc) collections = [] for collection_data in collections_data: try: collections.append(Collection.objects.get(**collection_data)) except Collection.DoesNotExist: errmsg = ( 'Collection "{namespace}.{name}" not found while creating synclist {synclist}' ) raise ValidationError( errmsg.format( namespace=collection_data["namespace"], name=collection_data["name"], synclist=instance.name, )) instance.collections.clear() instance.collections.set(collections) instance.namespaces.add(*namespaces_data) return instance @transaction.atomic def update(self, instance, validated_data): collections_data = validated_data.get("collections", []) groups_data = validated_data.get("groups") if groups_data: instance.groups = groups_data namespaces_data = validated_data.get("namespaces") if namespaces_data is not None: instance.namespaces.set(namespaces_data) instance.policy = validated_data.get("policy", instance.policy) instance.name = validated_data.get("name", instance.name) new_collections = [] for collection_data in collections_data: try: new_collections.append( Collection.objects.get(**collection_data)) except Collection.DoesNotExist: errmsg = ( 'Collection "{namespace}.{name}" not found while updating synclist {synclist}' ) raise ValidationError( errmsg.format( namespace=collection_data["namespace"], name=collection_data["name"], synclist=instance.name, )) instance.collections.set(new_collections) # if collection goes from empty to having something in it, # then we also need to point the associated distro to the synclist repo if instance.collections.all() and instance.repository: self._update_distribution(instance.name, instance.repository) else: # synclist is no longer including/excluding anything, so point back # at the default upstream repo self._update_distribution(instance.name, instance.upstream_repository) instance.save() return instance class Meta: model = models.SyncList fields = [ "id", "name", "policy", "upstream_repository", "repository", "collections", "namespaces", "groups", ] read_only_fields = ("repository", )
class SyncListSerializer(serializers.ModelSerializer): namespaces = serializers.SlugRelatedField( many=True, slug_field="name", queryset=models.Namespace.objects.all()) collections = SyncListCollectionSummarySerializer(many=True) groups = GroupPermissionField() @transaction.atomic def create(self, validated_data): collections_data = validated_data.pop("collections") namespaces_data = validated_data.pop("namespaces") instance = models.SyncList.objects.create(**validated_data) collections = [] for collection_data in collections_data: try: collections.append(Collection.objects.get(**collection_data)) except Collection.DoesNotExist: errmsg = \ 'Collection "{namespace}.{name}" not found while creating synclist {synclist}' raise ValidationError( errmsg.format(namespace=collection_data["namespace"], name=collection_data["name"], synclist=instance.name)) instance.collections.clear() instance.collections.set(collections) instance.namespaces.add(*namespaces_data) return instance @transaction.atomic def update(self, instance, validated_data): collections_data = validated_data.get("collections") namespaces_data = validated_data.get("namespaces") instance.policy = validated_data.get("policy", instance.policy) instance.name = validated_data.get("name", instance.name) new_collections = [] for collection_data in collections_data: try: new_collections.append( Collection.objects.get(**collection_data)) except Collection.DoesNotExist: errmsg = \ 'Collection "{namespace}.{name}" not found while updating synclist {synclist}' raise ValidationError( errmsg.format(namespace=collection_data["namespace"], name=collection_data["name"], synclist=instance.name)) instance.collections.set(new_collections) instance.namespaces.set(namespaces_data) instance.save() instance.groups = validated_data.get('groups') return instance class Meta: model = models.SyncList fields = [ "id", "name", "policy", "repository", "collections", "namespaces", "groups", ]