Enhance address space handling to accept numeric CIDR masks - #4734
Enhance address space handling to accept numeric CIDR masks#4734James Chapman (JC-wk) wants to merge 61 commits into
Conversation
…e documentation accordingly
Unit Test Results774 tests 774 ✅ 11s ⏱️ Results for commit fb91c4c. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Pull request overview
Adds support in the API for requesting auto-assigned address spaces using numeric CIDR prefix lengths (as strings), extending beyond the existing small/medium/large presets while keeping backwards compatibility.
Changes:
- Extend address space allocation logic to accept numeric CIDR masks (string values) and validate allowed ranges.
- Add repository tests for numeric CIDR prefix requests.
- Update workspace authoring documentation and the project changelog to describe the new behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/tre-workspace-authors/authoring-workspace-templates.md | Documents numeric CIDR mask support for address_space_size when requesting additional address spaces. |
| CHANGELOG.md | Records the enhancement in the unreleased changelog. |
| api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py | Adds tests covering successful numeric CIDR prefix requests. |
| api_app/models/schemas/workspace_template.py | Updates sample schema description text to mention numeric CIDR masks. |
| api_app/db/repositories/workspaces.py | Implements numeric CIDR prefix parsing/validation and routes it into new CIDR allocation. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.
Suppressed comments (4)
api_app/tests_ma/test_api/test_routes/test_workspaces.py:822
HTTPException(detail=...)responses are typically JSON ({"detail": "..."}) in FastAPI/Starlette, so assertingresponse.textequals the raw message is likely to fail (the body will usually be JSON). Prefer assertingresponse.json()["detail"] == ..., or (if the intent is plain text errors) change the route to return aPlainTextResponsefor this error path for consistency.
response = await client.post(app.url_path_for(strings.API_CREATE_WORKSPACE_SERVICE, workspace_id=WORKSPACE_ID), json=workspace_service_input)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_CONTENT
assert response.text == "'address_space_size' numeric value must be between 16 and 29"
templates/workspaces/base/template_schema.json:66
- The description is misleading/inconsistent with the allowed values:
address_space_sizeis not a “CIDR value” (e.g.10.2.1.0/25), and the enum values are mask-length strings like"24", not strings like"/24". Recommend rewording to clearly state accepted inputs (presets or a numeric mask length string like"23"), and separately describe that"custom"requiresaddress_spaceto be an explicit CIDR (e.g.10.2.1.0/25).
"description": "Network address size as a CIDR value or (small /24, medium /22, large /16 or custom with an IP range e.g. 10.2.1.0/25) to be used by the workspace.",
"default": "small",
"enum": [
"24",
"23",
"22",
"21",
"20",
"19",
"18",
"17",
"16",
"small",
"medium",
"large",
docs/tre-workspace-authors/authoring-workspace-templates.md:115
- Lines 114–115 read as contradictory: they state templates are configured only for
"16"–"24"but then say you may configure up to"29". Suggest clarifying the distinction (e.g., “the built-in templates enumerate 16–24, but template authors can extend their own schema to 29” or similar), so readers understand what is supported by the API vs what the shipped templates allow by default.
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.
The API has support for allocating CIDR subnet masks from "16" to "29". Workspace templates are configured to support from "16" (65,536 IP addresses) to "24" (256 IP addresses).
Depending on the workspace service you are deploying you may configure a template with a CIDR up to "29" which has only 3 usable IP addresses as Azure reserves the first four and last address of every subnet.
CHANGELOG.md:6
- The changelog entry is added above the
0.29.0section, butapi_app/_version.pyis bumped to0.27.0in this PR. If the changelog is meant to track product releases, please file this entry under the correct version section (or add an “Unreleased” header if that’s the convention) and ensure version bumps align with the changelog structure.
* Allow numeric CIDR masks in `address_space_size` (e.g. "23") when requesting auto-assigned address spaces; accepts numeric strings and validates the mask range. ([#4733](https://github.com/microsoft/AzureTRE/issues/4733))
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Suppressed comments (1)
api_app/service_bus/deployment_status_updater.py:180
- The new address-space release state machine is not covered by the existing deployment-status updater tests. Add cases for single-step finalization, multi-step pending/finalization ordering, and ETag retry/failure so CIDRs cannot be released early or left permanently reserved without detection.
if (step_to_update.resourceType == ResourceType.Workspace
and step_to_update.resourceAction == RequestAction.Upgrade
and operation.action == RequestAction.UnInstall):
if not await self._finalize_pending_workspace_address_space(resource_to_persist, operation):
return False
if (step_to_update.templateStepId == "main"
and operation.action == RequestAction.UnInstall
and step_to_update.resourceType == ResourceType.WorkspaceService):
cleanup_succeeded = await self._finalize_workspace_address_space(resource_to_persist, operation) \
if is_last_step else await self._mark_workspace_address_space_pending(resource_to_persist, operation)
if not cleanup_succeeded:
return False
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (1)
api_app/tests_ma/test_service_bus/test_deployment_status_update.py:448
- This test only verifies that cleanup is skipped before the
mainuninstall step. The new successful-uninstall path that removes the service CIDR, retries ETag conflicts, and controls message completion is never exercised. Please add positive cleanup and retry/failure tests so an incorrect address release or permanently retried status message is caught.
with patch.object(status_updater, "_finalize_workspace_address_space", new_callable=AsyncMock) as finalize:
assert await status_updater.update_status_in_database(message) is True
finalize.assert_not_awaited()
|
/test-extended a6838f6 |
|
🤖 pr-bot 🤖 🏃 Running extended tests: https://github.com/microsoft/AzureTRE/actions/runs/32858080506 (with refid (in response to this comment from Jack Morris (@rudolphjacksonm)) |
There was a problem hiding this comment.
🟢 Approval recommended
The implementation, validation, documentation, versioning, and tests consistently support the intended CIDR behavior.
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 0 new
- Review effort level: Balanced
There was a problem hiding this comment.
🟢 Approval recommended
The implementation preserves preset compatibility, validates numeric boundaries, updates affected templates, and includes focused tests and documentation.
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 0 new
- Review effort level: Balanced

Resolves #4733 #3431
What is being addressed
Currently IP ranges are allocated based on t-shirt sizing s/m/l this introduces CIDR ranges to allow more granular subnet allocation
How is this addressed