| File: AzureManifestUtils.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Azure.Tests\Aspire.Hosting.Azure.Tests.csproj (Aspire.Hosting.Azure.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 System.Text; using System.Text.Json.Nodes; using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Aspire.Hosting.Tests.Utils; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace Aspire.Hosting.Utils; public sealed class AzureManifestUtils { public static Task<(JsonNode ManifestNode, string BicepText)> GetManifestWithBicep(IResource resource, bool skipPreparer = false) => GetManifestWithBicep(new DistributedApplicationModel([resource]), resource, skipPreparer); public static Task<(JsonNode ManifestNode, string BicepText)> GetManifestWithBicep(DistributedApplicationModel appModel, IResource resource) => GetManifestWithBicep(appModel, resource, skipPreparer: false); private static async Task<(JsonNode ManifestNode, string BicepText)> GetManifestWithBicep(DistributedApplicationModel appModel, IResource resource, bool skipPreparer) { if (!skipPreparer) { var executionContext = new DistributedApplicationExecutionContext(DistributedApplicationOperation.Publish); var azurePreparer = new AzureResourcePreparer(Options.Create(new AzureProvisioningOptions()), executionContext); await azurePreparer.OnBeforeStartAsync(new BeforeStartEvent(new TestServiceProvider(), appModel), cancellationToken: default); } string manifestDir = Directory.CreateTempSubdirectory(resource.Name).FullName; var manifestNode = await ManifestUtils.GetManifest(resource, manifestDir); if (!manifestNode.AsObject().TryGetPropertyValue("path", out var pathNode)) { throw new ArgumentException("Specified resource does not contain a path property.", nameof(resource)); } if (pathNode?.ToString() is not { } path || !File.Exists(Path.Combine(manifestDir, path))) { throw new ArgumentException("Path node in resource is null, empty, or does not exist.", nameof(resource)); } var bicepText = await File.ReadAllTextAsync(Path.Combine(manifestDir, path)); return (manifestNode, bicepText); } public static async Task VerifyAllAzureBicep(IDistributedApplicationBuilder builder) { await using var app = builder.Build(); var model = app.Services.GetRequiredService<DistributedApplicationModel>(); await ExecuteBeforeStartHooksAsync(app, default); // Collect bicep for all Azure provisioning resources, ordered by name for deterministic output var azureResources = model.Resources .OfType<AzureProvisioningResource>() .OrderBy(r => r.Name) .ToList(); var sb = new StringBuilder(); foreach (var resource in azureResources) { var (_, bicep) = await GetManifestWithBicep(resource, skipPreparer: true); sb.AppendLine($"// Resource: {resource.Name}"); sb.AppendLine(bicep); sb.AppendLine(); } await Verify(sb.ToString(), extension: "bicep") .ScrubLinesWithReplace(s => s.Replace("\\r\\n", "\\n")); } [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "ExecuteBeforeStartHooksAsync")] public static extern Task ExecuteBeforeStartHooksAsync(DistributedApplication app, CancellationToken cancellationToken); }