Skip to content

Commit c571c68

Browse files
Honor x-ms-client-flatten in Bicep type generator (#12001)
# Description Implements [`x-ms-client-flatten`](https://github.com/Azure/autorest/tree/main/docs/extensions#x-ms-client-flatten) in the Radius Bicep type generator so the ARM `.properties.` envelope no longer leaks into user-authored Bicep templates. Before: ```bicep container.properties.container.image gateway.properties.url ``` After: ```bicep container.container.image gateway.url ``` The annotation is already present on every Radius resource (via `TrackedResourceRequired` in `typespec/radius/v1/trackedresource.tsp`); the generator just had not been honoring it. ## Type of change - This pull request adds or changes features of Radius and has an approved issue (issue link required). Fixes: #12000 # Contributor checklist - [x] Existing tests pass - [x] New tests added (unit + integration + functional) - [x] Generated artifacts refreshed - [N/A] Schema/typespec changes — annotation already existed - [N/A] Sample/doc Bicep rewrites — deferred to a follow-up; this PR is backward compatible # Changes ## Generator (`hack/bicep-types-radius/src/autorest.bicep`) - `src/type-generator.ts` - New helpers: `isFlattenSafe`, `flagsForFlattenedChild`, `expandFlattenedInto`. - Wire flattening into both `processResourceBody` (resource envelope) and `parseObjectType` (nested objects). - Fall back to the nested representation (with a warning via `logWarning`) when flattening would lose information: - The schema uses a discriminator (polymorphic variants). - A flattened child name collides with an existing parent property. - Each flattened child is emitted as `ReadOnly`. `Required`, `WriteOnly`, `Identifier`, and `DeployTimeConstant` are intentionally not propagated from the wrapper — the flat alias is unambiguously a read-side projection of the underlying `properties` payload. ## Tests - `test/integration/specs/basic/.../spec.json` — extended with: - `TestType1` — happy-path flatten on a resource body. - `TestType2` — polymorphic child, exercises the discriminator fallback. - `TestType3` — child property names collide with the resource envelope, exercises the collision fallback. - Checked-in baselines (`test/integration/generated/basic/...`) refreshed. - New programmatic Jest suite `test/flatten/flatten.test.ts` asserts the contract end-to-end: walks the generated `types.json` and verifies hoisting, fallback emission, and warning behavior. ## Regenerated Bicep types Ran `make generate-bicep-types`. Updated: - `hack/bicep-types-radius/generated/applications/applications.core/2023-10-01-preview/types.json` - `hack/bicep-types-radius/generated/applications/applications.datastores/2023-10-01-preview/types.json` - `hack/bicep-types-radius/generated/applications/applications.messaging/2023-10-01-preview/types.json` - `hack/bicep-types-radius/generated/radius/radius.core/2025-08-01-preview/types.json` - `hack/bicep-types-radius/generated/index.json` Spot-checked: e.g. `Applications.Core/containers` now exposes `application`, `container`, `connections`, `extensions`, `environment`, `identity`, `restartPolicy`, `runtimes`, `resources`, `provisioningState`, `status` directly on the resource body, with no `ApplicationProperties` / `ContainerProperties` wrapper. ## Functional test `test/functional-portable/corerp/noncloud/resources/container_flatten_test.go` + `testdata/corerp-resources-container-flatten.bicep` — `Test_Container_Flatten` deploys an Application + Container written entirely in the flat syntax (no `.properties.`) and validates the RP resources and the rendered pod in the app namespace. The bicep template only compiles against the regenerated types, so the test doubles as a regression guard. # Compatibility - Flattening is purely **additive and read-side only**. The wrapper `properties: { ... }` is preserved as the writable authoring surface — existing templates that author via `.properties.{ ... }` continue to work unchanged. Hoisted flat aliases are emitted with the `ReadOnly` flag, so they can be consumed via `reference('foo').bar` / `output x = foo.bar` but cannot be assigned from a template body. This is intentional: it eliminates `.properties.` from read-side expressions without requiring any breaking authoring-side change. - Existing sample/doc/test Bicep files in this repo are NOT rewritten in this PR; that is a deliberately scoped follow-up. # Deployment-engine dependency (resolved) The deploy-time half of this feature shipped in [azure-octo/deployment-engine#583](azure-octo/deployment-engine#583) (merged), which flattens the JToken stored in the reference value lookup so flat references like `reference('myCtnr').application` resolve at deploy time. The `:latest` `ghcr.io/radius-project/deployment-engine` image picks up the fix automatically. Validated end-to-end on a local kind cluster prior to merge: `Test_Container_Flatten` passes. --------- Signed-off-by: willdavsmith <willdavsmith@gmail.com> Co-authored-by: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
1 parent c43a316 commit c571c68

15 files changed

Lines changed: 4299 additions & 1241 deletions

File tree

hack/bicep-types-radius/generated/applications/applications.core/2023-10-01-preview/types.json

Lines changed: 1292 additions & 596 deletions
Large diffs are not rendered by default.

hack/bicep-types-radius/generated/applications/applications.datastores/2023-10-01-preview/types.json

Lines changed: 735 additions & 225 deletions
Large diffs are not rendered by default.

hack/bicep-types-radius/generated/applications/applications.messaging/2023-10-01-preview/types.json

Lines changed: 270 additions & 86 deletions
Large diffs are not rendered by default.

hack/bicep-types-radius/generated/index.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
{
22
"resources": {
33
"Applications.Core/applications@2023-10-01-preview": {
4-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/62"
4+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/72"
55
},
66
"Applications.Core/containers@2023-10-01-preview": {
7-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/135"
7+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/164"
88
},
99
"Applications.Core/environments@2023-10-01-preview": {
10-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/176"
10+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/217"
1111
},
1212
"Applications.Core/extenders@2023-10-01-preview": {
13-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/197"
13+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/250"
1414
},
1515
"Applications.Core/gateways@2023-10-01-preview": {
16-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/220"
16+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/283"
1717
},
1818
"Applications.Core/secretStores@2023-10-01-preview": {
19-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/256"
19+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/319"
2020
},
2121
"Applications.Core/volumes@2023-10-01-preview": {
22-
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/294"
22+
"$ref": "applications/applications.core/2023-10-01-preview/types.json#/357"
2323
},
2424
"Applications.Dapr/configurationStores@2023-10-01-preview": {
2525
"$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/55"
@@ -34,16 +34,16 @@
3434
"$ref": "applications/applications.dapr/2023-10-01-preview/types.json#/114"
3535
},
3636
"Applications.Datastores/mongoDatabases@2023-10-01-preview": {
37-
"$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/55"
37+
"$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/68"
3838
},
3939
"Applications.Datastores/redisCaches@2023-10-01-preview": {
40-
"$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/77"
40+
"$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/103"
4141
},
4242
"Applications.Datastores/sqlDatabases@2023-10-01-preview": {
43-
"$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/99"
43+
"$ref": "applications/applications.datastores/2023-10-01-preview/types.json#/138"
4444
},
4545
"Applications.Messaging/rabbitMQQueues@2023-10-01-preview": {
46-
"$ref": "applications/applications.messaging/2023-10-01-preview/types.json#/55"
46+
"$ref": "applications/applications.messaging/2023-10-01-preview/types.json#/68"
4747
},
4848
"Radius.Compute/containers@2025-08-01-preview": {
4949
"$ref": "radius/radius.compute/2025-08-01-preview/types.json#/125"
@@ -55,19 +55,19 @@
5555
"$ref": "radius/radius.compute/2025-08-01-preview/types.json#/193"
5656
},
5757
"Radius.Core/applications@2025-08-01-preview": {
58-
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/44"
58+
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/53"
5959
},
6060
"Radius.Core/bicepConfigs@2025-08-01-preview": {
61-
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/66"
61+
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/86"
6262
},
6363
"Radius.Core/environments@2025-08-01-preview": {
64-
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/89"
64+
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/121"
6565
},
6666
"Radius.Core/recipePacks@2025-08-01-preview": {
67-
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/111"
67+
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/154"
6868
},
6969
"Radius.Core/terraformConfigs@2025-08-01-preview": {
70-
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/138"
70+
"$ref": "radius/radius.core/2025-08-01-preview/types.json#/192"
7171
},
7272
"Radius.Data/mySqlDatabases@2025-08-01-preview": {
7373
"$ref": "radius/radius.data/2025-08-01-preview/types.json#/17"

0 commit comments

Comments
 (0)