Skip to content

Commit 8e7a067

Browse files
feat: Added diverse specs for User-defined types (#1738)
1 parent 020d2d2 commit 8e7a067

File tree

7 files changed

+236
-2
lines changed

7 files changed

+236
-2
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: BCPRMNFR2 - User-defined types - AVM-Common-Types
3+
url: /spec/BCPRMNFR2
4+
geekdocNav: true
5+
geekdocAlign: left
6+
geekdocAnchor: true
7+
type: posts
8+
tags: [
9+
Class-Resource, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
10+
Type-NonFunctional, # SINGLE VALUE: this can be "Type-Functional" OR "Type-NonFunctional"
11+
Category-Inputs/Outputs, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
12+
Language-Bicep, # MULTIPLE VALUES: this can be "Language-Bicep" AND/OR "Language-Terraform"
13+
Severity-MUST, # SINGLE VALUE: this can be "Severity-MUST" OR "Severity-SHOULD" OR "Severity-MAY"
14+
Persona-Owner, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
15+
Persona-Contributor, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
16+
Lifecycle-BAU, # SINGLE VALUE: this can be "Lifecycle-Initial" OR "Lifecycle-BAU" OR "Lifecycle-EOL"
17+
Validation-Manual # SINGLE VALUE: this can be "Validation-Manual" OR "Validation-CI/Informational" OR "CI/Enforced"
18+
]
19+
priority: 13010
20+
---
21+
22+
#### ID: BCPRMNFR2 - User-defined types - AVM-Common-Types
23+
24+
When implementing any of the [shared](/Azure-Verified-Modules/specs/shared/interfaces) or [Bicep-specific](/Azure-Verified-Modules/specs/bicep/interfaces) AVM interface variants you MUST import their User-defined type (UDT) via the published [AVM-Common-Types](https://github.com/Azure/bicep-registry-modules/tree/main/avm/utl/types/avm-common-types) module.
25+
26+
When doing so, each type MUST be imported separately, right above the parameter or output that uses it.
27+
28+
```bicep
29+
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:*.*.*'
30+
@description('Optional. Array of role assignments to create.')
31+
param roleAssignments roleAssignmentType[]?
32+
import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:*.*.*'
33+
@description('Optional. The diagnostic settings of the service.')
34+
param diagnosticSettings diagnosticSettingFullType[]?
35+
```
36+
37+
Importing them individually as opposed to one common block has several benefits such as
38+
- Individual versioning of types
39+
- If you must update the version for one type, you're not exposed to unexpected changes to other types
40+
41+
{{< hint type=important >}}
42+
43+
The `import (...)` block MUST not be added in between a parameter's definition and its metadata. Doing so breaks the metadata's binding to the parameter in question.
44+
45+
{{< /hint >}}
46+
47+
Finally, you should check for version updates regularly to ensure the resource module stays consistent with the specs. If the used AVM-Common-Types runs stale, the CI may eventually fail the module's static tests.

docs/content/specs-defs/includes/bicep/shared/non-functional/BCPNFR1.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: BCPNFR1 - Data Types
2+
title: BCPNFR1 - User-defined types - General
33
url: /spec/BCPNFR1
44
geekdocNav: true
55
geekdocAlign: left
@@ -20,7 +20,7 @@ tags: [
2020
priority: 11010
2121
---
2222

23-
#### ID: BCPNFR1 - Category: Inputs - Data Types
23+
#### ID: BCPNFR1 - Inputs - User-defined types - General
2424

2525
To simplify the consumption experience for module consumers when interacting with complex data types input parameters, mainly objects and arrays, the Bicep feature of [User-Defined Types](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/user-defined-data-types) **MUST** be used and declared.
2626

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: BCPNFR18 - User-defined types - Specification
3+
url: /spec/BCPNFR18
4+
geekdocNav: true
5+
geekdocAlign: left
6+
geekdocAnchor: true
7+
type: posts
8+
tags: [
9+
Class-Resource, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
10+
Class-Pattern, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
11+
Type-NonFunctional, # SINGLE VALUE: this can be "Type-Functional" OR "Type-NonFunctional"
12+
Category-Inputs/Outputs, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
13+
Language-Bicep, # MULTIPLE VALUES: this can be "Language-Bicep" AND/OR "Language-Terraform"
14+
Severity-MUST, # SINGLE VALUE: this can be "Severity-MUST" OR "Severity-SHOULD" OR "Severity-MAY"
15+
Persona-Owner, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
16+
Persona-Contributor, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
17+
Lifecycle-BAU, # SINGLE VALUE: this can be "Lifecycle-Initial" OR "Lifecycle-BAU" OR "Lifecycle-EOL"
18+
Validation-TBD # SINGLE VALUE: this can be "Validation-Manual" OR "Validation-CI/Informational" OR "CI/Enforced"
19+
]
20+
priority: 11010
21+
---
22+
23+
#### ID: BCPNFR18 - User-defined types - Specification
24+
25+
User-defined types (UDTs) MUST always be singular and non-nullable. The configuration of either should instead be done directly at the parameter or output that uses the type.
26+
27+
For example, instead of
28+
```bicep
29+
param subnets subnetsType
30+
type subnetsType = { ... }[]?
31+
```
32+
the type should be defined like
33+
```bicep
34+
param subnets subnetType[]?
35+
type subnetType = { ... }
36+
```
37+
38+
The primary reason for this requirement is clarity. If not defined directly at the parameter or output, a user would always be required to check the type to understand how e.g., a parameter is expected.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: BCPNFR19 - User-defined types - Naming
3+
url: /spec/BCPNFR18
4+
geekdocNav: true
5+
geekdocAlign: left
6+
geekdocAnchor: true
7+
type: posts
8+
tags: [
9+
Class-Resource, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
10+
Class-Pattern, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
11+
Type-NonFunctional, # SINGLE VALUE: this can be "Type-Functional" OR "Type-NonFunctional"
12+
Category-Inputs/Outputs, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
13+
Category-Naming/Composition, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
14+
Language-Bicep, # MULTIPLE VALUES: this can be "Language-Bicep" AND/OR "Language-Terraform"
15+
Severity-MUST, # SINGLE VALUE: this can be "Severity-MUST" OR "Severity-SHOULD" OR "Severity-MAY"
16+
Persona-Owner, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
17+
Persona-Contributor, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
18+
Lifecycle-BAU, # SINGLE VALUE: this can be "Lifecycle-Initial" OR "Lifecycle-BAU" OR "Lifecycle-EOL"
19+
Validation-TBD # SINGLE VALUE: this can be "Validation-Manual" OR "Validation-CI/Informational" OR "CI/Enforced"
20+
]
21+
priority: 11010
22+
---
23+
24+
#### ID: BCPNFR19 - User-defined types - Naming
25+
26+
User-defined types (UDTs) MUST always end with the suffix `(...)Type` to make them obvious to users. In addition it is recommended to extend the suffix to `(...)OutputType` if a UDT is exclusively used for outputs.
27+
```bicep
28+
type subnet = { ... } // Wrong
29+
type subnetType = { ... } // Correct
30+
type subnetOutputType = { ... } // Correct, if used only for outputs
31+
```
32+
33+
Since User-defined types (UDTs) MUST always be singular as per [BCPNFR18](/Azure-Verified-Modules/spec/BCPNFR18), their naming should reflect this and also be singular.
34+
```bicep
35+
type subnetsType = { ... } // Wrong
36+
type subnetType = { ... } // Correct
37+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
title: BCPNFR20 - User-defined types - Export
3+
url: /spec/BCPNFR20
4+
geekdocNav: true
5+
geekdocAlign: left
6+
geekdocAnchor: true
7+
type: posts
8+
tags: [
9+
Class-Resource, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
10+
Class-Pattern, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
11+
Type-NonFunctional, # SINGLE VALUE: this can be "Type-Functional" OR "Type-NonFunctional"
12+
Category-Inputs/Outputs, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
13+
Language-Bicep, # MULTIPLE VALUES: this can be "Language-Bicep" AND/OR "Language-Terraform"
14+
Severity-MUST, # SINGLE VALUE: this can be "Severity-MUST" OR "Severity-SHOULD" OR "Severity-MAY"
15+
Persona-Owner, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
16+
Persona-Contributor, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
17+
Lifecycle-BAU, # SINGLE VALUE: this can be "Lifecycle-Initial" OR "Lifecycle-BAU" OR "Lifecycle-EOL"
18+
Validation-TBD # SINGLE VALUE: this can be "Validation-Manual" OR "Validation-CI/Informational" OR "CI/Enforced"
19+
]
20+
priority: 11010
21+
---
22+
23+
#### ID: BCPNFR20 - User-defined types - Export
24+
25+
User-defined types (UDTs) SHOULD always be exported via the `@export()` annotation in every template they're implemented in.
26+
```bicep
27+
@export()
28+
type subnetType = { ... }
29+
```
30+
31+
Doing so has the benefit that other (e.g., parent) modules can import them and as such reduce code duplication. Also, if the module itself is published, users of the Public Bicep Registry can import the types independently of the module itself. One example where this can be useful is a pattern module that may re-use the same interface when referencing a module from the registry.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
title: BCPNFR21 - User-defined types - Decorators
3+
url: /spec/BCPNFR21
4+
geekdocNav: true
5+
geekdocAlign: left
6+
geekdocAnchor: true
7+
type: posts
8+
tags: [
9+
Class-Resource, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
10+
Class-Pattern, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
11+
Type-NonFunctional, # SINGLE VALUE: this can be "Type-Functional" OR "Type-NonFunctional"
12+
Category-Inputs/Outputs, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
13+
Language-Bicep, # MULTIPLE VALUES: this can be "Language-Bicep" AND/OR "Language-Terraform"
14+
Severity-MUST, # SINGLE VALUE: this can be "Severity-MUST" OR "Severity-SHOULD" OR "Severity-MAY"
15+
Persona-Owner, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
16+
Persona-Contributor, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
17+
Lifecycle-BAU, # SINGLE VALUE: this can be "Lifecycle-Initial" OR "Lifecycle-BAU" OR "Lifecycle-EOL"
18+
Validation-TBD # SINGLE VALUE: this can be "Validation-Manual" OR "Validation-CI/Informational" OR "CI/Enforced"
19+
]
20+
priority: 11010
21+
---
22+
23+
#### ID: BCPNFR21 - User-defined types - Decorators
24+
25+
Similar to [BCPNFR9](/Azure-Verified-Modules/spec/BCPNFR9), User-defined types (UDTs) MUST implement [decorators](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/parameters#use-decorators) such as `description` & `secure` (if sensitive). This is true for every property of the UDT, as well as the UDT itself.
26+
27+
Further, User-defined types SHOULD implement decorators like `allowed`, `minValue`, `maxValue`, `minLength` & `maxLength` (and others if available) as they have a big positive impact on the module's usability.
28+
29+
```bicep
30+
@description('My type''s description.')
31+
type myType = {
32+
@description('Optional. The threshold of your resource.')
33+
@minValue(1)
34+
@maxValue(10)
35+
threshold: int?
36+
37+
@description('Required. The SKU of your resource.')
38+
sku: ('Basic' | 'Premium' | 'Standard')
39+
}
40+
```
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
title: BCPNFR9 - Inputs - Decorators
3+
url: /spec/BCPNFR9
4+
geekdocNav: true
5+
geekdocAlign: left
6+
geekdocAnchor: true
7+
type: posts
8+
tags: [
9+
Class-Resource, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
10+
Class-Pattern, # MULTIPLE VALUES: this can be "Class-Resource" AND/OR "Class-Pattern" AND/OR "Class-Utility"
11+
Type-NonFunctional, # SINGLE VALUE: this can be "Type-Functional" OR "Type-NonFunctional"
12+
Category-Inputs/Outputs, # SINGLE VALUE: this can be "Category-Testing" OR "Category-Telemetry" OR "Category-Contribution/Support" OR "Category-Documentation" OR "Category-CodeStyle" OR "Category-Naming/Composition" OR "Category-Inputs/Outputs" OR "Category-Release/Publishing"
13+
Language-Bicep, # MULTIPLE VALUES: this can be "Language-Bicep" AND/OR "Language-Terraform"
14+
Severity-MUST, # SINGLE VALUE: this can be "Severity-MUST" OR "Severity-SHOULD" OR "Severity-MAY"
15+
Persona-Owner, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
16+
Persona-Contributor, # MULTIPLE VALUES: this can be "Persona-Owner" AND/OR "Persona-Contributor"
17+
Lifecycle-BAU, # SINGLE VALUE: this can be "Lifecycle-Initial" OR "Lifecycle-BAU" OR "Lifecycle-EOL"
18+
Validation-TBD # SINGLE VALUE: this can be "Validation-Manual" OR "Validation-CI/Informational" OR "CI/Enforced"
19+
]
20+
priority: 11010
21+
---
22+
23+
#### ID: BCPNFR9 - Inputs - Decorators
24+
25+
Similar to [BCPNFR21](/Azure-Verified-Modules/spec/BCPNFR21), input parameters MUST implement [decorators](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/parameters#use-decorators) such as `description` & `secure` (if sensitive).
26+
27+
Further, input parameters SHOULD implement decorators like `allowed`, `minValue`, `maxValue`, `minLength` & `maxLength` (and others if available) as they have a big positive impact on the module's usability.
28+
29+
```bicep
30+
@description('Optional. The threshold of your resource.')
31+
@minValue(1)
32+
@maxValue(10)
33+
param threshold: int?
34+
@description('Required. The SKU of your resource.')
35+
@allowed([
36+
'Basic'
37+
'Premium'
38+
'Standard'
39+
])
40+
param sku string
41+
```

0 commit comments

Comments
 (0)