diff --git a/.github/workflows/refresh-manifests.yml b/.github/workflows/refresh-manifests.yml new file mode 100644 index 00000000000..d34d1954a4e --- /dev/null +++ b/.github/workflows/refresh-manifests.yml @@ -0,0 +1,39 @@ +name: Refresh Manifests + +on: + workflow_dispatch: + schedule: + - cron: '0 16 * * *' # 8am PST (16:00 UTC) - same schedule as API review + +permissions: + contents: write + pull-requests: write + +jobs: + generate-and-pr: + runs-on: windows-latest # Using Windows because the script uses PowerShell and build.cmd + if: ${{ github.repository_owner == 'dotnet' }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup .NET SDK + uses: actions/setup-dotnet@v4 + with: + global-json-file: global.json + + - name: Run RefreshManifests Script + shell: pwsh + run: | + ./eng/refreshManifests.ps1 + + - name: Create or update pull request + uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: update-manifests + base: main + labels: | + area-app-model + area-engineering-systems + title: "[Automated] Update Manifests" + body: "Auto-generated update to refresh the manifests. This PR will be updated automatically if new changes are detected." \ No newline at end of file diff --git a/eng/refreshManifests.ps1 b/eng/refreshManifests.ps1 index 581b7e0591a..7efbf9dda4b 100644 --- a/eng/refreshManifests.ps1 +++ b/eng/refreshManifests.ps1 @@ -1,2 +1,47 @@ -..\build.cmd -get-childitem ..\playground\*AppHost.csproj -Recurse | % { "Generating Manifest for: $_"; dotnet run --no-build --project $_.FullName --launch-profile generate-manifest } \ No newline at end of file +#!/usr/bin/env pwsh + +# Get the script directory +$scriptDir = $PSScriptRoot +$repoRoot = Split-Path -Parent $scriptDir + +# Determine which build script to use based on OS +if ($IsWindows -or $env:OS -eq "Windows_NT") { + & "$repoRoot/build.cmd" +} else { + & "$repoRoot/build.sh" +} + +# Find all AppHost projects in the playground directory +$playgroundDir = Join-Path -Path $repoRoot -ChildPath "playground" + +if (Test-Path $playgroundDir) { + Get-ChildItem -Path $playgroundDir -Filter "*AppHost.csproj" -Recurse | ForEach-Object { + # Check if the project has a launchSettings.json file with a generate-manifest profile + $projectDir = Split-Path -Parent $_.FullName + $launchSettingsPath = Join-Path -Path $projectDir -ChildPath "Properties" -AdditionalChildPath "launchSettings.json" + $hasManifestProfile = $false + + if (Test-Path $launchSettingsPath) { + try { + $launchSettings = Get-Content -Raw -Path $launchSettingsPath | ConvertFrom-Json + if ($launchSettings.profiles -and $launchSettings.profiles.'generate-manifest') { + $hasManifestProfile = $true + } + } + catch { + Write-Warning "Failed to read or parse launch settings for $_" + } + } + + if ($hasManifestProfile) { + Write-Host "Generating Manifest for: $_" + dotnet run --no-build --project $_.FullName --launch-profile generate-manifest + } + else { + Write-Warning "Skipping $_ - no generate-manifest profile found" + } + } +} +else { + Write-Error "Playground directory not found at: $playgroundDir" +} \ No newline at end of file diff --git a/playground/AzureContainerApps/AzureContainerApps.AppHost/infra.module.bicep b/playground/AzureContainerApps/AzureContainerApps.AppHost/infra.module.bicep index f3755339344..2aa69ebbcd8 100644 --- a/playground/AzureContainerApps/AzureContainerApps.AppHost/infra.module.bicep +++ b/playground/AzureContainerApps/AzureContainerApps.AppHost/infra.module.bicep @@ -70,15 +70,6 @@ resource aspireDashboard 'Microsoft.App/managedEnvironments/dotNetComponents@202 parent: infra } -resource infra_Contributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(infra.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: infra -} - resource infra_storageVolume 'Microsoft.Storage/storageAccounts@2024-01-01' = { name: take('infrastoragevolume${uniqueString(resourceGroup().id)}', 24) kind: 'StorageV2' diff --git a/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/aspire-manifest.json b/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/aspire-manifest.json index 2262527dbea..d759a8e7c9f 100644 --- a/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/aspire-manifest.json +++ b/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/aspire-manifest.json @@ -13,6 +13,10 @@ "type": "value.v0", "connectionString": "{storage.outputs.blobEndpoint}" }, + "myblobcontainer": { + "type": "value.v0", + "connectionString": "Endpoint={storage.outputs.blobEndpoint};ContainerName=myblobcontainer" + }, "eventhubs": { "type": "azure.bicep.v0", "connectionString": "{eventhubs.outputs.eventHubsEndpoint}", @@ -76,6 +80,7 @@ "Aspire__Azure__Messaging__EventHubs__EventProcessorClient__myhub__EventHubName": "myhub", "Aspire__Azure__Messaging__EventHubs__PartitionReceiver__myhub__EventHubName": "myhub", "Aspire__Azure__Messaging__EventHubs__EventHubBufferedProducerClient__myhub__EventHubName": "myhub", + "ConnectionStrings__myblobcontainer": "{myblobcontainer.connectionString}", "messaging__fullyQualifiedNamespace": "{messaging.outputs.serviceBusEndpoint}", "Aspire__Azure__Messaging__ServiceBus__messaging__FullyQualifiedNamespace": "{messaging.outputs.serviceBusEndpoint}", "cosmosdb__accountEndpoint": "{cosmosdb.outputs.connectionString}", @@ -179,4 +184,4 @@ } } } -} +} \ No newline at end of file diff --git a/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/storage.module.bicep b/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/storage.module.bicep index 5a375968ca9..3e6fc314ca4 100644 --- a/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/storage.module.bicep +++ b/playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/storage.module.bicep @@ -26,6 +26,11 @@ resource blobs 'Microsoft.Storage/storageAccounts/blobServices@2024-01-01' = { parent: storage } +resource myblobcontainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2024-01-01' = { + name: 'myblobcontainer' + parent: blobs +} + output blobEndpoint string = storage.properties.primaryEndpoints.blob output queueEndpoint string = storage.properties.primaryEndpoints.queue diff --git a/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/aspire-manifest.json b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/aspire-manifest.json index 9a3b06ec922..d26c582b3e8 100644 --- a/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/aspire-manifest.json +++ b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/aspire-manifest.json @@ -9,10 +9,30 @@ "type": "value.v0", "connectionString": "{storage.outputs.blobEndpoint}" }, + "mycontainer1": { + "type": "value.v0", + "connectionString": "Endpoint={storage.outputs.blobEndpoint};ContainerName=test-container-1" + }, + "mycontainer2": { + "type": "value.v0", + "connectionString": "Endpoint={storage.outputs.blobEndpoint};ContainerName=test-container-2" + }, "queues": { "type": "value.v0", "connectionString": "{storage.outputs.queueEndpoint}" }, + "storage2": { + "type": "azure.bicep.v0", + "path": "storage2.module.bicep" + }, + "blobs2": { + "type": "value.v0", + "connectionString": "{storage2.outputs.blobEndpoint}" + }, + "foocontainer": { + "type": "value.v0", + "connectionString": "Endpoint={storage2.outputs.blobEndpoint};ContainerName=foo-container" + }, "api": { "type": "project.v0", "path": "../AzureStorageEndToEnd.ApiService/AzureStorageEndToEnd.ApiService.csproj", @@ -23,6 +43,7 @@ "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", "HTTP_PORTS": "{api.bindings.http.targetPort}", "ConnectionStrings__blobs": "{blobs.connectionString}", + "ConnectionStrings__foocontainer": "{foocontainer.connectionString}", "ConnectionStrings__queues": "{queues.connectionString}" }, "bindings": { @@ -48,6 +69,15 @@ "principalType": "", "principalId": "" } + }, + "storage2-roles": { + "type": "azure.bicep.v0", + "path": "storage2-roles.module.bicep", + "params": { + "storage2_outputs_name": "{storage2.outputs.name}", + "principalType": "", + "principalId": "" + } } } } \ No newline at end of file diff --git a/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage.module.bicep b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage.module.bicep index 5a375968ca9..a35c22a7293 100644 --- a/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage.module.bicep +++ b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage.module.bicep @@ -26,6 +26,16 @@ resource blobs 'Microsoft.Storage/storageAccounts/blobServices@2024-01-01' = { parent: storage } +resource mycontainer1 'Microsoft.Storage/storageAccounts/blobServices/containers@2024-01-01' = { + name: 'test-container-1' + parent: blobs +} + +resource mycontainer2 'Microsoft.Storage/storageAccounts/blobServices/containers@2024-01-01' = { + name: 'test-container-2' + parent: blobs +} + output blobEndpoint string = storage.properties.primaryEndpoints.blob output queueEndpoint string = storage.properties.primaryEndpoints.queue diff --git a/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage2-roles.module.bicep b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage2-roles.module.bicep new file mode 100644 index 00000000000..783aa7109ef --- /dev/null +++ b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage2-roles.module.bicep @@ -0,0 +1,42 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param storage2_outputs_name string + +param principalType string + +param principalId string + +resource storage2 'Microsoft.Storage/storageAccounts@2024-01-01' existing = { + name: storage2_outputs_name +} + +resource storage2_StorageBlobDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storage2.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') + principalType: principalType + } + scope: storage2 +} + +resource storage2_StorageTableDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storage2.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3') + principalType: principalType + } + scope: storage2 +} + +resource storage2_StorageQueueDataContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storage2.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '974c5e8b-45b9-4653-ba55-5f855dd0fb88') + principalType: principalType + } + scope: storage2 +} \ No newline at end of file diff --git a/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage2.module.bicep b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage2.module.bicep new file mode 100644 index 00000000000..32838ffeb1c --- /dev/null +++ b/playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/storage2.module.bicep @@ -0,0 +1,40 @@ +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource storage2 'Microsoft.Storage/storageAccounts@2024-01-01' = { + name: take('storage2${uniqueString(resourceGroup().id)}', 24) + kind: 'StorageV2' + location: location + sku: { + name: 'Standard_GRS' + } + properties: { + accessTier: 'Hot' + allowSharedKeyAccess: false + minimumTlsVersion: 'TLS1_2' + networkAcls: { + defaultAction: 'Allow' + } + } + tags: { + 'aspire-resource-name': 'storage2' + } +} + +resource blobs 'Microsoft.Storage/storageAccounts/blobServices@2024-01-01' = { + name: 'default' + parent: storage2 +} + +resource foocontainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2024-01-01' = { + name: 'foo-container' + parent: blobs +} + +output blobEndpoint string = storage2.properties.primaryEndpoints.blob + +output queueEndpoint string = storage2.properties.primaryEndpoints.queue + +output tableEndpoint string = storage2.properties.primaryEndpoints.table + +output name string = storage2.name \ No newline at end of file diff --git a/playground/CustomResources/CustomResources.AppHost/aspire-manifest.json b/playground/CustomResources/CustomResources.AppHost/aspire-manifest.json index 9f280e133e2..65fcbce8d81 100644 --- a/playground/CustomResources/CustomResources.AppHost/aspire-manifest.json +++ b/playground/CustomResources/CustomResources.AppHost/aspire-manifest.json @@ -1,6 +1,12 @@ { "$schema": "https://json.schemastore.org/aspire-8.0.json", "resources": { + "talking-clock-tick-hand": { + "error": "This resource does not support generation in the manifest." + }, + "talking-clock-tock-hand": { + "error": "This resource does not support generation in the manifest." + }, "p0": { "type": "parameter.v0", "value": "{p0.inputs.value}", diff --git a/playground/OracleEndToEnd/OracleEndToEnd.AppHost/aspire-manifest.json b/playground/OracleEndToEnd/OracleEndToEnd.AppHost/aspire-manifest.json index b2869d211ad..a8072534c49 100644 --- a/playground/OracleEndToEnd/OracleEndToEnd.AppHost/aspire-manifest.json +++ b/playground/OracleEndToEnd/OracleEndToEnd.AppHost/aspire-manifest.json @@ -4,7 +4,7 @@ "oracle": { "type": "container.v0", "connectionString": "user id=system;password={oracle-password.value};data source={oracle.bindings.tcp.host}:{oracle.bindings.tcp.port}", - "image": "container-registry.oracle.com/database/free:23.6.0.0", + "image": "container-registry.oracle.com/database/free:23.7.0.0", "env": { "ORACLE_PWD": "{oracle-password.value}" }, diff --git a/playground/Qdrant/Qdrant.AppHost/aspire-manifest.json b/playground/Qdrant/Qdrant.AppHost/aspire-manifest.json index 1763c2cf48f..7a0831444f3 100644 --- a/playground/Qdrant/Qdrant.AppHost/aspire-manifest.json +++ b/playground/Qdrant/Qdrant.AppHost/aspire-manifest.json @@ -4,7 +4,7 @@ "qdrant": { "type": "container.v0", "connectionString": "Endpoint={qdrant.bindings.grpc.url};Key={qdrant-Key.value}", - "image": "docker.io/qdrant/qdrant:v1.13.4", + "image": "docker.io/qdrant/qdrant:v1.13.6", "volumes": [ { "name": "qdrant-data", diff --git a/playground/Redis/Redis.AppHost/aspire-manifest.json b/playground/Redis/Redis.AppHost/aspire-manifest.json index c90e1593b07..ea1db2ade99 100644 --- a/playground/Redis/Redis.AppHost/aspire-manifest.json +++ b/playground/Redis/Redis.AppHost/aspire-manifest.json @@ -36,7 +36,7 @@ "entrypoint": "/bin/sh", "args": [ "-c", - "/app/GarnetServer --auth Password --password $GARNET_PASSWORD --checkpointdir /data/checkpoints --recover --aof --aof-commit-freq 60000" + "/app/GarnetServer --protected-mode no --auth Password --password $GARNET_PASSWORD --checkpointdir /data/checkpoints --recover --aof --aof-commit-freq 60000" ], "volumes": [ { diff --git a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep index 84cbbacc154..6efe9992787 100644 --- a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep +++ b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql1-roles.module.bicep @@ -34,7 +34,7 @@ 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\r\nInstall-Module -Name SqlServer -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' + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\n\$sqlDatabaseName = "\$env:DBNAME"\n\$principalName = "\$env:PRINCIPALNAME"\n\$id = "\$env:ID"\n\n# Install SqlServer module\nInstall-Module -Name SqlServer -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' azPowerShellVersion: '10.0' retentionInterval: 'PT1H' environmentVariables: [ diff --git a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep index 63d872601f1..7abb05dd2b7 100644 --- a/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep +++ b/playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/sql2-roles.module.bicep @@ -34,7 +34,7 @@ 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\r\nInstall-Module -Name SqlServer -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' + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\n\$sqlDatabaseName = "\$env:DBNAME"\n\$principalName = "\$env:PRINCIPALNAME"\n\$id = "\$env:ID"\n\n# Install SqlServer module\nInstall-Module -Name SqlServer -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' azPowerShellVersion: '10.0' retentionInterval: 'PT1H' environmentVariables: [ diff --git a/playground/Stress/Stress.AppHost/aspire-manifest.json b/playground/Stress/Stress.AppHost/aspire-manifest.json index ed1ab02bec7..5faf1b1a086 100644 --- a/playground/Stress/Stress.AppHost/aspire-manifest.json +++ b/playground/Stress/Stress.AppHost/aspire-manifest.json @@ -1,6 +1,16 @@ { "$schema": "https://json.schemastore.org/aspire-8.0.json", "resources": { + "testParameterResource": { + "type": "parameter.v0", + "value": "{testParameterResource.inputs.value}", + "inputs": { + "value": { + "type": "string", + "secret": true + } + } + }, "stress-apiservice": { "type": "project.v0", "path": "../Stress.ApiService/Stress.ApiService.csproj", @@ -10,7 +20,10 @@ "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory", "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", "HTTP_PORTS": "{stress-apiservice.bindings.http.targetPort};{stress-apiservice.bindings.http-5181.targetPort};{stress-apiservice.bindings.http-5182.targetPort};{stress-apiservice.bindings.http-5183.targetPort};{stress-apiservice.bindings.http-5184.targetPort};{stress-apiservice.bindings.http-5185.targetPort};{stress-apiservice.bindings.http-5186.targetPort};{stress-apiservice.bindings.http-5187.targetPort};{stress-apiservice.bindings.http-5188.targetPort};{stress-apiservice.bindings.http-5189.targetPort};{stress-apiservice.bindings.http-5190.targetPort};{stress-apiservice.bindings.http-5191.targetPort};{stress-apiservice.bindings.http-5192.targetPort};{stress-apiservice.bindings.http-5193.targetPort};{stress-apiservice.bindings.http-5194.targetPort};{stress-apiservice.bindings.http-5195.targetPort};{stress-apiservice.bindings.http-5196.targetPort};{stress-apiservice.bindings.http-5197.targetPort};{stress-apiservice.bindings.http-5198.targetPort};{stress-apiservice.bindings.http-5199.targetPort};{stress-apiservice.bindings.http-5200.targetPort};{stress-apiservice.bindings.http-5201.targetPort};{stress-apiservice.bindings.http-5202.targetPort};{stress-apiservice.bindings.http-5203.targetPort};{stress-apiservice.bindings.http-5204.targetPort};{stress-apiservice.bindings.http-5205.targetPort};{stress-apiservice.bindings.http-5206.targetPort};{stress-apiservice.bindings.http-5207.targetPort};{stress-apiservice.bindings.http-5208.targetPort};{stress-apiservice.bindings.http-5209.targetPort};{stress-apiservice.bindings.http-5210.targetPort}", - "OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE": "true" + "OTEL_DOTNET_EXPERIMENTAL_METRICS_EMIT_OVERFLOW_ATTRIBUTE": "true", + "HOST": "{stress-apiservice.bindings.http.host}", + "PORT": "{stress-apiservice.bindings.http.port}", + "URL": "{stress-apiservice.bindings.http.url}" }, "bindings": { "http": { diff --git a/playground/TestShop/TestShop.AppHost/aspire-manifest.json b/playground/TestShop/TestShop.AppHost/aspire-manifest.json index a04e909c04e..f8a63c0e61e 100644 --- a/playground/TestShop/TestShop.AppHost/aspire-manifest.json +++ b/playground/TestShop/TestShop.AppHost/aspire-manifest.json @@ -4,7 +4,7 @@ "postgres": { "type": "container.v0", "connectionString": "Host={postgres.bindings.tcp.host};Port={postgres.bindings.tcp.port};Username=postgres;Password={postgres-password.value}", - "image": "docker.io/library/postgres:17.2", + "image": "docker.io/library/postgres:17.4", "volumes": [ { "name": "testshop.apphost-48e1ce2b9b-postgres-data", @@ -69,7 +69,7 @@ "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", "HTTP_PORTS": "{catalogdbapp.bindings.http.targetPort}", "ConnectionStrings__catalogdb": "{catalogdb.connectionString}", - "DatabaseResetKey": "9a5cbab2-b477-4a2f-9d2f-91080d988d75" + "DatabaseResetKey": "f5d39b41-8fb0-434c-9549-62e310a9ae4d" }, "bindings": { "http": { @@ -111,7 +111,7 @@ "messaging": { "type": "container.v0", "connectionString": "amqp://guest:{messaging-password.value}@{messaging.bindings.tcp.host}:{messaging.bindings.tcp.port}", - "image": "docker.io/library/rabbitmq:4.0-management", + "image": "docker.io/library/rabbitmq:4.1-management", "volumes": [ { "name": "testshop.apphost-48e1ce2b9b-messaging-data", @@ -203,14 +203,10 @@ } }, "apigateway": { - "type": "project.v0", - "path": "../ApiGateway/ApiGateway.csproj", + "type": "container.v0", + "image": "mcr.microsoft.com/dotnet/nightly/yarp:latest", "env": { - "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true", - "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true", - "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory", - "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", - "HTTP_PORTS": "{apigateway.bindings.http.targetPort}", + "ASPNETCORE_ENVIRONMENT": "Development", "services__basketservice__http__0": "{basketservice.bindings.http.url}", "services__basketservice__https__0": "{basketservice.bindings.https.url}", "services__catalogservice__http__0": "{catalogservice.bindings.http.url}", @@ -220,12 +216,8 @@ "http": { "scheme": "http", "protocol": "tcp", - "transport": "http" - }, - "https": { - "scheme": "https", - "protocol": "tcp", - "transport": "http" + "transport": "http", + "targetPort": 5000 } } }, diff --git a/playground/bicep/BicepSample.AppHost/aspire-manifest.json b/playground/bicep/BicepSample.AppHost/aspire-manifest.json index 84b6ed3119b..69e1f2cd14d 100644 --- a/playground/bicep/BicepSample.AppHost/aspire-manifest.json +++ b/playground/bicep/BicepSample.AppHost/aspire-manifest.json @@ -58,11 +58,7 @@ "sql": { "type": "azure.bicep.v0", "connectionString": "Server=tcp:{sql.outputs.sqlServerFqdn},1433;Encrypt=True;Authentication=\u0022Active Directory Default\u0022", - "path": "sql.module.bicep", - "params": { - "principalId": "", - "principalName": "" - } + "path": "sql.module.bicep" }, "db": { "type": "value.v0", @@ -252,8 +248,10 @@ "path": "sql-roles.module.bicep", "params": { "sql_outputs_name": "{sql.outputs.name}", + "sql_outputs_sqlserveradminname": "{sql.outputs.sqlServerAdminName}", "principalId": "", - "principalName": "" + "principalName": "", + "principalType": "" } }, "postgres2-kv-roles": { diff --git a/playground/bicep/BicepSample.AppHost/kv3-roles.module.bicep b/playground/bicep/BicepSample.AppHost/kv3-roles.module.bicep index 91ef8b881f2..b54602e5c29 100644 --- a/playground/bicep/BicepSample.AppHost/kv3-roles.module.bicep +++ b/playground/bicep/BicepSample.AppHost/kv3-roles.module.bicep @@ -11,11 +11,11 @@ resource kv3 'Microsoft.KeyVault/vaults@2023-07-01' existing = { name: kv3_outputs_name } -resource kv3_KeyVaultAdministrator 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(kv3.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')) +resource kv3_KeyVaultSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(kv3.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')) properties: { principalId: principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') principalType: principalType } scope: kv3 diff --git a/playground/bicep/BicepSample.AppHost/postgres2-kv-roles.module.bicep b/playground/bicep/BicepSample.AppHost/postgres2-kv-roles.module.bicep index e984a408bb8..4717191f6c7 100644 --- a/playground/bicep/BicepSample.AppHost/postgres2-kv-roles.module.bicep +++ b/playground/bicep/BicepSample.AppHost/postgres2-kv-roles.module.bicep @@ -11,11 +11,11 @@ resource postgres2_kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { name: postgres2_kv_outputs_name } -resource postgres2_kv_KeyVaultAdministrator 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(postgres2_kv.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')) +resource postgres2_kv_KeyVaultSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(postgres2_kv.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')) properties: { principalId: principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') principalType: principalType } scope: postgres2_kv diff --git a/playground/bicep/BicepSample.AppHost/sql-roles.module.bicep b/playground/bicep/BicepSample.AppHost/sql-roles.module.bicep index b51780ea7cd..d25b2fe780b 100644 --- a/playground/bicep/BicepSample.AppHost/sql-roles.module.bicep +++ b/playground/bicep/BicepSample.AppHost/sql-roles.module.bicep @@ -3,19 +3,61 @@ param location string = resourceGroup().location param sql_outputs_name string +param sql_outputs_sqlserveradminname string + param principalId string param principalName string +param principalType string + resource sql 'Microsoft.Sql/servers@2021-11-01' existing = { name: sql_outputs_name } -resource sql_admin 'Microsoft.Sql/servers/administrators@2021-11-01' = { - name: 'ActiveDirectory' +resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: sql_outputs_sqlserveradminname +} + +resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: principalName +} + +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: { - login: principalName - sid: principalId + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\n\$sqlDatabaseName = "\$env:DBNAME"\n\$principalName = "\$env:PRINCIPALNAME"\n\$id = "\$env:ID"\n\n# Install SqlServer module\nInstall-Module -Name SqlServer -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' + azPowerShellVersion: '10.0' + retentionInterval: 'PT1H' + environmentVariables: [ + { + name: 'DBNAME' + value: 'db' + } + { + name: 'DBSERVER' + value: sql.properties.fullyQualifiedDomainName + } + { + name: 'PRINCIPALTYPE' + value: principalType + } + { + name: 'PRINCIPALNAME' + value: principalName + } + { + name: 'ID' + value: mi.properties.clientId + } + ] } - parent: sql } \ No newline at end of file diff --git a/playground/bicep/BicepSample.AppHost/sql.module.bicep b/playground/bicep/BicepSample.AppHost/sql.module.bicep index 59bf18427e5..2fb6daba3a5 100644 --- a/playground/bicep/BicepSample.AppHost/sql.module.bicep +++ b/playground/bicep/BicepSample.AppHost/sql.module.bicep @@ -1,9 +1,10 @@ @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location -param principalId string - -param principalName string +resource sqlServerAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: take('sql-admin-${uniqueString(resourceGroup().id)}', 63) + location: location +} resource sql 'Microsoft.Sql/servers@2021-11-01' = { name: take('sql-${uniqueString(resourceGroup().id)}', 63) @@ -11,8 +12,8 @@ resource sql 'Microsoft.Sql/servers@2021-11-01' = { properties: { administrators: { administratorType: 'ActiveDirectory' - login: principalName - sid: principalId + login: sqlServerAdminManagedIdentity.name + sid: sqlServerAdminManagedIdentity.properties.principalId tenantId: subscription().tenantId azureADOnlyAuthentication: true } @@ -37,9 +38,18 @@ resource sqlFirewallRule_AllowAllAzureIps 'Microsoft.Sql/servers/firewallRules@2 resource db 'Microsoft.Sql/servers/databases@2021-11-01' = { name: 'db' location: location + properties: { + freeLimitExhaustionBehavior: 'AutoPause' + useFreeLimit: true + } + sku: { + name: 'GP_S_Gen5_2' + } parent: sql } output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName -output name string = sql.name \ No newline at end of file +output name string = sql.name + +output sqlServerAdminName string = sqlServerAdminManagedIdentity.name \ No newline at end of file diff --git a/playground/cdk/CdkSample.AppHost/aspire-manifest.json b/playground/cdk/CdkSample.AppHost/aspire-manifest.json index a6fd7da17b4..150c03c5459 100644 --- a/playground/cdk/CdkSample.AppHost/aspire-manifest.json +++ b/playground/cdk/CdkSample.AppHost/aspire-manifest.json @@ -43,11 +43,7 @@ "sql": { "type": "azure.bicep.v0", "connectionString": "Server=tcp:{sql.outputs.sqlServerFqdn},1433;Encrypt=True;Authentication=\u0022Active Directory Default\u0022", - "path": "sql.module.bicep", - "params": { - "principalId": "", - "principalName": "" - } + "path": "sql.module.bicep" }, "sqldb": { "type": "value.v0", @@ -246,8 +242,10 @@ "path": "sql-roles.module.bicep", "params": { "sql_outputs_name": "{sql.outputs.name}", + "sql_outputs_sqlserveradminname": "{sql.outputs.sqlServerAdminName}", "principalId": "", - "principalName": "" + "principalName": "", + "principalType": "" } }, "mykv-roles": { diff --git a/playground/cdk/CdkSample.AppHost/mykv-roles.module.bicep b/playground/cdk/CdkSample.AppHost/mykv-roles.module.bicep index 58aba49de9b..efca3c98fe6 100644 --- a/playground/cdk/CdkSample.AppHost/mykv-roles.module.bicep +++ b/playground/cdk/CdkSample.AppHost/mykv-roles.module.bicep @@ -11,11 +11,11 @@ resource mykv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { name: mykv_outputs_name } -resource mykv_KeyVaultAdministrator 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(mykv.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')) +resource mykv_KeyVaultSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(mykv.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')) properties: { principalId: principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') principalType: principalType } scope: mykv diff --git a/playground/cdk/CdkSample.AppHost/pgsql-kv-roles.module.bicep b/playground/cdk/CdkSample.AppHost/pgsql-kv-roles.module.bicep index 9c9e39fb812..c29ff672759 100644 --- a/playground/cdk/CdkSample.AppHost/pgsql-kv-roles.module.bicep +++ b/playground/cdk/CdkSample.AppHost/pgsql-kv-roles.module.bicep @@ -11,11 +11,11 @@ resource pgsql_kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { name: pgsql_kv_outputs_name } -resource pgsql_kv_KeyVaultAdministrator 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(pgsql_kv.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')) +resource pgsql_kv_KeyVaultSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(pgsql_kv.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')) properties: { principalId: principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483') + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') principalType: principalType } scope: pgsql_kv diff --git a/playground/cdk/CdkSample.AppHost/sql-roles.module.bicep b/playground/cdk/CdkSample.AppHost/sql-roles.module.bicep index b51780ea7cd..20b1c495844 100644 --- a/playground/cdk/CdkSample.AppHost/sql-roles.module.bicep +++ b/playground/cdk/CdkSample.AppHost/sql-roles.module.bicep @@ -3,19 +3,61 @@ param location string = resourceGroup().location param sql_outputs_name string +param sql_outputs_sqlserveradminname string + param principalId string param principalName string +param principalType string + resource sql 'Microsoft.Sql/servers@2021-11-01' existing = { name: sql_outputs_name } -resource sql_admin 'Microsoft.Sql/servers/administrators@2021-11-01' = { - name: 'ActiveDirectory' +resource sqlServerAdmin 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: sql_outputs_sqlserveradminname +} + +resource mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: principalName +} + +resource script_sql_sqldb 'Microsoft.Resources/deploymentScripts@2023-08-01' = { + name: take('script-${uniqueString('sql', principalName, 'sqldb', resourceGroup().id)}', 24) + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${sqlServerAdmin.id}': { } + } + } + kind: 'AzurePowerShell' properties: { - login: principalName - sid: principalId + scriptContent: '\$sqlServerFqdn = "\$env:DBSERVER"\n\$sqlDatabaseName = "\$env:DBNAME"\n\$principalName = "\$env:PRINCIPALNAME"\n\$id = "\$env:ID"\n\n# Install SqlServer module\nInstall-Module -Name SqlServer -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' + azPowerShellVersion: '10.0' + retentionInterval: 'PT1H' + environmentVariables: [ + { + name: 'DBNAME' + value: 'sqldb' + } + { + name: 'DBSERVER' + value: sql.properties.fullyQualifiedDomainName + } + { + name: 'PRINCIPALTYPE' + value: principalType + } + { + name: 'PRINCIPALNAME' + value: principalName + } + { + name: 'ID' + value: mi.properties.clientId + } + ] } - parent: sql } \ No newline at end of file diff --git a/playground/cdk/CdkSample.AppHost/sql.module.bicep b/playground/cdk/CdkSample.AppHost/sql.module.bicep index 43f854284c9..bdba06f3874 100644 --- a/playground/cdk/CdkSample.AppHost/sql.module.bicep +++ b/playground/cdk/CdkSample.AppHost/sql.module.bicep @@ -1,9 +1,10 @@ @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location -param principalId string - -param principalName string +resource sqlServerAdminManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: take('sql-admin-${uniqueString(resourceGroup().id)}', 63) + location: location +} resource sql 'Microsoft.Sql/servers@2021-11-01' = { name: take('sql-${uniqueString(resourceGroup().id)}', 63) @@ -11,8 +12,8 @@ resource sql 'Microsoft.Sql/servers@2021-11-01' = { properties: { administrators: { administratorType: 'ActiveDirectory' - login: principalName - sid: principalId + login: sqlServerAdminManagedIdentity.name + sid: sqlServerAdminManagedIdentity.properties.principalId tenantId: subscription().tenantId azureADOnlyAuthentication: true } @@ -37,9 +38,18 @@ resource sqlFirewallRule_AllowAllAzureIps 'Microsoft.Sql/servers/firewallRules@2 resource sqldb 'Microsoft.Sql/servers/databases@2021-11-01' = { name: 'sqldb' location: location + properties: { + freeLimitExhaustionBehavior: 'AutoPause' + useFreeLimit: true + } + sku: { + name: 'GP_S_Gen5_2' + } parent: sql } output sqlServerFqdn string = sql.properties.fullyQualifiedDomainName -output name string = sql.name \ No newline at end of file +output name string = sql.name + +output sqlServerAdminName string = sqlServerAdminManagedIdentity.name \ No newline at end of file diff --git a/playground/keycloak/Keycloak.AppHost/aspire-manifest.json b/playground/keycloak/Keycloak.AppHost/aspire-manifest.json index d146556710d..ffd1149e0ab 100644 --- a/playground/keycloak/Keycloak.AppHost/aspire-manifest.json +++ b/playground/keycloak/Keycloak.AppHost/aspire-manifest.json @@ -3,18 +3,11 @@ "resources": { "keycloak": { "type": "container.v0", - "image": "quay.io/keycloak/keycloak:26.1", + "image": "quay.io/keycloak/keycloak:26.2", "args": [ "start", "--import-realm" ], - "bindMounts": [ - { - "source": "../realms", - "target": "/opt/keycloak/data/import", - "readOnly": false - } - ], "volumes": [ { "name": "keycloak.apphost-28dd42043c-keycloak-data", diff --git a/playground/milvus/MilvusPlayground.AppHost/aspire-manifest.json b/playground/milvus/MilvusPlayground.AppHost/aspire-manifest.json index cecc66e1cc3..a546bbea9de 100644 --- a/playground/milvus/MilvusPlayground.AppHost/aspire-manifest.json +++ b/playground/milvus/MilvusPlayground.AppHost/aspire-manifest.json @@ -4,7 +4,7 @@ "milvus": { "type": "container.v0", "connectionString": "Endpoint={milvus.bindings.grpc.url};Key=root:{milvus-key.value}", - "image": "docker.io/milvusdb/milvus:v2.5.5", + "image": "docker.io/milvusdb/milvus:v2.5.9", "args": [ "milvus", "run", diff --git a/playground/mysql/MySqlDb.AppHost/aspire-manifest.json b/playground/mysql/MySqlDb.AppHost/aspire-manifest.json index 7630f362623..08246f04498 100644 --- a/playground/mysql/MySqlDb.AppHost/aspire-manifest.json +++ b/playground/mysql/MySqlDb.AppHost/aspire-manifest.json @@ -4,7 +4,7 @@ "mysql": { "type": "container.v0", "connectionString": "Server={mysql.bindings.tcp.host};Port={mysql.bindings.tcp.port};User ID=root;Password={mysql-password.value}", - "image": "docker.io/library/mysql:9.2", + "image": "docker.io/library/mysql:9.3", "bindMounts": [ { "source": "../MySql.ApiService/data", @@ -29,6 +29,14 @@ "type": "value.v0", "connectionString": "{mysql.connectionString};Database=catalog" }, + "myTestDb": { + "type": "value.v0", + "connectionString": "{mysql.connectionString};Database=myTestDb" + }, + "myTestDb2": { + "type": "value.v0", + "connectionString": "{mysql.connectionString};Database=myTestDb2" + }, "apiservice": { "type": "project.v0", "path": "../MySql.ApiService/MySql.ApiService.csproj", @@ -38,7 +46,9 @@ "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory", "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", "HTTP_PORTS": "{apiservice.bindings.http.targetPort}", - "ConnectionStrings__catalog": "{catalog.connectionString}" + "ConnectionStrings__catalog": "{catalog.connectionString}", + "ConnectionStrings__myTestDb": "{myTestDb.connectionString}", + "ConnectionStrings__myTestDb2": "{myTestDb2.connectionString}" }, "bindings": { "http": { diff --git a/playground/nats/Nats.AppHost/aspire-manifest.json b/playground/nats/Nats.AppHost/aspire-manifest.json index 0564155c2d0..bbfa0f35ce8 100644 --- a/playground/nats/Nats.AppHost/aspire-manifest.json +++ b/playground/nats/Nats.AppHost/aspire-manifest.json @@ -4,7 +4,7 @@ "nats": { "type": "container.v0", "connectionString": "nats://nats:{nats-password.value}@{nats.bindings.tcp.host}:{nats.bindings.tcp.port}", - "image": "docker.io/library/nats:2.10", + "image": "docker.io/library/nats:2.11", "args": [ "--user", "nats", diff --git a/playground/withdockerfile/WithDockerfile.AppHost/aspire-manifest.json b/playground/withdockerfile/WithDockerfile.AppHost/aspire-manifest.json index 8affec105f4..9ade345c2cf 100644 --- a/playground/withdockerfile/WithDockerfile.AppHost/aspire-manifest.json +++ b/playground/withdockerfile/WithDockerfile.AppHost/aspire-manifest.json @@ -1,6 +1,9 @@ { "$schema": "https://json.schemastore.org/aspire-8.0.json", "resources": { + "docker-compose": { + "error": "This resource does not support generation in the manifest." + }, "goversion": { "type": "parameter.v0", "value": "{goversion.inputs.value}",