diff --git a/fixbackend/cloud_accounts/gcp_service_account_service.py b/fixbackend/cloud_accounts/gcp_service_account_service.py index f9b81a5f..21c06bf8 100644 --- a/fixbackend/cloud_accounts/gcp_service_account_service.py +++ b/fixbackend/cloud_accounts/gcp_service_account_service.py @@ -91,14 +91,18 @@ def blocking_call() -> List[Dict[str, Any]]: return await asyncio.to_thread(blocking_call) async def update_cloud_accounts( - self, projects: List[Dict[str, Any]], tenant_id: WorkspaceId, key_id: GcpServiceAccountKeyId + self, projects: List[Dict[str, Any]], tenant_id: WorkspaceId, key_id: GcpServiceAccountKeyId, only_new: bool ) -> None: for project in projects: await self.cloud_account_service.create_gcp_account( - workspace_id=tenant_id, account_id=project["projectId"], account_name=project.get("name"), key_id=key_id + workspace_id=tenant_id, + account_id=project["projectId"], + account_name=project.get("name"), + key_id=key_id, + only_new_accounts=only_new, ) - async def _import_projects_from_service_account(self, key: GcpServiceAccountKey) -> None: + async def _import_projects_from_service_account(self, key: GcpServiceAccountKey, only_new: bool = False) -> None: try: projects = await self.list_projects(key.value) except MalformedError as e: @@ -114,7 +118,7 @@ async def _import_projects_from_service_account(self, key: GcpServiceAccountKey) await self.service_account_key_repo.update_status(key.id, can_access_sa=False, error=str(e)) return None await self.service_account_key_repo.update_status(key.id, can_access_sa=True) - await self.update_cloud_accounts(projects, key.tenant_id, key.id) + await self.update_cloud_accounts(projects, key.tenant_id, key.id, only_new=only_new) async def _ping_new_service_account_keys(self) -> None: created_less_than_30_minutes_ago = await self.service_account_key_repo.list_created_after( @@ -126,10 +130,14 @@ async def _ping_new_service_account_keys(self) -> None: tg.create_task(self._import_projects_from_service_account(key)) async def _service_account_healthcheck(self) -> None: + """ + This will look for any new projects created by the users after we imported the SA keys + and import them if we don't know about them yet. + """ older_than_1_hour = await self.service_account_key_repo.list_created_before( utc() - timedelta(hours=1), only_valid_keys=True ) async with asyncio.TaskGroup() as tg: for key in older_than_1_hour: - tg.create_task(self._import_projects_from_service_account(key)) + tg.create_task(self._import_projects_from_service_account(key, only_new=True)) diff --git a/fixbackend/cloud_accounts/service.py b/fixbackend/cloud_accounts/service.py index b05999ab..1cfa86cc 100644 --- a/fixbackend/cloud_accounts/service.py +++ b/fixbackend/cloud_accounts/service.py @@ -826,6 +826,7 @@ async def create_gcp_account( account_id: CloudAccountId, key_id: GcpServiceAccountKeyId, account_name: Optional[CloudAccountName], + only_new_accounts: bool = False, ) -> CloudAccount: """Create a GCP cloud account.""" set_workspace_id(workspace_id) @@ -838,7 +839,7 @@ async def create_gcp_account( raise ResourceNotFound("Organization does not exist") if existing := await self.cloud_account_repository.get_by_account_id(workspace_id, account_id): - if isinstance(existing.state, CloudAccountStates.Configured): + if only_new_accounts or isinstance(existing.state, CloudAccountStates.Configured): log.info("GCP account already exists") return existing diff --git a/tests/fixbackend/cloud_accounts/router_test.py b/tests/fixbackend/cloud_accounts/router_test.py index 6815ffe6..05a35f76 100644 --- a/tests/fixbackend/cloud_accounts/router_test.py +++ b/tests/fixbackend/cloud_accounts/router_test.py @@ -104,6 +104,7 @@ async def create_gcp_account( account_id: CloudAccountId, key_id: GcpServiceAccountKeyId, account_name: Optional[CloudAccountName], + only_new_accounts: bool = False, ) -> CloudAccount: """Create a GCP cloud account.""" raise NotImplementedError diff --git a/tests/fixbackend/conftest.py b/tests/fixbackend/conftest.py index ed32fe98..d5c70b3c 100644 --- a/tests/fixbackend/conftest.py +++ b/tests/fixbackend/conftest.py @@ -984,7 +984,7 @@ async def list_projects(self, service_account_key: str) -> List[Dict[str, Any]]: return [{"projectId": "foo", "name": "bar"}] async def update_cloud_accounts( - self, projects: List[Dict[str, Any]], tenant_id: WorkspaceId, key_id: GcpServiceAccountKeyId + self, projects: List[Dict[str, Any]], tenant_id: WorkspaceId, key_id: GcpServiceAccountKeyId, only_new: bool ) -> None: return None