bicep icon indicating copy to clipboard operation
bicep copied to clipboard

Resource Derived Types -> Add support for User Defined Types in referenced modules

Open schaijkw opened this issue 1 year ago • 6 comments

Is your feature request related to a problem? Please describe. When you declare a user defined type as a parameter of a module, you now cannot reference this type dynamically.

param myUDTValue string
param myUDTValue2 int

module myModule 'br/recipe:api:v1.0.4' = {
  name: 'myModule-${deploymentDate}'
  scope: resourceGroup
  params: {
    location: location
    myUDT: { 
     value: myUDTValue 
     secondValue: myUDTValue2 
    }
  }
}

Describe the solution you'd like A way to reference myUDT so we can provide the values via bicepparam, like:

param myUDTParam resource<myModule.myUDT>

module myModule 'br/recipe:api:v1.0.4' = {
  name: 'myModule-${deploymentDate}'
  scope: resourceGroup
  params: {
    location: location
    myUDT: myUDTParam
  }
}

schaijkw avatar Mar 22 '24 11:03 schaijkw

In this scenario what would the custom type declaration look like? And what does your existing bicepparam file that doesn't work look like (did you try creating and importing a custom types module)?

marsontret avatar Mar 27 '24 14:03 marsontret

In this example, the UDT definition will look like:

type myUDT = {
     value: string
     secondValue: int
}

And the thing is that when I create a module with some parameters, including this type; I would like to pass the UDT without exporting the UDT but instead use a reference. Because I publish my modules to a registry and use only modules from that registry. So, I would like to re-use the resource derived type way of referencing for my container registry published modules.

schaijkw avatar Mar 27 '24 15:03 schaijkw

@schaijkw Why don't you want to export the UDT?

jeskew avatar Mar 27 '24 17:03 jeskew

The UDT can evolve over time. And when you use a UDT as a parameter for a module, you want a specific version of that UDT, the version at time of writing your module. You can also define your UDT in a seperate file and import the UDT in your module, but when you expose your module via a Container Registry, you don't want the consumer think of what version of UDT was used for that module. I will work out an example later, to share my concern more clear.

schaijkw avatar Mar 28 '24 08:03 schaijkw

I'm still not following. The module and import keywords both need to point to a concrete template, either a path on disk or a module in a registry. If the UDT evolves, that would require publishing a new version of the module, right?

Let's say you have the following template published as br/recipe:api:v1.0.4:

@export()
type myUDT = {
     value: string
     secondValue: int
}

param myUdtParam myUDT

You can consume this template as both an import source and as a module:

import {myUDT} from 'br/recipe:api:v1.0.4'

param myUDTParam myUDT

module myModule 'br/recipe:api:v1.0.4' = {
  name: 'myModule-${deploymentDate}'
  scope: resourceGroup
  params: {
    location: location
    myUdtParam: myUDTParam
  }
}

jeskew avatar Mar 28 '24 17:03 jeskew

Hi Jonny, thanks for providing your example and it will work in the most straight-forward situations. I think the way how resource derived types are referenced, is easier to use, strongly-typed/more type-safe and is abstracting underlying resource references.

For example, we crafted module D in the image below. I believe that we don't have to know about the versions that are used by the modules we imported: Module references drawio

At this moment I can reference an older version of module A without the IDE or bicep complaining.

Code example: biceptemp.zip

schaijkw avatar Apr 03 '24 08:04 schaijkw