-
Notifications
You must be signed in to change notification settings - Fork 14
Description
Summary
Add a new Terraform resource powerplatform_environment_disaster_recovery that enables (and, if supported, disables) Disaster Recovery for an existing Power Platform environment using the Business App Platform (BAP) Admin API. The provider should issue the DR PATCH, capture the lifecycle operation ID from a response header, and poll the lifecycle operation until it completes. This should not be part of the base environment resource since the environment must exist and be a managed environment to enable DR. Since managed env is a separate resource, DR can't be applied on an environment create, this should be a separate resource that can be applied after managed env.
Preconditions (platform behavior):
- Environment must be Production
- Environment must be a Managed Environment
- The paired/secondary region is predetermined by the environment configuration (not user-selectable in this flow)
Proposed UX
resource "powerplatform_environment_disaster_recovery" "prod_dr" {
environment_id = powerplatform_environment.prod.id
enabled = true
}Behavior
- Create: Enable DR via PATCH; capture operation ID from response headers; poll lifecycle operation to
Succeeded. - Read: Report current DR state (enabled/disabled) and last lifecycle metadata.
- Update: Flip
enabledand repeat PATCH + poll. - Delete: If the platform supports disabling via PATCH, send the disable PATCH and poll; otherwise document as a no-op.
API Contract (observed)
Enable DR (PATCH)
PATCH https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/scopes/admin/environments/{environmentId}?api-version=2021-04-01
Content-Type: application/json
Authorization: Bearer <token>
{
"properties": {
"states": {
"disasterRecovery": { "id": "Enabled" }
}
}
}
Response: 202 Accepted
Headers (observed/expected):
- An operation reference header (e.g.,
Locationand/orAzure-AsyncOperation) that yields or includes the lifecycle operation ID - Optionally
Retry-Afterfor polling cadence
Poll lifecycle operation (GET)
GET https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/lifecycleOperations/{operationId}?api-version=2021-04-01
Terminal success example (real response captured):
{
"stages": [
{"id":"Validate","name":"Validate","state":{"id":"Succeeded"},"firstActionDateTime":"2025-10-03T21:30:42.268922Z","lastActionDateTime":"2025-10-03T21:30:42.268922Z"},
{"id":"Prepare","name":"Prepare","state":{"id":"Succeeded"},"firstActionDateTime":"2025-10-03T21:30:42.2845463Z","lastActionDateTime":"2025-10-03T21:30:42.2845463Z"},
{"id":"Run","name":"Run","state":{"id":"Succeeded"},"firstActionDateTime":"2025-10-03T21:30:42.300174Z","lastActionDateTime":"2025-10-03T21:32:46.6722115Z"},
{"id":"Finalize","name":"Finalize","state":{"id":"Succeeded"},"firstActionDateTime":"2025-10-03T21:32:47.0784649Z","lastActionDateTime":"2025-10-03T21:32:47.6409748Z"}
],
"id":"519e32e9-9e86-453d-a45d-b90d390a9623",
"links":{
"self":{"path":"/providers/Microsoft.BusinessAppPlatform/lifecycleOperations/519e32e9-9e86-453d-a45d-b90d390a9623"},
"environment":{"path":"/providers/Microsoft.BusinessAppPlatform/environments/ba87dcb8-f946-e87a-b4c6-8aafaa5c081d"}
},
"type":{"id":"Edit"},
"typeDisplayName":"Edit",
"state":{"id":"Succeeded"},
"createdDateTime":"2025-10-03T21:30:40.0422098Z",
"lastActionDateTime":"2025-10-03T21:32:47.6409748Z",
"requestedBy":{"id":"68429daf-e401-4e49-9354-31eacc594b56","displayName":"System Administrator","type":"User"}
}Terminal condition: state.id == "Succeeded" (provider should also surface failed/canceled stage details on error).
Disable DR (PATCH) — to be verified
PATCH .../environments/{environmentId}?api-version=2021-04-01
{
"properties": {
"states": {
"disasterRecovery": { "id": "Disabled" }
}
}
}
Assumption: same 202 + lifecycle operation behavior.
Provider Implementation Notes
-
Schema
-
environment_id(Required, string) -
enabled(Optional, bool; defaulttrueif resource is created) -
Computed:
status(e.g.,"Enabled"/"Disabled")last_operation_idlast_action_timerequested_by(if helpful for audit)
-
-
Validation
- Before PATCH,
GETenvironment; if not Production or not Managed, return a clear, actionable error.
- Before PATCH,
-
Lifecycle Operation Handling
- Read operation ID from response headers (e.g., parse
LocationorAzure-AsyncOperationto extract{operationId}). - Poll
lifecycleOperations/{operationId}until terminal (Succeeded/Failed/Canceled), honoringRetry-Afterif present; otherwise capped exponential backoff (e.g., 5s → 10s → … → 60s). - Respect
timeoutsand surface stage-by-stage progress in debug logs.
- Read operation ID from response headers (e.g., parse
-
Idempotency
- If DR already enabled, treat create/update as no-op.
- Plan should be stable after success.
-
Delete semantics
- If disable is supported: on
terraform destroy, send the disable PATCH and wait for terminal success. - If not supported: document as a no-op and require manual disable outside Terraform.
- If disable is supported: on
-
Import
terraform import powerplatform_environment_disaster_recovery.this {environmentId}
-
Testing
- Acceptance tests behind an opt-in env flag (DR has tenant-level implications).
- Test create → read (no drift) → optional disable (if supported).
Acceptance Criteria
- New resource
powerplatform_environment_disaster_recovery - Create/Update performs PATCH → reads operation ID from response header → polls lifecycle op to Succeeded
- Pre-validation for Production + Managed
- Stable plan after success;
terraform refreshreflects DR state - Delete either disables DR (if supported) with the same LRO flow, or is clearly documented as a no-op
- Timeouts + helpful error messages that include failing stage
- Docs + example HCL
- Opt-in acceptance tests
Open Items for Maintainers
- Header contract: confirm the exact header carrying the lifecycle operation link/ID (
Location,Azure-AsyncOperation, etc.). - Disable flow: confirm that setting
"disasterRecovery": {"id": "Disabled"}via PATCH is supported and follows the same LRO pattern. - RBAC: confirm the minimum role(s) required at tenant/environment scope for DR enable/disable.