Exemple #1
0
class ComposeTreeSerializer(StrictSerializerMixin,
                            DynamicFieldsSerializerMixin,
                            serializers.ModelSerializer):
    compose                 = serializers.SlugRelatedField(slug_field='compose_id', queryset=Compose.objects.all())
    variant                 = ComposeTreeVariantField()
    arch                    = serializers.SlugRelatedField(slug_field='name', queryset=Arch.objects.all())
    location                = ChoiceSlugField(slug_field='short', queryset=Location.objects.all())
    scheme                  = ChoiceSlugField(slug_field='name', queryset=Scheme.objects.all())
    url                     = serializers.CharField()
    synced_content          = ChoiceSlugField(slug_field='name', many=True, queryset=ContentCategory.objects.all())

    class Meta:
        model = ComposeTree
        fields = ('compose', 'variant', 'arch', 'location',
                  'scheme', 'url', 'synced_content')

    def validate(self, attrs):
        super(ComposeTreeSerializer, self).validate(attrs)
        compose = attrs.get('compose', None)
        variant = attrs.get('variant', None)
        arch = attrs.get('arch', None)
        if compose == variant.compose and arch in variant.arches:
            return attrs
        elif compose == variant.compose and arch not in variant.arches:
            raise serializers.ValidationError('Arch %s does not exist in given compose/variant branch' % arch)
        else:
            raise serializers.ValidationError('The combination with compose %s, variant %s, arch %s does not exist' %
                                              (compose, variant, arch))
Exemple #2
0
class ReleaseGroupSerializer(StrictSerializerMixin,
                             serializers.ModelSerializer):
    description = serializers.CharField(required=True)
    type = ChoiceSlugField(slug_field='name',
                           queryset=ReleaseGroupType.objects.all())
    releases = ChoiceSlugField(slug_field='release_id',
                               many=True,
                               queryset=Release.objects.all(),
                               allow_null=True,
                               required=False,
                               default=[])
    active = serializers.BooleanField(default=True)

    class Meta:
        model = ReleaseGroup
        fields = ('name', 'description', 'type', 'releases', 'active')

    def to_internal_value(self, data):
        releases = data.get('releases', [])
        for release in releases:
            try:
                Release.objects.get(release_id=release)
            except Release.DoesNotExist:
                raise serializers.ValidationError(
                    {'detail': 'release %s does not exist' % release})

        return super(ReleaseGroupSerializer, self).to_internal_value(data)
Exemple #3
0
class RepoSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    release_id       = serializers.CharField(source='variant_arch.variant.release.release_id')
    variant_uid      = serializers.CharField(source='variant_arch.variant.variant_uid')
    arch             = serializers.CharField(source='variant_arch.arch.name')
    service          = ChoiceSlugField(slug_field='name',
                                       queryset=models.Service.objects.all())
    repo_family      = ChoiceSlugField(slug_field='name',
                                       queryset=models.RepoFamily.objects.all())
    content_format   = ChoiceSlugField(slug_field='name',
                                       queryset=models.ContentFormat.objects.all())
    content_category = ChoiceSlugField(slug_field='name',
                                       queryset=models.ContentCategory.objects.all())
    name             = serializers.CharField()
    shadow           = serializers.BooleanField(required=False)

    class Meta:
        model = models.Repo
        fields = ('id', 'release_id', 'variant_uid', 'arch', 'service', 'repo_family',
                  'content_format', 'content_category', 'name', 'shadow', 'product_id')

    def validate(self, attrs):
        try:
            variant_arch = attrs.get('variant_arch', {})
            release_id  = variant_arch.get('variant', {}).get('release', {}).get('release_id', '')
            variant_uid = variant_arch.get('variant', {}).get('variant_uid', '')
            arch        = variant_arch.get('arch', {}).get('name', '')
            if self.instance and self.partial:
                variantarch = self.instance.variant_arch
                release_id = release_id or variantarch.variant.release.release_id
                variant_uid = variant_uid or variantarch.variant.variant_uid
                arch = arch or variantarch.arch.name
            attrs['variant_arch'] = release_models.VariantArch.objects.get(
                variant__release__release_id=release_id,
                variant__variant_uid=variant_uid,
                arch__name=arch
            )
        except ObjectDoesNotExist:
            raise serializers.ValidationError(
                'No VariantArch for release_id=%s, variant_uid=%s, arch=%s'
                % (release_id, variant_uid, arch)
            )
        if not self.instance:
            # Validate repo name.
            instance = models.Repo(**attrs)
            instance.clean()
            # Validate repo is unique.
            try:
                models.Repo.objects.get(**attrs)
                raise serializers.ValidationError(
                    'Repo with this Variant arch, Service, Repo family, Content format, '
                    'Content category, Name and Shadow already exists.'
                )
            except models.Repo.DoesNotExist:
                pass
        return super(RepoSerializer, self).validate(attrs)
class ComposeSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    compose_type = serializers.CharField()
    release = serializers.CharField()
    sigkeys = serializers.SerializerMethodField()
    rpm_mapping_template = serializers.SerializerMethodField()
    acceptance_testing = ChoiceSlugField(
        slug_field='name',
        queryset=ComposeAcceptanceTestingState.objects.all())
    linked_releases = LinkedReleasesField(slug_field='release_id',
                                          many=True,
                                          queryset=Release.objects.all())
    rtt_tested_architectures = serializers.SerializerMethodField()

    class Meta:
        model = Compose
        fields = (
            'compose_id',
            'compose_date',
            'compose_type',
            'compose_respin',
            'release',
            'compose_label',
            'deleted',
            'rpm_mapping_template',
            'sigkeys',
            'acceptance_testing',
            'linked_releases',
            'rtt_tested_architectures',
        )

    def get_rpm_mapping_template(self, obj):
        """url"""
        return urldecode(
            reverse('composerpmmapping-detail',
                    args=[obj.compose_id, '{{package}}'],
                    request=self.context['request']))

    def get_rtt_tested_architectures(self, obj):
        """{"variant": {"arch": "testing status"}}"""
        return obj.get_arch_testing_status()

    def get_sigkeys(self, obj):
        """["string"]"""
        compose_id_to_key_id_cache = self.context.get(
            "compose_id_to_key_id_cache")
        if compose_id_to_key_id_cache:
            result = sorted(list(compose_id_to_key_id_cache.get(obj.id, [])))
            if obj.exist_unsigned:
                result.append(None)
            return result

        return obj.sigkeys

    def validate(self, attrs):
        release = attrs.get('release') or getattr(
            getattr(self, 'object', None), 'release')
        if release and release in attrs.get('linked_releases', []):
            raise serializers.ValidationError(
                'Can not link to the release for which the compose was built.')
        return attrs
class BaseProductSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    base_product_id = serializers.CharField(read_only=True)
    release_type = ChoiceSlugField(slug_field='short', queryset=ReleaseType.objects.all())

    class Meta:
        model = BaseProduct
        fields = ('base_product_id', 'short', 'version', 'name', 'release_type')
Exemple #6
0
class ReleaseScheduleSerializer(StrictSerializerMixin,
                                serializers.HyperlinkedModelSerializer):
    """
    ReleaseSchedule Serializer
    """

    release = serializers.SlugRelatedField(slug_field='release_id',
                                           read_only=False,
                                           queryset=Release.objects.all())
    sla = ChoiceSlugField(slug_field='name', queryset=SLA.objects.all())
    date = serializers.DateField()
    active = serializers.BooleanField(read_only=True)
    release_url = serializers.HyperlinkedRelatedField(
        source="release",
        read_only=True,
        view_name='release-detail',
        lookup_field='release_id',
    )
    sla_url = serializers.HyperlinkedRelatedField(
        source="sla",
        read_only=True,
        view_name='sla-detail',
    )

    class Meta:
        model = ReleaseSchedule
        fields = ('id', 'release', 'sla', 'date', 'active', 'release_url',
                  'sla_url')
Exemple #7
0
class ReleaseVariantSerializer(StrictSerializerMixin,
                               serializers.ModelSerializer):
    type = ChoiceSlugField(source='variant_type',
                           slug_field='name',
                           queryset=VariantType.objects.all())
    release = serializers.SlugRelatedField(slug_field='release_id',
                                           queryset=Release.objects.all())
    id = serializers.CharField(source='variant_id')
    uid = serializers.CharField(source='variant_uid')
    name = serializers.CharField(source='variant_name')
    arches = VariantArchNestedSerializer(source='variantarch_set', many=True)

    key_combination_error = 'add_arches/remove_arches can not be combined with arches.'

    extra_fields = ['add_arches', 'remove_arches']

    class Meta:
        model = Variant
        fields = ('release', 'id', 'uid', 'name', 'type', 'arches')

    def to_internal_value(self, data):
        # Save value of attributes not directly corresponding to serializer
        # fields. We can't rely on data dict to be mutable, so the values can
        # not be removed from it.
        self.add_arches = data.get('add_arches', None)
        self.remove_arches = data.get('remove_arches', None)
        return super(ReleaseVariantSerializer, self).to_internal_value(data)

    def update(self, instance, validated_data):
        arches = validated_data.pop('variantarch_set', [])
        instance = super(ReleaseVariantSerializer,
                         self).update(instance, validated_data)
        if arches:
            if self.add_arches or self.remove_arches:
                raise FieldError(self.key_combination_error)
            # If arches were completely specified, try first to remove unwanted
            # arches, then create new ones.
            requested = dict([(x.arch.name, x) for x in arches])
            for variant in instance.variantarch_set.all():
                if variant.arch.name in requested:
                    del requested[variant.arch.name]
                else:
                    variant.delete()
            for arch in requested.values():
                arch.variant = instance
                arch.save()

        # These loops can only do something on partial update: when doing PUT,
        # "arches" is required and if any of the other arch modifications were
        # specified, an exception would be raised above.
        for arch_name in self.add_arches or []:
            arch = common_models.Arch.objects.get(name=arch_name)
            vararch = VariantArch(arch=arch, variant=instance)
            vararch.save()

        for arch_name in self.remove_arches or []:
            instance.variantarch_set.filter(arch__name=arch_name).delete()

        return instance
Exemple #8
0
class BuildImageRTTTestsSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    format = serializers.CharField(source='image_format.name', read_only=True)
    test_result = ChoiceSlugField(slug_field='name', queryset=ComposeAcceptanceTestingState.objects.all())
    build_nvr = serializers.CharField(source='image_id', read_only=True)

    class Meta:
        model = models.BuildImage
        fields = ('id', 'build_nvr', 'format', 'test_result')
class PushTargetSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    name = serializers.CharField()
    description = serializers.CharField(allow_blank=True)
    host = serializers.CharField(allow_blank=True, required=False)
    service = ChoiceSlugField(slug_field='name',
                              queryset=models.Service.objects.all())

    class Meta:
        model = models.PushTarget
        fields = ('id', 'name', 'description', 'service', 'host')
Exemple #10
0
class SLAToComponentBranchSerializerForComponentBranch(
        serializers.ModelSerializer):
    """
    A serializer for the SLAToComponentBranch model to be used in the
    ComponentBranch serializer
    """
    sla = ChoiceSlugField(slug_field='name', read_only=True)
    eol = serializers.DateField(read_only=True)

    class Meta:
        model = SLAToComponentBranch
        fields = ('id', 'sla', 'eol')
Exemple #11
0
class ReleaseComponentSerializer(DynamicFieldsSerializerMixin,
                                 StrictSerializerMixin,
                                 serializers.HyperlinkedModelSerializer):
    """
    ReleaseComponent Serializer
    """

    release = ReleaseField(read_only=False)
    global_component = serializers.SlugRelatedField(slug_field='name', read_only=False, queryset=GlobalComponent.objects.all())
    dist_git_branch = serializers.CharField(source='inherited_dist_git_branch', required=False)
    dist_git_web_url = serializers.URLField(required=False, max_length=200, read_only=True)
    bugzilla_component = TreeForeignKeyField(read_only=False, required=False, allow_null=True)
    brew_package = serializers.CharField(required=False)
    active = serializers.BooleanField(required=False, default=True)
    type = ChoiceSlugField(slug_field='name', queryset=ReleaseComponentType.objects.all(), required=False)

    def update(self, instance, validated_data):
        signals.releasecomponent_serializer_extract_data.send(sender=self, validated_data=validated_data)
        instance = super(ReleaseComponentSerializer, self).update(instance, validated_data)
        signals.releasecomponent_serializer_post_update.send(sender=self, release_component=instance)
        if hasattr(instance, 'pk'):
            # reload to make sure changes in mapping are reflected
            instance = ReleaseComponent.objects.get(pk=instance.pk)
        # from view's doc, for ReleaseComponent,
        # PUT and PATCH update works the same as each other except `name` is required when PUT update,
        # so there will be not setattr here.
        return instance

    def create(self, validated_data):
        signals.releasecomponent_serializer_extract_data.send(sender=self, validated_data=validated_data)
        instance = super(ReleaseComponentSerializer, self).create(validated_data)
        signals.releasecomponent_serializer_post_create.send(sender=self, release_component=instance)
        return instance

    def to_internal_value(self, data):
        # Raise error explictly when release are given.
        if self.instance:
            allowed_keys = self.get_allowed_keys() - set(['release'])
            extra_fields = set(data.keys()) - allowed_keys
            self.maybe_raise_error(extra_fields)
            data['release'] = self.instance.release
            data['global_component'] = data.get('global_component', self.instance.global_component)
        return super(ReleaseComponentSerializer, self).to_internal_value(data)

    def validate_release(self, value):
        if not value.is_active():
            raise serializers.ValidationError('Can not create a release component with an inactive release.')
        return value

    class Meta:
        model = ReleaseComponent
        fields = ('id', 'release', 'bugzilla_component', 'brew_package', 'global_component',
                  'name', 'dist_git_branch', 'dist_git_web_url', 'active', 'type')
Exemple #12
0
class ComposeTreeRTTTestSerializer(StrictSerializerMixin,
                                   DynamicFieldsSerializerMixin,
                                   serializers.ModelSerializer):
    compose                 = serializers.CharField(source='variant.compose.compose_id', read_only=True)
    variant                 = ComposeTreeVariantField(read_only=True)
    arch                    = serializers.CharField(source='arch.name', read_only=True)
    test_result             = ChoiceSlugField(source='rtt_testing_status', slug_field='name',
                                              queryset=ComposeAcceptanceTestingState.objects.all())

    class Meta:
        model = VariantArch
        fields = ('compose', 'variant', 'arch', 'test_result')
class MultiDestinationSerializer(StrictSerializerMixin,
                                 serializers.ModelSerializer):
    global_component = ChoiceSlugField(slug_field='name',
                                       queryset=GlobalComponent.objects.all())
    origin_repo = RepoField()
    destination_repo = RepoField()
    subscribers = ChoiceSlugField(slug_field='username',
                                  many=True,
                                  queryset=Person.objects.filter(active=True),
                                  default=[])
    active = serializers.BooleanField(default=True)

    class Meta:
        model = models.MultiDestination
        fields = (
            'id',
            'global_component',
            'origin_repo',
            'destination_repo',
            'subscribers',
            'active',
        )
Exemple #14
0
class ComposeImageRTTTestSerializer(StrictSerializerMixin,
                                    DynamicFieldsSerializerMixin,
                                    serializers.ModelSerializer):
    compose                 = serializers.CharField(source='variant_arch.variant.compose.compose_id', read_only=True)
    variant                 = serializers.CharField(source='variant_arch.variant', read_only=True)
    arch                    = serializers.CharField(source='variant_arch.arch', read_only=True)
    file_name               = serializers.CharField(source='image.file_name', read_only=True)
    test_result             = ChoiceSlugField(source='rtt_test_result', slug_field='name',
                                              queryset=ComposeAcceptanceTestingState.objects.all())

    class Meta:
        model = ComposeImage
        fields = ('compose', 'variant', 'arch', 'file_name', 'test_result')
Exemple #15
0
class ReleaseComponentRelationshipSerializer(StrictSerializerMixin,
                                             serializers.ModelSerializer):
    type = ChoiceSlugField(
        queryset=ReleaseComponentRelationshipType.objects.all(),
        slug_field='name',
        required=True,
        source='relation_type')
    from_component = ReleaseComponentField(
        required=True, queryset=ReleaseComponent.objects.all())
    to_component = ReleaseComponentField(
        required=True, queryset=ReleaseComponent.objects.all())

    class Meta:
        model = ReleaseComponentRelationship
        fields = ('id', 'type', 'from_component', 'to_component')
Exemple #16
0
class ComponentBranchSerializer(StrictSerializerMixin,
                                DynamicFieldsSerializerMixin,
                                serializers.ModelSerializer):
    """
    A serializer for the ComponentBranch model
    """
    name = BranchNameField()
    global_component = serializers.SlugRelatedField(
        slug_field='name', queryset=GlobalComponent.objects.all())
    type = ChoiceSlugField(slug_field='name',
                           queryset=ReleaseComponentType.objects.all())
    critical_path = serializers.BooleanField(default=False)
    slas = SLAToComponentBranchSerializerForComponentBranch(many=True,
                                                            read_only=True)
    active = serializers.SerializerMethodField('is_active')

    def is_active(self, branch):
        """
        Calls the is_branch_active function to determine if the branch is still
        active
        :param branch: a ComponentBranch object
        :return: a boolean
        """
        return is_branch_active(branch)

    class Meta:
        model = ComponentBranch
        fields = ('id', 'global_component', 'name', 'slas', 'type', 'active',
                  'critical_path')

    def update(self, instance, validated_data):
        """
        Override the update function to not allow a user to modify the branch
        name
        """
        if 'name' in validated_data and instance.name != validated_data['name']:
            raise serializers.ValidationError({
                'name':
                ['You may not modify the branch\'s name due to policy']
            })

        return super(ComponentBranchSerializer,
                     self).update(instance, validated_data)
Exemple #17
0
class ComponentBranchSerializerWithoutSLA(serializers.Serializer):
    """
    A serializer for the ComponentBranch model to be used in the
    SLAToComponentBranch serializer
    """
    id = serializers.IntegerField(read_only=True)
    name = BranchNameField()
    global_component = serializers.SlugRelatedField(
        slug_field='name', queryset=GlobalComponent.objects.all())
    type = ChoiceSlugField(slug_field='name',
                           queryset=ReleaseComponentType.objects.all())
    critical_path = serializers.BooleanField(required=False)
    active = serializers.SerializerMethodField('is_active')

    def is_active(self, branch):
        """
        Calls the is_branch_active function to determine if the branch is still
        active
        :param branch: a ComponentBranch object
        :return: a boolean
        """
        return is_branch_active(branch)
class ReleaseSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    release_type = ChoiceSlugField(slug_field='short',
                                   queryset=ReleaseType.objects.all())
    release_id = serializers.CharField(read_only=True)
    compose_set = serializers.SerializerMethodField()
    base_product = serializers.SlugRelatedField(slug_field='base_product_id',
                                                queryset=BaseProduct.objects.all(),
                                                required=False,
                                                default=None,
                                                allow_null=True)
    product_version = serializers.SlugRelatedField(slug_field='product_version_id',
                                                   queryset=ProductVersion.objects.all(),
                                                   required=False,
                                                   allow_null=True,
                                                   default=None)
    active = serializers.BooleanField(default=True)
    integrated_with = serializers.SlugRelatedField(slug_field='release_id',
                                                   queryset=Release.objects.all(),
                                                   required=False,
                                                   allow_null=True,
                                                   default=None)
    sigkey = serializers.SlugRelatedField(slug_field='key_id',
                                          queryset=SigKey.objects.all(),
                                          required=False,
                                          allow_null=True,
                                          default=None)
    allow_buildroot_push = serializers.BooleanField(default=False)
    allowed_debuginfo_services = ChoiceSlugField(slug_field='name',
                                                 many=True, queryset=Service.objects.all(),
                                                 required=False, default=[])
    allowed_push_targets = serializers.SlugRelatedField(
        many=True, slug_field='name', queryset=PushTarget.objects.all(), default=[])

    class Meta:
        model = Release
        fields = ('release_id', 'short', 'version', 'name', 'base_product',
                  'active', 'product_version', 'release_type',
                  'compose_set', 'integrated_with', 'sigkey', 'allow_buildroot_push',
                  'allowed_debuginfo_services', 'allowed_push_targets')

    def get_compose_set(self, obj):
        """[Compose.compose_id]"""
        return [compose.compose_id for compose in sorted(obj.get_all_composes())]

    def create(self, validated_data):
        signals.release_serializer_extract_data.send(sender=self, validated_data=validated_data)
        obj = super(ReleaseSerializer, self).create(validated_data)
        signals.release_serializer_post_create.send(sender=self, release=obj)
        return obj

    def update(self, instance, validated_data):
        signals.release_serializer_extract_data.send(sender=self, validated_data=validated_data)
        obj = super(ReleaseSerializer, self).update(instance, validated_data)
        signals.release_serializer_post_update.send(sender=self, release=obj)
        if hasattr(instance, 'pk'):
            # reload to make sure changes in mapping are reflected
            obj = Release.objects.get(pk=obj.pk)
        # By default, PUT does not erase optional field if not specified. This
        # loops over all optional fields and resets them manually.
        if not self.partial:
            for field_name, field in self.fields.iteritems():
                if not field.read_only and field_name not in validated_data:
                    attr = field.source or field_name
                    try:
                        if hasattr(obj, attr):
                            setattr(obj, attr, None)
                    except ValueError:
                        pass
        obj.save()
        return obj

    def validate(self, data):
        convert_push_targets_to_mask(data, self.instance, 'product_version')
        return data
class ReleaseSerializer(StrictSerializerMixin, serializers.ModelSerializer):
    release_type = ChoiceSlugField(slug_field='short',
                                   queryset=ReleaseType.objects.all())
    release_id = serializers.CharField(read_only=True)
    compose_set = serializers.SerializerMethodField()
    base_product = serializers.SlugRelatedField(
        slug_field='base_product_id',
        queryset=BaseProduct.objects.all(),
        required=False,
        default=None,
        allow_null=True)
    product_version = serializers.SlugRelatedField(
        slug_field='product_version_id',
        queryset=ProductVersion.objects.all(),
        required=False,
        allow_null=True,
        default=None)
    active = serializers.BooleanField(default=True)
    integrated_with = serializers.SlugRelatedField(
        slug_field='release_id',
        queryset=Release.objects.all(),
        required=False,
        allow_null=True,
        default=None)
    sigkey = serializers.SlugRelatedField(slug_field='key_id',
                                          queryset=SigKey.objects.all(),
                                          required=False,
                                          allow_null=True,
                                          default=None)
    allow_buildroot_push = serializers.BooleanField(default=False)
    allowed_debuginfo_services = ChoiceSlugField(
        slug_field='name',
        many=True,
        queryset=Service.objects.all(),
        required=False,
        default=[])
    allowed_push_targets = allowed_push_targets_field(
        parent_key='product version')

    class Meta:
        model = Release
        fields = ('release_id', 'short', 'version', 'name', 'base_product',
                  'active', 'product_version', 'release_type', 'compose_set',
                  'integrated_with', 'sigkey', 'allow_buildroot_push',
                  'allowed_debuginfo_services', 'allowed_push_targets')

    def set_default_sigkey(self, validated_data):
        if hasattr(settings, 'RELEASE_DEFAULT_SIGKEY'):
            if "sigkey" in validated_data and not validated_data["sigkey"]:
                validated_data["sigkey"], _ = SigKey.objects.get_or_create(
                    key_id=settings.RELEASE_DEFAULT_SIGKEY)
        return validated_data

    def get_compose_set(self, obj):
        """["Compose.compose_id"]"""
        return [
            compose.compose_id for compose in sorted(obj.get_all_composes())
        ]

    def create(self, validated_data):
        signals.release_serializer_extract_data.send(
            sender=self, validated_data=validated_data)
        validated_data = self.set_default_sigkey(validated_data)
        obj = super(ReleaseSerializer, self).create(validated_data)
        signals.release_serializer_post_create.send(sender=self, release=obj)
        return obj

    def update(self, instance, validated_data):
        signals.release_serializer_extract_data.send(
            sender=self, validated_data=validated_data)
        validated_data = self.set_default_sigkey(validated_data)
        obj = super(ReleaseSerializer, self).update(instance, validated_data)
        signals.release_serializer_post_update.send(sender=self, release=obj)
        if hasattr(instance, 'pk'):
            # reload to make sure changes in mapping are reflected
            obj = Release.objects.get(pk=obj.pk)
        obj.save()
        return obj

    def validate(self, data):
        convert_push_targets_to_mask(data, self.instance, 'product_version')
        return data
Exemple #20
0
class SLAToComponentBranchSerializer(StrictSerializerMixin,
                                     DynamicFieldsSerializerMixin,
                                     serializers.Serializer):
    """
    A serializer for the SLAToComponentBranch model that allows branch creation
    """
    id = serializers.IntegerField(read_only=True)
    sla = ChoiceSlugField(slug_field='name', queryset=SLA.objects.all())
    branch = ComponentBranchSerializerWithoutSLA()
    eol = serializers.DateField()

    def create(self, validated_data):
        """
        Creates the SLAToComponentBranch entry based on the serialized data
        """
        branch_component_type_name = validated_data['branch']['type']
        component_type = ReleaseComponentType.objects.filter(
            name=branch_component_type_name).first()
        if not component_type:
            error_msg = (
                'The specified ReleaseComponentType "{0}" does not exist'.
                format(branch_component_type_name))
            raise serializers.ValidationError({'branch.type': [error_msg]})

        branch_global_component_name = \
            validated_data['branch']['global_component']
        branch_global_component = GlobalComponent.objects.filter(
            name=branch_global_component_name).first()
        if not branch_global_component:
            error_msg = ('The specified GlobalComponent "{0}" does not exist'.
                         format(branch_global_component_name))
            raise serializers.ValidationError(
                {'branch.global_component': [error_msg]})

        branch_name = validated_data['branch']['name']
        branch_critical_path = validated_data['branch'].get('critical_path')
        branch = ComponentBranch.objects.filter(
            name=branch_name,
            type=component_type.id,
            global_component=branch_global_component.id).first()
        if branch:
            # The critical_path field is optional, but if it was supplied and it
            # doesn't match the found branch's critical_path field, raise an
            # error
            if branch_critical_path is not None and \
                    branch.critical_path != branch_critical_path:
                error_msg = ('The found branch\'s critical_path field did not '
                             'match the supplied value')
                raise serializers.ValidationError(
                    {'branch.critical_path': [error_msg]})
        else:
            # Set the default for this optional value when creating
            if branch_critical_path is None:
                branch_critical_path = False

            branch = ComponentBranch(
                name=branch_name,
                type=component_type,
                global_component=branch_global_component,
                critical_path=branch_critical_path,
            )

        sla_name = validated_data['sla']
        sla = SLA.objects.filter(name=sla_name).first()
        if not sla:
            error_msg = 'The specified SLA "{0}" does not exist'.format(
                sla_name)
            raise serializers.ValidationError({'sla': [error_msg]})

        if SLAToComponentBranch.objects.filter(sla=sla.id,
                                               branch=branch.id).exists():
            error_msg = (
                'The SLA "{0}" tied to the component "{1}" and branch "{2}" '
                'already exists').format(sla.name,
                                         branch.global_component.name,
                                         branch.name)
            raise serializers.ValidationError({'branch': [error_msg]})

        # This tells us if the branch object was created or not
        if branch._state.adding:
            branch.save()

        eol = validated_data['eol']
        return SLAToComponentBranch.objects.create(sla=sla,
                                                   branch=branch,
                                                   eol=eol)

    def update(self, instance, validated_data):
        """
        Updates the SLAToComponentBranch entry based on the serialized data
        """
        branch = validated_data.get('branch', {})
        branch_name = branch.get('name')
        component_type = branch.get('type')
        global_component = branch.get('global_component')
        critical_path = branch.get('critical_path', None)
        if branch:
            if instance.branch.name != branch_name \
                    or instance.branch.type != component_type \
                    or instance.branch.global_component != global_component \
                    or (critical_path is not None and
                        instance.branch.critical_path is not critical_path):
                raise serializers.ValidationError({
                    'branch': ['The branch cannot be modified using this API']
                })

        # TODO: Should we not allow this value to change?
        instance.sla = validated_data.get('sla', instance.sla)
        instance.eol = validated_data.get('eol', instance.eol)
        instance.save()
        return instance