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

Introduce option to exclude metadata and/or descriptions in compiled ARM #12919

Open
peter-de-wit opened this issue Jan 5, 2024 · 8 comments
Labels
enhancement New feature or request Needs: Upvote This issue requires more votes to be considered

Comments

@peter-de-wit
Copy link

Is your feature request related to a problem? Please describe.
We like the introduction of metadata within our BICEP deployments. Especially the combination with descriptions and markdown introduced a perfect way to document our deployments / features with our team. The problem with this is, we only need this documentation within our bicep file. We are now in a situation that we cannot deploy our solution(s) because the compiled ARM contains so much documentation (due child templates etc) that we manually have to remove all ARM/json metadata and description properties.

We need to keep an eye on the ARM deployment limit: https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/best-practices#template-limits

Describe the solution you'd like
As known from other programming languages, I would like to see an option (or default behaviour) that bicep compilation results in an ARM template without the descriptions and/or metadata.

@jeskew
Copy link
Member

jeskew commented Jan 5, 2024

It should be possible to add a config option similar to TypeScript's removeComments flag.

I would vote for keeping the current behavior as the default, though, since the description property of parameters and outputs is used for tooltips and completions when interacting with JSON modules and compile-time imports.

@peter-de-wit
Copy link
Author

Yes, you are absolutely right. But I would say that this is only useful and used from the main template and not all nested / child templates.

@matwilko
Copy link

matwilko commented Jan 8, 2024

To take this a step further, could there be an option to do full optimization to make for a minimal output ARM template?

In my project, it's great to have all the types and helpers etc. to make authoring easier and safer, but when I run the deployment, I don't need any of that extra information in the resulting deployment - I just need it to get to ARM in a semantically equivalent form.

I understand keeping all the types/metadata/variables etc. around for re-usable templates, but in a self-contained project with many smaller bicep files to deploy different parts of a service, those can quickly add up when copied into these sub-deployments and hit the 4MB template limit.

I'd propose there be an option to effectively erase all bicep information from the built ARM template at compile time, and inline any compile-time constant values, e.g. evaluate any function calls/property access that rely only on compile-time known data such as load* calls or variables in the template.

As a concrete example of where this would be useful for my project - I currently codegen a helper bicep file containing a map of Azure RBAC role names to their GUID values, as well as a type for specifying RBAC roles to a description of why it's being assigned (to make specifying RBAC assignments nicer and safer)

e.g.

@export()
type RbacRole =
    | 'Avere Cluster Create'
    ...

@export()
func toRoleId(role string) string =>
{
    'Avere Cluster Create': 'a7b1b19a-0e83-4fe5-935c-faaefbfd18c3'
    ...
}[role]

@export()
type RbacRoles = {
    @description('Avere cluster create role used by the Avere controller to create a vFXT cluster.')
    @minLength(20)
    'Avere Cluster Create': string?

     ...
}

This information is, in principle, inlinable by the compiler, since all the data is known to it at compile-time - but at the moment, any file that references any of these types or functions gets a massive injection of duplicated data.

I'd like to keep the type safety/authoring niceness this kind of helper affords me, but without ballooning the size of my deployment ARM that doesn't need any of this information to execute.

@peter-de-wit
Copy link
Author

@matwilko Your scenario describes exactly my point. The metadata for these generic types that can be used in multiple child deployments is for the actual deployment unneeded and only contributes to the actual size explosion of the ARM output.

@matwilko
Copy link

matwilko commented Jan 8, 2024

Yup, I'd like to see things go further than just metadata/type erasure though :)

@jeskew
Copy link
Member

jeskew commented Jan 8, 2024

@matwilko I think your scenario might be helped by work on #444 -- I'm guessing that the mapping in the toRoleId function is pretty big, and folding invocations at compile time might significantly reduce the size of your template.

Type erasure would be more complex than just pruning comments and descriptions, as the compiler would only be able to do this for parameters that can't be overridden from the outermost template. For example, in:

main.bicep

param foo string

module mod 'mod.bicep' = {
  params: {
    foo: foo
    bar: 'bar'
  }
}

mod.bicep

@minLength(5)
param foo string

@minLength(2)
param bar string

the compiler could in theory drop the @minLength(2) constraint on bar in mod.bicep, since main.bicep can't be deployed in any way that would result in an invalid value for bar being passed to mod.bicep, but the same isn't true of the @minLength(5) constraint on foo in mod.bicep, since any string would be accepted for foo in main.bicep and then passed directly through.

Trimming descriptions would be an easier place to start.

@matwilko
Copy link

matwilko commented Jan 8, 2024

I can see there'd be some situations where full type/validation erasure wouldn't be possible because of the potential presence of runtime values getting passed to parameters/functions etc.

But I think that if the compiler can prove, given the complete set of data it has at compile time (including any parameters passed to the deployment, which can be considered constants), that a type/validation is statically satisfied, it should be eliminated under this new mode.

I realise I'm proposing a whole new mode for the compiler itself where it knows a deployment is happening and using parameters etc. as part of its analysis and emit, rather than just outputting an ARM template, and then passing that on to the deployment steps that add in parameters etc.

Perhaps this could be a more general ARM template optimizer that can take any ARM template and do erasure/constant folding as a discrete step, whether with or without input parameters - that way the bicep compiler doesn't even have to get involved?

It's a big ask, I know, let me know if I should spin this wider idea out into a separate issue or poke the constant folding thread with some of these ideas, or if you're happy to keep discussion here :)

@stephaniezyen stephaniezyen added Needs: Upvote This issue requires more votes to be considered and removed Needs: Triage 🔍 labels Jan 24, 2024
@jeskew
Copy link
Member

jeskew commented Jan 24, 2024

@matwilko There's been some discussion about migrating deployment functionality into the Bicep CLI (the best issue I could find for this was #11434). I think that would need to be in place before tree-shaking out unused types and functions could have the desired impact.

Adding an option to strip descriptions (or all metadata) seems like a good first step in the right direction, though. In the meantime, you could try using a comment instead of a description, though that of course would not show up in hovers and completion prompts.

@jeskew jeskew removed their assignment Jan 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Needs: Upvote This issue requires more votes to be considered
Projects
Status: Todo
Development

No branches or pull requests

4 participants