Bicep | Existing Resource Dependencies
Background
The Bicep existing keyword is a powerful capability that allows us to reference a resource that wasn’t deployed as part of the current Bicep file.
One of the typical use cases that I often see is where a resource is deployed as part of a module called by the parent template, the resource that was deployed as part of the module is then required later in the parent template and therefore an existing resource definition is used. As part of the template configuration there would be an explicit dependency between the existing resource definition and the module reference.
An example diagram of this is shown below:
For Bicep v0.34.1 and lower, there are two scenarios that can be observed when deploying the templates:
- Scenario 1: Successful deployment. The existing resource has been found and the explicit dependency between Existing Resource and Module Ref 1 has been honoured.
- Scenario 2: Deployment Failure.
The Resource XYZ under resource group 'XXYYZZ' was not found.
. The existing resource has not been found and the explicit dependency between Existing Resource and Module Ref 1 has not been honoured.
For most that fall into scenario 2, without much explanation of what may be going on behind the scenes, their typical solution to this particular problem may be to force the dependency chaining by extracting further of the parent template into a further module.
An example of this can be seen below:
Yes this is a valid solution, but why is there a problem in the first place?
Explanation
It all comes down to whether your template is compiled with symbolic name code generation.
Symbolic Name Code Generation allows the ARM template layer to use a new schema to represent resources as an object dictionary rather than an array of objects. This feature improves the semantic equivalence of the Bicep and ARM templates, resulting in more reliable code generation.
In a symbolic name template, an existing resource can depend on other resources or modules, and this will cause the backend to delay reading the resource until those dependencies are completed. This allows you to deploy a resource in a module, then refer to it with an existing declaration in the module parent. In non-symbolic name templates, existing resources are compiled to reference(resourceId()) expressions and are all handled in the first wave of deployment jobs.
In a non-symbolic name compiled template the existing reference looks like this:
reference(resourceId('Microsoft.xxx/yyy', parameters('resourceName'))), '2023-05-01', 'full')
In a symbolic name compiled template the existing reference and dependencies look like this:
reference('existingResource', '2023-05-01', 'full')
"dependsOn": [
"existingResource",
"ModuleRef1"
]
This explains why in some template deployment cases the deployment succeeds and in others it fails (the template is not setup for symbolic name code generation). But how do you enable symbolic name code generation?
Solution
Symbolic name code generation is part of the languageVersion 2.0 functionality and can be enabled automatically by using any of the following Bicep Features:
- user-defined types
- user-defined functions
- compile-time imports
- experimental features
For most of you up until this point like me, you will have unintentionally and thankfully enabled symbolic name code generation by using features as described above and therefore not suffered from the problem case as described.
Symbolic name code generation can also be explicitly enabled by adding the following to your bicepconfig.json:
"experimentalFeaturesEnabled": {
"symbolicNameCodegen": true
}
Or the preferred option use Bicep v0.34.44 or higher where languageVersion2.0 is used automatically when an existing resource has an explicit DependsOn dependency stipulated.
If you are unsure as to whether your templates are compiled using symbolic name code generation, have a look at the first few lines of your compiled Bicep template. The ARM template should specify languageVersion 2.0 if enabled and missing this line if not.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"languageVersion": "2.0",
"contentVersion": "1.0.0.0",
Hope this helps and have fun.
For the original version of this post see Andrew Wilson's personal blog at Bicep | Existing Resource Dependencies