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

[SYNTAX PROPOSAL] Referencing nested child resources #1564

Closed
alex-frankel opened this issue Feb 17, 2021 · 38 comments
Closed

[SYNTAX PROPOSAL] Referencing nested child resources #1564

alex-frankel opened this issue Feb 17, 2021 · 38 comments
Labels
enhancement New feature or request Needs: Author Feedback Awaiting feedback from the author of the issue

Comments

@alex-frankel
Copy link
Collaborator

With #1516, we are introducing a new syntax for child resources that will allow them to be declared inside of their parent resource. For example:

resource vnet 'Microsoft.Network/virtualNetworks@2020-06-01' = {
  name: 'myvnet'
  location: resourceGroup().location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }  
  }
  
  resource subnet 'subnets' = {
    name: 'sub001'
    properties: {
      addressPrefix: '10.0.0.1/24'
    }
  }
}

Problem

We need a syntax to reference the symbolic name of the child resource subnet symbolic name. We cannot use just subnet because it would be ambiguous if the vnet was created as part of a loop since there is no way to distinguish between the subnet resource for vnet[0] vs vnet[1]

Requirements

  • Must be unambiguous, even if the parent resource is created as part of a loop
  • We may one day need to expose resources from a module. We should be able to use the same/similar syntax in this context
  • Discoverable with intellisense

Proposed syntax change

We have two options that we like.

Option 1

Add a dedicated top-level property - resources or $resources - to any resource with child resources declared:

1A - resources

output subnetId string = vnet.resources.subnet.id

1B - $resources

The $ would help distinguish this property from a "normal" property:

output subnetId string = vnet.$resources.subnet.id

Option 2

Instead of a dedicated property, we would have a different access character for child resources. This would be a terser syntax. So far we like the following:

2A - :

output subnetId string = vnet:subnet.id

2B - /

output subnetId string = vnet/subnet.id

We have historically used / to separate segments for child resources, so this has some nice familiarity.

2C - ..

output subnetId string = vnet..subnet.id

2D - >

output subnetId string = vnet>subnet.id

ASK

Please share your feedback by simply commenting with your favorite option (1A, 1B, 2A, 2B, 2C, 2D) or provide an alternative with some context as to why that is your favorite.

@alex-frankel alex-frankel added the enhancement New feature or request label Feb 17, 2021
@ghost ghost added the Needs: Triage 🔍 label Feb 17, 2021
@alex-frankel alex-frankel added Needs: Author Feedback Awaiting feedback from the author of the issue and removed Needs: Triage 🔍 labels Feb 17, 2021
@tohov
Copy link

tohov commented Feb 17, 2021

2B

@rynowak
Copy link
Contributor

rynowak commented Feb 17, 2021

2A followed by 2B (do I get a vote?)

@majastrz
Copy link
Member

2B

1 similar comment
@ChrisGibson1982
Copy link

2B

@SimonWahlin
Copy link
Collaborator

2B

Can we please also use this for modules? (as discussed in #923)

module myModule './module.bicep' = {
...
}

output mymodule/hubVnet.id string

@birdnathan
Copy link

1A

@EldertGrootenboer
Copy link

1B would be my first choice for clarity.
Second choice would be 2B for familiarity.

@slavizh
Copy link
Contributor

slavizh commented Feb 17, 2021

Preferably 2B, if not than 2A. Option 1 is too verbose.

@StefanIvemo
Copy link
Collaborator

2B

And I agree with @SimonWahlin on this:

Can we please also use this for modules? (as discussed in #923)

module myModule './module.bicep' = {
...
}

output mymodule/hubVnet.id string

@takekazuomi
Copy link
Contributor

2B

@anthony-c-martin
Copy link
Member

2B followed by 2A

@anthony-c-martin
Copy link
Member

2B

And I agree with @SimonWahlin on this:

Can we please also use this for modules? (as discussed in #923)

module myModule './module.bicep' = {
...
}

output mymodule/hubVnet.id string

Also want to point out I've added a somewhat related proposal here (allowing resources to be passed as inputs/outputs): #1170

@miqm
Copy link
Collaborator

miqm commented Feb 17, 2021

2A looks nice, but to align and ease with existing (ARM) syntax the winner is 2B

Edit: After considering @mbsnl comment, 2A seems more reasonable now.

@sebader
Copy link
Member

sebader commented Feb 17, 2021

1A feels by far the most natural to me. The dot-notation is used everywhere else inside bicep, why use something different here?

@miqm
Copy link
Collaborator

miqm commented Feb 17, 2021

1A feels by far the most natural to me. The dot-notation is used everywhere else inside bicep, why use something different here?

With 1A you will be mixing properties received from REST api with bicep's names - that might be confusing without IDE support.

@sebader
Copy link
Member

sebader commented Feb 17, 2021

With 1A you will be mixing properties received from REST api with bicep's names - that might be confusing without IDE support.

Would a user care about that? I expect bicep handle that for me. In the same way that I don't care if an expression that I write in bicep is handled by the bicep compiler or the underlying ARM deployment

@mbsnl
Copy link
Contributor

mbsnl commented Feb 17, 2021

2A. It would stand out as a Bicep specific implementation. 2C/2D is also an option, but 2C/2D look less attractive.

Specifically not 2B, because 2B, could suggest it's reflecting ARM Specifications, while it is not, people would wonder why not to use "vnetname/subnets/subnetname.id". And yes, this example is wrong, but just trying to point out a 2B implementation would get some users in the wrong think-pattern.

@alex-frankel
Copy link
Collaborator Author

With 1A you will be mixing properties received from REST api with bicep's names - that might be confusing without IDE support.

You are right that we are mixing things, and if you understand how ARM works at a lower level this could be a bit surprising. In practice though, to @sebader's point, I'd expect most users wouldn't care.

In theory, it's possible there could be an ambiguity if a resource had a real property called resources, but because ARM Templates allow you to add a property called resources to any resource, this shouldn't be allowed to happen and we should block resource type from adding it.

@TSunny007
Copy link
Contributor

TSunny007 commented Feb 17, 2021

2B with intellisense support when vnet. is typed to an autocomplete item /subnet which will autocomplete to vnet/subnet when selected (removes the period).
The autocomplete could apply to 2A-D as well.

@majastrz
Copy link
Member

majastrz commented Feb 17, 2021

We will have language server/IDE support for all of these options btw. This includes completions, validation, etc.

@glav
Copy link
Contributor

glav commented Feb 18, 2021

2A or 2B - torn between both actually with probably a leaning towards 2A as it is explicit/new and specific to bicep(imho). 2B looks too similar to other syntax uses.

2C & 2D hurt my eyes.

@J0F3
Copy link

J0F3 commented Feb 18, 2021

1A followed by 2B.

The Syntax 1A is also the most natural to me.

@miqm
Copy link
Collaborator

miqm commented Feb 18, 2021

I just realised, that 2A fits with the proposal I made for declaring child resources in a non nested way here #127 (comment)

resource myVm 'Microsoft.Compute/virtualMachines@2019-03-01' = existing {
  name: 'myVm'
}

resource myVm:myExtension 'extensions@2019-03-01' = {
  name: 'myExtension'
  properties: {
  (...)
  }
}

@JFolberth
Copy link
Contributor

1A seems most natural to. Followed by 2C

@WhitWaldo
Copy link

Especially since we can benefit from Intellisense to distinguish the relatively few resources with internal resources, I vote for 1A, then 2B.

While I agree that if users leap into Bicep right off the bat and work with these nested resources, it may be confusing why 2B syntax is used for some resources and not others, but I think In general, the dot notation makes sense and the IDE/Intellisense can lead them down the right road to differentiate between the relatively few special resources that would use this syntax.

@miqm
Copy link
Collaborator

miqm commented Feb 18, 2021

just adding why I don't want 1A - too much typing and with 2A basically word .resources. is replaced with :

@MaxFrost
Copy link

2A seems to make the most sense. 2B looks pretty and is familiar, but I believe that familiarity might cause issues during the migration/relearning process.

@nathanmitten
Copy link

From a simplicity standpoint 1A is the winner for me.

@cloudchristoph
Copy link

2A (followed by 2B)

@ChristopherGLewis
Copy link
Contributor

ChristopherGLewis commented Feb 21, 2021

Syntax 1A certainly feels the most natural.

2B would also be acceptable, but probably a little confusing ( is subnet in vnet/subnet a property of vnet or a resource)? And what happens if you have a sub-resource that is the same name as a property? Certainly perfectly valid bicep and ARM, but now you've got a really confusing syntax.

@iamalexmang
Copy link

2B without a shed of doubt. Not only familiarity, but naturality. Not sure what others thought, but reading through the first paragraph I was hoping you'd have the option of / -- and there it was.
In fairness, once I reached this option I only briefly skimmed what other options were available and none of them made me change my mind. 2B FTW

@MichaelKoster70
Copy link

Option 2B

@JustinGrote
Copy link

JustinGrote commented Feb 25, 2021

1A, keep things consistent wth .properties being "special", this isn't something that needs a new operator.

@NWiddup
Copy link

NWiddup commented Mar 1, 2021

1A makes the most sense to me, as we currently use myModuleResource.outputs.myOutput and so the x.y.z syntax feels most natural.

However in lieu of this, option 2B looks familiar considering current usage within ARM templates.

@johndowns
Copy link
Contributor

I really like 1A and think that's the most natural and feels the most 'Bicep-ish'. 1B is my next preference after that, but the $ makes me think of JSON schemas, which isn't a good thing...

@alex-frankel
Copy link
Collaborator Author

alex-frankel commented Mar 3, 2021

Current vote tally:

2B: ||||||||||||
1A: ||||||||||
2A: |||||
1B: |

Combining 1A+1B vs 2A+2B:

2: |||||||||||||||||
1: |||||||||||

We're going to start with a variant of option 2 since it seems to be the more popular choice. It will be checked into main to start to give folks an opportunity to play with it in the nightly build and share their thoughts before it gets officially released.

We are going to go with 2A for now, because the implementation is cleaner. It turns out / is particularly confusing for the language service because it is ambiguous whether you want to access a child resource or if you want to divide one resource by another (which doesn't make sense semantically), so we would need to special case that.

@pbstrein
Copy link

pbstrein commented Mar 8, 2021

1A (if its not too late to vote :))

@alex-frankel
Copy link
Collaborator Author

Closing since this has been implemented as :: since : led to an ambiguous grammar.

Docs are here:
https://github.com/Azure/bicep/blob/main/docs/spec/resources.md#resource-nesting

@ghost ghost locked as resolved and limited conversation to collaborators May 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request Needs: Author Feedback Awaiting feedback from the author of the issue
Projects
None yet
Development

No branches or pull requests