You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: sdk/provisioning/Azure.Provisioning/CHANGELOG.md
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,21 +1,23 @@
1
1
# Release History
2
2
3
-
## 1.4.0-beta.2 (Unreleased)
3
+
## 1.4.0-beta.2 (2025-11-10)
4
4
5
5
### Features Added
6
6
7
+
- Added extension method `BicepValueExtensions.ToBicepExpression` which converts any `IBicepValue` into `BicepExpression` to build up complex expressions in bicep. For more details, please refer to the documents in `README`.
7
8
- Added `BicepFunction.GetResourceId` corresponding to bicep built-in function `resourceId`.
8
9
- Added `BicepFunction.GetExtensionResourceId` corresponding to bicep built-in function `extensionResourceId`.
9
10
10
-
### Breaking Changes
11
-
12
11
### Bugs Fixed
13
12
14
13
- Enabled the ability to assign expressions into a property with type of a `ProvisionableConstruct` via low level APIs.
15
14
- Fixed exception when output variable has a type of array or object.
15
+
- Fixed bug when indexing output list or dictionary, a `KeyNotFoundException` was always thrown. ([#48491](https://github.com/Azure/azure-sdk-for-net/issues/48491))
16
16
17
17
### Other Changes
18
18
19
+
- Now collection types (`BicepList<T>` and `BicepDictionary<T>`) would be able to force to be empty. ([#53346](https://github.com/Azure/azure-sdk-for-net/issues/53346))
This library allows you to specify your infrastructure in a declarative style using dotnet. You can then use `azd` to deploy your infrastructure to Azure directly without needing to write or maintain `bicep` or arm templates.
23
+
This library allows you to specify your infrastructure in a declarative style using `dotnet`. You can then use `azd` to deploy your infrastructure to Azure directly without needing to write or maintain `bicep` or `arm` templates.
24
+
25
+
### Important Usage Guidelines
26
+
27
+
**Declarative Design Pattern**: `Azure.Provisioning` is designed for declarative infrastructure definition. Each resource and construct instance should represent a single infrastructure component. Avoid reusing the same instance across multiple properties or locations, as this can lead to unexpected behavior in the generated Bicep templates.
StorageAccountstorage1=new(nameof(storage1)) { Sku=sharedSku }; // ❌ Bad
48
+
StorageAccountstorage2=new(nameof(storage2)) { Sku=sharedSku }; // ❌ Bad
49
+
```
50
+
51
+
This pattern can lead to incorrect Bicep expressions when you build expressions on them. Details could be found in [this section](#tobicepexpression-method).
52
+
53
+
</details>
54
+
55
+
**Safe Collection Access**: You can safely access any index in a `BicepList` or any key in a `BicepDictionary` without exceptions. This is **especially important when working with output properties** from Azure resources, where the actual data doesn't exist at design time but you need to create references for the generated Bicep template.
56
+
57
+
```C# Snippet:SafeCollectionAccess
58
+
// ✅ Accessing output properties safely - very common scenario
**`ProvisionableResource`** - Base class for Azure resources that provides resource-specific functionality. Users typically work with specific resource types like `StorageAccount`, `VirtualMachine`, `AppService`, etc. An instance of type `ProvisionableResource` corresponds to a resource statement in `bicep` language.
145
+
**`ProvisionableResource`** - Base class for Azure resources that provides resource-specific functionality. Users typically work with specific resource types like `StorageAccount`, `VirtualNetwork`, `WebSite`, etc. An instance of type `ProvisionableResource` corresponds to a resource statement in `bicep` language.
87
146
88
-
**`ProvisionableConstruct`** - Base class for infrastructure components that group related properties and resources. Most users will work with concrete implementations like `StorageAccountSku`, `VirtualNetworkIPConfiguration`, etc. An instance of type `ProvisionableConstruct` usually corresponds to an object definition statement in `bicep` language.
147
+
**`ProvisionableConstruct`** - Base class for infrastructure components that group related properties and resources. Most users will work with concrete implementations like `StorageAccountSku`, `VirtualNetworkEncryption`, etc. An instance of type `ProvisionableConstruct` usually corresponds to an object definition statement in `bicep` language.
89
148
90
149
Here's how you use the provided Azure resource classes:
The `ToBicepExpression()` extension method allows you to create references to resource properties and values for use in Bicep expressions. This is essential when you need to reference one resource's properties in another resource or build dynamic configuration strings.
// this would produce: 'AccountName=mystorageaccount;EndpointSuffix=core.windows.net'
213
+
```
214
+
215
+
Use `ToBicepExpression()` whenever you need to reference a resource property or value in Bicep expressions, function calls, or when building dynamic configuration values.
216
+
217
+
#### Important Notes
218
+
219
+
**NamedProvisionableConstruct Requirement**:
220
+
221
+
`ToBicepExpression()` requires that the value can be traced back through a chain of properties to a root `NamedProvisionableConstruct`. The method recursively traverses up the property ownership chain until it finds a `NamedProvisionableConstruct` at the root.
222
+
223
+
**Types that qualify as root `NamedProvisionableConstruct`:**
224
+
-**Azure resources** (like `StorageAccount`, `CognitiveServicesAccount`, etc.) - these inherit from `ProvisionableResource`
225
+
-**Infrastructure components** like:
226
+
-`ProvisioningParameter` - input parameters to your template
227
+
-`ProvisioningOutput` - output values from your template
228
+
-`ProvisioningVariable` - variables within your template
229
+
-`ModuleImport` - imported modules
230
+
231
+
**How the traversal works:**
232
+
- ✅ `storage.Name` - direct property of `StorageAccount` (a `NamedProvisionableConstruct`)
233
+
- ✅ `storage.Sku.Name` - `Sku` is a property of `StorageAccount`, `Name` is a property of `Sku`
234
+
- ✅ `storage.Properties.Encryption.Services.Blob.Enabled` - any depth is supported as long as it traces back to `StorageAccount`
235
+
- ✅ `storage.Tags[0]` - collection element where the collection (`Tags`) is a property of `StorageAccount`
236
+
- ✅ `storage.NetworkRuleSet.VirtualNetworkRules[0].Action` - element of a list property, then accessing a property of that element
237
+
- ❌ `new StorageSku().Name` - standalone `StorageSku` has no traceable path to a `NamedProvisionableConstruct`
238
+
239
+
This restriction exists because the generated Bicep expression needs an identifier to make it syntax correct (e.g., `storage.sku.name` or `param.someProperty.value`).
// ✅ Works - if you assign it to another NamedProvisionableConstruct first
254
+
storage.Sku=sku;
255
+
BicepExpressiongoodRef=storage.Sku.Name.ToBicepExpression(); // Works
256
+
```
257
+
258
+
**Why Instance Sharing Fails**:
259
+
260
+
As mentioned in the [Declarative Design Pattern](#important-usage-guidelines) section, sharing the same construct instance across multiple properties leads to problems with `ToBicepExpression()`. Here's the correct approach and what happens when you don't follow it:
120
261
121
-
// Reference properties in other resources
122
-
varappService=newAppService("myApp")
262
+
**The correct approach:**
263
+
264
+
```C# Snippet:InstanceSharingCorrect
265
+
// ✅ GOOD: Create separate instances with the same values
266
+
StorageAccountstorage1=new("storage1")
123
267
{
124
-
// Reference the storage account's connection string
// Now both storage accounts reference the SAME StorageSku object
291
+
// This creates ambiguity when building Bicep expressions:
292
+
293
+
// ❌ PROBLEM: Which storage account should this reference?
294
+
// storage1.sku.name or storage2.sku.name?
295
+
BicepExpressionskuNameRef=sharedSku.Name.ToBicepExpression(); // Confusing and unpredictable!
296
+
297
+
// The system can't determine whether this should generate:
298
+
// - "${storage1.sku.name}"
299
+
// - "${storage2.sku.name}"
300
+
// This leads to incorrect or unpredictable Bicep output.
301
+
```
302
+
303
+
**Key takeaway:** Each construct instance must have a single, unambiguous path back to its owning `NamedProvisionableConstruct`. Sharing instances breaks this requirement and makes Bicep reference generation impossible.
0 commit comments