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

Use any() in scope #3542

Open
slavizh opened this issue Jul 9, 2021 · 8 comments
Open

Use any() in scope #3542

slavizh opened this issue Jul 9, 2021 · 8 comments
Labels
enhancement New feature or request

Comments

@slavizh
Copy link
Contributor

slavizh commented Jul 9, 2021

Is your feature request related to a problem? Please describe.
When we have extension resources can we use the any() function to provide the scope.

Describe the solution you'd like

For example

var resourceType = 'Microsoft.Compute/virtualMachines'
var resourceName = 'vm0001'
resource dcra 'Microsoft.Insights/dataCollectionRuleAssociations@2021-04-01' = {
  name: 'dcra1'
  scope: any('${resourceType}/${resourceName}')
  properties: {
    dataCollectionRuleId: ''
    description: 'trest12'
  }
}

This will make it easier to have flexible and dynamic code where people can have input such as resourceType (Microsoft.Compute/virtualMachines) and resourceName (vm0001). The idea is that once a new resource supports dataCollectionRuleAssociations resource extension I do not have to update the code to provide support for that resource. If I have to use the current method once new resource supports the extension I have to do two things:

  • add that resource as existing with if statement so it does not apply when different resource type is chosen.
  • add another if to scope. You can imagine if I have 20 resource that support that extension the if will be quite big in code.
@slavizh slavizh added the enhancement New feature or request label Jul 9, 2021
@ghost ghost added the Needs: Triage 🔍 label Jul 9, 2021
@anthony-c-martin
Copy link
Member

Would the proposal under #2246 give you the flexibility you need here, specifically the example under heading "Generic"? This would allow passing a dynamic resource reference as a module parameter, and allow it to be used as an extension resource scope.

@slavizh
Copy link
Contributor Author

slavizh commented Jul 9, 2021

@anthony-c-martin as far as I could understand probably not unfortunately. I would like end users to be able to specify resourceType and resourceName as parameters without having to specify versions. At the end scope is just a string that is not even resourceId of the resource. I want to be able to specify scope as string without having to be a resource. Think of Microsoft.Insights/diagnosticSettings resource. The scope can be any resource provider + resource name that supports diagnostic settings. Every time Azure has a new service that supports diagnostic settings I do not want to change my code for deploying that, the end user can just provide the correct input and should be able to configure that. I gave the dataCollectionRuleAssociations example as that resource along with dataCollectionRules are suppose to replace diagnosticSettings in the future.

@anthony-c-martin
Copy link
Member

anthony-c-martin commented Jul 9, 2021

Here's how I'd imagine your scenario with proposals #2245 & #2246 if you're consuming in another module:

  • dataCollection.bicep
    param resource dataCollectionScopeResource
    
    resource dcra 'Microsoft.Insights/dataCollectionRuleAssociations@2021-04-01' = {
      name: 'dcra1'
      scope: dataCollectionScopeResource
      properties: {
        dataCollectionRuleId: ''
        description: 'trest12'
      }
    }
  • main.bicep:
    param vmName string
    
    module dataCollection './dataCollection.bicep' = {
      name: 'dataCollection'
      params: {
        // note that API version is unfortunately required here as of the current proposal, and this value could not be substituted as a param
        dataCollectionScopeResource: resource('Microsoft.Compute/virtualMachines@2020-01-01', vmName)
      }
    }

If consuming directly, I'd expect more flexibility to do things dynamically. I haven't got around to model what the ARM JSON equivalent of param resource dataCollectionScopeResource, but I envisage being able to pass a combination of name + type via the params file - (the az command may not be fully accurate, but just to illustrate the example):

az group deployment create ... dataCollection.bicep --parameters dataCollectionScopeResource={"type": "Microsoft.Compute/virtualMachines", "name": "vm0001"}

Would either of those options satisfy your requirements?

@slavizh
Copy link
Contributor Author

slavizh commented Jul 12, 2021

@anthony-c-martin If I can specify different input type and name (without API version) would be sufficient. Currently that specific API has support for Microsoft.Compute/virtualMachines, Microsoft.HybridCompute/machines and Microsoft.Compute/virtualMachineScaleSets. More probably will come over time. If specify one of those types and different name every time the same code should work. If they for example add Microsoft.Sql/servers in the future I should not change the code to work just will need to specify different input type and name.

@slavizh
Copy link
Contributor Author

slavizh commented Aug 31, 2021

@anthony-c-martin additionally allow setting empty string ('') value for scope. This allows for better flexibility if you want the scope to be for specific resource or for the resource group. Often used with roleAssignments resource. By having such flexibility you can reduce your code instead of creating two paths where the resource does not have scope property and where the resource has it.

@guidooliveira
Copy link

guidooliveira commented Sep 7, 2021

This would help me immensely in my current project as I need to set Role Based assignments on a resource level.
I personally like the resource type param and resource() functions. If resource() supports an object resourceId and can be used in the resource scope it would be ideal.

@guidooliveira
Copy link

This would help me immensely in my current project as I need to set Role Based assignments on a resource level. I personally like the resource type param and resource() functions. If resource() supports an object resourceId and can be used in the resource scope it would be ideal.

In the meantime, since JSON arm templates are now supported as modules, I've created one that was enough to meet my needs instead of having to create 1 bicep file/module per scope:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "targetResourceId": {
      "type": "string"
    },
    "roleDefinitionName": {
      "type": "string",
      "allowedValues": [
        "Contributor",
        "Private DNS Zone Contributor",
        "Network Contributor",
        "AcrPull",
        "Managed Identity Operator",
        "Virtual Machine Contributor",
        "Reader",
        "Key Vault Administrator"
      ]
    },
    "targetType": {
      "type": "string",
      "allowedValues": [
        "Resource",
        "Group"
      ]
    },
    "principalId": {
      "type": "string"
    }
  },
  "variables": {
    "Roles": {
      "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
      "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]",
      "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]",
      "AcrPull": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]",
      "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]",
      "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]",
      "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
      "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]"
    },
    "scope": {
      "Resource": "[skip(parameters('targetResourceId'), add(lastIndexOf(parameters('targetResourceId'), '/providers/'), 11))]",
      "Group": ""
    }
  },
  "resources": [
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2020-04-01-preview",
      "name": "[guid(parameters('targetResourceId'), parameters('roleDefinitionName'), parameters('principalId'))]",
      "scope": "[variables('scope')[parameters('targetType')]]",
      "condition":"[equals(parameters('targetType'), 'Resource')]",
      "properties": {
        "principalId": "[parameters('principalId')]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[variables('Roles')[parameters('roleDefinitionName')]]"
      }
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2020-04-01-preview",
      "name": "[guid(resourceGroup().name, parameters('roleDefinitionName'), parameters('principalId'))]",
      "condition":"[equals(parameters('targetType'), 'Group')]",
      "properties": {
        "principalId": "[parameters('principalId')]",
        "principalType": "ServicePrincipal",
        "roleDefinitionId": "[variables('Roles')[parameters('roleDefinitionName')]]"
      }
    }
  ]
}

@slavizh
Copy link
Contributor Author

slavizh commented May 5, 2022

Yes, I am aware that there is a workaround with arm templates as the possibility to be able to do that in Bicep already exists in ARM template :) . Of course this could be only temporary workaround due to wanting to get rid of ARM template code on 100%.

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

No branches or pull requests

4 participants