class SourceStatus: """Source Status.""" def __init__(self, request, source_id): """Initialize source id.""" self.request = request self.user = request.user self.source_id = source_id self.source = Sources.objects.get(source_id=source_id) self.sources_client = SourcesHTTPClient(self.source.auth_header, source_id=source_id) @property def sources_response(self): return self.sources_client.build_source_status(self.status()) def _set_provider_active_status(self, active_status): """Set provider active status.""" if self.source.koku_uuid: try: provider = Provider.objects.get(uuid=self.source.koku_uuid) provider.active = active_status provider.save() except Provider.DoesNotExist: LOG.info( f"No provider found for Source ID: {self.source.source_id}" ) def determine_status(self, provider_type, source_authentication, source_billing_source): """Check cloud configuration status.""" interface = ProviderAccessor(provider_type) error_obj = None try: interface.cost_usage_source_ready(source_authentication, source_billing_source) self._set_provider_active_status(True) except ValidationError as validation_error: self._set_provider_active_status(False) error_obj = validation_error return error_obj def status(self): """Find the source's availability status.""" source_billing_source = self.source.billing_source.get( "data_source") or {} source_authentication = self.source.authentication.get( "credentials") or {} provider_type = self.source.source_type return self.determine_status(provider_type, source_authentication, source_billing_source) def push_status(self): """Push status_msg to platform sources.""" try: status_obj = self.status() self.sources_client.set_source_status(status_obj) except SourcesHTTPClientError as error: err_msg = "Unable to push source status. Reason: {}".format( str(error)) LOG.warning(err_msg)
class SourceStatus: """Source Status.""" def __init__(self, request, source_id): """Initialize source id.""" self.request = request self.user = request.user self.source_id = source_id self.source = Sources.objects.get(source_id=source_id) self.sources_client = SourcesHTTPClient(self.source.auth_header, source_id=source_id) @property def sources_response(self): return self.sources_client.build_source_status(self.status()) def determine_status(self, provider, source_authentication, source_billing_source): """Check cloud configuration status.""" interface = ProviderAccessor(provider) error_obj = None try: interface.cost_usage_source_ready(source_authentication, source_billing_source) except ValidationError as validation_error: error_obj = validation_error return error_obj def status(self): """Find the source's availability status.""" # Get the source billing_source, whether it's named bucket if self.source.billing_source.get("bucket"): source_billing_source = self.source.billing_source.get("bucket") elif self.source.billing_source.get("data_source"): source_billing_source = self.source.billing_source.get("data_source") else: source_billing_source = {} # Get the source authentication if self.source.authentication.get("resource_name"): source_authentication = self.source.authentication.get("resource_name") elif self.source.authentication.get("credentials"): source_authentication = self.source.authentication.get("credentials") else: source_authentication = {} provider = self.source.source_type status_obj = self.determine_status(provider, source_authentication, source_billing_source) return status_obj def push_status(self): """Push status_msg to platform sources.""" try: status_obj = self.status() self.sources_client.set_source_status(status_obj) except SourcesHTTPClientError as error: err_msg = "Unable to push source status. Reason: {}".format(str(error)) LOG.warning(err_msg)
def test_build_source_status(self): """Test build source status.""" table = [ {"error": None, "expected": {"availability_status": "available", "availability_status_error": ""}}, { "error": "my-error", "expected": {"availability_status": "unavailable", "availability_status_error": "my-error"}, }, ] client = SourcesHTTPClient(auth_header=Config.SOURCES_FAKE_HEADER) for test in table: with self.subTest(test=test): result = client.build_source_status(test.get("error")) self.assertDictEqual(result, test.get("expected"))
class SourceStatus: """Source Status.""" def __init__(self, source_id): """Initialize source id.""" self.source_id = source_id self.source = Sources.objects.get(source_id=source_id) if not source_settings_complete( self.source) or self.source.pending_delete: raise ObjectDoesNotExist( f"Source ID: {self.source_id} not ready for status") self.sources_client = SourcesHTTPClient(self.source.auth_header, source_id=source_id) @property def sources_response(self): return self.sources_client.build_source_status(self.status()) def _set_provider_active_status(self, active_status): """Set provider active status.""" if self.source.koku_uuid: try: provider = Provider.objects.get(uuid=self.source.koku_uuid) provider.active = active_status provider.save() except Provider.DoesNotExist: LOG.info( f"No provider found for Source ID: {self.source.source_id}" ) def determine_status(self, provider_type, source_authentication, source_billing_source): """Check cloud configuration status.""" interface = ProviderAccessor(provider_type) error_obj = None try: if self.source.account_id not in settings.DEMO_ACCOUNTS: interface.cost_usage_source_ready(source_authentication, source_billing_source) self._set_provider_active_status(True) except ValidationError as validation_error: self._set_provider_active_status(False) error_obj = validation_error self.source.refresh_from_db() return error_obj def status(self): """Find the source's availability status.""" source_billing_source = self.source.billing_source.get( "data_source") or {} source_authentication = self.source.authentication.get( "credentials") or {} provider_type = self.source.source_type return self.determine_status(provider_type, source_authentication, source_billing_source) @transaction.atomic def update_source_name(self): """Update source name if it is out of sync with platform.""" source_details = self.sources_client.get_source_details() if source_details.get("name") != self.source.name: self.source.name = source_details.get("name") self.source.save() builder = SourcesProviderCoordinator(self.source_id, self.source.auth_header) builder.update_account(self.source) def push_status(self): """Push status_msg to platform sources.""" try: status_obj = self.status() if self.source.source_type in (Provider.PROVIDER_GCP, Provider.PROVIDER_GCP_LOCAL): builder = SourcesProviderCoordinator(self.source.source_id, self.source.auth_header) if not status_obj: if self.source.koku_uuid: builder.update_account(self.source) elif self.source.billing_source.get("data_source", {}).get("table_id"): builder.create_account(self.source) self.sources_client.set_source_status(status_obj) self.update_source_name() LOG.info( f"Source status for Source ID: {str(self.source_id)}: Status: {str(status_obj)}" ) except SkipStatusPush as error: LOG.info( f"Platform sources status push skipped. Reason: {str(error)}") except SourcesHTTPClientError as error: err_msg = "Unable to push source status. Reason: {}".format( str(error)) LOG.warning(err_msg)