diff --git a/CHANGELOG.md b/CHANGELOG.md index d52d77954a..5ef9aa94bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ENHANCEMENTS: * API: Replace HTTP_422_UNPROCESSABLE_ENTITY response with HTTP_422_UNPROCESSABLE_CONTENT as per RFC 9110 ([#4742](https://github.com/microsoft/AzureTRE/issues/4742)) * Change Group.ReadWrite.All permission to Group.Create for AUTO_WORKSPACE_GROUP_CREATION ([#4772](https://github.com/microsoft/AzureTRE/issues/4772)) * Make workspace shared storage quota updateable ([#4314](https://github.com/microsoft/AzureTRE/issues/4314)) +* Allow numeric CIDR masks in `address_space_size` (e.g. "25") when requesting auto-assigned address spaces; accepts numeric strings and validates the mask range. ([#4733](https://github.com/microsoft/AzureTRE/issues/4733)) * Update Porter, AzureCLI, Terraform and its providers across the solution ([#4799](https://github.com/microsoft/AzureTRE/issues/4799)) BUG FIXES: diff --git a/api_app/_version.py b/api_app/_version.py index 5461be1190..4f3cae6929 100644 --- a/api_app/_version.py +++ b/api_app/_version.py @@ -1 +1 @@ -__version__ = "0.25.7" +__version__ = "0.25.8" diff --git a/api_app/db/repositories/workspaces.py b/api_app/db/repositories/workspaces.py index 5be9cab979..36f366f2fb 100644 --- a/api_app/db/repositories/workspaces.py +++ b/api_app/db/repositories/workspaces.py @@ -142,13 +142,25 @@ async def get_address_space_based_on_size(self, workspace_properties: dict): address_space_size = workspace_properties.get("address_space_size", "small").lower() # 773 allow custom sized networks to be requested - if (address_space_size == "custom"): + if address_space_size == "custom": if (await self.validate_address_space(workspace_properties.get("address_space"))): return workspace_properties.get("address_space") else: raise InvalidInput("The custom 'address_space' you requested does not fit in the current network.") - # Default mask is 24 (small) + # If a numeric cidr was provided (e.g as a string like "25"), accept it + try: + if address_space_size.isdigit(): + cidr_netmask = int(address_space_size) + # basic validation for reasonable CIDR mask values + if cidr_netmask < 16 or cidr_netmask > 29: + raise InvalidInput("'address_space_size' numeric value must be between 16 and 29") + return await self.get_new_address_space(cidr_netmask) + except ValueError: + # fall through to predefined handling + pass + + # Default mask is 24 (small). Keep backwards compatibility with presets. cidr_netmask = WorkspaceRepository.predefined_address_spaces.get(address_space_size, 24) return await self.get_new_address_space(cidr_netmask) diff --git a/api_app/models/schemas/workspace_template.py b/api_app/models/schemas/workspace_template.py index bc20955217..0b3fcd31e0 100644 --- a/api_app/models/schemas/workspace_template.py +++ b/api_app/models/schemas/workspace_template.py @@ -22,7 +22,7 @@ def get_sample_workspace_template_object(template_name: str = "tre-workspace-bas "address_space_size": Property( type="string", default="small", - description="This can have a value of small, medium, large or custom. If you specify custom, then you need to specify a VNet address space in 'address_space' (e.g. 10.2.1.0/24)") + description="This can have a value of small, medium, large, a numeric CIDR mask (e.g. 25) or custom. If you specify custom, then you need to specify a VNet address space in 'address_space' (e.g. 10.2.1.0/24)") }, customActions=[ CustomAction() diff --git a/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py b/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py index 9abbc96727..c57a57d457 100644 --- a/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py +++ b/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py @@ -329,3 +329,29 @@ async def test_is_workspace_storage_account_available_when_name_not_available(mo mock_storage_client.return_value.storage_accounts.check_name_availability.assert_called_once_with({"name": f"stgws{workspace_id[-4:]}"}) assert result is False + + +@pytest.mark.asyncio +@patch('core.config.RESOURCE_LOCATION', "useast2") +@patch('core.config.TRE_ID', "9876") +@patch('core.config.CORE_ADDRESS_SPACE', "10.1.0.0/22") +@patch('core.config.TRE_ADDRESS_SPACE', "10.0.0.0/12") +async def test_get_address_space_based_on_size_with_string_19(workspace_repo, basic_workspace_request): + workspace_to_create = basic_workspace_request + # request a /19 + workspace_to_create.properties["address_space_size"] = "19" + address_space = await workspace_repo.get_address_space_based_on_size(workspace_to_create.properties) + assert address_space.endswith('/19') + + +@pytest.mark.asyncio +@patch('core.config.RESOURCE_LOCATION', "useast2") +@patch('core.config.TRE_ID', "9876") +@patch('core.config.CORE_ADDRESS_SPACE', "10.1.0.0/22") +@patch('core.config.TRE_ADDRESS_SPACE', "10.0.0.0/12") +async def test_get_address_space_based_on_size_with_string_29(workspace_repo, basic_workspace_request): + workspace_to_create = basic_workspace_request + # request a /29 + workspace_to_create.properties["address_space_size"] = "29" + address_space = await workspace_repo.get_address_space_based_on_size(workspace_to_create.properties) + assert address_space.endswith('/29') diff --git a/docs/tre-workspace-authors/authoring-workspace-templates.md b/docs/tre-workspace-authors/authoring-workspace-templates.md index 23614bb29f..48e9f7a24c 100644 --- a/docs/tre-workspace-authors/authoring-workspace-templates.md +++ b/docs/tre-workspace-authors/authoring-workspace-templates.md @@ -106,6 +106,7 @@ Some workspace services may require additional address spaces to be provisioned. To request an additional address space, the workspace service bundle must define an `address_space` parameter in the `porter.yaml` file. The value of this parameter will be provided by API to the resource processor. The size of the `address_space` will default to `/24`, however other sizes can be requested by including an `address_space_size` as part of the workspace service template. +This parameter accepts the presets `small` (/24), `medium` (/22), `large` (/16), the literal value `custom` together with an explicit `address_space` CIDR (e.g. `10.2.1.0/25`), or a numeric CIDR mask as a string from "16" to "29" (e.g. `"25"`) to ask the system to auto-select an available `/25`. The `address_space` allocation will only take place during the install phase of a deployment, as this is a breaking change to your template you should increment the major version of your template, this means a you must deploy a new resource instead of upgrading an existing one.