Skip to content

Commit 5e97c58

Browse files
montanehamiltonHamilton, MontaneHofmeisterAn
authored
feat: Add Seq module (#1276)
Co-authored-by: Hamilton, Montane <Montane.Hamilton@corp.eddom.org> Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
1 parent 49f6171 commit 5e97c58

19 files changed

Lines changed: 392 additions & 0 deletions

Directory.Packages.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
<PackageVersion Include="RabbitMQ.Client" Version="6.4.0"/>
9090
<PackageVersion Include="RavenDB.Client" Version="5.4.100"/>
9191
<PackageVersion Include="Selenium.WebDriver" Version="4.8.1"/>
92+
<PackageVersion Include="Seq.Api" Version="2025.2.2"/>
93+
<PackageVersion Include="Seq.Extensions.Logging" Version="9.0.0"/>
9294
<PackageVersion Include="StackExchange.Redis" Version="2.6.90"/>
9395
<PackageVersion Include="Temporalio" Version="1.11.0"/>
9496
<PackageVersion Include="ToxiproxyNetCore" Version="1.0.40"/>

Testcontainers.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Redis", "src
124124
EndProject
125125
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Redpanda", "src\Testcontainers.Redpanda\Testcontainers.Redpanda.csproj", "{45D6F69C-4D87-4130-AA90-0DB2F7460DAE}"
126126
EndProject
127+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Seq", "src\Testcontainers.Seq\Testcontainers.Seq.csproj", "{EB246B55-788B-4B58-8739-994A66F91C8A}"
128+
EndProject
127129
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ServiceBus", "src\Testcontainers.ServiceBus\Testcontainers.ServiceBus.csproj", "{2E39E532-B81E-4B48-A004-FAE18EDF9E79}"
128130
EndProject
129131
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Sftp", "src\Testcontainers.Sftp\Testcontainers.Sftp.csproj", "{7D5C6816-0DD2-4E13-A585-033B5D3C80D5}"
@@ -264,6 +266,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Redpanda.Tes
264266
EndProject
265267
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ResourceReaper.Tests", "tests\Testcontainers.ResourceReaper.Tests\Testcontainers.ResourceReaper.Tests.csproj", "{9E8E6AA5-65D1-498F-BEAB-BA34723A0050}"
266268
EndProject
269+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Seq.Tests", "tests\Testcontainers.Seq.Tests\Testcontainers.Seq.Tests.csproj", "{4EFC0DFB-9F04-4070-848A-856D2F11C1BC}"
270+
EndProject
267271
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ServiceBus.Tests", "tests\Testcontainers.ServiceBus.Tests\Testcontainers.ServiceBus.Tests.csproj", "{232DD918-46ED-4BA8-B383-1A9146D83064}"
268272
EndProject
269273
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Sftp.Tests", "tests\Testcontainers.Sftp.Tests\Testcontainers.Sftp.Tests.csproj", "{B73C3CC0-9F16-4B34-92BE-6EC0853912C5}"
@@ -498,6 +502,10 @@ Global
498502
{45D6F69C-4D87-4130-AA90-0DB2F7460DAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
499503
{45D6F69C-4D87-4130-AA90-0DB2F7460DAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
500504
{45D6F69C-4D87-4130-AA90-0DB2F7460DAE}.Release|Any CPU.Build.0 = Release|Any CPU
505+
{EB246B55-788B-4B58-8739-994A66F91C8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
506+
{EB246B55-788B-4B58-8739-994A66F91C8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
507+
{EB246B55-788B-4B58-8739-994A66F91C8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
508+
{EB246B55-788B-4B58-8739-994A66F91C8A}.Release|Any CPU.Build.0 = Release|Any CPU
501509
{2E39E532-B81E-4B48-A004-FAE18EDF9E79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
502510
{2E39E532-B81E-4B48-A004-FAE18EDF9E79}.Debug|Any CPU.Build.0 = Debug|Any CPU
503511
{2E39E532-B81E-4B48-A004-FAE18EDF9E79}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -778,6 +786,10 @@ Global
778786
{9E8E6AA5-65D1-498F-BEAB-BA34723A0050}.Debug|Any CPU.Build.0 = Debug|Any CPU
779787
{9E8E6AA5-65D1-498F-BEAB-BA34723A0050}.Release|Any CPU.ActiveCfg = Release|Any CPU
780788
{9E8E6AA5-65D1-498F-BEAB-BA34723A0050}.Release|Any CPU.Build.0 = Release|Any CPU
789+
{4EFC0DFB-9F04-4070-848A-856D2F11C1BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
790+
{4EFC0DFB-9F04-4070-848A-856D2F11C1BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
791+
{4EFC0DFB-9F04-4070-848A-856D2F11C1BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
792+
{4EFC0DFB-9F04-4070-848A-856D2F11C1BC}.Release|Any CPU.Build.0 = Release|Any CPU
781793
{232DD918-46ED-4BA8-B383-1A9146D83064}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
782794
{232DD918-46ED-4BA8-B383-1A9146D83064}.Debug|Any CPU.Build.0 = Debug|Any CPU
783795
{232DD918-46ED-4BA8-B383-1A9146D83064}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -876,6 +888,7 @@ Global
876888
{F6394475-D6F1-46E2-81BF-4BA78A40B878} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
877889
{BFDA179A-40EB-4CEB-B8E9-0DF32C65E2C5} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
878890
{45D6F69C-4D87-4130-AA90-0DB2F7460DAE} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
891+
{EB246B55-788B-4B58-8739-994A66F91C8A} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
879892
{2E39E532-B81E-4B48-A004-FAE18EDF9E79} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
880893
{7D5C6816-0DD2-4E13-A585-033B5D3C80D5} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
881894
{24431BF1-7BEB-4C53-BAE8-B9D9F622A240} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
@@ -946,6 +959,7 @@ Global
946959
{31EE94A0-E721-4073-B6F1-DD912D004DEF} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
947960
{867BD04E-4670-4FBA-98D5-9F83220E6DFB} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
948961
{9E8E6AA5-65D1-498F-BEAB-BA34723A0050} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
962+
{4EFC0DFB-9F04-4070-848A-856D2F11C1BC} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
949963
{232DD918-46ED-4BA8-B383-1A9146D83064} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
950964
{B73C3CC0-9F16-4B34-92BE-6EC0853912C5} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
951965
{28B5DEDF-C19B-4A7E-B276-FC4C83DBB7EF} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}

Testcontainers.slnx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
<Project Path="src/Testcontainers.RavenDb/Testcontainers.RavenDb.csproj"/>
6363
<Project Path="src/Testcontainers.Redis/Testcontainers.Redis.csproj"/>
6464
<Project Path="src/Testcontainers.Redpanda/Testcontainers.Redpanda.csproj"/>
65+
<Project Path="src/Testcontainers.Seq/Testcontainers.Seq.csproj"/>
6566
<Project Path="src/Testcontainers.ServiceBus/Testcontainers.ServiceBus.csproj"/>
6667
<Project Path="src/Testcontainers.Sftp/Testcontainers.Sftp.csproj"/>
6768
<Project Path="src/Testcontainers.Temporalio/Testcontainers.Temporalio.csproj"/>
@@ -134,6 +135,7 @@
134135
<Project Path="tests/Testcontainers.Redis.Tests/Testcontainers.Redis.Tests.csproj"/>
135136
<Project Path="tests/Testcontainers.Redpanda.Tests/Testcontainers.Redpanda.Tests.csproj"/>
136137
<Project Path="tests/Testcontainers.ResourceReaper.Tests/Testcontainers.ResourceReaper.Tests.csproj"/>
138+
<Project Path="tests/Testcontainers.Seq.Tests/Testcontainers.Seq.Tests.csproj"/>
137139
<Project Path="tests/Testcontainers.ServiceBus.Tests/Testcontainers.ServiceBus.Tests.csproj"/>
138140
<Project Path="tests/Testcontainers.Sftp.Tests/Testcontainers.Sftp.Tests.csproj"/>
139141
<Project Path="tests/Testcontainers.Temporalio.Tests/Testcontainers.Temporalio.Tests.csproj"/>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
root = true
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
namespace Testcontainers.Seq;
2+
3+
/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" />
4+
[PublicAPI]
5+
public sealed class SeqBuilder : ContainerBuilder<SeqBuilder, SeqContainer, SeqConfiguration>
6+
{
7+
public const string SeqImage = "datalust/seq:2025.2";
8+
9+
public const ushort SeqPort = 80;
10+
11+
/// <summary>
12+
/// Initializes a new instance of the <see cref="SeqBuilder" /> class.
13+
/// </summary>
14+
[Obsolete("This parameterless constructor is obsolete and will be removed. Use the constructor with the image parameter instead: https://github.com/testcontainers/testcontainers-dotnet/discussions/1470#discussioncomment-15185721.")]
15+
[ExcludeFromCodeCoverage]
16+
public SeqBuilder()
17+
: this(SeqImage)
18+
{
19+
}
20+
21+
/// <summary>
22+
/// Initializes a new instance of the <see cref="SeqBuilder" /> class.
23+
/// </summary>
24+
/// <param name="image">
25+
/// The full Docker image name, including the image repository and tag
26+
/// (e.g., <c>datalust/seq:2025.2</c>).
27+
/// </param>
28+
/// <remarks>
29+
/// Docker image tags available at <see href="https://hub.docker.com/r/datalust/seq" />.
30+
/// </remarks>
31+
public SeqBuilder(string image)
32+
: this(new DockerImage(image))
33+
{
34+
}
35+
36+
/// <summary>
37+
/// Initializes a new instance of the <see cref="SeqBuilder" /> class.
38+
/// </summary>
39+
/// <param name="image">
40+
/// An <see cref="IImage" /> instance that specifies the Docker image to be used
41+
/// for the container builder configuration.
42+
/// </param>
43+
/// <remarks>
44+
/// Docker image tags available at <see href="https://hub.docker.com/r/datalust/seq" />.
45+
/// </remarks>
46+
public SeqBuilder(IImage image)
47+
: this(new SeqConfiguration())
48+
{
49+
DockerResourceConfiguration = Init().WithImage(image).DockerResourceConfiguration;
50+
}
51+
52+
/// <summary>
53+
/// Initializes a new instance of the <see cref="SeqBuilder" /> class.
54+
/// </summary>
55+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
56+
private SeqBuilder(SeqConfiguration resourceConfiguration)
57+
: base(resourceConfiguration)
58+
{
59+
DockerResourceConfiguration = resourceConfiguration;
60+
}
61+
62+
/// <inheritdoc />
63+
protected override SeqConfiguration DockerResourceConfiguration { get; }
64+
65+
/// <inheritdoc />
66+
protected override string AcceptLicenseAgreementEnvVar { get; } = "ACCEPT_EULA";
67+
68+
/// <inheritdoc />
69+
protected override string AcceptLicenseAgreement { get; } = "Y";
70+
71+
/// <inheritdoc />
72+
protected override string DeclineLicenseAgreement { get; } = "N";
73+
74+
/// <summary>
75+
/// Accepts the license agreement.
76+
/// </summary>
77+
/// <remarks>
78+
/// When <paramref name="acceptLicenseAgreement" /> is set to <c>true</c>, the Seq <see href="https://datalust.co/doc/eula-current.pdf">license</see> is accepted.
79+
/// </remarks>
80+
/// <param name="acceptLicenseAgreement">A boolean value indicating whether the Seq license agreement is accepted.</param>
81+
/// <returns>A configured instance of <see cref="SeqBuilder" />.</returns>
82+
public override SeqBuilder WithAcceptLicenseAgreement(bool acceptLicenseAgreement)
83+
{
84+
var licenseAgreement = acceptLicenseAgreement ? AcceptLicenseAgreement : DeclineLicenseAgreement;
85+
return WithEnvironment(AcceptLicenseAgreementEnvVar, licenseAgreement);
86+
}
87+
88+
/// <inheritdoc />
89+
public override SeqContainer Build()
90+
{
91+
Validate();
92+
ValidateLicenseAgreement();
93+
94+
return new SeqContainer(DockerResourceConfiguration);
95+
}
96+
97+
/// <inheritdoc />
98+
protected override SeqBuilder Init()
99+
{
100+
return base.Init()
101+
.WithPortBinding(SeqPort, true)
102+
.WithEnvironment("SEQ_FIRSTRUN_NOAUTHENTICATION", "true")
103+
.WithConnectionStringProvider(new SeqConnectionStringProvider())
104+
.WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request =>
105+
request.ForPort(SeqPort).ForPath("/health")));
106+
}
107+
108+
/// <inheritdoc />
109+
protected override SeqBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
110+
{
111+
return Merge(DockerResourceConfiguration, new SeqConfiguration(resourceConfiguration));
112+
}
113+
114+
/// <inheritdoc />
115+
protected override SeqBuilder Clone(IContainerConfiguration resourceConfiguration)
116+
{
117+
return Merge(DockerResourceConfiguration, new SeqConfiguration(resourceConfiguration));
118+
}
119+
120+
/// <inheritdoc />
121+
protected override SeqBuilder Merge(SeqConfiguration oldValue, SeqConfiguration newValue)
122+
{
123+
return new SeqBuilder(new SeqConfiguration(oldValue, newValue));
124+
}
125+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
namespace Testcontainers.Seq;
2+
3+
/// <inheritdoc cref="ContainerConfiguration" />
4+
[PublicAPI]
5+
public sealed class SeqConfiguration : ContainerConfiguration
6+
{
7+
/// <summary>
8+
/// Initializes a new instance of the <see cref="SeqConfiguration" /> class.
9+
/// </summary>
10+
public SeqConfiguration()
11+
{
12+
}
13+
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="SeqConfiguration" /> class.
16+
/// </summary>
17+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
18+
public SeqConfiguration(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
19+
: base(resourceConfiguration)
20+
{
21+
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
22+
}
23+
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="SeqConfiguration" /> class.
26+
/// </summary>
27+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
28+
public SeqConfiguration(IContainerConfiguration resourceConfiguration)
29+
: base(resourceConfiguration)
30+
{
31+
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
32+
}
33+
34+
/// <summary>
35+
/// Initializes a new instance of the <see cref="SeqConfiguration" /> class.
36+
/// </summary>
37+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
38+
public SeqConfiguration(SeqConfiguration resourceConfiguration)
39+
: this(new SeqConfiguration(), resourceConfiguration)
40+
{
41+
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
42+
}
43+
44+
/// <summary>
45+
/// Initializes a new instance of the <see cref="SeqConfiguration" /> class.
46+
/// </summary>
47+
/// <param name="oldValue">The old Docker resource configuration.</param>
48+
/// <param name="newValue">The new Docker resource configuration.</param>
49+
public SeqConfiguration(SeqConfiguration oldValue, SeqConfiguration newValue)
50+
: base(oldValue, newValue)
51+
{
52+
}
53+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace Testcontainers.Seq;
2+
3+
/// <summary>
4+
/// Provides the Seq connection string.
5+
/// </summary>
6+
internal sealed class SeqConnectionStringProvider : ContainerConnectionStringProvider<SeqContainer, SeqConfiguration>
7+
{
8+
/// <inheritdoc />
9+
protected override string GetHostConnectionString()
10+
{
11+
return Container.GetEndpoint();
12+
}
13+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace Testcontainers.Seq;
2+
3+
/// <inheritdoc cref="DockerContainer" />
4+
[PublicAPI]
5+
public sealed class SeqContainer : DockerContainer
6+
{
7+
/// <summary>
8+
/// Initializes a new instance of the <see cref="SeqContainer" /> class.
9+
/// </summary>
10+
/// <param name="configuration">The container configuration.</param>
11+
public SeqContainer(SeqConfiguration configuration)
12+
: base(configuration)
13+
{
14+
}
15+
16+
/// <summary>
17+
/// Gets the Seq endpoint.
18+
/// </summary>
19+
/// <returns>The Seq endpoint.</returns>
20+
public string GetEndpoint()
21+
{
22+
return new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(SeqBuilder.SeqPort)).ToString();
23+
}
24+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
4+
<LangVersion>latest</LangVersion>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="JetBrains.Annotations" VersionOverride="2023.3.0" PrivateAssets="All"/>
8+
</ItemGroup>
9+
<ItemGroup>
10+
<ProjectReference Include="../Testcontainers/Testcontainers.csproj"/>
11+
</ItemGroup>
12+
</Project>

src/Testcontainers.Seq/Usings.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
global using System;
2+
global using System.Diagnostics.CodeAnalysis;
3+
global using Docker.DotNet.Models;
4+
global using DotNet.Testcontainers.Builders;
5+
global using DotNet.Testcontainers.Configurations;
6+
global using DotNet.Testcontainers.Containers;
7+
global using DotNet.Testcontainers.Images;
8+
global using JetBrains.Annotations;

0 commit comments

Comments
 (0)