| File: AzureKubernetesIngressTests.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Azure.Kubernetes.Tests\Aspire.Hosting.Azure.Kubernetes.Tests.csproj (Aspire.Hosting.Azure.Kubernetes.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma warning disable ASPIREAZURE003 using Aspire.Hosting.Kubernetes; using Aspire.Hosting.Utils; namespace Aspire.Hosting.Azure.Tests; public class AzureKubernetesIngressTests(ITestOutputHelper outputHelper) { [Fact] public async Task AksAddIngress_WithPath_GeneratesIngressInHelmOutput() { using var workspace = TemporaryWorkspace.Create(outputHelper); var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, workspace.Path); var aks = builder.AddAzureKubernetesEnvironment("aks"); var ingress = aks.AddIngress("public") .WithIngressClass("nginx"); var api = builder.AddContainer("myapi", "nginx") .WithHttpEndpoint(targetPort: 8080) .WithExternalHttpEndpoints(); ingress.WithPath("/", api.GetEndpoint("http")); var app = builder.Build(); app.Run(); // With AKS, the Helm output goes to the inner K8S env subdirectory var ingressPath = Path.Combine(workspace.Path, "templates", "public", "public.yaml"); Assert.True(File.Exists(ingressPath), $"Expected ingress YAML at {ingressPath}"); var content = await File.ReadAllTextAsync(ingressPath); Assert.Contains("Ingress", content); Assert.Contains("nginx", content); } [Fact] public void AksAddIngress_HasCorrectParent() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var aks = builder.AddAzureKubernetesEnvironment("aks"); var ingress = aks.AddIngress("public"); // The ingress should be a child of the inner K8S environment, not the AKS environment Assert.IsType<KubernetesIngressResource>(ingress.Resource); Assert.IsType<KubernetesEnvironmentResource>(ingress.Resource.Parent); } [Fact] public void AksAddGateway_HasCorrectParent() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var aks = builder.AddAzureKubernetesEnvironment("aks"); var gateway = aks.AddGateway("public"); Assert.IsType<KubernetesGatewayResource>(gateway.Resource); Assert.IsType<KubernetesEnvironmentResource>(gateway.Resource.Parent); } [Fact] public async Task WithLoadBalancer_OnGateway_AnnotatesAndDefaultsClass() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var vnet = builder.AddAzureVirtualNetwork("vnet", "10.0.0.0/16"); var albSubnet = vnet.AddSubnet("alb", "10.0.4.0/24"); var aks = builder.AddAzureKubernetesEnvironment("aks"); var lb = aks.AddLoadBalancer("lb1", albSubnet); var gateway = aks.AddGateway("public").WithLoadBalancer(lb); Assert.NotNull(gateway.Resource.GatewayClassName); var resolvedClass = await gateway.Resource.GatewayClassName!.GetValueAsync(default); Assert.Equal("azure-alb-external", resolvedClass); Assert.True(gateway.Resource.GatewayAnnotations.TryGetValue("alb.networking.azure.io/alb-name", out var albNameRef)); Assert.Equal("alb-lb1", await albNameRef!.GetValueAsync(default)); Assert.True(gateway.Resource.GatewayAnnotations.TryGetValue("alb.networking.azure.io/alb-namespace", out var albNsRef)); Assert.Equal("default", await albNsRef!.GetValueAsync(default)); } [Fact] public async Task WithLoadBalancer_OnIngress_AnnotatesAndDefaultsClass() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var vnet = builder.AddAzureVirtualNetwork("vnet", "10.0.0.0/16"); var albSubnet = vnet.AddSubnet("alb", "10.0.4.0/24"); var aks = builder.AddAzureKubernetesEnvironment("aks"); var lb = aks.AddLoadBalancer("lb1", albSubnet); var ingress = aks.AddIngress("public").WithLoadBalancer(lb); Assert.NotNull(ingress.Resource.IngressClassName); var resolvedClass = await ingress.Resource.IngressClassName!.GetValueAsync(default); Assert.Equal("azure-alb-external", resolvedClass); Assert.True(ingress.Resource.IngressAnnotations.TryGetValue("alb.networking.azure.io/alb-name", out var albNameRef)); Assert.Equal("alb-lb1", await albNameRef!.GetValueAsync(default)); Assert.True(ingress.Resource.IngressAnnotations.TryGetValue("alb.networking.azure.io/alb-namespace", out var albNsRef)); Assert.Equal("default", await albNsRef!.GetValueAsync(default)); } [Fact] public async Task WithLoadBalancer_RespectsExplicitGatewayClass() { var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); var vnet = builder.AddAzureVirtualNetwork("vnet", "10.0.0.0/16"); var albSubnet = vnet.AddSubnet("alb", "10.0.4.0/24"); var aks = builder.AddAzureKubernetesEnvironment("aks"); var lb = aks.AddLoadBalancer("lb1", albSubnet); // Explicit class set BEFORE WithLoadBalancer is preserved; AGC annotations // are still applied so AGC can still discover the LB. var gateway = aks.AddGateway("public") .WithGatewayClass("custom-class") .WithLoadBalancer(lb); Assert.NotNull(gateway.Resource.GatewayClassName); var resolvedClass = await gateway.Resource.GatewayClassName!.GetValueAsync(default); Assert.Equal("custom-class", resolvedClass); Assert.True(gateway.Resource.GatewayAnnotations.ContainsKey("alb.networking.azure.io/alb-name")); Assert.True(gateway.Resource.GatewayAnnotations.ContainsKey("alb.networking.azure.io/alb-namespace")); } [Fact] public void AksAddIngress_WithPath_NonExternalEndpoint_ThrowsOnPublish() { using var workspace = TemporaryWorkspace.Create(outputHelper); var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, workspace.Path); var aks = builder.AddAzureKubernetesEnvironment("aks"); var ingress = aks.AddIngress("public").WithIngressClass("nginx"); var api = builder.AddContainer("myapi", "nginx") .WithHttpEndpoint(targetPort: 8080); ingress.WithPath("/", api.GetEndpoint("http")); var app = builder.Build(); var aggregate = Assert.Throws<AggregateException>(app.Run); var ex = aggregate.Flatten().InnerExceptions.OfType<InvalidOperationException>().First(e => e.Message.Contains("WithExternalHttpEndpoints")); Assert.Contains("myapi", ex.Message); Assert.Contains("WithExternalHttpEndpoints", ex.Message); } [Fact] public void AksAddGateway_WithRoute_NonExternalEndpoint_ThrowsOnPublish() { using var workspace = TemporaryWorkspace.Create(outputHelper); var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish, workspace.Path); var aks = builder.AddAzureKubernetesEnvironment("aks"); var gateway = aks.AddGateway("public").WithGatewayClass("nginx"); var api = builder.AddContainer("myapi", "nginx") .WithHttpEndpoint(targetPort: 8080); gateway.WithRoute("/", api.GetEndpoint("http")); var app = builder.Build(); var aggregate = Assert.Throws<AggregateException>(app.Run); var ex = aggregate.Flatten().InnerExceptions.OfType<InvalidOperationException>().First(e => e.Message.Contains("WithExternalHttpEndpoints")); Assert.Contains("myapi", ex.Message); Assert.Contains("WithExternalHttpEndpoints", ex.Message); } }