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
Original file line number Diff line number Diff line change
Expand Up @@ -38,57 +38,68 @@ public static IResourceBuilder<AzureApplicationInsightsResource> AddAzureApplica

var configureInfrastructure = (AzureResourceInfrastructure infrastructure) =>
{
var appTypeParameter = new ProvisioningParameter("applicationType", typeof(string))
{
Value = "web"
};
infrastructure.Add(appTypeParameter);
var appInsights = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure,
(identifier, name) =>
{
var resource = ApplicationInsightsComponent.FromExisting(identifier);
resource.Name = name;
return resource;
},
(infrastructure) =>
{
var appTypeParameter = new ProvisioningParameter("applicationType", typeof(string))
{
Value = "web"
};
infrastructure.Add(appTypeParameter);

var kindParameter = new ProvisioningParameter("kind", typeof(string))
{
Value = "web"
};
infrastructure.Add(kindParameter);
var kindParameter = new ProvisioningParameter("kind", typeof(string))
{
Value = "web"
};
infrastructure.Add(kindParameter);

var appInsights = new ApplicationInsightsComponent(infrastructure.AspireResource.GetBicepIdentifier())
{
ApplicationType = appTypeParameter,
Kind = kindParameter,
Tags = { { "aspire-resource-name", name } }
};
infrastructure.Add(appInsights);
var appInsights = new ApplicationInsightsComponent(infrastructure.AspireResource.GetBicepIdentifier())
{
ApplicationType = appTypeParameter,
Kind = kindParameter,
Tags = { { "aspire-resource-name", name } }
};

if (logAnalyticsWorkspace != null)
{
// If someone provides a workspace via the extension method we should use it.
appInsights.WorkspaceResourceId = logAnalyticsWorkspace.Resource.WorkspaceId.AsProvisioningParameter(infrastructure, AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId);
}
else if (builder.ExecutionContext.IsRunMode)
{
// ... otherwise if we are in run mode, the provisioner expects us to create one ourselves.
var autoInjectedLogAnalyticsWorkspaceName = $"law_{appInsights.BicepIdentifier}";
var autoInjectedLogAnalyticsWorkspace = new OperationalInsightsWorkspace(autoInjectedLogAnalyticsWorkspaceName)
{
Sku = new OperationalInsightsWorkspaceSku()
if (logAnalyticsWorkspace != null)
{
// If someone provides a workspace via the extension method we should use it.
appInsights.WorkspaceResourceId = logAnalyticsWorkspace.Resource.WorkspaceId.AsProvisioningParameter(infrastructure, AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId);
}
else if (builder.ExecutionContext.IsRunMode)
{
// ... otherwise if we are in run mode, the provisioner expects us to create one ourselves.
var autoInjectedLogAnalyticsWorkspaceName = $"law_{appInsights.BicepIdentifier}";
var autoInjectedLogAnalyticsWorkspace = new OperationalInsightsWorkspace(autoInjectedLogAnalyticsWorkspaceName)
{
Sku = new OperationalInsightsWorkspaceSku()
{
Name = OperationalInsightsWorkspaceSkuName.PerGB2018
},
Tags = { { "aspire-resource-name", autoInjectedLogAnalyticsWorkspaceName } }
};
infrastructure.Add(autoInjectedLogAnalyticsWorkspace);

// If the user does not supply a log analytics workspace of their own we still create a parameter on the Aspire
// side and the CDK side so that AZD can fill the value in with the one it generates.
appInsights.WorkspaceResourceId = autoInjectedLogAnalyticsWorkspace.Id;
}
else
{
Name = OperationalInsightsWorkspaceSkuName.PerGB2018
},
Tags = { { "aspire-resource-name", autoInjectedLogAnalyticsWorkspaceName } }
};
infrastructure.Add(autoInjectedLogAnalyticsWorkspace);
// If the user does not supply a log analytics workspace of their own, and we are in publish mode
// then we want AZD to provide one to us.
var logAnalyticsWorkspaceParameter = new ProvisioningParameter(AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId, typeof(string));
infrastructure.Add(logAnalyticsWorkspaceParameter);
appInsights.WorkspaceResourceId = logAnalyticsWorkspaceParameter;
}

// If the user does not supply a log analytics workspace of their own we still create a parameter on the Aspire
// side and the CDK side so that AZD can fill the value in with the one it generates.
appInsights.WorkspaceResourceId = autoInjectedLogAnalyticsWorkspace.Id;
}
else
{
// If the user does not supply a log analytics workspace of their own, and we are in publish mode
// then we want AZD to provide one to us.
var logAnalyticsWorkspaceParameter = new ProvisioningParameter(AzureBicepResource.KnownParameters.LogAnalyticsWorkspaceId, typeof(string));
infrastructure.Add(logAnalyticsWorkspaceParameter);
appInsights.WorkspaceResourceId = logAnalyticsWorkspaceParameter;
}
return appInsights;
});

infrastructure.Add(new ProvisioningOutput("appInsightsConnectionString", typeof(string)) { Value = appInsights.ConnectionString });
};
Expand Down
34 changes: 20 additions & 14 deletions src/Aspire.Hosting.Azure.CognitiveServices/AzureOpenAIExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,29 @@ public static IResourceBuilder<AzureOpenAIResource> AddAzureOpenAI(this IDistrib

var configureInfrastructure = (AzureResourceInfrastructure infrastructure) =>
{
var cogServicesAccount = new CognitiveServicesAccount(infrastructure.AspireResource.GetBicepIdentifier())
{
Kind = "OpenAI",
Sku = new CognitiveServicesSku()
var cogServicesAccount = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure,
(identifier, name) =>
{
Name = "S0"
var resource = CognitiveServicesAccount.FromExisting(identifier);
resource.Name = name;
return resource;
},
Properties = new CognitiveServicesAccountProperties()
(infrastructure) => new CognitiveServicesAccount(infrastructure.AspireResource.GetBicepIdentifier())
{
CustomSubDomainName = ToLower(Take(Concat(infrastructure.AspireResource.Name, GetUniqueString(GetResourceGroup().Id)), 24)),
PublicNetworkAccess = ServiceAccountPublicNetworkAccess.Enabled,
// Disable local auth for AOAI since managed identity is used
DisableLocalAuth = true
},
Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } }
};
infrastructure.Add(cogServicesAccount);
Kind = "OpenAI",
Sku = new CognitiveServicesSku()
{
Name = "S0"
},
Properties = new CognitiveServicesAccountProperties()
{
CustomSubDomainName = ToLower(Take(Concat(infrastructure.AspireResource.Name, GetUniqueString(GetResourceGroup().Id)), 24)),
PublicNetworkAccess = ServiceAccountPublicNetworkAccess.Enabled,
// Disable local auth for AOAI since managed identity is used
DisableLocalAuth = true
},
Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } }
});

infrastructure.Add(new ProvisioningOutput("connectionString", typeof(string))
{
Expand Down
32 changes: 18 additions & 14 deletions src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,26 +324,34 @@ public static IResourceBuilder<AzureCosmosDBResource> WithAccessKeyAuthenticatio
private static void ConfigureCosmosDBInfrastructure(AzureResourceInfrastructure infrastructure)
{
var azureResource = (AzureCosmosDBResource)infrastructure.AspireResource;
bool disableLocalAuth = !azureResource.UseAccessKeyAuthentication;

var cosmosAccount = new CosmosDBAccount(infrastructure.AspireResource.GetBicepIdentifier())
{
Kind = CosmosDBAccountKind.GlobalDocumentDB,
ConsistencyPolicy = new ConsistencyPolicy()
var cosmosAccount = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure,
(identifier, name) =>
{
DefaultConsistencyLevel = DefaultConsistencyLevel.Session
var resource = CosmosDBAccount.FromExisting(identifier);
resource.Name = name;
return resource;
},
DatabaseAccountOfferType = CosmosDBAccountOfferType.Standard,
Locations =
(infrastructure) => new CosmosDBAccount(infrastructure.AspireResource.GetBicepIdentifier())
{
Kind = CosmosDBAccountKind.GlobalDocumentDB,
ConsistencyPolicy = new ConsistencyPolicy()
{
DefaultConsistencyLevel = DefaultConsistencyLevel.Session
},
DatabaseAccountOfferType = CosmosDBAccountOfferType.Standard,
Locations =
{
new CosmosDBAccountLocation
{
LocationName = new IdentifierExpression("location"),
FailoverPriority = 0
}
},
Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } }
};
infrastructure.Add(cosmosAccount);
DisableLocalAuth = disableLocalAuth,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to this. Setting this directly on the resource instead of after the fact reads better as well.

Tags = { { "aspire-resource-name", infrastructure.AspireResource.Name } }
});

foreach (var database in azureResource.Databases)
{
Expand Down Expand Up @@ -376,8 +384,6 @@ private static void ConfigureCosmosDBInfrastructure(AzureResourceInfrastructure

if (azureResource.UseAccessKeyAuthentication)
{
cosmosAccount.DisableLocalAuth = false;

var kvNameParam = new ProvisioningParameter(AzureBicepResource.KnownParameters.KeyVaultName, typeof(string));
infrastructure.Add(kvNameParam);

Expand All @@ -398,8 +404,6 @@ private static void ConfigureCosmosDBInfrastructure(AzureResourceInfrastructure
}
else
{
cosmosAccount.DisableLocalAuth = true;

var principalTypeParameter = new ProvisioningParameter(AzureBicepResource.KnownParameters.PrincipalType, typeof(string));
infrastructure.Add(principalTypeParameter);

Expand Down
30 changes: 6 additions & 24 deletions src/Aspire.Hosting.Azure.Redis/AzureRedisExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,8 @@ private static CdkRedisResource CreateRedisResource(AzureResourceInfrastructure
return AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infrastructure,
(identifier, name) =>
{
var redisResource = (AzureRedisCacheResource)infrastructure.AspireResource;
var resource = new ExistingCdkRedisResource(identifier, !redisResource.UseAccessKeyAuthentication)
{
Name = name,
};
var resource = CdkRedisResource.FromExisting(identifier);
resource.Name = name;
return resource;
},
(infrastructure) => new CdkRedisResource(infrastructure.AspireResource.GetBicepIdentifier())
Expand Down Expand Up @@ -249,12 +246,12 @@ private static void ConfigureRedisInfrastructure(AzureResourceInfrastructure inf
}
else
{
redis.RedisConfiguration = new RedisCommonConfiguration()
{
IsAadEnabled = "true"
};
if (!redis.IsExistingResource)
{
redis.RedisConfiguration = new RedisCommonConfiguration()
{
IsAadEnabled = "true"
};
redis.IsAccessKeyAuthenticationDisabled = true;
}

Expand All @@ -277,19 +274,4 @@ private static void ConfigureRedisInfrastructure(AzureResourceInfrastructure inf
});
}
}

/// <remarks>
/// The provisioning APIs will mark the IsAccessKeyAuthenticationDisabled as `ReadOnly` after the
/// `IsExistingResource` property is set, making it impossible to configure the
/// `IsAccessKeyAuthenticationDisabled` property in our usual flows. This is a workaround to
/// allow us to set the property on existing resources.
/// </remarks>
private sealed class ExistingCdkRedisResource : CdkRedisResource
{
public ExistingCdkRedisResource(string bicepIdentifier, bool isAccessKeyAuthenticationDisabled, string? resourceVersion = null) : base(bicepIdentifier, resourceVersion)
{
IsAccessKeyAuthenticationDisabled = isAccessKeyAuthenticationDisabled;
IsExistingResource = true;
}
}
}
24 changes: 12 additions & 12 deletions tests/Aspire.Hosting.Azure.Tests/AzureBicepResourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -859,29 +859,29 @@ public async Task AddApplicationInsightsWithoutExplicitLawGetsDefaultLawParamete

param kind string = 'web'

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
name: take('appInsights-${uniqueString(resourceGroup().id)}', 260)
kind: kind
resource law_appInsights 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
name: take('lawappInsights-${uniqueString(resourceGroup().id)}', 63)
location: location
properties: {
Application_Type: applicationType
WorkspaceResourceId: law_appInsights.id
sku: {
name: 'PerGB2018'
}
}
tags: {
'aspire-resource-name': 'appInsights'
'aspire-resource-name': 'law_appInsights'
}
}

resource law_appInsights 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
name: take('lawappInsights-${uniqueString(resourceGroup().id)}', 63)
resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
name: take('appInsights-${uniqueString(resourceGroup().id)}', 260)
kind: kind
location: location
properties: {
sku: {
name: 'PerGB2018'
}
Application_Type: applicationType
WorkspaceResourceId: law_appInsights.id
}
tags: {
'aspire-resource-name': 'law_appInsights'
'aspire-resource-name': 'appInsights'
}
}

Expand Down
Loading