| File: AzureEnvironmentResourceExtensions.cs | Web Access |
| Project: src\src\Aspire.Hosting.Azure\Aspire.Hosting.Azure.csproj (Aspire.Hosting.Azure) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma warning disable ASPIREAZURE001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using Aspire.Hosting.ApplicationModel; using Microsoft.Extensions.DependencyInjection; namespace Aspire.Hosting.Azure; /// <summary> /// Provides extension methods for adding Azure environment resources to the application model. /// </summary> public static class AzureEnvironmentResourceExtensions { /// <summary> /// Adds an Azure environment resource to the application model. /// </summary> /// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param> /// <returns>The <see cref="IResourceBuilder{AzureEnvironmentResource}"/>.</returns> /// <ats-returns>The resource builder.</ats-returns> [AspireExport] [Experimental("ASPIREAZURE001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")] public static IResourceBuilder<AzureEnvironmentResource> AddAzureEnvironment(this IDistributedApplicationBuilder builder) { if (builder.Resources.OfType<AzureEnvironmentResource>().SingleOrDefault() is { } existingResource) { // If the resource already exists, return the existing builder return builder.CreateResourceBuilder(existingResource); } var resourceName = builder.CreateDefaultAzureEnvironmentName(); var locationParam = ParameterResourceBuilderExtensions.CreateParameter(builder, "location", false); var resourceGroupName = ParameterResourceBuilderExtensions.CreateParameter(builder, "resourceGroupName", false); var principalId = ParameterResourceBuilderExtensions.CreateParameter(builder, "principalId", false); var resource = new AzureEnvironmentResource(resourceName, locationParam, resourceGroupName, principalId); if (builder.ExecutionContext.IsRunMode) { var resourceBuilder = builder.AddResource(resource) .OnInitializeResource(ProvisionAzureResourcesAsync) .WithInitialState(new CustomResourceSnapshot { ResourceType = nameof(AzureEnvironmentResource), CreationTimeStamp = DateTime.UtcNow, State = KnownResourceStates.NotStarted, Properties = ImmutableArray<ResourcePropertySnapshot>.Empty }); foreach (var command in AzureProvisioningController.EnvironmentCommandDefinitions) { resourceBuilder.WithCommand( command.Name, command.DisplayName, executeCommand: context => command.ExecuteCommand(context.Services.GetRequiredService<AzureProvisioningController>(), context), commandOptions: new CommandOptions { Description = command.Description, ConfirmationMessage = command.ConfirmationMessage, IconName = command.IconName, IconVariant = command.IconVariant, IsHighlighted = command.IsHighlighted, Arguments = command.Arguments ?? [], ValidateArguments = command.ValidateArguments, UpdateState = context => context.Services.GetRequiredService<AzureProvisioningController>().GetEnvironmentCommandState() }); } return resourceBuilder.ExcludeFromManifest(); } // In publish mode, add the resource to the application model // but exclude it from the manifest so that it is not treated // as a publishable resource by components that process the manifest // for elements. // We need to always add the resource because the AzureEnvironmentResource // needs to show up in the app model during run mode so that we can discover // the pipeline step annotations on it but it needs to be hidden from the end-user. return builder.AddResource(resource) .ExcludeFromManifest() .WithInitialState(new() { ResourceType = nameof(AzureEnvironmentResource), Properties = [], IsHidden = true // hidden from the dashboard }); } private static async Task ProvisionAzureResourcesAsync(AzureEnvironmentResource resource, InitializeResourceEvent @event, CancellationToken cancellationToken) { var model = @event.Services.GetRequiredService<DistributedApplicationModel>(); var provisioner = @event.Services.GetRequiredService<AzureProvisioner>(); await provisioner.ProvisionResourcesAsync(model, cancellationToken).ConfigureAwait(false); } /// <summary> /// Sets the location of the Azure environment resource. /// </summary> /// <param name="builder">The <see cref="IResourceBuilder{TResource}"/>.</param> /// <param name="location">The Azure location.</param> /// <returns>The <see cref="IResourceBuilder{AzureEnvironmentResource}"/>.</returns> /// <ats-returns>The resource builder.</ats-returns> /// <remarks> /// This method is used to set the location of the Azure environment resource. /// The location is used to determine where the resources will be deployed. /// </remarks> [AspireExport] [Experimental("ASPIREAZURE001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")] public static IResourceBuilder<AzureEnvironmentResource> WithLocation( this IResourceBuilder<AzureEnvironmentResource> builder, IResourceBuilder<ParameterResource> location) { ArgumentNullException.ThrowIfNull(builder); ArgumentNullException.ThrowIfNull(location); builder.Resource.Location = location.Resource; return builder; } /// <summary> /// Sets the resource group name of the Azure environment resource. /// </summary> /// <param name="builder">The <see cref="IResourceBuilder{TResource}"/>.</param> /// <param name="resourceGroup">The Azure resource group name.</param> /// <returns>The <see cref="IResourceBuilder{AzureEnvironmentResource}"/>.</returns> /// <ats-returns>The resource builder.</ats-returns> /// <remarks> /// This method is used to set the resource group name of the Azure environment resource. /// The resource group name is used to determine where the resources will be deployed. /// </remarks> [AspireExport] [Experimental("ASPIREAZURE001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")] public static IResourceBuilder<AzureEnvironmentResource> WithResourceGroup( this IResourceBuilder<AzureEnvironmentResource> builder, IResourceBuilder<ParameterResource> resourceGroup) { ArgumentNullException.ThrowIfNull(builder); ArgumentNullException.ThrowIfNull(resourceGroup); builder.Resource.ResourceGroupName = resourceGroup.Resource; return builder; } private static string CreateDefaultAzureEnvironmentName(this IDistributedApplicationBuilder builder) { var name = "azure-environment"; var index = 2; while (builder.Resources.Any(resource => StringComparers.ResourceName.Equals(resource.Name, name))) { name = $"azure-environment{index++}"; } return name; } }