bicep icon indicating copy to clipboard operation
bicep copied to clipboard

Enabling languageVersion v2 breaks references to resource typed parameters by removing API versions

Open Xitric opened this issue 4 months ago • 0 comments

Bicep version Bicep CLI version 0.26.54 (5e20b29b58)

Describe the bug

Using the experimental feature resourceTypedParamsAndOutputs alone with the following templates works fine:

// main.bicep
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: 'st${uniqueString(deployment().name)}'
  location: 'westeurope'
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    accessTier: 'Hot'
    allowBlobPublicAccess: false
    publicNetworkAccess: 'Disabled'
  }
}

module myModule 'module.bicep' = {
  name: 'myModule'
  params: {
    storageAccount: storageAccount
  }
}
// module.bicep
param storageAccount resource 'Microsoft.Storage/storageAccounts@2023-01-01'

output blobEndpoint string = storageAccount.properties.primaryEndpoints.blob

However, if we start using user defined types or explicitly enable the experimental feature symbolicNameCodegen to generate ARM templates with languageVersion: 2.0, the same deployment fails with the error:

{"code": "InvalidTemplate", "target": "", "message": "Deployment template validation failed: 'The resource 'Microsoft.Storage/storageAccounts/st5o3ihl5d3qzhs' referenced in output is not defined in the template. Please specify resource identifier and api version if the resource is outside of the template. Please see https://aka.ms/arm-function-reference for usage details.'.", "additionalInfo": [{"type": "TemplateViolation", "info": {"lineNumber": 0, "linePosition": 0, "path": ""}}]}

To Reproduce

Using the Bicep templates above, here is the ARM template generated with the "old" language version:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.26.54.24096",
      "templateHash": "11676319683145003944"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-01-01",
      "name": "[format('st{0}', uniqueString(deployment().name))]",
      "location": "westeurope",
      "kind": "StorageV2",
      "sku": {
        "name": "Standard_LRS"
      },
      "properties": {
        "accessTier": "Hot",
        "allowBlobPublicAccess": false,
        "publicNetworkAccess": "Disabled"
      }
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "myModule",
      "properties": {
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "mode": "Incremental",
        "parameters": {
          "storageAccount": {
            "value": "[resourceId('Microsoft.Storage/storageAccounts', format('st{0}', uniqueString(deployment().name)))]"
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "metadata": {
            "_generator": {
              "name": "bicep",
              "version": "0.26.54.24096",
              "templateHash": "14104008023461642064"
            }
          },
          "parameters": {
            "storageAccount": {
              "type": "string",
              "metadata": {
                "resourceType": "Microsoft.Storage/storageAccounts@2023-01-01"
              }
            }
          },
          "resources": [],
          "outputs": {
            "blobEndpoint": {
              "type": "string",
              "value": "[reference(parameters('storageAccount'), '2023-01-01').primaryEndpoints.blob]"
            }
          }
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', format('st{0}', uniqueString(deployment().name)))]"
      ]
    }
  ]
}

This one deploys without issues.

If we then enable symbolicNameCodegen and generate the ARM template anew, we get the following result with language version 2.0:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "languageVersion": "2.0",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.26.54.24096",
      "templateHash": "17784816660608002450"
    }
  },
  "resources": {
    "storageAccount": {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-01-01",
      "name": "[format('st{0}', uniqueString(deployment().name))]",
      "location": "westeurope",
      "kind": "StorageV2",
      "sku": {
        "name": "Standard_LRS"
      },
      "properties": {
        "accessTier": "Hot",
        "allowBlobPublicAccess": false,
        "publicNetworkAccess": "Disabled"
      }
    },
    "myModule": {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2022-09-01",
      "name": "myModule",
      "properties": {
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "mode": "Incremental",
        "parameters": {
          "storageAccount": {
            "value": "[resourceId('Microsoft.Storage/storageAccounts', format('st{0}', uniqueString(deployment().name)))]"
          }
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "languageVersion": "2.0",
          "contentVersion": "1.0.0.0",
          "metadata": {
            "_generator": {
              "name": "bicep",
              "version": "0.26.54.24096",
              "templateHash": "16648886737782780637"
            }
          },
          "parameters": {
            "storageAccount": {
              "type": "string",
              "metadata": {
                "resourceType": "Microsoft.Storage/storageAccounts@2023-01-01"
              }
            }
          },
          "resources": {},
          "outputs": {
            "blobEndpoint": {
              "type": "string",
              "value": "[reference(parameters('storageAccount')).primaryEndpoints.blob]"
            }
          }
        }
      },
      "dependsOn": [
        "storageAccount"
      ]
    }
  }
}

Comparing these ARM templates, we see that the API version is dropped from the reference function when using language version 2.0.

Additional context

This issue also occurs in other cases where a resource typed parameter is referenced inside a module using languageVersion: 2.0. For instance, we have a federated identity credential in one of our deployments:

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
  ...

  resource hostFederation 'federatedIdentityCredentials' = {
    name: serviceAccountName
    properties: {
      issuer: aksCluster.properties.oidcIssuerProfile.issuerURL
      subject: 'system:serviceaccount:${namespace}:${serviceAccountName}'
      audiences: [
        'api://AzureADTokenExchange'
      ]
    }
  }
}

This deployment similarly fails, albeit with a slightly different message:

'The template resource 'Microsoft.ManagedIdentity/userAssignedIdentities//federatedIdentityCredentials/' reference to 'Microsoft.ContainerService/managedClusters/' requires an API version. Please see https://aka.ms/arm-syntax for usage details.'. (Code:InvalidTemplate)

This is because the generated ARM template contains the following reference:

"issuer": "[reference(parameters('aksCluster')).oidcIssuerProfile.issuerURL]",

Which should instead be:

"issuer": "[reference(parameters('aksCluster'), '2023-07-01').oidcIssuerProfile.issuerURL]",

Xitric avatar Apr 09 '24 11:04 Xitric