Azure / Azure/bicep

Snapshots output results degrade when using modules

Open
#19,695 4 comments 1 reaction 0 assignees View on GitHub
Bicep Snapshot
Dominant language
Bicep
Stars
3.6k
Forks
830
Avg merge
1d 21m
Merged PRs (30d)
79

Description

**Bicep version**
Bicep CLI version 0.43.8 (310735909d)

**Describe the bug**
I have managed the test the output functionality for bicep snapshots but unfortunately it works only on single modules. As soon as you have more than one module and pass outputs between them you start to see ARM code exposed like createArray(), createObject(), etc. instead of the actual results. For example when such functions are used on resources they resolve in most cases correctly without being exposed as ARM code. I say most cases as there are some edge cases with more complex code. Here is a code I came up that can be tested.

output1.bicep
```bicep

param input1 array
param input2 array

module tests 'output2.bicep' = [for i in input2: {
params: {
input: input1
}
}]

output unexpected array = [for (test, i) in input2: tests[i].outputs.resources]
output expected array = [for (test, i) in input2: map(input1, input => {
name: input.name
location: input.location
tags: input.tags
storageAccountName: input.storageAccountName
})]

```

output2.bicep
```bicep

param input array

output resources array = [for i in input: {
name: i.name
location: i.location
tags: i.tags
storageAccountName: i.storageAccountName
}]

```

output.bicepparam
```bicep

```using 'output1.bicep'

param input1 = [
{
name: 'workspace1'
location: 'eastus'
tags: {
environment: 'dev'
}
storageAccountName: 'storageaccount1'
}
{
name: 'workspace2'
location: 'westus'
tags: {
environment: 'prod'
}
storageAccountName: 'storageaccount2'
}
]

param input2 = [1, 2, 3]
```

output.snapshot.json
```json
{
"predictedResources": [],
"diagnostics": [],
"outputs": {
"expected": [
[
{
"name": "workspace1",
"location": "eastus",
"tags": {
"environment": "dev"
},
"storageAccountName": "storageaccount1"
},
{
"name": "workspace2",
"location": "westus",
"tags": {
"environment": "prod"
},
"storageAccountName": "storageaccount2"
}
],
[
{
"name": "workspace1",
"location": "eastus",
"tags": {
"environment": "dev"
},
"storageAccountName": "storageaccount1"
},
{
"name": "workspace2",
"location": "westus",
"tags": {
"environment": "prod"
},
"storageAccountName": "storageaccount2"
}
],
[
{
"name": "workspace1",
"location": "eastus",
"tags": {
"environment": "dev"
},
"storageAccountName": "storageaccount1"
},
{
"name": "workspace2",
"location": "westus",
"tags": {
"environment": "prod"
},
"storageAccountName": "storageaccount2"
}
]
],
"unexpected": "[createArray(reference(resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Resources/deployments', format('tests-{0}-{1}', 0, uniqueString('tests', deployment().name))), '2025-04-01').outputs.resources.value, reference(resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Resources/deployments', format('tests-{0}-{1}', 1, uniqueString('tests', deployment().name))), '2025-04-01').outputs.resources.value, reference(resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.Resources/deployments', format('tests-{0}-{1}', 2, uniqueString('tests', deployment().name))), '2025-04-01').outputs.resources.value)]"
}
}
```

You can see the difference between what is the actual result when using modules and what I expect to be the actual result. After all the point of the snapshots is to see how the structure of the resource/output will look when deployed at Azure. With the current result if I change the name of the output in output2.bicep that will be registered as change in the snapshot but it should not as I am not changing the structure of the output. I am just changing internals of the code that are irrelevant for the output structure.

Note that I do not know why reference to deployments resource are used as well. In some other code that I have that I cannot share here at least that reference for deployments resource does not exist and I get actual values passed like `createArray(createObject('name', 'syst003', 'identity',....`

**To Reproduce**
Steps to reproduce the behavior:
described

**Additional context**
Add any other context about the problem here.

Contributor guide

Open the contributing guide

Research direction

Start with the reproduced files output1.bicep, output2.bicep, output.bicepparam, and output.snapshot.json, then run the snapshot scenario described in the issue. Trace how module outputs are represented when passed between modules. Done means snapshot outputs show the resolved structure rather than ARM expressions such as createArray() and createObject().

Written by the indexing model from the issue text.

Assessment

Tech stack
azure
Domain
cloud, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.