Conversation
Make it so that aspire can use dynamic ports for `ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL`, `ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL` and other urls that previously had to be specifeid in `launchsettings.json` if they're missing. This does a number of things such as: - Make it easier to use a dashboard within tests - you can now enable the dashboad simply by setting `DistributedApplicationBuilderOptions.DisableDashboard = false` - A single file app host should now be possible, without needing to specify `aspire.config.json` or `apphost.run.json`
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16046Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16046" |
There was a problem hiding this comment.
Pull request overview
Updates Aspire dashboard/resource-service configuration to treat several URL settings as optional, enabling dynamic port allocation (reducing the need for launchSettings.json-pinned URLs) and making it easier to enable the dashboard in tests and single-file app host scenarios.
Changes:
- Relaxes transport/dashboard option validation so missing/blank URLs can succeed and be dynamically allocated.
- Auto-configures dashboard frontend + OTLP endpoints when configuration is missing/blank.
- Updates/extends tests and removes pinned dashboard/resource-service URL env vars from many playground launch profiles/config files.
Reviewed changes
Copilot reviewed 73 out of 77 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Tests/Dashboard/TransportOptionsValidatorTests.cs | Updates expectations so missing/blank URLs validate successfully. |
| tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs | Adds coverage for dynamic OTLP + frontend endpoint auto-configuration. |
| tests/Aspire.Hosting.Tests/Dashboard/DashboardOptionsTests.cs | Adds coverage for blank OTLP endpoint normalization to null. |
| src/Aspire.Hosting/Dashboard/TransportOptionsValidator.cs | Makes app/OTLP/resource-service URL settings optional (only validate when present). |
| src/Aspire.Hosting/Dashboard/DashboardServiceHost.cs | Chooses default scheme for dynamic resource service hosting based on AllowUnsecuredTransport. |
| src/Aspire.Hosting/Dashboard/DashboardOptions.cs | Normalizes blank OTLP endpoint URLs to null; removes dashboard option validation. |
| src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs | Adds dynamic dashboard frontend endpoint when ASPNETCORE_URLS missing; always adds OTLP endpoint annotations. |
| playground/yarp/Yarp.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/withdockerfile/WithDockerfile.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/webpubsub/WebPubSub.AppHost/Properties/launchSettings.json | Removes pinned dashboard OTLP env var; updates applicationUrl host. |
| playground/waitfor/WaitForSandbox.DbSetup/Properties/launchSettings.json | JSON formatting fix (closing brace). |
| playground/waitfor/WaitForSandbox.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/TypeScriptApps/RpsArena/aspire.config.json | Removes pinned dashboard/resource-service endpoint env vars from profile. |
| playground/TypeScriptApps/RpsArena/apphost.run.json | Removes pinned dashboard/resource-service endpoint env vars; JSON formatting fix. |
| playground/TypeScriptApps/AzureFunctionsSample/AppHost/apphost.run.json | Removes pinned dashboard/resource-service endpoint env vars; JSON formatting fix. |
| playground/TypeScriptAppHost/apphost.run.json | Removes pinned dashboard/resource-service endpoint env vars. |
| playground/TestShop/TestShop.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/Stress/Stress.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/SqlServerScript/AppHost1/Properties/launchSettings.json | Removes pinned dashboard OTLP env var. |
| playground/SqlServerEndToEnd/SqlServerEndToEnd.DbSetup/Properties/launchSettings.json | JSON formatting fix (closing brace). |
| playground/SqlServerEndToEnd/SqlServerEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host; JSON formatting fix. |
| playground/signalr/SignalR.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/seq/Seq.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/Redis/Redis.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/Qdrant/Qdrant.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/PythonAppHost/apphost.run.json | Removes pinned dashboard/resource-service endpoint env vars (keeps MCP endpoint). |
| playground/python/Python.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/publishers/Publishers.DbSetup/Properties/launchSettings.json | JSON formatting fix (closing brace). |
| playground/publishers/Publishers.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/ProxylessEndToEnd/ProxylessEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/ProjectResourceExtensions/ProjectResourceExtensions.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/PostgresEndToEnd/PostgresEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/pipelines/Pipelines.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/ParameterEndToEnd/ParameterEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/orleans/Orleans.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/OracleEndToEnd/OracleEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/OpenAIEndToEnd/OpenAIEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/nats/Nats.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/mysql/MySqlDb.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/mongo/Mongo.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/milvus/MilvusPlayground.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/keycloak/Keycloak.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/kafka/KafkaBasic.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/JavaAppHost/aspire.config.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/HealthChecks/HealthChecksSandbox.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/GitHubModelsEndToEnd/GitHubModelsEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/FoundryEndToEnd/FoundryEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/FoundryAgentBasic/FoundryAgentBasic.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/FileBasedApps/apphost.settings.json | Adds Dashboard config section (DetailedErrors). |
| playground/FileBasedApps/apphost.run.json.old | Removes pinned dashboard/resource-service endpoint env vars. |
| playground/ExternalServices/ExternalServices.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/DotnetTool/DotnetTool.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/DevTunnels/DevTunnels.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/deployers/Deployers.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/DatabaseMigration/DatabaseMigration.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/CustomResources/CustomResources.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/CosmosEndToEnd/CosmosEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/cdk/CdkSample.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/BrowserTelemetry/BrowserTelemetry.AppHost/Properties/launchSettings.json | Removes pinned OTLP/resource-service endpoint env vars; updates applicationUrl host. |
| playground/bicep/BicepSample.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureVirtualNetworkEndToEnd/AzureVirtualNetworkEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureStorageEndToEnd/AzureStorageEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureServiceBus/ServiceBus.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureSearchEndToEnd/AzureSearch.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureOpenAIEndToEnd/AzureOpenAIEndToEnd.WebStory/Properties/launchSettings.json | JSON formatting fix (closing brace). |
| playground/AzureOpenAIEndToEnd/AzureOpenAIEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureKusto/AzureKusto.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureFunctionsWithDts/AzureFunctionsWithDts.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureFunctionsEndToEnd/AzureFunctionsEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureDataLakeEndToEnd/AzureDataLakeEndToEnd.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureContainerApps/AzureContainerApps.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureAppService/AzureAppService.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AzureAppConfiguration/AzureAppConfiguration.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AspireWithNode/AspireWithNode.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AspireWithMaui/AspireWithMaui.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AspireWithJavaScript/AspireJavaScript.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| playground/AspireEventHub/EventHubs.AppHost/Properties/launchSettings.json | Removes pinned dashboard/resource-service endpoint env vars; updates applicationUrl host. |
| var uriScheme = allowUnsecureTransport ? "http" : "https"; | ||
| var endpointName = allowUnsecureTransport ? "http" : "https"; | ||
| dashboardResource.Annotations.Add(new EndpointAnnotation(ProtocolType.Tcp, name: endpointName, uriScheme: uriScheme, isProxied: true)); | ||
| } |
There was a problem hiding this comment.
dashboardUrls is parsed in the foreach loop before the new string.IsNullOrWhiteSpace(dashboardUrls) check. If ASPNETCORE_URLS is set to whitespace (or contains whitespace-only entries), Split(..., RemoveEmptyEntries) will still yield whitespace strings and BindingAddress.Parse(d) will throw at runtime before the dynamic endpoint fallback runs. Consider guarding the loop with if (!string.IsNullOrWhiteSpace(dashboardUrls)) (and trimming entries) and using the else branch for the dynamic endpoint case.
| private static EndpointAnnotation CreateDashboardOtlpEndpointAnnotation(string? endpointUrl, string endpointName, string? transport = null) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(endpointUrl)) | ||
| { | ||
| return new EndpointAnnotation(ProtocolType.Tcp, name: endpointName, uriScheme: "https", isProxied: true, transport: transport); | ||
| } |
There was a problem hiding this comment.
When endpointUrl is missing/blank, CreateDashboardOtlpEndpointAnnotation hard-codes uriScheme: "https". This ignores ASPIRE_ALLOW_UNSECURED_TRANSPORT and can unintentionally create HTTPS endpoints (triggering HTTPS certificate configuration) even when the dashboard is otherwise configured for HTTP-only, which may break unsecured scenarios. Consider selecting the default scheme based on AllowUnsecuredTransport (or on the frontend scheme) when auto-configuring dynamic OTLP endpoints.
| internal class ValidateDashboardOptions : IValidateOptions<DashboardOptions> | ||
| { | ||
| public ValidateOptionsResult Validate(string? name, DashboardOptions options) | ||
| { | ||
| var builder = new ValidateOptionsResultBuilder(); | ||
|
|
||
| if (string.IsNullOrEmpty(options.DashboardUrl)) | ||
| { | ||
| builder.AddError($"Failed to configure dashboard resource because {KnownConfigNames.AspNetCoreUrls} environment variable was not set."); | ||
| } | ||
|
|
||
| if (string.IsNullOrEmpty(options.OtlpGrpcEndpointUrl) && string.IsNullOrEmpty(options.OtlpHttpEndpointUrl)) | ||
| { | ||
| builder.AddError($"Failed to configure dashboard resource because {KnownConfigNames.DashboardOtlpGrpcEndpointUrl} and {KnownConfigNames.DashboardOtlpHttpEndpointUrl} environment variables are not set. At least one OTLP endpoint must be provided."); | ||
| } | ||
|
|
||
| return builder.Build(); | ||
| return ValidateOptionsResult.Success; | ||
| } | ||
| } |
There was a problem hiding this comment.
ValidateDashboardOptions.Validate now always returns Success, so registering this validator no longer provides any validation and can be misleading for maintainers (and makes the comment in ConfigureEnvironmentVariables about validated options inaccurate). Either remove this validator registration or add targeted validation that is still required with the new optional-URL behavior (e.g., validating DashboardPath when present).
| var options = dashboardOptions.Value; | ||
|
|
||
| // Options should have been validated these should not be null | ||
|
|
||
| Debug.Assert(options.DashboardUrl is not null, "DashboardUrl should not be null"); | ||
| Debug.Assert(options.OtlpGrpcEndpointUrl is not null || options.OtlpHttpEndpointUrl is not null, "OtlpGrpcEndpointUrl and OtlpHttpEndpointUrl should not both be null"); | ||
|
|
||
| var environment = options.AspNetCoreEnvironment; | ||
| var browserToken = options.DashboardToken; |
There was a problem hiding this comment.
The comment "Options should have been validated these should not be null" is now outdated because ValidateDashboardOptions no longer performs any validation and the Debug.Assert checks were removed. Consider removing/updating the comment (and ensuring downstream code paths tolerate nulls where appropriate).
…ICE_ENDPOINT_URL` from default templates
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
| @@ -8,9 +8,7 @@ | |||
| "applicationUrl": "https://filebasedapps.dev.localhost:17123;http://filebasedapps.dev.localhost:15234", | |||
There was a problem hiding this comment.
oops, didn't mean to commit - Can't fully remove this file yey as the dashboard fails to load if ASPNETCORE_ENVIRONMENT is not set
| "Microsoft.AspNetCore": "Warning" | ||
| } | ||
| }, | ||
| "Dashboard" : { |
There was a problem hiding this comment.
My bad, again didn't mean to commit. This was to try and see if I could work out why the dashboard wasn't loading. Got as far as working out it was caued by the missing ASPNETCORE_ENVIRONMENT env var
davidfowl
left a comment
There was a problem hiding this comment.
When OTLP endpoint URLs are not specified (null/blank), CreateDashboardOtlpEndpointAnnotation always creates endpoints with "https" scheme, even when ASPIRE_ALLOW_UNSECURED_TRANSPORT=true.
The frontend dashboard endpoint correctly respects allowUnsecureTransport to choose http vs https (line ~422-424), but the OTLP endpoints dont — CreateDashboardOtlpEndpointAnnotation hardcodes "https" when endpointUrl is null (line ~642).
This means when users set ASPIRE_ALLOW_UNSECURED_TRANSPORT=true and dont specify OTLP URLs, the dashboard will try to bind OTLP endpoints using HTTPS, which will fail without dev certificates — defeating the purpose of the flag.
Suggested fix: Pass allowUnsecuredTransport to CreateDashboardOtlpEndpointAnnotation and use it for the default scheme:
uriScheme: allowUnsecuredTransport ? "http" : "https"Also missing a test case combining allowUnsecuredTransport=true with blank OTLP URLs to verify they use HTTP.
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
|
@afscrome please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
Description
Make it so that aspire can use dynamic ports for
ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL,ASPIRE_RESOURCE_SERVICE_ENDPOINT_URLand other urls that previously had to be specifeid inlaunchsettings.jsonif they're missing.This does a number of things such as:
Make it easier to use a dashboard within tests - you can now enable the dashboad simply by setting
DistributedApplicationBuilderOptions.DisableDashboard = false, and not needing to set a bunch of magic env vars. (Which then get ignored anyway due to Port randomisation for testing)A single file app host should now be possible, without needing to specify
aspire.config.jsonorapphost.run.json. (Not quite possible yet due to Dashboard doesn't load ifASPNETCORE_ENVIRONMENTis notDevelopment#16069)Helps towards #15999 and #13746
Checklist
<remarks />and<code />elements on your triple slash comments?aspire.devissue: