diff --git a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep index b6ccdd4b9de..d177f557f1a 100644 --- a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep +++ b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep @@ -34,7 +34,6 @@ resource script_sql1_db1 'Microsoft.Resources/deploymentScripts@2023-08-01' = { } kind: 'AzurePowerShell' properties: { - scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' azPowerShellVersion: '10.0' retentionInterval: 'PT1H' environmentVariables: [ @@ -59,5 +58,6 @@ resource script_sql1_db1 'Microsoft.Resources/deploymentScripts@2023-08-01' = { value: mi.properties.clientId } ] + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' } } \ No newline at end of file diff --git a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep index c2051080997..aa63d3640bd 100644 --- a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep +++ b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep @@ -34,7 +34,6 @@ resource script_sql2_db2 'Microsoft.Resources/deploymentScripts@2023-08-01' = { } kind: 'AzurePowerShell' properties: { - scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' azPowerShellVersion: '10.0' retentionInterval: 'PT1H' environmentVariables: [ @@ -59,5 +58,6 @@ resource script_sql2_db2 'Microsoft.Resources/deploymentScripts@2023-08-01' = { value: mi.properties.clientId } ] + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' } } \ No newline at end of file diff --git a/playground/SqlServerScript/AppHost1/Properties/launchSettings.json b/playground/SqlServerScript/AppHost1/Properties/launchSettings.json index 592a45ea228..8477b4bcbc7 100644 --- a/playground/SqlServerScript/AppHost1/Properties/launchSettings.json +++ b/playground/SqlServerScript/AppHost1/Properties/launchSettings.json @@ -24,6 +24,18 @@ "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19139", "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20080" } + }, + "generate-manifest": { + "commandName": "Project", + "commandLineArgs": "--publisher manifest --output-path aspire-manifest.json", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16175" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:15888" } } } diff --git a/playground/SqlServerScript/AppHost1/api1-identity.module.bicep b/playground/SqlServerScript/AppHost1/api1-identity.module.bicep index 944849b25f2..b84a714477c 100644 --- a/playground/SqlServerScript/AppHost1/api1-identity.module.bicep +++ b/playground/SqlServerScript/AppHost1/api1-identity.module.bicep @@ -1,7 +1,7 @@ @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location -resource api1_identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { +resource api1_identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { name: take('api1_identity-${uniqueString(resourceGroup().id)}', 128) location: location } @@ -12,4 +12,6 @@ output clientId string = api1_identity.properties.clientId output principalId string = api1_identity.properties.principalId -output principalName string = api1_identity.name \ No newline at end of file +output principalName string = api1_identity.name + +output name string = api1_identity.name \ No newline at end of file diff --git a/playground/SqlServerScript/AppHost1/api1-roles-mysqlserver.module.bicep b/playground/SqlServerScript/AppHost1/api1-roles-mysqlserver.module.bicep index 81e1dd89d7f..2a9e00f1632 100644 --- a/playground/SqlServerScript/AppHost1/api1-roles-mysqlserver.module.bicep +++ b/playground/SqlServerScript/AppHost1/api1-roles-mysqlserver.module.bicep @@ -9,15 +9,15 @@ param principalId string param principalName string -resource mysqlserver 'Microsoft.Sql/servers@2021-11-01' existing = { +resource mysqlserver 'Microsoft.Sql/servers@2023-08-01' existing = { name: mysqlserver_outputs_name } -resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { +resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = { name: mysqlserver_outputs_sqlserveradminname } -resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { +resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = { name: principalName } @@ -32,7 +32,6 @@ resource script_mysqlserver_todosdb 'Microsoft.Resources/deploymentScripts@2023- } kind: 'AzurePowerShell' properties: { - scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' azPowerShellVersion: '10.0' retentionInterval: 'PT1H' environmentVariables: [ @@ -57,5 +56,6 @@ resource script_mysqlserver_todosdb 'Microsoft.Resources/deploymentScripts@2023- value: mi.properties.clientId } ] + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' } } \ No newline at end of file diff --git a/playground/SqlServerScript/AppHost1/api1.module.bicep b/playground/SqlServerScript/AppHost1/api1.module.bicep index efeece62c88..67d8fe92bce 100644 --- a/playground/SqlServerScript/AppHost1/api1.module.bicep +++ b/playground/SqlServerScript/AppHost1/api1.module.bicep @@ -19,7 +19,7 @@ param mysqlserver_outputs_sqlserverfqdn string param api1_identity_outputs_clientid string -resource api1 'Microsoft.App/containerApps@2024-03-01' = { +resource api1 'Microsoft.App/containerApps@2025-02-02-preview' = { name: 'api1' location: location properties: { @@ -36,6 +36,11 @@ resource api1 'Microsoft.App/containerApps@2024-03-01' = { identity: env_outputs_azure_container_registry_managed_identity_id } ] + runtime: { + dotnet: { + autoConfigureDataProtection: true + } + } } environmentId: env_outputs_azure_container_apps_environment_id template: { diff --git a/playground/SqlServerScript/AppHost1/api2-identity.module.bicep b/playground/SqlServerScript/AppHost1/api2-identity.module.bicep index 2b19718d6dd..9afc26aa534 100644 --- a/playground/SqlServerScript/AppHost1/api2-identity.module.bicep +++ b/playground/SqlServerScript/AppHost1/api2-identity.module.bicep @@ -1,7 +1,7 @@ @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location -resource api2_identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { +resource api2_identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { name: take('api2_identity-${uniqueString(resourceGroup().id)}', 128) location: location } @@ -12,4 +12,6 @@ output clientId string = api2_identity.properties.clientId output principalId string = api2_identity.properties.principalId -output principalName string = api2_identity.name \ No newline at end of file +output principalName string = api2_identity.name + +output name string = api2_identity.name \ No newline at end of file diff --git a/playground/SqlServerScript/AppHost1/api2-roles-mysqlserver.module.bicep b/playground/SqlServerScript/AppHost1/api2-roles-mysqlserver.module.bicep index 81e1dd89d7f..2a9e00f1632 100644 --- a/playground/SqlServerScript/AppHost1/api2-roles-mysqlserver.module.bicep +++ b/playground/SqlServerScript/AppHost1/api2-roles-mysqlserver.module.bicep @@ -9,15 +9,15 @@ param principalId string param principalName string -resource mysqlserver 'Microsoft.Sql/servers@2021-11-01' existing = { +resource mysqlserver 'Microsoft.Sql/servers@2023-08-01' existing = { name: mysqlserver_outputs_name } -resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { +resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = { name: mysqlserver_outputs_sqlserveradminname } -resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { +resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = { name: principalName } @@ -32,7 +32,6 @@ resource script_mysqlserver_todosdb 'Microsoft.Resources/deploymentScripts@2023- } kind: 'AzurePowerShell' properties: { - scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' azPowerShellVersion: '10.0' retentionInterval: 'PT1H' environmentVariables: [ @@ -57,5 +56,6 @@ resource script_mysqlserver_todosdb 'Microsoft.Resources/deploymentScripts@2023- value: mi.properties.clientId } ] + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\r\n\$sqlDatabaseName = "\$env:DBNAME"\r\n\$principalName = "\$env:PRINCIPALNAME"\r\n\$id = "\$env:ID"\r\n\r\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\r\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\r\nImport-Module SqlServer\r\n\r\n\$sqlCmd = @"\r\nDECLARE @name SYSNAME = \'\$principalName\';\r\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\r\n\r\n-- Convert the guid to the right type\r\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\r\n\r\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\r\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\r\nEXEC (@cmd);\r\n\r\n-- Assign roles to the new user\r\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\r\nEXEC (@role1);\r\n\r\n"@\r\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\r\n\r\nWrite-Host \$sqlCmd\r\n\r\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\r\n\r\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' } } \ No newline at end of file diff --git a/playground/SqlServerScript/AppHost1/api2.module.bicep b/playground/SqlServerScript/AppHost1/api2.module.bicep index a7c5dc0712e..f19acf971c5 100644 --- a/playground/SqlServerScript/AppHost1/api2.module.bicep +++ b/playground/SqlServerScript/AppHost1/api2.module.bicep @@ -19,7 +19,7 @@ param mysqlserver_outputs_sqlserverfqdn string param api2_identity_outputs_clientid string -resource api2 'Microsoft.App/containerApps@2024-03-01' = { +resource api2 'Microsoft.App/containerApps@2025-02-02-preview' = { name: 'api2' location: location properties: { @@ -36,6 +36,11 @@ resource api2 'Microsoft.App/containerApps@2024-03-01' = { identity: env_outputs_azure_container_registry_managed_identity_id } ] + runtime: { + dotnet: { + autoConfigureDataProtection: true + } + } } environmentId: env_outputs_azure_container_apps_environment_id template: { diff --git a/playground/SqlServerScript/AppHost1/env.module.bicep b/playground/SqlServerScript/AppHost1/env.module.bicep index ec5ab38a4b6..d37612ff904 100644 --- a/playground/SqlServerScript/AppHost1/env.module.bicep +++ b/playground/SqlServerScript/AppHost1/env.module.bicep @@ -5,13 +5,13 @@ param userPrincipalId string param tags object = { } -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) location: location tags: tags } -resource env_acr 'Microsoft.ContainerRegistry/registries@2023-07-01' = { +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' = { name: take('envacr${uniqueString(resourceGroup().id)}', 50) location: location sku: { @@ -30,7 +30,7 @@ resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04 scope: env_acr } -resource env_law 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { +resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location properties: { @@ -41,7 +41,7 @@ resource env_law 'Microsoft.OperationalInsights/workspaces@2023-09-01' = { tags: tags } -resource env 'Microsoft.App/managedEnvironments@2024-03-01' = { +resource env 'Microsoft.App/managedEnvironments@2025-01-01' = { name: take('env${uniqueString(resourceGroup().id)}', 24) location: location properties: { @@ -70,19 +70,6 @@ resource aspireDashboard 'Microsoft.App/managedEnvironments/dotNetComponents@202 parent: env } -resource env_Contributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env.id, userPrincipalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')) - properties: { - principalId: userPrincipalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - } - scope: env -} - -output MANAGED_IDENTITY_NAME string = env_mi.name - -output MANAGED_IDENTITY_PRINCIPAL_ID string = env_mi.properties.principalId - output AZURE_LOG_ANALYTICS_WORKSPACE_NAME string = env_law.name output AZURE_LOG_ANALYTICS_WORKSPACE_ID string = env_law.id diff --git a/playground/SqlServerScript/AppHost1/mysqlserver.module.bicep b/playground/SqlServerScript/AppHost1/mysqlserver.module.bicep index 062e31cadfc..6db945598de 100644 --- a/playground/SqlServerScript/AppHost1/mysqlserver.module.bicep +++ b/playground/SqlServerScript/AppHost1/mysqlserver.module.bicep @@ -1,12 +1,12 @@ @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location -resource sqlServerAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { +resource sqlServerAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { name: take('mysqlserver-admin-${uniqueString(resourceGroup().id)}', 63) location: location } -resource mysqlserver 'Microsoft.Sql/servers@2021-11-01' = { +resource mysqlserver 'Microsoft.Sql/servers@2023-08-01' = { name: take('mysqlserver-${uniqueString(resourceGroup().id)}', 63) location: location properties: { @@ -26,7 +26,7 @@ resource mysqlserver 'Microsoft.Sql/servers@2021-11-01' = { } } -resource sqlFirewallRule_AllowAllAzureIps 'Microsoft.Sql/servers/firewallRules@2021-11-01' = { +resource sqlFirewallRule_AllowAllAzureIps 'Microsoft.Sql/servers/firewallRules@2023-08-01' = { name: 'AllowAllAzureIps' properties: { endIpAddress: '0.0.0.0' diff --git a/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs b/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs index 9f5e900057d..2349e17273b 100644 --- a/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs +++ b/src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs @@ -3,7 +3,6 @@ using Aspire.Hosting.ApplicationModel; using Azure.Provisioning; -using Azure.Provisioning.AppContainers; using Azure.Provisioning.Expressions; using Azure.Provisioning.Primitives; using Azure.Provisioning.Resources; @@ -160,9 +159,8 @@ public override void AddRoleAssignments(IAddRoleAssignmentsContext roleAssignmen var scriptResource = new SqlServerScriptProvisioningResource($"script_{uniqueScriptIdentifier}") { Name = BicepFunction.Take(BicepFunction.Interpolate($"script-{BicepFunction.GetUniqueString(this.GetBicepIdentifier(), roleAssignmentContext.PrincipalName, new StringLiteralExpression(resource), BicepFunction.GetResourceGroup().Id)}"), 24), - Kind = "AzurePowerShell", // List of supported versions: https://mcr.microsoft.com/v2/azuredeploymentscripts-powershell/tags/list - AZPowerShellVersion = "10.0" + AzPowerShellVersion = "10.0" }; // Run the script as the administrator @@ -172,11 +170,11 @@ public override void AddRoleAssignments(IAddRoleAssignmentsContext roleAssignmen scriptResource.Identity.UserAssignedIdentities[id] = new UserAssignedIdentityDetails(); // Script don't support Bicep expression, they need to be passed as ENVs - scriptResource.EnvironmentVariables.Add(new EnvironmentVariable() { Name = "DBNAME", Value = database }); - scriptResource.EnvironmentVariables.Add(new EnvironmentVariable() { Name = "DBSERVER", Value = sqlserver.FullyQualifiedDomainName }); - scriptResource.EnvironmentVariables.Add(new EnvironmentVariable() { Name = "PRINCIPALTYPE", Value = roleAssignmentContext.PrincipalType }); - scriptResource.EnvironmentVariables.Add(new EnvironmentVariable() { Name = "PRINCIPALNAME", Value = roleAssignmentContext.PrincipalName }); - scriptResource.EnvironmentVariables.Add(new EnvironmentVariable() { Name = "ID", Value = userId }); + scriptResource.EnvironmentVariables.Add(new ScriptEnvironmentVariable() { Name = "DBNAME", Value = database }); + scriptResource.EnvironmentVariables.Add(new ScriptEnvironmentVariable() { Name = "DBSERVER", Value = sqlserver.FullyQualifiedDomainName }); + scriptResource.EnvironmentVariables.Add(new ScriptEnvironmentVariable() { Name = "PRINCIPALTYPE", Value = roleAssignmentContext.PrincipalType }); + scriptResource.EnvironmentVariables.Add(new ScriptEnvironmentVariable() { Name = "PRINCIPALNAME", Value = roleAssignmentContext.PrincipalName }); + scriptResource.EnvironmentVariables.Add(new ScriptEnvironmentVariable() { Name = "ID", Value = userId }); scriptResource.ScriptContent = $$""" $sqlServerFqdn = "$env:DBSERVER" diff --git a/src/Aspire.Hosting.Azure.Sql/EnvironmentVariable.cs b/src/Aspire.Hosting.Azure.Sql/EnvironmentVariable.cs deleted file mode 100644 index b7e7f16e25c..00000000000 --- a/src/Aspire.Hosting.Azure.Sql/EnvironmentVariable.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -// Used to define environment variables in Bicep on a deployment script until it's available in the CDK --> -// This code was copied from https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/provisioning/Azure.Provisioning.AppContainers/src/Generated/Models/ContainerAppEnvironmentVariable.cs -// https://github.com/Azure/azure-sdk-for-net/issues/49283 --> - -// - -#nullable enable - -using Azure.Provisioning.Primitives; -using System; - -namespace Azure.Provisioning.AppContainers; - -/// -/// Environment variable. -/// -sealed class EnvironmentVariable : ProvisionableConstruct -{ - /// - /// Environment variable name. - /// - public BicepValue Name - { - get { Initialize(); return _name!; } - set { Initialize(); _name!.Assign(value); } - } - private BicepValue? _name; - - /// - /// Non-secret environment variable value. - /// - public BicepValue Value - { - get { Initialize(); return _value!; } - set { Initialize(); _value!.Assign(value); } - } - private BicepValue? _value; - - /// - /// Name of the secret from which to pull the environment - /// variable value. - /// - public BicepValue SecretRef - { - get { Initialize(); return _secretRef!; } - set { Initialize(); _secretRef!.Assign(value); } - } - private BicepValue? _secretRef; - - /// - /// Creates a new EnvironmentVariable. - /// - public EnvironmentVariable() - { - } - - /// - /// Define all the provisionable properties of - /// EnvironmentVariable. - /// - protected override void DefineProvisionableProperties() - { - base.DefineProvisionableProperties(); - _name = DefineProperty("Name", ["name"]); - _value = DefineProperty("Value", ["value"]); - _secretRef = DefineProperty("SecretRef", ["secretRef"]); - } -} diff --git a/src/Aspire.Hosting.Azure.Sql/SqlServerScriptProvisioningResource.cs b/src/Aspire.Hosting.Azure.Sql/SqlServerScriptProvisioningResource.cs index c851e9472dd..cfbc1b79f17 100644 --- a/src/Aspire.Hosting.Azure.Sql/SqlServerScriptProvisioningResource.cs +++ b/src/Aspire.Hosting.Azure.Sql/SqlServerScriptProvisioningResource.cs @@ -2,89 +2,37 @@ // The .NET Foundation licenses this file to you under the MIT license. using Azure.Provisioning; -using Azure.Provisioning.AppContainers; using Azure.Provisioning.Resources; namespace Aspire.Hosting.Azure; -// The existing class doesn't expose necessary properties like EnvironmentVariables and Kind. -// This class is a workaround until the Azure SDK for .NET exposes these properties in the CDK -// c.f. https://github.com/Azure/azure-sdk-for-net/issues/49283 +// The AzurePowerShellScript class doesn't work correctly. +// See https://github.com/Azure/azure-sdk-for-net/issues/51135 // Reference: https://learn.microsoft.com/azure/azure-resource-manager/templates/deployment-script-template -sealed class SqlServerScriptProvisioningResource : ArmDeploymentScript +sealed class SqlServerScriptProvisioningResource : AzurePowerShellScript { - private BicepValue? _scriptContent; - private BicepValue? _kind; - private BicepValue? _azCliVersion; - private BicepValue? _azPowerShellVersion; - private BicepValue? _retentionInterval; - private BicepList? _environmentVariables; + private BicepValue? _retentionIntervalOverride; public SqlServerScriptProvisioningResource(string bicepIdentifier) : base(bicepIdentifier) { RetentionInterval = TimeSpan.FromHours(1); - } - - /// - /// Type of the script. e.g., AzurePowerShell, . - /// - public BicepValue Kind - { - get { Initialize(); return _kind!; } - set { Initialize(); _kind!.Assign(value); } - } - - /// - /// Script body. - /// - public BicepValue ScriptContent - { - get { Initialize(); return _scriptContent!; } - set { Initialize(); _scriptContent!.Assign(value); } - } - - /// - /// Azure CLI module version to be used. - /// - public BicepValue AZCliVersion - { - get { Initialize(); return _azCliVersion!; } - set { Initialize(); _azCliVersion!.Assign(value); } - } - - /// - /// Azure CLI module version to be used. - /// - public BicepValue AZPowerShellVersion - { - get { Initialize(); return _azPowerShellVersion!; } - set { Initialize(); _azPowerShellVersion!.Assign(value); } + RetentionIntervalOverride = TimeSpan.FromHours(1); } /// /// Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P1D means one day). /// - public BicepValue RetentionInterval - { - get { Initialize(); return _retentionInterval!; } - set { Initialize(); _retentionInterval!.Assign(value); } - } - - public BicepList EnvironmentVariables + public BicepValue RetentionIntervalOverride { - get { Initialize(); return _environmentVariables!; } - set { Initialize(); _environmentVariables!.Assign(value); } + get { Initialize(); return _retentionIntervalOverride!; } + set { Initialize(); _retentionIntervalOverride!.Assign(value); } } protected override void DefineProvisionableProperties() { base.DefineProvisionableProperties(); - _kind = DefineProperty(nameof(Kind), ["kind"], isRequired: true); - _scriptContent = DefineProperty(nameof(ScriptContent), ["properties", "scriptContent"]); - _azCliVersion = DefineProperty(nameof(AZCliVersion), ["properties", "azCliVersion"]); - _azPowerShellVersion = DefineProperty(nameof(AZPowerShellVersion), ["properties", "azPowerShellVersion"]); - _retentionInterval = DefineProperty(nameof(RetentionInterval), ["properties", "retentionInterval"], format: "P"); - _environmentVariables = DefineListProperty(nameof(EnvironmentVariables), ["properties", "environmentVariables"]); + DefineProperty("Kind", ["kind"], defaultValue: "AzurePowerShell"); + _retentionIntervalOverride = DefineProperty(nameof(RetentionInterval), ["properties", "retentionInterval"], format: "P"); } } diff --git a/tests/Aspire.Hosting.Azure.Tests/RoleAssignmentTests.cs b/tests/Aspire.Hosting.Azure.Tests/RoleAssignmentTests.cs index e42cc051f66..a38f2378e47 100644 --- a/tests/Aspire.Hosting.Azure.Tests/RoleAssignmentTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/RoleAssignmentTests.cs @@ -168,16 +168,20 @@ public Task SqlSupport() return RoleAssignmentTest("sql", builder => { - var redis = builder.AddAzureSqlServer("sql"); + var sql = builder.AddAzureSqlServer("sql") + .AddDatabase("db"); builder.AddProject("api", launchProfileName: null) - .WithReference(redis); - }); + .WithReference(sql); + }, + // scrub new lines since the test needs to run on Windows and Linux, and the new lines are different. + s => s.Replace("\\r\\n", "\\n")); } private static async Task RoleAssignmentTest( string azureResourceName, - Action configureBuilder + Action configureBuilder, + Func? scrubLines = null ) { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); @@ -195,9 +199,15 @@ Action configureBuilder var (rolesManifest, rolesBicep) = await GetManifestWithBicep(projRoles); - await Verify(rolesManifest.ToString(), "json") + var verify = Verify(rolesManifest.ToString(), "json") .AppendContentAsFile(rolesBicep, "bicep"); - + + if (scrubLines is not null) + { + verify = verify.ScrubLinesWithReplace(scrubLines); + } + + await verify; } private static Task<(JsonNode ManifestNode, string BicepText)> GetManifestWithBicep(IResource resource) => diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/RoleAssignmentTests.SqlSupport.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/RoleAssignmentTests.SqlSupport.verified.bicep index 32c5dd88f26..dc67bbea64f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/RoleAssignmentTests.SqlSupport.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/RoleAssignmentTests.SqlSupport.verified.bicep @@ -1,4 +1,4 @@ -@description('The location for the resource(s) to be deployed.') +@description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location param sql_outputs_name string @@ -19,4 +19,43 @@ resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-1 resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = { name: principalName -} \ No newline at end of file +} + +resource script_sql_db 'Microsoft.Resources/deploymentScripts@2023-08-01' = { + name: take('script-${uniqueString('sql', principalName, 'db', resourceGroup().id)}', 24) + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${sqlServerAdmin.id}': { } + } + } + kind: 'AzurePowerShell' + properties: { + azPowerShellVersion: '10.0' + retentionInterval: 'PT1H' + environmentVariables: [ + { + name: 'DBNAME' + value: 'db' + } + { + name: 'DBSERVER' + value: sql.properties.fullyQualifiedDomainName + } + { + name: 'PRINCIPALTYPE' + value: 'ServicePrincipal' + } + { + name: 'PRINCIPALNAME' + value: principalName + } + { + name: 'ID' + value: mi.properties.clientId + } + ] + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\n\$sqlDatabaseName = "\$env:DBNAME"\n\$principalName = "\$env:PRINCIPALNAME"\n\$id = "\$env:ID"\n\n# Install SqlServer module - using specific version to avoid breaking changes in 22.4.5.1 (see https://github.com/dotnet/aspire/issues/9926)\nInstall-Module -Name SqlServer -RequiredVersion 22.3.0 -Force -AllowClobber -Scope CurrentUser\nImport-Module SqlServer\n\n\$sqlCmd = @"\nDECLARE @name SYSNAME = \'\$principalName\';\nDECLARE @id UNIQUEIDENTIFIER = \'\$id\';\n\n-- Convert the guid to the right type\nDECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);\n\n-- Construct command: CREATE USER [@name] WITH SID = @castId, TYPE = E;\nDECLARE @cmd NVARCHAR(MAX) = N\'CREATE USER [\' + @name + \'] WITH SID = \' + @castId + \', TYPE = E;\'\nEXEC (@cmd);\n\n-- Assign roles to the new user\nDECLARE @role1 NVARCHAR(MAX) = N\'ALTER ROLE db_owner ADD MEMBER [\' + @name + \']\';\nEXEC (@role1);\n\n"@\n# Note: the string terminator must not have whitespace before it, therefore it is not indented.\n\nWrite-Host \$sqlCmd\n\n\$connectionString = "Server=tcp:\${sqlServerFqdn},1433;Initial Catalog=\${sqlDatabaseName};Authentication=Active Directory Default;"\n\nInvoke-Sqlcmd -ConnectionString \$connectionString -Query \$sqlCmd' + } +}