Default dashboard endpoints when config is missing - #17371
Default dashboard endpoints when config is missing#17371Adam Ratzman (adamint) wants to merge 1 commit into
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17371Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17371" |
There was a problem hiding this comment.
Pull request overview
Restores the Aspire Hosting dashboard’s ability to start when aspire.config.json / launch profile endpoint configuration is missing, by falling back to dynamically allocated runtime endpoints and relaxing the relevant validation. The PR also includes a sizable Aspire CLI change around update-notification banners (including JSON-output suppression) and adds VS Code task dependencies to ensure the extension’s packages are installed before watch tasks run.
Changes:
- Hosting: Allow missing dashboard/OTLP/resource-service endpoint configuration to succeed validation and rely on runtime endpoint allocation.
- Hosting tests: Add/adjust tests to cover “missing/empty config uses dynamic defaults” scenarios.
- CLI/DevEx: Rework update-notification defaults and suppress banners for JSON output; add
yarn installprerequisite tasks for extension watch.
Reviewed changes
Copilot reviewed 46 out of 46 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Tests/Dashboard/TransportOptionsValidatorTests.cs | Updates validation expectations so missing/empty endpoint config succeeds. |
| tests/Aspire.Hosting.Tests/Dashboard/DashboardResourceTests.cs | Adds coverage for dynamic default endpoint allocation when config is absent/partial. |
| tests/Aspire.Cli.Tests/Commands/BaseCommandTests.cs | Adds test coverage for update notification behavior under JSON/non-JSON invocations. |
| src/Aspire.Hosting/Dashboard/TransportOptionsValidator.cs | Relaxes validation so missing dashboard-related endpoint config can fall back to runtime defaults. |
| src/Aspire.Hosting/Dashboard/DashboardOptions.cs | Removes options validation that previously required dashboard/OTLP URLs. |
| src/Aspire.Hosting/Dashboard/DashboardEventHandlers.cs | Creates default endpoints when missing and wires endpoint annotations for runtime allocation. |
| src/Aspire.Cli/Commands/BaseCommand.cs | Changes update-notification gating behavior and adds JSON-based suppression. |
| src/Aspire.Cli/Commands/AddCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/InitCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/NewCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/LsCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/PsCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/StartCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/StopCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/WaitCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/RestoreCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/ResourceCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/LogsCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/DescribeCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/ExportCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/DashboardRunCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/SetupCommand.cs | Opts command into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/PipelineCommandBase.cs | Opts pipeline commands into update notifications under new BaseCommand default behavior. |
| src/Aspire.Cli/Commands/UpdateCommand.cs | Relies on new BaseCommand default to avoid update notifications for the update command. |
| src/Aspire.Cli/Commands/RenderCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/ParentCommand.cs | Relies on new BaseCommand default to avoid update notifications for parent/help-style commands. |
| src/Aspire.Cli/Commands/ApiGetCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/ApiListCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/ApiSearchCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/DocsGetCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/DocsListCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/DocsSearchCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/IntegrationSearchCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/ConfigCommand.cs | Relies on new BaseCommand default to avoid update notifications for config subcommands. |
| src/Aspire.Cli/Commands/ExtensionInternalCommand.cs | Relies on new BaseCommand default to avoid update notifications for internal/extension commands. |
| src/Aspire.Cli/Commands/McpStartCommand.cs | Relies on new BaseCommand default to avoid update notifications for MCP commands. |
| src/Aspire.Cli/Commands/McpInitCommand.cs | Relies on new BaseCommand default to avoid update notifications for MCP commands. |
| src/Aspire.Cli/Commands/AgentMcpCommand.cs | Relies on new BaseCommand default to avoid update notifications for MCP server command. |
| src/Aspire.Cli/Commands/AgentInitCommand.cs | Relies on new BaseCommand default to avoid update notifications for agent init command. |
| src/Aspire.Cli/Commands/Sdk/SdkDumpCommand.cs | Relies on new BaseCommand default to avoid update notifications for SDK dump. |
| src/Aspire.Cli/Commands/DoctorCommand.cs | Relies on new BaseCommand default to avoid update notifications (per existing rationale). |
| src/Aspire.Cli/Commands/CertificatesTrustCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/CertificatesCleanCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| src/Aspire.Cli/Commands/CacheCommand.cs | Relies on new BaseCommand default to avoid update notifications. |
| extension/.vscode/tasks.json | Ensures yarn install runs before extension watch task. |
| .vscode/tasks.json | Ensures yarn install runs before extension watch task when running from repo root. |
PR Testing CompleteResult: ✅ Verified with the PR dogfood CLI.
Evidence from the dashboard-defaults scenario:
Notes:
|
|
Adam Ratzman (@adamint) Rebase the PR to remove commits from other PRs. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
d666175 to
4ca5ef3
Compare
James Newton-King (JamesNK)
left a comment
There was a problem hiding this comment.
Design difference from #16046: PR #16046 uses AllowUnsecuredTransport to decide whether dynamic endpoints use http or https. This PR instead infers the OTLP scheme from the configured dashboard URLs via GetDefaultOtlpScheme (https if any https URL present, http otherwise). The two approaches conflict — worth aligning on one strategy if both are under consideration.
Main observations:
ValidateDashboardOptionsis now dead code (always returns Success) — consider removing- Only OTLP gRPC is created in the dynamic defaults case (no HTTP) — browser telemetry won't work without explicit config
- Minor normalization inconsistency for edge case of empty-string config values
| { | ||
| 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 is now dead code — it unconditionally returns ValidateOptionsResult.Success. Consider removing the class (and its DI registration) entirely, or adding a comment explaining why the shell is retained.
| if (otlpGrpcEndpointUrl is null && otlpHttpEndpointUrl is null) | ||
| { | ||
| dashboardResource.Annotations.Add(CreateEndpoint(KnownEndpointNames.OtlpGrpcEndpointName, uriScheme: GetDefaultOtlpScheme(dashboardUrls), transport: "http2")); |
There was a problem hiding this comment.
When both OTLP endpoints are unconfigured, only a gRPC endpoint is created — no HTTP OTLP endpoint. This means browser-based telemetry (which requires HTTP OTLP) won't work with dynamic defaults. Consider adding a comment explaining why only gRPC is defaulted, so future readers don't assume it's an oversight.
Also noting a design difference vs #16046: that PR uses AllowUnsecuredTransport to decide whether dynamic endpoints use http or https. This PR instead infers the OTLP scheme from the configured dashboard URLs (https if any https URL present, http otherwise) via GetDefaultOtlpScheme. The two approaches would conflict if both were merged.
| static string? NormalizeConfiguredUrl(string? url) => | ||
| string.IsNullOrWhiteSpace(url) ? null : url; |
There was a problem hiding this comment.
Minor: ConfigureAspireDashboardResource normalizes options.OtlpHttpEndpointUrl to null when empty via NormalizeConfiguredUrl, so no OTLP HTTP endpoint is created. But ConfigureEnvironmentVariables (line ~594) reads options.OtlpHttpEndpointUrl directly — if someone sets ASPIRE_DASHBOARD_OTLP_HTTP_ENDPOINT_URL="", the empty string passes the != null check and enters the CORS block despite no HTTP OTLP endpoint existing. Previously, validation would have rejected this case. Consider using !string.IsNullOrWhiteSpace(options.OtlpHttpEndpointUrl) in the CORS gate for consistency with the normalization here.
Description
Fixes #9999
Aspire dashboard startup should not require
aspire.config.jsonor launch profile environment variables to provide dashboard and OTLP endpoint URLs. Today, custom or incomplete profiles can fail validation before the dashboard has a chance to use runtime endpoint allocation.This change lets missing dashboard URL, OTLP endpoint, and resource service endpoint configuration fall back to dynamic runtime defaults instead of mutating existing config files. Explicitly configured values are still validated, including malformed URLs and insecure HTTP values unless unsecured transport is allowed.
User-facing usage
Users can run an AppHost even when the profile/config does not include dashboard endpoint environment variables such as:
{ "ASPNETCORE_URLS": "https://localhost:<port>;http://localhost:<port>", "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:<port>", "ASPIRE_DASHBOARD_RESOURCE_SERVER_ENDPOINT_URL": "https://localhost:<port>" }When those values are absent, Aspire Hosting now creates dashboard and OTLP endpoints dynamically and uses the allocated endpoint values for the dashboard environment at runtime.
Validation:
dotnet test --project tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj --no-launch-profile -- --filter-class "*.DashboardResourceTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"dotnet test --project tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj --no-launch-profile -- --filter-class "*.TransportOptionsValidatorTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"dotnet test --project tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj --no-build --no-launch-profile -- --filter-class "*.DashboardResourceTests" --filter-class "*.TransportOptionsValidatorTests" --filter-class "*.DashboardOptionsTests" --filter-class "*.DashboardEventHandlersTests" --filter-class "*.WithOtlpExporterTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"dotnet build tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj --no-restore /p:SkipNativeBuild=trueChecklist
<remarks />and<code />elements on your triple slash comments?