diff --git a/.github/workflows/deploy_tre.yml b/.github/workflows/deploy_tre.yml index bddea6979f..a630c99905 100644 --- a/.github/workflows/deploy_tre.yml +++ b/.github/workflows/deploy_tre.yml @@ -36,7 +36,7 @@ jobs: ${{ (github.event_name == 'push' && 'extended or extended_aad') || 'extended or extended_aad or shared_services or airlock' }} environmentName: ${{ github.event.inputs.environment || 'CICD' }} - E2E_TESTS_NUMBER_PROCESSES: 1 + E2E_TESTS_NUMBER_PROCESSES: 3 DEVCONTAINER_TAG: 'latest' secrets: AAD_TENANT_ID: ${{ secrets.AAD_TENANT_ID }} diff --git a/.github/workflows/pr_comment_bot.yml b/.github/workflows/pr_comment_bot.yml index cfc14dc739..6e0d034ae6 100644 --- a/.github/workflows/pr_comment_bot.yml +++ b/.github/workflows/pr_comment_bot.yml @@ -164,7 +164,7 @@ jobs: (needs.pr_comment.outputs.command == 'run-tests-shared-services' && 'shared_services') || (needs.pr_comment.outputs.command == 'run-tests' && '') }} environmentName: CICD - E2E_TESTS_NUMBER_PROCESSES: 1 + E2E_TESTS_NUMBER_PROCESSES: 3 DEVCONTAINER_TAG: ${{ needs.pr_comment.outputs.prRefId }} secrets: AAD_TENANT_ID: ${{ secrets.AAD_TENANT_ID }} diff --git a/Makefile b/Makefile index 4c0b32bafa..b890ff0fbb 100644 --- a/Makefile +++ b/Makefile @@ -345,8 +345,12 @@ test-e2e-extended-aad: ## 🧪 Run E2E extended AAD tests $(call target_title, "Running E2E extended AAD tests") && \ $(MAKE) test-e2e-custom SELECTOR=extended_aad -test-e2e-shared-services: ## 🧪 Run E2E shared service tests - $(call target_title, "Running E2E shared service tests") && \ +test-e2e-workspace-services: ## 🧪 Run E2E workspace services tests + $(call target_title, "Running E2E workspace services tests") && \ + $(MAKE) test-e2e-custom SELECTOR=workspace_services + +test-e2e-shared-services: ## 🧪 Run E2E shared services tests + $(call target_title, "Running E2E shared services tests") && \ $(MAKE) test-e2e-custom SELECTOR=shared_services test-e2e-custom: ## 🧪 Run E2E tests with custom selector (SELECTOR=) diff --git a/api_app/_version.py b/api_app/_version.py index 1a95d56216..8261536c68 100644 --- a/api_app/_version.py +++ b/api_app/_version.py @@ -1 +1 @@ -__version__ = "0.19.3" +__version__ = "0.19.4" diff --git a/api_app/api/routes/workspaces.py b/api_app/api/routes/workspaces.py index e1d049c3f0..a3513eabe8 100644 --- a/api_app/api/routes/workspaces.py +++ b/api_app/api/routes/workspaces.py @@ -1,4 +1,5 @@ import asyncio +import time from fastapi import APIRouter, Depends, HTTPException, Header, status, Request, Response @@ -267,12 +268,25 @@ async def create_workspace_service(response: Response, workspace_service_input: workspace_patch = ResourcePatch() workspace_patch.properties = {"address_spaces": workspace.properties["address_spaces"] + [workspace_service.properties["address_space"]]} # IP address allocation is managed by the API. Ideally this request would happen as a result of the workspace - # service deployment via the reosurce processor. there is no such functionality so the database is being + # service deployment via the resource processor. there is no such functionality so the database is being # updated directly, and an "update" on the workspace is called by the workspace service pipeline. - try: - await workspace_repo.patch_workspace(workspace, workspace_patch, workspace.etag, resource_template_repo, resource_history_repo, user, False) - except CosmosAccessConditionFailedError: - raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=strings.ETAG_CONFLICT) + MAX_RETRIES = 3 + RETRY_DELAY = 1 + + retries = 0 + while retries < MAX_RETRIES: + try: + await workspace_repo.patch_workspace(workspace, workspace_patch, workspace.etag, resource_template_repo, resource_history_repo, user, False) + break + except CosmosAccessConditionFailedError: + workspace = await workspace_repo.get_workspace(workspace.id) + workspace.etag = workspace.etag.strip('"') + workspace_patch = ResourcePatch() + workspace_patch.properties = {"address_spaces": workspace.properties["address_spaces"] + [workspace_service.properties["address_space"]]} + retries += 1 + if retries == MAX_RETRIES: + raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=strings.ETAG_CONFLICT) + time.sleep(RETRY_DELAY) operation = await save_and_deploy_resource( resource=workspace_service, diff --git a/e2e_tests/resources/strings.py b/e2e_tests/resources/strings.py index 8e690aa6a5..724c69f3fd 100644 --- a/e2e_tests/resources/strings.py +++ b/e2e_tests/resources/strings.py @@ -14,10 +14,13 @@ AIRLOCK_IMPORT_REVIEW_WORKSPACE = "tre-workspace-airlock-import-review" AZUREML_SERVICE = "tre-service-azureml" +DATABRICKS_SERVICE = "tre-service-databricks" GUACAMOLE_SERVICE = "tre-service-guacamole" GITEA_SERVICE = "tre-workspace-service-gitea" -MLFLOW_SERVICE = "tre-service-mlflow" +GUACAMOLE_SERVICE = "tre-service-guacamole" +HEALTH_SERVICE = "tre-workspace-service-health" MYSQL_SERVICE = "tre-workspace-service-mysql" +OHDSI_SERVICE = "tre-workspace-service-ohdsi" HEALTH_SERVICE = "tre-workspace-service-health" AZURESQL_SERVICE = "tre-workspace-service-azuresql" OPENAI_SERVICE = "tre-workspace-service-openai" diff --git a/e2e_tests/test_workspace_services.py b/e2e_tests/test_workspace_services.py index cd48910817..21ab0ed2b6 100644 --- a/e2e_tests/test_workspace_services.py +++ b/e2e_tests/test_workspace_services.py @@ -10,7 +10,7 @@ workspace_services = [ strings.AZUREML_SERVICE, strings.GITEA_SERVICE, - strings.MLFLOW_SERVICE, + # strings.OHDSI_SERVICE, strings.MYSQL_SERVICE, strings.HEALTH_SERVICE, strings.AZURESQL_SERVICE, @@ -64,11 +64,12 @@ async def ping_guacamole_workspace_service(workspace_service_path, access_token, await check_aad_auth_redirect(endpoint, verify) +@pytest.mark.extended @pytest.mark.workspace_services @pytest.mark.timeout(45 * 60) @pytest.mark.parametrize("template_name", workspace_services) -async def test_install_workspace_service(template_name, verify, setup_test_workspace) -> None: - workspace_path, workspace_id = setup_test_workspace +async def test_install_workspace_service(template_name, verify, setup_test_aad_workspace) -> None: + workspace_path, workspace_id = setup_test_aad_workspace workspace_owner_token = await get_workspace_owner_token(workspace_id, verify) service_payload = {