Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/BuslyCLI.Console/BuslyCLI.Console.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentValidation" Version="12.1.1" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="12.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.0" />
<PackageReference Include="NServiceBus" Version="9.2.7" />
Expand Down
2 changes: 1 addition & 1 deletion src/BuslyCLI.Console/Commands/Command/SendCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SendCommand(IRawEndpointFactory rawEndpointFactory, INServiceBusCon
{
public override async Task<int> ExecuteAsync(CommandContext context, SendCommandSettings settings, CancellationToken cancellationToken)
{
var config = await nServiceBusConfiguration.GetConfigurationAsync(settings.Config.Path);
var config = await nServiceBusConfiguration.GetValidatedConfigurationAsync(settings.Config.Path);
var rawEndpoint = await rawEndpointFactory.CreateRawSendOnlyEndpoint(Constants.DefaultOriginatingEndpoint, config.CurrentTransportConfig);
// TODO: Validate body is valid json/xml
var headers = new Dictionary<string, string>
Expand Down
2 changes: 1 addition & 1 deletion src/BuslyCLI.Console/Commands/Demo/StartCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class StartDemoCommand(IAnsiConsole console, IRawEndpointFactory rawEndpo
public override async Task<int> ExecuteAsync(CommandContext context, CurrentTransportSettings settings, CancellationToken cancellationToken)
{
console.WriteLine("Starting demo endpoint for quick start guide...");
var config = await nServiceBusConfiguration.GetConfigurationAsync(settings.Config.Path);
var config = await nServiceBusConfiguration.GetValidatedConfigurationAsync(settings.Config.Path);
var rawEndpoint = await rawEndpointFactory.CreateRawEndpoint(Constants.DemoDefaultOriginatingEndpoint, config.CurrentTransportConfig);

await rawEndpoint.StartEndpoint();
Expand Down
2 changes: 1 addition & 1 deletion src/BuslyCLI.Console/Commands/Event/PublishCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class PublishCommand(IRawEndpointFactory rawEndpointFactory, INServiceBus
{
public override async Task<int> ExecuteAsync(CommandContext context, PublishCommandSettings settings, CancellationToken cancellationToken)
{
var config = await nServiceBusConfiguration.GetConfigurationAsync(settings.Config.Path);
var config = await nServiceBusConfiguration.GetValidatedConfigurationAsync(settings.Config.Path);
var rawEndpoint = await rawEndpointFactory.CreateRawSendOnlyEndpoint(Constants.DefaultOriginatingEndpoint, config.CurrentTransportConfig);
// TODO: Validate body is valid json/xml
var headers = new Dictionary<string, string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class CurrentTransportCommand(IAnsiConsole console, INServiceBusConfigura
{
public override async Task<int> ExecuteAsync(CommandContext context, CurrentTransportSettings settings, CancellationToken cancellationToken)
{
var nsbConfiguration = await nservicebusConfiguration.GetConfigurationAsync(settings.Config.Path);
var nsbConfiguration = await nservicebusConfiguration.GetUnValidatedConfigurationAsync(settings.Config.Path);

console.WriteLine(nsbConfiguration != null && nsbConfiguration.CurrentTransport is not null ? nsbConfiguration.CurrentTransport : "Current transport is not set.");
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class DeleteTransportCommand(IAnsiConsole console, INServiceBusConfigurat
{
public override async Task<int> ExecuteAsync(CommandContext context, DeleteTransportSettings settings, CancellationToken cancellationToken)
{
var nsbConfiguration = await nservicebusConfiguration.GetConfigurationAsync(settings.Config.Path);
var nsbConfiguration = await nservicebusConfiguration.GetValidatedConfigurationAsync(settings.Config.Path);
var targetTransport = settings.TransportName.ToLower();
if (nsbConfiguration.Transports.Select(x => x.Name.ToLower()).Contains(targetTransport))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ public override async Task<int> ExecuteAsync(CommandContext context, ListTranspo
// Add header row
grid.AddRow("CURRENT", "NAME", "TRANSPORT-TYPE");

var nsbConfiguration = await nservicebusConfiguration.GetConfigurationAsync(settings.Config.Path);
var nsbConfiguration = await nservicebusConfiguration.GetUnValidatedConfigurationAsync(settings.Config.Path);

if (nsbConfiguration != null)
if (nsbConfiguration is { Transports: not null })
{
foreach (var transport in nsbConfiguration.Transports)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class SetTransportCommand(IAnsiConsole console, INServiceBusConfiguration
{
public override async Task<int> ExecuteAsync(CommandContext context, SetTransportSettings settings, CancellationToken cancellationToken)
{
var nsbConfiguration = await nservicebusConfiguration.GetConfigurationAsync(settings.Config.Path);
var nsbConfiguration = await nservicebusConfiguration.GetValidatedConfigurationAsync(settings.Config.Path);
var targetTransport = settings.TransportName.ToLower();
if (nsbConfiguration.Transports.Select(x => x.Name.ToLower()).Contains(targetTransport))
{
Expand Down
37 changes: 27 additions & 10 deletions src/BuslyCLI.Console/Config/INServiceBusConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,45 @@
using YamlDotNet.Serialization;
using FluentValidation;
using YamlDotNet.Serialization;

namespace BuslyCLI.Config;

public interface INServiceBusConfiguration
{
Task<NServiceBusConfig> GetConfigurationAsync(string path);
Task<NServiceBusConfig> GetValidatedConfigurationAsync(string path);

Task<NServiceBusConfig> GetUnValidatedConfigurationAsync(string path);

Task PersistConfiguration(string path, NServiceBusConfig config);
}

public class NServiceBusConfiguration(IDeserializer yamlDeserializer, ISerializer yamlSerializer) : INServiceBusConfiguration
public class NServiceBusConfiguration(IDeserializer yamlDeserializer, ISerializer yamlSerializer, IValidator<NServiceBusConfig> validator) : INServiceBusConfiguration
{

public async Task<NServiceBusConfig> GetConfigurationAsync(string path)

private async Task<NServiceBusConfig> LoadConfigurationAsync(
string path,
bool validate)
{
if (File.Exists(path))
{
var yaml = await File.ReadAllTextAsync(path);
return yamlDeserializer.Deserialize<NServiceBusConfig>(yaml);
}
if (!File.Exists(path)) return null;

var yaml = await File.ReadAllTextAsync(path);
var config = yamlDeserializer.Deserialize<NServiceBusConfig>(yaml);

// config is null if yaml file is empty
if (config is null) return null;

return null;
if (validate)
await validator.ValidateAsync(config, opts => opts.ThrowOnFailures());

return config;
}

public async Task<NServiceBusConfig> GetValidatedConfigurationAsync(string path)
=> await LoadConfigurationAsync(path, validate: true);

public async Task<NServiceBusConfig> GetUnValidatedConfigurationAsync(string path)
=> await LoadConfigurationAsync(path, validate: false);

public async Task PersistConfiguration(string path, NServiceBusConfig config)
{
var yaml = yamlSerializer.Serialize(config);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using FluentValidation;

namespace BuslyCLI.Config.Validators;

public class LearningTransportConfigValidator : AbstractValidator<LearningTransportConfig>
{
public LearningTransportConfigValidator()
{
RuleFor(x => x.StorageDirectory)
.NotEmpty();
}
}
22 changes: 22 additions & 0 deletions src/BuslyCLI.Console/Config/Validators/RootConfigValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using FluentValidation;

namespace BuslyCLI.Config.Validators;

public class RootConfigValidator : AbstractValidator<NServiceBusConfig>
{
public RootConfigValidator()
{
RuleFor(x => x.CurrentTransport).NotEmpty();

RuleFor(x => x.Transports)
.NotEmpty()
.ForEach(x => x.SetValidator(new TransportConfigValidator()));

RuleFor(x => x.CurrentTransport)
.Must((model, currentTransport) =>
model.Transports.Any(t => t.Name == currentTransport))
.WithMessage("current-transport must match one of the defined transports.")
.When(x => x.Transports != null);

}
}
19 changes: 19 additions & 0 deletions src/BuslyCLI.Console/Config/Validators/TransportConfigValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using FluentValidation;

namespace BuslyCLI.Config.Validators;

public class TransportConfigValidator : AbstractValidator<TransportConfig>
{
public TransportConfigValidator()
{
RuleFor(x => x.Name).NotEmpty();

RuleFor(x => x.Config)
.NotEmpty()
.WithMessage("Transport must define exactly one transport configuration.");

RuleFor(x => x.LearningTransportConfig)
.SetValidator(new LearningTransportConfigValidator())
.When(x => x.Config is not null);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using BuslyCLI.Config;
using BuslyCLI.Config.Validators;
using BuslyCLI.Factories;
using FluentValidation;
using Microsoft.Extensions.DependencyInjection;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
Expand All @@ -11,11 +13,15 @@ public static class ServiceCollectionExtensions
public static IServiceCollection AddBuslyCLIServices(this IServiceCollection services)
{
services.AddScoped<IRawEndpointFactory, RawEndpointFactory>();
services.AddSingleton<INServiceBusConfiguration, NServiceBusConfiguration>();
services.AddValidatorsFromAssemblyContaining<RootConfigValidator>();
services.AddYamlDeserializer();
services.AddYamlSerializer();

return services;
}

public static IServiceCollection AddYamlDeserializer(this IServiceCollection services)
private static IServiceCollection AddYamlDeserializer(this IServiceCollection services)
{
services.AddSingleton(
new DeserializerBuilder()
Expand All @@ -36,7 +42,7 @@ public static IServiceCollection AddYamlDeserializer(this IServiceCollection ser
return services;
}

public static IServiceCollection AddYamlSerializer(this IServiceCollection services)
private static IServiceCollection AddYamlSerializer(this IServiceCollection services)
{
services.AddSingleton(
new SerializerBuilder()
Expand Down
4 changes: 0 additions & 4 deletions src/BuslyCLI.Console/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Diagnostics;
using BuslyCLI.Config;
using BuslyCLI.DependencyInjection;
using BuslyCLI.Spectre;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -14,9 +13,6 @@

var registrations = new ServiceCollection();
registrations.AddBuslyCLIServices();
registrations.AddYamlDeserializer();
registrations.AddYamlSerializer();
registrations.AddSingleton<INServiceBusConfiguration, NServiceBusConfiguration>();
using var registrar = new DependencyInjectionRegistrar(registrations);
var app = new CommandApp(registrar);
app.Configure(AppConfiguration.GetSpectreCommandConfiguration());
Expand Down
2 changes: 2 additions & 0 deletions tests/BuslyCLI.Console.Tests/BuslyCLI.Console.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Bogus" Version="35.6.5" />
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentValidation" Version="12.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="NServiceBus.AmazonSQS" Version="8.0.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BuslyCLI.Config;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.DependencyInjection;
using BuslyCLI.Spectre;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -18,9 +17,6 @@ public void Setup()
{
var registrations = new ServiceCollection();
registrations.AddBuslyCLIServices();
registrations.AddYamlDeserializer();
registrations.AddYamlSerializer();
registrations.AddSingleton<INServiceBusConfiguration, NServiceBusConfiguration>();
using var registrar = new DependencyInjectionRegistrar(registrations);
_sut = new CommandAppTester(registrar);
_sut.Configure(AppConfiguration.GetSpectreCommandConfiguration());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BuslyCLI.Config;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.DependencyInjection;
using BuslyCLI.Spectre;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -18,9 +17,6 @@ public void Setup()
{
var registrations = new ServiceCollection();
registrations.AddBuslyCLIServices();
registrations.AddYamlDeserializer();
registrations.AddYamlSerializer();
registrations.AddSingleton<INServiceBusConfiguration, NServiceBusConfiguration>();
using var registrar = new DependencyInjectionRegistrar(registrations);
_sut = new CommandAppTester(registrar);
_sut.Configure(AppConfiguration.GetSpectreCommandConfiguration());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BuslyCLI.Config;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.DependencyInjection;
using BuslyCLI.Spectre;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -18,26 +17,39 @@ public void Setup()
{
var registrations = new ServiceCollection();
registrations.AddBuslyCLIServices();
registrations.AddYamlDeserializer();
registrations.AddYamlSerializer();
registrations.AddSingleton<INServiceBusConfiguration, NServiceBusConfiguration>();
using var registrar = new DependencyInjectionRegistrar(registrations);
_sut = new CommandAppTester(registrar);
_sut.Configure(AppConfiguration.GetSpectreCommandConfiguration());
}

[Test]
public void ShouldOutputAnEmptyGrid()
public void ShouldOutputAnEmptyGridWhenConfigFileIsEmptyYaml()
{
// Arrange
var yamlFile = "---";
var yamlFile = """
---
""";
using var configFile = new TestableNServiceBusConfigurationFile(yamlFile);
var result = _sut.Run("transport", "list", "--config", configFile.FilePath);

Assert.That(result.ExitCode, Is.EqualTo(0));
Assert.That(result.Output, Is.EqualTo("CURRENT NAME TRANSPORT-TYPE"));
}

[Test]
public void ShouldOutputAnEmptyGridWhenTransportArrayIsEmpty()
{
// Arrange
var yamlFile = """
---
transports:
""";
using var configFile = new TestableNServiceBusConfigurationFile(yamlFile);
var result = _sut.Run("transport", "list", "--config", configFile.FilePath);

Assert.That(result.ExitCode, Is.EqualTo(0));
Assert.That(result.Output, Is.EqualTo("CURRENT NAME TRANSPORT-TYPE"));
}
[Test]
public void ShouldOutputASingleTransport()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using BuslyCLI.Config;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.Console.Tests.TestHelpers;
using BuslyCLI.DependencyInjection;
using BuslyCLI.Spectre;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -18,9 +17,6 @@ public void Setup()
{
var registrations = new ServiceCollection();
registrations.AddBuslyCLIServices();
registrations.AddYamlDeserializer();
registrations.AddYamlSerializer();
registrations.AddSingleton<INServiceBusConfiguration, NServiceBusConfiguration>();
using var registrar = new DependencyInjectionRegistrar(registrations);
_sut = new CommandAppTester(registrar);
_sut.Configure(AppConfiguration.GetSpectreCommandConfiguration());
Expand Down Expand Up @@ -59,21 +55,25 @@ public void ShouldOutputAMessageWhenTransportIsSet()
// Arrange
var yamlFile = """
---
current-transport: local-learning
transports:
- name: local-learning
learning-transport-config:
storage-directory: .learningtransport
- name: local-learning2
learning-transport-config:
storage-directory: .learningtransport
""";
using var configFile = new TestableNServiceBusConfigurationFile(yamlFile);

// Act
var result = _sut.Run("transport", "set", "local-learning", "--config", configFile.FilePath);
var result = _sut.Run("transport", "set", "local-learning2", "--config", configFile.FilePath);

// Assert
Assert.That(result.ExitCode, Is.EqualTo(0));
Assert.That(result.Output, Is.EqualTo(
$"""
Switched to transport "local-learning".
Switched to transport "local-learning2".
""".NormalizeLineEndings()
));
}
Expand Down
Loading