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

Bicep philosophy inquiry #729

Closed
WhitWaldo opened this issue Oct 26, 2020 · 5 comments
Closed

Bicep philosophy inquiry #729

WhitWaldo opened this issue Oct 26, 2020 · 5 comments
Labels
discussion This is a discussion issue and not a change proposal.

Comments

@WhitWaldo
Copy link

Would someone be able to tell me a little bit more about the intention of Bicep?

  1. Is the intent that one builds and maintains Bicep file(s), versioning them in a repository with eventual support to build and deploy the generated ARM templates on demand? With some option to jump start this process by decompiling an existing ARM template eventually? In TypeScript, one authors the application in TypeScript and while it produces readable JavaScript, it's intended that future development is not done against the produced JavaScript.
  2. Or is it the goal to produce an ARM template that's true to form to the logic in Bicep so it's effectively a synonymous language to be used interchangeably to essentially provide trivial shortcut references without hammering out all the JSON/ARM syntax manually?

I ask, because I just set up two parameters as follows:

param vmssUseLinux bool = true
param vmImageOffer string = vmssUseLinux ? 'UbuntuServer' : 'WindowsServer'

I was surprised to see the output show up as:

   "vmssUseLinux": {
      "type": "bool",
      "defaultValue": true
    },
    "vmImageOffer": {
      "type": "string",
      "defaultValue": "[if(parameters('vmssUseLinux'), 'UbuntuServer', 'WindowsServer')]"
    },

I was instead hoping to see the following instead:

   "vmssUseLinux": {
      "type": "bool",
      "defaultValue": true
    },
    "vmImageOffer": {
      "type": "string",
      "defaultValue": "UbuntuServer"
    },

That suggests option 2 above, but this seems limiting to me as you're effectively saying that the functionality can only exist if it can be rendered in some way to an ARM template. This seems to be confirmed by this comment on the looping issue. While I understand a desire to provide a 1:1 experience back and forth (saw this ticket describing the idea, but could have sworn I read somewhere else that a decompiler wasn't intended to be 100% accurate), what if the decompiler simply served to make it easier to get a starting point in Bicep and then led to using that file for future development?

Frankly, I just finished authoring a first take of a template in Bicep and while the whole experience was far easier and less time-consuming than doing the same in ARM. That said, my Bicep file is 2489 lines long and my ARM output is 2413 lines, so it really didn't save much typing all in all. Opting for route 1 and making the ARM template just a build artifact would lend itself to the possibility for far richer support to really simplify template development - loops, scripting variables and who knows what else in the name of shortening these files and further simplifying development and maintenance.

@WhitWaldo WhitWaldo added the enhancement New feature or request label Oct 26, 2020
@ghost ghost added the Needs: Triage 🔍 label Oct 26, 2020
@alex-frankel
Copy link
Collaborator

Hi @WhitWaldo,

First off thanks for taking a deep dive into Bicep and provided all of this feedback, as well as the other issues you've open/replied to. We are still very early in the process, so getting this feedback now helps us tremendously.

In TypeScript, one authors the application in TypeScript and while it produces readable JavaScript, it's intended that future development is not done against the produced JavaScript.

That's exactly what we want for bicep. The generated ARM template is almost like a binary at this point. You shouldn't care what we compile it to because you should be 100% confident that you will get the result you desired/described in your bicep code. Once you transition to bicep, you should only need to be writing bicep code.

To the best of our ability, we want to compile as close to 1:1 with the JSON as possible. This keeps our compiler code at the right level of complexity and enables smoother compile/decompile. You are right that we don't expect 100% decompile accuracy, so we are prepared to depart from that where necessary. As an example, there is no representation of symbolic names in ARM Templates today (though we are going to add it) and resource properties like *.id or *.apiVersion don't actually exist in the ARM JSON.

That said, my Bicep file is 2489 lines long and my ARM output is 2413 lines, so it really didn't save much typing all in all.

I suspect you saved typing on the number of characters, even though the number of lines was not really affected (though I'd love to see your bicep and ARM code, I haven't seen an example where the bicep code was actually more LOC). On average we are seeing a 40-60% reduction in characters. The LOC is much more a reflection of the complexities of the resources PUT APIs rather than the bicep or ARM template language itself. To help reduce LOC further, we have implemented modules (these are in the main branch and will have to be installed via the "nightly" instructions).

Opting for route 1 and making the ARM template just a build artifact would lend itself to the possibility for far richer support to really simplify template development - loops, scripting variables and who knows what else in the name of shortening these files and further simplifying development and maintenance.

I think we are closer to option 1, then option 2, but neither should prevent looping for example. Looping is already present in the from of the copy property. If there were limitations to what we can express with something like copy then we need to inventory those and try to fix them in the ARM JSON layer as much as possible before deciding to paper over the problem in bicep. Correct me if I'm wrong, but I don't believe that you can write any TypeScript code that cannot be transpiled into JavaScript because that is what is actually being executed.

Scripting as a kind of "precompile" step is a more interesting scenario and wouldn't get reflected in the ARM JSON. I'll comment on your other issue with more details. We are not against introducing something like that, but we need to be really careful with it.

Let me know if I missed anything!

@majastrz
Copy link
Member

Btw, the reason your expression wasn't simplified to a constant is because we haven't yet implemented Constant Folding and boolean literal types in the compiler. Once that's implemented, you would see your expression compiled to 'UbuntuServer'.

@alex-frankel alex-frankel added discussion This is a discussion issue and not a change proposal. and removed Needs: Triage 🔍 enhancement New feature or request labels Oct 26, 2020
@WhitWaldo
Copy link
Author

Hello @majastrz and @alex-frankel - thanks for responding back so quickly!

I just ran a character check and found that unfortunately Bicep was quite a few more characters - 94726 compared to 84804 in the main.json output. I'd be happy to share my ARM template with you. I realized I'm still missing a few more resources, so it's only going to be growing from here and there's nothing sensitive in there (yet). What's a good email address to send to?

I'll dig into the modules, but to a large degree, I think my current needs there would be met in such a large file simply by having adequate IDE support (using VS Code) to show different related sections in the overview (such as this request looking at region/endregion folding as in C#) instead of splitting out resources by type to separate files. I tried that when doing the same in C# with the Azure Management SDKs and it proved a little more trouble than it was worth.

I'd missed the Constant Folding ticket (now found) - thank you @majastrz . I think that's exactly what I'm looking for here as that would remove some of the weight associated with the Bicep output.

That said, I'm appreciative and onboard with route 1 expressed above. Only writing Bicep and not dealing with the intermediate ARM file would be ideal. I'm happy to see that's where this is going.

I'm afraid I'm not familiar with really any of the advanced ARM functions, so I've missed copy, but that's likely why my file is so long in the first place. It's likely a very naive approach, but.. it's worked so far. You're correct - all TypeScript transpiles into proper JavaScript (though with the intriguing idea that all JavaScript is valid TypeScript as well).

Thank you!

@alex-frankel
Copy link
Collaborator

You can send the files to [email protected]. You won't be able to send us a zip, so you may need to make it available in onedrive or something similar.

@WhitWaldo
Copy link
Author

@alex-frankel Sent it your way.

@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
discussion This is a discussion issue and not a change proposal.
Projects
None yet
Development

No branches or pull requests

3 participants