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
feat: Expand usage of UDT for the AVNM Bicep Module - avm/res/network/network-manager
#1584
base: main
Are you sure you want to change the base?
Conversation
avm/res/network/network-manager/connectivity-configuration/main.bicep
Outdated
Show resolved
Hide resolved
deleteExistingPeering: ('True' | 'False')? | ||
|
||
@sys.description('Optional. Is global configuration.') | ||
isGlobal: ('True' | 'False')? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is actually a new spec waiting in a PR that asks primitive types to be declared as such (e.g. use int instead if string for numbers, or boolean instead of string for true/false).
This would mean, this parameter should be changed to isGlobal: bool
and the place where it is used needs to (optionally) cast the value to a string. I've seen implicit casts in the pasts, so we may not need it.
Same comment for the other string-boolean parameters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I would avoid hiding such things and align to the API as much as possible. That way its a standard consumption method from an API and IaC perspective and less abstraction code to maintain. But if that's the path that AVM is going to take then I will wait for that PR to be merged. Would be great to know if that's something that will be as a recommendation for the module owner or something that is a must have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd argue it's probably a 'Should' that targets improved usability of the resource, which in many instances is just plain bad (case an point CMK or boolean strings 😄 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @AlexanderSehr I have done some testing on the casting approach.
Here is an example PR: comparing the current UDT implementation as per this PR with an approach for casting.
It definetly took a toll on testing and validation a lot more than it was before. And seems more code to maintain for an owner. What are your thoughts on this? How has this been tested with other modules at a big scale?
I have some questions around the default
behaviour for a UDT param of type bool
. Because I had to use casting, I now am enforced in my test files to explicitly pass the parameter either true
false
compared to the past. Is there a specific pattern I should follow here as per AVM standards?
See above picture as an example. If I do not provide these values, my deployments now fail :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ahmadabdalla,
maybe we can find a slot some time to actually have a chat about the subject, as it's just easier to talk about than write 😄
Anyhow, the modules I've seen implement this on scale did usually not introduce much added code. Usually it was not much more than introducing e.g. a string(parameter)
or '${parameter}'
where a parameter was used an a string was expected, while in others it made the module actually easier as conditions didn't need to check for explicit string values in conditions like if(parameter == 'true')
. But naturally, the argument you made (i.e., deviating from the API) was exactlythe discussion to have. In like 'is it worth it'. At least for now we opted for 'yes' on the backdrop that we want to improve/easy a deployments usuability when we can.
Regarding the default behavior - if a parameter is optional, you can still just make it nullable. Also booleans. Does this answer the question (not sure I fully understood it 😄)? Something else that speaks for a chat 😉
@sys.description('Required. List of network groups for configuration. An admin rule collection must be associated to at least one network group.') | ||
appliesToGroups: { | ||
@sys.description('Required. The resource ID of the network group.') | ||
networkGroupId: string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should ideally be networkGroupResourceId
Please note, if changed to e.g. networkGroupResourceId
, also the location where it is used must be updated wth a map function to map it to the expected
networkGroupId`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also mind you, as you implemented the UDT in mutliple files, it would also need to be fixed in multiple files.
Looking forward to the time when types can simply be imported via a types.bicep (ref)
…n.bicep Co-authored-by: Alexander Sehr <ASehr@hotmail.de>
avm/res/network/network-manager
…network manager in main.json
avm/res/network/network-manager/security-admin-configuration/rule-collection/rule/main.bicep
Outdated
Show resolved
Hide resolved
@@ -58,10 +58,10 @@ param priority int | |||
param protocol string | |||
|
|||
@sys.description('Optional. List of destination port ranges. This specifies on which ports traffic will be allowed or denied by this rule. Provide an (*) to allow traffic on any port. Port ranges are between 1-65535.') | |||
param sourcePortRanges array = [] | |||
param sourcePortRanges sourcePortRangesType? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as before
param sourcePortRanges sourcePortRangesType? | |
param sourcePortRanges string[]? |
avm/res/network/network-manager/security-admin-configuration/rule-collection/rule/main.bicep
Outdated
Show resolved
Hide resolved
destinationPortRanges: contains(rule, 'destinationPortRanges') ? rule.destinationPortRanges : [] | ||
destinations: contains(rule, 'destinations') ? rule.destinations : [] | ||
description: rule.?description ?? '' | ||
destinationPortRanges: rule.?destinationPortRanges ?? [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a suggestion (so feel free to just resolve), but you could actually leave the else case out when referencing the child module.
Example
- If in the child module
param destinationPortRanges
has a default in the child, and this line here is justdestinationPortRanges: rule.?destinationPortRanges
, then it will automatically pick the default in the child - If in the child module
param destinationPortRanges
has no default but is nullable like in your case, then no value is passed through (which I guess also is fine)
…ule-collection/rule/main.bicep Co-authored-by: Alexander Sehr <ASehr@hotmail.de>
…ule-collection/rule/main.bicep Co-authored-by: Alexander Sehr <ASehr@hotmail.de>
Description
Introducing User Defined Types for the Azure Virtual Network Manager (AVNM) Bicep module. Additionally, expanded on the test cases for the maxium to increase test coverage for UDT validations.
Pipeline Reference
Type of Change
version.json
:version.json
.version.json
.Checklist
Set-AVMModule
locally to generate the supporting module files.