| File: InnerLoop\RadiusInfrastructureInitializationTests.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Radius.Tests\Aspire.Hosting.Radius.Tests.csproj (Aspire.Hosting.Radius.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.CompilerServices; using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Utils; using Microsoft.Extensions.DependencyInjection; namespace Aspire.Hosting.Radius.Tests.InnerLoop; public class RadiusInfrastructureInitializationTests { // These tests drive the pipeline through DistributedApplication.ExecuteBeforeStartHooksAsync, // which is internal and only reachable from inside Aspire.Hosting. UnsafeAccessor lets us // invoke it from outside without making it public. This mirrors the established pattern in // the Kubernetes/Docker integration tests. [Fact] public async Task PrepareDeploymentTargets_AttachesDeploymentTargetAnnotation_ToContainerResources() { using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddRadiusEnvironment("radius"); builder.AddContainer("api", "myapp/api:latest"); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); var apiResource = model.Resources.First(r => r.Name == "api"); var annotations = apiResource.Annotations.OfType<DeploymentTargetAnnotation>().ToArray(); Assert.Single(annotations); Assert.IsType<RadiusEnvironmentResource>(annotations[0].ComputeEnvironment); } [Fact] public async Task PrepareDeploymentTargets_AttachesAnnotation_ToAllComputeResources() { using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddRadiusEnvironment("radius"); builder.AddContainer("frontend", "myapp/frontend:latest"); builder.AddContainer("backend", "myapp/backend:latest"); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); foreach (var resource in model.GetComputeResources()) { var annotations = resource.Annotations.OfType<DeploymentTargetAnnotation>().ToArray(); Assert.NotEmpty(annotations); } } [Fact] public async Task PrepareDeploymentTargets_DoesNotAnnotate_NonComputeResources() { using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddRadiusEnvironment("radius"); builder.AddContainer("api", "myapp/api:latest"); builder.AddParameter("my-param"); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); var paramResource = model.Resources.First(r => r.Name == "my-param"); // Parameters are not compute resources, so should not have a deployment target annotation var annotations = paramResource.Annotations.OfType<DeploymentTargetAnnotation>().ToArray(); Assert.Empty(annotations); } [Fact] public async Task PrepareDeploymentTargets_AnnotationPointsToCorrectEnvironment() { using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var env = builder.AddRadiusEnvironment("myenv"); builder.AddContainer("api", "myapp/api:latest"); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); var apiResource = model.Resources.First(r => r.Name == "api"); var annotation = apiResource.Annotations.OfType<DeploymentTargetAnnotation>().First(); Assert.Same(env.Resource, annotation.ComputeEnvironment); } [Fact] public async Task PrepareDeploymentTargets_AttachesAnnotation_ToProjectResources() { using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); builder.AddRadiusEnvironment("radius"); builder.AddProject<TestProjectMetadata>("webapp"); using var app = builder.Build(); await ExecuteBeforeStartHooksAsync(app, default); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); var projectResource = model.Resources.First(r => r.Name == "webapp"); var annotations = projectResource.Annotations.OfType<DeploymentTargetAnnotation>().ToArray(); Assert.Single(annotations); Assert.IsType<RadiusEnvironmentResource>(annotations[0].ComputeEnvironment); } [Fact] public async Task AddRadiusEnvironment_InRunMode_DoesNotRegisterEnvironmentResource() { // A3: In Run mode the integration short-circuits and the environment is NOT added to the // application builder. This avoids surfacing a publish-only resource in the dashboard // and prevents pipeline steps from being wired up for inner-loop scenarios. Matches the // Kubernetes / Docker Compose integration behaviour. using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Run); builder.AddRadiusEnvironment("radius"); builder.AddContainer("api", "myapp/api:latest"); using var app = builder.Build(); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); Assert.Empty(model.Resources.OfType<RadiusEnvironmentResource>()); } [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "ExecuteBeforeStartHooksAsync")] private static extern Task ExecuteBeforeStartHooksAsync(DistributedApplication app, CancellationToken cancellationToken); private sealed class TestProjectMetadata : IProjectMetadata { public string ProjectPath => "testproject"; public LaunchSettings LaunchSettings { get; } = new(); } }