def create(self, validated_data): """Create a user from validated data.""" user = None tenant = None request = self.context.get('request') if request and hasattr(request, 'META'): json_rh_auth = extract_header(request, RH_IDENTITY_HEADER) if (json_rh_auth and 'identity' in json_rh_auth and # noqa: W504 'account_number' in json_rh_auth['identity']): account = json_rh_auth['identity']['account_number'] if account: schema_name = create_schema_name(account) try: tenant = Tenant.objects.get(schema_name=schema_name) except Tenant.DoesNotExist: tenant = Tenant(schema_name=schema_name) tenant.save() tenant = Tenant.objects.get(schema_name=schema_name) else: key = 'detail' message = 'Tenant for requesting user could not be found.' raise serializers.ValidationError(error_obj(key, message)) user = _create_user(username=validated_data.get('username'), email=validated_data.get('email'), tenant=tenant) return user
def _create_customer(cls, account, create_tenant=True): """Create a customer. Args: account (str): The account identifier Returns: (Customer) The created customer """ connection.set_schema_to_public() schema_name = create_schema_name(account) tenant = None if create_tenant: tenant = Tenant(schema_name=schema_name) tenant.save() return tenant
def _create_tenant(account): """Create a tenant. Args: account (str): The account identifier Returns: (Tenant) The created tenant """ schema_name = create_schema_name(account) try: with transaction.atomic(): tenant = Tenant(schema_name=schema_name) tenant.save() logger.info('Created new tenant from account_id %s.', account) except IntegrityError: tenant = Tenant.objects.filter(schema_name=schema_name).get() return tenant
class ReportQueryTest(IamTestCase): """Tests the report queries.""" def setUp(self): """Set up the customer view tests.""" super().setUp() self.create_service_admin() customer = self.customer_data[0] response = self.create_customer(customer) self.assertEqual(response.status_code, 201) customer_json = response.json() customer_uuid = customer_json.get('uuid') customer_obj = Customer.objects.filter(uuid=customer_uuid).get() self.tenant = Tenant(schema_name=customer_obj.schema_name) self.tenant.save() self.add_data_to_tenant() def create_hourly_instance_usage(self, payer_account_id, bill, ce_pricing, ce_product, rate, cost, start_hour, end_hour): """Create houlr instance usage.""" cost_entry = AWSCostEntry(interval_start=start_hour, interval_end=end_hour, bill=bill) cost_entry.save() line_item = AWSCostEntryLineItem( invoice_id=self.fake.sha1(raw_output=False), line_item_type='Usage', usage_account_id=payer_account_id, usage_start=start_hour, usage_end=end_hour, product_code='AmazonEC2', usage_type='BoxUsage:c4.xlarge', operation='RunInstances', availability_zone='us-east-1a', resource_id='i-{}'.format(self.fake.ean8()), usage_amount=1, currency_code='USD', unblended_rate=rate, unblended_cost=cost, blended_rate=rate, blended_cost=cost, cost_entry=cost_entry, cost_entry_bill=bill, cost_entry_product=ce_product, cost_entry_pricing=ce_pricing) line_item.save() def add_data_to_tenant(self): """Populate tenant with data.""" payer_account_id = self.fake.ean(length=13) # pylint: disable=no-member self.payer_account_id = payer_account_id one_day = datetime.timedelta(days=1) one_hour = datetime.timedelta(minutes=60) this_hour = timezone.now().replace(microsecond=0, second=0, minute=0) yesterday = this_hour - one_day bill_start = this_hour.replace(microsecond=0, second=0, minute=0, hour=0, day=1) bill_end = ReportQueryHandler.next_month(bill_start) with tenant_context(self.tenant): bill = AWSCostEntryBill(bill_type='Anniversary', payer_account_id=payer_account_id, billing_period_start=bill_start, billing_period_end=bill_end) bill.save() rate = 0.199 amount = 1 cost = rate * amount # pylint: disable=no-member sku = self.fake.pystr(min_chars=12, max_chars=12).upper() prod_ec2 = 'Amazon Elastic Compute Cloud' ce_product = AWSCostEntryProduct(sku=sku, product_name=prod_ec2, product_family='Compute Instance', service_code='AmazonEC2', region='US East (N. Virginia)', instance_type='c4.xlarge', memory=7.5, vcpu=4) ce_product.save() ce_pricing = AWSCostEntryPricing(public_on_demand_cost=rate * 1, public_on_demand_rate=rate, term='OnDemand', unit='Hrs') ce_pricing.save() current = yesterday while current < this_hour: end_hour = current + one_hour self.create_hourly_instance_usage(payer_account_id, bill, ce_pricing, ce_product, rate, cost, current, end_hour) current = end_hour def test_has_filter_no_filter(self): """Test the has_filter method with no filter in the query params.""" handler = ReportQueryHandler({}, '', self.tenant, 'unblended_cost', 'currency_code') self.assertFalse( handler.check_query_params('filter', 'time_scope_value')) def test_has_filter_with_filter(self): """Test the has_filter method with filter in the query params.""" query_params = { 'filter': { 'resolution': 'monthly', 'time_scope_value': -1 } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertIsNotNone( handler.check_query_params('filter', 'time_scope_value')) def test_get_group_by_no_data(self): """Test the get_group_by_data method with no data in the query params.""" handler = ReportQueryHandler({}, '', self.tenant, 'unblended_cost', 'currency_code') self.assertFalse(handler.get_group_by_data('service')) def test_get_group_by_with_service_list(self): """Test the get_group_by_data method with no data in the query params.""" expected = ['a', 'b'] query_string = '?group_by[service]=a&group_by[service]=b' handler = ReportQueryHandler({'group_by': { 'service': expected }}, query_string, self.tenant, 'unblended_cost', 'currency_code') service = handler.get_group_by_data('service') self.assertEqual(expected, service) def test_get_resolution_empty_default(self): """Test get_resolution returns default when query params are empty.""" query_params = {} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_resolution(), 'daily') self.assertEqual(handler.get_resolution(), 'daily') def test_get_resolution_empty_month_time_scope(self): """Test get_resolution returns default when time_scope is month.""" query_params = {'filter': {'time_scope_value': -1}} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_resolution(), 'monthly') def test_get_resolution_empty_day_time_scope(self): """Test get_resolution returns default when time_scope is month.""" query_params = {'filter': {'time_scope_value': -10}} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_resolution(), 'daily') def test_get_time_scope_units_empty_default(self): """Test get_time_scope_units returns default when query params are empty.""" query_params = {} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_time_scope_units(), 'day') self.assertEqual(handler.get_time_scope_units(), 'day') def test_get_time_scope_units_empty_month_time_scope(self): """Test get_time_scope_units returns default when time_scope is month.""" query_params = {'filter': {'time_scope_value': -1}} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_time_scope_units(), 'month') def test_get_time_scope_units_empty_day_time_scope(self): """Test get_time_scope_units returns default when time_scope is month.""" query_params = {'filter': {'time_scope_value': -10}} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_time_scope_units(), 'day') def test_get_time_scope_value_empty_default(self): """Test get_time_scope_value returns default when query params are empty.""" query_params = {} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_time_scope_value(), -10) self.assertEqual(handler.get_time_scope_value(), -10) def test_get_time_scope_value_empty_month_time_scope(self): """Test get_time_scope_value returns default when time_scope is month.""" query_params = {'filter': {'time_scope_units': 'month'}} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_time_scope_value(), -1) def test_get_time_scope_value_empty_day_time_scope(self): """Test get_time_scope_value returns default when time_scope is month.""" query_params = {'filter': {'time_scope_units': 'day'}} handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') self.assertEqual(handler.get_time_scope_value(), -10) def test_get_time_frame_filter_current_month(self): """Test _get_time_frame_filter for current month.""" query_params = { 'filter': { 'resolution': 'daily', 'time_scope_value': -1, 'time_scope_units': 'month' } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') current_month = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0, day=1) next_month = ReportQueryHandler.next_month(current_month) start = handler.start_datetime end = handler.end_datetime interval = handler.time_interval self.assertEqual(start, current_month) self.assertEqual(end, next_month) self.assertIsInstance(interval, list) self.assertTrue(len(interval) >= 28) def test_get_time_frame_filter_previous_month(self): """Test _get_time_frame_filter for previous month.""" query_params = { 'filter': { 'resolution': 'daily', 'time_scope_value': -2, 'time_scope_units': 'month' } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') current_month = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0, day=1) prev_month = ReportQueryHandler.previous_month(current_month) start = handler.start_datetime end = handler.end_datetime interval = handler.time_interval self.assertEqual(start, prev_month) self.assertEqual(end, current_month) self.assertIsInstance(interval, list) self.assertTrue(len(interval) >= 28) def test_get_time_frame_filter_last_ten(self): """Test _get_time_frame_filter for last ten days.""" query_params = { 'filter': { 'resolution': 'daily', 'time_scope_value': -10, 'time_scope_units': 'day' } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') current_day = timezone.now().replace(microsecond=0, second=0, minute=0) ten_days_ago = ReportQueryHandler.n_days_ago(current_day, 10) start = handler.start_datetime end = handler.end_datetime interval = handler.time_interval self.assertEqual(start, ten_days_ago) self.assertEqual(end, current_day) self.assertIsInstance(interval, list) self.assertTrue(len(interval) == 11) def test_get_time_frame_filter_last_thirty(self): """Test _get_time_frame_filter for last thirty days.""" query_params = { 'filter': { 'resolution': 'daily', 'time_scope_value': -30, 'time_scope_units': 'day' } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') current_day = timezone.now().replace(microsecond=0, second=0, minute=0) ten_days_ago = ReportQueryHandler.n_days_ago(current_day, 30) start = handler.start_datetime end = handler.end_datetime interval = handler.time_interval self.assertEqual(start, ten_days_ago) self.assertEqual(end, current_day) self.assertIsInstance(interval, list) self.assertTrue(len(interval) == 31) def test_execute_query_current_month_daily(self): """Test execute_query for current month on daily breakdown.""" query_params = { 'filter': { 'resolution': 'daily', 'time_scope_value': -1, 'time_scope_units': 'month' } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') query_output = handler.execute_query() self.assertIsNotNone(query_output.get('data')) self.assertIsNotNone(query_output.get('total')) total = query_output.get('total') self.assertIsNotNone(total.get('value')) self.assertEqual(total.get('value'), Decimal('4.776000000')) def test_execute_query_current_month_monthly(self): """Test execute_query for current month on monthly breakdown.""" query_params = { 'filter': { 'resolution': 'monthly', 'time_scope_value': -1, 'time_scope_units': 'month' } } handler = ReportQueryHandler(query_params, '', self.tenant, 'unblended_cost', 'currency_code') query_output = handler.execute_query() self.assertIsNotNone(query_output.get('data')) self.assertIsNotNone(query_output.get('total')) total = query_output.get('total') self.assertIsNotNone(total.get('value')) self.assertEqual(total.get('value'), Decimal('4.776000000')) def test_execute_query_current_month_by_service(self): """Test execute_query for current month on monthly breakdown by service.""" query_params = { 'filter': { 'resolution': 'monthly', 'time_scope_value': -1, 'time_scope_units': 'month' }, 'group_by': { 'service': ['*'] } } handler = ReportQueryHandler(query_params, '?group_by[service]=*', self.tenant, 'unblended_cost', 'currency_code') query_output = handler.execute_query() data = query_output.get('data') self.assertIsNotNone(data) self.assertIsNotNone(query_output.get('total')) total = query_output.get('total') self.assertIsNotNone(total.get('value')) self.assertEqual(total.get('value'), Decimal('4.776000000')) current_month = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0, day=1) cmonth_str = current_month.strftime('%Y-%m') for data_item in data: month_val = data_item.get('date') month_data = data_item.get('services') self.assertEqual(month_val, cmonth_str) self.assertIsInstance(month_data, list) for month_item in month_data: compute = month_item.get('service') self.assertEqual(compute, 'Compute Instance') self.assertIsInstance(month_item.get('values'), list) def test_execute_query_by_filtered_service(self): """Test execute_query monthly breakdown by filtered service.""" query_params = { 'filter': { 'resolution': 'monthly', 'time_scope_value': -1, 'time_scope_units': 'month' }, 'group_by': { 'service': ['Compute Instance'] } } handler = ReportQueryHandler(query_params, '?group_by[service]=Compute Instance', self.tenant, 'unblended_cost', 'currency_code') query_output = handler.execute_query() data = query_output.get('data') self.assertIsNotNone(data) self.assertIsNotNone(query_output.get('total')) total = query_output.get('total') self.assertIsNotNone(total.get('value')) self.assertEqual(total.get('value'), Decimal('4.776000000')) current_month = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0, day=1) cmonth_str = current_month.strftime('%Y-%m') for data_item in data: month_val = data_item.get('date') month_data = data_item.get('services') self.assertEqual(month_val, cmonth_str) self.assertIsInstance(month_data, list) for month_item in month_data: compute = month_item.get('service') self.assertEqual(compute, 'Compute Instance') self.assertIsInstance(month_item.get('values'), list) def test_execute_query_current_month_by_account(self): """Test execute_query for current month on monthly breakdown by account.""" query_params = { 'filter': { 'resolution': 'monthly', 'time_scope_value': -1, 'time_scope_units': 'month' }, 'group_by': { 'account': ['*'] } } handler = ReportQueryHandler(query_params, '?group_by[account]=*', self.tenant, 'unblended_cost', 'currency_code') query_output = handler.execute_query() data = query_output.get('data') self.assertIsNotNone(data) self.assertIsNotNone(query_output.get('total')) total = query_output.get('total') self.assertIsNotNone(total.get('value')) self.assertEqual(total.get('value'), Decimal('4.776000000')) current_month = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0, day=1) cmonth_str = current_month.strftime('%Y-%m') for data_item in data: month_val = data_item.get('date') month_data = data_item.get('accounts') self.assertEqual(month_val, cmonth_str) self.assertIsInstance(month_data, list) for month_item in month_data: account = month_item.get('account') self.assertEqual(account, self.payer_account_id) self.assertIsInstance(month_item.get('values'), list) def test_execute_query_by_account_by_service(self): """Test execute_query for current month breakdown by account by service.""" query_params = { 'filter': { 'resolution': 'monthly', 'time_scope_value': -1, 'time_scope_units': 'month' }, 'group_by': { 'account': ['*'], 'service': ['*'] } } query_string = '?group_by[account]=*&group_by[service]=Compute Instance' handler = ReportQueryHandler(query_params, query_string, self.tenant, 'unblended_cost', 'currency_code') query_output = handler.execute_query() data = query_output.get('data') self.assertIsNotNone(data) self.assertIsNotNone(query_output.get('total')) total = query_output.get('total') self.assertIsNotNone(total.get('value')) self.assertEqual(total.get('value'), Decimal('4.776000000')) current_month = timezone.now().replace(microsecond=0, second=0, minute=0, hour=0, day=1) cmonth_str = current_month.strftime('%Y-%m') for data_item in data: month_val = data_item.get('date') month_data = data_item.get('accounts') self.assertEqual(month_val, cmonth_str) self.assertIsInstance(month_data, list) for month_item in month_data: account = month_item.get('account') self.assertEqual(account, self.payer_account_id) self.assertIsInstance(month_item.get('services'), list)
class ReportViewTest(IamTestCase): """Tests the report view.""" def setUp(self): """Set up the customer view tests.""" super().setUp() self.create_service_admin() customer = self.customer_data[0] response = self.create_customer(customer) self.assertEqual(response.status_code, 201) customer_json = response.json() customer_uuid = customer_json.get('uuid') customer_obj = Customer.objects.filter(uuid=customer_uuid).get() self.tenant = Tenant(schema_name=customer_obj.schema_name) self.tenant.save() def tearDown(self): """Tear down user tests.""" super().tearDown() Customer.objects.all().delete() User.objects.all().delete() def test_get_costs_anon(self): """Test costs reports fail with an anonymous user.""" url = reverse('reports-costs') client = APIClient() response = client.get(url) self.assertEqual(response.status_code, 403) def test_get_storage_anon(self): """Test inventory storage reports fail with an anonymous user.""" url = reverse('reports-storage') client = APIClient() response = client.get(url) self.assertEqual(response.status_code, 403) def test_get_instance_anon(self): """Test inventory instance reports fail with an anonymous user.""" url = reverse('reports-instance-type') client = APIClient() response = client.get(url) self.assertEqual(response.status_code, 403) def test_get_costs_customer_owner(self): """Test costs reports runs with a customer owner.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-costs') client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 200) json_result = response.json() self.assertIsNotNone(json_result.get('data')) self.assertIsInstance(json_result.get('data'), list) self.assertTrue(len(json_result.get('data')) > 0) def test_get_instance_customer_owner(self): """Test inventory instance reports runs with a customer owner.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-instance-type') client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 200) json_result = response.json() self.assertIsNotNone(json_result.get('data')) self.assertIsInstance(json_result.get('data'), list) self.assertTrue(len(json_result.get('data')) > 0) def test_get_storage_customer_owner(self): """Test inventory storage reports runs with a customer owner.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-storage') client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 200) json_result = response.json() self.assertIsNotNone(json_result.get('data')) self.assertIsInstance(json_result.get('data'), list) self.assertTrue(len(json_result.get('data')) > 0) def test_process_query_parameters(self): """Test processing of valid parameters.""" qs = 'group_by%5Baccount%5D=account1&filter%5Bresolution%5D=daily' valid, query_dict = process_query_parameters(qs) self.assertTrue(valid) self.assertEqual(query_dict.get('group_by'), {'account': ['account1']}) self.assertEqual(query_dict.get('filter'), {'resolution': 'daily'}) def test_process_query_parameters_invalid(self): """Test processing of invalid parameters.""" qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' valid, _ = process_query_parameters(qs) self.assertFalse(valid) def test_get_costs_invalid_query_param(self): """Test costs reports runs with an invalid query param.""" token = self.get_customer_owner_token(self.customer_data[0]) qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' url = reverse('reports-costs') + '?' + qs client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 400) def test_get_instance_usage_invalid_query_param(self): """Test instance usage reports runs with an invalid query param.""" token = self.get_customer_owner_token(self.customer_data[0]) qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' url = reverse('reports-instance-type') + '?' + qs client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 400) def test_get_storage_usage_invalid_query_param(self): """Test storage usage reports runs with an invalid query param.""" token = self.get_customer_owner_token(self.customer_data[0]) qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' url = reverse('reports-storage') + '?' + qs client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 400) def test_get_tenant_no_group(self): """Test get_tenant with a user with no group.""" user = Mock() group = Mock() group.id = 909090 user.groups.first.return_value = group with self.assertRaises(ValidationError): get_tenant(user)
class ReportViewTest(IamTestCase): """Tests the report view.""" def setUp(self): """Set up the customer view tests.""" super().setUp() self.create_service_admin() customer = self.customer_data[0] response = self.create_customer(customer) self.assertEqual(response.status_code, 201) customer_json = response.json() customer_uuid = customer_json.get('uuid') customer_obj = Customer.objects.filter(uuid=customer_uuid).get() self.tenant = Tenant(schema_name=customer_obj.schema_name) self.tenant.save() self.report = { 'group_by': { 'account': ['*'] }, 'filter': { 'resolution': 'monthly', 'time_scope_value': -1, 'time_scope_units': 'month', 'resource_scope': [] }, 'data': [ { 'date': '2018-07', 'accounts': [ { 'account': '4418636104713', 'values': [ { 'date': '2018-07', 'units': 'GB-Mo', 'account': '4418636104713', 'total': 1826.74238146924 } ] }, { 'account': '8577742690384', 'values': [ { 'date': '2018-07', 'units': 'GB-Mo', 'account': '8577742690384', 'total': 1137.74036198065 } ] }, { 'account': '3474227945050', 'values': [ { 'date': '2018-07', 'units': 'GB-Mo', 'account': '3474227945050', 'total': 1045.80659412797 } ] }, { 'account': '7249815104968', 'values': [ { 'date': '2018-07', 'units': 'GB-Mo', 'account': '7249815104968', 'total': 807.326470618818 } ] }, { 'account': '9420673783214', 'values': [ { 'date': '2018-07', 'units': 'GB-Mo', 'account': '9420673783214', 'total': 658.306642830709 } ] } ] } ], 'total': { 'value': 5475.922451027388, 'units': 'GB-Mo' } } def tearDown(self): """Tear down user tests.""" super().tearDown() Customer.objects.all().delete() User.objects.all().delete() def test_get_costs_anon(self): """Test costs reports fail with an anonymous user.""" url = reverse('reports-costs') client = APIClient() response = client.get(url) self.assertEqual(response.status_code, 403) def test_get_storage_anon(self): """Test inventory storage reports fail with an anonymous user.""" url = reverse('reports-storage') client = APIClient() response = client.get(url) self.assertEqual(response.status_code, 403) def test_get_instance_anon(self): """Test inventory instance reports fail with an anonymous user.""" url = reverse('reports-instance-type') client = APIClient() response = client.get(url) self.assertEqual(response.status_code, 403) def test_get_costs_customer_owner(self): """Test costs reports runs with a customer owner.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-costs') client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 200) json_result = response.json() self.assertIsNotNone(json_result.get('data')) self.assertIsInstance(json_result.get('data'), list) self.assertTrue(len(json_result.get('data')) > 0) def test_get_instance_customer_owner(self): """Test inventory instance reports runs with a customer owner.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-instance-type') client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 200) json_result = response.json() self.assertIsNotNone(json_result.get('data')) self.assertIsInstance(json_result.get('data'), list) self.assertTrue(len(json_result.get('data')) > 0) def test_get_storage_customer_owner(self): """Test inventory storage reports runs with a customer owner.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-storage') client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 200) json_result = response.json() self.assertIsNotNone(json_result.get('data')) self.assertIsInstance(json_result.get('data'), list) self.assertTrue(len(json_result.get('data')) > 0) def test_process_query_parameters(self): """Test processing of valid parameters.""" qs = 'group_by%5Baccount%5D=account1&filter%5Bresolution%5D=daily' valid, query_dict = process_query_parameters(qs) self.assertTrue(valid) self.assertEqual(query_dict.get('group_by'), {'account': ['account1']}) self.assertEqual(query_dict.get('filter'), {'resolution': 'daily'}) def test_process_query_parameters_invalid(self): """Test processing of invalid parameters.""" qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' valid, _ = process_query_parameters(qs) self.assertFalse(valid) def test_get_costs_invalid_query_param(self): """Test costs reports runs with an invalid query param.""" token = self.get_customer_owner_token(self.customer_data[0]) qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' url = reverse('reports-costs') + '?' + qs client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 400) def test_get_instance_usage_invalid_query_param(self): """Test instance usage reports runs with an invalid query param.""" token = self.get_customer_owner_token(self.customer_data[0]) qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' url = reverse('reports-instance-type') + '?' + qs client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 400) def test_get_storage_usage_invalid_query_param(self): """Test storage usage reports runs with an invalid query param.""" token = self.get_customer_owner_token(self.customer_data[0]) qs = 'group_by%5Binvalid%5D=account1&filter%5Bresolution%5D=daily' url = reverse('reports-storage') + '?' + qs client = APIClient() client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) self.assertEqual(response.status_code, 400) def test_get_tenant_no_group(self): """Test get_tenant with a user with no group.""" user = Mock() group = Mock() group.id = 909090 user.groups.first.return_value = group with self.assertRaises(ValidationError): get_tenant(user) def test_get_costs_csv(self): """Test CSV output of costs reports.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-costs') client = APIClient(HTTP_ACCEPT='text/csv') client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url) response.render() self.assertEqual(response.status_code, 200) self.assertEqual(response.accepted_media_type, 'text/csv') self.assertIsInstance(response.accepted_renderer, CSVRenderer) def test_get_instance_csv(self): """Test CSV output of inventory instance reports.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-instance-type') client = APIClient(HTTP_ACCEPT='text/csv') client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url, content_type='text/csv') response.render() self.assertEqual(response.status_code, 200) self.assertEqual(response.accepted_media_type, 'text/csv') self.assertIsInstance(response.accepted_renderer, CSVRenderer) def test_get_storage_csv(self): """Test CSV output of inventory storage reports.""" token = self.get_customer_owner_token(self.customer_data[0]) url = reverse('reports-storage') client = APIClient(HTTP_ACCEPT='text/csv') client.credentials(HTTP_AUTHORIZATION=token) response = client.get(url, content_type='text/csv') response.render() self.assertEqual(response.status_code, 200) self.assertEqual(response.accepted_media_type, 'text/csv') self.assertIsInstance(response.accepted_renderer, CSVRenderer) def test_convert_units_success(self): """Test unit conversion succeeds.""" converter = UnitConverter() to_unit = 'byte' expected_unit = f'{to_unit}-Mo' report_total = self.report.get('total', {}).get('value') result = _convert_units(converter, self.report, to_unit) result_unit = result.get('total', {}).get('units') result_total = result.get('total', {}).get('value') self.assertEqual(expected_unit, result_unit) self.assertEqual(report_total * 1E9, result_total) def test_convert_units_list(self): """Test that the list check is hit.""" converter = UnitConverter() to_unit = 'byte' expected_unit = f'{to_unit}-Mo' report_total = self.report.get('total', {}).get('value') report = [self.report] result = _convert_units(converter, report, to_unit) result_unit = result[0].get('total', {}).get('units') result_total = result[0].get('total', {}).get('value') self.assertEqual(expected_unit, result_unit) self.assertEqual(report_total * 1E9, result_total) def test_convert_units_total_not_dict(self): """Test that the total not dict block is hit.""" converter = UnitConverter() to_unit = 'byte' expected_unit = f'{to_unit}-Mo' report = self.report['data'][0]['accounts'][0]['values'][0] report_total = report.get('total') result = _convert_units(converter, report, to_unit) result_unit = result.get('units') result_total = result.get('total') self.assertEqual(expected_unit, result_unit) self.assertEqual(report_total * 1E9, result_total) @patch('api.report.view.ReportQueryHandler') def test_generic_report_with_units_success(self, mock_handler): """Test unit conversion succeeds in generic report.""" mock_handler.return_value.execute_query.return_value = self.report params = { 'group_by[account]': '*', 'filter[resolution]': 'monthly', 'filter[time_scope_value]': '-1', 'filter[time_scope_units]': 'month', 'units': 'byte' } user = User.objects.filter( username=self.customer_data[0]['owner']['username'] ).first() django_request = HttpRequest() qd = QueryDict(mutable=True) qd.update(params) django_request.GET = qd request = Request(django_request) request.user = user response = _generic_report( request, 'usage_amount', 'cost_entry_pricing__unit' ) self.assertIsInstance(response, Response) @patch('api.report.view.ReportQueryHandler') def test_generic_report_with_units_fails_well(self, mock_handler): """Test that validation error is thrown for bad unit conversion.""" mock_handler.return_value.execute_query.return_value = self.report # The 'bad' unit here is that the report is in GB-Mo, and can't # convert to seconds params = { 'group_by[account]': '*', 'filter[resolution]': 'monthly', 'filter[time_scope_value]': '-1', 'filter[time_scope_units]': 'month', 'units': 'second' } user = User.objects.filter( username=self.customer_data[0]['owner']['username'] ).first() django_request = HttpRequest() qd = QueryDict(mutable=True) qd.update(params) django_request.GET = qd request = Request(django_request) request.user = user with self.assertRaises(ValidationError): _generic_report(request, 'usage_amount', 'cost_entry_pricing__unit') def test_find_unit_list(self): """Test that the correct unit is returned.""" expected_unit = 'Hrs' data = [ {'date': '2018-07-22', 'units': '', 'instance_type': 't2.micro', 'total': 30.0, 'count': 0}, {'date': '2018-07-22', 'units': expected_unit, 'instance_type': 't2.small', 'total': 17.0, 'count': 0}, {'date': '2018-07-22', 'units': expected_unit, 'instance_type': 't2.micro', 'total': 1.0, 'count': 0} ] result_unit = _find_unit()(data) self.assertEqual(expected_unit, result_unit) def test_find_unit_dict(self): """Test that the correct unit is returned for a dictionary.""" data = {'date': '2018-07-22', 'units': '', 'instance_type': 't2.micro', 'total': 30.0, 'count': 0}, result_unit = _find_unit()(data) self.assertIsNone(result_unit) def test_fill_in_missing_units_list(self): """Test that missing units are filled in.""" expected_unit = 'Hrs' data = [ {'date': '2018-07-22', 'units': '', 'instance_type': 't2.micro', 'total': 30.0, 'count': 0}, {'date': '2018-07-22', 'units': expected_unit, 'instance_type': 't2.small', 'total': 17.0, 'count': 0}, {'date': '2018-07-22', 'units': expected_unit, 'instance_type': 't2.micro', 'total': 1.0, 'count': 0} ] unit = _find_unit()(data) result = _fill_in_missing_units(unit)(data) for entry in result: self.assertEqual(entry.get('units'), expected_unit) def test_fill_in_missing_units_dict(self): """Test that missing units are filled in for a dictionary.""" expected_unit = 'Hrs' data = {'date': '2018-07-22', 'units': '', 'instance_type': 't2.micro', 'total': 30.0, 'count': 0} result = _fill_in_missing_units(expected_unit)(data) self.assertEqual(result.get('units'), expected_unit)