Azure / bicep

Bicep is a declarative language for describing and deploying Azure resources
MIT License
3.21k stars 742 forks source link

Provide type safety for enum type properties #423

Open pacodelacruz opened 4 years ago

pacodelacruz commented 4 years ago

Is your feature request related to a problem? Please describe. Currently (v0.1), we are still relying on using strings to define many of the property values and would need to depend on tooling to know if the assigned values are valid.

Describe the solution you'd like All resource types have a template reference in which they describe what properties are of enum type. The authoring process would be much simpler if the language allowed me to use those type safe enums as opposed to just strings.

I know that strings give a lot of flexibility. But ideally, the compilation from Bicep to ARM would allow both approaches, and fail if a string value cannot be parsed/converted to an enum value.

anthony-c-martin commented 4 years ago

Totally agree! This is something that we will be covering under https://github.com/Azure/bicep/issues/401

alex-frankel commented 4 years ago

Going to close this as it is covered by #401

pacodelacruz commented 4 years ago

Hi @alex-frankel, @anthony-c-martin

This issue does not just refer to validating if input strings are valid on a first pass validation. I would like to have the option of having type safety and IntelliSense at write time. For instance if I'm specifying the location of a storage account, I'd like to be able to use any of the two options below

location: Location.AustraliaSouthEast

or

location: 'australiasoutheast'

With proper tooling and IntelliSense, the first option would give me a huge productivity advantage. I don't need to remember all potential valid values, but would be suggested by the editor. And the same would apply to all enum types, as they are provided by the resource provider API Swagger specs.

Validation and analysers are a great advantage, but IntelliSense for enum values would boost productivity considerably IMO.

I hope this this is something being considered for Bicep 💪

If we think about your Goal:

  1. Build the best possible language for describing, validating, and deploying infrastructure to Azure.

I would like to see: 1. Build the best possible language for authoring, describing, validating, and deploying infrastructure to Azure.

I hope this clarification makes sense.

majastrz commented 4 years ago

@pacodelacruz Absolutely! We have already begun working on IntelliSense. Enum value completions will be included in that.

I also agree that we should add "authoring" to the first goal. @alex-frankel thoughts?

pacodelacruz commented 4 years ago

Thanks @majastrz! @alex-frankel , is IntelliSense and Enum value completions included in #401 ? Thank you all!

majastrz commented 4 years ago

It isn't. I think we linked to the wrong issue when closing this one. There is another issue tracking the IntelliSense work. I'll leave this one open for now.

pacodelacruz commented 3 years ago

I'd love to see something like Pulumi's enum support in Bicep. I like their relaxed enums approach.

alex-frankel commented 3 years ago

@pacodelacruz - pulumi's enum support is interesting. I'm not sure I see the benefit of strict enum's versus what we have today in bicep. For example, on a storage account sku, I think we already do a good job with intellisense and validation:

image

How would you want the current bicep experience to change to be more like Pulumi's?

I can see the concept of relaxed enum's being useful for something like locations, where it is harder to have the exact list of known good values because it is dependent on so many factors.

pacodelacruz commented 3 years ago

Hey @alex-frankel , thanks for your prompt response. Agree that you are already giving great intellisense there that cover most of the cases. But, if enums were fully supported in Bicep, then you could define variables and params to be of those enum types, and those validations and autocomplete features can happen upstream, e.g. when typing my values in a params file. That's what you typically get in a first class programming language. Relaxed enums type approach would be best of both worlds.

Or, Is there another good and easy way to define allowed values for params based on the enums defined in the API spec of resource providers? I wouldn't want to have to go to the documentation to define them.

majastrz commented 3 years ago

@shenglol with the upcoming decorator support, I wonder if we should look into having a decorator that inherits the paramer allowed values from the type definition of the property to which the parameter is assigned. It's the reverse of a typical flow of types, but feels like it could be useful. (Probably something we'd need to run by Anders as well.)

alex-frankel commented 3 years ago

But, if enums were fully supported in Bicep, then you could define variables and params to be of those enum types, and those validations and autocomplete features can happen upstream

Got it - this clicked for me and agreed it would be very nice. It would be interesting if we could implement something like what @majastrz is describing.

shenglol commented 3 years ago

@shenglol with the upcoming decorator support, I wonder if we should look into having a decorator that inherits the paramer allowed values from the type definition of the property to which the parameter is assigned. It's the reverse of a typical flow of types, but feels like it could be useful. (Probably something we'd need to run by Anders as well.)

Yeah agree that this could be useful and we should run this by Anders. I think it would be challenging to come up with a syntax to reference the type definitions as the resource types are lengthy quoted strings.

majastrz commented 3 years ago

I was thinking of something more like "inherit allowed values from call/reference site(s)" without having to type in a huge reference path.

shenglol commented 3 years ago

Something similar to TypeScript's typeof keywords?

interface LeeeeeeeeeeeeeeeeeeengthyResourceType {
    sku: {
        name: 'A' | 'B' | 'C'
    }
}

declare var foo: LeeeeeeeeeeeeeeeeeeengthyResourceType;

declare var fooName1: LeeeeeeeeeeeeeeeeeeengthyResourceType['sku']['name']; // 'A' | 'B' | 'C'
declare var fooName2: typeof foo.sku.name; // 'A' | 'B' | 'C'
skyaddict commented 3 years ago

It would be great if when creating modules one could specify allowed values come from another enum.

param IntegrationAccountName string

@typeof = 'Microsoft.Logic/integrationAccounts@2016-06-01.skuname'
param sku string

resource IntegrationAccount 'Microsoft.Logic/integrationAccounts@2016-06-01' = {
  name: IntegrationAccountName
  location: resourceGroup().location
  sku: {
    name: sku
  }
  properties: {
    state: 'Enabled'
  }  
}