-
Notifications
You must be signed in to change notification settings - Fork 856
Add polyglot endpoint callback exports #15856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Net.Sockets; | ||
|
|
||
| namespace Aspire.Hosting.ApplicationModel; | ||
|
|
||
| /// <summary> | ||
| /// Provides a mutable callback context for updating an endpoint in polyglot app hosts. | ||
| /// </summary> | ||
| [AspireExport(ExposeProperties = true)] | ||
| internal sealed class EndpointUpdateContext(EndpointAnnotation endpointAnnotation) | ||
| { | ||
| private readonly EndpointAnnotation _endpointAnnotation = endpointAnnotation ?? throw new ArgumentNullException(nameof(endpointAnnotation)); | ||
|
|
||
sebastienros marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /// <summary> | ||
| /// Gets the endpoint name. | ||
| /// </summary> | ||
| public string Name => _endpointAnnotation.Name; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the network protocol. | ||
| /// </summary> | ||
| public ProtocolType Protocol | ||
| { | ||
| get => _endpointAnnotation.Protocol; | ||
| set => _endpointAnnotation.Protocol = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the desired host port. | ||
| /// </summary> | ||
| public int? Port | ||
| { | ||
| get => _endpointAnnotation.Port; | ||
| set => _endpointAnnotation.Port = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the target port. | ||
| /// </summary> | ||
| public int? TargetPort | ||
| { | ||
| get => _endpointAnnotation.TargetPort; | ||
| set => _endpointAnnotation.TargetPort = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the URI scheme. | ||
| /// </summary> | ||
| public string UriScheme | ||
| { | ||
| get => _endpointAnnotation.UriScheme; | ||
| set => _endpointAnnotation.UriScheme = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the target host. | ||
| /// </summary> | ||
| public string TargetHost | ||
| { | ||
| get => _endpointAnnotation.TargetHost; | ||
| set => _endpointAnnotation.TargetHost = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the transport. | ||
| /// </summary> | ||
| public string Transport | ||
| { | ||
| get => _endpointAnnotation.Transport; | ||
| set => _endpointAnnotation.Transport = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether the endpoint is external. | ||
| /// </summary> | ||
| public bool IsExternal | ||
| { | ||
| get => _endpointAnnotation.IsExternal; | ||
| set => _endpointAnnotation.IsExternal = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether the endpoint is proxied. | ||
| /// </summary> | ||
| public bool IsProxied | ||
| { | ||
| get => _endpointAnnotation.IsProxied; | ||
| set => _endpointAnnotation.IsProxied = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether the endpoint is excluded from the default reference set. | ||
| /// </summary> | ||
| public bool ExcludeReferenceEndpoint | ||
| { | ||
| get => _endpointAnnotation.ExcludeReferenceEndpoint; | ||
| set => _endpointAnnotation.ExcludeReferenceEndpoint = value; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether TLS is enabled. | ||
| /// </summary> | ||
| public bool TlsEnabled | ||
| { | ||
| get => _endpointAnnotation.TlsEnabled; | ||
| set => _endpointAnnotation.TlsEnabled = value; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1210,9 +1210,9 @@ private static void ApplyEndpoints<T>(this IResourceBuilder<T> builder, IResourc | |
| /// }); | ||
| /// </code> | ||
| /// </example> | ||
| /// <para>This method is not available in polyglot app hosts. Use the parameter-based overload instead.</para> | ||
| /// <para>This method is not available in polyglot app hosts. Use the callback-based endpoint mutation export instead.</para> | ||
| /// </remarks> | ||
| [AspireExportIgnore(Reason = "EndpointAnnotation has read-only properties AllocatedEndpointSnapshot and AllAllocatedEndpoints that are not ATS-compatible. Callback-free variant is exported.")] | ||
| [AspireExportIgnore(Reason = "Polyglot app hosts use the internal withEndpointCallback export, which exposes EndpointUpdateContext instead of EndpointAnnotation.")] | ||
| [System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "<Pending>")] | ||
| public static IResourceBuilder<T> WithEndpoint<T>(this IResourceBuilder<T> builder, [EndpointName] string endpointName, Action<EndpointAnnotation> callback, bool createIfNotExists = true) where T : IResourceWithEndpoints | ||
| { | ||
|
|
@@ -1247,6 +1247,33 @@ public static IResourceBuilder<T> WithEndpoint<T>(this IResourceBuilder<T> build | |
| return builder; | ||
| } | ||
|
|
||
| [AspireExport(Description = "Updates a named endpoint via callback")] | ||
| internal static IResourceBuilder<T> WithEndpointCallback<T>(this IResourceBuilder<T> builder, [EndpointName] string endpointName, Action<EndpointUpdateContext> callback, bool createIfNotExists = true) where T : IResourceWithEndpoints | ||
| { | ||
| ArgumentNullException.ThrowIfNull(builder); | ||
| ArgumentNullException.ThrowIfNull(endpointName); | ||
| ArgumentNullException.ThrowIfNull(callback); | ||
|
|
||
| return builder.WithEndpoint(endpointName, endpoint => callback(new EndpointUpdateContext(endpoint)), createIfNotExists); | ||
| } | ||
|
|
||
| [AspireExport(Description = "Updates an HTTP endpoint via callback")] | ||
| internal static IResourceBuilder<T> WithHttpEndpointCallback<T>(this IResourceBuilder<T> builder, Action<EndpointUpdateContext> callback, [EndpointName] string? name = null, bool createIfNotExists = true) where T : IResourceWithEndpoints | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's also WithHttpsEndpointCallback?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's The polyglot samples work around this by calling |
||
| { | ||
| ArgumentNullException.ThrowIfNull(builder); | ||
| ArgumentNullException.ThrowIfNull(callback); | ||
|
|
||
| var endpointName = name ?? "http"; | ||
|
|
||
| if (createIfNotExists && | ||
| !builder.Resource.Annotations.OfType<EndpointAnnotation>().Any(endpoint => string.Equals(endpoint.Name, endpointName, StringComparisons.EndpointAnnotationName))) | ||
| { | ||
| builder.WithHttpEndpoint(name: endpointName); | ||
| } | ||
|
|
||
| return builder.WithEndpoint(endpointName, endpoint => callback(new EndpointUpdateContext(endpoint)), createIfNotExists: false); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Exposes an endpoint on a resource. A reference to this endpoint can be retrieved using <see cref="ResourceBuilderExtensions.GetEndpoint{T}(IResourceBuilder{T}, string, NetworkIdentifier)"/>. | ||
| /// The endpoint name will be the scheme name if not specified. | ||
|
|
@@ -1394,7 +1421,6 @@ public static IResourceBuilder<T> WithExternalHttpEndpoints<T>(this IResourceBui | |
|
|
||
| return builder; | ||
| } | ||
|
|
||
| /// <summary> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: The blank line between |
||
| /// Gets an <see cref="EndpointReference"/> by name from the resource. These endpoints are declared either using <see cref="WithEndpoint{T}(IResourceBuilder{T}, int?, int?, string?, string?, string?, bool, bool?, ProtocolType?)"/> or by launch settings (for project resources). | ||
| /// The <see cref="EndpointReference"/> can be used to resolve the address of the endpoint in <see cref="WithEnvironment{T}(IResourceBuilder{T}, Action{EnvironmentCallbackContext})"/>. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.