|
// 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.Tests.Utils;
using Aspire.Hosting.Utils;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Aspire.Hosting.Dapr.Tests;
public class DaprTests
{
[Fact]
public async Task WithDaprSideCarAddsAnnotationAndSidecarResource()
{
using var builder = TestDistributedApplicationBuilder.Create();
builder.AddDapr(o =>
{
// Fake path to avoid throwing
o.DaprPath = "dapr";
});
builder.AddContainer("name", "image")
.WithEndpoint("http", e =>
{
e.Port = 8000;
e.AllocatedEndpoint = new(e, "localhost", 80);
})
.WithDaprSidecar();
using var app = builder.Build();
await ExecuteBeforeStartHooksAsync(app, default);
var model = app.Services.GetRequiredService<DistributedApplicationModel>();
Assert.Equal(3, model.Resources.Count);
var container = Assert.Single(model.Resources.OfType<ContainerResource>());
var sidecarResource = Assert.Single(model.Resources.OfType<IDaprSidecarResource>());
var sideCarCli = Assert.Single(model.Resources.OfType<ExecutableResource>());
Assert.True(sideCarCli.TryGetEndpoints(out var endpoints));
var ports = new Dictionary<string, int>
{
["http"] = 3500,
["grpc"] = 50001,
["metrics"] = 9090
};
foreach (var e in endpoints)
{
e.AllocatedEndpoint = new(e, "localhost", ports[e.Name], targetPortExpression: $$$"""{{- portForServing "{{{e.Name}}}" -}}""");
}
var config = await EnvironmentVariableEvaluator.GetEnvironmentVariablesAsync(container, DistributedApplicationOperation.Run, TestServiceProvider.Instance);
var sidecarArgs = await ArgumentEvaluator.GetArgumentListAsync(sideCarCli);
Assert.Equal("3500", config["DAPR_HTTP_PORT"]);
Assert.Equal("50001", config["DAPR_GRPC_PORT"]);
Assert.Equal("http://host.docker.internal:3500", config["DAPR_HTTP_ENDPOINT"]);
Assert.Equal("http://host.docker.internal:50001", config["DAPR_GRPC_ENDPOINT"]);
var expectedArgs = new[]
{
"run",
"--app-id",
"name",
"--app-port",
"80",
"--dapr-grpc-port",
"{{- portForServing \"grpc\" -}}",
"--dapr-http-port",
"{{- portForServing \"http\" -}}",
"--metrics-port",
"{{- portForServing \"metrics\" -}}",
"--app-channel-address",
"localhost",
"--app-protocol",
"http"
};
Assert.Equal(expectedArgs, sidecarArgs);
Assert.NotNull(container.Annotations.OfType<DaprSidecarAnnotation>());
}
[Theory]
[InlineData("https", "https", 555, "https", "localhost", 555)]
[InlineData(null, null, null, "http", "localhost", 8000)]
[InlineData("https", null, null, "https", "localhost", 8001)]
[InlineData(null, "https", null, "https", "localhost", 8001)]
[InlineData(null, null, 555, "http", "localhost", 555)]
[InlineData("https", "http", null, "https", "localhost", 8000)]
public async Task WithDaprSideCarAddsAnnotationBasedOnTheSidecarAppOptions(string? schema, string? endPoint, int? port, string expectedSchema, string expectedChannelAddress, int expectedPort)
{
using var builder = TestDistributedApplicationBuilder.Create();
builder.AddDapr(o =>
{
// Fake path to avoid throwing
o.DaprPath = "dapr";
});
var containerResource = builder.AddContainer("name", "image")
.WithEndpoint("http", e =>
{
e.Port = 8000;
e.UriScheme = "http";
e.AllocatedEndpoint = new(e, "localhost", 8000);
})
.WithEndpoint("https", e =>
{
e.Port = 8001;
e.UriScheme = "https";
e.AllocatedEndpoint = new(e, "localhost", 8001);
});
if (schema is null && endPoint is null && port is null)
{
containerResource.WithDaprSidecar();
}
else
{
containerResource.WithDaprSidecar(new DaprSidecarOptions()
{
AppProtocol = schema,
AppEndpoint = endPoint,
AppPort = port
});
}
using var app = builder.Build();
await ExecuteBeforeStartHooksAsync(app, default);
var model = app.Services.GetRequiredService<DistributedApplicationModel>();
Assert.Equal(3, model.Resources.Count);
var container = Assert.Single(model.Resources.OfType<ContainerResource>());
var sidecarResource = Assert.Single(model.Resources.OfType<IDaprSidecarResource>());
var sideCarCli = Assert.Single(model.Resources.OfType<ExecutableResource>());
Assert.True(sideCarCli.TryGetEndpoints(out var endpoints));
var ports = new Dictionary<string, int>
{
["http"] = 3500,
["grpc"] = 50001,
["metrics"] = 9090
};
foreach (var e in endpoints)
{
e.AllocatedEndpoint = new(e, "localhost", ports[e.Name], targetPortExpression: $$$"""{{- portForServing "{{{e.Name}}}" -}}""");
}
var config = await EnvironmentVariableEvaluator.GetEnvironmentVariablesAsync(container, DistributedApplicationOperation.Run, TestServiceProvider.Instance);
var sidecarArgs = await ArgumentEvaluator.GetArgumentListAsync(sideCarCli);
Assert.Equal("http://host.docker.internal:3500", config["DAPR_HTTP_ENDPOINT"]);
Assert.Equal("http://host.docker.internal:50001", config["DAPR_GRPC_ENDPOINT"]);
// because the order of the parameters is changing, we are just checking if the important ones here.
var commandline = string.Join(" ", sidecarArgs);
Assert.Contains($"--app-port {expectedPort}", commandline);
Assert.Contains($"--app-channel-address {expectedChannelAddress}", commandline);
Assert.Contains($"--app-protocol {expectedSchema}", commandline);
Assert.NotNull(container.Annotations.OfType<DaprSidecarAnnotation>());
}
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "ExecuteBeforeStartHooksAsync")]
private static extern Task ExecuteBeforeStartHooksAsync(DistributedApplication app, CancellationToken cancellationToken);
}
|