예제 #1
0
    def update(self, instance, validated_data):
        """Update a Provider instance from validated data."""
        provider_type = validated_data['type']
        interface = ProviderAccessor(provider_type)

        authentication = validated_data.pop('authentication')
        credentials = authentication.get('credentials')
        provider_resource_name = credentials.get('provider_resource_name')

        billing_source = validated_data.pop('billing_source')
        data_source = billing_source.get('data_source')
        bucket = billing_source.get('bucket')

        if credentials and data_source and provider_type not in ['AWS', 'OCP']:
            interface.cost_usage_source_ready(credentials, data_source)
        else:
            interface.cost_usage_source_ready(provider_resource_name, bucket)

        bill, __ = ProviderBillingSource.objects.get_or_create(**billing_source)
        auth, __ = ProviderAuthentication.objects.get_or_create(**authentication)

        for key in validated_data.keys():
            setattr(instance, key, validated_data[key])

        instance.authentication = auth
        instance.billing_source = bill
        try:
            instance.save()
        except IntegrityError:
            error = {'Error': 'A Provider already exists with that Authentication and Billing Source'}
            raise serializers.ValidationError(error)
        return instance
예제 #2
0
    def update(self, instance, validated_data):
        """Update a Provider instance from validated data."""
        _, customer = self.get_request_info()
        provider_type = validated_data["type"].lower()
        provider_type = Provider.PROVIDER_CASE_MAPPING.get(provider_type)
        validated_data["type"] = provider_type
        interface = ProviderAccessor(provider_type)
        authentication = validated_data.pop("authentication")
        credentials = authentication.get("credentials")
        billing_source = validated_data.pop("billing_source")
        data_source = billing_source.get("data_source")

        # updating `paused` must happen regardless of Provider availabilty
        instance.paused = validated_data.pop("paused", instance.paused)

        try:
            if self._is_demo_account(provider_type, credentials):
                LOG.info(
                    "Customer account is a DEMO account. Skipping cost_usage_source_ready check."
                )
            else:
                interface.cost_usage_source_ready(credentials, data_source)
        except serializers.ValidationError as validation_error:
            instance.active = False
            instance.save()
            raise validation_error

        with transaction.atomic():
            bill, __ = ProviderBillingSource.objects.get_or_create(
                **billing_source)
            auth, __ = ProviderAuthentication.objects.get_or_create(
                **authentication)
            if instance.billing_source != bill or instance.authentication != auth:
                dup_queryset = (Provider.objects.filter(
                    authentication=auth).filter(billing_source=bill).filter(
                        customer=customer))
                if dup_queryset.count() != 0:
                    conflict_provder = dup_queryset.first()
                    message = (
                        f"Cost management does not allow duplicate accounts. "
                        f"{conflict_provder.name} already exists. Edit source settings to configure a new source."
                    )
                    LOG.warn(message)
                    raise serializers.ValidationError(
                        error_obj(ProviderErrors.DUPLICATE_AUTH, message))

            for key in validated_data.keys():
                setattr(instance, key, validated_data[key])

            instance.authentication = auth
            instance.billing_source = bill
            instance.active = True

            instance.save()

            customer.date_updated = DateHelper().now_utc
            customer.save()

            return instance
예제 #3
0
    def create(self, validated_data):
        """Create a provider from validated data."""
        user, customer = self.get_request_info()

        if "billing_source" in validated_data:
            billing_source = validated_data.pop("billing_source")
            data_source = billing_source.get("data_source", {})
            bucket = data_source.get("bucket")
        else:
            # Because of a unique together constraint, this is done
            # to allow for this field to be non-required for OCP
            # but will still have a blank no-op entry in the DB
            billing_source = {"bucket": "", "data_source": {}}
            data_source = None

        authentication = validated_data.pop("authentication")
        credentials = authentication.get("credentials")
        provider_resource_name = credentials.get("provider_resource_name")
        provider_type = validated_data["type"]
        provider_type = Provider.PROVIDER_CASE_MAPPING.get(provider_type)
        validated_data["type"] = provider_type
        interface = ProviderAccessor(provider_type)

        if customer.account_id not in settings.DEMO_ACCOUNTS:
            if credentials and data_source and provider_type not in [
                    Provider.PROVIDER_AWS, Provider.PROVIDER_OCP
            ]:
                interface.cost_usage_source_ready(credentials, data_source)
            else:
                interface.cost_usage_source_ready(provider_resource_name,
                                                  bucket)

        bill, __ = ProviderBillingSource.objects.get_or_create(
            **billing_source)
        auth, __ = ProviderAuthentication.objects.get_or_create(
            **authentication)

        # We can re-use a billing source or a auth, but not the same combination.
        dup_queryset = (Provider.objects.filter(authentication=auth).filter(
            billing_source=bill).filter(customer=customer))
        if dup_queryset.count() != 0:
            conflict_provider = dup_queryset.first()
            message = (
                f"Cost management does not allow duplicate accounts. "
                f"{conflict_provider.name} already exists. Edit source settings to configure a new source."
            )
            LOG.warn(message)
            raise serializers.ValidationError(
                error_obj(ProviderErrors.DUPLICATE_AUTH, message))

        provider = Provider.objects.create(**validated_data)
        provider.customer = customer
        provider.created_by = user
        provider.authentication = auth
        provider.billing_source = bill
        provider.active = True

        provider.save()
        return provider
예제 #4
0
    def create(self, validated_data):
        """Create a provider from validated data."""
        user = None
        customer = None
        request = self.context.get('request')
        if request and hasattr(request, 'user'):
            user = request.user
            if user.customer:
                customer = user.customer
            else:
                key = 'customer'
                message = 'Customer for requesting user could not be found.'
                raise serializers.ValidationError(error_obj(key, message))
        else:
            key = 'created_by'
            message = 'Requesting user could not be found.'
            raise serializers.ValidationError(error_obj(key, message))

        if 'billing_source' in validated_data:
            billing_source = validated_data.pop('billing_source')
            data_source = billing_source.get('data_source', {})
            bucket = data_source.get('bucket')
        else:
            # Because of a unique together constraint, this is done
            # to allow for this field to be non-required for OCP
            # but will still have a blank no-op entry in the DB
            billing_source = {'bucket': '', 'data_source': {}}
            data_source = None

        authentication = validated_data.pop('authentication')
        credentials = authentication.get('credentials')
        provider_resource_name = credentials.get('provider_resource_name')
        provider_type = validated_data['type']
        interface = ProviderAccessor(provider_type)

        if credentials and data_source and provider_type not in ['AWS', 'OCP']:
            interface.cost_usage_source_ready(credentials, data_source)
        else:
            interface.cost_usage_source_ready(provider_resource_name, bucket)

        bill, __ = ProviderBillingSource.objects.get_or_create(**billing_source)
        auth, __ = ProviderAuthentication.objects.get_or_create(**authentication)

        # We can re-use a billing source or a auth, but not the same combination.
        unique_count = Provider.objects.filter(authentication=auth)\
            .filter(billing_source=bill).count()
        if unique_count != 0:
            error = {'Error': 'A Provider already exists with that Authentication and Billing Source'}
            raise serializers.ValidationError(error)

        provider = Provider.objects.create(**validated_data)
        provider.customer = customer
        provider.created_by = user
        provider.authentication = auth
        provider.billing_source = bill
        provider.active = True

        provider.save()
        return provider
예제 #5
0
    def update(self, instance, validated_data):
        """Update a Provider instance from validated data."""
        _, customer = self.get_request_info()
        provider_type = validated_data["type"].lower()
        provider_type = Provider.PROVIDER_CASE_MAPPING.get(provider_type)
        validated_data["type"] = provider_type
        interface = ProviderAccessor(provider_type)
        authentication = validated_data.pop("authentication")
        credentials = authentication.get("credentials")
        provider_resource_name = credentials.get("provider_resource_name")
        billing_source = validated_data.pop("billing_source")
        data_source = billing_source.get("data_source")
        bucket = billing_source.get("bucket")

        try:
            if customer.account_id not in settings.DEMO_ACCOUNTS:
                if credentials and data_source and provider_type not in [
                        Provider.PROVIDER_AWS, Provider.PROVIDER_OCP
                ]:
                    interface.cost_usage_source_ready(credentials, data_source)
                else:
                    interface.cost_usage_source_ready(provider_resource_name,
                                                      bucket)
        except serializers.ValidationError as validation_error:
            instance.active = False
            instance.save()
            raise validation_error

        with transaction.atomic():
            bill, __ = ProviderBillingSource.objects.get_or_create(
                **billing_source)
            auth, __ = ProviderAuthentication.objects.get_or_create(
                **authentication)
            dup_queryset = (Provider.objects.filter(
                authentication=auth).filter(billing_source=bill).filter(
                    customer=customer))
            if dup_queryset.count() != 0:
                conflict_provder = dup_queryset.first()
                message = (
                    f"Cost management does not allow duplicate accounts. "
                    f"{conflict_provder.name} already exists. Edit source settings to configure a new source."
                )
                LOG.warn(message)

            for key in validated_data.keys():
                setattr(instance, key, validated_data[key])

            instance.authentication = auth
            instance.billing_source = bill
            instance.active = True

            try:
                instance.save()
            except IntegrityError:
                raise serializers.ValidationError(
                    error_obj(ProviderErrors.DUPLICATE_AUTH, message))
            return instance
예제 #6
0
    def update(self, instance, validated_data):
        """Update a Provider instance from validated data."""
        _, _, customer = self.get_request_info()
        provider_type = validated_data["type"].lower()
        provider_type = Provider.PROVIDER_CASE_MAPPING.get(provider_type)
        validated_data["type"] = provider_type
        if instance.type != provider_type:
            error = {
                "Error":
                "The Provider Type cannot be changed with a PUT request."
            }
            raise serializers.ValidationError(error)
        interface = ProviderAccessor(provider_type)
        authentication = validated_data.pop("authentication")
        credentials = authentication.get("credentials")
        provider_resource_name = credentials.get("provider_resource_name")
        billing_source = validated_data.pop("billing_source")
        data_source = billing_source.get("data_source")
        bucket = billing_source.get("bucket")

        try:
            if customer.account_id not in settings.DEMO_ACCOUNTS:
                if credentials and data_source and provider_type not in [
                        Provider.PROVIDER_AWS, Provider.PROVIDER_OCP
                ]:
                    interface.cost_usage_source_ready(credentials, data_source)
                else:
                    interface.cost_usage_source_ready(provider_resource_name,
                                                      bucket)
        except serializers.ValidationError as validation_error:
            instance.active = False
            instance.save()
            raise validation_error

        with transaction.atomic():
            bill, __ = ProviderBillingSource.objects.get_or_create(
                **billing_source)
            auth, __ = ProviderAuthentication.objects.get_or_create(
                **authentication)

            for key in validated_data.keys():
                setattr(instance, key, validated_data[key])

            instance.authentication = auth
            instance.billing_source = bill
            instance.active = True

            try:
                instance.save()
            except IntegrityError:
                error = {
                    "Error":
                    "A Provider already exists with that Authentication and Billing Source"
                }
                raise serializers.ValidationError(error)
            return instance
예제 #7
0
    def create(self, validated_data):
        """Create a provider from validated data."""
        _, user, customer = self.get_request_info()

        if "billing_source" in validated_data:
            billing_source = validated_data.pop("billing_source")
            data_source = billing_source.get("data_source", {})
            bucket = data_source.get("bucket")
        else:
            # Because of a unique together constraint, this is done
            # to allow for this field to be non-required for OCP
            # but will still have a blank no-op entry in the DB
            billing_source = {"bucket": "", "data_source": {}}
            data_source = None

        authentication = validated_data.pop("authentication")
        credentials = authentication.get("credentials")
        provider_resource_name = credentials.get("provider_resource_name")
        provider_type = validated_data["type"]
        provider_type = Provider.PROVIDER_CASE_MAPPING.get(provider_type)
        validated_data["type"] = provider_type
        interface = ProviderAccessor(provider_type)

        if customer.account_id not in settings.DEMO_ACCOUNTS:
            if credentials and data_source and provider_type not in [
                    Provider.PROVIDER_AWS, Provider.PROVIDER_OCP
            ]:
                interface.cost_usage_source_ready(credentials, data_source)
            else:
                interface.cost_usage_source_ready(provider_resource_name,
                                                  bucket)

        bill, __ = ProviderBillingSource.objects.get_or_create(
            **billing_source)
        auth, __ = ProviderAuthentication.objects.get_or_create(
            **authentication)

        # We can re-use a billing source or a auth, but not the same combination.
        unique_count = (Provider.objects.filter(authentication=auth).filter(
            billing_source=bill).filter(customer=customer).count())
        if unique_count != 0:
            error = {
                "Error":
                "A Provider already exists with that Authentication and Billing Source"
            }
            raise serializers.ValidationError(error)

        provider = Provider.objects.create(**validated_data)
        provider.customer = customer
        provider.created_by = user
        provider.authentication = auth
        provider.billing_source = bill
        provider.active = True

        provider.save()
        return provider
예제 #8
0
    def determine_status(self, provider, source_authentication, source_billing_source):
        """Check cloud configuration status."""
        interface = ProviderAccessor(provider)
        error_obj = None
        try:
            interface.cost_usage_source_ready(source_authentication, source_billing_source)
        except ValidationError as validation_error:
            error_obj = validation_error

        return error_obj
예제 #9
0
 def determine_status(self, provider_type, source_authentication, source_billing_source):
     """Check cloud configuration status."""
     interface = ProviderAccessor(provider_type)
     error_obj = None
     try:
         if self.source.account_id not in settings.DEMO_ACCOUNTS:
             interface.cost_usage_source_ready(source_authentication, source_billing_source)
         self._set_provider_active_status(True)
     except ValidationError as validation_error:
         self._set_provider_active_status(False)
         error_obj = validation_error
     self.source.refresh_from_db()
     return error_obj
예제 #10
0
    def create(self, validated_data):
        """Create a provider from validated data."""
        user, customer = self.get_request_info()
        provider_type = validated_data["type"].lower()
        provider_type = Provider.PROVIDER_CASE_MAPPING.get(provider_type)
        validated_data["type"] = provider_type
        interface = ProviderAccessor(provider_type)
        authentication = validated_data.pop("authentication")
        credentials = authentication.get("credentials")
        billing_source = validated_data.pop("billing_source")
        data_source = billing_source.get("data_source")

        if self._is_demo_account(provider_type, credentials):
            LOG.info(
                "Customer account is a DEMO account. Skipping cost_usage_source_ready check."
            )
        else:
            interface.cost_usage_source_ready(credentials, data_source)

        bill, __ = ProviderBillingSource.objects.get_or_create(
            **billing_source)
        auth, __ = ProviderAuthentication.objects.get_or_create(
            **authentication)

        # We can re-use a billing source or a auth, but not the same combination.
        dup_queryset = (Provider.objects.filter(authentication=auth).filter(
            billing_source=bill).filter(customer=customer))
        if dup_queryset.count() != 0:
            conflict_provider = dup_queryset.first()
            message = (
                f"Cost management does not allow duplicate accounts. "
                f"{conflict_provider.name} already exists. Edit source settings to configure a new source."
            )
            LOG.warn(message)
            raise serializers.ValidationError(
                error_obj(ProviderErrors.DUPLICATE_AUTH, message))

        provider = Provider.objects.create(**validated_data)
        provider.customer = customer
        provider.created_by = user
        provider.authentication = auth
        provider.billing_source = bill
        provider.active = True

        provider.save()

        customer.date_updated = DateHelper().now_utc
        customer.save()

        return provider
예제 #11
0
    def test_invalid_provider_funcs(self):
        """Verify that an invalid service is created and raises errors."""
        provider_name = "BAD"
        interface = ProviderAccessor(provider_name)
        self.assertIsNone(interface.service)

        with self.assertRaises(ValidationError):
            interface.cost_usage_source_ready({}, {})

        with self.assertRaises(ValidationError):
            interface.service_name()

        with self.assertRaises(ValidationError):
            interface.infrastructure_type({}, {})

        with self.assertRaises(ValidationError):
            interface.infrastructure_key_list({}, {})
예제 #12
0
    def test_usage_source_ready(self):
        """Get status of cost usage source."""
        provider = Provider.PROVIDER_AWS
        interface = ProviderAccessor(provider)

        credential = "arn:aws:s3:::my_s3_bucket"
        source_name = "my_s3_bucket"

        source_ready = False
        with patch.object(AWSProvider, "cost_usage_source_is_reachable", return_value=True):
            source_ready = interface.cost_usage_source_ready(credential, source_name)
        self.assertTrue(source_ready)
예제 #13
0
파일: serializers.py 프로젝트: LaVLaS/koku
    def create(self, validated_data):
        """Create a provider from validated data."""
        authentication = validated_data.pop('authentication')
        billing_source = validated_data.pop('billing_source')

        user = None
        customer = None
        request = self.context.get('request')
        if request and hasattr(request, 'user'):
            user = User.objects.get(pk=request.user.id)
            if user.groups.count() == 1:
                group = user.groups.first()
                customer = Customer.objects.get(pk=group.id)
            else:
                key = 'customer'
                message = 'Group for requesting user could not be found.'
                raise serializers.ValidationError(error_obj(key, message))
        else:
            key = 'created_by'
            message = 'Requesting user could not be found.'
            raise serializers.ValidationError(error_obj(key, message))

        provider_resource_name = authentication.get('provider_resource_name')
        bucket = billing_source.get('bucket')

        provider_type = validated_data['type']
        interface = ProviderAccessor(provider_type)
        interface.cost_usage_source_ready(provider_resource_name, bucket)

        auth = ProviderAuthentication.objects.create(**authentication)
        bill = ProviderBillingSource.objects.create(**billing_source)
        auth.save()
        bill.save()
        provider = Provider.objects.create(**validated_data)
        provider.customer = customer
        provider.created_by = user
        provider.authentication = auth
        provider.billing_source = bill
        provider.save()
        return provider