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

support "naive" nested deployments #145

Closed
alex-frankel opened this issue Aug 6, 2020 · 22 comments · Fixed by #275 or #1433
Closed

support "naive" nested deployments #145

alex-frankel opened this issue Aug 6, 2020 · 22 comments · Fixed by #275 or #1433
Assignees
Milestone

Comments

@alex-frankel
Copy link
Collaborator

for 0.1, want to verify that we have at least a way to do this, even if it's not great

@alex-frankel alex-frankel created this issue from a note in Backlog (0.1) Aug 6, 2020
@alex-frankel
Copy link
Collaborator Author

Attempted this and hit an issue with the $schema property which is required in a template. Here's the code:

image

resource nested 'microsoft.resources/deployments@2020-06-01' = {
  name: 'nested01'
  properties: {
    mode: 'Incremental'
    resourceGroup: 'giants-deep'
    template: {
      $schema: 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#'
      contentVersion: '1.0.0.0'
      resources: [
        {
          name: 'storage001'
          type: 'Microsoft.Storage/storageAccounts'
          apiVersion: '2019-06-01'
          sku: {
            name: 'Standard_LRS'
          }
          kind: 'StorageV2'
          location: 'eastus'
        }
      ]
    }
  }
}

Here's the error:

image

@majastrz
Copy link
Member

majastrz commented Aug 7, 2020

Yeah, properties only support identifier characters right now and $ isn't one. I think we have 2 questions here:

  • Should $ be allowed in identifier names? I don't have a huge objection against it.
  • We need an alternative syntax for object property names that also allows characters that are not allowed in identifiers. Something like this likely:
variable foo = {
  'this property has spaces in its name for some reason': true
}

For situations like user-assigned identities, we would also need to allow string interpolation. (The IL allows expressions in property names.)

@alex-frankel
Copy link
Collaborator Author

Feels like it's ok to just allow it. TypeScript seems to allow it.

You start the property name with ' and end it with ```, what that intentional? I think I'm fine with either one.

@bterlson
Copy link
Member

bterlson commented Aug 7, 2020

JS allows $ and _ to start identifiers, which are common additions. UAX-31 has a table of optional start, medial, and continue identifier characters you can consider!

@majastrz
Copy link
Member

majastrz commented Aug 7, 2020

@alex-frankel Fixed the quote in my comment.

@alex-frankel
Copy link
Collaborator Author

This looks good to me

@alex-frankel alex-frankel added this to the v0.1 milestone Aug 11, 2020
@alex-frankel alex-frankel added this to To do in 0.1 release Aug 11, 2020
@alex-frankel alex-frankel changed the title nested deployments support "naive" nested deployments Aug 17, 2020
@anthony-c-martin anthony-c-martin moved this from To do to In review in 0.1 release Aug 20, 2020
@azcloudfarmer azcloudfarmer moved this from In review to Done in 0.1 release Aug 21, 2020
@alex-frankel alex-frankel reopened this Aug 21, 2020
@filizt
Copy link
Contributor

filizt commented Aug 21, 2020

The top level resource group name and subscription properties show error in nested deployments. See image below.

image

Error: The property 'resourceGroup' is not allowed on objects of type 'Microsoft.Resources/deployments@2020-06-01'.bicep(BCP037)

@alex-frankel alex-frankel modified the milestones: v0.1, v0.2 Sep 8, 2020
@alex-frankel alex-frankel added this to To Do in 0.2 release Sep 16, 2020
@anthony-c-martin anthony-c-martin moved this from To Do to In Progress in 0.2 release Sep 30, 2020
@anthony-c-martin anthony-c-martin self-assigned this Sep 30, 2020
@anthony-c-martin
Copy link
Member

We're now using swagger-generated types, but looks like we're still missing these properties:
https://github.com/Azure/bicep-types-az/blob/main/generated/docs/microsoft.resources/2020-06-01/types.md#microsoftresourcesdeployments

I'll need to look into whether this is a problem with our swagger definitions or our type generator...

@SimonWahlin
Copy link
Collaborator

I'm trying to create a nested deployment using 'inner' as expressionEvaluationOptions and sending params from my parent template to my nested template.

Using the latest code in main, creating a nested template seems to work, but I cannot figure out a way to reference my inner parameters inside my nested template.

This is what I got so far:

resource additionalAppSettings 'Microsoft.Resources/deployments@2020-06-01' = {
    name: 'additionalAppSettings'
    properties: {
        expressionEvaluationOptions: {
            scope: 'inner'
        }
        mode: 'Incremental'
        template: {
            '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#'
            contentVersion: '1.0.0.0'
            parameters: {
                existingAppSettings: {
                    type: 'object'
                    defaultValue: {}
                }
                newAppSettings: {
                    type: 'object'
                    defaultValue: {}
                }
                functionAppName: {
                    type: 'string'
                }
            }
            resources: [
                {
                    type: 'Microsoft.Web/sites/config'
                    name: '[concat(parameters(functionAppName),\'/appsettings\')]'
                    apiVersion: '2020-06-01'
                    properties: '[union(parameters(\'existingAppSettings\'),parameters(\'newAppSettings\'))]'
                }
            ]
            outputs: {}
        }
        parameters: {
            existingAppSettings: {
                value: functionAppSettings
            }
            newAppSettings: {
                value: appSettings
            }
            functionAppName: {
                value: functionApp.name
            }
        }
    }
}

My problem is on these two lines:

name: '[concat(parameters(functionAppName),\'/appsettings\')]'
properties: '[union(parameters(\'existingAppSettings\'),parameters(\'newAppSettings\'))]'

Here I've tried using "native" ARM language, which is the closest I've gotten, but bicep then escapes the first '[' with an extra '[' resulting in an ARM template that looks like this:

"name": "[[concat(parameters(functionAppName),'/appsettings')]",

I've also tried using a more bicep-like approach with something similar to:

name: '${parameters('functionAppName')}/appsettings'

Then I get the error Error BCP057: The name "parameters" does not exist in the current context.

Is there a way to write a string that gets directly passed on to the ARM template without being escaped?
This would be a nice feature for anytime I want to do something that bicep hasn't implemented yet.

@alex-frankel
Copy link
Collaborator Author

Is there a way to write a string that gets directly passed on to the ARM template without being escaped?

Not today. We intentionally are blocking this to expose specific cases where we need this :) We will have to take a look to see if we should revoke this.

However, in this particular case, you can use the new modules capability, which will create a nested deployment using scope: inner. You will need to install the latest version of the CLI and VS Code extension from here as it is not officially released:
https://github.com/Azure/bicep/actions/runs/320112126

Instructions on installing these "nightly" builds here: https://github.com/Azure/bicep/blob/main/docs/installing-nightly.md

@SimonWahlin
Copy link
Collaborator

Thank you @alex-frankel!

I will give modules a try tonight.

@alex-frankel
Copy link
Collaborator Author

Great! Here is the spec: https://github.com/Azure/bicep/blob/main/docs/spec/modules.md

@SimonWahlin
Copy link
Collaborator

Works like a charm!

Had to use reference() to avoid getting api-version and 'Full' since appsettings don't support GET methods.

module additionalAppSettings './additionalAppSettings.bicep' = {
    name: 'additionalAppSettings'
    params: {
        existingAppSettings: union(reference(functionAppSettings.id),appSettings)
        functionAppName: functionAppName
    }
}

Thank you @alex-frankel

@alex-frankel
Copy link
Collaborator Author

Awesome! Out of curiosity did you try:

existingAppSettings: union(functionAppSettings.properties, appSettings)

functionAppSettings.properties should be the same as reference(functionAppSettings.id)

@SimonWahlin
Copy link
Collaborator

That works! Thank you!

I like bicep more an more for every day!
Now I just wish the ARM-api had a DevOps provider so we could manage our Azure DevOps org with bicep as well ;)

@alex-frankel
Copy link
Collaborator Author

maybe one day! glad everything is working well.

@gopinathch
Copy link

That works! Thank you!

I like bicep more an more for every day!
Now I just wish the ARM-api had a DevOps provider so we could manage our Azure DevOps org with bicep as well ;)

@SimonWahlin - will you be able to share scenarios or use cases on what you would like to achieve if that is available?

@SimonWahlin
Copy link
Collaborator

That works! Thank you!
I like bicep more an more for every day!
Now I just wish the ARM-api had a DevOps provider so we could manage our Azure DevOps org with bicep as well ;)

@SimonWahlin - will you be able to share scenarios or use cases on what you would like to achieve if that is available?

I'd be glad to, but maybe in a different forum?

@alex-frankel
Copy link
Collaborator Author

I think we can close this now that we have module + scope implemented. Thoughts @anthony-c-martin / @majastrz?

@SimonWahlin
Copy link
Collaborator

That works! Thank you!
I like bicep more an more for every day!
Now I just wish the ARM-api had a DevOps provider so we could manage our Azure DevOps org with bicep as well ;)

@SimonWahlin - will you be able to share scenarios or use cases on what you would like to achieve if that is available?

Since you are about to close this I'm taking the opportunity to highjack the Issue to reply to @gopinathch.

We want to create and configure Azure DevOps Projects using ARM-templates (pref bicep) so that we can deliver a new project to a team including example-git repo containing a markdown wiki with welcome information, example code and pipelines to get them started and links to our central repository with templates, pipelines and such.

The new project needs have pre-populated service connections to the teams dedicated landing zone subscriptions in Azure as well as service connections to services we use, for example SonarCloud.

The project need to be populated with a few custom roles that has custom permissions and maps to centrally managed Azure AD Groups (where we can make use of Access Review and other security features).

We want to keep all this configuration defined as code so we can prevent configuration drift and easily update projects base-configuration by changing the configuration and re-deploy, just like we do with infrastructure in Azure. This also opens the possibility for team members to request changes to their projects by a simple PR to the ARM template which would give us approval flow and traceability using the same tools and processes as we use for changing infrastructure.

Most of this is doable using the new Terraform provider for Azure DevOps, but since we use bicep/arm for everything else, I've become a bit spoiled of the automagic and amazing state-machine that is ARM. Keeping my own state in a file that has to be kept up to date with reality feels less tempting for each day that goes by.

Don't hesitate to reach out if you want more details, I think my email is public on my GitHub profile.

@alex-frankel alex-frankel removed this from In Progress in 0.2 release Nov 10, 2020
@alex-frankel alex-frankel modified the milestones: v0.2, v0.3 Nov 16, 2020
@alex-frankel alex-frankel added this to To Do in 0.3 release Nov 16, 2020
@alex-frankel
Copy link
Collaborator Author

Until we support templateSpec as a source for a module, we should treat this issue as HiPri as it is the only way to deploy a templateSpec

@alex-frankel
Copy link
Collaborator Author

We need to also check the behavior for the scope property, and ensure it allows for nested MG and tenant deployments.

@TSunny007 TSunny007 moved this from To Do to In Progress in 0.3 release Feb 1, 2021
@TSunny007 TSunny007 moved this from In Progress to In Review in 0.3 release Feb 2, 2021
@azcloudfarmer azcloudfarmer moved this from In Review to Done in 0.3 release Feb 3, 2021
@ghost ghost locked as resolved and limited conversation to collaborators May 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
No open projects
0.1 release
  
Done
0.3 release
  
Done
8 participants