| File: DotnetProgramResourceBuilderExtensions.cs | Web Access |
| Project: src\src\Aspire.Hosting\Aspire.Hosting.csproj (Aspire.Hosting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using Aspire.Hosting.ApplicationModel; namespace Aspire.Hosting; /// <summary> /// Provides publishing configuration for resources backed by .NET programs. /// </summary> [Experimental("ASPIREPROJECTS001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")] public static class DotnetProgramResourceBuilderExtensions { /// <summary> /// Configures the .NET program to run the specified number of replicas. /// </summary> /// <typeparam name="T">The .NET program resource type.</typeparam> /// <param name="builder">The resource builder.</param> /// <param name="replicas">The number of replicas.</param> /// <returns>The resource builder for chaining.</returns> [AspireExportIgnore(Reason = "Polyglot integrations export concrete resource overloads so fluent APIs preserve their concrete builder type.")] public static IResourceBuilder<T> WithReplicas<T>(this IResourceBuilder<T> builder, int replicas) where T : IDotnetProgramResource { ArgumentNullException.ThrowIfNull(builder); builder.WithAnnotation(new ReplicaAnnotation(replicas)); return builder; } /// <summary> /// Configures the .NET program to omit automatic forwarded-header configuration when publishing. /// </summary> /// <typeparam name="T">The .NET program resource type.</typeparam> /// <param name="builder">The resource builder.</param> /// <returns>The resource builder for chaining.</returns> [AspireExportIgnore(Reason = "Polyglot integrations export concrete resource overloads so fluent APIs preserve their concrete builder type.")] public static IResourceBuilder<T> DisableForwardedHeaders<T>(this IResourceBuilder<T> builder) where T : IDotnetProgramResource { ArgumentNullException.ThrowIfNull(builder); return builder.WithAnnotation<DisableForwardedHeadersAnnotation>(ResourceAnnotationMutationBehavior.Replace); } /// <summary> /// Configures which endpoints contribute environment variables for the .NET program. /// </summary> /// <typeparam name="T">The .NET program resource type.</typeparam> /// <param name="builder">The resource builder.</param> /// <param name="filter">The endpoint inclusion filter.</param> /// <returns>The resource builder for chaining.</returns> [AspireExportIgnore(Reason = "Uses Func<EndpointAnnotation, bool>; polyglot app hosts use the endpoint-name dispatcher.")] public static IResourceBuilder<T> WithEndpointsInEnvironment<T>( this IResourceBuilder<T> builder, Func<EndpointAnnotation, bool> filter) where T : IDotnetProgramResource { ArgumentNullException.ThrowIfNull(builder); ArgumentNullException.ThrowIfNull(filter); builder.Resource.Annotations.Add(new EndpointEnvironmentInjectionFilterAnnotation(filter)); return builder; } /// <summary> /// Adds a callback that configures build-only environment variables for .NET SDK container publishing. /// </summary> /// <typeparam name="T">The .NET program resource type.</typeparam> /// <param name="builder">The resource builder.</param> /// <param name="callback">The callback that configures the build environment.</param> /// <returns>The resource builder for chaining.</returns> /// <exception cref="ArgumentNullException"> /// Thrown when <paramref name="builder"/> or <paramref name="callback"/> is <see langword="null"/>. /// </exception> /// <remarks> /// <para> /// Values supplied through this callback affect the publishing MSBuild evaluation and may appear in build /// diagnostics. They are not a secret transport. Callbacks are evaluated in registration order for each publish build. /// </para> /// <para> /// When publishing a container, Aspire rejects values that control the output artifact's identity, destination, /// format, or target platform because downstream publishing steps use the corresponding container build options. /// Configure those values with <c>WithContainerBuildOptions</c>. /// </para> /// </remarks> [AspireExportIgnore(Reason = "Integration authoring API with a raw delegate callback that is not ATS-compatible.")] public static IResourceBuilder<T> WithDotnetProgramBuildEnvironment<T>( this IResourceBuilder<T> builder, Func<EnvironmentCallbackContext, Task> callback) where T : IDotnetProgramResource { ArgumentNullException.ThrowIfNull(builder); ArgumentNullException.ThrowIfNull(callback); return builder.WithAnnotation(new DotnetProgramBuildEnvironmentCallbackAnnotation(callback)); } /// <summary> /// Configures a .NET program resource to publish a container image through the .NET SDK. /// </summary> /// <typeparam name="T">The .NET program resource type.</typeparam> /// <param name="builder">The resource builder.</param> /// <returns>The resource builder for chaining.</returns> /// <exception cref="InvalidOperationException"> /// The resource does not implement <see cref="IComputeResource"/> or does not carry exactly one stable /// <see cref="IProjectMetadata"/> annotation. /// </exception> /// <remarks> /// This method is intended for .NET language integrations that model programs without deriving from /// <see cref="ProjectResource"/>. Ordinary projects created with <c>AddProject</c> are configured automatically. /// </remarks> [AspireExportIgnore(Reason = "Integration authoring API that depends on .NET project metadata and is not part of the ATS surface.")] public static IResourceBuilder<T> WithDotnetProgramPublishing<T>(this IResourceBuilder<T> builder) where T : IDotnetProgramResource { ArgumentNullException.ThrowIfNull(builder); if (builder.Resource is not IComputeResource) { throw new InvalidOperationException( $"Resource '{builder.Resource.Name}' must implement {nameof(IComputeResource)} to use .NET SDK publishing."); } _ = builder.Resource.GetProjectMetadata(); DotnetProgramPublishing.Configure(builder.Resource); return builder; } }