Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,9 @@ public static partial class BicepFunction
public static Azure.Provisioning.BicepValue<string> Concat(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.BicepValue<string> CreateGuid(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.Resources.ArmDeployment GetDeployment() { throw null; }
public static Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> GetExtensionResourceId(Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> resourceId, Azure.Provisioning.BicepValue<string> resourceType, params Azure.Provisioning.BicepValue<string>[] resourceNames) { throw null; }
public static Azure.Provisioning.Resources.ResourceGroup GetResourceGroup() { throw null; }
public static Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> GetResourceId(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.Resources.Subscription GetSubscription() { throw null; }
public static Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> GetSubscriptionResourceId(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.Resources.Tenant GetTenant() { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,9 @@ public static partial class BicepFunction
public static Azure.Provisioning.BicepValue<string> Concat(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.BicepValue<string> CreateGuid(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.Resources.ArmDeployment GetDeployment() { throw null; }
public static Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> GetExtensionResourceId(Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> resourceId, Azure.Provisioning.BicepValue<string> resourceType, params Azure.Provisioning.BicepValue<string>[] resourceNames) { throw null; }
public static Azure.Provisioning.Resources.ResourceGroup GetResourceGroup() { throw null; }
public static Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> GetResourceId(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.Resources.Subscription GetSubscription() { throw null; }
public static Azure.Provisioning.BicepValue<Azure.Core.ResourceIdentifier> GetSubscriptionResourceId(params Azure.Provisioning.BicepValue<string>[] values) { throw null; }
public static Azure.Provisioning.Resources.Tenant GetTenant() { throw null; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Linq;
using Azure.Core;
using Azure.Provisioning.Resources;
using Azure.Provisioning.Utilities;

namespace Azure.Provisioning.Expressions;

Expand Down Expand Up @@ -49,7 +48,10 @@ public static class BicepFunction
/// </remarks>
public static BicepValue<string> GetUniqueString(params BicepValue<string>[] values)
{
if (values.Length < 1) { throw new ArgumentException($"{nameof(GetUniqueString)} requires at least one value.", nameof(values)); }
if (values.Length < 1)
{
throw new ArgumentException($"{nameof(GetUniqueString)} requires at least one value.", nameof(values));
}
return BicepSyntax.Call("uniqueString", values.Select(v => v.Compile()).ToArray());
}

Expand Down Expand Up @@ -110,7 +112,10 @@ public static BicepValue<string> Take(BicepValue<string> text, BicepValue<int> s
/// </remarks>
public static BicepValue<string> CreateGuid(params BicepValue<string>[] values)
{
if (values.Length < 1) { throw new ArgumentException($"{nameof(CreateGuid)} requires at least one value.", nameof(values)); }
if (values.Length < 1)
{
throw new ArgumentException($"{nameof(CreateGuid)} requires at least one value.", nameof(values));
}
return BicepSyntax.Call("guid", values.Select(v => v.Compile()).ToArray());
}

Expand Down Expand Up @@ -143,12 +148,93 @@ public static BicepValue<string> CreateGuid(params BicepValue<string>[] values)
/// Bicep Functions Reference</see> for more.
/// </para>
/// </remarks>
/// <exception cref="ArgumentException">When <paramref name="values"/> is empty or contains fewer than two elements.</exception>
public static BicepValue<ResourceIdentifier> GetSubscriptionResourceId(params BicepValue<string>[] values)
{
if (values.Length < 2) { throw new ArgumentException($"{nameof(GetSubscriptionResourceId)} requires at least two values.", nameof(values)); }
if (values.Length < 2)
{
throw new ArgumentException($"{nameof(GetSubscriptionResourceId)} requires at least two values.", nameof(values));
}
return BicepSyntax.Call("subscriptionResourceId", values.Select(v => v.Compile()).ToArray());
}

/// <summary>
/// Returns the unique identifier of a resource. This represents the <c>resourceId</c>
/// Bicep function.
/// </summary>
/// <param name="values">
/// Optional subscription id, resource group name, resource types, and resource names used to
/// construct the resource ID. At least two values are required.
/// </param>
/// <returns>
/// The unique identifier of the resource.
/// </returns>
/// <remarks>
/// <para>
/// You use this function when the resource name is ambiguous or not provisioned within the same Bicep file.
/// The format of the returned identifier varies based on whether the deployment happens at the scope of
/// a resource group, subscription, management group, or tenant.
/// </para>
/// <para>
/// See the
/// <see href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-resource#resourceid">
/// Bicep Functions Reference</see> for more.
/// </para>
/// </remarks>
/// <exception cref="ArgumentException">When <paramref name="values"/> is empty or contains fewer than two elements.</exception>
public static BicepValue<ResourceIdentifier> GetResourceId(params BicepValue<string>[] values)
{
if (values.Length < 2)
{
throw new ArgumentException($"{nameof(GetResourceId)} requires at least two values.", nameof(values));
}
return BicepSyntax.Call("resourceId", values.Select(v => v.Compile()).ToArray());
}

/// <summary>
/// Returns the resource ID for an extension resource. An extension resource is a resource type
/// that is applied to another resource to add to its capabilities.
/// This represents the <c>extensionResourceId</c> Bicep function.
/// </summary>
/// <param name="resourceId">The resource ID to be extended on.</param>
/// <param name="resourceType">The resource type.</param>
/// <param name="resourceNames">The resource names.</param>
/// <returns>
/// The resource ID for an extension resource.
/// </returns>
/// <remarks>
/// <para>
/// The basic format of the resource ID returned by this function is:
/// <c>{scope}/providers/{extensionResourceProviderNamespace}/{extensionResourceType}/{extensionResourceName}</c>
/// The scope segment varies by the resource being extended.
/// When the extension resource is applied to a resource, the resource ID is returned in the following format:
/// <c>/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{baseResourceProviderNamespace}/{baseResourceType}/{baseResourceName}/providers/{extensionResourceProviderNamespace}/{extensionResourceType}/{extensionResourceName}</c>
/// When the extension resource is applied to a resource group, the format is:
/// <c>/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{extensionResourceProviderNamespace}/{extensionResourceType}/{extensionResourceName}</c>
/// When the extension resource is applied to a subscription, the format is:
/// <c>/subscriptions/{subscriptionId}/providers/{extensionResourceProviderNamespace}/{extensionResourceType}/{extensionResourceName}</c>
/// When the extension resource is applied to a management group, the format is:
/// <c>/providers/Microsoft.Management/managementGroups/{managementGroupName}/providers/{extensionResourceProviderNamespace}/{extensionResourceType}/{extensionResourceName}</c>
/// </para>
/// <para>
/// See the
/// <see href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-resource#extensionresourceid">
/// Bicep Functions Reference</see> for more.
/// </para>
/// </remarks>
/// <exception cref="ArgumentException">When <paramref name="resourceNames"/> is empty.</exception>
public static BicepValue<ResourceIdentifier> GetExtensionResourceId(
BicepValue<ResourceIdentifier> resourceId,
BicepValue<string> resourceType,
params BicepValue<string>[] resourceNames)
{
if (resourceNames.Length < 1)
{
throw new ArgumentException($"{nameof(GetExtensionResourceId)} requires at least one element for resourceNames parameter.", nameof(resourceNames));
}
return BicepSyntax.Call("extensionResourceId", [resourceId.Compile(), resourceType.Compile(), .. resourceNames.Select(v => v.Compile())]);
}

/// <summary>
/// Returns information about the current deployment operation. This
/// represents the <c>deployment</c> Bicep function.
Expand Down Expand Up @@ -305,7 +391,10 @@ public static BicepValue<string> ToUpper(BicepValue<object> value) =>
/// </remarks>
public static BicepValue<string> Concat(params BicepValue<string>[] values)
{
if (values.Length < 1) { throw new ArgumentException($"{nameof(Concat)} requires at least one value.", nameof(values)); }
if (values.Length < 1)
{
throw new ArgumentException($"{nameof(Concat)} requires at least one value.", nameof(values));
}
return BicepSyntax.Call("concat", values.Select(v => v.Compile()).ToArray());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Azure.Provisioning.Expressions;
using Azure.Provisioning.Storage;
using NUnit.Framework;

namespace Azure.Provisioning.Tests.Expressions.BicepFunctions;

public class ResourceIdFunctionsTests
{
[Test]
public void TestGetResourceId()
{
var id1 = BicepFunction.GetResourceId("00000000-0000-0000-0000-000000000000", "myResourceGroup", "Microsoft.Storage/storageAccounts", "myStorageAccount");
TestHelpers.AssertExpression("resourceId('00000000-0000-0000-0000-000000000000', 'myResourceGroup', 'Microsoft.Storage/storageAccounts', 'myStorageAccount')", id1);

var id2 = BicepFunction.GetResourceId("Microsoft.Network/virtualNetworks/subnets", "myVnet", "mySubnet");
TestHelpers.AssertExpression("resourceId('Microsoft.Network/virtualNetworks/subnets', 'myVnet', 'mySubnet')", id2);
}

[Test]
public void TestGetSubscriptionResourceId()
{
var id1 = BicepFunction.GetSubscriptionResourceId("Microsoft.Storage/storageAccounts", "myStorageAccount");
TestHelpers.AssertExpression("subscriptionResourceId('Microsoft.Storage/storageAccounts', 'myStorageAccount')", id1);

var id2 = BicepFunction.GetSubscriptionResourceId("00000000-0000-0000-0000-000000000000", "Microsoft.Resources/resourceGroups", "myResourceGroup");
TestHelpers.AssertExpression("subscriptionResourceId('00000000-0000-0000-0000-000000000000', 'Microsoft.Resources/resourceGroups', 'myResourceGroup')", id2);
}

[Test]
public void TestGetExtensionResourceId()
{
var scope = BicepFunction.GetResourceId("Microsoft.Compute/virtualMachines", "myVm");
var id1 = BicepFunction.GetExtensionResourceId(scope, "Microsoft.GuestConfigurations/configurations", "myConfiguration");
TestHelpers.AssertExpression("extensionResourceId(resourceId('Microsoft.Compute/virtualMachines', 'myVm'), 'Microsoft.GuestConfigurations/configurations', 'myConfiguration')", id1);

var storageAccount = new StorageAccount("account");
var id2 = BicepFunction.GetExtensionResourceId(storageAccount.Id, "Microsoft.Authorization/policyDefinitions", "myDef");
TestHelpers.AssertExpression("extensionResourceId(account.id, 'Microsoft.Authorization/policyDefinitions', 'myDef')", id2);
}
}