diff --git a/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentAcrPullIdentityAnnotation.cs b/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentAcrPullIdentityAnnotation.cs index 5ccec51388b..c55028e3ce4 100644 --- a/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentAcrPullIdentityAnnotation.cs +++ b/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppEnvironmentAcrPullIdentityAnnotation.cs @@ -12,10 +12,21 @@ namespace Aspire.Hosting.Azure; /// role assignment. /// /// The user-assigned identity resource to use for the AcrPull role. -internal sealed class AzureContainerAppEnvironmentAcrPullIdentityAnnotation(AzureUserAssignedIdentityResource identity) : IResourceAnnotation +/// +/// when the identity is Aspire-generated and Aspire is responsible for granting it the +/// AcrPull role on the environment's registry; when the caller supplied their own +/// identity via WithAcrPullIdentity and therefore owns the role assignment. +/// +internal sealed class AzureContainerAppEnvironmentAcrPullIdentityAnnotation(AzureUserAssignedIdentityResource identity, bool assignAcrPullRole = false) : IResourceAnnotation { /// /// Gets the user-assigned identity resource that holds the AcrPull role. /// public AzureUserAssignedIdentityResource Identity { get; } = identity; + + /// + /// Gets a value indicating whether Aspire generated and must grant it the + /// AcrPull role on the environment's container registry. + /// + public bool AssignAcrPullRole { get; } = assignAcrPullRole; } diff --git a/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppExtensions.cs b/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppExtensions.cs index 2ad16ea7027..26c8bca6994 100644 --- a/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppExtensions.cs +++ b/src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #pragma warning disable ASPIREPIPELINES001 +#pragma warning disable ASPIREAZURE001 // AzureEnvironmentResource is for evaluation purposes only. Suppressed to reference the well-known prepare-resources step name. #pragma warning disable ASPIREAZURE003 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System.Diagnostics; @@ -27,6 +28,22 @@ namespace Aspire.Hosting; /// public static class AzureContainerAppExtensions { + // The AcrPull role granted to the environment's container-pull identity. Declared as a model + // RoleAssignmentAnnotation (rather than an inline role assignment in the env Bicep) so the preparer + // can emit it as a separately scoped module for cross-resource-group existing registries (BCP139). + // See https://github.com/microsoft/aspire/issues/11256. + // + // NOTE: This field and the helpers below (AssignAcrPullRoleToGeneratedIdentity, ResolveContainerRegistry, + // CreateDefaultAcrPullIdentity, GetUniqueAcrPullIdentityName, RemoveGeneratedAcrPullIdentity) plus the + // "finalize-azure-container-apps-acr-pull-roles" pipeline step are intentionally duplicated in + // AzureAppServiceEnvironmentExtensions (the two packages don't share internals). Keep the two copies in sync. + private static readonly IReadOnlySet s_acrPullRole = new HashSet + { + new( + ContainerRegistryBuiltInRole.AcrPull.ToString(), + ContainerRegistryBuiltInRole.GetBuiltInRoleName(ContainerRegistryBuiltInRole.AcrPull)) + }; + /// /// Adds the necessary infrastructure for Azure Container Apps to the distributed application builder. /// @@ -81,11 +98,67 @@ internal static IDistributedApplicationBuilder AddAzureContainerAppsInfrastructu return Task.CompletedTask; }, requiredBy: WellKnownPipelineSteps.BeforeStart); + + // Grant the Aspire-generated ACR-pull identity the AcrPull role on each environment's FINAL + // container registry. This runs just before azure-prepare-resources so it observes the registry + // chosen by WithAzureContainerRegistry, and the preparer then emits the role assignment as a + // separately scoped module (required for cross-resource-group existing registries — BCP139). + // See https://github.com/microsoft/aspire/issues/11256. + builder.Pipeline.AddStep( + name: "finalize-azure-container-apps-acr-pull-roles", + action: ctx => + { + if (!ctx.ExecutionContext.IsPublishMode) + { + return Task.CompletedTask; + } + + foreach (var env in ctx.Model.Resources.OfType()) + { + AssignAcrPullRoleToGeneratedIdentity(env); + } + + return Task.CompletedTask; + }, + requiredBy: AzureEnvironmentResource.PrepareResourcesStepName); } return builder; } + private static void AssignAcrPullRoleToGeneratedIdentity(AzureContainerAppEnvironmentResource env) + { + if (!env.TryGetLastAnnotation(out var identityAnnotation) || + !identityAnnotation.AssignAcrPullRole) + { + // No generated identity (run mode, or the caller supplied their own identity via WithAcrPullIdentity). + return; + } + + var registry = ResolveContainerRegistry(env); + var identity = identityAnnotation.Identity; + + // Idempotent: the step may run once per pipeline, but guard against re-adding if invoked again. + if (identity.Annotations.OfType().Any(a => a.Target == registry && a.Roles.SetEquals(s_acrPullRole))) + { + return; + } + + identity.Annotations.Add(new RoleAssignmentAnnotation(registry, s_acrPullRole)); + } + + private static AzureProvisioningResource ResolveContainerRegistry(AzureContainerAppEnvironmentResource env) + { + if (env.TryGetLastAnnotation(out var registryReferenceAnnotation) && + registryReferenceAnnotation.Registry is AzureProvisioningResource explicitRegistry) + { + return explicitRegistry; + } + + return env.DefaultContainerRegistry as AzureProvisioningResource + ?? throw new InvalidOperationException($"No container registry associated with environment '{env.Name}'. This should have been added automatically."); + } + private sealed class ContainerAppsPipelineStepMarker { public const string StepName = "validate-azure-container-apps"; @@ -429,6 +502,18 @@ public static IResourceBuilder AddAzureCon var defaultRegistry = CreateDefaultAzureContainerRegistry(builder, registryName, containerAppEnvResource); containerAppEnvResource.DefaultContainerRegistry = defaultRegistry; + if (builder.ExecutionContext.IsPublishMode) + { + // Materialize the ACR-pull identity as a first-class model resource so AzureResourcePreparer emits + // the AcrPull role assignment as a separate module — correctly scoped to the registry's resource + // group when it is an existing registry in another resource group. This is the fix for BCP139. + // See https://github.com/microsoft/aspire/issues/11256. The role assignment itself is added against + // the environment's FINAL registry by the finalize-acr-pull-identity-roles pipeline step (which runs + // just before the preparer), so that WithAzureContainerRegistry swaps are observed. + var acrPullIdentity = CreateDefaultAcrPullIdentity(builder, name); + containerAppEnvResource.Annotations.Add(new AzureContainerAppEnvironmentAcrPullIdentityAnnotation(acrPullIdentity, assignAcrPullRole: true)); + } + // Create the resource builder first, then attach the registry to avoid recreating builders var appEnvBuilder = builder.ExecutionContext.IsRunMode // HACK: We need to return a valid resource builder for the container app environment @@ -756,11 +841,57 @@ public static IResourceBuilder WithAcrPull ArgumentNullException.ThrowIfNull(builder); ArgumentNullException.ThrowIfNull(identityBuilder); - builder.WithAnnotation(new AzureContainerAppEnvironmentAcrPullIdentityAnnotation(identityBuilder.Resource)); + RemoveGeneratedAcrPullIdentity(builder); + builder.WithAnnotation( + new AzureContainerAppEnvironmentAcrPullIdentityAnnotation(identityBuilder.Resource), + ResourceAnnotationMutationBehavior.Replace); return builder; } + private static void RemoveGeneratedAcrPullIdentity(IResourceBuilder builder) + { + if (!builder.Resource.TryGetLastAnnotation(out var existing) || + !existing.AssignAcrPullRole) + { + return; + } + + // The caller is supplying their own identity and owns its AcrPull role assignment, so drop the + // Aspire-generated identity entirely. The role assignment is added later (in the finalize pipeline + // step) only for AssignAcrPullRole identities, so removing the generated identity from the model is + // sufficient to ensure no generated identity or role module is emitted. + builder.ApplicationBuilder.Resources.Remove(existing.Identity); + } + + private static AzureUserAssignedIdentityResource CreateDefaultAcrPullIdentity(IDistributedApplicationBuilder builder, string environmentName) + { + // The identity is a first-class resource so the preparer can order it before the environment + // module and pass its id into the environment Bicep as an input parameter. + var identity = new AzureUserAssignedIdentityResource(GetUniqueAcrPullIdentityName(builder, environmentName)); + builder.AddResource(identity); + + return identity; + } + + private static string GetUniqueAcrPullIdentityName(IDistributedApplicationBuilder builder, string environmentName) + { + var baseName = $"{environmentName}-mi"; + if (!builder.Resources.TryGetByName(baseName, out _)) + { + return baseName; + } + + for (var i = 2; ; i++) + { + var candidate = $"{baseName}-{i}"; + if (!builder.Resources.TryGetByName(candidate, out _)) + { + return candidate; + } + } + } + private static AzureContainerRegistryResource CreateDefaultAzureContainerRegistry(IDistributedApplicationBuilder builder, string name, AzureContainerAppEnvironmentResource containerAppEnvironment) { var configureInfrastructure = (AzureResourceInfrastructure infrastructure) => diff --git a/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentAcrPullIdentityAnnotation.cs b/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentAcrPullIdentityAnnotation.cs index 366ecd3eeca..f706b4c5367 100644 --- a/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentAcrPullIdentityAnnotation.cs +++ b/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentAcrPullIdentityAnnotation.cs @@ -12,10 +12,21 @@ namespace Aspire.Hosting.Azure; /// role assignment. /// /// The user-assigned identity resource to use for the AcrPull role. -internal sealed class AzureAppServiceEnvironmentAcrPullIdentityAnnotation(AzureUserAssignedIdentityResource identity) : IResourceAnnotation +/// +/// when the identity is Aspire-generated and Aspire is responsible for granting it the +/// AcrPull role on the environment's registry; when the caller supplied their own +/// identity via WithAcrPullIdentity and therefore owns the role assignment. +/// +internal sealed class AzureAppServiceEnvironmentAcrPullIdentityAnnotation(AzureUserAssignedIdentityResource identity, bool assignAcrPullRole = false) : IResourceAnnotation { /// /// Gets the user-assigned identity resource that holds the AcrPull role. /// public AzureUserAssignedIdentityResource Identity { get; } = identity; + + /// + /// Gets a value indicating whether Aspire generated and must grant it the + /// AcrPull role on the environment's container registry. + /// + public bool AssignAcrPullRole { get; } = assignAcrPullRole; } diff --git a/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentExtensions.cs b/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentExtensions.cs index ed10e163642..5048fc0d5b6 100644 --- a/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentExtensions.cs +++ b/src/Aspire.Hosting.Azure.AppService/AzureAppServiceEnvironmentExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #pragma warning disable ASPIREPIPELINES001 // Pipeline APIs are experimental +#pragma warning disable ASPIREAZURE001 // AzureEnvironmentResource is for evaluation purposes only. Suppressed to reference the well-known prepare-resources step name. using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; @@ -24,6 +25,22 @@ namespace Aspire.Hosting; /// public static partial class AzureAppServiceEnvironmentExtensions { + // The AcrPull role granted to the environment's container-pull identity. Declared as a model + // RoleAssignmentAnnotation (rather than an inline role assignment in the env Bicep) so the preparer + // can emit it as a separately scoped module for cross-resource-group existing registries (BCP139). + // See https://github.com/microsoft/aspire/issues/11256. + // + // NOTE: This field and the helpers below (AssignAcrPullRoleToGeneratedIdentity, ResolveContainerRegistry, + // CreateDefaultAcrPullIdentity, GetUniqueAcrPullIdentityName, RemoveGeneratedAcrPullIdentity) plus the + // "finalize-azure-app-service-acr-pull-roles" pipeline step are intentionally duplicated in + // AzureContainerAppExtensions (the two packages don't share internals). Keep the two copies in sync. + private static readonly IReadOnlySet s_acrPullRole = new HashSet + { + new( + ContainerRegistryBuiltInRole.AcrPull.ToString(), + ContainerRegistryBuiltInRole.GetBuiltInRoleName(ContainerRegistryBuiltInRole.AcrPull)) + }; + internal static IDistributedApplicationBuilder AddAzureAppServiceInfrastructureCore(this IDistributedApplicationBuilder builder) { builder.AddAzureProvisioning(); @@ -65,11 +82,67 @@ internal static IDistributedApplicationBuilder AddAzureAppServiceInfrastructureC return Task.CompletedTask; }, requiredBy: WellKnownPipelineSteps.BeforeStart); + + // Grant the Aspire-generated ACR-pull identity the AcrPull role on each environment's FINAL + // container registry. This runs just before azure-prepare-resources so it observes the registry + // chosen by WithAzureContainerRegistry, and the preparer then emits the role assignment as a + // separately scoped module (required for cross-resource-group existing registries — BCP139). + // See https://github.com/microsoft/aspire/issues/11256. + builder.Pipeline.AddStep( + name: "finalize-azure-app-service-acr-pull-roles", + action: ctx => + { + if (!ctx.ExecutionContext.IsPublishMode) + { + return Task.CompletedTask; + } + + foreach (var env in ctx.Model.Resources.OfType()) + { + AssignAcrPullRoleToGeneratedIdentity(env); + } + + return Task.CompletedTask; + }, + requiredBy: AzureEnvironmentResource.PrepareResourcesStepName); } return builder; } + private static void AssignAcrPullRoleToGeneratedIdentity(AzureAppServiceEnvironmentResource env) + { + if (!env.TryGetLastAnnotation(out var identityAnnotation) || + !identityAnnotation.AssignAcrPullRole) + { + // No generated identity (run mode, or the caller supplied their own identity via WithAcrPullIdentity). + return; + } + + var registry = ResolveContainerRegistry(env); + var identity = identityAnnotation.Identity; + + // Idempotent: the step may run once per pipeline, but guard against re-adding if invoked again. + if (identity.Annotations.OfType().Any(a => a.Target == registry && a.Roles.SetEquals(s_acrPullRole))) + { + return; + } + + identity.Annotations.Add(new RoleAssignmentAnnotation(registry, s_acrPullRole)); + } + + private static AzureProvisioningResource ResolveContainerRegistry(AzureAppServiceEnvironmentResource env) + { + if (env.TryGetLastAnnotation(out var registryReferenceAnnotation) && + registryReferenceAnnotation.Registry is AzureProvisioningResource explicitRegistry) + { + return explicitRegistry; + } + + return env.DefaultContainerRegistry as AzureProvisioningResource + ?? throw new InvalidOperationException($"No container registry associated with environment '{env.Name}'. This should have been added automatically."); + } + private sealed class AppServicePipelineStepMarker { public const string StepName = "validate-azure-app-service"; @@ -292,6 +365,18 @@ public static IResourceBuilder AddAzureAppSe DefaultContainerRegistry = defaultRegistry }; + if (builder.ExecutionContext.IsPublishMode) + { + // Materialize the ACR-pull identity as a first-class model resource so AzureResourcePreparer emits + // the AcrPull role assignment as a separate module — correctly scoped to the registry's resource + // group when it is an existing registry in another resource group. This is the fix for BCP139. + // See https://github.com/microsoft/aspire/issues/11256. The role assignment itself is added against + // the environment's FINAL registry by the finalize-acr-pull-identity-roles pipeline step (which runs + // just before the preparer), so that WithAzureContainerRegistry swaps are observed. + var acrPullIdentity = CreateDefaultAcrPullIdentity(builder, name); + resource.Annotations.Add(new AzureAppServiceEnvironmentAcrPullIdentityAnnotation(acrPullIdentity, assignAcrPullRole: true)); + } + // Create the resource builder first, then attach the registry to avoid recreating builders var appServiceEnvBuilder = builder.ExecutionContext.IsPublishMode ? builder.AddResource(resource) @@ -534,11 +619,57 @@ public static IResourceBuilder WithAcrPullId ArgumentNullException.ThrowIfNull(builder); ArgumentNullException.ThrowIfNull(identityBuilder); - builder.WithAnnotation(new AzureAppServiceEnvironmentAcrPullIdentityAnnotation(identityBuilder.Resource)); + RemoveGeneratedAcrPullIdentity(builder); + builder.WithAnnotation( + new AzureAppServiceEnvironmentAcrPullIdentityAnnotation(identityBuilder.Resource), + ResourceAnnotationMutationBehavior.Replace); return builder; } + private static void RemoveGeneratedAcrPullIdentity(IResourceBuilder builder) + { + if (!builder.Resource.TryGetLastAnnotation(out var existing) || + !existing.AssignAcrPullRole) + { + return; + } + + // The caller is supplying their own identity and owns its AcrPull role assignment, so drop the + // Aspire-generated identity entirely. The role assignment is added later (in the finalize pipeline + // step) only for AssignAcrPullRole identities, so removing the generated identity from the model is + // sufficient to ensure no generated identity or role module is emitted. + builder.ApplicationBuilder.Resources.Remove(existing.Identity); + } + + private static AzureUserAssignedIdentityResource CreateDefaultAcrPullIdentity(IDistributedApplicationBuilder builder, string environmentName) + { + // The identity is a first-class resource so the preparer can order it before the environment + // module and pass its id into the environment Bicep as an input parameter. + var identity = new AzureUserAssignedIdentityResource(GetUniqueAcrPullIdentityName(builder, environmentName)); + builder.AddResource(identity); + + return identity; + } + + private static string GetUniqueAcrPullIdentityName(IDistributedApplicationBuilder builder, string environmentName) + { + var baseName = $"{environmentName}-mi"; + if (!builder.Resources.TryGetByName(baseName, out _)) + { + return baseName; + } + + for (var i = 2; ; i++) + { + var candidate = $"{baseName}-{i}"; + if (!builder.Resources.TryGetByName(candidate, out _)) + { + return candidate; + } + } + } + private static AzureContainerRegistryResource CreateDefaultAzureContainerRegistry(IDistributedApplicationBuilder builder, string name) { var resource = new AzureContainerRegistryResource(name, ContainerRegistryInfrastructure.ConfigureContainerRegistry); diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureAppServiceEnvironmentExtensionsTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureAppServiceEnvironmentExtensionsTests.cs index 87ed6796dbc..d7b46f59326 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureAppServiceEnvironmentExtensionsTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureAppServiceEnvironmentExtensionsTests.cs @@ -95,4 +95,51 @@ public void ContainerRegistry_ThrowsWhenNonAzureRegistryConfigured() Assert.Contains("not an Azure Container Registry", exception.Message); Assert.Contains("env", exception.Message); } + + [Fact] + public async Task PublishAsExisting_CrossResourceGroupAcr_EmitsScopedAcrPullRoleModule() + { + // Regression test for https://github.com/microsoft/aspire/issues/11256. + // When the environment's container registry is an existing ACR in a DIFFERENT resource group, + // the default ACR-pull role assignment must be emitted as a separately scoped module (not inlined + // in the env Bicep), otherwise Bicep fails with BCP139. + var tempDir = Directory.CreateTempSubdirectory(".acr-crossrg-appservice-test"); + try + { + var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, tempDir.FullName); + + var acr = builder.AddAzureContainerRegistry("acr") + .PublishAsExisting("myexistingacr", "my-existing-resource-group"); + + builder.AddAzureAppServiceEnvironment("env") + .WithAzureContainerRegistry(acr); + + builder.AddProject("apiservice", launchProfileName: null); + + using var app = builder.Build(); + app.Run(); + + var envBicep = await File.ReadAllTextAsync(Path.Combine(tempDir.FullName, "env", "env.bicep")); + // The env module must not contain an inline AcrPull role assignment scoped to the cross-RG + // registry (AcrPull built-in role id 7f951dda-4ed3-4680-a7ca-43fe172d538d) - that is what + // triggers BCP139. The role assignment must instead live in a separately scoped module. + Assert.DoesNotContain("7f951dda-4ed3-4680-a7ca-43fe172d538d", envBicep); + + var mainBicep = await File.ReadAllTextAsync(Path.Combine(tempDir.FullName, "main.bicep")); + // A role-assignment module for the generated identity must be scoped to the registry's resource group. + Assert.Contains("env_mi_roles_acr", mainBicep); + Assert.Contains("resourceGroup('my-existing-resource-group')", mainBicep); + } + finally + { + tempDir.Delete(recursive: true); + } + } + + private sealed class TestProject : IProjectMetadata + { + public string ProjectPath => "another-path"; + + public LaunchSettings? LaunchSettings { get; set; } + } } diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureContainerAppEnvironmentExtensionsTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureContainerAppEnvironmentExtensionsTests.cs index a993f1e0ecd..aedf60f9c25 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureContainerAppEnvironmentExtensionsTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureContainerAppEnvironmentExtensionsTests.cs @@ -120,6 +120,46 @@ public void ContainerRegistry_ReturnsNullWhenNoRegistryConfigured() Assert.Null(environment.ContainerRegistry); } + [Fact] + public async Task PublishAsExisting_CrossResourceGroupAcr_EmitsScopedAcrPullRoleModule() + { + // Regression test for https://github.com/microsoft/aspire/issues/11256. + // When the environment's container registry is an existing ACR in a DIFFERENT resource group, + // the default ACR-pull role assignment must be emitted as a separately scoped module (not inlined + // in the env Bicep), otherwise Bicep fails with BCP139. + var tempDir = Directory.CreateTempSubdirectory(".acr-crossrg-aca-test"); + try + { + var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, tempDir.FullName); + + var acr = builder.AddAzureContainerRegistry("acr") + .PublishAsExisting("myexistingacr", "my-existing-resource-group"); + + builder.AddAzureContainerAppEnvironment("env") + .WithAzureContainerRegistry(acr); + + builder.AddProject("apiservice", launchProfileName: null); + + using var app = builder.Build(); + app.Run(); + + var envBicep = await File.ReadAllTextAsync(Path.Combine(tempDir.FullName, "env", "env.bicep")); + // The env module must not contain an inline AcrPull role assignment scoped to the cross-RG + // registry (AcrPull built-in role id 7f951dda-4ed3-4680-a7ca-43fe172d538d) - that is what + // triggers BCP139. The role assignment must instead live in a separately scoped module. + Assert.DoesNotContain("7f951dda-4ed3-4680-a7ca-43fe172d538d", envBicep); + + var mainBicep = await File.ReadAllTextAsync(Path.Combine(tempDir.FullName, "main.bicep")); + // A role-assignment module for the generated identity must be scoped to the registry's resource group. + Assert.Contains("env_mi_roles_acr", mainBicep); + Assert.Contains("resourceGroup('my-existing-resource-group')", mainBicep); + } + finally + { + tempDir.Delete(recursive: true); + } + } + [Fact] public void ContainerRegistry_ThrowsWhenNonAzureRegistryConfigured() { @@ -366,4 +406,11 @@ public async Task WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistry await Verify(mainBicep, "bicep") .AppendContentAsFile(envBicep, "bicep"); } + + private sealed class TestProject : IProjectMetadata + { + public string ProjectPath => "another-path"; + + public LaunchSettings? LaunchSettings { get; set; } + } } diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs index 0851666c090..b0c9f451b9e 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs @@ -144,6 +144,12 @@ public async Task DeployAsync_WithBuildOnlyContainers() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -207,6 +213,12 @@ public async Task DeployAsync_WithAzureStorageResourcesWorks() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -266,6 +278,12 @@ public async Task DeployAsync_WithContainer_Works() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -326,6 +344,12 @@ public async Task DeployAsync_WithDockerfile_Works() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -392,6 +416,12 @@ public async Task DeployAsync_WithProjectResource_Works() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -458,6 +488,12 @@ public async Task DeployAsync_WithContainerAppExternalEndpoint_IncludesPortalLin ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -514,6 +550,12 @@ public async Task DeployAsync_WithAppServiceExternalEndpoint_IncludesPortalLinks ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -577,6 +619,12 @@ public async Task DeployAsync_WithMultipleComputeEnvironments_Works(string step) ["name"] = new { type = "String", value = "acaregistry" }, ["loginServer"] = new { type = "String", value = "acaregistry.azurecr.io" } }, + string name when name.StartsWith("aca-env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aca-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("aca-env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "acaregistry" }, @@ -591,6 +639,12 @@ public async Task DeployAsync_WithMultipleComputeEnvironments_Works(string step) ["name"] = new { type = "String", value = "aasregistry" }, ["loginServer"] = new { type = "String", value = "aasregistry.azurecr.io" } }, + string name when name.StartsWith("aas-env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aas-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000003" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000004" } + }, string name when name.StartsWith("aas-env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "aasregistry" }, @@ -811,6 +865,12 @@ public async Task DeployAsync_WithSingleRedisCache_CallsDeployingComputeResource ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, @@ -875,6 +935,12 @@ public async Task DeployAsync_WithOnlyAzureResources_PrintsDashboardUrl() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN"] = new { type = "String", value = "test.westus.azurecontainerapps.io" }, @@ -1041,6 +1107,12 @@ public async Task DeployAsync_WithAzureFunctionsProject_Works() ["name"] = new { type = "String", value = "testregistry" }, ["loginServer"] = new { type = "String", value = "testregistry.azurecr.io" } }, + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["name"] = new { type = "String", value = "env" }, @@ -1156,6 +1228,12 @@ public async Task DeployAsync_WithAzureResourceDependencies_DoesNotHang(string s { return deploymentName switch { + string name when name.StartsWith("env-mi") => new Dictionary + { + ["id"] = new { type = "String", value = GetTestResourceId("/providers/Microsoft.ManagedIdentity/userAssignedIdentities/test-identity") }, + ["principalId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000001" }, + ["clientId"] = new { type = "String", value = "00000000-0000-0000-0000-000000000002" } + }, string name when name.StartsWith("env") => new Dictionary { ["AZURE_CONTAINER_REGISTRY_NAME"] = new { type = "String", value = "testregistry" }, diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs index 63dfc210cfd..0d9fc458d9a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureResourcePreparerTests.cs @@ -490,13 +490,15 @@ public async Task AppliesRoleAssignmentsOnlyToDirectReferences() Assert.Collection(model.Resources.Select(r => r.Name), n => Assert.StartsWith("azure", n), n => Assert.Equal("env-acr", n), + n => Assert.Equal("env-mi", n), n => Assert.Equal("env", n), n => Assert.Equal("storage", n), n => Assert.Equal("blobs", n), n => Assert.Equal("api", n), n => Assert.Equal("api2", n), n => Assert.Equal("api-identity", n), - n => Assert.Equal("api-roles-storage", n)); + n => Assert.Equal("api-roles-storage", n), + n => Assert.Equal("env-mi-roles-env-acr", n)); } [Fact] @@ -525,13 +527,15 @@ public async Task ViteAppDoesNotGetManagedIdentity() Assert.Collection(model.Resources.Select(r => r.Name), n => Assert.StartsWith("azure", n), n => Assert.Equal("env-acr", n), + n => Assert.Equal("env-mi", n), n => Assert.Equal("env", n), n => Assert.Equal("storage", n), n => Assert.Equal("blobs", n), n => Assert.Equal("api", n), n => Assert.Equal("frontend", n), n => Assert.Equal("api-identity", n), - n => Assert.Equal("api-roles-storage", n)); + n => Assert.Equal("api-roles-storage", n), + n => Assert.Equal("env-mi-roles-env-acr", n)); // The ViteApp should NOT get a managed identity since it is a BuildOnlyContainer resource, // even though it references the storage account. Only the API should get a managed identity. diff --git a/tests/Aspire.Hosting.Azure.Tests/AzureUserAssignedIdentityTests.cs b/tests/Aspire.Hosting.Azure.Tests/AzureUserAssignedIdentityTests.cs index d9124efcf24..78cda7aece2 100644 --- a/tests/Aspire.Hosting.Azure.Tests/AzureUserAssignedIdentityTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/AzureUserAssignedIdentityTests.cs @@ -73,16 +73,16 @@ public async Task AddAzureUserAssignedIdentity_WithRoleAssignments_Works() Assert.Collection(model.Resources, r => Assert.IsType(r), r => Assert.IsType(r), + // The environment's default ACR-pull identity is now a first-class model resource (#11256). + r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), - r => - { - Assert.IsType(r); - Assert.Equal("myidentity-roles-myregistry", r.Name); - }); + r => Assert.IsType(r), + // The default ACR-pull identity's AcrPull role assignment module (#11256). + r => Assert.IsType(r)); - var identityResource = Assert.Single(model.Resources.OfType()); + var identityResource = Assert.Single(model.Resources.OfType(), r => r.Name == "myidentity"); var (_, identityBicep) = await GetManifestWithBicep(identityResource, skipPreparer: true); var registryResource = Assert.Single(model.Resources.OfType(), r => r.Name == "myregistry"); @@ -117,8 +117,9 @@ public async Task WithAzureUserAssignedIdentity_Works() var model = app.Services.GetRequiredService(); - // Check that only one AzureUserAssignedIdentityResource is created, the one that we explicitly constructed - var identityResource = Assert.Single(model.Resources.OfType()); + // Check that the explicitly-constructed identity exists (the environment also adds its own + // default ACR-pull identity as a model resource since #11256). + var identityResource = Assert.Single(model.Resources.OfType(), r => r.Name == "myidentity"); Assert.Equal("myidentity", identityResource.Name); // Check for IComputeResource having the correct identity @@ -158,14 +159,18 @@ public async Task WithAzureUserAssignedIdentity_WithRoleAssignments_Works() Assert.Collection(model.Resources, r => Assert.IsType(r), r => Assert.IsType(r), + // The environment's default ACR-pull identity is now a first-class model resource (#11256). + r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), + r => Assert.IsType(r), + // The default ACR-pull identity's AcrPull role assignment module (#11256). r => Assert.IsType(r)); - // Verify the identity resource is the only one that exists - var identityResource = Assert.Single(model.Resources.OfType()); + // Verify the explicitly-constructed identity resource exists + var identityResource = Assert.Single(model.Resources.OfType(), r => r.Name == "myidentity"); Assert.Equal("myidentity", identityResource.Name); // Verify the compute resource has the identity annotation @@ -216,14 +221,18 @@ public async Task WithAzureUserAssignedIdentity_WithRoleAssignments_AzureAppServ Assert.Collection(model.Resources, r => Assert.IsType(r), r => Assert.IsType(r), + // The environment's default ACR-pull identity is now a first-class model resource (#11256). + r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), + r => Assert.IsType(r), + // The default ACR-pull identity's AcrPull role assignment module (#11256). r => Assert.IsType(r)); - // Verify the identity resource is the only one that exists - var identityResource = Assert.Single(model.Resources.OfType()); + // Verify the explicitly-constructed identity resource exists + var identityResource = Assert.Single(model.Resources.OfType(), r => r.Name == "myidentity"); Assert.Equal("myidentity", identityResource.Name); // Verify the compute resource has the identity annotation @@ -295,16 +304,21 @@ public async Task WithAzureUserAssignedIdentity_WithRoleAssignments_MultipleProj Assert.Collection(model.Resources, r => Assert.IsType(r), r => Assert.IsType(r), + // The environment's default ACR-pull identity is now a first-class model resource (#11256). + r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), r => Assert.IsType(r), - r => Assert.True(r is AzureRoleAssignmentResource { Name: "myapp-roles-mystorage" }), - r => Assert.True(r is AzureRoleAssignmentResource { Name: "myapp2-roles-mystorage" })); + // Three role-assignment modules: one per project plus the default ACR-pull identity's + // AcrPull role assignment (#11256). Asserted by type since their relative order is incidental. + r => Assert.IsType(r), + r => Assert.IsType(r), + r => Assert.IsType(r)); - // Verify the identity resource is the only one that exists - var identityResource = Assert.Single(model.Resources.OfType()); + // Verify the explicitly-constructed identity resource exists + var identityResource = Assert.Single(model.Resources.OfType(), r => r.Name == "myidentity"); Assert.Equal("myidentity", identityResource.Name); // Verify that both compute resources have the same identity annotation diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.bicep index d1203024fbc..3a33a1469f1 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.bicep @@ -1,32 +1,20 @@ -@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 userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_mi_outputs_clientid string + +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('envasplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -51,6 +39,6 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.json index aff9b2f4d4f..614a3ef42e7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceEnvironmentWithoutDashboardAddsEnvironmentResource.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.bicep index 643fb1fb539..fded421b258 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.bicep @@ -5,28 +5,16 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_mi_outputs_clientid string + +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('envasplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -64,7 +52,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -104,7 +92,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -156,9 +144,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.json index aff9b2f4d4f..614a3ef42e7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsDefaultLocation.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.bicep index e5d783a7680..01c26dbcde6 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.bicep @@ -5,28 +5,16 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_mi_outputs_clientid string + +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('envasplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -64,7 +52,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -104,7 +92,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -156,9 +144,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.json index aff9b2f4d4f..614a3ef42e7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocation.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.bicep index 67c97b129a5..6e696536e71 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.bicep @@ -5,30 +5,18 @@ param userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + +param env_mi_outputs_clientid string + param env_acr_outputs_name string param appInsightsLocation string -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('envasplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -66,7 +54,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -106,7 +94,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -158,9 +146,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.json index 43767c55cff..fdd8a4f993b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsLocationParam.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "appInsightsLocation": "{appInsightsLocation.value}", "userPrincipalId": "" diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsNormalizesBicepIdentifiers.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsNormalizesBicepIdentifiers.verified.bicep index 08a87488e0a..2fce3212e8b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsNormalizesBicepIdentifiers.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithApplicationInsightsNormalizesBicepIdentifiers.verified.bicep @@ -5,28 +5,16 @@ param userPrincipalId string = '' param tags object = { } -param env_1_acr_outputs_name string +param env_1_mi_outputs_id string -resource env_1_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_1_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_1_mi_outputs_clientid string + +param env_1_acr_outputs_name string resource env_1_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_1_acr_outputs_name } -resource env_1_acr_env_1_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_1_acr.id, env_1_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_1_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_1_acr -} - resource env_1_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('env1asplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -64,7 +52,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_1_mi.properties.clientId + acrUserManagedIdentityID: env_1_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -104,7 +92,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_1_mi.properties.clientId + value: env_1_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -156,9 +144,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_1_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_1_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_1_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_1_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_1_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_1_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_1_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.bicep index d702111eb40..7a1fbb8a6ee 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.bicep @@ -5,30 +5,18 @@ param userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + +param env_mi_outputs_clientid string + param env_acr_outputs_name string param existingappinsights_outputs_name string -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('envasplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -66,7 +54,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -106,7 +94,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -141,9 +129,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.json index 75f212c0623..526feef4c5b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddAppServiceWithExistingApplicationInsights.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "existingappinsights_outputs_name": "{existingAppInsights.outputs.name}", "userPrincipalId": "" diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.bicep index 38fae319461..eac83ba1d13 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.bicep @@ -5,28 +5,16 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_mi_outputs_clientid string + +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_asplan 'Microsoft.Web/serverfarms@2025-03-01' = { name: take('envasplan-${uniqueString(resourceGroup().id)}', 60) location: location @@ -64,7 +52,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -104,7 +92,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -135,9 +123,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.json index aff9b2f4d4f..614a3ef42e7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AddContainerAppEnvironmentAddsEnvironmentResource.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.bicep index 203ecbdf8a5..c8dd9c4bf82 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.bicep @@ -1,37 +1,25 @@ -@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 userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + +param env_mi_outputs_clientid string + param registryName string param sharedRg string param appServicePlanName string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} - resource acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: registryName scope: resourceGroup(sharedRg) } -resource acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: acr -} - resource env 'Microsoft.Web/serverfarms@2025-03-01' existing = { name: appServicePlanName scope: resourceGroup(sharedRg) @@ -47,6 +35,6 @@ output AZURE_CONTAINER_REGISTRY_NAME string = acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.json index 6f7ce79d856..0e143d04d4b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesEnvWithExistingPlanAndRegistry.verified.json @@ -2,9 +2,11 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "registryName": "{registryName.value}", "sharedRg": "{sharedRg.value}", "appServicePlanName": "{appServicePlanName.value}", "userPrincipalId": "" } -} +} \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#00.verified.bicep index 66244cac743..4d64d49b72f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#00.verified.bicep @@ -23,11 +23,21 @@ module env_acr 'env-acr/env-acr.bicep' = { } } +module env_mi 'env-mi/env-mi.bicep' = { + name: 'env-mi' + scope: rg + params: { + location: location + } +} + module env 'env/env.bicep' = { name: 'env' scope: rg params: { location: location + env_mi_outputs_id: env_mi.outputs.id + env_mi_outputs_clientid: env_mi.outputs.clientId env_acr_outputs_name: env_acr.outputs.name appServicePlanName: appServicePlanName appServicePlanResourceGroup: appServicePlanResourceGroup @@ -35,6 +45,16 @@ module env 'env/env.bicep' = { } } +module env_mi_roles_env_acr 'env-mi-roles-env-acr/env-mi-roles-env-acr.bicep' = { + name: 'env-mi-roles-env-acr' + scope: rg + params: { + location: location + env_acr_outputs_name: env_acr.outputs.name + principalId: env_mi.outputs.principalId + } +} + output env_AZURE_CONTAINER_REGISTRY_ENDPOINT string = env.outputs.AZURE_CONTAINER_REGISTRY_ENDPOINT output env_planId string = env.outputs.planId diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#01.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#01.verified.bicep index f7ec9b3e4d8..7f2b81d1c2e 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#01.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanPublishExistingAppServicePlan#01.verified.bicep @@ -1,36 +1,24 @@ -@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 userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + +param env_mi_outputs_clientid string + param env_acr_outputs_name string param appServicePlanName string param appServicePlanResourceGroup string -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env 'Microsoft.Web/serverfarms@2025-03-01' existing = { name: appServicePlanName scope: resourceGroup(appServicePlanResourceGroup) @@ -59,7 +47,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -99,7 +87,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -130,12 +118,12 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_PRINCIPAL_ID string = env_contributor_mi.properties.principalId -output AZURE_APP_SERVICE_DASHBOARD_URI string = 'https://${take('${toLower('env')}-${toLower('aspiredashboard')}-${uniqueString(resourceGroup().id)}', 60)}.azurewebsites.net' +output AZURE_APP_SERVICE_DASHBOARD_URI string = 'https://${take('${toLower('env')}-${toLower('aspiredashboard')}-${uniqueString(resourceGroup().id)}', 60)}.azurewebsites.net' \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.bicep index d2d885c954c..7f2b81d1c2e 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.bicep @@ -5,32 +5,20 @@ param userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + +param env_mi_outputs_clientid string + param env_acr_outputs_name string param appServicePlanName string param appServicePlanResourceGroup string -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env 'Microsoft.Web/serverfarms@2025-03-01' existing = { name: appServicePlanName scope: resourceGroup(appServicePlanResourceGroup) @@ -59,7 +47,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { numberOfWorkers: 1 linuxFxVersion: 'ASPIREDASHBOARD|1.0' acrUseManagedIdentityCreds: true - acrUserManagedIdentityID: env_mi.properties.clientId + acrUserManagedIdentityID: env_mi_outputs_clientid appSettings: [ { name: 'DASHBOARD__FRONTEND__AUTHMODE' @@ -99,7 +87,7 @@ resource dashboard 'Microsoft.Web/sites@2025-03-01' = { } { name: 'ALLOWED_MANAGED_IDENTITIES' - value: env_mi.properties.clientId + value: env_mi_outputs_clientid } { name: 'ASPIRE_ENVIRONMENT_NAME' @@ -130,9 +118,9 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi.properties.clientId +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_CLIENT_ID string = env_mi_outputs_clientid output AZURE_WEBSITE_CONTRIBUTOR_MANAGED_IDENTITY_ID string = env_contributor_mi.id diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.json index 0d492e11f13..021af29652d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.AzureAppServiceEnvironmentCanReferenceExistingAppServicePlan.verified.json @@ -2,6 +2,8 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", + "env_mi_outputs_clientid": "{env-mi.outputs.clientId}", "env_acr_outputs_name": "{env-acr.outputs.name}", "appServicePlanName": "{appServicePlanName.value}", "appServicePlanResourceGroup": "{appServicePlanResourceGroup.value}", diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.MultipleAzureAppServiceEnvironmentsSupported.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.MultipleAzureAppServiceEnvironmentsSupported.verified.json index f444e0a16c3..160200cdb8c 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.MultipleAzureAppServiceEnvironmentsSupported.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureAppServiceTests.MultipleAzureAppServiceEnvironmentsSupported.verified.json @@ -1,13 +1,19 @@ -{ +{ "resources": { "env1-acr": { "type": "azure.bicep.v0", "path": "env1-acr.module.bicep" }, + "env1-mi": { + "type": "azure.bicep.v0", + "path": "env1-mi.module.bicep" + }, "env1": { "type": "azure.bicep.v0", "path": "env1.module.bicep", "params": { + "env1_mi_outputs_id": "{env1-mi.outputs.id}", + "env1_mi_outputs_clientid": "{env1-mi.outputs.clientId}", "env1_acr_outputs_name": "{env1-acr.outputs.name}", "userPrincipalId": "" } @@ -16,10 +22,16 @@ "type": "azure.bicep.v0", "path": "env2-acr.module.bicep" }, + "env2-mi": { + "type": "azure.bicep.v0", + "path": "env2-mi.module.bicep" + }, "env2": { "type": "azure.bicep.v0", "path": "env2.module.bicep", "params": { + "env2_mi_outputs_id": "{env2-mi.outputs.id}", + "env2_mi_outputs_clientid": "{env2-mi.outputs.clientId}", "env2_acr_outputs_name": "{env2-acr.outputs.name}", "userPrincipalId": "" } @@ -97,6 +109,22 @@ "external": true } } + }, + "env1-mi-roles-env1-acr": { + "type": "azure.bicep.v0", + "path": "env1-mi-roles-env1-acr.module.bicep", + "params": { + "env1_acr_outputs_name": "{env1-acr.outputs.name}", + "principalId": "{env1-mi.outputs.principalId}" + } + }, + "env2-mi-roles-env2-acr": { + "type": "azure.bicep.v0", + "path": "env2-mi-roles-env2-acr.module.bicep", + "params": { + "env2_acr_outputs_name": "{env2-acr.outputs.name}", + "principalId": "{env2-mi.outputs.principalId}" + } } } } \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.bicep index f9d1b63e9fa..570f9e911da 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.bicep @@ -9,6 +9,8 @@ param environmentName string param sharedRg string +param env_mi_outputs_id string + param env_acr_outputs_name string resource env 'Microsoft.App/managedEnvironments@2025-07-01' existing = { @@ -16,31 +18,15 @@ resource env 'Microsoft.App/managedEnvironments@2025-07-01' existing = { scope: resourceGroup(sharedRg) } -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.json index 9bc677f1a95..6483af523bf 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_PublishGeneratesThinModuleReferencingExistingEnvironment.verified.json @@ -4,6 +4,7 @@ "params": { "environmentName": "{environmentName.value}", "sharedRg": "{sharedRg.value}", + "env_mi_outputs_id": "{env-mi.outputs.id}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.bicep index f8677f05beb..5fa2f0b9e09 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.bicep @@ -9,6 +9,8 @@ param environmentName string param sharedRg string +param env_mi_outputs_id string + param registryName string resource env 'Microsoft.App/managedEnvironments@2025-07-01' existing = { @@ -16,32 +18,16 @@ resource env 'Microsoft.App/managedEnvironments@2025-07-01' existing = { scope: resourceGroup(sharedRg) } -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} - resource acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: registryName scope: resourceGroup(sharedRg) } -resource acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: acr -} - output AZURE_CONTAINER_REGISTRY_NAME string = acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.json index c38700cd900..dc9b486080a 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.AsExisting_WithExplicitContainerRegistry_PublishGeneratesThinModule.verified.json @@ -4,6 +4,7 @@ "params": { "environmentName": "{environmentName.value}", "sharedRg": "{sharedRg.value}", + "env_mi_outputs_id": "{env-mi.outputs.id}", "registryName": "{registryName.value}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#00.verified.bicep index 288c8b3680b..5f9d16109b8 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#00.verified.bicep @@ -19,16 +19,35 @@ module acr 'acr/acr.bicep' = { } } +module env_mi 'env-mi/env-mi.bicep' = { + name: 'env-mi' + scope: rg + params: { + location: location + } +} + module env 'env/env.bicep' = { name: 'env' scope: rg params: { location: location + env_mi_outputs_id: env_mi.outputs.id acr_outputs_name: acr.outputs.name userPrincipalId: principalId } } +module env_mi_roles_acr 'env-mi-roles-acr/env-mi-roles-acr.bicep' = { + name: 'env-mi-roles-acr' + scope: rg + params: { + location: location + acr_outputs_name: acr.outputs.name + principalId: env_mi.outputs.principalId + } +} + output env_AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = env.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN output env_AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = env.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_ID \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#01.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#01.verified.bicep index 0e67ae0d495..c4b76d46fbc 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#01.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureContainerRegistry_PublishSucceeds_WhenDefaultRegistryIsRedundant#01.verified.bicep @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param acr_outputs_name string resource acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: acr_outputs_name } -resource acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -75,7 +61,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.bicep index dc70c22c517..950c6772488 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.bicep @@ -5,32 +5,18 @@ param userPrincipalId string = '' param tags object = { } +param app_host_mi_outputs_id string + param app_host_acr_outputs_name string param log_env_shared_name string param log_env_shared_rg string -resource app_host_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('app_host_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} - resource app_host_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: app_host_acr_outputs_name } -resource app_host_acr_app_host_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(app_host_acr.id, app_host_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: app_host_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: app_host_acr -} - resource log_env_shared 'Microsoft.OperationalInsights/workspaces@2025-02-01' existing = { name: log_env_shared_name scope: resourceGroup(log_env_shared_rg) @@ -73,7 +59,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = app_host_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = app_host_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = app_host_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = app_host_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = app_host.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.json index 0d767c250b8..92fb8d73dd5 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithAzureLogAnalyticsWorkspace_RespectsExistingWorkspaceInDifferentResourceGroup.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "app-host.module.bicep", "params": { + "app_host_mi_outputs_id": "{app-host-mi.outputs.id}", "app_host_acr_outputs_name": "{app-host-acr.outputs.name}", "log_env_shared_name": "{log-env-shared-name.value}", "log_env_shared_rg": "{log-env-shared-rg.value}", diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithDelegatedSubnet_ConfiguresVnetConfiguration.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithDelegatedSubnet_ConfiguresVnetConfiguration.verified.bicep index 14a03d3f091..ba036aed4d9 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithDelegatedSubnet_ConfiguresVnetConfiguration.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppEnvironmentExtensionsTests.WithDelegatedSubnet_ConfiguresVnetConfiguration.verified.bicep @@ -5,30 +5,16 @@ param userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + param env_acr_outputs_name string param myvnet_outputs_container_apps_subnet_id string -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -80,7 +66,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.bicep index 1b38b2f2fa3..59ceb611fcb 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.bicep @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -118,7 +104,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.json index aff9b2f4d4f..a829dbb695d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=False.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.bicep index 053997260ea..c43e171712f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.bicep @@ -5,30 +5,16 @@ param userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + param env_acr_outputs_name string var resourceToken = uniqueString(resourceGroup().id) -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: 'mi-${resourceToken}' - location: location - tags: tags -} - resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: replace('acr-${resourceToken}', '-', '') } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: 'law-${resourceToken}' location: location @@ -120,7 +106,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.json index aff9b2f4d4f..a829dbb695d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentAddsEnvironmentResource_useAzdNaming=True.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWithCompactNamingPreservesUniqueString.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWithCompactNamingPreservesUniqueString.verified.bicep index e0ab7783fd4..f61f92d74f9 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWithCompactNamingPreservesUniqueString.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.AddContainerAppEnvironmentWithCompactNamingPreservesUniqueString.verified.bicep @@ -5,30 +5,16 @@ param userPrincipalId string = '' param tags object = { } +param my_long_env_name_mi_outputs_id string + param my_long_env_name_acr_outputs_name string var resourceToken = uniqueString(resourceGroup().id) -resource my_long_env_name_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('my_long_env_name_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} - resource my_long_env_name_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: my_long_env_name_acr_outputs_name } -resource my_long_env_name_acr_my_long_env_name_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(my_long_env_name_acr.id, my_long_env_name_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: my_long_env_name_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: my_long_env_name_acr -} - resource my_long_env_name_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('mylongenvnamelaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -120,7 +106,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = my_long_env_name_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = my_long_env_name_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = my_long_env_name_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = my_long_env_name_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = my_long_env_name.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.CompactNamingMultipleVolumesHaveUniqueNames.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.CompactNamingMultipleVolumesHaveUniqueNames.verified.bicep index 607feb19989..393f29d8989 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.CompactNamingMultipleVolumesHaveUniqueNames.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.CompactNamingMultipleVolumesHaveUniqueNames.verified.bicep @@ -5,30 +5,16 @@ param userPrincipalId string = '' param tags object = { } +param my_ace_mi_outputs_id string + param my_ace_acr_outputs_name string var resourceToken = uniqueString(resourceGroup().id) -resource my_ace_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('my_ace_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} - resource my_ace_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: my_ace_acr_outputs_name } -resource my_ace_acr_my_ace_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(my_ace_acr.id, my_ace_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: my_ace_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: my_ace_acr -} - resource my_ace_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('myacelaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -168,7 +154,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = my_ace_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = my_ace_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = my_ace_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = my_ace_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = my_ace.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.bicep index c6eff64aca2..c163c3f2468 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.bicep @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param customregistry_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param customregistry_outputs_name string resource customregistry 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: customregistry_outputs_name } -resource customregistry_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(customregistry.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: customregistry -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -75,7 +61,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = customregistry.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = customregistry.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.json index cc8f2653782..19d2f760128 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomRegistry#00.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", "customregistry_outputs_name": "{customregistry.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.bicep index e7bed670938..c31df39957b 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.bicep @@ -5,30 +5,16 @@ param userPrincipalId string = '' param tags object = { } +param env_mi_outputs_id string + param env_acr_outputs_name string param customworkspace_outputs_name string -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@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource customworkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' existing = { name: customworkspace_outputs_name } @@ -70,7 +56,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.json index 0a71a394f85..540467726ef 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#00.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", "env_acr_outputs_name": "{env-acr.outputs.name}", "customworkspace_outputs_name": "{customworkspace.outputs.name}", "userPrincipalId": "" diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.bicep index 49ebfaebad4..4951c9acd4e 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.bicep @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -67,7 +53,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.json index aff9b2f4d4f..a829dbb695d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardDisabled.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.bicep index 1340440b1f3..a71fe381fac 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.bicep @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -75,7 +61,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.json index aff9b2f4d4f..a829dbb695d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithDashboardEnabled.verified.json @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "env.module.bicep", "params": { + "env_mi_outputs_id": "{env-mi.outputs.id}", "env_acr_outputs_name": "{env-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleAzureContainerAppEnvironmentsSupported.verified.json b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleAzureContainerAppEnvironmentsSupported.verified.json index 90767a4c7c5..46f69f7436d 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleAzureContainerAppEnvironmentsSupported.verified.json +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleAzureContainerAppEnvironmentsSupported.verified.json @@ -4,10 +4,15 @@ "type": "azure.bicep.v0", "path": "env1-acr.module.bicep" }, + "env1-mi": { + "type": "azure.bicep.v0", + "path": "env1-mi.module.bicep" + }, "env1": { "type": "azure.bicep.v0", "path": "env1.module.bicep", "params": { + "env1_mi_outputs_id": "{env1-mi.outputs.id}", "env1_acr_outputs_name": "{env1-acr.outputs.name}", "userPrincipalId": "" } @@ -16,10 +21,15 @@ "type": "azure.bicep.v0", "path": "env2-acr.module.bicep" }, + "env2-mi": { + "type": "azure.bicep.v0", + "path": "env2-mi.module.bicep" + }, "env2": { "type": "azure.bicep.v0", "path": "env2.module.bicep", "params": { + "env2_mi_outputs_id": "{env2-mi.outputs.id}", "env2_acr_outputs_name": "{env2-acr.outputs.name}", "userPrincipalId": "" } @@ -47,6 +57,22 @@ "env2_outputs_azure_container_apps_environment_id": "{env2.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_ID}" } } + }, + "env1-mi-roles-env1-acr": { + "type": "azure.bicep.v0", + "path": "env1-mi-roles-env1-acr.module.bicep", + "params": { + "env1_acr_outputs_name": "{env1-acr.outputs.name}", + "principalId": "{env1-mi.outputs.principalId}" + } + }, + "env2-mi-roles-env2-acr": { + "type": "azure.bicep.v0", + "path": "env2-mi-roles-env2-acr.module.bicep", + "params": { + "env2_acr_outputs_name": "{env2-acr.outputs.name}", + "principalId": "{env2-mi.outputs.principalId}" + } } } } \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#02.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#02.verified.txt index 5f4e5709703..5ee6d3da2db 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#02.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#02.verified.txt @@ -2,6 +2,7 @@ "type": "azure.bicep.v0", "path": "my-ace.module.bicep", "params": { + "my_ace_mi_outputs_id": "{my-ace-mi.outputs.id}", "my_ace_acr_outputs_name": "{my-ace-acr.outputs.name}", "userPrincipalId": "" } diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#03.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#03.verified.txt index d03fabe909a..bcab5c7f7c4 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#03.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.MultipleVolumesHaveUniqueNamesInBicep#03.verified.txt @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param my_ace_acr_outputs_name string +param my_ace_mi_outputs_id string -resource my_ace_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('my_ace_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param my_ace_acr_outputs_name string resource my_ace_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: my_ace_acr_outputs_name } -resource my_ace_acr_my_ace_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(my_ace_acr.id, my_ace_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: my_ace_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: my_ace_acr -} - resource my_ace_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('myacelaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -166,7 +152,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = my_ace_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = my_ace_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = my_ace_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = my_ace_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = my_ace.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt index a2bcdea5cc5..5df73119910 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithAzureResourceDependencies_DoesNotHang_step=diagnostics.verified.txt @@ -5,7 +5,7 @@ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS This diagnostic output shows the complete pipeline dependency graph structure. Use this to understand step relationships and troubleshoot execution issues. -Total steps defined: 38 +Total steps defined: 41 Analysis for full pipeline execution (showing all steps and their relationships) @@ -14,44 +14,47 @@ EXECUTION ORDER This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. - 1. azure-prepare-resources - 2. validate-compute-environments - 3. prepare-azure-app-service-env - 4. validate-azure-app-service - 5. before-start - 6. process-parameters - 7. build-prereq - 8. check-container-runtime - 9. validate-build-only-container-references - 10. deploy-prereq - 11. build-api - 12. build - 13. validate-azure-login - 14. create-provisioning-context - 15. provision-api-identity - 16. provision-kv - 17. provision-api-roles-kv - 18. provision-env-acr - 19. provision-env - 20. login-to-acr-env-acr - 21. push-prereq - 22. push-api - 23. provision-api-website - 24. print-api-summary - 25. provision-azure-bicep-resources - 26. print-dashboard-url-env - 27. deploy - 28. deploy-api - 29. destroy-prereq - 30. destroy-azure-azure-environment - 31. destroy - 32. diagnostics - 33. publish-prereq - 34. publish-azure-environment - 35. validate-appservice-config-env - 36. publish - 37. publish-manifest - 38. push + 1. finalize-azure-app-service-acr-pull-roles + 2. azure-prepare-resources + 3. validate-compute-environments + 4. prepare-azure-app-service-env + 5. validate-azure-app-service + 6. before-start + 7. process-parameters + 8. build-prereq + 9. check-container-runtime + 10. validate-build-only-container-references + 11. deploy-prereq + 12. build-api + 13. build + 14. validate-azure-login + 15. create-provisioning-context + 16. provision-api-identity + 17. provision-kv + 18. provision-api-roles-kv + 19. provision-env-acr + 20. provision-env-mi + 21. provision-env + 22. login-to-acr-env-acr + 23. push-prereq + 24. push-api + 25. provision-api-website + 26. print-api-summary + 27. provision-env-mi-roles-env-acr + 28. provision-azure-bicep-resources + 29. print-dashboard-url-env + 30. deploy + 31. deploy-api + 32. destroy-prereq + 33. destroy-azure-azure-environment + 34. destroy + 35. diagnostics + 36. publish-prereq + 37. publish-azure-environment + 38. validate-appservice-config-env + 39. publish + 40. publish-manifest + 41. push DETAILED STEP ANALYSIS ====================== @@ -60,7 +63,7 @@ Shows each step's dependencies, associated resources, tags, and descriptions. Step: azure-prepare-resources Description: Prepares the Azure resources. - Dependencies: none + Dependencies: ✓ finalize-azure-app-service-acr-pull-roles Resource: azure-environment (AzureEnvironmentResource) Step: before-start @@ -121,6 +124,9 @@ Step: diagnostics Description: Dumps dependency graph information for troubleshooting pipeline execution. Dependencies: none +Step: finalize-azure-app-service-acr-pull-roles + Dependencies: none + Step: login-to-acr-env-acr Dependencies: ✓ provision-env-acr Resource: env-acr (AzureContainerRegistryResource) @@ -167,13 +173,13 @@ Step: provision-api-website Step: provision-azure-bicep-resources Description: Aggregation step for all Azure infrastructure provisioning operations. - Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-api-identity, ✓ provision-api-roles-kv, ✓ provision-api-website, ✓ provision-env, ✓ provision-env-acr, ✓ provision-kv + Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-api-identity, ✓ provision-api-roles-kv, ✓ provision-api-website, ✓ provision-env, ✓ provision-env-acr, ✓ provision-env-mi, ✓ provision-env-mi-roles-env-acr, ✓ provision-kv Resource: azure-environment (AzureEnvironmentResource) Tags: provision-infra Step: provision-env Description: Provisions the Azure Bicep resource env using Azure infrastructure. - Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr + Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr, ✓ provision-env-mi Resource: env (AzureAppServiceEnvironmentResource) Tags: provision-infra @@ -183,6 +189,18 @@ Step: provision-env-acr Resource: env-acr (AzureContainerRegistryResource) Tags: provision-infra +Step: provision-env-mi + Description: Provisions the Azure Bicep resource env-mi using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: env-mi (AzureUserAssignedIdentityResource) + Tags: provision-infra + +Step: provision-env-mi-roles-env-acr + Description: Provisions the Azure Bicep resource env-mi-roles-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr, ✓ provision-env-mi + Resource: env-mi-roles-env-acr (AzureRoleAssignmentResource) + Tags: provision-infra + Step: provision-kv Description: Provisions the Azure Bicep resource kv using Azure infrastructure. Dependencies: ✓ create-provisioning-context @@ -252,18 +270,20 @@ Shows what steps would run for each possible target step and in what order. Steps at the same level can run concurrently. ───────────────────────────────────────────────────────────────────────────── If targeting 'azure-prepare-resources': - Direct dependencies: none - Total steps: 1 + Direct dependencies: finalize-azure-app-service-acr-pull-roles + Total steps: 2 Execution order: - [0] azure-prepare-resources + [0] finalize-azure-app-service-acr-pull-roles + [1] azure-prepare-resources If targeting 'before-start': Direct dependencies: azure-prepare-resources, prepare-azure-app-service-env, validate-azure-app-service, validate-compute-environments - Total steps: 5 + Total steps: 6 Execution order: - [0] azure-prepare-resources | validate-azure-app-service | validate-compute-environments (parallel) - [1] prepare-azure-app-service-env - [2] before-start + [0] finalize-azure-app-service-acr-pull-roles | validate-azure-app-service | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-app-service-env + [3] before-start If targeting 'build': Direct dependencies: build-api @@ -306,14 +326,14 @@ If targeting 'create-provisioning-context': If targeting 'deploy': Direct dependencies: build-api, create-provisioning-context, print-api-summary, print-dashboard-url-env, provision-azure-bicep-resources, validate-azure-login - Total steps: 21 + Total steps: 23 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-env-acr | provision-kv (parallel) - [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env (parallel) + [4] provision-api-identity | provision-env-acr | provision-env-mi | provision-kv (parallel) + [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env | provision-env-mi-roles-env-acr (parallel) [6] push-prereq [7] push-api [8] provision-api-website @@ -323,13 +343,13 @@ If targeting 'deploy': If targeting 'deploy-api': Direct dependencies: print-api-summary - Total steps: 19 + Total steps: 20 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-env-acr | provision-kv (parallel) + [4] provision-api-identity | provision-env-acr | provision-env-mi | provision-kv (parallel) [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env (parallel) [6] push-prereq [7] push-api @@ -371,6 +391,12 @@ If targeting 'diagnostics': Execution order: [0] diagnostics +If targeting 'finalize-azure-app-service-acr-pull-roles': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] finalize-azure-app-service-acr-pull-roles + If targeting 'login-to-acr-env-acr': Direct dependencies: provision-env-acr Total steps: 7 @@ -384,20 +410,21 @@ If targeting 'login-to-acr-env-acr': If targeting 'prepare-azure-app-service-env': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 4 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-azure-app-service-env + [0] finalize-azure-app-service-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-app-service-env If targeting 'print-api-summary': Direct dependencies: provision-api-website - Total steps: 18 + Total steps: 19 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-env-acr | provision-kv (parallel) + [4] provision-api-identity | provision-env-acr | provision-env-mi | provision-kv (parallel) [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env (parallel) [6] push-prereq [7] push-api @@ -406,14 +433,14 @@ If targeting 'print-api-summary': If targeting 'print-dashboard-url-env': Direct dependencies: provision-azure-bicep-resources, provision-env - Total steps: 19 + Total steps: 21 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-env-acr | provision-kv (parallel) - [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env (parallel) + [4] provision-api-identity | provision-env-acr | provision-env-mi | provision-kv (parallel) + [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env | provision-env-mi-roles-env-acr (parallel) [6] push-prereq [7] push-api [8] provision-api-website @@ -449,42 +476,42 @@ If targeting 'provision-api-roles-kv': If targeting 'provision-api-website': Direct dependencies: create-provisioning-context, provision-api-identity, provision-api-roles-kv, provision-env, provision-kv, push-api - Total steps: 17 + Total steps: 18 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-env-acr | provision-kv (parallel) + [4] provision-api-identity | provision-env-acr | provision-env-mi | provision-kv (parallel) [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env (parallel) [6] push-prereq [7] push-api [8] provision-api-website If targeting 'provision-azure-bicep-resources': - Direct dependencies: create-provisioning-context, deploy-prereq, provision-api-identity, provision-api-roles-kv, provision-api-website, provision-env, provision-env-acr, provision-kv - Total steps: 18 + Direct dependencies: create-provisioning-context, deploy-prereq, provision-api-identity, provision-api-roles-kv, provision-api-website, provision-env, provision-env-acr, provision-env-mi, provision-env-mi-roles-env-acr, provision-kv + Total steps: 20 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-env-acr | provision-kv (parallel) - [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env (parallel) + [4] provision-api-identity | provision-env-acr | provision-env-mi | provision-kv (parallel) + [5] login-to-acr-env-acr | provision-api-roles-kv | provision-env | provision-env-mi-roles-env-acr (parallel) [6] push-prereq [7] push-api [8] provision-api-website [9] provision-azure-bicep-resources If targeting 'provision-env': - Direct dependencies: create-provisioning-context, provision-env-acr - Total steps: 7 + Direct dependencies: create-provisioning-context, provision-env-acr, provision-env-mi + Total steps: 8 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-env-acr + [4] provision-env-acr | provision-env-mi (parallel) [5] provision-env If targeting 'provision-env-acr': @@ -497,6 +524,27 @@ If targeting 'provision-env-acr': [3] create-provisioning-context [4] provision-env-acr +If targeting 'provision-env-mi': + Direct dependencies: create-provisioning-context + Total steps: 6 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-env-mi + +If targeting 'provision-env-mi-roles-env-acr': + Direct dependencies: create-provisioning-context, provision-env-acr, provision-env-mi + Total steps: 8 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-env-acr | provision-env-mi (parallel) + [5] provision-env-mi-roles-env-acr + If targeting 'provision-kv': Direct dependencies: create-provisioning-context Total steps: 6 diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt index 9cbca8c4cc3..d04598b6ef1 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithFoundryAndAzureContainerApps_CreatesCorrectDependencies.verified.txt @@ -5,7 +5,7 @@ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS This diagnostic output shows the complete pipeline dependency graph structure. Use this to understand step relationships and troubleshoot execution issues. -Total steps defined: 43 +Total steps defined: 46 Analysis for full pipeline execution (showing all steps and their relationships) @@ -14,49 +14,52 @@ EXECUTION ORDER This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. - 1. azure-prepare-resources - 2. validate-compute-environments - 3. prepare-azure-container-apps-aca-env - 4. prepare-foundry-project-foundry-project - 5. validate-azure-container-apps - 6. before-start - 7. process-parameters - 8. build-prereq - 9. check-container-runtime - 10. validate-build-only-container-references - 11. deploy-prereq - 12. build-agent - 13. build-api - 14. build - 15. validate-azure-login - 16. create-provisioning-context - 17. provision-aca-env-acr - 18. provision-aca-env - 19. login-to-acr-aca-env-acr - 20. provision-foundry-project-acr - 21. login-to-acr-foundry-project-acr - 22. push-prereq - 23. push-api - 24. provision-api-containerapp - 25. provision-foundry - 26. provision-foundry-project - 27. provision-azure-bicep-resources - 28. compute-endpoints-foundry-project - 29. push-agent - 30. deploy-agent-ha - 31. print-api-summary - 32. print-dashboard-url-aca-env - 33. deploy - 34. deploy-api - 35. destroy-prereq - 36. destroy-azure-azure-environment - 37. destroy - 38. diagnostics - 39. publish-prereq - 40. publish-azure-environment - 41. publish - 42. publish-manifest - 43. push + 1. finalize-azure-container-apps-acr-pull-roles + 2. azure-prepare-resources + 3. validate-compute-environments + 4. prepare-azure-container-apps-aca-env + 5. prepare-foundry-project-foundry-project + 6. validate-azure-container-apps + 7. before-start + 8. process-parameters + 9. build-prereq + 10. check-container-runtime + 11. validate-build-only-container-references + 12. deploy-prereq + 13. build-agent + 14. build-api + 15. build + 16. validate-azure-login + 17. create-provisioning-context + 18. provision-aca-env-acr + 19. provision-aca-env-mi + 20. provision-aca-env + 21. provision-aca-env-mi-roles-aca-env-acr + 22. login-to-acr-aca-env-acr + 23. provision-foundry-project-acr + 24. login-to-acr-foundry-project-acr + 25. push-prereq + 26. push-api + 27. provision-api-containerapp + 28. provision-foundry + 29. provision-foundry-project + 30. provision-azure-bicep-resources + 31. compute-endpoints-foundry-project + 32. push-agent + 33. deploy-agent-ha + 34. print-api-summary + 35. print-dashboard-url-aca-env + 36. deploy + 37. deploy-api + 38. destroy-prereq + 39. destroy-azure-azure-environment + 40. destroy + 41. diagnostics + 42. publish-prereq + 43. publish-azure-environment + 44. publish + 45. publish-manifest + 46. push DETAILED STEP ANALYSIS ====================== @@ -65,7 +68,7 @@ Shows each step's dependencies, associated resources, tags, and descriptions. Step: azure-prepare-resources Description: Prepares the Azure resources. - Dependencies: none + Dependencies: ✓ finalize-azure-container-apps-acr-pull-roles Resource: azure-environment (AzureEnvironmentResource) Step: before-start @@ -141,6 +144,9 @@ Step: diagnostics Description: Dumps dependency graph information for troubleshooting pipeline execution. Dependencies: none +Step: finalize-azure-container-apps-acr-pull-roles + Dependencies: none + Step: login-to-acr-aca-env-acr Dependencies: ✓ provision-aca-env-acr Resource: aca-env-acr (AzureContainerRegistryResource) @@ -179,7 +185,7 @@ Step: process-parameters Step: provision-aca-env Description: Provisions the Azure Bicep resource aca-env using Azure infrastructure. - Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr + Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr, ✓ provision-aca-env-mi Resource: aca-env (AzureContainerAppEnvironmentResource) Tags: provision-infra @@ -189,6 +195,18 @@ Step: provision-aca-env-acr Resource: aca-env-acr (AzureContainerRegistryResource) Tags: provision-infra +Step: provision-aca-env-mi + Description: Provisions the Azure Bicep resource aca-env-mi using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: aca-env-mi (AzureUserAssignedIdentityResource) + Tags: provision-infra + +Step: provision-aca-env-mi-roles-aca-env-acr + Description: Provisions the Azure Bicep resource aca-env-mi-roles-aca-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr, ✓ provision-aca-env-mi + Resource: aca-env-mi-roles-aca-env-acr (AzureRoleAssignmentResource) + Tags: provision-infra + Step: provision-api-containerapp Description: Provisions the Azure Bicep resource api-containerapp using Azure infrastructure. Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env, ✓ push-api @@ -197,7 +215,7 @@ Step: provision-api-containerapp Step: provision-azure-bicep-resources Description: Aggregation step for all Azure infrastructure provisioning operations. - Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-aca-env, ✓ provision-aca-env-acr, ✓ provision-api-containerapp, ✓ provision-foundry, ✓ provision-foundry-project, ✓ provision-foundry-project-acr + Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-aca-env, ✓ provision-aca-env-acr, ✓ provision-aca-env-mi, ✓ provision-aca-env-mi-roles-aca-env-acr, ✓ provision-api-containerapp, ✓ provision-foundry, ✓ provision-foundry-project, ✓ provision-foundry-project-acr Resource: azure-environment (AzureEnvironmentResource) Tags: provision-infra @@ -282,18 +300,20 @@ Shows what steps would run for each possible target step and in what order. Steps at the same level can run concurrently. ───────────────────────────────────────────────────────────────────────────── If targeting 'azure-prepare-resources': - Direct dependencies: none - Total steps: 1 + Direct dependencies: finalize-azure-container-apps-acr-pull-roles + Total steps: 2 Execution order: - [0] azure-prepare-resources + [0] finalize-azure-container-apps-acr-pull-roles + [1] azure-prepare-resources If targeting 'before-start': Direct dependencies: azure-prepare-resources, prepare-azure-container-apps-aca-env, prepare-foundry-project-foundry-project, validate-azure-container-apps, validate-compute-environments - Total steps: 6 + Total steps: 7 Execution order: - [0] azure-prepare-resources | validate-azure-container-apps | validate-compute-environments (parallel) - [1] prepare-azure-container-apps-aca-env | prepare-foundry-project-foundry-project (parallel) - [2] before-start + [0] finalize-azure-container-apps-acr-pull-roles | validate-azure-container-apps | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-container-apps-aca-env | prepare-foundry-project-foundry-project (parallel) + [3] before-start If targeting 'build': Direct dependencies: build-agent, build-api @@ -335,14 +355,14 @@ If targeting 'check-container-runtime': If targeting 'compute-endpoints-foundry-project': Direct dependencies: provision-azure-bicep-resources - Total steps: 20 + Total steps: 22 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) - [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr | provision-foundry-project (parallel) [6] push-prereq [7] push-api [8] provision-api-containerapp @@ -360,14 +380,14 @@ If targeting 'create-provisioning-context': If targeting 'deploy': Direct dependencies: build-agent, build-api, compute-endpoints-foundry-project, create-provisioning-context, deploy-agent-ha, print-api-summary, print-dashboard-url-aca-env, provision-azure-bicep-resources, validate-azure-login - Total steps: 26 + Total steps: 28 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-agent | build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) - [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr | provision-foundry-project (parallel) [6] push-prereq [7] push-agent | push-api (parallel) [8] provision-api-containerapp @@ -377,14 +397,14 @@ If targeting 'deploy': If targeting 'deploy-agent-ha': Direct dependencies: deploy-prereq, provision-azure-bicep-resources, push-agent - Total steps: 22 + Total steps: 24 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-agent | build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) - [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr | provision-foundry-project (parallel) [6] push-prereq [7] push-agent | push-api (parallel) [8] provision-api-containerapp @@ -393,13 +413,13 @@ If targeting 'deploy-agent-ha': If targeting 'deploy-api': Direct dependencies: print-api-summary - Total steps: 18 + Total steps: 19 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry-project-acr (parallel) [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env (parallel) [6] push-prereq [7] push-api @@ -441,6 +461,12 @@ If targeting 'diagnostics': Execution order: [0] diagnostics +If targeting 'finalize-azure-container-apps-acr-pull-roles': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] finalize-azure-container-apps-acr-pull-roles + If targeting 'login-to-acr-aca-env-acr': Direct dependencies: provision-aca-env-acr Total steps: 7 @@ -465,27 +491,29 @@ If targeting 'login-to-acr-foundry-project-acr': If targeting 'prepare-azure-container-apps-aca-env': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 4 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-azure-container-apps-aca-env + [0] finalize-azure-container-apps-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-container-apps-aca-env If targeting 'prepare-foundry-project-foundry-project': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 4 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-foundry-project-foundry-project + [0] finalize-azure-container-apps-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-foundry-project-foundry-project If targeting 'print-api-summary': Direct dependencies: provision-api-containerapp - Total steps: 17 + Total steps: 18 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry-project-acr (parallel) [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env (parallel) [6] push-prereq [7] push-api @@ -494,14 +522,14 @@ If targeting 'print-api-summary': If targeting 'print-dashboard-url-aca-env': Direct dependencies: provision-aca-env, provision-azure-bicep-resources - Total steps: 20 + Total steps: 22 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) - [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr | provision-foundry-project (parallel) [6] push-prereq [7] push-api [8] provision-api-containerapp @@ -515,14 +543,14 @@ If targeting 'process-parameters': [0] process-parameters If targeting 'provision-aca-env': - Direct dependencies: create-provisioning-context, provision-aca-env-acr - Total steps: 7 + Direct dependencies: create-provisioning-context, provision-aca-env-acr, provision-aca-env-mi + Total steps: 8 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-aca-env-acr + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) [5] provision-aca-env If targeting 'provision-aca-env-acr': @@ -535,30 +563,51 @@ If targeting 'provision-aca-env-acr': [3] create-provisioning-context [4] provision-aca-env-acr +If targeting 'provision-aca-env-mi': + Direct dependencies: create-provisioning-context + Total steps: 6 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-mi + +If targeting 'provision-aca-env-mi-roles-aca-env-acr': + Direct dependencies: create-provisioning-context, provision-aca-env-acr, provision-aca-env-mi + Total steps: 8 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) + [5] provision-aca-env-mi-roles-aca-env-acr + If targeting 'provision-api-containerapp': Direct dependencies: create-provisioning-context, provision-aca-env, push-api - Total steps: 16 + Total steps: 17 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry-project-acr (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry-project-acr (parallel) [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env (parallel) [6] push-prereq [7] push-api [8] provision-api-containerapp If targeting 'provision-azure-bicep-resources': - Direct dependencies: create-provisioning-context, deploy-prereq, provision-aca-env, provision-aca-env-acr, provision-api-containerapp, provision-foundry, provision-foundry-project, provision-foundry-project-acr - Total steps: 19 + Direct dependencies: create-provisioning-context, deploy-prereq, provision-aca-env, provision-aca-env-acr, provision-aca-env-mi, provision-aca-env-mi-roles-aca-env-acr, provision-api-containerapp, provision-foundry, provision-foundry-project, provision-foundry-project-acr + Total steps: 21 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aca-env-acr | provision-foundry | provision-foundry-project-acr (parallel) - [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-foundry-project (parallel) + [4] provision-aca-env-acr | provision-aca-env-mi | provision-foundry | provision-foundry-project-acr (parallel) + [5] login-to-acr-aca-env-acr | login-to-acr-foundry-project-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr | provision-foundry-project (parallel) [6] push-prereq [7] push-api [8] provision-api-containerapp diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt index ae9ae7873e5..de264742e38 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithMultipleComputeEnvironments_Works_step=diagnostics.verified.txt @@ -5,7 +5,7 @@ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS This diagnostic output shows the complete pipeline dependency graph structure. Use this to understand step relationships and troubleshoot execution issues. -Total steps defined: 50 +Total steps defined: 56 Analysis for full pipeline execution (showing all steps and their relationships) @@ -14,56 +14,62 @@ EXECUTION ORDER This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. - 1. azure-prepare-resources - 2. validate-compute-environments - 3. prepare-azure-app-service-aas-env - 4. prepare-azure-container-apps-aca-env - 5. validate-azure-app-service - 6. validate-azure-container-apps - 7. before-start - 8. process-parameters - 9. build-prereq - 10. check-container-runtime - 11. validate-build-only-container-references - 12. deploy-prereq - 13. build-api-service - 14. build-python-app - 15. build - 16. validate-azure-login - 17. create-provisioning-context - 18. provision-aas-env-acr - 19. provision-aas-env - 20. login-to-acr-aas-env-acr - 21. provision-aca-env-acr - 22. login-to-acr-aca-env-acr - 23. push-prereq - 24. push-api-service - 25. provision-api-service-website - 26. print-api-service-summary - 27. provision-aca-env - 28. provision-cache-containerapp - 29. print-cache-summary - 30. push-python-app - 31. provision-python-app-containerapp - 32. provision-storage - 33. provision-azure-bicep-resources - 34. print-dashboard-url-aas-env - 35. print-dashboard-url-aca-env - 36. print-python-app-summary - 37. deploy - 38. deploy-api-service - 39. deploy-cache - 40. deploy-python-app - 41. destroy-prereq - 42. destroy-azure-azure-environment - 43. destroy - 44. diagnostics - 45. publish-prereq - 46. publish-azure-environment - 47. validate-appservice-config-aas-env - 48. publish - 49. publish-manifest - 50. push + 1. finalize-azure-app-service-acr-pull-roles + 2. finalize-azure-container-apps-acr-pull-roles + 3. azure-prepare-resources + 4. validate-compute-environments + 5. prepare-azure-app-service-aas-env + 6. prepare-azure-container-apps-aca-env + 7. validate-azure-app-service + 8. validate-azure-container-apps + 9. before-start + 10. process-parameters + 11. build-prereq + 12. check-container-runtime + 13. validate-build-only-container-references + 14. deploy-prereq + 15. build-api-service + 16. build-python-app + 17. build + 18. validate-azure-login + 19. create-provisioning-context + 20. provision-aas-env-acr + 21. provision-aas-env-mi + 22. provision-aas-env + 23. login-to-acr-aas-env-acr + 24. provision-aca-env-acr + 25. login-to-acr-aca-env-acr + 26. push-prereq + 27. push-api-service + 28. provision-api-service-website + 29. print-api-service-summary + 30. provision-aca-env-mi + 31. provision-aca-env + 32. provision-cache-containerapp + 33. print-cache-summary + 34. provision-aas-env-mi-roles-aas-env-acr + 35. provision-aca-env-mi-roles-aca-env-acr + 36. push-python-app + 37. provision-python-app-containerapp + 38. provision-storage + 39. provision-azure-bicep-resources + 40. print-dashboard-url-aas-env + 41. print-dashboard-url-aca-env + 42. print-python-app-summary + 43. deploy + 44. deploy-api-service + 45. deploy-cache + 46. deploy-python-app + 47. destroy-prereq + 48. destroy-azure-azure-environment + 49. destroy + 50. diagnostics + 51. publish-prereq + 52. publish-azure-environment + 53. validate-appservice-config-aas-env + 54. publish + 55. publish-manifest + 56. push DETAILED STEP ANALYSIS ====================== @@ -72,7 +78,7 @@ Shows each step's dependencies, associated resources, tags, and descriptions. Step: azure-prepare-resources Description: Prepares the Azure resources. - Dependencies: none + Dependencies: ✓ finalize-azure-app-service-acr-pull-roles, ✓ finalize-azure-container-apps-acr-pull-roles Resource: azure-environment (AzureEnvironmentResource) Step: before-start @@ -150,6 +156,12 @@ Step: diagnostics Description: Dumps dependency graph information for troubleshooting pipeline execution. Dependencies: none +Step: finalize-azure-app-service-acr-pull-roles + Dependencies: none + +Step: finalize-azure-container-apps-acr-pull-roles + Dependencies: none + Step: login-to-acr-aas-env-acr Dependencies: ✓ provision-aas-env-acr Resource: aas-env-acr (AzureContainerRegistryResource) @@ -206,7 +218,7 @@ Step: process-parameters Step: provision-aas-env Description: Provisions the Azure Bicep resource aas-env using Azure infrastructure. - Dependencies: ✓ create-provisioning-context, ✓ provision-aas-env-acr + Dependencies: ✓ create-provisioning-context, ✓ provision-aas-env-acr, ✓ provision-aas-env-mi Resource: aas-env (AzureAppServiceEnvironmentResource) Tags: provision-infra @@ -216,9 +228,21 @@ Step: provision-aas-env-acr Resource: aas-env-acr (AzureContainerRegistryResource) Tags: provision-infra +Step: provision-aas-env-mi + Description: Provisions the Azure Bicep resource aas-env-mi using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: aas-env-mi (AzureUserAssignedIdentityResource) + Tags: provision-infra + +Step: provision-aas-env-mi-roles-aas-env-acr + Description: Provisions the Azure Bicep resource aas-env-mi-roles-aas-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-aas-env-acr, ✓ provision-aas-env-mi + Resource: aas-env-mi-roles-aas-env-acr (AzureRoleAssignmentResource) + Tags: provision-infra + Step: provision-aca-env Description: Provisions the Azure Bicep resource aca-env using Azure infrastructure. - Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr + Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr, ✓ provision-aca-env-mi Resource: aca-env (AzureContainerAppEnvironmentResource) Tags: provision-infra @@ -228,6 +252,18 @@ Step: provision-aca-env-acr Resource: aca-env-acr (AzureContainerRegistryResource) Tags: provision-infra +Step: provision-aca-env-mi + Description: Provisions the Azure Bicep resource aca-env-mi using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: aca-env-mi (AzureUserAssignedIdentityResource) + Tags: provision-infra + +Step: provision-aca-env-mi-roles-aca-env-acr + Description: Provisions the Azure Bicep resource aca-env-mi-roles-aca-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-aca-env-acr, ✓ provision-aca-env-mi + Resource: aca-env-mi-roles-aca-env-acr (AzureRoleAssignmentResource) + Tags: provision-infra + Step: provision-api-service-website Description: Provisions the Azure Bicep resource api-service-website using Azure infrastructure. Dependencies: ✓ create-provisioning-context, ✓ provision-aas-env, ✓ push-api-service @@ -236,7 +272,7 @@ Step: provision-api-service-website Step: provision-azure-bicep-resources Description: Aggregation step for all Azure infrastructure provisioning operations. - Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-aas-env, ✓ provision-aas-env-acr, ✓ provision-aca-env, ✓ provision-aca-env-acr, ✓ provision-api-service-website, ✓ provision-cache-containerapp, ✓ provision-python-app-containerapp, ✓ provision-storage + Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-aas-env, ✓ provision-aas-env-acr, ✓ provision-aas-env-mi, ✓ provision-aas-env-mi-roles-aas-env-acr, ✓ provision-aca-env, ✓ provision-aca-env-acr, ✓ provision-aca-env-mi, ✓ provision-aca-env-mi-roles-aca-env-acr, ✓ provision-api-service-website, ✓ provision-cache-containerapp, ✓ provision-python-app-containerapp, ✓ provision-storage Resource: azure-environment (AzureEnvironmentResource) Tags: provision-infra @@ -329,18 +365,20 @@ Shows what steps would run for each possible target step and in what order. Steps at the same level can run concurrently. ───────────────────────────────────────────────────────────────────────────── If targeting 'azure-prepare-resources': - Direct dependencies: none - Total steps: 1 + Direct dependencies: finalize-azure-app-service-acr-pull-roles, finalize-azure-container-apps-acr-pull-roles + Total steps: 3 Execution order: - [0] azure-prepare-resources + [0] finalize-azure-app-service-acr-pull-roles | finalize-azure-container-apps-acr-pull-roles (parallel) + [1] azure-prepare-resources If targeting 'before-start': Direct dependencies: azure-prepare-resources, prepare-azure-app-service-aas-env, prepare-azure-container-apps-aca-env, validate-azure-app-service, validate-azure-container-apps, validate-compute-environments - Total steps: 7 + Total steps: 9 Execution order: - [0] azure-prepare-resources | validate-azure-app-service | validate-azure-container-apps | validate-compute-environments (parallel) - [1] prepare-azure-app-service-aas-env | prepare-azure-container-apps-aca-env (parallel) - [2] before-start + [0] finalize-azure-app-service-acr-pull-roles | finalize-azure-container-apps-acr-pull-roles | validate-azure-app-service | validate-azure-container-apps | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-app-service-aas-env | prepare-azure-container-apps-aca-env (parallel) + [3] before-start If targeting 'build': Direct dependencies: build-api-service, build-python-app @@ -391,14 +429,14 @@ If targeting 'create-provisioning-context': If targeting 'deploy': Direct dependencies: build-api-service, build-python-app, create-provisioning-context, print-api-service-summary, print-cache-summary, print-dashboard-url-aas-env, print-dashboard-url-aca-env, print-python-app-summary, provision-azure-bicep-resources, validate-azure-login - Total steps: 29 + Total steps: 33 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr | provision-storage (parallel) - [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aca-env (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr | provision-aca-env-mi | provision-storage (parallel) + [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aas-env-mi-roles-aas-env-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr (parallel) [6] provision-cache-containerapp | push-prereq (parallel) [7] print-cache-summary | push-api-service | push-python-app (parallel) [8] provision-api-service-website | provision-python-app-containerapp (parallel) @@ -408,13 +446,13 @@ If targeting 'deploy': If targeting 'deploy-api-service': Direct dependencies: print-api-service-summary - Total steps: 18 + Total steps: 19 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr (parallel) [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env (parallel) [6] push-prereq [7] push-api-service @@ -424,13 +462,13 @@ If targeting 'deploy-api-service': If targeting 'deploy-cache': Direct dependencies: print-cache-summary - Total steps: 10 + Total steps: 11 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-aca-env-acr + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) [5] provision-aca-env [6] provision-cache-containerapp [7] print-cache-summary @@ -445,13 +483,13 @@ If targeting 'deploy-prereq': If targeting 'deploy-python-app': Direct dependencies: print-python-app-summary - Total steps: 18 + Total steps: 19 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr (parallel) + [4] provision-aas-env-acr | provision-aca-env-acr | provision-aca-env-mi (parallel) [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aca-env (parallel) [6] push-prereq [7] push-python-app @@ -486,6 +524,18 @@ If targeting 'diagnostics': Execution order: [0] diagnostics +If targeting 'finalize-azure-app-service-acr-pull-roles': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] finalize-azure-app-service-acr-pull-roles + +If targeting 'finalize-azure-container-apps-acr-pull-roles': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] finalize-azure-container-apps-acr-pull-roles + If targeting 'login-to-acr-aas-env-acr': Direct dependencies: provision-aas-env-acr Total steps: 7 @@ -510,27 +560,29 @@ If targeting 'login-to-acr-aca-env-acr': If targeting 'prepare-azure-app-service-aas-env': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 5 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-azure-app-service-aas-env + [0] finalize-azure-app-service-acr-pull-roles | finalize-azure-container-apps-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-app-service-aas-env If targeting 'prepare-azure-container-apps-aca-env': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 5 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-azure-container-apps-aca-env + [0] finalize-azure-app-service-acr-pull-roles | finalize-azure-container-apps-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-container-apps-aca-env If targeting 'print-api-service-summary': Direct dependencies: provision-api-service-website - Total steps: 17 + Total steps: 18 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr (parallel) [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env (parallel) [6] push-prereq [7] push-api-service @@ -539,27 +591,27 @@ If targeting 'print-api-service-summary': If targeting 'print-cache-summary': Direct dependencies: provision-cache-containerapp - Total steps: 9 + Total steps: 10 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-aca-env-acr + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) [5] provision-aca-env [6] provision-cache-containerapp [7] print-cache-summary If targeting 'print-dashboard-url-aas-env': Direct dependencies: provision-aas-env, provision-azure-bicep-resources - Total steps: 24 + Total steps: 28 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr | provision-storage (parallel) - [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aca-env (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr | provision-aca-env-mi | provision-storage (parallel) + [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aas-env-mi-roles-aas-env-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr (parallel) [6] provision-cache-containerapp | push-prereq (parallel) [7] push-api-service | push-python-app (parallel) [8] provision-api-service-website | provision-python-app-containerapp (parallel) @@ -568,14 +620,14 @@ If targeting 'print-dashboard-url-aas-env': If targeting 'print-dashboard-url-aca-env': Direct dependencies: provision-aca-env, provision-azure-bicep-resources - Total steps: 24 + Total steps: 28 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr | provision-storage (parallel) - [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aca-env (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr | provision-aca-env-mi | provision-storage (parallel) + [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aas-env-mi-roles-aas-env-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr (parallel) [6] provision-cache-containerapp | push-prereq (parallel) [7] push-api-service | push-python-app (parallel) [8] provision-api-service-website | provision-python-app-containerapp (parallel) @@ -584,13 +636,13 @@ If targeting 'print-dashboard-url-aca-env': If targeting 'print-python-app-summary': Direct dependencies: provision-python-app-containerapp - Total steps: 17 + Total steps: 18 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr (parallel) + [4] provision-aas-env-acr | provision-aca-env-acr | provision-aca-env-mi (parallel) [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aca-env (parallel) [6] push-prereq [7] push-python-app @@ -604,14 +656,14 @@ If targeting 'process-parameters': [0] process-parameters If targeting 'provision-aas-env': - Direct dependencies: create-provisioning-context, provision-aas-env-acr - Total steps: 7 + Direct dependencies: create-provisioning-context, provision-aas-env-acr, provision-aas-env-mi + Total steps: 8 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-aas-env-acr + [4] provision-aas-env-acr | provision-aas-env-mi (parallel) [5] provision-aas-env If targeting 'provision-aas-env-acr': @@ -624,15 +676,36 @@ If targeting 'provision-aas-env-acr': [3] create-provisioning-context [4] provision-aas-env-acr +If targeting 'provision-aas-env-mi': + Direct dependencies: create-provisioning-context + Total steps: 6 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aas-env-mi + +If targeting 'provision-aas-env-mi-roles-aas-env-acr': + Direct dependencies: create-provisioning-context, provision-aas-env-acr, provision-aas-env-mi + Total steps: 8 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aas-env-acr | provision-aas-env-mi (parallel) + [5] provision-aas-env-mi-roles-aas-env-acr + If targeting 'provision-aca-env': - Direct dependencies: create-provisioning-context, provision-aca-env-acr - Total steps: 7 + Direct dependencies: create-provisioning-context, provision-aca-env-acr, provision-aca-env-mi + Total steps: 8 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-aca-env-acr + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) [5] provision-aca-env If targeting 'provision-aca-env-acr': @@ -645,30 +718,51 @@ If targeting 'provision-aca-env-acr': [3] create-provisioning-context [4] provision-aca-env-acr +If targeting 'provision-aca-env-mi': + Direct dependencies: create-provisioning-context + Total steps: 6 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-mi + +If targeting 'provision-aca-env-mi-roles-aca-env-acr': + Direct dependencies: create-provisioning-context, provision-aca-env-acr, provision-aca-env-mi + Total steps: 8 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) + [5] provision-aca-env-mi-roles-aca-env-acr + If targeting 'provision-api-service-website': Direct dependencies: create-provisioning-context, provision-aas-env, push-api-service - Total steps: 16 + Total steps: 17 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr (parallel) [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env (parallel) [6] push-prereq [7] push-api-service [8] provision-api-service-website If targeting 'provision-azure-bicep-resources': - Direct dependencies: create-provisioning-context, deploy-prereq, provision-aas-env, provision-aas-env-acr, provision-aca-env, provision-aca-env-acr, provision-api-service-website, provision-cache-containerapp, provision-python-app-containerapp, provision-storage - Total steps: 23 + Direct dependencies: create-provisioning-context, deploy-prereq, provision-aas-env, provision-aas-env-acr, provision-aas-env-mi, provision-aas-env-mi-roles-aas-env-acr, provision-aca-env, provision-aca-env-acr, provision-aca-env-mi, provision-aca-env-mi-roles-aca-env-acr, provision-api-service-website, provision-cache-containerapp, provision-python-app-containerapp, provision-storage + Total steps: 27 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api-service | build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr | provision-storage (parallel) - [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aca-env (parallel) + [4] provision-aas-env-acr | provision-aas-env-mi | provision-aca-env-acr | provision-aca-env-mi | provision-storage (parallel) + [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aas-env | provision-aas-env-mi-roles-aas-env-acr | provision-aca-env | provision-aca-env-mi-roles-aca-env-acr (parallel) [6] provision-cache-containerapp | push-prereq (parallel) [7] push-api-service | push-python-app (parallel) [8] provision-api-service-website | provision-python-app-containerapp (parallel) @@ -676,25 +770,25 @@ If targeting 'provision-azure-bicep-resources': If targeting 'provision-cache-containerapp': Direct dependencies: create-provisioning-context, provision-aca-env - Total steps: 8 + Total steps: 9 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-aca-env-acr + [4] provision-aca-env-acr | provision-aca-env-mi (parallel) [5] provision-aca-env [6] provision-cache-containerapp If targeting 'provision-python-app-containerapp': Direct dependencies: create-provisioning-context, provision-aca-env, push-python-app - Total steps: 16 + Total steps: 17 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-python-app | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-aas-env-acr | provision-aca-env-acr (parallel) + [4] provision-aas-env-acr | provision-aca-env-acr | provision-aca-env-mi (parallel) [5] login-to-acr-aas-env-acr | login-to-acr-aca-env-acr | provision-aca-env (parallel) [6] push-prereq [7] push-python-app diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt index b9edc94c95a..f266b8d4d02 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithPrivateEndpoints_CreatesCorrectDependencies.verified.txt @@ -5,7 +5,7 @@ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS This diagnostic output shows the complete pipeline dependency graph structure. Use this to understand step relationships and troubleshoot execution issues. -Total steps defined: 50 +Total steps defined: 53 Analysis for full pipeline execution (showing all steps and their relationships) @@ -14,56 +14,59 @@ EXECUTION ORDER This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. - 1. azure-prepare-resources - 2. validate-compute-environments - 3. prepare-azure-container-apps-env - 4. validate-azure-container-apps - 5. before-start - 6. process-parameters - 7. build-prereq - 8. check-container-runtime - 9. validate-build-only-container-references - 10. deploy-prereq - 11. build-api - 12. build - 13. validate-azure-login - 14. create-provisioning-context - 15. provision-api-identity - 16. provision-cosmos - 17. provision-api-roles-cosmos - 18. provision-sql-nsg - 19. provision-vnet - 20. provision-privatelink-file-core-windows-net - 21. provision-sql-store - 22. provision-pe-subnet-files-pe - 23. provision-privatelink-database-windows-net - 24. provision-sql - 25. provision-pe-subnet-sql-pe - 26. provision-api-roles-sql - 27. provision-env-acr - 28. provision-env - 29. provision-privatelink-documents-azure-com - 30. provision-pe-subnet-cosmos-pe - 31. login-to-acr-env-acr - 32. push-prereq - 33. push-api - 34. provision-api-containerapp - 35. print-api-summary - 36. provision-sql-admin-identity - 37. provision-sql-admin-identity-roles-sql-store - 38. provision-azure-bicep-resources - 39. print-dashboard-url-env - 40. deploy - 41. deploy-api - 42. destroy-prereq - 43. destroy-azure-azure-environment - 44. destroy - 45. diagnostics - 46. publish-prereq - 47. publish-azure-environment - 48. publish - 49. publish-manifest - 50. push + 1. finalize-azure-container-apps-acr-pull-roles + 2. azure-prepare-resources + 3. validate-compute-environments + 4. prepare-azure-container-apps-env + 5. validate-azure-container-apps + 6. before-start + 7. process-parameters + 8. build-prereq + 9. check-container-runtime + 10. validate-build-only-container-references + 11. deploy-prereq + 12. build-api + 13. build + 14. validate-azure-login + 15. create-provisioning-context + 16. provision-api-identity + 17. provision-cosmos + 18. provision-api-roles-cosmos + 19. provision-sql-nsg + 20. provision-vnet + 21. provision-privatelink-file-core-windows-net + 22. provision-sql-store + 23. provision-pe-subnet-files-pe + 24. provision-privatelink-database-windows-net + 25. provision-sql + 26. provision-pe-subnet-sql-pe + 27. provision-api-roles-sql + 28. provision-env-acr + 29. provision-env-mi + 30. provision-env + 31. provision-privatelink-documents-azure-com + 32. provision-pe-subnet-cosmos-pe + 33. login-to-acr-env-acr + 34. push-prereq + 35. push-api + 36. provision-api-containerapp + 37. print-api-summary + 38. provision-env-mi-roles-env-acr + 39. provision-sql-admin-identity + 40. provision-sql-admin-identity-roles-sql-store + 41. provision-azure-bicep-resources + 42. print-dashboard-url-env + 43. deploy + 44. deploy-api + 45. destroy-prereq + 46. destroy-azure-azure-environment + 47. destroy + 48. diagnostics + 49. publish-prereq + 50. publish-azure-environment + 51. publish + 52. publish-manifest + 53. push DETAILED STEP ANALYSIS ====================== @@ -72,7 +75,7 @@ Shows each step's dependencies, associated resources, tags, and descriptions. Step: azure-prepare-resources Description: Prepares the Azure resources. - Dependencies: none + Dependencies: ✓ finalize-azure-container-apps-acr-pull-roles Resource: azure-environment (AzureEnvironmentResource) Step: before-start @@ -133,6 +136,9 @@ Step: diagnostics Description: Dumps dependency graph information for troubleshooting pipeline execution. Dependencies: none +Step: finalize-azure-container-apps-acr-pull-roles + Dependencies: none + Step: login-to-acr-env-acr Dependencies: ✓ provision-env-acr Resource: env-acr (AzureContainerRegistryResource) @@ -185,7 +191,7 @@ Step: provision-api-roles-sql Step: provision-azure-bicep-resources Description: Aggregation step for all Azure infrastructure provisioning operations. - Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-api-containerapp, ✓ provision-api-identity, ✓ provision-api-roles-cosmos, ✓ provision-api-roles-sql, ✓ provision-cosmos, ✓ provision-env, ✓ provision-env-acr, ✓ provision-pe-subnet-cosmos-pe, ✓ provision-pe-subnet-files-pe, ✓ provision-pe-subnet-sql-pe, ✓ provision-privatelink-database-windows-net, ✓ provision-privatelink-documents-azure-com, ✓ provision-privatelink-file-core-windows-net, ✓ provision-sql, ✓ provision-sql-admin-identity, ✓ provision-sql-admin-identity-roles-sql-store, ✓ provision-sql-nsg, ✓ provision-sql-store, ✓ provision-vnet + Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-api-containerapp, ✓ provision-api-identity, ✓ provision-api-roles-cosmos, ✓ provision-api-roles-sql, ✓ provision-cosmos, ✓ provision-env, ✓ provision-env-acr, ✓ provision-env-mi, ✓ provision-env-mi-roles-env-acr, ✓ provision-pe-subnet-cosmos-pe, ✓ provision-pe-subnet-files-pe, ✓ provision-pe-subnet-sql-pe, ✓ provision-privatelink-database-windows-net, ✓ provision-privatelink-documents-azure-com, ✓ provision-privatelink-file-core-windows-net, ✓ provision-sql, ✓ provision-sql-admin-identity, ✓ provision-sql-admin-identity-roles-sql-store, ✓ provision-sql-nsg, ✓ provision-sql-store, ✓ provision-vnet Resource: azure-environment (AzureEnvironmentResource) Tags: provision-infra @@ -197,7 +203,7 @@ Step: provision-cosmos Step: provision-env Description: Provisions the Azure Bicep resource env using Azure infrastructure. - Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr + Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr, ✓ provision-env-mi Resource: env (AzureContainerAppEnvironmentResource) Tags: provision-infra @@ -207,6 +213,18 @@ Step: provision-env-acr Resource: env-acr (AzureContainerRegistryResource) Tags: provision-infra +Step: provision-env-mi + Description: Provisions the Azure Bicep resource env-mi using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: env-mi (AzureUserAssignedIdentityResource) + Tags: provision-infra + +Step: provision-env-mi-roles-env-acr + Description: Provisions the Azure Bicep resource env-mi-roles-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr, ✓ provision-env-mi + Resource: env-mi-roles-env-acr (AzureRoleAssignmentResource) + Tags: provision-infra + Step: provision-pe-subnet-cosmos-pe Description: Provisions the Azure Bicep resource pe-subnet-cosmos-pe using Azure infrastructure. Dependencies: ✓ create-provisioning-context, ✓ provision-cosmos, ✓ provision-privatelink-documents-azure-com, ✓ provision-vnet @@ -337,18 +355,20 @@ Shows what steps would run for each possible target step and in what order. Steps at the same level can run concurrently. ───────────────────────────────────────────────────────────────────────────── If targeting 'azure-prepare-resources': - Direct dependencies: none - Total steps: 1 + Direct dependencies: finalize-azure-container-apps-acr-pull-roles + Total steps: 2 Execution order: - [0] azure-prepare-resources + [0] finalize-azure-container-apps-acr-pull-roles + [1] azure-prepare-resources If targeting 'before-start': Direct dependencies: azure-prepare-resources, prepare-azure-container-apps-env, validate-azure-container-apps, validate-compute-environments - Total steps: 5 + Total steps: 6 Execution order: - [0] azure-prepare-resources | validate-azure-container-apps | validate-compute-environments (parallel) - [1] prepare-azure-container-apps-env - [2] before-start + [0] finalize-azure-container-apps-acr-pull-roles | validate-azure-container-apps | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-container-apps-env + [3] before-start If targeting 'build': Direct dependencies: build-api @@ -391,14 +411,14 @@ If targeting 'create-provisioning-context': If targeting 'deploy': Direct dependencies: build-api, create-provisioning-context, print-api-summary, print-dashboard-url-env, provision-azure-bicep-resources, validate-azure-login - Total steps: 34 + Total steps: 36 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-sql | provision-sql-nsg | provision-sql-store (parallel) - [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-sql-admin-identity | provision-vnet (parallel) + [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-env-mi | provision-sql | provision-sql-nsg | provision-sql-store (parallel) + [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-env-mi-roles-env-acr | provision-sql-admin-identity | provision-vnet (parallel) [6] provision-privatelink-database-windows-net | provision-privatelink-documents-azure-com | provision-privatelink-file-core-windows-net | provision-sql-admin-identity-roles-sql-store | push-prereq (parallel) [7] provision-pe-subnet-cosmos-pe | provision-pe-subnet-files-pe | provision-pe-subnet-sql-pe | push-api (parallel) [8] provision-api-roles-sql @@ -409,13 +429,13 @@ If targeting 'deploy': If targeting 'deploy-api': Direct dependencies: print-api-summary - Total steps: 30 + Total steps: 31 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-sql | provision-sql-nsg | provision-sql-store (parallel) + [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-env-mi | provision-sql | provision-sql-nsg | provision-sql-store (parallel) [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-vnet (parallel) [6] provision-privatelink-database-windows-net | provision-privatelink-documents-azure-com | provision-privatelink-file-core-windows-net | push-prereq (parallel) [7] provision-pe-subnet-cosmos-pe | provision-pe-subnet-files-pe | provision-pe-subnet-sql-pe | push-api (parallel) @@ -458,6 +478,12 @@ If targeting 'diagnostics': Execution order: [0] diagnostics +If targeting 'finalize-azure-container-apps-acr-pull-roles': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] finalize-azure-container-apps-acr-pull-roles + If targeting 'login-to-acr-env-acr': Direct dependencies: provision-env-acr Total steps: 7 @@ -471,20 +497,21 @@ If targeting 'login-to-acr-env-acr': If targeting 'prepare-azure-container-apps-env': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 4 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-azure-container-apps-env + [0] finalize-azure-container-apps-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-container-apps-env If targeting 'print-api-summary': Direct dependencies: provision-api-containerapp - Total steps: 29 + Total steps: 30 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-sql | provision-sql-nsg | provision-sql-store (parallel) + [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-env-mi | provision-sql | provision-sql-nsg | provision-sql-store (parallel) [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-vnet (parallel) [6] provision-privatelink-database-windows-net | provision-privatelink-documents-azure-com | provision-privatelink-file-core-windows-net | push-prereq (parallel) [7] provision-pe-subnet-cosmos-pe | provision-pe-subnet-files-pe | provision-pe-subnet-sql-pe | push-api (parallel) @@ -494,14 +521,14 @@ If targeting 'print-api-summary': If targeting 'print-dashboard-url-env': Direct dependencies: provision-azure-bicep-resources, provision-env - Total steps: 32 + Total steps: 34 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-sql | provision-sql-nsg | provision-sql-store (parallel) - [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-sql-admin-identity | provision-vnet (parallel) + [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-env-mi | provision-sql | provision-sql-nsg | provision-sql-store (parallel) + [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-env-mi-roles-env-acr | provision-sql-admin-identity | provision-vnet (parallel) [6] provision-privatelink-database-windows-net | provision-privatelink-documents-azure-com | provision-privatelink-file-core-windows-net | provision-sql-admin-identity-roles-sql-store | push-prereq (parallel) [7] provision-pe-subnet-cosmos-pe | provision-pe-subnet-files-pe | provision-pe-subnet-sql-pe | push-api (parallel) [8] provision-api-roles-sql @@ -517,13 +544,13 @@ If targeting 'process-parameters': If targeting 'provision-api-containerapp': Direct dependencies: create-provisioning-context, provision-api-identity, provision-api-roles-cosmos, provision-api-roles-sql, provision-cosmos, provision-env, provision-pe-subnet-cosmos-pe, provision-pe-subnet-sql-pe, provision-sql, push-api - Total steps: 28 + Total steps: 29 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-sql | provision-sql-nsg | provision-sql-store (parallel) + [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-env-mi | provision-sql | provision-sql-nsg | provision-sql-store (parallel) [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-vnet (parallel) [6] provision-privatelink-database-windows-net | provision-privatelink-documents-azure-com | provision-privatelink-file-core-windows-net | push-prereq (parallel) [7] provision-pe-subnet-cosmos-pe | provision-pe-subnet-files-pe | provision-pe-subnet-sql-pe | push-api (parallel) @@ -566,15 +593,15 @@ If targeting 'provision-api-roles-sql': [8] provision-api-roles-sql If targeting 'provision-azure-bicep-resources': - Direct dependencies: create-provisioning-context, deploy-prereq, provision-api-containerapp, provision-api-identity, provision-api-roles-cosmos, provision-api-roles-sql, provision-cosmos, provision-env, provision-env-acr, provision-pe-subnet-cosmos-pe, provision-pe-subnet-files-pe, provision-pe-subnet-sql-pe, provision-privatelink-database-windows-net, provision-privatelink-documents-azure-com, provision-privatelink-file-core-windows-net, provision-sql, provision-sql-admin-identity, provision-sql-admin-identity-roles-sql-store, provision-sql-nsg, provision-sql-store, provision-vnet - Total steps: 31 + Direct dependencies: create-provisioning-context, deploy-prereq, provision-api-containerapp, provision-api-identity, provision-api-roles-cosmos, provision-api-roles-sql, provision-cosmos, provision-env, provision-env-acr, provision-env-mi, provision-env-mi-roles-env-acr, provision-pe-subnet-cosmos-pe, provision-pe-subnet-files-pe, provision-pe-subnet-sql-pe, provision-privatelink-database-windows-net, provision-privatelink-documents-azure-com, provision-privatelink-file-core-windows-net, provision-sql, provision-sql-admin-identity, provision-sql-admin-identity-roles-sql-store, provision-sql-nsg, provision-sql-store, provision-vnet + Total steps: 33 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-sql | provision-sql-nsg | provision-sql-store (parallel) - [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-sql-admin-identity | provision-vnet (parallel) + [4] provision-api-identity | provision-cosmos | provision-env-acr | provision-env-mi | provision-sql | provision-sql-nsg | provision-sql-store (parallel) + [5] login-to-acr-env-acr | provision-api-roles-cosmos | provision-env | provision-env-mi-roles-env-acr | provision-sql-admin-identity | provision-vnet (parallel) [6] provision-privatelink-database-windows-net | provision-privatelink-documents-azure-com | provision-privatelink-file-core-windows-net | provision-sql-admin-identity-roles-sql-store | push-prereq (parallel) [7] provision-pe-subnet-cosmos-pe | provision-pe-subnet-files-pe | provision-pe-subnet-sql-pe | push-api (parallel) [8] provision-api-roles-sql @@ -592,14 +619,14 @@ If targeting 'provision-cosmos': [4] provision-cosmos If targeting 'provision-env': - Direct dependencies: create-provisioning-context, provision-env-acr - Total steps: 7 + Direct dependencies: create-provisioning-context, provision-env-acr, provision-env-mi + Total steps: 8 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-env-acr + [4] provision-env-acr | provision-env-mi (parallel) [5] provision-env If targeting 'provision-env-acr': @@ -612,6 +639,27 @@ If targeting 'provision-env-acr': [3] create-provisioning-context [4] provision-env-acr +If targeting 'provision-env-mi': + Direct dependencies: create-provisioning-context + Total steps: 6 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-env-mi + +If targeting 'provision-env-mi-roles-env-acr': + Direct dependencies: create-provisioning-context, provision-env-acr, provision-env-mi + Total steps: 8 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-env-acr | provision-env-mi (parallel) + [5] provision-env-mi-roles-env-acr + If targeting 'provision-pe-subnet-cosmos-pe': Direct dependencies: create-provisioning-context, provision-cosmos, provision-privatelink-documents-azure-com, provision-vnet Total steps: 10 diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt index a53ec5c3e33..7e9bb43fc1c 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureDeployerTests.DeployAsync_WithRedisAccessKeyAuthentication_CreatesCorrectDependencies.verified.txt @@ -5,7 +5,7 @@ PIPELINE DEPENDENCY GRAPH DIAGNOSTICS This diagnostic output shows the complete pipeline dependency graph structure. Use this to understand step relationships and troubleshoot execution issues. -Total steps defined: 45 +Total steps defined: 48 Analysis for full pipeline execution (showing all steps and their relationships) @@ -14,51 +14,54 @@ EXECUTION ORDER This shows the order in which steps would execute, respecting all dependencies. Steps with no dependencies run first, followed by steps that depend on them. - 1. azure-prepare-resources - 2. validate-compute-environments - 3. prepare-azure-app-service-env - 4. validate-azure-app-service - 5. before-start - 6. process-parameters - 7. build-prereq - 8. check-container-runtime - 9. validate-build-only-container-references - 10. deploy-prereq - 11. build-api - 12. build - 13. validate-azure-login - 14. create-provisioning-context - 15. provision-api-identity - 16. provision-cache-kv - 17. provision-api-roles-cache-kv - 18. provision-cosmos-kv - 19. provision-api-roles-cosmos-kv - 20. provision-pg-kv - 21. provision-api-roles-pg-kv - 22. provision-cache - 23. provision-cosmos - 24. provision-env-acr - 25. provision-env - 26. provision-pg - 27. login-to-acr-env-acr - 28. push-prereq - 29. push-api - 30. provision-api-website - 31. print-api-summary - 32. provision-azure-bicep-resources - 33. print-dashboard-url-env - 34. deploy - 35. deploy-api - 36. destroy-prereq - 37. destroy-azure-azure-environment - 38. destroy - 39. diagnostics - 40. publish-prereq - 41. publish-azure-environment - 42. validate-appservice-config-env - 43. publish - 44. publish-manifest - 45. push + 1. finalize-azure-app-service-acr-pull-roles + 2. azure-prepare-resources + 3. validate-compute-environments + 4. prepare-azure-app-service-env + 5. validate-azure-app-service + 6. before-start + 7. process-parameters + 8. build-prereq + 9. check-container-runtime + 10. validate-build-only-container-references + 11. deploy-prereq + 12. build-api + 13. build + 14. validate-azure-login + 15. create-provisioning-context + 16. provision-api-identity + 17. provision-cache-kv + 18. provision-api-roles-cache-kv + 19. provision-cosmos-kv + 20. provision-api-roles-cosmos-kv + 21. provision-pg-kv + 22. provision-api-roles-pg-kv + 23. provision-cache + 24. provision-cosmos + 25. provision-env-acr + 26. provision-env-mi + 27. provision-env + 28. provision-pg + 29. login-to-acr-env-acr + 30. push-prereq + 31. push-api + 32. provision-api-website + 33. print-api-summary + 34. provision-env-mi-roles-env-acr + 35. provision-azure-bicep-resources + 36. print-dashboard-url-env + 37. deploy + 38. deploy-api + 39. destroy-prereq + 40. destroy-azure-azure-environment + 41. destroy + 42. diagnostics + 43. publish-prereq + 44. publish-azure-environment + 45. validate-appservice-config-env + 46. publish + 47. publish-manifest + 48. push DETAILED STEP ANALYSIS ====================== @@ -67,7 +70,7 @@ Shows each step's dependencies, associated resources, tags, and descriptions. Step: azure-prepare-resources Description: Prepares the Azure resources. - Dependencies: none + Dependencies: ✓ finalize-azure-app-service-acr-pull-roles Resource: azure-environment (AzureEnvironmentResource) Step: before-start @@ -128,6 +131,9 @@ Step: diagnostics Description: Dumps dependency graph information for troubleshooting pipeline execution. Dependencies: none +Step: finalize-azure-app-service-acr-pull-roles + Dependencies: none + Step: login-to-acr-env-acr Dependencies: ✓ provision-env-acr Resource: env-acr (AzureContainerRegistryResource) @@ -186,7 +192,7 @@ Step: provision-api-website Step: provision-azure-bicep-resources Description: Aggregation step for all Azure infrastructure provisioning operations. - Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-api-identity, ✓ provision-api-roles-cache-kv, ✓ provision-api-roles-cosmos-kv, ✓ provision-api-roles-pg-kv, ✓ provision-api-website, ✓ provision-cache, ✓ provision-cache-kv, ✓ provision-cosmos, ✓ provision-cosmos-kv, ✓ provision-env, ✓ provision-env-acr, ✓ provision-pg, ✓ provision-pg-kv + Dependencies: ✓ create-provisioning-context, ✓ deploy-prereq, ✓ provision-api-identity, ✓ provision-api-roles-cache-kv, ✓ provision-api-roles-cosmos-kv, ✓ provision-api-roles-pg-kv, ✓ provision-api-website, ✓ provision-cache, ✓ provision-cache-kv, ✓ provision-cosmos, ✓ provision-cosmos-kv, ✓ provision-env, ✓ provision-env-acr, ✓ provision-env-mi, ✓ provision-env-mi-roles-env-acr, ✓ provision-pg, ✓ provision-pg-kv Resource: azure-environment (AzureEnvironmentResource) Tags: provision-infra @@ -216,7 +222,7 @@ Step: provision-cosmos-kv Step: provision-env Description: Provisions the Azure Bicep resource env using Azure infrastructure. - Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr + Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr, ✓ provision-env-mi Resource: env (AzureAppServiceEnvironmentResource) Tags: provision-infra @@ -226,6 +232,18 @@ Step: provision-env-acr Resource: env-acr (AzureContainerRegistryResource) Tags: provision-infra +Step: provision-env-mi + Description: Provisions the Azure Bicep resource env-mi using Azure infrastructure. + Dependencies: ✓ create-provisioning-context + Resource: env-mi (AzureUserAssignedIdentityResource) + Tags: provision-infra + +Step: provision-env-mi-roles-env-acr + Description: Provisions the Azure Bicep resource env-mi-roles-env-acr using Azure infrastructure. + Dependencies: ✓ create-provisioning-context, ✓ provision-env-acr, ✓ provision-env-mi + Resource: env-mi-roles-env-acr (AzureRoleAssignmentResource) + Tags: provision-infra + Step: provision-pg Description: Provisions the Azure Bicep resource pg using Azure infrastructure. Dependencies: ✓ create-provisioning-context, ✓ provision-pg-kv @@ -301,18 +319,20 @@ Shows what steps would run for each possible target step and in what order. Steps at the same level can run concurrently. ───────────────────────────────────────────────────────────────────────────── If targeting 'azure-prepare-resources': - Direct dependencies: none - Total steps: 1 + Direct dependencies: finalize-azure-app-service-acr-pull-roles + Total steps: 2 Execution order: - [0] azure-prepare-resources + [0] finalize-azure-app-service-acr-pull-roles + [1] azure-prepare-resources If targeting 'before-start': Direct dependencies: azure-prepare-resources, prepare-azure-app-service-env, validate-azure-app-service, validate-compute-environments - Total steps: 5 + Total steps: 6 Execution order: - [0] azure-prepare-resources | validate-azure-app-service | validate-compute-environments (parallel) - [1] prepare-azure-app-service-env - [2] before-start + [0] finalize-azure-app-service-acr-pull-roles | validate-azure-app-service | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-app-service-env + [3] before-start If targeting 'build': Direct dependencies: build-api @@ -355,14 +375,14 @@ If targeting 'create-provisioning-context': If targeting 'deploy': Direct dependencies: build-api, create-provisioning-context, print-api-summary, print-dashboard-url-env, provision-azure-bicep-resources, validate-azure-login - Total steps: 28 + Total steps: 30 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-pg-kv (parallel) - [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-pg (parallel) + [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-env-mi | provision-pg-kv (parallel) + [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-env-mi-roles-env-acr | provision-pg (parallel) [6] push-prereq [7] push-api [8] provision-api-website @@ -372,13 +392,13 @@ If targeting 'deploy': If targeting 'deploy-api': Direct dependencies: print-api-summary - Total steps: 26 + Total steps: 27 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-pg-kv (parallel) + [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-env-mi | provision-pg-kv (parallel) [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-pg (parallel) [6] push-prereq [7] push-api @@ -420,6 +440,12 @@ If targeting 'diagnostics': Execution order: [0] diagnostics +If targeting 'finalize-azure-app-service-acr-pull-roles': + Direct dependencies: none + Total steps: 1 + Execution order: + [0] finalize-azure-app-service-acr-pull-roles + If targeting 'login-to-acr-env-acr': Direct dependencies: provision-env-acr Total steps: 7 @@ -433,20 +459,21 @@ If targeting 'login-to-acr-env-acr': If targeting 'prepare-azure-app-service-env': Direct dependencies: azure-prepare-resources, validate-compute-environments - Total steps: 3 + Total steps: 4 Execution order: - [0] azure-prepare-resources | validate-compute-environments (parallel) - [1] prepare-azure-app-service-env + [0] finalize-azure-app-service-acr-pull-roles | validate-compute-environments (parallel) + [1] azure-prepare-resources + [2] prepare-azure-app-service-env If targeting 'print-api-summary': Direct dependencies: provision-api-website - Total steps: 25 + Total steps: 26 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-pg-kv (parallel) + [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-env-mi | provision-pg-kv (parallel) [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-pg (parallel) [6] push-prereq [7] push-api @@ -455,14 +482,14 @@ If targeting 'print-api-summary': If targeting 'print-dashboard-url-env': Direct dependencies: provision-azure-bicep-resources, provision-env - Total steps: 26 + Total steps: 28 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-pg-kv (parallel) - [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-pg (parallel) + [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-env-mi | provision-pg-kv (parallel) + [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-env-mi-roles-env-acr | provision-pg (parallel) [6] push-prereq [7] push-api [8] provision-api-website @@ -520,28 +547,28 @@ If targeting 'provision-api-roles-pg-kv': If targeting 'provision-api-website': Direct dependencies: create-provisioning-context, provision-api-identity, provision-api-roles-cache-kv, provision-api-roles-cosmos-kv, provision-api-roles-pg-kv, provision-cache, provision-cache-kv, provision-cosmos, provision-cosmos-kv, provision-env, provision-pg, provision-pg-kv, push-api - Total steps: 24 + Total steps: 25 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-pg-kv (parallel) + [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-env-mi | provision-pg-kv (parallel) [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-pg (parallel) [6] push-prereq [7] push-api [8] provision-api-website If targeting 'provision-azure-bicep-resources': - Direct dependencies: create-provisioning-context, deploy-prereq, provision-api-identity, provision-api-roles-cache-kv, provision-api-roles-cosmos-kv, provision-api-roles-pg-kv, provision-api-website, provision-cache, provision-cache-kv, provision-cosmos, provision-cosmos-kv, provision-env, provision-env-acr, provision-pg, provision-pg-kv - Total steps: 25 + Direct dependencies: create-provisioning-context, deploy-prereq, provision-api-identity, provision-api-roles-cache-kv, provision-api-roles-cosmos-kv, provision-api-roles-pg-kv, provision-api-website, provision-cache, provision-cache-kv, provision-cosmos, provision-cosmos-kv, provision-env, provision-env-acr, provision-env-mi, provision-env-mi-roles-env-acr, provision-pg, provision-pg-kv + Total steps: 27 Execution order: [0] check-container-runtime | process-parameters | validate-build-only-container-references (parallel) [1] build-prereq | deploy-prereq (parallel) [2] build-api | validate-azure-login (parallel) [3] create-provisioning-context - [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-pg-kv (parallel) - [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-pg (parallel) + [4] provision-api-identity | provision-cache-kv | provision-cosmos-kv | provision-env-acr | provision-env-mi | provision-pg-kv (parallel) + [5] login-to-acr-env-acr | provision-api-roles-cache-kv | provision-api-roles-cosmos-kv | provision-api-roles-pg-kv | provision-cache | provision-cosmos | provision-env | provision-env-mi-roles-env-acr | provision-pg (parallel) [6] push-prereq [7] push-api [8] provision-api-website @@ -590,14 +617,14 @@ If targeting 'provision-cosmos-kv': [4] provision-cosmos-kv If targeting 'provision-env': - Direct dependencies: create-provisioning-context, provision-env-acr - Total steps: 7 + Direct dependencies: create-provisioning-context, provision-env-acr, provision-env-mi + Total steps: 8 Execution order: [0] process-parameters | validate-build-only-container-references (parallel) [1] deploy-prereq [2] validate-azure-login [3] create-provisioning-context - [4] provision-env-acr + [4] provision-env-acr | provision-env-mi (parallel) [5] provision-env If targeting 'provision-env-acr': @@ -610,6 +637,27 @@ If targeting 'provision-env-acr': [3] create-provisioning-context [4] provision-env-acr +If targeting 'provision-env-mi': + Direct dependencies: create-provisioning-context + Total steps: 6 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-env-mi + +If targeting 'provision-env-mi-roles-env-acr': + Direct dependencies: create-provisioning-context, provision-env-acr, provision-env-mi + Total steps: 8 + Execution order: + [0] process-parameters | validate-build-only-container-references (parallel) + [1] deploy-prereq + [2] validate-azure-login + [3] create-provisioning-context + [4] provision-env-acr | provision-env-mi (parallel) + [5] provision-env-mi-roles-env-acr + If targeting 'provision-pg': Direct dependencies: create-provisioning-context, provision-pg-kv Total steps: 7 diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_CapturesParametersAndOutputsCorrectly_WithSnapshot#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_CapturesParametersAndOutputsCorrectly_WithSnapshot#00.verified.bicep index fb1997f97b9..40fc26bfbbc 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_CapturesParametersAndOutputsCorrectly_WithSnapshot#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_CapturesParametersAndOutputsCorrectly_WithSnapshot#00.verified.bicep @@ -23,11 +23,20 @@ module acaEnv_acr 'acaEnv-acr/acaEnv-acr.bicep' = { } } +module acaEnv_mi 'acaEnv-mi/acaEnv-mi.bicep' = { + name: 'acaEnv-mi' + scope: rg + params: { + location: location + } +} + module acaEnv 'acaEnv/acaEnv.bicep' = { name: 'acaEnv' scope: rg params: { location: location + acaenv_mi_outputs_id: acaEnv_mi.outputs.id acaenv_acr_outputs_name: acaEnv_acr.outputs.name userPrincipalId: principalId } @@ -87,6 +96,16 @@ module fe_roles_account 'fe-roles-account/fe-roles-account.bicep' = { } } +module acaEnv_mi_roles_acaEnv_acr 'acaEnv-mi-roles-acaEnv-acr/acaEnv-mi-roles-acaEnv-acr.bicep' = { + name: 'acaEnv-mi-roles-acaEnv-acr' + scope: rg + params: { + location: location + acaenv_acr_outputs_name: acaEnv_acr.outputs.name + principalId: acaEnv_mi.outputs.principalId + } +} + output acaEnv_AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = acaEnv.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN output acaEnv_AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = acaEnv.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_ID diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_WritesScopedModuleExpressions.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_WritesScopedModuleExpressions.verified.bicep index 050aab363e0..035cea580d8 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_WritesScopedModuleExpressions.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.AzurePublishingContext_WritesScopedModuleExpressions.verified.bicep @@ -23,11 +23,20 @@ module acaEnv_acr 'acaEnv-acr/acaEnv-acr.bicep' = { } } +module acaEnv_mi 'acaEnv-mi/acaEnv-mi.bicep' = { + name: 'acaEnv-mi' + scope: rg + params: { + location: location + } +} + module acaEnv 'acaEnv/acaEnv.bicep' = { name: 'acaEnv' scope: rg params: { location: location + acaenv_mi_outputs_id: acaEnv_mi.outputs.id acaenv_acr_outputs_name: acaEnv_acr.outputs.name userPrincipalId: principalId } @@ -55,4 +64,14 @@ module tenantScoped 'tenantScoped/tenantScoped.bicep' = { params: { location: location } +} + +module acaEnv_mi_roles_acaEnv_acr 'acaEnv-mi-roles-acaEnv-acr/acaEnv-mi-roles-acaEnv-acr.bicep' = { + name: 'acaEnv-mi-roles-acaEnv-acr' + scope: rg + params: { + location: location + acaenv_acr_outputs_name: acaEnv_acr.outputs.name + principalId: acaEnv_mi.outputs.principalId + } } \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.PublishAsync_GeneratesMainBicep_WithSnapshots.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.PublishAsync_GeneratesMainBicep_WithSnapshots.verified.bicep index 9842ee5082f..abe6eda9ab7 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.PublishAsync_GeneratesMainBicep_WithSnapshots.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.PublishAsync_GeneratesMainBicep_WithSnapshots.verified.bicep @@ -27,11 +27,20 @@ module acaEnv_acr 'acaEnv-acr/acaEnv-acr.bicep' = { } } +module acaEnv_mi 'acaEnv-mi/acaEnv-mi.bicep' = { + name: 'acaEnv-mi' + scope: rg + params: { + location: location + } +} + module acaEnv 'acaEnv/acaEnv.bicep' = { name: 'acaEnv' scope: rg params: { location: location + acaenv_mi_outputs_id: acaEnv_mi.outputs.id acaenv_acr_outputs_name: acaEnv_acr.outputs.name userPrincipalId: principalId } @@ -125,6 +134,16 @@ module fe_roles_storage 'fe-roles-storage/fe-roles-storage.bicep' = { } } +module acaEnv_mi_roles_acaEnv_acr 'acaEnv-mi-roles-acaEnv-acr/acaEnv-mi-roles-acaEnv-acr.bicep' = { + name: 'acaEnv-mi-roles-acaEnv-acr' + scope: rg + params: { + location: location + acaenv_acr_outputs_name: acaEnv_acr.outputs.name + principalId: acaEnv_mi.outputs.principalId + } +} + output acaEnv_AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = acaEnv.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN output acaEnv_AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = acaEnv.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_ID diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#00.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#00.verified.bicep index 78243879eb4..f0a8652cd31 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#00.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#00.verified.bicep @@ -19,16 +19,35 @@ module env_acr 'env-acr/env-acr.bicep' = { } } +module env_mi 'env-mi/env-mi.bicep' = { + name: 'env-mi' + scope: rg + params: { + location: location + } +} + module env 'env/env.bicep' = { name: 'env' scope: rg params: { location: location + env_mi_outputs_id: env_mi.outputs.id env_acr_outputs_name: env_acr.outputs.name userPrincipalId: principalId } } +module env_mi_roles_env_acr 'env-mi-roles-env-acr/env-mi-roles-env-acr.bicep' = { + name: 'env-mi-roles-env-acr' + scope: rg + params: { + location: location + env_acr_outputs_name: env_acr.outputs.name + principalId: env_mi.outputs.principalId + } +} + output env_AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = env.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN output env_AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = env.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_ID \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#01.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#01.verified.bicep index 1340440b1f3..a71fe381fac 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#01.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_GeneratesProperBicep#01.verified.bicep @@ -5,28 +5,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -75,7 +61,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_RespectsStronglyTypedProperties.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_RespectsStronglyTypedProperties.verified.bicep index e824faa7983..0681a4940d4 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_RespectsStronglyTypedProperties.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureEnvironmentResourceTests.WhenUsedWithAzureContainerAppsEnvironment_RespectsStronglyTypedProperties.verified.bicep @@ -19,16 +19,35 @@ module env_acr 'env-acr/env-acr.bicep' = { } } +module env_mi 'env-mi/env-mi.bicep' = { + name: 'env-mi' + scope: rg + params: { + location: location + } +} + module env 'env/env.bicep' = { name: 'env' scope: rg params: { location: location + env_mi_outputs_id: env_mi.outputs.id env_acr_outputs_name: env_acr.outputs.name userPrincipalId: principalId } } +module env_mi_roles_env_acr 'env-mi-roles-env-acr/env-mi-roles-env-acr.bicep' = { + name: 'env-mi-roles-env-acr' + scope: rg + params: { + location: location + env_acr_outputs_name: env_acr.outputs.name + principalId: env_mi.outputs.principalId + } +} + output env_AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = env.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN output env_AZURE_CONTAINER_APPS_ENVIRONMENT_ID string = env.outputs.AZURE_CONTAINER_APPS_ENVIRONMENT_ID \ No newline at end of file diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_AutoCreatesBothSubnetAndStorage.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_AutoCreatesBothSubnetAndStorage.verified.bicep index 21142d16cca..9ab7385ece1 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_AutoCreatesBothSubnetAndStorage.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_AutoCreatesBothSubnetAndStorage.verified.bicep @@ -122,28 +122,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -192,7 +178,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -221,6 +207,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_BothExplicitSubnetAndStorage.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_BothExplicitSubnetAndStorage.verified.bicep index 3ac06bdc70c..b386182cffa 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_BothExplicitSubnetAndStorage.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_BothExplicitSubnetAndStorage.verified.bicep @@ -160,28 +160,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -230,7 +216,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -259,6 +245,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ClearDefaultRoleAssignments_RemovesDeploymentScriptInfra.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ClearDefaultRoleAssignments_RemovesDeploymentScriptInfra.verified.bicep index c9e232ef419..fe23673476f 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ClearDefaultRoleAssignments_RemovesDeploymentScriptInfra.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ClearDefaultRoleAssignments_RemovesDeploymentScriptInfra.verified.bicep @@ -6,28 +6,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -76,7 +62,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -105,6 +91,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitStorage_AutoCreatesSubnet.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitStorage_AutoCreatesSubnet.verified.bicep index 20b62974c29..28c0b3eebad 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitStorage_AutoCreatesSubnet.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitStorage_AutoCreatesSubnet.verified.bicep @@ -160,28 +160,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -230,7 +216,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -259,6 +245,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitSubnet_AutoCreatesStorage.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitSubnet_AutoCreatesStorage.verified.bicep index 4e4db20b35d..3ef92499ecb 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitSubnet_AutoCreatesStorage.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_ExplicitSubnet_AutoCreatesStorage.verified.bicep @@ -122,28 +122,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -192,7 +178,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -221,6 +207,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_StorageBeforePrivateEndpoint.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_StorageBeforePrivateEndpoint.verified.bicep index 20b62974c29..28c0b3eebad 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_StorageBeforePrivateEndpoint.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_StorageBeforePrivateEndpoint.verified.bicep @@ -160,28 +160,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -230,7 +216,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -259,6 +245,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location diff --git a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_SubnetBeforePrivateEndpoint.verified.bicep b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_SubnetBeforePrivateEndpoint.verified.bicep index 4e4db20b35d..3ef92499ecb 100644 --- a/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_SubnetBeforePrivateEndpoint.verified.bicep +++ b/tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureSqlDeploymentScriptTests.SqlWithPrivateEndpoint_SubnetBeforePrivateEndpoint.verified.bicep @@ -122,28 +122,14 @@ param userPrincipalId string = '' param tags object = { } -param env_acr_outputs_name string +param env_mi_outputs_id string -resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { - name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) - location: location - tags: tags -} +param env_acr_outputs_name string resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { name: env_acr_outputs_name } -resource env_acr_env_mi_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(env_acr.id, env_mi.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) - properties: { - principalId: env_mi.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - } - scope: env_acr -} - resource env_law 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: take('envlaw-${uniqueString(resourceGroup().id)}', 63) location: location @@ -192,7 +178,7 @@ output AZURE_CONTAINER_REGISTRY_NAME string = env_acr.name output AZURE_CONTAINER_REGISTRY_ENDPOINT string = env_acr.properties.loginServer -output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi.id +output AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID string = env_mi_outputs_id output AZURE_CONTAINER_APPS_ENVIRONMENT_NAME string = env.name @@ -221,6 +207,47 @@ output loginServer string = env_acr.properties.loginServer output id string = env_acr.id +// Resource: env-mi +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +resource env_mi 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { + name: take('env_mi-${uniqueString(resourceGroup().id)}', 128) + location: location +} + +output id string = env_mi.id + +output clientId string = env_mi.properties.clientId + +output principalId string = env_mi.properties.principalId + +output principalName string = env_mi.name + +output name string = env_mi.name + +// Resource: env-mi-roles-env-acr +@description('The location for the resource(s) to be deployed.') +param location string = resourceGroup().location + +param env_acr_outputs_name string + +param principalId string + +resource env_acr 'Microsoft.ContainerRegistry/registries@2025-04-01' existing = { + name: env_acr_outputs_name +} + +resource env_acr_AcrPull 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(env_acr.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')) + properties: { + principalId: principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') + principalType: 'ServicePrincipal' + } + scope: env_acr +} + // Resource: myvnet @description('The location for the resource(s) to be deployed.') param location string = resourceGroup().location