From 8cad0fb19c7ab2b462bae0822a2b47881513b1c1 Mon Sep 17 00:00:00 2001 From: "Hamilton, Montane" Date: Thu, 10 Oct 2024 11:25:38 -0600 Subject: [PATCH] Add Seq Module --- .github/workflows/cicd.yml | 1 + Directory.Packages.props | 3 + Testcontainers.sln | 23 +++++- src/Testcontainers.Seq/.editorconfig | 1 + src/Testcontainers.Seq/SeqBuilder.cs | 72 +++++++++++++++++++ src/Testcontainers.Seq/SeqConfiguration.cs | 56 +++++++++++++++ src/Testcontainers.Seq/SeqContainer.cs | 22 ++++++ .../Testcontainers.Seq.csproj | 12 ++++ src/Testcontainers.Seq/Usings.cs | 6 ++ .../Testcontainers.Databases.Tests.csproj | 58 +++++++++++++-- tests/Testcontainers.Seq.Tests/.editorconfig | 1 + .../SeqContainerTest.cs | 38 ++++++++++ .../Testcontainers.Seq.Tests.csproj | 26 +++++++ tests/Testcontainers.Seq.Tests/Usings.cs | 3 + 14 files changed, 313 insertions(+), 9 deletions(-) create mode 100644 src/Testcontainers.Seq/.editorconfig create mode 100644 src/Testcontainers.Seq/SeqBuilder.cs create mode 100644 src/Testcontainers.Seq/SeqConfiguration.cs create mode 100644 src/Testcontainers.Seq/SeqContainer.cs create mode 100644 src/Testcontainers.Seq/Testcontainers.Seq.csproj create mode 100644 src/Testcontainers.Seq/Usings.cs create mode 100644 tests/Testcontainers.Seq.Tests/.editorconfig create mode 100644 tests/Testcontainers.Seq.Tests/SeqContainerTest.cs create mode 100644 tests/Testcontainers.Seq.Tests/Testcontainers.Seq.Tests.csproj create mode 100644 tests/Testcontainers.Seq.Tests/Usings.cs diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 036861069..45542b95d 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -78,6 +78,7 @@ jobs: { name: "Testcontainers.RavenDb", runs-on: "ubuntu-22.04" }, { name: "Testcontainers.Redis", runs-on: "ubuntu-22.04" }, { name: "Testcontainers.Redpanda", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Seq", runs-on: "ubuntu-22.04" }, { name: "Testcontainers.WebDriver", runs-on: "ubuntu-22.04" }, { name: "Testcontainers.Xunit", runs-on: "ubuntu-22.04" } ] diff --git a/Directory.Packages.props b/Directory.Packages.props index 813d398cf..004f60648 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -9,6 +9,7 @@ + @@ -23,6 +24,8 @@ + + diff --git a/Testcontainers.sln b/Testcontainers.sln index 1caef1ce5..6cbd1c779 100644 --- a/Testcontainers.sln +++ b/Testcontainers.sln @@ -201,14 +201,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Xunit.Tests", "tests\Testcontainers.Xunit.Tests\Testcontainers.Xunit.Tests.csproj", "{E901DF14-6F05-4FC2-825A-3055FAD33561}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Seq", "..\testcontainers-dotnet\src\Testcontainers.Seq\Testcontainers.Seq.csproj", "{F148CB77-9438-9DCF-CA37-75F7BCD5FEF6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Seq.Tests", "..\testcontainers-dotnet\tests\Testcontainers.Seq.Tests\Testcontainers.Seq.Tests.csproj", "{6FF86CD0-3801-ADE4-A59B-271AC8B2390C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5365F780-0E6C-41F0-B1B9-7DC34368F80C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5365F780-0E6C-41F0-B1B9-7DC34368F80C}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -586,6 +587,17 @@ Global {E901DF14-6F05-4FC2-825A-3055FAD33561}.Debug|Any CPU.Build.0 = Debug|Any CPU {E901DF14-6F05-4FC2-825A-3055FAD33561}.Release|Any CPU.ActiveCfg = Release|Any CPU {E901DF14-6F05-4FC2-825A-3055FAD33561}.Release|Any CPU.Build.0 = Release|Any CPU + {F148CB77-9438-9DCF-CA37-75F7BCD5FEF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F148CB77-9438-9DCF-CA37-75F7BCD5FEF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F148CB77-9438-9DCF-CA37-75F7BCD5FEF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F148CB77-9438-9DCF-CA37-75F7BCD5FEF6}.Release|Any CPU.Build.0 = Release|Any CPU + {6FF86CD0-3801-ADE4-A59B-271AC8B2390C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FF86CD0-3801-ADE4-A59B-271AC8B2390C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FF86CD0-3801-ADE4-A59B-271AC8B2390C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FF86CD0-3801-ADE4-A59B-271AC8B2390C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} @@ -682,5 +694,10 @@ Global {27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {E901DF14-6F05-4FC2-825A-3055FAD33561} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} + {F148CB77-9438-9DCF-CA37-75F7BCD5FEF6} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} + {6FF86CD0-3801-ADE4-A59B-271AC8B2390C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5EC93352-CD4F-4CB4-84D3-B822DB932443} EndGlobalSection EndGlobal diff --git a/src/Testcontainers.Seq/.editorconfig b/src/Testcontainers.Seq/.editorconfig new file mode 100644 index 000000000..6f066619d --- /dev/null +++ b/src/Testcontainers.Seq/.editorconfig @@ -0,0 +1 @@ +root = true \ No newline at end of file diff --git a/src/Testcontainers.Seq/SeqBuilder.cs b/src/Testcontainers.Seq/SeqBuilder.cs new file mode 100644 index 000000000..e0648c85f --- /dev/null +++ b/src/Testcontainers.Seq/SeqBuilder.cs @@ -0,0 +1,72 @@ +namespace Testcontainers.Seq; + +/// +[PublicAPI] +public sealed class SeqBuilder : ContainerBuilder +{ + public const string SeqImage = "datalust/seq:2024.2.11456"; + + public const ushort SeqApiPort = 80; + public const ushort SeqIngestionPort = 5341; + + /// + protected override SeqConfiguration DockerResourceConfiguration { get; } + + /// + /// Initializes a new instance of the class. + /// + public SeqBuilder() + : this(new SeqConfiguration()) + { + DockerResourceConfiguration = Init().DockerResourceConfiguration; + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + private SeqBuilder(SeqConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + DockerResourceConfiguration = resourceConfiguration; + } + + /// + public override SeqContainer Build() + { + Validate(); + return new SeqContainer(DockerResourceConfiguration); + } + /// + protected override SeqBuilder Init() + { + return base.Init() + .WithImage(SeqImage) + .WithPortBinding(SeqApiPort, true) + .WithPortBinding(SeqIngestionPort, true) + .WithEnvironment(new Dictionary + { + {"ACCEPT_EULA", "Y" } + }) + .WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request => + request.ForPath("/health").ForPort(SeqApiPort))); + } + + /// + protected override SeqBuilder Clone(IResourceConfiguration resourceConfiguration) + { + return Merge(DockerResourceConfiguration, new SeqConfiguration(resourceConfiguration)); + } + + /// + protected override SeqBuilder Clone(IContainerConfiguration resourceConfiguration) + { + return Merge(DockerResourceConfiguration, new SeqConfiguration(resourceConfiguration)); + } + + /// + protected override SeqBuilder Merge(SeqConfiguration oldValue, SeqConfiguration newValue) + { + return new SeqBuilder(new SeqConfiguration(oldValue, newValue)); + } +} \ No newline at end of file diff --git a/src/Testcontainers.Seq/SeqConfiguration.cs b/src/Testcontainers.Seq/SeqConfiguration.cs new file mode 100644 index 000000000..3302aa1e9 --- /dev/null +++ b/src/Testcontainers.Seq/SeqConfiguration.cs @@ -0,0 +1,56 @@ +namespace Testcontainers.Seq; + +/// +[PublicAPI] +public sealed class SeqConfiguration : ContainerConfiguration +{ + /// + /// Initializes a new instance of the class. + /// + /// The Orion.TestContainers.Seq config. + public SeqConfiguration(object config = null) + { + // Sets the custom builder methods property values. + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public SeqConfiguration(IResourceConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + // Passes the configuration upwards to the base implementations to create an updated immutable copy. + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public SeqConfiguration(IContainerConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + // Passes the configuration upwards to the base implementations to create an updated immutable copy. + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public SeqConfiguration(SeqConfiguration resourceConfiguration) + : this(new SeqConfiguration(), resourceConfiguration) + { + // Passes the configuration upwards to the base implementations to create an updated immutable copy. + } + + /// + /// Initializes a new instance of the class. + /// + /// The old Docker resource configuration. + /// The new Docker resource configuration. + public SeqConfiguration(SeqConfiguration oldValue, SeqConfiguration newValue) + : base(oldValue, newValue) + { + // Create an updated immutable copy of the module configuration. + } +} \ No newline at end of file diff --git a/src/Testcontainers.Seq/SeqContainer.cs b/src/Testcontainers.Seq/SeqContainer.cs new file mode 100644 index 000000000..befc9850a --- /dev/null +++ b/src/Testcontainers.Seq/SeqContainer.cs @@ -0,0 +1,22 @@ +using System; + +namespace Testcontainers.Seq; + +/// +[PublicAPI] +public sealed class SeqContainer : DockerContainer +{ + /// + /// Initializes a new instance of the class. + /// + /// The container configuration. + public SeqContainer(SeqConfiguration configuration) + : base(configuration) + { + } + + public string GetServerApiUrl() + { + return new UriBuilder("http", Hostname, GetMappedPublicPort(SeqBuilder.SeqApiPort)).Uri.ToString(); + } +} \ No newline at end of file diff --git a/src/Testcontainers.Seq/Testcontainers.Seq.csproj b/src/Testcontainers.Seq/Testcontainers.Seq.csproj new file mode 100644 index 000000000..8b2ed72c6 --- /dev/null +++ b/src/Testcontainers.Seq/Testcontainers.Seq.csproj @@ -0,0 +1,12 @@ + + + net6.0;net8.0;netstandard2.0;netstandard2.1 + latest + + + + + + + + \ No newline at end of file diff --git a/src/Testcontainers.Seq/Usings.cs b/src/Testcontainers.Seq/Usings.cs new file mode 100644 index 000000000..080580c42 --- /dev/null +++ b/src/Testcontainers.Seq/Usings.cs @@ -0,0 +1,6 @@ +global using System.Collections.Generic; +global using Docker.DotNet.Models; +global using DotNet.Testcontainers.Builders; +global using DotNet.Testcontainers.Configurations; +global using DotNet.Testcontainers.Containers; +global using JetBrains.Annotations; diff --git a/tests/Testcontainers.Databases.Tests/Testcontainers.Databases.Tests.csproj b/tests/Testcontainers.Databases.Tests/Testcontainers.Databases.Tests.csproj index 2ca23a8cb..a5f13fc67 100644 --- a/tests/Testcontainers.Databases.Tests/Testcontainers.Databases.Tests.csproj +++ b/tests/Testcontainers.Databases.Tests/Testcontainers.Databases.Tests.csproj @@ -5,13 +5,59 @@ false - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/Testcontainers.Seq.Tests/.editorconfig b/tests/Testcontainers.Seq.Tests/.editorconfig new file mode 100644 index 000000000..6f066619d --- /dev/null +++ b/tests/Testcontainers.Seq.Tests/.editorconfig @@ -0,0 +1 @@ +root = true \ No newline at end of file diff --git a/tests/Testcontainers.Seq.Tests/SeqContainerTest.cs b/tests/Testcontainers.Seq.Tests/SeqContainerTest.cs new file mode 100644 index 000000000..ed30ff6e9 --- /dev/null +++ b/tests/Testcontainers.Seq.Tests/SeqContainerTest.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Logging; +using Seq.Api; +using System; +using System.Linq; + +namespace Testcontainers.Seq; + +public sealed class SeqContainerTest : IAsyncLifetime +{ + private readonly SeqContainer _seqContainer = new SeqBuilder().Build(); + + public Task InitializeAsync() + { + return _seqContainer.StartAsync(); + } + + public Task DisposeAsync() + { + return _seqContainer.DisposeAsync().AsTask(); + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task CanLog() + { + var currentSeqApiPort = _seqContainer.GetMappedPublicPort(80); + var currentSeqHostname = _seqContainer.Hostname; + + ILoggerFactory loggerFactory = new LoggerFactory(); + loggerFactory.AddSeq(_seqContainer.GetServerApiUrl()); + var testLogger = loggerFactory.CreateLogger("testlogger"); + testLogger.LogInformation("TRY THIS"); + + var seqConnection = new SeqConnection(_seqContainer.GetServerApiUrl()); + var eventList = await seqConnection.Events.ListAsync(fromDateUtc: DateTime.Now.AddMinutes(-1)); + Assert.Contains(eventList, e => e.MessageTemplateTokens.Last().Text == "TRY THIS"); + } +} \ No newline at end of file diff --git a/tests/Testcontainers.Seq.Tests/Testcontainers.Seq.Tests.csproj b/tests/Testcontainers.Seq.Tests/Testcontainers.Seq.Tests.csproj new file mode 100644 index 000000000..4ea635b58 --- /dev/null +++ b/tests/Testcontainers.Seq.Tests/Testcontainers.Seq.Tests.csproj @@ -0,0 +1,26 @@ + + + net8.0 + false + false + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + \ No newline at end of file diff --git a/tests/Testcontainers.Seq.Tests/Usings.cs b/tests/Testcontainers.Seq.Tests/Usings.cs new file mode 100644 index 000000000..346085388 --- /dev/null +++ b/tests/Testcontainers.Seq.Tests/Usings.cs @@ -0,0 +1,3 @@ +global using System.Threading.Tasks; +global using DotNet.Testcontainers.Commons; +global using Xunit; \ No newline at end of file