diff --git a/Directory.Packages.props b/Directory.Packages.props index 93e12965cf..4b9bda200f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -25,7 +25,7 @@ - + diff --git a/playground/cdk/CdkSample.ApiService/CdkSample.ApiService.csproj b/playground/cdk/CdkSample.ApiService/CdkSample.ApiService.csproj index e458308746..493052dc3b 100644 --- a/playground/cdk/CdkSample.ApiService/CdkSample.ApiService.csproj +++ b/playground/cdk/CdkSample.ApiService/CdkSample.ApiService.csproj @@ -10,6 +10,7 @@ + diff --git a/playground/cdk/CdkSample.ApiService/Program.cs b/playground/cdk/CdkSample.ApiService/Program.cs index 23cd8a93ac..655fb82046 100644 --- a/playground/cdk/CdkSample.ApiService/Program.cs +++ b/playground/cdk/CdkSample.ApiService/Program.cs @@ -15,17 +15,19 @@ builder.AddSqlServerDbContext("sqldb"); builder.AddAzureKeyVaultClient("mykv"); builder.AddRedisClient("cache"); +builder.AddNpgsqlDbContext("pgsqldb"); var app = builder.Build(); -app.MapGet("/", async (BlobServiceClient bsc, SqlContext context, SecretClient sc, IConnectionMultiplexer connection) => +app.MapGet("/", async (BlobServiceClient bsc, SqlContext sqlContext, SecretClient sc, IConnectionMultiplexer connection, NpgsqlContext npgsqlContext) => { return new { redisEntries = await TestRedisAsync(connection), secretChecked = await TestSecretAsync(sc), blobFiles = await TestBlobStorageAsync(bsc), - sqlRows = await TestSqlServerAsync(context) + sqlRows = await TestSqlServerAsync(sqlContext), + npgsqlRows = await TestNpgsqlAsync(npgsqlContext), }; }); app.Run(); @@ -89,10 +91,28 @@ static async Task> TestSqlServerAsync(SqlContext context) return entries; } +static async Task> TestNpgsqlAsync(NpgsqlContext context) +{ + await context.Database.EnsureCreatedAsync(); + + var entry = new Entry(); + await context.Entries.AddAsync(entry); + await context.SaveChangesAsync(); + + var entries = await context.Entries.ToListAsync(); + return entries; +} + +public class NpgsqlContext(DbContextOptions options) : DbContext(options) +{ + public DbSet Entries { get; set; } +} + public class SqlContext(DbContextOptions options) : DbContext(options) { public DbSet Entries { get; set; } } + public class Entry { public Guid Id { get; set; } = Guid.NewGuid(); diff --git a/playground/cdk/CdkSample.AppHost/Program.cs b/playground/cdk/CdkSample.AppHost/Program.cs index 4ba95fd325..89252acb28 100644 --- a/playground/cdk/CdkSample.AppHost/Program.cs +++ b/playground/cdk/CdkSample.AppHost/Program.cs @@ -28,11 +28,20 @@ var cache = builder.AddRedis("cache").AsAzureRedisConstruct(); +var pgsqlAdministratorLogin = builder.AddParameter("pgsqlAdministratorLogin"); +var pgsqlAdministratorLoginPassword = builder.AddParameter("pgsqlAdministratorLoginPassword", secret: true); +var pgsqldb = builder.AddPostgres("pgsql") + .AsAzurePostgresFlexibleServerConstruct(pgsqlAdministratorLogin, pgsqlAdministratorLoginPassword) + .AddDatabase("pgsqldb"); + +var pgsql2 = builder.AddPostgres("pgsql2").AsAzurePostgresFlexibleServerConstruct(); + builder.AddProject("api") .WithReference(blobs) .WithReference(sqldb) .WithReference(keyvault) - .WithReference(cache); + .WithReference(cache) + .WithReference(pgsqldb); // This project is only added in playground projects to support development/debugging // of the dashboard. It is not required in end developer code. Comment out this code diff --git a/playground/cdk/CdkSample.AppHost/aspire-manifest.json b/playground/cdk/CdkSample.AppHost/aspire-manifest.json index 53f854fd7c..ea57b86c65 100644 --- a/playground/cdk/CdkSample.AppHost/aspire-manifest.json +++ b/playground/cdk/CdkSample.AppHost/aspire-manifest.json @@ -48,6 +48,17 @@ "params": { "principalId": "", "principalName": "" + }, + "inputs": { + "password": { + "type": "string", + "secret": true, + "default": { + "generate": { + "minLength": 10 + } + } + } } }, "sqldb": { @@ -73,6 +84,81 @@ "keyVaultName": "" } }, + "pgsqlAdministratorLogin": { + "type": "parameter.v0", + "value": "{pgsqlAdministratorLogin.inputs.value}", + "inputs": { + "value": { + "type": "string" + } + } + }, + "pgsqlAdministratorLoginPassword": { + "type": "parameter.v0", + "value": "{pgsqlAdministratorLoginPassword.inputs.value}", + "inputs": { + "value": { + "type": "string", + "secret": true + } + } + }, + "pgsql": { + "type": "azure.bicep.v0", + "connectionString": "{pgsql.secretOutputs.connectionString}", + "path": "pgsql.module.bicep", + "params": { + "principalId": "", + "keyVaultName": "", + "administratorLogin": "{pgsqlAdministratorLogin.value}", + "administratorLoginPassword": "{pgsqlAdministratorLoginPassword.value}" + }, + "inputs": { + "password": { + "type": "string", + "secret": true, + "default": { + "generate": { + "minLength": 10 + } + } + } + } + }, + "pgsqldb": { + "type": "value.v0", + "connectionString": "{pgsql.connectionString};Database=pgsqldb" + }, + "pgsql2": { + "type": "azure.bicep.v0", + "connectionString": "{pgsql2.secretOutputs.connectionString}", + "path": "pgsql2.module.bicep", + "params": { + "principalId": "", + "keyVaultName": "", + "administratorLogin": "{pgsql2.inputs.username}", + "administratorLoginPassword": "{pgsql2.inputs.password}" + }, + "inputs": { + "password": { + "type": "string", + "secret": true, + "default": { + "generate": { + "minLength": 10 + } + } + }, + "username": { + "type": "string", + "default": { + "generate": { + "minLength": 10 + } + } + } + } + }, "api": { "type": "project.v0", "path": "../CdkSample.ApiService/CdkSample.ApiService.csproj", @@ -82,7 +168,8 @@ "ConnectionStrings__blobs": "{blobs.connectionString}", "ConnectionStrings__sqldb": "{sqldb.connectionString}", "ConnectionStrings__mykv": "{mykv.connectionString}", - "ConnectionStrings__cache": "{cache.connectionString}" + "ConnectionStrings__cache": "{cache.connectionString}", + "ConnectionStrings__pgsqldb": "{pgsqldb.connectionString}" }, "bindings": { "http": { diff --git a/playground/cdk/CdkSample.AppHost/aspire.hosting.azure.bicep.postgres.bicep b/playground/cdk/CdkSample.AppHost/aspire.hosting.azure.bicep.postgres.bicep new file mode 100644 index 0000000000..77c57ac31c --- /dev/null +++ b/playground/cdk/CdkSample.AppHost/aspire.hosting.azure.bicep.postgres.bicep @@ -0,0 +1,68 @@ +param administratorLogin string +param keyVaultName string + +@secure() +param administratorLoginPassword string +param location string = resourceGroup().location +param serverName string +param serverEdition string = 'Burstable' +param skuSizeGB int = 32 +param dbInstanceType string = 'Standard_B1ms' +param haMode string = 'Disabled' +param availabilityZone string = '1' +param version string = '16' +param databases array = [] + +var resourceToken = uniqueString(resourceGroup().id) + +resource pgserver 'Microsoft.DBforPostgreSQL/flexibleServers@2021-06-01' = { + name: '${serverName}-${resourceToken}' + location: location + sku: { + name: dbInstanceType + tier: serverEdition + } + properties: { + version: version + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword + network: { + delegatedSubnetResourceId: null + privateDnsZoneArmResourceId: null + } + highAvailability: { + mode: haMode + } + storage: { + storageSizeGB: skuSizeGB + } + backup: { + backupRetentionDays: 7 + geoRedundantBackup: 'Disabled' + } + availabilityZone: availabilityZone + } + + resource firewallRules 'firewallRules@2021-06-01' = { + name: 'fw-pg-localdev' + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '255.255.255.255' + } + } + + resource database 'databases@2021-06-01' = [for name in databases: { + name: name + }] +} + +resource vault 'Microsoft.KeyVault/vaults@2023-07-01' existing = { + name: keyVaultName + + resource secret 'secrets@2023-07-01' = { + name: 'connectionString' + properties: { + value: 'Host=${pgserver.properties.fullyQualifiedDomainName};Username=${administratorLogin};Password=${administratorLoginPassword}' + } + } +} diff --git a/playground/cdk/CdkSample.AppHost/cache.module.bicep b/playground/cdk/CdkSample.AppHost/cache.module.bicep index 32e5fe0636..bbf78fdd25 100644 --- a/playground/cdk/CdkSample.AppHost/cache.module.bicep +++ b/playground/cdk/CdkSample.AppHost/cache.module.bicep @@ -1,13 +1,13 @@ targetScope = 'resourceGroup' @description('') -param principalId string +param location string = resourceGroup().location @description('') param keyVaultName string @description('') -param location string = resourceGroup().location +param principalId string resource keyVault_IeF8jZvXV 'Microsoft.KeyVault/vaults@2023-02-01' existing = { diff --git a/playground/cdk/CdkSample.AppHost/mykv.module.bicep b/playground/cdk/CdkSample.AppHost/mykv.module.bicep index aff9e9c3da..ae9a8310bf 100644 --- a/playground/cdk/CdkSample.AppHost/mykv.module.bicep +++ b/playground/cdk/CdkSample.AppHost/mykv.module.bicep @@ -1,13 +1,13 @@ targetScope = 'resourceGroup' @description('') -param principalId string +param location string = resourceGroup().location @description('') -param principalType string +param principalId string @description('') -param location string = resourceGroup().location +param principalType string @description('') param signaturesecret string diff --git a/playground/cdk/CdkSample.AppHost/pgsql.module.bicep b/playground/cdk/CdkSample.AppHost/pgsql.module.bicep new file mode 100644 index 0000000000..12a85ae3a7 --- /dev/null +++ b/playground/cdk/CdkSample.AppHost/pgsql.module.bicep @@ -0,0 +1,72 @@ +targetScope = 'resourceGroup' + +@description('') +param location string = resourceGroup().location + +@description('') +param administratorLogin string + +@secure() +@description('') +param administratorLoginPassword string + +@description('') +param principalId string + +@description('') +param keyVaultName string + + +resource keyVault_IeF8jZvXV 'Microsoft.KeyVault/vaults@2023-02-01' existing = { + name: keyVaultName +} + +resource postgreSqlFlexibleServer_UTKFzAL0U 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = { + name: toLower(take(concat('pgsql', uniqueString(resourceGroup().id)), 24)) + location: location + sku: { + name: 'Standard_B1ms' + tier: 'Burstable' + } + properties: { + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword + version: '16' + storage: { + storageSizeGB: 32 + } + backup: { + backupRetentionDays: 7 + geoRedundantBackup: 'Disabled' + } + highAvailability: { + mode: 'Disabled' + } + availabilityZone: '1' + } +} + +resource postgreSqlFirewallRule_TT2MuwakC 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2023-03-01-preview' = { + parent: postgreSqlFlexibleServer_UTKFzAL0U + name: 'AllowAllAzureIps' + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '0.0.0.0' + } +} + +resource postgreSqlFlexibleServerDatabase_MVhrhEeMJ 'Microsoft.DBforPostgreSQL/flexibleServers/databases@2022-12-01' = { + parent: postgreSqlFlexibleServer_UTKFzAL0U + name: 'pgsqldb' + properties: { + } +} + +resource keyVaultSecret_Ddsc3HjrA 'Microsoft.KeyVault/vaults/secrets@2023-02-01' = { + parent: keyVault_IeF8jZvXV + name: 'connectionString' + location: location + properties: { + value: 'Host=${postgreSqlFlexibleServer_UTKFzAL0U.properties.fullyQualifiedDomainName};Username=${administratorLogin};Password=${administratorLoginPassword}' + } +} diff --git a/playground/cdk/CdkSample.AppHost/pgsql2.module.bicep b/playground/cdk/CdkSample.AppHost/pgsql2.module.bicep new file mode 100644 index 0000000000..d1cc554dff --- /dev/null +++ b/playground/cdk/CdkSample.AppHost/pgsql2.module.bicep @@ -0,0 +1,65 @@ +targetScope = 'resourceGroup' + +@description('') +param location string = resourceGroup().location + +@description('') +param administratorLogin string + +@secure() +@description('') +param administratorLoginPassword string + +@description('') +param principalId string + +@description('') +param keyVaultName string + + +resource keyVault_IeF8jZvXV 'Microsoft.KeyVault/vaults@2023-02-01' existing = { + name: keyVaultName +} + +resource postgreSqlFlexibleServer_L4yCjMLWz 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = { + name: toLower(take(concat('pgsql2', uniqueString(resourceGroup().id)), 24)) + location: location + sku: { + name: 'Standard_B1ms' + tier: 'Burstable' + } + properties: { + administratorLogin: administratorLogin + administratorLoginPassword: administratorLoginPassword + version: '16' + storage: { + storageSizeGB: 32 + } + backup: { + backupRetentionDays: 7 + geoRedundantBackup: 'Disabled' + } + highAvailability: { + mode: 'Disabled' + } + availabilityZone: '1' + } +} + +resource postgreSqlFirewallRule_b2WDQTOKx 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2023-03-01-preview' = { + parent: postgreSqlFlexibleServer_L4yCjMLWz + name: 'AllowAllAzureIps' + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '0.0.0.0' + } +} + +resource keyVaultSecret_Ddsc3HjrA 'Microsoft.KeyVault/vaults/secrets@2023-02-01' = { + parent: keyVault_IeF8jZvXV + name: 'connectionString' + location: location + properties: { + value: 'Host=${postgreSqlFlexibleServer_L4yCjMLWz.properties.fullyQualifiedDomainName};Username=${administratorLogin};Password=${administratorLoginPassword}' + } +} diff --git a/playground/cdk/CdkSample.AppHost/sql.module.bicep b/playground/cdk/CdkSample.AppHost/sql.module.bicep index 3091ae52f5..401a32590e 100644 --- a/playground/cdk/CdkSample.AppHost/sql.module.bicep +++ b/playground/cdk/CdkSample.AppHost/sql.module.bicep @@ -1,13 +1,13 @@ targetScope = 'resourceGroup' @description('') -param principalId string +param location string = resourceGroup().location @description('') -param principalName string +param principalId string @description('') -param location string = resourceGroup().location +param principalName string resource sqlServer_l5O9GRsSn 'Microsoft.Sql/servers@2022-08-01-preview' = { diff --git a/playground/cdk/CdkSample.AppHost/storage.module.bicep b/playground/cdk/CdkSample.AppHost/storage.module.bicep index 877a07f703..44f00a68cd 100644 --- a/playground/cdk/CdkSample.AppHost/storage.module.bicep +++ b/playground/cdk/CdkSample.AppHost/storage.module.bicep @@ -1,13 +1,13 @@ targetScope = 'resourceGroup' @description('') -param principalId string +param location string = resourceGroup().location @description('') -param principalType string +param principalId string @description('') -param location string = resourceGroup().location +param principalType string @description('') param storagesku string diff --git a/src/Aspire.Hosting.Azure/AzurePostgresResource.cs b/src/Aspire.Hosting.Azure/AzurePostgresResource.cs index 987158fafa..c39ff98f5f 100644 --- a/src/Aspire.Hosting.Azure/AzurePostgresResource.cs +++ b/src/Aspire.Hosting.Azure/AzurePostgresResource.cs @@ -50,3 +50,50 @@ public class AzurePostgresResource(PostgresServerResource innerResource) : /// public override ResourceAnnotationCollection Annotations => innerResource.Annotations; } + +/// +/// Represents an resource for Azure Postgres Flexible Server. +/// +/// that this resource wraps. +/// Callback to configure construct. +public class AzurePostgresConstructResource(PostgresServerResource innerResource, Action configureConstruct) : + AzureConstructResource(innerResource.Name, configureConstruct), + IResourceWithConnectionString +{ + /// + /// Gets the "connectionString" secret output reference from the bicep template for the Azure Postgres Flexible Server. + /// + public BicepSecretOutputReference ConnectionString => new("connectionString", this); + + /// + /// Gets the connection template for the manifest for the Azure Postgres Flexible Server. + /// + public string ConnectionStringExpression => ConnectionString.ValueExpression; + + /// + /// Gets the connection string for the Azure Postgres Flexible Server. + /// + /// The connection string. + public string? GetConnectionString() => ConnectionString.Value; + + /// + /// Gets the connection string for the Azure Postgres Flexible Server. + /// + /// A to observe while waiting for the task to complete. + /// The connection string. + public async ValueTask GetConnectionStringAsync(CancellationToken cancellationToken = default) + { + if (ProvisioningTaskCompletionSource is not null) + { + await ProvisioningTaskCompletionSource.Task.WaitAsync(cancellationToken).ConfigureAwait(false); + } + + return GetConnectionString(); + } + + /// + public override string Name => innerResource.Name; + + /// + public override ResourceAnnotationCollection Annotations => innerResource.Annotations; +} diff --git a/src/Aspire.Hosting.Azure/Extensions/AzurePostgresExtensions.cs b/src/Aspire.Hosting.Azure/Extensions/AzurePostgresExtensions.cs index 305624100b..b3f7083977 100644 --- a/src/Aspire.Hosting.Azure/Extensions/AzurePostgresExtensions.cs +++ b/src/Aspire.Hosting.Azure/Extensions/AzurePostgresExtensions.cs @@ -3,6 +3,9 @@ using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; +using Azure.Provisioning; +using Azure.Provisioning.KeyVaults; +using Azure.Provisioning.PostgreSql; namespace Aspire.Hosting; @@ -83,10 +86,10 @@ private static IResourceBuilder ConfigureDefaults(this IR .WithParameter(AzureBicepResource.KnownParameters.KeyVaultName); } - private static IResourceBuilder WithLoginAndPassword( - this IResourceBuilder builder, + private static IResourceBuilder WithLoginAndPassword( + this IResourceBuilder builder, IResourceBuilder? administratorLogin, - IResourceBuilder? administratorLoginPassword) + IResourceBuilder? administratorLoginPassword) where T: AzureBicepResource { if (administratorLogin is null) { @@ -116,4 +119,124 @@ private static IResourceBuilder WithLoginAndPassword( return builder; } + + internal static IResourceBuilder PublishAsAzurePostgresFlexibleServerConstruct( + this IResourceBuilder builder, + IResourceBuilder? administratorLogin = null, + IResourceBuilder? administratorLoginPassword = null, + Action, ResourceModuleConstruct, PostgreSqlFlexibleServer>? configureResource = null, + bool useProvisioner = false) + { + var configureConstruct = (ResourceModuleConstruct construct) => + { + var administratorLogin = new Parameter("administratorLogin"); + var administratorLoginPassword = new Parameter("administratorLoginPassword", isSecure: true); + + var postgres = new PostgreSqlFlexibleServer(construct, administratorLogin, administratorLoginPassword, name: construct.Resource.Name); + postgres.AssignProperty(x => x.Sku.Name, "'Standard_B1ms'"); + postgres.AssignProperty(x => x.Sku.Tier, "'Burstable'"); + postgres.AssignProperty(x => x.Version, "'16'"); + postgres.AssignProperty(x => x.HighAvailability.Mode, "'Disabled'"); + postgres.AssignProperty(x => x.Storage.StorageSizeInGB, "32"); + postgres.AssignProperty(x => x.Backup.BackupRetentionDays, "7"); + postgres.AssignProperty(x => x.Backup.GeoRedundantBackup, "'Disabled'"); + postgres.AssignProperty(x => x.AvailabilityZone, "'1'"); + + // Opens access to all Azure services. + var azureServicesFirewallRule = new PostgreSqlFirewallRule(construct, "0.0.0.0", "0.0.0.0", postgres, "AllowAllAzureIps"); + + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + // Opens access to the Internet. + var openFirewallRule = new PostgreSqlFirewallRule(construct, "0.0.0.0", "255.255.255.255", postgres, "AllowAllIps"); + } + + List sqlDatabases = new List(); + foreach (var databaseNames in builder.Resource.Databases) + { + var databaseName = databaseNames.Value; + var pgsqlDatabase = new PostgreSqlFlexibleServerDatabase(construct, postgres, databaseName); + sqlDatabases.Add(pgsqlDatabase); + } + + var keyVault = KeyVault.FromExisting(construct, "keyVaultName"); + _ = new KeyVaultSecret(construct, "connectionString", postgres.GetConnectionString(administratorLogin, administratorLoginPassword)); + + if (configureResource != null) + { + var azureResource = (AzurePostgresConstructResource)construct.Resource; + var azureResourceBuilder = builder.ApplicationBuilder.CreateResourceBuilder(azureResource); + configureResource(azureResourceBuilder, construct, postgres); + } + }; + + var resource = new AzurePostgresConstructResource(builder.Resource, configureConstruct); + var resourceBuilder = builder.ApplicationBuilder.CreateResourceBuilder(resource) + .WithParameter(AzureBicepResource.KnownParameters.PrincipalId) + .WithParameter(AzureBicepResource.KnownParameters.KeyVaultName) + .WithManifestPublishingCallback(resource.WriteToManifest) + .WithLoginAndPassword(administratorLogin, administratorLoginPassword); + + if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) + { + resourceBuilder.WithParameter(AzureBicepResource.KnownParameters.PrincipalType); + } + + if (useProvisioner) + { + // Used to hold a reference to the azure surrogate for use with the provisioner. + builder.WithAnnotation(new AzureBicepResourceAnnotation(resource)); + builder.WithConnectionStringRedirection(resource); + + // Remove the container annotation so that DCP doesn't do anything with it. + if (builder.Resource.Annotations.OfType().SingleOrDefault() is { } containerAnnotation) + { + builder.Resource.Annotations.Remove(containerAnnotation); + } + } + + return builder; + } + + /// + /// Configures Postgres Server resource to be deployed as Azure Postgres Flexible Server. + /// + /// The builder. + /// + /// + /// Callback to configure Azure resource. + /// A reference to the builder. + public static IResourceBuilder PublishAsAzurePostgresFlexibleServerConstruct( + this IResourceBuilder builder, + IResourceBuilder? administratorLogin = null, + IResourceBuilder? administratorLoginPassword = null, + Action, ResourceModuleConstruct, PostgreSqlFlexibleServer>? configureResource = null) + { + return builder.PublishAsAzurePostgresFlexibleServerConstruct( + administratorLogin, + administratorLoginPassword, + configureResource, + useProvisioner: false); + } + + /// + /// Configures resource to use Azure for local development and when doing a deployment via the Azure Developer CLI. + /// + /// The builder. + /// + /// + /// Callback to configure Azure resource. + /// A reference to the builder. + public static IResourceBuilder AsAzurePostgresFlexibleServerConstruct( + this IResourceBuilder builder, + IResourceBuilder? administratorLogin = null, + IResourceBuilder? administratorLoginPassword = null, + Action, ResourceModuleConstruct, PostgreSqlFlexibleServer>? configureResource = null) + { + return builder.PublishAsAzurePostgresFlexibleServerConstruct( + administratorLogin, + administratorLoginPassword, + configureResource, + useProvisioner: true); + } } diff --git a/src/Aspire.Hosting.Azure/Extensions/AzureRedisExtensions.cs b/src/Aspire.Hosting.Azure/Extensions/AzureRedisExtensions.cs index 299cbb0a2f..4322dabf6c 100644 --- a/src/Aspire.Hosting.Azure/Extensions/AzureRedisExtensions.cs +++ b/src/Aspire.Hosting.Azure/Extensions/AzureRedisExtensions.cs @@ -119,10 +119,7 @@ internal static IResourceBuilder PublishAsAzureRedisConstruct(thi if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) { - if (builder.ApplicationBuilder.ExecutionContext.IsRunMode) - { - resourceBuilder.WithParameter(AzureBicepResource.KnownParameters.PrincipalType); - } + resourceBuilder.WithParameter(AzureBicepResource.KnownParameters.PrincipalType); } if (useProvisioner) diff --git a/src/Aspire.Hosting.Azure/Extensions/AzureSqlExtensions.cs b/src/Aspire.Hosting.Azure/Extensions/AzureSqlExtensions.cs index 9e8c9cf45e..09e3055e9b 100644 --- a/src/Aspire.Hosting.Azure/Extensions/AzureSqlExtensions.cs +++ b/src/Aspire.Hosting.Azure/Extensions/AzureSqlExtensions.cs @@ -95,7 +95,7 @@ internal static IResourceBuilder PublishAsAzureSqlDatab // the principalType. sqlServer.AssignProperty(x => x.Administrators.PrincipalType, construct.PrincipalTypeParameter); - var sqlFirewall = new SqlFirewallRule(construct); + var sqlFirewall = new SqlFirewallRule(construct, sqlServer); sqlFirewall.AssignProperty(x => x.StartIPAddress, "'0.0.0.0'"); sqlFirewall.AssignProperty(x => x.EndIPAddress, "'255.255.255.255'"); }