diff --git a/playground/ExternalServices/ExternalServices.AppHost/aspire-manifest.json b/playground/ExternalServices/ExternalServices.AppHost/aspire-manifest.json index 27e3fc5a1b2..368edbe202f 100644 --- a/playground/ExternalServices/ExternalServices.AppHost/aspire-manifest.json +++ b/playground/ExternalServices/ExternalServices.AppHost/aspire-manifest.json @@ -41,4 +41,29 @@ }, "frontend": { "type": "project.v0", - "path": "../WebFrontEnd/WebFrontEnd.csproj" \ No newline at end of file + "path": "../WebFrontEnd/WebFrontEnd.csproj", + "env": { + "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true", + "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true", + "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory", + "ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true", + "HTTP_PORTS": "{frontend.bindings.http.targetPort}", + "services__nuget__https__0": "https://api.nuget.org/", + "EXTERNAL_SERVICE_URL": "{external-service-url.value}", + "services__gateway__http__0": "{gateway.bindings.http.url}" + }, + "bindings": { + "http": { + "scheme": "http", + "protocol": "tcp", + "transport": "http" + }, + "https": { + "scheme": "https", + "protocol": "tcp", + "transport": "http" + } + } + } + } +} \ No newline at end of file diff --git a/src/Aspire.Hosting/ResourceBuilderExtensions.cs b/src/Aspire.Hosting/ResourceBuilderExtensions.cs index 364d0c793c9..13c148cc7e5 100644 --- a/src/Aspire.Hosting/ResourceBuilderExtensions.cs +++ b/src/Aspire.Hosting/ResourceBuilderExtensions.cs @@ -179,12 +179,14 @@ public static IResourceBuilder WithEnvironment(this IResourceBuilder bu { builder.WithEnvironment(async context => { - var url = await externalService.Resource.UrlParameter.GetValueAsync(context.CancellationToken).ConfigureAwait(false); - // In publish mode we can't validate the parameter value so we'll just use it without validating. - if (!context.ExecutionContext.IsPublishMode && !ExternalServiceResource.UrlIsValidForExternalService(url, out var _, out var message)) + if (!context.ExecutionContext.IsPublishMode) { - throw new DistributedApplicationException($"The URL parameter '{externalService.Resource.UrlParameter.Name}' for the external service '{externalService.Resource.Name}' is invalid: {message}"); + var url = await externalService.Resource.UrlParameter.GetValueAsync(context.CancellationToken).ConfigureAwait(false); + if (!ExternalServiceResource.UrlIsValidForExternalService(url, out var _, out var message)) + { + throw new DistributedApplicationException($"The URL parameter '{externalService.Resource.UrlParameter.Name}' for the external service '{externalService.Resource.Name}' is invalid: {message}"); + } } context.EnvironmentVariables[name] = externalService.Resource.UrlParameter; diff --git a/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs b/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs index 9cdc3652d53..aae26da9132 100644 --- a/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs +++ b/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs @@ -443,6 +443,23 @@ public async Task ExternalServiceWithParameterHttpHealthCheckResolvesUrlAsync() Assert.Contains(healthCheckKey, result.Entries.Keys); } + [Fact] + public async Task ExternalServiceWithParameterPublishManifest() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var urlParam = builder.AddParameter("external-url"); + var externalService = builder.AddExternalService("external", urlParam); + + var project = builder.AddProject("project") + .WithReference(externalService) + .WithEnvironment("EXTERNAL_SERVICE", externalService); + + var manifest = await ManifestUtils.GetManifest(project.Resource); + + await Verify(manifest.ToString(), extension: "json"); + } + private sealed class TestProject : IProjectMetadata { public string ProjectPath => "testproject"; diff --git a/tests/Aspire.Hosting.Tests/Snapshots/ExternalServiceTests.ExternalServiceWithParameterPublishManifest.verified.json b/tests/Aspire.Hosting.Tests/Snapshots/ExternalServiceTests.ExternalServiceWithParameterPublishManifest.verified.json new file mode 100644 index 00000000000..73910c77b68 --- /dev/null +++ b/tests/Aspire.Hosting.Tests/Snapshots/ExternalServiceTests.ExternalServiceWithParameterPublishManifest.verified.json @@ -0,0 +1,11 @@ +{ + "type": "project.v0", + "path": "testproject", + "env": { + "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true", + "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true", + "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory", + "services__external__default__0": "{external-url.value}", + "EXTERNAL_SERVICE": "{external-url.value}" + } +} \ No newline at end of file