Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dependsOn not allowed on existing resources #2716

Open
stan-sz opened this issue May 18, 2021 · 14 comments
Open

dependsOn not allowed on existing resources #2716

stan-sz opened this issue May 18, 2021 · 14 comments
Labels

Comments

@stan-sz
Copy link
Contributor

stan-sz commented May 18, 2021

Bicep version
0.3.539

Describe the bug

resource rg 'Microsoft.Resources/resourceGroups@2018-05-01' existing = {
    name: 'foo'
    scope: subscription('subId')
    dependsOn: [

    ]
}

The property "dependsOn" is not allowed on objects of type "Microsoft.Resources/resourceGroups". No other properties are allowed.bicep(BCP037)

To Reproduce
See the file above

Additional context
The idea is to create a resource group in a module and trying to solve the issue from #1431, where an existing resource group resource would depend on that module.

@ghost ghost added the Needs: Triage 🔍 label May 18, 2021
@alex-frankel
Copy link
Collaborator

existing is the equivalent of a reference() call so there is no need for a dependsOn. As long as the rg symbol is not called before the module is deployed you should be good to go. I would put the dependency on the module that creates the resource group. Can you share the full code sample and what is not working currently?

@stan-sz
Copy link
Contributor Author

stan-sz commented May 21, 2021

  • azuredeploy.bicep
targetScope = 'subscription'
param rgName string

module createRg 'createRg.bicep' = {
  name: 'foo'
  params: {
    rgName: rgName
  }
}

resource rg 'Microsoft.Resources/resourceGroups@2021-01-01' existing = {
  name: rgName
  dependsOn: [
    createRg
  ]
}

module srch 'search.template.bicep' = {
    name: '${deployment().name}-1'
    scope: rg
    params: {
        search_name: 'foo'
        search_location: 'westus'
    }
}
  • createRg.bicep
targetScope = 'subscription'
param rgName string

resource rg 'Microsoft.Resources/resourceGroups@2021-01-01' = {
  name: rgName
  location: 'westus'
}
  • search.template.bicep
param search_name string
param search_location string

resource search 'Microsoft.Search/searchServices@2020-08-01' = {
    name: search_name
    location: search_location
    properties: {
        replicaCount: 1
        partitionCount: 1
    }
    sku: {
        name: 'standard'
    }
}

The property "dependsOn" is not allowed on objects of type "Microsoft.Resources/resourceGroups". Permissible properties include "scope".bicep(BCP037)

@alex-frankel
Copy link
Collaborator

What I want to understand is what you plan to do with the existing rg reference. How is that reference going to be consumed? Also, why not output the relevant info as a module output?

@stan-sz
Copy link
Contributor Author

stan-sz commented May 24, 2021

I've updated the previous reply to have a coherent story. The idea is to create resources within the newly-created resource group.
The relevant info from the module output cannot be used in scope. A slightly modified:

  • createRg.bicep
targetScope = 'subscription'
param rgName string

resource rg 'Microsoft.Resources/resourceGroups@2021-01-01' = {
  name: rgName
  location: 'westus'
}

output resourceGroup object = rg

*azuredeploy.bicep

targetScope = 'subscription'
param rgName string

module createRg 'createRg.bicep' = {
  name: 'foo'
  params: {
    rgName: rgName
  }
}

module srch 'search.template.bicep' = {
    name: '${deployment().name}-1'
    scope: createRg.outputs.resourceGroup
    params: {
        search_name: 'foo'
        search_location: 'westus'
    }
}

yield:

The property "scope" expected a value of type "resourceGroup" but the provided value is of type "object".bicep(BCP036)
The property "scope" must be evaluable at the start of the deployment, and cannot depend on any values that have not yet been calculated. Accessible properties of createRg are "name".bicep(BCP120)

@stan-sz
Copy link
Contributor Author

stan-sz commented May 24, 2021

Looks like the #622 output types could be a step toward helping in solving the dependsOn problem.

@alex-frankel
Copy link
Collaborator

alex-frankel commented May 24, 2021

Gotcha - I think the problem will be solved once #2245 is done, as you'll be able to output the rg resource as a "resource" type. Then you could do:

createRg.bicep

...
output rg resource = rg

then

azuredeploy.bicep

module srch 'search.template.bicep' = {
    name: '${deployment().name}-1'
    scope: createRg.outputs.rg
    params: {
        search_name: 'foo'
        search_location: 'westus'
    }
}

In the meantime, you can avoid the existing reference using the resourceGroup() function and using the rgName parameter:

targetScope = 'subscription'
param rgName string

module createRg 'createRg.bicep' = {
  name: 'foo'
  params: {
    rgName: rgName
  }
}

module srch 'search.template.bicep' = {
    name: '${deployment().name}-1'
    scope: resourceGroup(rgName)
    params: {
        search_name: 'foo'
        search_location: 'westus'
    }
    dependsOn: [
      createRg
    ]
}

If you want to avoid the explicit dependsOn, it might work if you output the rgName from the module and reference it inside the resourceGroup() function: resourceGroup(createRg.outputs.rgName). I'm not 100% sure this works though.

@Dylan-Prins
Copy link

Hi,

I have the same issue with storage account keys. I want to use the listKeys(), but this is not working with modules.

error: This expression is being used in an argument of the function "listKeys", which requires a value that can be calculated at the start of the deployment. Properties of stg which can be calculated at the start include "name".bicep(BCP181)

resource auditingSettings 'Microsoft.Sql/servers/auditingSettings@2021-05-01-Preview' = {
  parent: sqlServer
  name: 'default'
  properties: {
    state: auditingSettingsState
    storageEndpoint: '${stg.outputs.primaryEndpointsBlob}'
    storageAccountAccessKey: listKeys(stg.outputs.resourceId, providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value
    retentionDays: auditRententionInDays
    auditActionsAndGroups: null
    storageAccountSubscriptionId: subscription().subscriptionId
    isStorageSecondaryKeyInUse: false
  }
}

do we have a solution for this as well?

@alex-frankel
Copy link
Collaborator

@DylanPrinsITScripts -- can you instead re-establish the reference to the existing resource? If the storage account is in a different scope than the current module, it may get a little tricky though.

resource existingStorage 'Microsoft.Storage/storageAccounts@2021-06-01' existing = {
  name: ...
}

...

resource auditingSettings 'Microsoft.Sql/servers/auditingSettings@2021-05-01-Preview' = {
  parent: sqlServer
  name: 'default'
  properties: {
    state: auditingSettingsState
    storageEndpoint: stg.outputs.primaryEndpointsBlob
    storageAccountAccessKey: existingStorage.listKeys.keys[0].value
    retentionDays: auditRententionInDays
    auditActionsAndGroups: null
    storageAccountSubscriptionId: subscription().subscriptionId
    isStorageSecondaryKeyInUse: false
  }
}

BTW, I got rid of some unnecessary interpolation in the *.properties.storageEndpoint property value.

@Dylan-Prins
Copy link

Hi Alex,

Thanks for your reply.

storageAccountAccessKey: stg.listKeys.keys[0].value
I got the following error: The type "Microsoft.Storage/storageAccounts" does not contain property "listKeys"

@alex-frankel
Copy link
Collaborator

Sorry it should be listKeys(), not listKeys

@Broomhilde
Copy link

This is a major bug where especially with key vault deployments.

@SPSCS-Simon
Copy link

SPSCS-Simon commented Apr 12, 2022

@alex-frankel per you response above for the original issue :

Whist I get where you are going with this, say an organization has a naming/tagging policy for resource group creation, and that wants to encapsulate that in a module.

In your example above the name the resource group is not know before the module is invoked, so one really does want to use the output of the module to get to the created resource group and specifically its name to pas into the subsequent modules scope: resourceGroup(<scope>) parameter; however when one does that it results in the BCP120 error.

Generally one would assume that if one get up a matching dependsOn so that module the runtime could resolve that resource group name. I guess there is more to the runtime scoping requirements that is currently understood.

Any help greatly appreciated!

Bicep CLI version 0.4.1318 (ee0d808f35)

@alex-frankel
Copy link
Collaborator

Currently, it's a limitation in what bicep is able to comprehend at "compile-time". When a resource is created in a module, it's outputs are considered "run-time" properties that we can't calculate upfront.

@SPSCS-Simon -- personally, for the reasons you are describing, I think creating a resource group in a module is an anti-pattern. Resource groups are simple enough that it shouldn't be too onerous to ask users to maintain the "raw" resource definition. I recognize this makes it harder to enforce naming conventions though.

I'm hoping that #2245/#2246 should open the door to enable the scenario you are describing. I know there are a lot of others wanting/doing similar things.

@dbeyda
Copy link

dbeyda commented Apr 19, 2023

I'm having a similar problem, but with SQL Servers.
I created a module that setups up a SQL Server + AuditStorageAccount + Audit Settings.
This enforces compliance requirements within our product, and we re-use this module to instantiate multiple SQL Servers.

The desired functionality is to create SQL Server inside the module, then reference it in the parent template to create SQL DBs.

However:

  1. If I try get a reference to the SQL server on the parent template, with the existing keyword, I get error during deployment that resource was not found (indeed this resource does not have any dependence on the module deployment).
  2. Trying to add dependsOn: [SqlServerModule] to the reference doesn't work, since The property "dependsOn" is not allowed on objects of type "Microsoft.Sql/servers".
  3. If I try to add a dependency to the module deployment, through name: module.output.DatabaseName, I run into the limitation that the resulting ARM needs all resource names upfront.

The solution I found was to forget about refencing the SQL Server on the parent template. Just create all databases, with name: '${sqlServerName}/{sqlDbName}', dependsOn: [SqlServerModule], which is not very nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants