def test_initialize_session_msi_authentication_error(self, mock_log, mock_cred): with self.assertRaises(SystemExit): mock_cred.side_effect = HTTPError() with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() s.get_subscription_id() mock_log.assert_called_once_with('Failed to authenticate with MSI')
def test_initialize_session_cli_error(self, mock_log, mock_cli_creds): with self.assertRaises(SystemExit): mock_cli_creds.side_effect = CLIError("Bad CLI credentials") with patch.dict(os.environ, { constants.ENV_TENANT_ID: 'tenant', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, }, clear=True): s = Session() s.get_subscription_id() mock_log.assert_called_once_with('Failed to authenticate with CLI credentials. ' 'Bad CLI credentials')
def test_initialize_session_auth_file(self): s = Session(authorization_file=self.authorization_file) self.assertIs(type(s.get_credentials()._credential), ClientSecretCredential) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID) self.assertEqual(s.get_tenant_id(), 'tenant')
def test_initialize_session_kv_authentication_error(self, mock_log, mock_get_kv_secret): with self.assertRaises(SystemExit): mock_get_kv_secret.side_effect = HTTPError() with patch.dict(os.environ, { constants.ENV_TENANT_ID: 'tenant', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, constants.ENV_KEYVAULT_CLIENT_ID: 'kv_client', constants.ENV_KEYVAULT_SECRET_ID: 'kv_secret' }, clear=True): s = Session() s.get_subscription_id() mock_log.assert_called_once_with( 'Failed to retrieve SP credential from ' 'Key Vault with client id: kv_client')
def test_initialize_session_auth_file(self): with patch('azure.common.credentials.ServicePrincipalCredentials.__init__', autospec=True, return_value=None): s = Session(authorization_file=self.authorization_file) self.assertIs(type(s.get_credentials()), ServicePrincipalCredentials) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID) self.assertEqual(s.get_tenant_id(), 'tenant')
def test_initialize_session_msi_authentication_error( self, mock_log, mock_cred): with self.assertRaises(SystemExit): mock_cred.side_effect = HTTPError() with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() s.get_subscription_id() mock_log.assert_called_once_with( 'Azure Authentication Failure\n' 'Error: Could not authenticate using managed service identity (system identity)' )
def test_initialize_session_cli(self, mock_run): mock_run.return_value = \ f'{{"id":"{DEFAULT_SUBSCRIPTION_ID}", "tenantId":"{DEFAULT_TENANT_ID}"}}' with patch.dict(os.environ, {}, clear=True): s = Session() self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID) self.assertEqual(s.get_tenant_id(), DEFAULT_TENANT_ID)
def test_initialize_session_auth_file_no_sub(self): s = Session(subscription_id=CUSTOM_SUBSCRIPTION_ID, authorization_file=self.authorization_file_no_sub) self.assertIs(type(s.get_credentials()._credential), ClientSecretCredential) self.assertEqual(s.get_subscription_id(), CUSTOM_SUBSCRIPTION_ID) # will vary between recorded/live auth options but useful to ensure # we ended up with one of the valid values self.assertTrue(s.get_tenant_id() in [DEFAULT_TENANT_ID, 'tenant'])
def test_initialize_msi_auth_system(self): with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() self.assertIsInstance(s.get_credentials()._credential, ManagedIdentityCredential) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID)
def test_initialize_session_token(self, _1): with patch.dict(os.environ, { constants.ENV_ACCESS_TOKEN: 'token', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), BasicTokenAuthentication) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID)
class AzureEventsTest(BaseTest): def setUp(self): super(AzureEventsTest, self).setUp() self.session = Session() def test_get_returns_event_dict(self): event_dic = AzureEvents.get('VmWrite') self.assertEqual(event_dic['event'], 'write') self.assertEqual(event_dic['resource_provider'], 'Microsoft.Compute/virtualMachines') def test_get_event_operations_one_string(self): event_string = 'VmWrite' event_operations = AzureEvents.get_event_operations([event_string]) self.assertEqual(len(event_operations), 1) self.assertEqual(event_operations[0], 'Microsoft.Compute/virtualMachines/write') def test_get_event_operations_one_event_object(self): event_dictionary = { 'resourceProvider': 'Microsoft.Compute/virtualMachines', 'event': 'write' } event_operations = AzureEvents.get_event_operations([event_dictionary]) self.assertEqual(len(event_operations), 1) self.assertEqual(event_operations[0], 'Microsoft.Compute/virtualMachines/write') def test_get_event_operations_both_event_types(self): event_string = 'AppServicePlanWrite' event_dict = { 'resourceProvider': 'Microsoft.Compute/virtualMachines', 'event': 'write' } event_operations = AzureEvents.get_event_operations( [event_string, event_dict]) self.assertEqual(len(event_operations), 2) self.assertTrue( 'Microsoft.Compute/virtualMachines/write' in event_operations) self.assertTrue('Microsoft.Web/serverFarms/write' in event_operations) @arm_template('storage.json') def test_create_azure_event_subscription(self): account = self.setup_account() queue_name = 'cctestevensub' StorageUtilities.create_queue_from_storage_account( account, queue_name, self.session) sub_destination = StorageQueueEventSubscriptionDestination( resource_id=account.id, queue_name=queue_name) sub_name = 'custodiantestsubscription' event_subscription = AzureEventSubscription.create( sub_destination, sub_name, self.session.get_subscription_id()) self.assertEqual(event_subscription.name, sub_name) self.assertEqual(event_subscription.destination.endpoint_type, 'StorageQueue')
def test_initialize_session_authentication_error(self, mock_log, mock_cred): with self.assertRaises(SystemExit): adal_err = AdalError("test") adal_err.error_response = {'error': 'test'} err = AuthenticationError('test') err.inner_exception = adal_err mock_cred.side_effect = err with patch.dict(os.environ, { constants.ENV_TENANT_ID: DEFAULT_TENANT_ID, constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, constants.ENV_CLIENT_ID: 'client', constants.ENV_CLIENT_SECRET: 'secret' }, clear=True): s = Session() s.get_subscription_id() mock_log.assert_called_once_with( 'Failed to authenticate with service principal.\nMessage: {\n "error": "test"\n}')
def test_initialize_session_token(self): with patch.dict(os.environ, { constants.ENV_ACCESS_TOKEN: 'token', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() self.assertIsNone(s.get_credentials()._credential) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID) self.assertEqual(s.get_credentials().get_token(), AccessToken('token', 0))
class AzureEventsTest(BaseTest): def setUp(self): super(AzureEventsTest, self).setUp() self.session = Session() def test_get_returns_event_dict(self): event_dic = AzureEvents.get('VmWrite') self.assertEqual(event_dic['event'], 'write') self.assertEqual(event_dic['resource_provider'], 'Microsoft.Compute/virtualMachines') def test_get_event_operations_one_string(self): event_string = 'VmWrite' event_operations = AzureEvents.get_event_operations([event_string]) self.assertEqual(len(event_operations), 1) self.assertEqual(event_operations[0], 'Microsoft.Compute/virtualMachines/write') def test_get_event_operations_one_event_object(self): event_dictionary = { 'resourceProvider': 'Microsoft.Compute/virtualMachines', 'event': 'write' } event_operations = AzureEvents.get_event_operations([event_dictionary]) self.assertEqual(len(event_operations), 1) self.assertEqual(event_operations[0], 'Microsoft.Compute/virtualMachines/write') def test_get_event_operations_both_event_types(self): event_string = 'AppServicePlanWrite' event_dict = { 'resourceProvider': 'Microsoft.Compute/virtualMachines', 'event': 'write' } event_operations = AzureEvents.get_event_operations( [event_string, event_dict]) self.assertEqual(len(event_operations), 2) self.assertTrue( 'Microsoft.Compute/virtualMachines/write' in event_operations) self.assertTrue('Microsoft.Web/serverFarms/write' in event_operations) @patch('azure.mgmt.eventgrid.operations.event_subscriptions_operations.' 'EventSubscriptionsOperations.create_or_update') def test_create_azure_event_subscription(self, create_mock): sub_destination = StorageQueueEventSubscriptionDestination( resource_id="cctestid", queue_name="cctestevensub") sub_name = 'custodiantestsubscription' sub_id = self.session.get_subscription_id() AzureEventSubscription.create(sub_destination, sub_name, sub_id) args = create_mock.mock_calls[0].args self.assertTrue(sub_id in args[0]) self.assertEqual(sub_name, args[1]) self.assertEqual(sub_destination, args[2].destination)
def test_initialize_session_token(self): with patch.dict(os.environ, { constants.ENV_ACCESS_TOKEN: 'token', constants.ENV_SUB_ID: 'ea42f556-5106-4743-99b0-c129bfa71a47' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), BasicTokenAuthentication) self.assertEqual(s.get_subscription_id(), 'ea42f556-5106-4743-99b0-c129bfa71a47')
def test_initialize_session_token(self): with patch.dict(os.environ, { constants.ENV_ACCESS_TOKEN: 'token', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), BasicTokenAuthentication) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID)
def test_initialize_msi_auth_system(self): with patch('msrestazure.azure_active_directory.MSIAuthentication.__init__', autospec=True, return_value=None): with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), MSIAuthentication) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID)
def test_initialize_msi_auth_system(self): with patch('msrestazure.azure_active_directory.MSIAuthentication.__init__', autospec=True, return_value=None): with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: 'ea42f556-5106-4743-99b0-c129bfa71a47' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), MSIAuthentication) self.assertEqual(s.get_subscription_id(), 'ea42f556-5106-4743-99b0-c129bfa71a47')
def test_initialize_session_auth_file_no_sub(self): with patch('azure.common.credentials.ServicePrincipalCredentials.__init__', autospec=True, return_value=None): s = Session(subscription_id=CUSTOM_SUBSCRIPTION_ID, authorization_file=self.authorization_file_no_sub) self.assertIs(type(s.get_credentials()), ServicePrincipalCredentials) self.assertEqual(s.get_subscription_id(), CUSTOM_SUBSCRIPTION_ID) # will vary between recorded/live auth options but useful to ensure # we ended up with one of the valid values self.assertTrue(s.get_tenant_id() in [DEFAULT_TENANT_ID, 'tenant'])
def test_initialize_session_kv_authentication_error( self, mock_log, mock_get_kv_secret): reload(sys.modules['c7n_azure.session']) with self.assertRaises(SystemExit): mock_get_kv_secret.side_effect = HTTPError() with patch.dict(os.environ, { constants.ENV_TENANT_ID: 'tenant', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, constants.ENV_KEYVAULT_CLIENT_ID: 'kv_client', constants.ENV_KEYVAULT_SECRET_ID: 'kv_secret' }, clear=True): s = Session() s.get_subscription_id() mock_log.assert_called_once_with( 'Azure Authentication Failure\nError: ' 'Cannot retrieve SP credentials from the Key Vault ' '(KV uses MSI to access) with client id: kv_client')
def test_initialize_session_principal(self): with patch.dict(os.environ, { constants.ENV_TENANT_ID: DEFAULT_TENANT_ID, constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, constants.ENV_CLIENT_ID: 'client', constants.ENV_CLIENT_SECRET: 'secret' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()._credential), ClientSecretCredential) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID) self.assertEqual(s.get_tenant_id(), DEFAULT_TENANT_ID)
def test_initialize_session_token(self): with patch.dict( os.environ, { constants.ENV_ACCESS_TOKEN: 'token', constants.ENV_SUB_ID: 'ea42f556-5106-4743-99b0-c129bfa71a47' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), BasicTokenAuthentication) self.assertEqual(s.get_subscription_id(), 'ea42f556-5106-4743-99b0-c129bfa71a47')
def test_initialize_msi_auth_user(self): with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, constants.ENV_CLIENT_ID: 'client' }, clear=True): s = Session() self.assertIsInstance(s.get_credentials()._credential, ManagedIdentityCredential) # self.assertEqual( # s.get_credentials()._credential._credential._identity_config["client_id"], # 'client') self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID)
def test_initialize_session_principal(self): with patch('azure.common.credentials.ServicePrincipalCredentials.__init__', autospec=True, return_value=None): with patch.dict(os.environ, { constants.ENV_TENANT_ID: DEFAULT_TENANT_ID, constants.ENV_SUB_ID: DEFAULT_SUBSCRIPTION_ID, constants.ENV_CLIENT_ID: 'client', constants.ENV_CLIENT_SECRET: 'secret' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), ServicePrincipalCredentials) self.assertEqual(s.get_subscription_id(), DEFAULT_SUBSCRIPTION_ID) self.assertEqual(s.get_tenant_id(), DEFAULT_TENANT_ID)
def test_initialize_session_principal(self): with patch('azure.common.credentials.ServicePrincipalCredentials.__init__', autospec=True, return_value=None): with patch.dict(os.environ, { constants.ENV_TENANT_ID: 'tenant', constants.ENV_SUB_ID: 'ea42f556-5106-4743-99b0-c129bfa71a47', constants.ENV_CLIENT_ID: 'client', constants.ENV_CLIENT_SECRET: 'secret' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), ServicePrincipalCredentials) self.assertEqual(s.get_subscription_id(), 'ea42f556-5106-4743-99b0-c129bfa71a47')
def test_initialize_msi_auth_user(self): with patch( 'msrestazure.azure_active_directory.MSIAuthentication.__init__', autospec=True, return_value=None): with patch.dict(os.environ, { constants.ENV_USE_MSI: 'true', constants.ENV_SUB_ID: 'ea42f556-5106-4743-99b0-c129bfa71a47', constants.ENV_CLIENT_ID: 'client' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), MSIAuthentication) self.assertEqual(s.get_subscription_id(), 'ea42f556-5106-4743-99b0-c129bfa71a47')
def test_initialize_session_principal(self): with patch( 'azure.common.credentials.ServicePrincipalCredentials.__init__', autospec=True, return_value=None): with patch.dict(os.environ, { constants.ENV_TENANT_ID: 'tenant', constants.ENV_SUB_ID: 'ea42f556-5106-4743-99b0-c129bfa71a47', constants.ENV_CLIENT_ID: 'client', constants.ENV_CLIENT_SECRET: 'secret' }, clear=True): s = Session() self.assertIs(type(s.get_credentials()), ServicePrincipalCredentials) self.assertEqual(s.get_subscription_id(), 'ea42f556-5106-4743-99b0-c129bfa71a47')
class AzureEventSubscriptionsTest(BaseTest): event_sub_name = 'custodiantestsubscription' def setUp(self): super(AzureEventSubscriptionsTest, self).setUp() self.session = Session() account = self.setup_account() queue_name = 'cctesteventsub' StorageUtilities.create_queue_from_storage_account( account, queue_name, self.session) event_sub_destination = StorageQueueEventSubscriptionDestination( resource_id=account.id, queue_name=queue_name) AzureEventSubscription.create(event_sub_destination, self.event_sub_name, self.session.get_subscription_id()) def test_event_subscription_schema_validate(self): with self.sign_out_patch(): p = self.load_policy( { 'name': 'test-azure-event-subscription', 'resource': 'azure.eventsubscription', 'actions': [{ 'type': 'delete' }] }, validate=True) self.assertTrue(p) @arm_template('storage.json') def test_azure_event_subscription_policy_run(self): p = self.load_policy({ 'name': 'test-azure-event-subscriptions', 'resource': 'azure.eventsubscription', 'filters': [{ 'type': 'value', 'key': 'name', 'op': 'eq', 'value': self.event_sub_name }], }) resources = p.run() self.assertEqual(len(resources), 1) @arm_template('storage.json') def test_azure_event_subscription_delete(self): p_get = self.load_policy({ 'name': 'test-azure-event-subscriptions', 'resource': 'azure.eventsubscription', 'filters': [{ 'type': 'value', 'key': 'name', 'op': 'eq', 'value': self.event_sub_name }], }) resources_pre_delete = p_get.run() self.assertEqual(len(resources_pre_delete), 1) p_delete = self.load_policy( { 'name': 'test-azure-event-subscriptions', 'resource': 'azure.eventsubscription', 'actions': [{ 'type': 'delete' }] }, validate=True) p_delete.run() resources_post_delete = p_get.run() self.assertEqual(len(resources_post_delete), 0)
class CostFilterTest(BaseTest): def setUp(self): super(CostFilterTest, self).setUp() self.session = Session() def test_schema(self): self.assertTrue( self.load_policy( { 'name': 'test-cost-filter', 'resource': 'azure.vm', 'filters': [{ 'type': 'cost', 'timeframe': 'MonthToDate', 'op': 'eq', 'value': 1 }] }, validate=True)) self.assertTrue( self.load_policy( { 'name': 'test-cost-filter', 'resource': 'azure.resourcegroup', 'filters': [{ 'type': 'cost', 'timeframe': 7, 'op': 'eq', 'value': 1 }] }, validate=True)) def test_custom_timeframe(self): resources = [ self._get_resource('vm1', 2000), self._get_resource('vm2', 20), self._get_resource('vm3', 3000) ] f = self._get_filter( { 'timeframe': 'TheLastWeek', 'op': 'gt', 'value': 1000 }, resources) result = f.process(resources, None) usage_by_scope = f.manager.get_client.return_value.query.usage_by_scope self._verify_expected_call(usage_by_scope, 'TheLastWeek', False) self.assertEqual(len(result), 2) def test_rg(self): resources = [ self._get_resource_group('rg1', 2000), self._get_resource_group('rg2', 20), self._get_resource_group('rg3', 3000) ] f = self._get_filter({ 'timeframe': 1, 'op': 'lt', 'value': 1000 }, resources) result = f.process(resources, None) usage_by_scope = f.manager.get_client.return_value.query.usage_by_scope self._verify_expected_call(usage_by_scope, 1, True) self.assertEqual(len(result), 1) def test_child_resources(self): resources = [ self._get_resource('vm1', 0), self._get_resource('vm1/child1', 300), self._get_resource('vm1/child2', 3000) ] f = self._get_filter( { 'timeframe': 'TheLastWeek', 'op': 'eq', 'value': 3300 }, resources) result = f.process(resources, None) usage_by_scope = f.manager.get_client.return_value.query.usage_by_scope self._verify_expected_call(usage_by_scope, 'TheLastWeek', False) self.assertEqual(len(result), 1) def _verify_expected_call(self, mock, timeframe, resource_group): subscription_id = self.session.get_subscription_id() mock.assert_called_once() definition = mock.call_args[0][1] if isinstance(timeframe, int): today = utcnow().replace(hour=0, minute=0, second=0, microsecond=0) self.assertEqual(definition.timeframe, 'Custom') self.assertEqual(definition.time_period.to, today) self.assertEqual(definition.time_period.from_property, today - datetime.timedelta(days=timeframe)) else: self.assertEqual(definition.timeframe, timeframe) self.assertEqual(len(definition.dataset.grouping), 1) self.assertEqual(definition.dataset.grouping[0].type, 'Dimension') self.assertEqual( definition.dataset.grouping[0].name, 'ResourceGroupName' if resource_group else 'ResourceId') self.assertEqual(definition.dataset.aggregation['totalCost'].name, 'PreTaxCost') if not resource_group: self.assertEqual(definition.dataset.filter.dimension.name, 'ResourceType') self.assertEqual(definition.dataset.filter.dimension.operator, 'In') self.assertEqual(definition.dataset.filter.dimension.values, ['Microsoft.Compute/virtualMachines']) mock.assert_called_once_with('/subscriptions/' + subscription_id, definition) def _get_filter(self, data, resources): manager = Mock() manager.get_session.return_value.get_subscription_id.return_value = \ self.session.get_subscription_id() manager.get_client.return_value.query.usage_by_scope.return_value = \ self._get_costs(resources) if 'Microsoft.Compute/virtualMachines' in resources[0]['id']: manager.resource_type.resource_type = 'Microsoft.Compute/virtualMachines' else: manager.type = 'resourcegroup' manager.resource_type.resource_type = 'Microsoft.Resources/subscriptions/resourceGroups' return CostFilter(data=data, manager=manager) def _get_resource(self, name, cost): return { 'id': '/subscriptions/ea42f556-5106-4743-99b0-c129bfa71a47/resourceGroups/' 'TEST_VM/providers/Microsoft.Compute/virtualMachines/{0}'.format( name), '_cost': cost } def _get_resource_group(self, name, cost): return { 'id': '/subscriptions/ea42f556-5106-4743-99b0-c129bfa71a47/resourceGroups/' '{0}'.format(name), '_cost': cost } def _get_costs(self, resources): rows = [[r['id'], r['_cost'], 'USD'] for r in resources] cost = { 'columns': [ Column('ResourceId'), Column('PreTaxCost'), Column('Currency'), ], 'rows': rows } cost = namedtuple("Cost", cost.keys())(*cost.values()) return [cost]
class CostFilterTest(BaseTest): def setUp(self): super(CostFilterTest, self).setUp() self.session = Session() def test_cost_filter_schema_validate_named_timeframe(self): p = self.load_policy( { 'name': 'test-cost-filter', 'resource': 'azure.armresource', 'filters': [{ 'type': 'cost', 'timeframe': 'MonthToDate', 'op': 'eq', 'value': 1 }] }, validate=True) self.assertTrue(p) def test_cost_filter_schema_validate_timeframe_in_days(self): p = self.load_policy( { 'name': 'test-cost-filter', 'resource': 'azure.armresource', 'filters': [{ 'type': 'cost', 'timeframe': 7, 'op': 'eq', 'value': 1 }] }, validate=True) self.assertTrue(p) # run ./templates/provision.sh vm sqlserver to deploy required resource. def test_exact_cost(self): p = self.load_policy({ 'name': 'test-cost_filter', # 'resource': 'azure.vm', 'resource': 'azure.vm', 'filters': [{ 'type': 'cost', 'timeframe': 'MonthToDate', 'op': 'ge', 'value': 0 }] }) resources = p.run() self.assertTrue(len(resources) > 0) for resource in resources: self.assertEqual(resource['c7n:cost']['Currency'], 'USD') self.assertTrue(resource['c7n:cost']['PreTaxCost'] >= 0) def test_timeframe_days(self): p = self.load_policy({ 'name': 'test-cost_filter', # 'resource': 'azure.vm', 'resource': 'azure.vm', 'filters': [{ 'type': 'cost', 'timeframe': 7, 'op': 'ge', 'value': 0 }] }) resources = p.run() self.assertTrue(len(resources) > 0) for resource in resources: self.assertEqual(resource['c7n:cost']['Currency'], 'USD') self.assertTrue(resource['c7n:cost']['PreTaxCost'] >= 0) def test_cost_greater_than(self): p = self.load_policy({ 'name': 'test-cost_filter', 'resource': 'azure.armresource', 'filters': [{ 'type': 'cost', 'timeframe': 'TheLastWeek', 'op': 'gt', 'value': 1000 }] }) id1 = '/subscriptions/s1/resourceGroups/test_rg1/id1' id2 = '/subscriptions/s1/resourceGroups/test_rg1/id2' id3 = '/subscriptions/s1/resourceGroups/test_rg2/id3' id4 = '/subscriptions/s1/resourceGroups/test_rg2/id4' resources = [{'id': id1}, {'id': id2}, {'id': id3}, {'id': id4}] cost = self._make_cost([ [id1, 2000], [id2, 20], [id3, 3000], [id4, 40], ]) with patch.object(DescribeSource, 'get_resources', return_value=resources): with patch.object( azure.mgmt.costmanagement.operations.QueryOperations, 'usage_by_scope', return_value=cost) as mock: resources = p.run() mock.assert_has_calls( [self._make_expected_call(mock, 'TheLastWeek')]) self.assertEqual(mock.call_count, 1) self.assertEqual(len(resources), 2) self.assertEqual(resources[0]['id'], id1) self.assertEqual(resources[1]['id'], id3) def test_cost_two_filters(self): p = self.load_policy({ 'name': 'test-cost_filter', 'resource': 'azure.armresource', 'filters': [{ 'type': 'cost', 'timeframe': 'TheLastWeek', 'op': 'eq', 'value': 100 }, { 'type': 'cost', 'timeframe': 'TheLastMonth', 'op': 'eq', 'value': 1000 }] }) id1 = '/subscriptions/s1/resourceGroups/test_rg1/id1' id2 = '/subscriptions/s1/resourceGroups/test_rg1/id2' id3 = '/subscriptions/s1/resourceGroups/test_rg2/id3' id4 = '/subscriptions/s1/resourceGroups/test_rg2/id4' resources = [{'id': id1}, {'id': id2}, {'id': id3}, {'id': id4}] week_cost = self._make_cost([ [id1, 100], [id2, 100], [id3, 100], [id4, 10], ]) month_cost = self._make_cost([ [id1, 2000], [id2, 1000], [id3, 1000], [id4, 1000], ]) with patch.object(DescribeSource, 'get_resources', return_value=resources): with patch.object( azure.mgmt.costmanagement.operations.QueryOperations, 'usage_by_scope') as mock: mock.side_effect = [week_cost, month_cost] resources = p.run() mock.assert_has_calls([ self._make_expected_call(mock, 'TheLastWeek'), self._make_expected_call(mock, 'TheLastMonth') ]) self.assertEqual(mock.call_count, 2) self.assertEqual(len(resources), 2) self.assertEqual(resources[0]['id'], id2) self.assertEqual(resources[1]['id'], id3) def _make_expected_call(self, mock, timeframe): grouping = [QueryGrouping(type='Dimension', name='ResourceId')] aggregation = {'totalCost': QueryAggregation(name='PreTaxCost')} dataset = QueryDataset(grouping=grouping, aggregation=aggregation) definition = QueryDefinition(timeframe=timeframe, dataset=dataset) subscription_id = self.session.get_subscription_id() return call('/subscriptions/' + subscription_id, definition) def _make_cost(self, rows): cost = { 'columns': [ Column('ResourceId'), Column('PreTaxCost'), Column('Currency'), ], 'rows': rows } cost = namedtuple("Cost", cost.keys())(*cost.values()) return [cost]