Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions sdk/provisioning/Azure.Provisioning/src/Resource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,14 @@ private protected void AssignParameter(object instance, string propertyName, Par
/// <param name="name">The name of the output.</param>
/// <param name="instance">The instance which contains the property for the output.</param>
/// <param name="propertyName">The property name to output.</param>
/// <param name="expression">The expression from the lambda</param>
/// <param name="isLiteral">Is the output literal.</param>
/// <param name="isSecure">Is the output secure.</param>
/// <returns>The <see cref="Output"/>.</returns>
/// <exception cref="ArgumentException">If the <paramref name="propertyName"/> is not found on the resources properties.</exception>
private protected Output AddOutput(string name, object instance, string propertyName, bool isLiteral = false, bool isSecure = false)
private protected Output AddOutput(string name, object instance, string propertyName, string expression, bool isLiteral = false, bool isSecure = false)
{
string? reference = GetReference(instance.GetType(), ResourceData.GetType(), propertyName, Name.ToCamelCase());

if (reference is null)
throw new ArgumentException(nameof(propertyName), $"{propertyName} was not found in the property tree for {ResourceData.GetType().Name}");
var result = new Output(name, reference, Scope, isLiteral, isSecure);
var result = new Output(name, $"{Name}.{expression}", Scope, isLiteral, isSecure);
Scope.AddOutput(result);
return result;
}
Expand Down
52 changes: 35 additions & 17 deletions sdk/provisioning/Azure.Provisioning/src/ResourceOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Linq;
using System.Linq.Expressions;
using Azure.Core;

Expand Down Expand Up @@ -46,7 +47,7 @@ protected Resource(IConstruct scope, Resource? parent, string resourceName, Reso
/// <exception cref="NotSupportedException"></exception>
public void AssignParameter(Expression<Func<T, object?>> propertySelector, Parameter parameter)
{
(object instance, string name) = EvaluateLambda(propertySelector);
(object instance, string name, string expression) = EvaluateLambda(propertySelector);
AssignParameter(instance, name, parameter);
}

Expand All @@ -60,47 +61,64 @@ public void AssignParameter(Expression<Func<T, object?>> propertySelector, Param
/// <returns>The <see cref="Output"/>.</returns>
public Output AddOutput(Expression<Func<T, object?>> propertySelector, string outputName, bool isLiteral = false, bool isSecure = false)
{
(object instance, string name) = EvaluateLambda(propertySelector);
return AddOutput(outputName, instance, name, isLiteral, isSecure);
(object instance, string name, string expression) = EvaluateLambda(propertySelector);

return AddOutput(outputName, instance, name, expression, isLiteral, isSecure);
}

private (object Instance, string PropertyName) EvaluateLambda(Expression<Func<T, object?>> propertySelector)
private (object Instance, string PropertyName, string Expression) EvaluateLambda(Expression<Func<T, object?>> propertySelector)
{
ParameterExpression? root = null;
Expression? body = null;
string? name = null;
string expression = string.Empty;
if (propertySelector is LambdaExpression lambda)
{
root = lambda.Parameters[0];
if (lambda.Body is MemberExpression member)
{
GetBicepExpression(member, ref expression);
body = member.Expression;
name = member.Member.Name;
}
else if (lambda.Body is UnaryExpression { NodeType: ExpressionType.Convert, Operand: MemberExpression member2 })
{
GetBicepExpression(member2, ref expression);
body = member2.Expression;
name = member2.Member.Name;
}
else if (lambda.Body is IndexExpression { Arguments.Count: 1 } indexer)
{
body = indexer.Object;
name = Expression.Lambda(indexer.Arguments[0], root).Compile().DynamicInvoke(Properties) as string;
}
else if (lambda.Body is MethodCallExpression { Method.Name: "get_Item", Arguments.Count: 1 } call)
else
{
body = call.Object;
name = Expression.Lambda(call.Arguments[0], root).Compile().DynamicInvoke(Properties) as string;
throw new InvalidOperationException("Invalid expression type.");
}
}

if (body is null || name is null || root is null)
else
{
throw new NotSupportedException();
throw new InvalidOperationException("Invalid expression type.");
}

object instance = Expression.Lambda(body, root).Compile().DynamicInvoke(Properties)!;
return (instance, name);
object instance = Expression.Lambda(body!, root).Compile().DynamicInvoke(Properties)!;
return (instance, name, expression);
}

private void GetBicepExpression(Expression expression, ref string result)
{
switch (expression)
{
case MemberExpression memberExpression:
var attrib = memberExpression.Member.GetCustomAttributes(false).FirstOrDefault(a => a.GetType().Name == "WirePathAttribute");
string nodeString = attrib?.ToString() ?? memberExpression.Member.Name.ToCamelCase();
result = result == string.Empty ? nodeString : $"{nodeString}.{result}";
if (memberExpression.Expression is not null)
{
GetBicepExpression(memberExpression.Expression, ref result);
}
break;
case ParameterExpression parameterExpression:
return; // we have reached the root
default:
throw new InvalidOperationException($"Unsupported expression type {expression.GetType().Name}");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public AppConfigurationStore(IConstruct scope, string name = "store", string ver
location: location ?? Environment.GetEnvironmentVariable("AZURE_LOCATION") ?? AzureLocation.WestUS,
skuName: "free"))
{
AddOutput(store => store.Endpoint, $"{Name}_endpoint");
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,15 @@ protected override string GetAzureName(IConstruct scope, string resourceName)
{
continue;
}
if (char.IsDigit(c) && !char.IsLower(c))
if (char.IsLetter(c))
{
stringBuilder.Append(char.ToLower(c));
stringBuilder.Append(char.ToLowerInvariant(c));
}
else
{
stringBuilder.Append(c);
}
}
stringBuilder.Append('-');
stringBuilder.Append(Guid.NewGuid().ToString("N"));

return stringBuilder.ToString(0, Math.Min(stringBuilder.Length, 24));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
'azd-env-name': 'TEST'
}
}

Expand All @@ -19,3 +19,5 @@ resource appConfigurationStore_sgecYnln3 'Microsoft.AppConfiguration/configurati
properties: {
}
}

output appConfigurationStore_sgecYnln3_endpoint string = appConfigurationStore_sgecYnln3.properties.endpoint
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
'azd-env-name': 'TEST'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
'azd-env-name': 'TEST'
}
}

resource storageAccount_SIHb28RDV 'Microsoft.Storage/storageAccounts@2022-09-01' = {
resource storageAccount_8fTaUIzOg 'Microsoft.Storage/storageAccounts@2022-09-01' = {
scope: resourceGroup_I6QNkoPsb
name: 'photoAcct-4f6f922c331347'
name: 'photoacct2af3506bedd4415'
location: 'westus'
sku: {
name: 'Premium_LRS'
Expand All @@ -21,8 +21,8 @@ resource storageAccount_SIHb28RDV 'Microsoft.Storage/storageAccounts@2022-09-01'
}
}

resource blobService_lyt6uqODr 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_SIHb28RDV
resource blobService_1iUqwyvnt 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_8fTaUIzOg
name: 'default'
properties: {
cors: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
'azd-env-name': 'TEST'
}
}

resource storageAccount_bhaja5ROZ 'Microsoft.Storage/storageAccounts@2022-09-01' = {
resource storageAccount_VpeHv8O32 'Microsoft.Storage/storageAccounts@2022-09-01' = {
scope: resourceGroup_I6QNkoPsb
name: 'photoAcct-96a1eefb1ac845'
name: 'photoacct414ad12f6b9c4a2'
location: 'westus'
sku: {
name: 'Premium_LRS'
Expand All @@ -21,8 +21,8 @@ resource storageAccount_bhaja5ROZ 'Microsoft.Storage/storageAccounts@2022-09-01'
}
}

resource blobService_PQ7aICJK8 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_bhaja5ROZ
resource blobService_6SRi2s6Pf 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_VpeHv8O32
name: 'default'
properties: {
cors: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
key: 'value'
'azd-env-name': 'TEST'
'key': 'value'
}
}

Expand Down Expand Up @@ -232,8 +232,8 @@ resource applicationSettingsResource_vEe46o8Zn 'Microsoft.Web/sites/config@2021-
parent: webSite_4pzZqR2OO
name: 'appsettings'
properties: {
SCM_DO_BUILD_DURING_DEPLOYMENT: 'False'
ENABLE_ORYX_BUILD: 'True'
'SCM_DO_BUILD_DURING_DEPLOYMENT': 'False'
'ENABLE_ORYX_BUILD': 'True'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
key: 'value'
'azd-env-name': 'TEST'
'key': 'value'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ resource applicationSettingsResource_vEe46o8Zn 'Microsoft.Web/sites/config@2021-
parent: webSite_4pzZqR2OO
name: 'appsettings'
properties: {
SCM_DO_BUILD_DURING_DEPLOYMENT: 'False'
ENABLE_ORYX_BUILD: 'True'
'SCM_DO_BUILD_DURING_DEPLOYMENT': 'False'
'ENABLE_ORYX_BUILD': 'True'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ resource resourceGroup_I6QNkoPsb 'Microsoft.Resources/resourceGroups@2023-07-01'
name: 'rg-TEST'
location: 'westus'
tags: {
azd-env-name: 'TEST'
key: 'value'
'azd-env-name': 'TEST'
'key': 'value'
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ resource applicationSettingsResource_vEe46o8Zn 'Microsoft.Web/sites/config@2021-
parent: webSite_4pzZqR2OO
name: 'appsettings'
properties: {
SCM_DO_BUILD_DURING_DEPLOYMENT: 'False'
ENABLE_ORYX_BUILD: 'True'
'SCM_DO_BUILD_DURING_DEPLOYMENT': 'False'
'ENABLE_ORYX_BUILD': 'True'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ resource keyVault_CRoMbemLF 'Microsoft.KeyVault/vaults@2023-02-01' = {
name: 'kv-TEST'
location: 'westus'
tags: {
key: 'value'
'key': 'value'
}
properties: {
tenantId: '00000000-0000-0000-0000-000000000000'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void WebSiteUsingL1()

WebSite frontEnd = new WebSite(infra, "frontEnd", appServicePlan, WebSiteRuntime.Node, "18-lts");
var frontEndPrincipalId = frontEnd.AddOutput(
website => website.Identity.PrincipalId,
website => website.Identity.PrincipalId, //Identity.PrincipalId
"SERVICE_API_IDENTITY_PRINCIPAL_ID",
isSecure: true);

Expand Down