|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Utils;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Sockets;
using Xunit;
namespace Aspire.Hosting.RabbitMQ.Tests;
public class AddRabbitMQTests
{
[Fact]
public void AddRabbitMQAddsGeneratedPasswordParameterWithUserSecretsParameterDefaultInRunMode()
{
using var appBuilder = TestDistributedApplicationBuilder.Create();
var rmq = appBuilder.AddRabbitMQ("rmq");
Assert.Equal("Aspire.Hosting.ApplicationModel.UserSecretsParameterDefault", rmq.Resource.PasswordParameter.Default?.GetType().FullName);
}
[Fact]
public void AddRabbitMQDoesNotAddGeneratedPasswordParameterWithUserSecretsParameterDefaultInPublishMode()
{
using var appBuilder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);
var rmq = appBuilder.AddRabbitMQ("rmq");
Assert.NotEqual("Aspire.Hosting.ApplicationModel.UserSecretsParameterDefault", rmq.Resource.PasswordParameter.Default?.GetType().FullName);
}
[Theory]
[InlineData(false, null)]
[InlineData(true, null)]
[InlineData(true, 15672)]
public void AddRabbitMQContainerWithDefaultsAddsAnnotationMetadata(bool withManagementPlugin, int? withManagementPluginPort)
{
var appBuilder = TestDistributedApplicationBuilder.Create();
var rabbitmq = appBuilder.AddRabbitMQ("rabbit");
if (withManagementPlugin)
{
rabbitmq.WithManagementPlugin(withManagementPluginPort);
}
using var app = appBuilder.Build();
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
var containerResource = Assert.Single(appModel.Resources.OfType<RabbitMQServerResource>());
Assert.Equal("rabbit", containerResource.Name);
var primaryEndpoint = Assert.Single(containerResource.Annotations.OfType<EndpointAnnotation>().Where(e => e.Name == "tcp"));
Assert.Equal(5672, primaryEndpoint.TargetPort);
Assert.False(primaryEndpoint.IsExternal);
Assert.Equal("tcp", primaryEndpoint.Name);
Assert.Null(primaryEndpoint.Port);
Assert.Equal(ProtocolType.Tcp, primaryEndpoint.Protocol);
Assert.Equal("tcp", primaryEndpoint.Transport);
Assert.Equal("tcp", primaryEndpoint.UriScheme);
if (withManagementPlugin)
{
var mangementEndpoint = Assert.Single(containerResource.Annotations.OfType<EndpointAnnotation>().Where(e => e.Name == "management"));
Assert.Equal(15672, mangementEndpoint.TargetPort);
Assert.False(primaryEndpoint.IsExternal);
Assert.Equal("management", mangementEndpoint.Name);
Assert.Equal(ProtocolType.Tcp, mangementEndpoint.Protocol);
Assert.Equal("http", mangementEndpoint.Transport);
Assert.Equal("http", mangementEndpoint.UriScheme);
if (!withManagementPluginPort.HasValue)
{
Assert.Null(mangementEndpoint.Port);
}
else
{
Assert.Equal(withManagementPluginPort.Value, mangementEndpoint.Port);
}
}
var containerAnnotation = Assert.Single(containerResource.Annotations.OfType<ContainerImageAnnotation>());
Assert.Equal(RabbitMQContainerImageTags.Image, containerAnnotation.Image);
Assert.Equal(withManagementPlugin ? RabbitMQContainerImageTags.ManagementTag : RabbitMQContainerImageTags.Tag, containerAnnotation.Tag);
Assert.Equal(RabbitMQContainerImageTags.Registry, containerAnnotation.Registry);
}
[Fact]
public async Task RabbitMQCreatesConnectionString()
{
var appBuilder = DistributedApplication.CreateBuilder();
appBuilder.Configuration["Parameters:pass"] = "p@ssw0rd1";
var pass = appBuilder.AddParameter("pass");
appBuilder
.AddRabbitMQ("rabbit", password: pass)
.WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 27011));
using var app = appBuilder.Build();
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
var rabbitMqResource = Assert.Single(appModel.Resources.OfType<RabbitMQServerResource>());
var connectionStringResource = rabbitMqResource as IResourceWithConnectionString;
var connectionString = await connectionStringResource.GetConnectionStringAsync(default);
Assert.Equal("amqp://guest:p@ssw0rd1@localhost:27011", connectionString);
Assert.Equal("amqp://guest:{pass.value}@{rabbit.bindings.tcp.host}:{rabbit.bindings.tcp.port}", connectionStringResource.ConnectionStringExpression.ValueExpression);
}
[Theory]
[InlineData(null, RabbitMQContainerImageTags.ManagementTag)]
[InlineData("3", "3-management")]
[InlineData("3.12", "3.12-management")]
[InlineData("3.12.0", "3.12.0-management")]
[InlineData("3-alpine", "3-management-alpine")]
[InlineData("3.12-alpine", "3.12-management-alpine")]
[InlineData("3.12.0-alpine", "3.12.0-management-alpine")]
[InlineData("999", "999-management")]
[InlineData("12345", "12345-management")]
[InlineData("12345.00.12", "12345.00.12-management")]
public void WithManagementPluginUpdatesContainerImageTagToEnableManagementPlugin(string? imageTag, string expectedTag)
{
var appBuilder = TestDistributedApplicationBuilder.Create();
var rabbitmq = appBuilder.AddRabbitMQ("rabbit");
if (imageTag is not null)
{
rabbitmq.WithImageTag(imageTag);
}
rabbitmq.WithManagementPlugin();
using var app = appBuilder.Build();
var appModel = app.Services.GetRequiredService<DistributedApplicationModel>();
var containerResource = Assert.Single(appModel.Resources.OfType<RabbitMQServerResource>());
var containerAnnotation = Assert.Single(containerResource.Annotations.OfType<ContainerImageAnnotation>());
Assert.Equal(expectedTag, containerAnnotation.Tag);
}
[Theory]
[InlineData(" ")]
[InlineData("test")]
[InlineData(".123")]
[InlineData(".")]
[InlineData(".1.2")]
[InlineData("1.2.")]
[InlineData("1.٩.3")]
[InlineData("1.2..3")]
[InlineData("not-supported")]
public void WithManagementPluginThrowsForUnsupportedContainerImageTag(string imageTag)
{
using var appBuilder = TestDistributedApplicationBuilder.Create();
var rabbitmq = appBuilder.AddRabbitMQ("rabbit");
rabbitmq.WithImageTag(imageTag);
Assert.Throws<DistributedApplicationException>(rabbitmq.WithManagementPlugin);
}
[Theory]
[InlineData(" ")]
[InlineData("notrabbitmq")]
[InlineData("not-supported")]
public void WithManagementPluginThrowsForUnsupportedContainerImageName(string imageName)
{
using var appBuilder = TestDistributedApplicationBuilder.Create();
var rabbitmq = appBuilder.AddRabbitMQ("rabbit");
rabbitmq.WithImage(imageName);
Assert.Throws<DistributedApplicationException>(rabbitmq.WithManagementPlugin);
}
[Theory]
[InlineData(" ")]
[InlineData("custom.url")]
[InlineData("not.the.default")]
public void WithManagementPluginThrowsForUnsupportedContainerImageRegistry(string registry)
{
using var appBuilder = TestDistributedApplicationBuilder.Create();
var rabbitmq = appBuilder.AddRabbitMQ("rabbit");
rabbitmq.WithImageRegistry(registry);
Assert.Throws<DistributedApplicationException>(rabbitmq.WithManagementPlugin);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task VerifyManifest(bool withManagementPlugin)
{
using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);
var rabbit = builder.AddRabbitMQ("rabbit");
if (withManagementPlugin)
{
rabbit.WithManagementPlugin();
}
var manifest = await ManifestUtils.GetManifest(rabbit.Resource);
var expectedTag = withManagementPlugin ? RabbitMQContainerImageTags.ManagementTag : RabbitMQContainerImageTags.Tag;
var managementBinding = withManagementPlugin
? """
,
"management": {
"scheme": "http",
"protocol": "tcp",
"transport": "http",
"targetPort": 15672
}
"""
: "";
var expectedManifest = $$"""
{
"type": "container.v0",
"connectionString": "amqp://guest:{rabbit-password.value}@{rabbit.bindings.tcp.host}:{rabbit.bindings.tcp.port}",
"image": "{{RabbitMQContainerImageTags.Registry}}/{{RabbitMQContainerImageTags.Image}}:{{expectedTag}}",
"env": {
"RABBITMQ_DEFAULT_USER": "guest",
"RABBITMQ_DEFAULT_PASS": "{rabbit-password.value}"
},
"bindings": {
"tcp": {
"scheme": "tcp",
"protocol": "tcp",
"transport": "tcp",
"targetPort": 5672
}{{managementBinding}}
}
}
""";
Assert.Equal(expectedManifest, manifest.ToString());
}
[Fact]
public async Task VerifyManifestWithParameters()
{
using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);
var userNameParameter = builder.AddParameter("user");
var passwordParameter = builder.AddParameter("pass");
var rabbit = builder.AddRabbitMQ("rabbit", userNameParameter, passwordParameter);
var manifest = await ManifestUtils.GetManifest(rabbit.Resource);
var expectedManifest = $$"""
{
"type": "container.v0",
"connectionString": "amqp://{user.value}:{pass.value}@{rabbit.bindings.tcp.host}:{rabbit.bindings.tcp.port}",
"image": "{{RabbitMQContainerImageTags.Registry}}/{{RabbitMQContainerImageTags.Image}}:{{RabbitMQContainerImageTags.Tag}}",
"env": {
"RABBITMQ_DEFAULT_USER": "{user.value}",
"RABBITMQ_DEFAULT_PASS": "{pass.value}"
},
"bindings": {
"tcp": {
"scheme": "tcp",
"protocol": "tcp",
"transport": "tcp",
"targetPort": 5672
}
}
}
""";
Assert.Equal(expectedManifest, manifest.ToString());
rabbit = builder.AddRabbitMQ("rabbit2", userNameParameter);
manifest = await ManifestUtils.GetManifest(rabbit.Resource);
expectedManifest = $$"""
{
"type": "container.v0",
"connectionString": "amqp://{user.value}:{rabbit2-password.value}@{rabbit2.bindings.tcp.host}:{rabbit2.bindings.tcp.port}",
"image": "{{RabbitMQContainerImageTags.Registry}}/{{RabbitMQContainerImageTags.Image}}:{{RabbitMQContainerImageTags.Tag}}",
"env": {
"RABBITMQ_DEFAULT_USER": "{user.value}",
"RABBITMQ_DEFAULT_PASS": "{rabbit2-password.value}"
},
"bindings": {
"tcp": {
"scheme": "tcp",
"protocol": "tcp",
"transport": "tcp",
"targetPort": 5672
}
}
}
""";
Assert.Equal(expectedManifest, manifest.ToString());
rabbit = builder.AddRabbitMQ("rabbit3", password: passwordParameter);
manifest = await ManifestUtils.GetManifest(rabbit.Resource);
expectedManifest = $$"""
{
"type": "container.v0",
"connectionString": "amqp://guest:{pass.value}@{rabbit3.bindings.tcp.host}:{rabbit3.bindings.tcp.port}",
"image": "{{RabbitMQContainerImageTags.Registry}}/{{RabbitMQContainerImageTags.Image}}:{{RabbitMQContainerImageTags.Tag}}",
"env": {
"RABBITMQ_DEFAULT_USER": "guest",
"RABBITMQ_DEFAULT_PASS": "{pass.value}"
},
"bindings": {
"tcp": {
"scheme": "tcp",
"protocol": "tcp",
"transport": "tcp",
"targetPort": 5672
}
}
}
""";
Assert.Equal(expectedManifest, manifest.ToString());
}
}
|