From aef56b67d43de777a13a26150869cf80fed78159 Mon Sep 17 00:00:00 2001 From: Phil Adams Date: Tue, 25 Oct 2022 15:38:48 -0500 Subject: [PATCH 1/2] fix(Enterprise Usage Reports): regen service to get Pager This commit contains a re-gen of the service to leverage the new Pagers emitted by the SDK generator. Signed-off-by: Phil Adams --- ...st_enterprise_usage_reports_v1_examples.py | 18 +- .../enterprise_usage_reports_v1.py | 121 ++++++++++- .../test_enterprise_usage_reports_v1.py | 50 +++-- test/unit/test_enterprise_usage_reports_v1.py | 191 +++++++++++++++--- 4 files changed, 317 insertions(+), 63 deletions(-) diff --git a/examples/test_enterprise_usage_reports_v1_examples.py b/examples/test_enterprise_usage_reports_v1_examples.py index 31e99088..720c5ce5 100644 --- a/examples/test_enterprise_usage_reports_v1_examples.py +++ b/examples/test_enterprise_usage_reports_v1_examples.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# (C) Copyright IBM Corp. 2020. +# (C) Copyright IBM Corp. 2020, 2022. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -98,21 +98,23 @@ def test_get_resource_usage_report_example(self): get_resource_usage_report request example """ try: - global enterprise_id, billing_month - print('\nget_resource_usage_report() result:') # begin-get_resource_usage_report - reports = enterprise_usage_reports_service.get_resource_usage_report( + all_results = [] + pager = GetResourceUsageReportPager( + client=enterprise_usage_reports_service, enterprise_id=enterprise_id, month=billing_month, - limit=10 - ).get_result() + ) + while pager.has_next(): + next_page = pager.get_next() + assert next_page is not None + all_results.extend(next_page) - print(json.dumps(reports, indent=2)) + print(json.dumps(all_results, indent=2)) # end-get_resource_usage_report - except ApiException as e: pytest.fail(str(e)) diff --git a/ibm_platform_services/enterprise_usage_reports_v1.py b/ibm_platform_services/enterprise_usage_reports_v1.py index 4ba83950..46b6c586 100644 --- a/ibm_platform_services/enterprise_usage_reports_v1.py +++ b/ibm_platform_services/enterprise_usage_reports_v1.py @@ -1,6 +1,6 @@ # coding: utf-8 -# (C) Copyright IBM Corp. 2020. +# (C) Copyright IBM Corp. 2022. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,17 +14,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -# IBM OpenAPI SDK Code Generator Version: 99-SNAPSHOT-629bbb97-20201207-171303 +# IBM OpenAPI SDK Code Generator Version: 3.60.0-13f6e1ba-20221019-164457 """ Usage reports for IBM Cloud enterprise entities + +API Version: 1.0.0-beta.1 """ from enum import Enum from typing import Dict, List import json -from ibm_cloud_sdk_core import BaseService, DetailedResponse +from ibm_cloud_sdk_core import BaseService, DetailedResponse, get_query_param from ibm_cloud_sdk_core.authenticators.authenticator import Authenticator from ibm_cloud_sdk_core.get_authenticator import get_authenticator_from_environment @@ -62,7 +64,7 @@ def __init__(self, Construct a new client for the Enterprise Usage Reports service. :param Authenticator authenticator: The authenticator specifies the authentication mechanism. - Get up to date information from https://github.com/IBM/python-sdk-core/blob/master/README.md + Get up to date information from https://github.com/IBM/python-sdk-core/blob/main/README.md about initializing the authenticator of your choice. """ BaseService.__init__(self, @@ -141,6 +143,7 @@ def get_resource_usage_report(self, if 'headers' in kwargs: headers.update(kwargs.get('headers')) + del kwargs['headers'] headers['Accept'] = 'application/json' url = '/v1/resource-usage-reports' @@ -149,7 +152,7 @@ def get_resource_usage_report(self, headers=headers, params=params) - response = self.send(request) + response = self.send(request, **kwargs) return response @@ -224,7 +227,7 @@ class MetricUsage(): charges. :attr float cost: The cost that was incurred by the metric. :attr float rated_cost: The pre-discounted cost that was incurred by the metric. - :attr List[object] price: (optional) The price with which cost was calculated. + :attr List[dict] price: (optional) The price with which cost was calculated. """ def __init__(self, @@ -235,7 +238,7 @@ def __init__(self, cost: float, rated_cost: float, *, - price: List[object] = None) -> None: + price: List[dict] = None) -> None: """ Initialize a MetricUsage object. @@ -247,7 +250,7 @@ def __init__(self, :param float cost: The cost that was incurred by the metric. :param float rated_cost: The pre-discounted cost that was incurred by the metric. - :param List[object] price: (optional) The price with which cost was + :param List[dict] price: (optional) The price with which cost was calculated. """ self.metric = metric @@ -860,3 +863,105 @@ class EntityTypeEnum(str, Enum): ACCOUNT_GROUP = 'account-group' ACCOUNT = 'account' + +############################################################################## +# Pagers +############################################################################## + +class GetResourceUsageReportPager(): + """ + GetResourceUsageReportPager can be used to simplify the use of the "get_resource_usage_report" method. + """ + + def __init__(self, + *, + client: EnterpriseUsageReportsV1, + enterprise_id: str = None, + account_group_id: str = None, + account_id: str = None, + children: bool = None, + month: str = None, + billing_unit_id: str = None, + limit: int = None, + ) -> None: + """ + Initialize a GetResourceUsageReportPager object. + :param str enterprise_id: (optional) The ID of the enterprise for which the + reports are queried. This parameter cannot be used with the `account_id` or + `account_group_id` query parameters. + :param str account_group_id: (optional) The ID of the account group for + which the reports are queried. This parameter cannot be used with the + `account_id` or `enterprise_id` query parameters. + :param str account_id: (optional) The ID of the account for which the + reports are queried. This parameter cannot be used with the + `account_group_id` or `enterprise_id` query parameters. + :param bool children: (optional) Returns the reports for the immediate + child entities under the current account group or enterprise. This + parameter cannot be used with the `account_id` query parameter. + :param str month: (optional) The billing month for which the usage report + is requested. The format is in yyyy-mm. Defaults to the month in which the + report is queried. + :param str billing_unit_id: (optional) The ID of the billing unit by which + to filter the reports. + :param int limit: (optional) The maximum number of search results to be + returned. + """ + self._has_next = True + self._client = client + self._page_context = { 'next': None } + self._enterprise_id = enterprise_id + self._account_group_id = account_group_id + self._account_id = account_id + self._children = children + self._month = month + self._billing_unit_id = billing_unit_id + self._limit = limit + + def has_next(self) -> bool: + """ + Returns true if there are potentially more results to be retrieved. + """ + return self._has_next + + def get_next(self) -> List[dict]: + """ + Returns the next page of results. + :return: A List[dict], where each element is a dict that represents an instance of ResourceUsageReport. + :rtype: List[dict] + """ + if not self.has_next(): + raise StopIteration(message='No more results available') + + result = self._client.get_resource_usage_report( + enterprise_id=self._enterprise_id, + account_group_id=self._account_group_id, + account_id=self._account_id, + children=self._children, + month=self._month, + billing_unit_id=self._billing_unit_id, + limit=self._limit, + offset=self._page_context.get('next'), + ).get_result() + + next = None + next_page_link = result.get('next') + if next_page_link is not None: + next = get_query_param(next_page_link.get('href'), 'offset') + self._page_context['next'] = next + if next is None: + self._has_next = False + + return result.get('reports') + + def get_all(self) -> List[dict]: + """ + Returns all results by invoking get_next() repeatedly + until all pages of results have been retrieved. + :return: A List[dict], where each element is a dict that represents an instance of ResourceUsageReport. + :rtype: List[dict] + """ + results = [] + while self.has_next(): + next_page = self.get_next() + results.extend(next_page) + return results diff --git a/test/integration/test_enterprise_usage_reports_v1.py b/test/integration/test_enterprise_usage_reports_v1.py index 3efd27c1..158998c7 100644 --- a/test/integration/test_enterprise_usage_reports_v1.py +++ b/test/integration/test_enterprise_usage_reports_v1.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# (C) Copyright IBM Corp. 2020. +# (C) Copyright IBM Corp. 2020, 2022. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,8 +19,6 @@ import os import pytest -import urllib.parse as urlparse -from urllib.parse import parse_qs from ibm_cloud_sdk_core import * from ibm_platform_services.enterprise_usage_reports_v1 import * @@ -61,19 +59,6 @@ def setup_class(cls): not os.path.exists(config_file), reason="External configuration not available, skipping..." ) - def get_offset_from_url(self, url): - if url is None: - return None - try: - parsed = urlparse.urlparse(url) - query_value = parse_qs(parsed.query).get('offset') - if query_value is not None: - return query_value[0] - return None - except Exception as e: - print('Error parsing URL', e) - return None - @needscredentials def test_get_resource_usage_report_enterprise(self): results = [] @@ -97,7 +82,7 @@ def test_get_resource_usage_report_enterprise(self): next = reports.get('next') offset = None if next is not None and 'href' in next: - offset = self.get_offset_from_url(next['href']) + offset = get_query_param(next['href'], 'offset') if offset is None: break @@ -130,7 +115,7 @@ def test_get_resource_usage_report_account(self): next = reports.get('next') offset = None if next is not None and 'href' in next: - offset = self.get_offset_from_url(next['href']) + offset = get_query_param(next['href'], 'offset') if offset is None: break @@ -163,7 +148,7 @@ def test_get_resource_usage_report_account_group(self): next = reports.get('next') offset = None if next is not None and 'href' in next: - offset = self.get_offset_from_url(next['href']) + offset = get_query_param(next['href'], 'offset') if offset is None: break @@ -172,3 +157,30 @@ def test_get_resource_usage_report_account_group(self): print( f'get_resource_usage_report()/account-group response contained {numReports} total reports.') assert numReports > 0 + + @needscredentials + def test_get_resource_usage_report_with_pager(self): + all_results = [] + + # Test get_next(). + pager = GetResourceUsageReportPager( + client=self.enterprise_usage_reports_service, + account_group_id=self.ACCOUNT_GROUP_ID, + month=self.BILLING_MONTH, + ) + while pager.has_next(): + next_page = pager.get_next() + assert next_page is not None + all_results.extend(next_page) + + # Test get_all(). + pager = GetResourceUsageReportPager( + client=self.enterprise_usage_reports_service, + account_group_id=self.ACCOUNT_GROUP_ID, + month=self.BILLING_MONTH, + ) + all_items = pager.get_all() + assert all_items is not None + + assert len(all_results) == len(all_items) + print(f'\nget_resource_usage_report() returned a total of {len(all_results)} items(s) using GetResourceUsageReportPager.') diff --git a/test/unit/test_enterprise_usage_reports_v1.py b/test/unit/test_enterprise_usage_reports_v1.py index 7d381911..02a7a68a 100644 --- a/test/unit/test_enterprise_usage_reports_v1.py +++ b/test/unit/test_enterprise_usage_reports_v1.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# (C) Copyright IBM Corp. 2020. +# (C) Copyright IBM Corp. 2022. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ from ibm_cloud_sdk_core.authenticators.no_auth_authenticator import NoAuthAuthenticator import inspect import json +import os import pytest import re import requests @@ -28,31 +29,76 @@ from ibm_platform_services.enterprise_usage_reports_v1 import * -service = EnterpriseUsageReportsV1( +_service = EnterpriseUsageReportsV1( authenticator=NoAuthAuthenticator() - ) +) + +_base_url = 'https://enterprise.cloud.ibm.com' +_service.set_service_url(_base_url) + + +def preprocess_url(operation_path: str): + """ + Returns the request url associated with the specified operation path. + This will be base_url concatenated with a quoted version of operation_path. + The returned request URL is used to register the mock response so it needs + to match the request URL that is formed by the requests library. + """ + # First, unquote the path since it might have some quoted/escaped characters in it + # due to how the generator inserts the operation paths into the unit test code. + operation_path = urllib.parse.unquote(operation_path) + + # Next, quote the path using urllib so that we approximate what will + # happen during request processing. + operation_path = urllib.parse.quote(operation_path, safe='/') + + # Finally, form the request URL from the base URL and operation path. + request_url = _base_url + operation_path + + # If the request url does NOT end with a /, then just return it as-is. + # Otherwise, return a regular expression that matches one or more trailing /. + if re.fullmatch('.*/+', request_url) is None: + return request_url + else: + return re.compile(request_url.rstrip('/') + '/+') -base_url = 'https://enterprise.cloud.ibm.com' -service.set_service_url(base_url) ############################################################################## # Start of Service: EnterpriseUsageReports ############################################################################## # region -class TestGetResourceUsageReport(): +class TestNewInstance(): """ - Test Class for get_resource_usage_report + Test Class for new_instance """ - def preprocess_url(self, request_url: str): + def test_new_instance(self): + """ + new_instance() + """ + os.environ['TEST_SERVICE_AUTH_TYPE'] = 'noAuth' + + service = EnterpriseUsageReportsV1.new_instance( + service_name='TEST_SERVICE', + ) + + assert service is not None + assert isinstance(service, EnterpriseUsageReportsV1) + + def test_new_instance_without_authenticator(self): """ - Preprocess the request URL to ensure the mock response will be found. + new_instance_without_authenticator() """ - if re.fullmatch('.*/+', request_url) is None: - return request_url - else: - return re.compile(request_url.rstrip('/') + '/+') + with pytest.raises(ValueError, match='authenticator must be provided'): + service = EnterpriseUsageReportsV1.new_instance( + service_name='TEST_SERVICE_NOT_FOUND', + ) + +class TestGetResourceUsageReport(): + """ + Test Class for get_resource_usage_report + """ @responses.activate def test_get_resource_usage_report_all_params(self): @@ -60,7 +106,7 @@ def test_get_resource_usage_report_all_params(self): get_resource_usage_report() """ # Set up mock - url = self.preprocess_url(base_url + '/v1/resource-usage-reports') + url = preprocess_url('/v1/resource-usage-reports') mock_response = '{"limit": 5, "first": {"href": "href"}, "next": {"href": "href"}, "reports": [{"entity_id": "de129b787b86403db7d3a14be2ae5f76", "entity_type": "enterprise", "entity_crn": "crn:v1:bluemix:public:enterprise::a/e9a57260546c4b4aa9ebfa316a82e56e::enterprise:de129b787b86403db7d3a14be2ae5f76", "entity_name": "Platform-Services", "billing_unit_id": "65719a07280a4022a9efa2f6ff4c3369", "billing_unit_crn": "crn:v1:bluemix:public:billing::a/3f99f8accbc848ea96f3c61a0ae22c44::billing-unit:65719a07280a4022a9efa2f6ff4c3369", "billing_unit_name": "Operations", "country_code": "USA", "currency_code": "USD", "month": "2017-08", "billable_cost": 13, "non_billable_cost": 17, "billable_rated_cost": 19, "non_billable_rated_cost": 23, "resources": [{"resource_id": "resource_id", "billable_cost": 13, "billable_rated_cost": 19, "non_billable_cost": 17, "non_billable_rated_cost": 23, "plans": [{"plan_id": "plan_id", "pricing_region": "pricing_region", "pricing_plan_id": "pricing_plan_id", "billable": true, "cost": 4, "rated_cost": 10, "usage": [{"metric": "UP-TIME", "unit": "HOURS", "quantity": 711.11, "rateable_quantity": 700, "cost": 123.45, "rated_cost": 130, "price": [{"anyKey": "anyValue"}]}]}]}]}]}' responses.add(responses.GET, url, @@ -79,7 +125,7 @@ def test_get_resource_usage_report_all_params(self): offset = 'testString' # Invoke method - response = service.get_resource_usage_report( + response = _service.get_resource_usage_report( enterprise_id=enterprise_id, account_group_id=account_group_id, account_id=account_id, @@ -106,6 +152,14 @@ def test_get_resource_usage_report_all_params(self): assert 'limit={}'.format(limit) in query_string assert 'offset={}'.format(offset) in query_string + def test_get_resource_usage_report_all_params_with_retries(self): + # Enable retries and run test_get_resource_usage_report_all_params. + _service.enable_retries() + self.test_get_resource_usage_report_all_params() + + # Disable retries and run test_get_resource_usage_report_all_params. + _service.disable_retries() + self.test_get_resource_usage_report_all_params() @responses.activate def test_get_resource_usage_report_required_params(self): @@ -113,7 +167,7 @@ def test_get_resource_usage_report_required_params(self): test_get_resource_usage_report_required_params() """ # Set up mock - url = self.preprocess_url(base_url + '/v1/resource-usage-reports') + url = preprocess_url('/v1/resource-usage-reports') mock_response = '{"limit": 5, "first": {"href": "href"}, "next": {"href": "href"}, "reports": [{"entity_id": "de129b787b86403db7d3a14be2ae5f76", "entity_type": "enterprise", "entity_crn": "crn:v1:bluemix:public:enterprise::a/e9a57260546c4b4aa9ebfa316a82e56e::enterprise:de129b787b86403db7d3a14be2ae5f76", "entity_name": "Platform-Services", "billing_unit_id": "65719a07280a4022a9efa2f6ff4c3369", "billing_unit_crn": "crn:v1:bluemix:public:billing::a/3f99f8accbc848ea96f3c61a0ae22c44::billing-unit:65719a07280a4022a9efa2f6ff4c3369", "billing_unit_name": "Operations", "country_code": "USA", "currency_code": "USD", "month": "2017-08", "billable_cost": 13, "non_billable_cost": 17, "billable_rated_cost": 19, "non_billable_rated_cost": 23, "resources": [{"resource_id": "resource_id", "billable_cost": 13, "billable_rated_cost": 19, "non_billable_cost": 17, "non_billable_rated_cost": 23, "plans": [{"plan_id": "plan_id", "pricing_region": "pricing_region", "pricing_plan_id": "pricing_plan_id", "billable": true, "cost": 4, "rated_cost": 10, "usage": [{"metric": "UP-TIME", "unit": "HOURS", "quantity": 711.11, "rateable_quantity": 700, "cost": 123.45, "rated_cost": 130, "price": [{"anyKey": "anyValue"}]}]}]}]}]}' responses.add(responses.GET, url, @@ -122,13 +176,94 @@ def test_get_resource_usage_report_required_params(self): status=200) # Invoke method - response = service.get_resource_usage_report() + response = _service.get_resource_usage_report() # Check for correct operation assert len(responses.calls) == 1 assert response.status_code == 200 + def test_get_resource_usage_report_required_params_with_retries(self): + # Enable retries and run test_get_resource_usage_report_required_params. + _service.enable_retries() + self.test_get_resource_usage_report_required_params() + + # Disable retries and run test_get_resource_usage_report_required_params. + _service.disable_retries() + self.test_get_resource_usage_report_required_params() + + @responses.activate + def test_get_resource_usage_report_with_pager_get_next(self): + """ + test_get_resource_usage_report_with_pager_get_next() + """ + # Set up a two-page mock response + url = preprocess_url('/v1/resource-usage-reports') + mock_response1 = '{"next":{"href":"https://myhost.com/somePath?offset=1"},"reports":[{"entity_id":"de129b787b86403db7d3a14be2ae5f76","entity_type":"enterprise","entity_crn":"crn:v1:bluemix:public:enterprise::a/e9a57260546c4b4aa9ebfa316a82e56e::enterprise:de129b787b86403db7d3a14be2ae5f76","entity_name":"Platform-Services","billing_unit_id":"65719a07280a4022a9efa2f6ff4c3369","billing_unit_crn":"crn:v1:bluemix:public:billing::a/3f99f8accbc848ea96f3c61a0ae22c44::billing-unit:65719a07280a4022a9efa2f6ff4c3369","billing_unit_name":"Operations","country_code":"USA","currency_code":"USD","month":"2017-08","billable_cost":13,"non_billable_cost":17,"billable_rated_cost":19,"non_billable_rated_cost":23,"resources":[{"resource_id":"resource_id","billable_cost":13,"billable_rated_cost":19,"non_billable_cost":17,"non_billable_rated_cost":23,"plans":[{"plan_id":"plan_id","pricing_region":"pricing_region","pricing_plan_id":"pricing_plan_id","billable":true,"cost":4,"rated_cost":10,"usage":[{"metric":"UP-TIME","unit":"HOURS","quantity":711.11,"rateable_quantity":700,"cost":123.45,"rated_cost":130,"price":[{"anyKey":"anyValue"}]}]}]}]}],"total_count":2,"limit":1}' + mock_response2 = '{"reports":[{"entity_id":"de129b787b86403db7d3a14be2ae5f76","entity_type":"enterprise","entity_crn":"crn:v1:bluemix:public:enterprise::a/e9a57260546c4b4aa9ebfa316a82e56e::enterprise:de129b787b86403db7d3a14be2ae5f76","entity_name":"Platform-Services","billing_unit_id":"65719a07280a4022a9efa2f6ff4c3369","billing_unit_crn":"crn:v1:bluemix:public:billing::a/3f99f8accbc848ea96f3c61a0ae22c44::billing-unit:65719a07280a4022a9efa2f6ff4c3369","billing_unit_name":"Operations","country_code":"USA","currency_code":"USD","month":"2017-08","billable_cost":13,"non_billable_cost":17,"billable_rated_cost":19,"non_billable_rated_cost":23,"resources":[{"resource_id":"resource_id","billable_cost":13,"billable_rated_cost":19,"non_billable_cost":17,"non_billable_rated_cost":23,"plans":[{"plan_id":"plan_id","pricing_region":"pricing_region","pricing_plan_id":"pricing_plan_id","billable":true,"cost":4,"rated_cost":10,"usage":[{"metric":"UP-TIME","unit":"HOURS","quantity":711.11,"rateable_quantity":700,"cost":123.45,"rated_cost":130,"price":[{"anyKey":"anyValue"}]}]}]}]}],"total_count":2,"limit":1}' + responses.add(responses.GET, + url, + body=mock_response1, + content_type='application/json', + status=200) + responses.add(responses.GET, + url, + body=mock_response2, + content_type='application/json', + status=200) + + # Exercise the pager class for this operation + all_results = [] + pager = GetResourceUsageReportPager( + client=_service, + enterprise_id='abc12340d4bf4e36b0423d209b286f24', + account_group_id='def456a237b94b9a9238ef024e204c9f', + account_id='987abcba31834216b8c726a7dd9eb8d6', + children=True, + month='2019-06', + billing_unit_id='testString', + limit=10, + ) + while pager.has_next(): + next_page = pager.get_next() + assert next_page is not None + all_results.extend(next_page) + assert len(all_results) == 2 + + @responses.activate + def test_get_resource_usage_report_with_pager_get_all(self): + """ + test_get_resource_usage_report_with_pager_get_all() + """ + # Set up a two-page mock response + url = preprocess_url('/v1/resource-usage-reports') + mock_response1 = '{"next":{"href":"https://myhost.com/somePath?offset=1"},"reports":[{"entity_id":"de129b787b86403db7d3a14be2ae5f76","entity_type":"enterprise","entity_crn":"crn:v1:bluemix:public:enterprise::a/e9a57260546c4b4aa9ebfa316a82e56e::enterprise:de129b787b86403db7d3a14be2ae5f76","entity_name":"Platform-Services","billing_unit_id":"65719a07280a4022a9efa2f6ff4c3369","billing_unit_crn":"crn:v1:bluemix:public:billing::a/3f99f8accbc848ea96f3c61a0ae22c44::billing-unit:65719a07280a4022a9efa2f6ff4c3369","billing_unit_name":"Operations","country_code":"USA","currency_code":"USD","month":"2017-08","billable_cost":13,"non_billable_cost":17,"billable_rated_cost":19,"non_billable_rated_cost":23,"resources":[{"resource_id":"resource_id","billable_cost":13,"billable_rated_cost":19,"non_billable_cost":17,"non_billable_rated_cost":23,"plans":[{"plan_id":"plan_id","pricing_region":"pricing_region","pricing_plan_id":"pricing_plan_id","billable":true,"cost":4,"rated_cost":10,"usage":[{"metric":"UP-TIME","unit":"HOURS","quantity":711.11,"rateable_quantity":700,"cost":123.45,"rated_cost":130,"price":[{"anyKey":"anyValue"}]}]}]}]}],"total_count":2,"limit":1}' + mock_response2 = '{"reports":[{"entity_id":"de129b787b86403db7d3a14be2ae5f76","entity_type":"enterprise","entity_crn":"crn:v1:bluemix:public:enterprise::a/e9a57260546c4b4aa9ebfa316a82e56e::enterprise:de129b787b86403db7d3a14be2ae5f76","entity_name":"Platform-Services","billing_unit_id":"65719a07280a4022a9efa2f6ff4c3369","billing_unit_crn":"crn:v1:bluemix:public:billing::a/3f99f8accbc848ea96f3c61a0ae22c44::billing-unit:65719a07280a4022a9efa2f6ff4c3369","billing_unit_name":"Operations","country_code":"USA","currency_code":"USD","month":"2017-08","billable_cost":13,"non_billable_cost":17,"billable_rated_cost":19,"non_billable_rated_cost":23,"resources":[{"resource_id":"resource_id","billable_cost":13,"billable_rated_cost":19,"non_billable_cost":17,"non_billable_rated_cost":23,"plans":[{"plan_id":"plan_id","pricing_region":"pricing_region","pricing_plan_id":"pricing_plan_id","billable":true,"cost":4,"rated_cost":10,"usage":[{"metric":"UP-TIME","unit":"HOURS","quantity":711.11,"rateable_quantity":700,"cost":123.45,"rated_cost":130,"price":[{"anyKey":"anyValue"}]}]}]}]}],"total_count":2,"limit":1}' + responses.add(responses.GET, + url, + body=mock_response1, + content_type='application/json', + status=200) + responses.add(responses.GET, + url, + body=mock_response2, + content_type='application/json', + status=200) + + # Exercise the pager class for this operation + pager = GetResourceUsageReportPager( + client=_service, + enterprise_id='abc12340d4bf4e36b0423d209b286f24', + account_group_id='def456a237b94b9a9238ef024e204c9f', + account_id='987abcba31834216b8c726a7dd9eb8d6', + children=True, + month='2019-06', + billing_unit_id='testString', + limit=10, + ) + all_results = pager.get_all() + assert all_results is not None + assert len(all_results) == 2 # endregion ############################################################################## @@ -140,7 +275,7 @@ def test_get_resource_usage_report_required_params(self): # Start of Model Tests ############################################################################## # region -class TestLink(): +class TestModel_Link(): """ Test Class for Link """ @@ -169,7 +304,7 @@ def test_link_serialization(self): link_model_json2 = link_model.to_dict() assert link_model_json2 == link_model_json -class TestMetricUsage(): +class TestModel_MetricUsage(): """ Test Class for MetricUsage """ @@ -187,7 +322,7 @@ def test_metric_usage_serialization(self): metric_usage_model_json['rateable_quantity'] = 700 metric_usage_model_json['cost'] = 123.45 metric_usage_model_json['rated_cost'] = 130 - metric_usage_model_json['price'] = [{ 'foo': 'bar' }] + metric_usage_model_json['price'] = [{'foo': 'bar'}] # Construct a model instance of MetricUsage by calling from_dict on the json representation metric_usage_model = MetricUsage.from_dict(metric_usage_model_json) @@ -204,7 +339,7 @@ def test_metric_usage_serialization(self): metric_usage_model_json2 = metric_usage_model.to_dict() assert metric_usage_model_json2 == metric_usage_model_json -class TestPlanUsage(): +class TestModel_PlanUsage(): """ Test Class for PlanUsage """ @@ -223,7 +358,7 @@ def test_plan_usage_serialization(self): metric_usage_model['rateable_quantity'] = 700 metric_usage_model['cost'] = 123.45 metric_usage_model['rated_cost'] = 130 - metric_usage_model['price'] = [{ 'foo': 'bar' }] + metric_usage_model['price'] = [{'foo': 'bar'}] # Construct a json representation of a PlanUsage model plan_usage_model_json = {} @@ -250,7 +385,7 @@ def test_plan_usage_serialization(self): plan_usage_model_json2 = plan_usage_model.to_dict() assert plan_usage_model_json2 == plan_usage_model_json -class TestReports(): +class TestModel_Reports(): """ Test Class for Reports """ @@ -272,7 +407,7 @@ def test_reports_serialization(self): metric_usage_model['rateable_quantity'] = 10 metric_usage_model['cost'] = 10 metric_usage_model['rated_cost'] = 10 - metric_usage_model['price'] = [{ 'foo': 'bar' }] + metric_usage_model['price'] = [{'foo': 'bar'}] plan_usage_model = {} # PlanUsage plan_usage_model['plan_id'] = 'cloudant-standard' @@ -330,7 +465,7 @@ def test_reports_serialization(self): reports_model_json2 = reports_model.to_dict() assert reports_model_json2 == reports_model_json -class TestResourceUsage(): +class TestModel_ResourceUsage(): """ Test Class for ResourceUsage """ @@ -349,7 +484,7 @@ def test_resource_usage_serialization(self): metric_usage_model['rateable_quantity'] = 700 metric_usage_model['cost'] = 123.45 metric_usage_model['rated_cost'] = 130 - metric_usage_model['price'] = [{ 'foo': 'bar' }] + metric_usage_model['price'] = [{'foo': 'bar'}] plan_usage_model = {} # PlanUsage plan_usage_model['plan_id'] = 'testString' @@ -384,7 +519,7 @@ def test_resource_usage_serialization(self): resource_usage_model_json2 = resource_usage_model.to_dict() assert resource_usage_model_json2 == resource_usage_model_json -class TestResourceUsageReport(): +class TestModel_ResourceUsageReport(): """ Test Class for ResourceUsageReport """ @@ -403,7 +538,7 @@ def test_resource_usage_report_serialization(self): metric_usage_model['rateable_quantity'] = 700 metric_usage_model['cost'] = 123.45 metric_usage_model['rated_cost'] = 130 - metric_usage_model['price'] = [{ 'foo': 'bar' }] + metric_usage_model['price'] = [{'foo': 'bar'}] plan_usage_model = {} # PlanUsage plan_usage_model['plan_id'] = 'testString' From 9955a4bae419d560c66f0ec866bae13854677f78 Mon Sep 17 00:00:00 2001 From: Phil Adams Date: Wed, 26 Oct 2022 07:35:42 -0500 Subject: [PATCH 2/2] chore: update .secrets.baseline to avoid false alerts Signed-off-by: Phil Adams --- .secrets.baseline | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 9c1b75da..67808564 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2021-12-02T14:38:21Z", + "generated_at": "2022-10-26T12:35:22Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -82,7 +82,7 @@ "hashed_secret": "a2190c299b60e882d9fb33736d5e6ab6ffe42708", "is_secret": false, "is_verified": false, - "line_number": 822, + "line_number": 826, "type": "Secret Keyword", "verified_result": null } @@ -92,7 +92,7 @@ "hashed_secret": "eafd657ce70e075f0b72cdbe48232ed4fd5a47d1", "is_secret": false, "is_verified": false, - "line_number": 617, + "line_number": 624, "type": "Secret Keyword", "verified_result": null }, @@ -100,7 +100,7 @@ "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", "is_secret": false, "is_verified": false, - "line_number": 3536, + "line_number": 4243, "type": "Secret Keyword", "verified_result": null } @@ -110,7 +110,7 @@ "hashed_secret": "d506bd5213c46bd49e16c634754ad70113408252", "is_secret": false, "is_verified": false, - "line_number": 3326, + "line_number": 3380, "type": "Secret Keyword", "verified_result": null } @@ -140,7 +140,7 @@ "hashed_secret": "a2190c299b60e882d9fb33736d5e6ab6ffe42708", "is_secret": false, "is_verified": false, - "line_number": 1035, + "line_number": 1041, "type": "Secret Keyword", "verified_result": null } @@ -168,7 +168,7 @@ "hashed_secret": "b8473b86d4c2072ca9b08bd28e373e8253e865c4", "is_secret": false, "is_verified": false, - "line_number": 4605, + "line_number": 6309, "type": "Secret Keyword", "verified_result": null } @@ -204,7 +204,7 @@ "hashed_secret": "f0b0b291c4d22d76db59faaeb94802714dd6d884", "is_secret": false, "is_verified": false, - "line_number": 884, + "line_number": 832, "type": "Hex High Entropy String", "verified_result": null }, @@ -212,7 +212,7 @@ "hashed_secret": "4c41e7a08e8895da0c6066adf33bf389c202b4e2", "is_secret": false, "is_verified": false, - "line_number": 1294, + "line_number": 1227, "type": "Hex High Entropy String", "verified_result": null }, @@ -220,7 +220,7 @@ "hashed_secret": "ca8b3e9d1445b3218e3512da63b05c8f26f181e5", "is_secret": false, "is_verified": false, - "line_number": 1303, + "line_number": 1236, "type": "Hex High Entropy String", "verified_result": null } @@ -240,7 +240,7 @@ "hashed_secret": "5bfabda9d31f1270745654e91a23ca1ff9b26a95", "is_secret": false, "is_verified": false, - "line_number": 72, + "line_number": 256, "type": "Hex High Entropy String", "verified_result": null }, @@ -248,7 +248,7 @@ "hashed_secret": "d06f0318f9eff64a13844ce2fa66cf9fb37a8cad", "is_secret": false, "is_verified": false, - "line_number": 73, + "line_number": 257, "type": "Hex High Entropy String", "verified_result": null }, @@ -256,7 +256,7 @@ "hashed_secret": "820b2eb95f60d828f82a984ce0321feab7868833", "is_secret": false, "is_verified": false, - "line_number": 74, + "line_number": 258, "type": "Hex High Entropy String", "verified_result": null }, @@ -264,7 +264,7 @@ "hashed_secret": "0f947a1a4f7cb716dc9f780bc563477bfb569c0e", "is_secret": false, "is_verified": false, - "line_number": 295, + "line_number": 430, "type": "Hex High Entropy String", "verified_result": null }, @@ -272,7 +272,7 @@ "hashed_secret": "953fd8a5aac905b12bf5d8cff3710d345c209632", "is_secret": false, "is_verified": false, - "line_number": 427, + "line_number": 562, "type": "Hex High Entropy String", "verified_result": null }, @@ -280,7 +280,7 @@ "hashed_secret": "a0138a9944cb15ff025195706f98f95d9a544eb6", "is_secret": false, "is_verified": false, - "line_number": 431, + "line_number": 566, "type": "Hex High Entropy String", "verified_result": null } @@ -290,7 +290,7 @@ "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", "is_secret": false, "is_verified": false, - "line_number": 1227, + "line_number": 1346, "type": "Secret Keyword", "verified_result": null }, @@ -298,7 +298,7 @@ "hashed_secret": "cf4d2385b84329a52ca542285b93d9c4618420df", "is_secret": false, "is_verified": false, - "line_number": 2982, + "line_number": 3256, "type": "Secret Keyword", "verified_result": null }, @@ -306,7 +306,7 @@ "hashed_secret": "469f62fa9e1c6afe62e8808180668934ee548e8f", "is_secret": false, "is_verified": false, - "line_number": 3049, + "line_number": 3571, "type": "Secret Keyword", "verified_result": null }, @@ -314,7 +314,7 @@ "hashed_secret": "b8473b86d4c2072ca9b08bd28e373e8253e865c4", "is_secret": false, "is_verified": false, - "line_number": 3731, + "line_number": 4540, "type": "Secret Keyword", "verified_result": null } @@ -324,7 +324,7 @@ "hashed_secret": "d4c3d66fd0c38547a3c7a4c6bdc29c36911bc030", "is_secret": false, "is_verified": false, - "line_number": 2212, + "line_number": 2277, "type": "Secret Keyword", "verified_result": null }, @@ -332,13 +332,13 @@ "hashed_secret": "b8473b86d4c2072ca9b08bd28e373e8253e865c4", "is_secret": false, "is_verified": false, - "line_number": 3112, + "line_number": 3177, "type": "Secret Keyword", "verified_result": null } ] }, - "version": "0.13.1+ibm.46.dss", + "version": "0.13.1+ibm.55.dss", "word_list": { "file": null, "hash": null