Пример #1
0
 def process_request(self, request):
     # type: (UsageFile) -> None
     if request.contract.id == 'CRD-99082-45842-69181':
         usage_file = UsageFile(
             name='sdk test',
             product=Product(id=request.product.id),
             contract=Contract(id=request.contract.id)
         )
         usages = [UsageRecord(
             item_search_criteria='item.mpn',
             item_search_value='SKUA',
             quantity=1,
             start_time_utc=(date.today() - timedelta(1)).strftime('%Y-%m-%d'),
             end_time_utc=time.strftime('%Y-%m-%d %H:%M:%S'),
             asset_search_criteria='parameter.param_b',
             asset_search_value='tenant2'
         )]
         self.submit_usage(usage_file, usages)
     elif request.contract.id == 'CRD-99082-45842-69182':
         pass
     elif request.contract.id == 'CRD-99082-45842-69183':
         pass
     elif request.contract.id == 'CRD-99082-45842-69184':
         usage_file = UsageFile(
             product=Product(id=request.product.id),
             contract=Contract(id=request.contract.id)
         )
         usages = [UsageRecord(
             record_id='123',
             item_search_criteria='item.mpn',
             item_search_value='SKUA',
             quantity=1,
             start_time_utc=(date.today() - timedelta(1)).strftime('%Y-%m-%d'),
             end_time_utc=time.strftime('%Y-%m-%d %H:%M:%S'),
             asset_search_criteria='parameter.param_b',
             asset_search_value='tenant2'
         )]
         self.submit_usage(usage_file, usages)
     elif request.contract.id == 'CRD-99082-45842-69185':
         pass
     elif request.contract.id == 'CRD-99082-45842-69186':
         pass
     elif request.contract.id == 'CRD-99082-45842-69187':
         pass
     else:
         raise UserWarning('Invalid test')
Пример #2
0
def test_get_usage_template_ok(get_mock):
    get_mock.side_effect = [
        Response(ok=True, text='{"template_link": "..."}', status_code=200),
        BinaryResponse(ok=True, content=b'template_contents', status_code=200)]
    resource = UsageAutomation()
    assert resource.get_usage_template(Product(id='PRD-638-321-603')) == b'template_contents'
    get_mock.assert_has_calls([
        call(
            url='http://localhost:8080/api/public/v1/usage/products/PRD-638-321-603/template/',
            headers={'Content-Type': 'application/json', 'Authorization': 'ApiKey XXXX:YYYYY'},
            timeout=300),
        call('...')
    ])
Пример #3
0
    def process_request(self, request):
        # type: (UsageListing) -> None

        # Detect specific provider contract
        if request.contract.id == 'CRD-41560-05399-123':
            # Can also be seen from request.provider.id and parametrized further
            # via marketplace available at request.marketplace.id
            usage_file = UsageFile(
                name='sdk test',
                product=Product(id=request.product.id),
                contract=Contract(id=request.contract.id)
            )

            today = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
            yesterday = today - timedelta(days=1)

            usages = [
                UsageRecord(
                    usage_record_id='unique record value',

                    item_search_criteria='item.mpn',
                    # Possible values are item.mpn or item.local_id.

                    item_search_value='SKUA',
                    # Value defined as MPN on vendor portal.

                    quantity=1,
                    # Quantity to be reported.

                    start_time_utc=yesterday.strftime('%Y-%m-%d %H:%M:%S'),
                    # From when to report.

                    end_time_utc=today.strftime('%Y-%m-%d %H:%M:%S'),
                    # Till when to report.

                    asset_search_criteria='parameter.param_b',
                    # How to find the asset on Connect.  Typical use case is to use a parameter
                    # provided by vendor, in this case called param_b.  Additionally, asset.id
                    # can be used in case you want to use Connect identifiers.

                    asset_search_value='tenant2'
                )
            ]

            self.submit_usage(usage_file, usages)
        else:
            # Something different could be done here
            pass
Пример #4
0
 def make_object(self, data):
     from connect.models import Product
     return Product(**data)
Пример #5
0
    def process_request(self, request):
        """Generate UsageFile for each active Asset"""

        # store each processed request for debug
        self.usages.append(request)

        today = datetime.utcnow() - timedelta(minutes=10)
        name_format = 'Report for {asset} {date}'

        project = self.get_project(request)
        if not project:
            return

        stop_report_time = self.get_stop_report_time(request, project)
        start_report_time = self.get_start_report_time(request, project)
        self.logger.info("Start report time: %s, stop report time: %s",
                         start_report_time, stop_report_time)
        if request.status in ['suspended', 'terminated'
                              ] and not stop_report_time:
            self.logger.info(
                "%s-%s: asset usage reporting was stopped without stop report time label",
                request.id, project.id)
            return

        last_report_time, confirmed = self.get_last_report_time(
            request, project)
        report_time = last_report_time + timedelta(days=1)
        report_time = report_time.replace(hour=0,
                                          minute=0,
                                          second=0,
                                          microsecond=0)
        self.logger.info(
            "Last report time: %s, report time: %s, confirmed: %s",
            last_report_time, report_time, confirmed)

        if self.project_id is not None and self.project_id != project.id:
            self.logger.info(
                "project_id=%s is not the same as project.id=%s, skip it",
                self.project_id, project.id)
            return

        # check that previous report has passed validation
        if confirmed is False:
            usage_files = UsageFileAutomation()
            try:
                report_date = last_report_time.strftime('%Y-%m-%d')
                report_name = name_format.format(asset=request.id,
                                                 date=report_date)

                filters = Query().equal('name', report_name).limit(10)
                if self.config.products:
                    filters.in_('product_id', self.config.products)
                found = usage_files.list(filters)

                found = [f for f in found or [] if f.status != 'deleted']
                self.logger.debug("Found usage files: %s", found)

                if found:
                    if len(found) > 2:
                        raise Exception("Found multiple reports with name %s" %
                                        report_name)

                    report = found[0]

                    if report.status in ('processing', 'draft', 'uploading'):
                        self.logger.info(
                            "%s-%s: usage report '%s' is being processed",
                            request.id, project.id, report_name)
                        return

                    if report.status in ('invalid', 'rejected'):
                        # we have to wait when user remove invalid report
                        self.logger.error(
                            "%s-%s: failed usage report '%s' found",
                            request.id, project.id, report_name)
                        return

                    self.update_last_report_time(project,
                                                 last_report_time,
                                                 confirmed=True)
                else:
                    report_time = last_report_time

            except ServerError:
                # this section is useless but left for future development
                raise

        if request.status in ['suspended', 'terminated']:
            if stop_report_time and last_report_time < stop_report_time <= report_time:
                self.logger.info("%s-%s: sending last report (%s)", request.id,
                                 project.id, request.status)
                report_time = stop_report_time

        if start_report_time and last_report_time < start_report_time < report_time:
            last_report_time = start_report_time

        if report_time > today and self.project_id is None:
            self.logger.info("%s-%s: usage is already reported", request.id,
                             project.id)
            return

        usage_file = UsageFile(
            name=name_format.format(asset=request.id,
                                    date=report_time.strftime('%Y-%m-%d')),
            product=Product(id=request.product.id),
            contract=Contract(id=request.contract.id),
            description=name_format.format(
                asset=request.id, date=report_time.strftime('%Y-%m-%d')),
        )

        # report for each day since last report date
        self.logger.info("%s-%s: creating report from %s to %s", request.id,
                         project.id, last_report_time, report_time)
        items = {item.mpn: item for item in request.items}
        usage_records = self.collect_usage_records(items, project,
                                                   last_report_time,
                                                   report_time)
        self.submit_usage(usage_file=usage_file, usage_records=usage_records)

        if report_time > today:
            # when project id is specified we allow to send usage for today
            # but don't update last report time
            return

        self.update_last_report_time(project, report_time)
Пример #6
0
def test_get_usage_template_no_file():
    resource = UsageAutomation()
    with pytest.raises(FileRetrievalError):
        resource.get_usage_template(Product(id='PRD-638-321-603'))