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
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
<PackageVersion Include="Microsoft.Playwright" Version="1.55.0"/>
<PackageVersion Include="Milvus.Client" Version="2.2.2-preview.6"/>
<PackageVersion Include="MongoDB.Driver" Version="3.2.0"/>
<PackageVersion Include="MQTTnet" Version="5.0.1.1416"/>
<PackageVersion Include="MyCouch" Version="7.6.0"/>
<PackageVersion Include="MySqlConnector" Version="2.2.5"/>
<PackageVersion Include="NATS.Client" Version="1.0.8"/>
Expand Down
1 change: 1 addition & 0 deletions Testcontainers.dic
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ lipsum
ltsc
memopt
mongosh
mosquitto
mycounter
mydatabase
myregistry
Expand Down
14 changes: 14 additions & 0 deletions Testcontainers.sln
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Minio", "src
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MongoDb", "src\Testcontainers.MongoDb\Testcontainers.MongoDb.csproj", "{2613F146-6C66-4059-9D37-D48BA6B61515}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Mosquitto", "src\Testcontainers.Mosquitto\Testcontainers.Mosquitto.csproj", "{3A64B210-645C-4229-B089-5BB2AAFCF535}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MsSql", "src\Testcontainers.MsSql\Testcontainers.MsSql.csproj", "{121FB123-40D9-44D4-9AB7-AD57ED34F466}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MySql", "src\Testcontainers.MySql\Testcontainers.MySql.csproj", "{9FDCFAEA-AE42-4C69-89EF-F1FF75E88CCC}"
Expand Down Expand Up @@ -210,6 +212,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Minio.Tests"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MongoDb.Tests", "tests\Testcontainers.MongoDb.Tests\Testcontainers.MongoDb.Tests.csproj", "{82A7E7B8-3187-4CAE-845B-0BF43409B38A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Mosquitto.Tests", "tests\Testcontainers.Mosquitto.Tests\Testcontainers.Mosquitto.Tests.csproj", "{6314B57A-EE0C-4C3B-A9A9-64D68A47312A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MsSql.Tests", "tests\Testcontainers.MsSql.Tests\Testcontainers.MsSql.Tests.csproj", "{25DBED78-99F4-433F-BBF5-1B4E9DEAE437}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MySql.Tests", "tests\Testcontainers.MySql.Tests\Testcontainers.MySql.Tests.csproj", "{E42DA1CE-698F-4E45-8D1F-5D5895893840}"
Expand Down Expand Up @@ -418,6 +422,10 @@ Global
{2613F146-6C66-4059-9D37-D48BA6B61515}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2613F146-6C66-4059-9D37-D48BA6B61515}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2613F146-6C66-4059-9D37-D48BA6B61515}.Release|Any CPU.Build.0 = Release|Any CPU
{3A64B210-645C-4229-B089-5BB2AAFCF535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A64B210-645C-4229-B089-5BB2AAFCF535}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A64B210-645C-4229-B089-5BB2AAFCF535}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A64B210-645C-4229-B089-5BB2AAFCF535}.Release|Any CPU.Build.0 = Release|Any CPU
{121FB123-40D9-44D4-9AB7-AD57ED34F466}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{121FB123-40D9-44D4-9AB7-AD57ED34F466}.Debug|Any CPU.Build.0 = Debug|Any CPU
{121FB123-40D9-44D4-9AB7-AD57ED34F466}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -662,6 +670,10 @@ Global
{82A7E7B8-3187-4CAE-845B-0BF43409B38A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{82A7E7B8-3187-4CAE-845B-0BF43409B38A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{82A7E7B8-3187-4CAE-845B-0BF43409B38A}.Release|Any CPU.Build.0 = Release|Any CPU
{6314B57A-EE0C-4C3B-A9A9-64D68A47312A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6314B57A-EE0C-4C3B-A9A9-64D68A47312A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6314B57A-EE0C-4C3B-A9A9-64D68A47312A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6314B57A-EE0C-4C3B-A9A9-64D68A47312A}.Release|Any CPU.Build.0 = Release|Any CPU
{25DBED78-99F4-433F-BBF5-1B4E9DEAE437}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25DBED78-99F4-433F-BBF5-1B4E9DEAE437}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25DBED78-99F4-433F-BBF5-1B4E9DEAE437}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -834,6 +846,7 @@ Global
{B024E315-831F-429D-92AA-44B839AC10F4} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{1266E1E6-5CEF-4161-8B45-83282455746E} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{2613F146-6C66-4059-9D37-D48BA6B61515} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{3A64B210-645C-4229-B089-5BB2AAFCF535} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{121FB123-40D9-44D4-9AB7-AD57ED34F466} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{9FDCFAEA-AE42-4C69-89EF-F1FF75E88CCC} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
{BF37BEA1-0816-4326-B1E0-E82290F8FCE0} = {673F23AE-7694-4BB9-ABD4-136D6C13634E}
Expand Down Expand Up @@ -895,6 +908,7 @@ Global
{5247DF94-32F3-4ED6-AE71-6AB4F4078E6D} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{5DB1F35F-B714-4B62-84BE-16A33084D3E1} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{82A7E7B8-3187-4CAE-845B-0BF43409B38A} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{6314B57A-EE0C-4C3B-A9A9-64D68A47312A} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{25DBED78-99F4-433F-BBF5-1B4E9DEAE437} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{E42DA1CE-698F-4E45-8D1F-5D5895893840} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
{87A3F137-6DC3-4CE5-91E6-01797D076086} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF}
Expand Down
1 change: 1 addition & 0 deletions Testcontainers.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=ltsc/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=memopt/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mongosh/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mosquitto/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mycounter/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mydatabase/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=myregistry/@EntryIndexedValue">True</s:Boolean>
Expand Down
1 change: 1 addition & 0 deletions docs/modules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ await moduleNameContainer.StartAsync();
| Milvus | `milvusdb/milvus:v2.3.10` | [NuGet](https://www.nuget.org/packages/Testcontainers.Milvus) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Milvus) |
| MinIO | `minio/minio:RELEASE.2023-01-31T02-24-19Z` | [NuGet](https://www.nuget.org/packages/Testcontainers.Minio) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Minio) |
| MongoDB | `mongo:6.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.MongoDb) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.MongoDb) |
| Mosquitto | `eclipse-mosquitto:2.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.Mosquitto) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Mosquitto) |
| MySQL | `mysql:8.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.MySql) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.MySql) |
| NATS | `nats:2.9` | [NuGet](https://www.nuget.org/packages/Testcontainers.Nats) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Nats) |
| Neo4j | `neo4j:5.4` | [NuGet](https://www.nuget.org/packages/Testcontainers.Neo4j) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Neo4j) |
Expand Down
1 change: 1 addition & 0 deletions src/Testcontainers.Mosquitto/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
root = true
139 changes: 139 additions & 0 deletions src/Testcontainers.Mosquitto/MosquittoBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
namespace Testcontainers.Mosquitto;

/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" />
[PublicAPI]
public sealed class MosquittoBuilder : ContainerBuilder<MosquittoBuilder, MosquittoContainer, MosquittoConfiguration>
{
public const string MosquittoImage = "eclipse-mosquitto:2.0";

public const ushort MqttPort = 1883;

public const ushort MqttTlsPort = 8883;

public const ushort MqttWsPort = 8080;

public const ushort MqttWssPort = 8081;

public const string CertificateFilePath = "/etc/mosquitto/certs/server.crt";

public const string CertificateKeyFilePath = "/etc/mosquitto/certs/server.key";

/// <summary>
/// Initializes a new instance of the <see cref="MosquittoBuilder" /> class.
/// </summary>
public MosquittoBuilder()
: this(new MosquittoConfiguration())
{
DockerResourceConfiguration = Init().DockerResourceConfiguration;
}

/// <summary>
/// Initializes a new instance of the <see cref="MosquittoBuilder" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public MosquittoBuilder(MosquittoConfiguration resourceConfiguration)
: base(resourceConfiguration)
{
DockerResourceConfiguration = resourceConfiguration;
}

/// <inheritdoc />
protected override MosquittoConfiguration DockerResourceConfiguration { get; }

/// <summary>
/// Sets the public certificate and private key to enable TLS.
/// </summary>
/// <param name="certificate">The public certificate in PEM format.</param>
/// <param name="certificateKey">The private key associated with the certificate in PEM format.</param>
/// <returns>A configured instance of <see cref="MosquittoBuilder" />.</returns>
public MosquittoBuilder WithCertificate(string certificate, string certificateKey)
{
return Merge(DockerResourceConfiguration, new MosquittoConfiguration(certificate: certificate, certificateKey: certificateKey))
.WithPortBinding(MqttTlsPort, true)
.WithPortBinding(MqttWssPort, true)
.WithResourceMapping(Encoding.Default.GetBytes(certificate), CertificateFilePath)
.WithResourceMapping(Encoding.Default.GetBytes(certificateKey), CertificateKeyFilePath);
}

/// <inheritdoc />
public override MosquittoContainer Build()
{
Validate();

// Maybe we should move this into the startup callback.
var mosquittoConfig = new StringWriter();
mosquittoConfig.NewLine = "\n";

mosquittoConfig.WriteLine("per_listener_settings true");
mosquittoConfig.WriteLine("log_dest stdout");
mosquittoConfig.WriteLine("log_type information");

mosquittoConfig.WriteLine();
mosquittoConfig.WriteLine("persistence false");
mosquittoConfig.WriteLine("persistence_location /mosquitto/data/");

mosquittoConfig.WriteLine();
mosquittoConfig.WriteLine("# MQTT, unencrypted, unauthenticated");
mosquittoConfig.WriteLine($"listener {MqttPort} 0.0.0.0");
mosquittoConfig.WriteLine("protocol mqtt");
mosquittoConfig.WriteLine("allow_anonymous true");

mosquittoConfig.WriteLine();
mosquittoConfig.WriteLine("# MQTT over WebSockets, unencrypted, unauthenticated");
mosquittoConfig.WriteLine($"listener {MqttWsPort} 0.0.0.0");
mosquittoConfig.WriteLine("protocol websockets");
mosquittoConfig.WriteLine("allow_anonymous true");

if (DockerResourceConfiguration.TlsEnabled)
{
mosquittoConfig.WriteLine();
mosquittoConfig.WriteLine("# MQTT, encrypted, unauthenticated");
mosquittoConfig.WriteLine($"listener {MqttTlsPort} 0.0.0.0");
mosquittoConfig.WriteLine("protocol mqtt");
mosquittoConfig.WriteLine("allow_anonymous true");
mosquittoConfig.WriteLine("tls_version tlsv1.2");
mosquittoConfig.WriteLine($"certfile {CertificateFilePath}");
mosquittoConfig.WriteLine($"keyfile {CertificateKeyFilePath}");

mosquittoConfig.WriteLine();
mosquittoConfig.WriteLine("# MQTT over WebSockets, encrypted, unauthenticated");
mosquittoConfig.WriteLine($"listener {MqttWssPort} 0.0.0.0");
mosquittoConfig.WriteLine("protocol websockets");
mosquittoConfig.WriteLine("allow_anonymous true");
mosquittoConfig.WriteLine("tls_version tlsv1.2");
mosquittoConfig.WriteLine($"certfile {CertificateFilePath}");
mosquittoConfig.WriteLine($"keyfile {CertificateKeyFilePath}");
}

var mosquittoBuilder = WithResourceMapping(Encoding.Default.GetBytes(mosquittoConfig.ToString()), "/mosquitto/config/mosquitto.conf");
return new MosquittoContainer(mosquittoBuilder.DockerResourceConfiguration);
}

/// <inheritdoc />
protected override MosquittoBuilder Init()
{
return base.Init()
.WithImage(MosquittoImage)
.WithPortBinding(MqttPort, true)
.WithPortBinding(MqttWsPort, true)
.WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("mosquitto.*running"));
}

/// <inheritdoc />
protected override MosquittoBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
{
return Merge(DockerResourceConfiguration, new MosquittoConfiguration(resourceConfiguration));
}

/// <inheritdoc />
protected override MosquittoBuilder Clone(IContainerConfiguration resourceConfiguration)
{
return Merge(DockerResourceConfiguration, new MosquittoConfiguration(resourceConfiguration));
}

/// <inheritdoc />
protected override MosquittoBuilder Merge(MosquittoConfiguration oldValue, MosquittoConfiguration newValue)
{
return new MosquittoBuilder(new MosquittoConfiguration(oldValue, newValue));
}
}
76 changes: 76 additions & 0 deletions src/Testcontainers.Mosquitto/MosquittoConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
namespace Testcontainers.Mosquitto;

/// <inheritdoc cref="ContainerConfiguration" />
[PublicAPI]
public sealed class MosquittoConfiguration : ContainerConfiguration
{
/// <summary>
/// Initializes a new instance of the <see cref="MosquittoConfiguration" /> class.
/// </summary>
/// <param name="certificate">The public certificate in PEM format.</param>
/// <param name="certificateKey">The private key associated with the certificate in PEM format.</param>
public MosquittoConfiguration(
string certificate = null,
string certificateKey = null)
{
Certificate = certificate;
CertificateKey = certificateKey;
}

/// <summary>
/// Initializes a new instance of the <see cref="MosquittoConfiguration" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public MosquittoConfiguration(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
: base(resourceConfiguration)
{
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
}

/// <summary>
/// Initializes a new instance of the <see cref="MosquittoConfiguration" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public MosquittoConfiguration(IContainerConfiguration resourceConfiguration)
: base(resourceConfiguration)
{
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
}

/// <summary>
/// Initializes a new instance of the <see cref="MosquittoConfiguration" /> class.
/// </summary>
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
public MosquittoConfiguration(MosquittoConfiguration resourceConfiguration)
: this(new MosquittoConfiguration(), resourceConfiguration)
{
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
}

/// <summary>
/// Initializes a new instance of the <see cref="MosquittoConfiguration" /> class.
/// </summary>
/// <param name="oldValue">The old Docker resource configuration.</param>
/// <param name="newValue">The new Docker resource configuration.</param>
public MosquittoConfiguration(MosquittoConfiguration oldValue, MosquittoConfiguration newValue)
: base(oldValue, newValue)
{
Certificate = BuildConfiguration.Combine(oldValue.Certificate, newValue.Certificate);
CertificateKey = BuildConfiguration.Combine(oldValue.CertificateKey, newValue.CertificateKey);
}

/// <summary>
/// Gets a value indicating whether TLS is enabled or not.
/// </summary>
public bool TlsEnabled => Certificate != null && CertificateKey != null;

/// <summary>
/// Gets the public certificate in PEM format.
/// </summary>
public string Certificate { get; }

/// <summary>
/// Gets the private key associated with the certificate in PEM format.
/// </summary>
public string CertificateKey { get; }
}
Loading