Skip to content

Commit aa4385d

Browse files
feat: Add Consul module (#1028)
Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
1 parent c7cedb8 commit aa4385d

11 files changed

+257
-0
lines changed

Testcontainers.sln

+14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Azurite", "s
1717
EndProject
1818
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ClickHouse", "src\Testcontainers.ClickHouse\Testcontainers.ClickHouse.csproj", "{B061A78E-536E-4CA1-8401-234D5FBFBAB7}"
1919
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Consul", "src\Testcontainers.Consul\Testcontainers.Consul.csproj", "{51ED33B9-B688-401E-85F2-329D3C935BD1}"
21+
EndProject
2022
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.CosmosDb", "src\Testcontainers.CosmosDb\Testcontainers.CosmosDb.csproj", "{A724806F-8C94-4438-8011-04A9A1575318}"
2123
EndProject
2224
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Couchbase", "src\Testcontainers.Couchbase\Testcontainers.Couchbase.csproj", "{58E94721-2681-4D82-8D94-0B2F9DB0D575}"
@@ -85,6 +87,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.ClickHouse.T
8587
EndProject
8688
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Commons", "tests\Testcontainers.Commons\Testcontainers.Commons.csproj", "{2478673C-B063-469D-ABD1-0C3E0A25541B}"
8789
EndProject
90+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Consul.Tests", "tests\Testcontainers.Consul.Tests\Testcontainers.Consul.Tests.csproj", "{91B23679-A2A5-4132-8AFA-740CE40A88B6}"
91+
EndProject
8892
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.CosmosDb.Tests", "tests\Testcontainers.CosmosDb.Tests\Testcontainers.CosmosDb.Tests.csproj", "{BD445A54-F411-4758-955E-397A1E98680C}"
8993
EndProject
9094
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Couchbase.Tests", "tests\Testcontainers.Couchbase.Tests\Testcontainers.Couchbase.Tests.csproj", "{809322BA-D690-4F2B-B884-23F895663963}"
@@ -172,6 +176,10 @@ Global
172176
{B061A78E-536E-4CA1-8401-234D5FBFBAB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
173177
{B061A78E-536E-4CA1-8401-234D5FBFBAB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
174178
{B061A78E-536E-4CA1-8401-234D5FBFBAB7}.Release|Any CPU.Build.0 = Release|Any CPU
179+
{51ED33B9-B688-401E-85F2-329D3C935BD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
180+
{51ED33B9-B688-401E-85F2-329D3C935BD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
181+
{51ED33B9-B688-401E-85F2-329D3C935BD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
182+
{51ED33B9-B688-401E-85F2-329D3C935BD1}.Release|Any CPU.Build.0 = Release|Any CPU
175183
{A724806F-8C94-4438-8011-04A9A1575318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
176184
{A724806F-8C94-4438-8011-04A9A1575318}.Debug|Any CPU.Build.0 = Debug|Any CPU
177185
{A724806F-8C94-4438-8011-04A9A1575318}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -308,6 +316,10 @@ Global
308316
{2478673C-B063-469D-ABD1-0C3E0A25541B}.Debug|Any CPU.Build.0 = Debug|Any CPU
309317
{2478673C-B063-469D-ABD1-0C3E0A25541B}.Release|Any CPU.ActiveCfg = Release|Any CPU
310318
{2478673C-B063-469D-ABD1-0C3E0A25541B}.Release|Any CPU.Build.0 = Release|Any CPU
319+
{91B23679-A2A5-4132-8AFA-740CE40A88B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
320+
{91B23679-A2A5-4132-8AFA-740CE40A88B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
321+
{91B23679-A2A5-4132-8AFA-740CE40A88B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
322+
{91B23679-A2A5-4132-8AFA-740CE40A88B6}.Release|Any CPU.Build.0 = Release|Any CPU
311323
{BD445A54-F411-4758-955E-397A1E98680C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
312324
{BD445A54-F411-4758-955E-397A1E98680C}.Debug|Any CPU.Build.0 = Debug|Any CPU
313325
{BD445A54-F411-4758-955E-397A1E98680C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -452,6 +464,7 @@ Global
452464
GlobalSection(NestedProjects) = preSolution
453465
{3F2E254F-C203-43FD-A078-DC3E2CBC0F9F} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
454466
{B061A78E-536E-4CA1-8401-234D5FBFBAB7} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
467+
{51ED33B9-B688-401E-85F2-329D3C935BD1} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
455468
{A724806F-8C94-4438-8011-04A9A1575318} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
456469
{58E94721-2681-4D82-8D94-0B2F9DB0D575} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
457470
{DCECB1F6-D9AA-431F-AE42-25D56B9E7DFC} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
@@ -486,6 +499,7 @@ Global
486499
{B272FDDE-5E01-425D-B9E1-10FF883DDAAA} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
487500
{9D0A0B32-4921-400C-99CB-8650677E3E44} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
488501
{2478673C-B063-469D-ABD1-0C3E0A25541B} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
502+
{91B23679-A2A5-4132-8AFA-740CE40A88B6} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
489503
{BD445A54-F411-4758-955E-397A1E98680C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
490504
{809322BA-D690-4F2B-B884-23F895663963} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
491505
{E4520FB1-4466-4DCA-AD08-4075102C68D3} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
root = true
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
namespace Testcontainers.Consul;
2+
3+
/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" />
4+
[PublicAPI]
5+
public sealed class ConsulBuilder : ContainerBuilder<ConsulBuilder, ConsulContainer, ConsulConfiguration>
6+
{
7+
public const string ConsulImage = "consul:1.15";
8+
9+
public const int ConsulHttpPort = 8500;
10+
11+
public const int ConsulGrpcPort = 8502;
12+
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="ConsulBuilder" /> class.
15+
/// </summary>
16+
public ConsulBuilder()
17+
: this(new ConsulConfiguration())
18+
{
19+
DockerResourceConfiguration = Init().DockerResourceConfiguration;
20+
}
21+
22+
/// <summary>
23+
/// Initializes a new instance of the <see cref="ConsulBuilder" /> class.
24+
/// </summary>
25+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
26+
private ConsulBuilder(ConsulConfiguration resourceConfiguration)
27+
: base(resourceConfiguration)
28+
{
29+
DockerResourceConfiguration = resourceConfiguration;
30+
}
31+
32+
/// <inheritdoc />
33+
protected override ConsulConfiguration DockerResourceConfiguration { get; }
34+
35+
/// <inheritdoc />
36+
public override ConsulContainer Build()
37+
{
38+
Validate();
39+
return new ConsulContainer(DockerResourceConfiguration, TestcontainersSettings.Logger);
40+
}
41+
42+
/// <inheritdoc />
43+
protected override ConsulBuilder Init()
44+
{
45+
return base.Init()
46+
.WithImage(ConsulImage)
47+
.WithPortBinding(ConsulHttpPort, true)
48+
.WithPortBinding(ConsulGrpcPort, true)
49+
.WithCommand("agent", "-dev", "-client", "0.0.0.0")
50+
.WithCreateParameterModifier(cmd => cmd.HostConfig.CapAdd = new[] { "IPC_LOCK" })
51+
.WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request =>
52+
request.ForPath("/v1/status/leader").ForPort(ConsulHttpPort)));
53+
}
54+
55+
/// <inheritdoc />
56+
protected override ConsulBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
57+
{
58+
return Merge(DockerResourceConfiguration, new ConsulConfiguration(resourceConfiguration));
59+
}
60+
61+
/// <inheritdoc />
62+
protected override ConsulBuilder Clone(IContainerConfiguration resourceConfiguration)
63+
{
64+
return Merge(DockerResourceConfiguration, new ConsulConfiguration(resourceConfiguration));
65+
}
66+
67+
/// <inheritdoc />
68+
protected override ConsulBuilder Merge(ConsulConfiguration oldValue, ConsulConfiguration newValue)
69+
{
70+
return new ConsulBuilder(new ConsulConfiguration(oldValue, newValue));
71+
}
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
namespace Testcontainers.Consul;
2+
3+
/// <inheritdoc cref="ContainerConfiguration" />
4+
[PublicAPI]
5+
public sealed class ConsulConfiguration : ContainerConfiguration
6+
{
7+
/// <summary>
8+
/// Initializes a new instance of the <see cref="ConsulConfiguration" /> class.
9+
/// </summary>
10+
public ConsulConfiguration()
11+
{
12+
}
13+
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="ConsulConfiguration" /> class.
16+
/// </summary>
17+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
18+
public ConsulConfiguration(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="ConsulConfiguration" /> class.
26+
/// </summary>
27+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
28+
public ConsulConfiguration(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="ConsulConfiguration" /> class.
36+
/// </summary>
37+
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
38+
public ConsulConfiguration(ConsulConfiguration resourceConfiguration)
39+
: this(new ConsulConfiguration(), 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="ConsulConfiguration" /> 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 ConsulConfiguration(ConsulConfiguration oldValue, ConsulConfiguration newValue)
50+
: base(oldValue, newValue)
51+
{
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
namespace Testcontainers.Consul;
2+
3+
/// <inheritdoc cref="DockerContainer" />
4+
[PublicAPI]
5+
public sealed class ConsulContainer : DockerContainer
6+
{
7+
/// <summary>
8+
/// Initializes a new instance of the <see cref="ConsulContainer" /> class.
9+
/// </summary>
10+
/// <param name="configuration">The container configuration.</param>
11+
/// <param name="logger">The logger.</param>
12+
public ConsulContainer(ConsulConfiguration configuration, ILogger logger)
13+
: base(configuration, logger)
14+
{
15+
}
16+
17+
/// <summary>
18+
/// Gets the Consul base address.
19+
/// </summary>
20+
/// <returns>The Consul base address.</returns>
21+
public string GetBaseAddress()
22+
{
23+
return new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(ConsulBuilder.ConsulHttpPort)).ToString();
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
4+
<LangVersion>latest</LangVersion>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
8+
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All"/>
9+
</ItemGroup>
10+
<ItemGroup>
11+
<ProjectReference Include="$(SolutionDir)src/Testcontainers/Testcontainers.csproj"/>
12+
</ItemGroup>
13+
</Project>

src/Testcontainers.Consul/Usings.cs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
global using System;
2+
global using System.Net;
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 JetBrains.Annotations;
8+
global using Microsoft.Extensions.Logging;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
root = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace Testcontainers.Consul;
2+
3+
public sealed class ConsulContainerTest : IAsyncLifetime
4+
{
5+
private readonly ConsulContainer _consulContainer = new ConsulBuilder().Build();
6+
7+
public Task InitializeAsync()
8+
{
9+
return _consulContainer.StartAsync();
10+
}
11+
12+
public Task DisposeAsync()
13+
{
14+
return _consulContainer.DisposeAsync().AsTask();
15+
}
16+
17+
[Fact]
18+
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
19+
public async Task GetItemReturnsPutItem()
20+
{
21+
// Given
22+
const string helloWorld = "Hello, World!";
23+
24+
var key = Guid.NewGuid().ToString("D");
25+
26+
var expected = new KVPair(key);
27+
expected.Value = Encoding.Default.GetBytes(helloWorld);
28+
29+
var consulClientConfiguration = new ConsulClientConfiguration();
30+
consulClientConfiguration.Address = new Uri(_consulContainer.GetBaseAddress());
31+
32+
using var consulClient = new ConsulClient(consulClientConfiguration);
33+
34+
// When
35+
_ = await consulClient.KV.Put(expected)
36+
.ConfigureAwait(false);
37+
38+
var actual = await consulClient.KV.Get(key)
39+
.ConfigureAwait(false);
40+
41+
// Then
42+
Assert.Equal(HttpStatusCode.OK, actual.StatusCode);
43+
Assert.Equal(helloWorld, Encoding.Default.GetString(actual.Response.Value));
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFrameworks>net6.0</TargetFrameworks>
4+
<IsPackable>false</IsPackable>
5+
<IsPublishable>false</IsPublishable>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<PackageReference Include="Consul" Version="1.6.10.9" />
9+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
10+
<PackageReference Include="coverlet.collector" Version="6.0.0" />
11+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0" />
12+
<PackageReference Include="xunit" Version="2.5.0" />
13+
</ItemGroup>
14+
<ItemGroup>
15+
<ProjectReference Include="$(SolutionDir)src/Testcontainers.Consul/Testcontainers.Consul.csproj" />
16+
<ProjectReference Include="$(SolutionDir)tests/Testcontainers.Commons/Testcontainers.Commons.csproj" />
17+
</ItemGroup>
18+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
global using System;
2+
global using System.Net;
3+
global using System.Text;
4+
global using System.Threading.Tasks;
5+
global using Consul;
6+
global using DotNet.Testcontainers.Commons;
7+
global using Xunit;

0 commit comments

Comments
 (0)