-
-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Andre Hofmeister <[email protected]>
- Loading branch information
1 parent
13dcbe4
commit 7715969
Showing
17 changed files
with
465 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Db2 | ||
|
||
[Db2](https://www.ibm.com/db2) is a relational database engine developed by IBM. | ||
|
||
Add the following dependency to your project file: | ||
|
||
```shell title="NuGet" | ||
dotnet add package Testcontainers.Db2 | ||
``` | ||
|
||
!!! warning | ||
|
||
The Linux client dependency, [Net.IBM.Data.Db2-lnx](https://www.nuget.org/packages/Net.IBM.Data.Db2-lnx), requires additional configurations. We use the [Testcontainers.Db2.Tests.targets](https://github.com/testcontainers/testcontainers-dotnet/blob/develop/tests/Testcontainers.Db2.Tests/Testcontainers.Db2.Tests.targets) file to configure the environment variables: `LD_LIBRARY_PATH`, `PATH`, `DB2_CLI_DRIVER_INSTALL_PATH`, at runtime. | ||
|
||
You can start an Db2 container instance from any .NET application. This example uses xUnit.net's `IAsyncLifetime` interface to manage the lifecycle of the container. The container is started in the `InitializeAsync` method before the test method runs, ensuring that the environment is ready for testing. After the test completes, the container is removed in the `DisposeAsync` method. | ||
|
||
=== "Usage Example" | ||
```csharp | ||
--8<-- "tests/Testcontainers.Db2.Tests/Db2ContainerTest.cs:UseDb2Container" | ||
``` | ||
|
||
The test example uses the following NuGet dependencies: | ||
|
||
=== "Package References" | ||
```xml | ||
--8<-- "tests/Testcontainers.Db2.Tests/Testcontainers.Db2.Tests.csproj:PackageReferences" | ||
``` | ||
|
||
To execute the tests, use the command `dotnet test` from a terminal. | ||
|
||
--8<-- "docs/modules/_call_out_test_projects.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
root = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
namespace Testcontainers.Db2; | ||
|
||
/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" /> | ||
[PublicAPI] | ||
public sealed class Db2Builder : ContainerBuilder<Db2Builder, Db2Container, Db2Configuration> | ||
{ | ||
public const string Db2Image = "icr.io/db2_community/db2:12.1.0.0"; | ||
|
||
public const ushort Db2Port = 50000; | ||
|
||
public const string DefaultDatabase = "test"; | ||
|
||
public const string DefaultUsername = "db2inst1"; | ||
|
||
public const string DefaultPassword = "db2inst1"; | ||
|
||
private const string AcceptLicenseAgreementEnvVar = "LICENSE"; | ||
|
||
private const string AcceptLicenseAgreement = "accept"; | ||
|
||
private const string DeclineLicenseAgreement = "decline"; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Db2Builder" /> class. | ||
/// </summary> | ||
public Db2Builder() | ||
: this(new Db2Configuration()) | ||
{ | ||
DockerResourceConfiguration = Init().DockerResourceConfiguration; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Db2Builder" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
private Db2Builder(Db2Configuration resourceConfiguration) | ||
: base(resourceConfiguration) | ||
{ | ||
DockerResourceConfiguration = resourceConfiguration; | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override Db2Configuration DockerResourceConfiguration { get; } | ||
|
||
/// <summary> | ||
/// Accepts the license agreement. | ||
/// </summary> | ||
/// <remarks> | ||
/// When <paramref name="acceptLicenseAgreement" /> is set to <c>true</c>, the Db2 <see href="www.ibm.com/terms/?id=L-SNMD-UVTL8R">license</see> is accepted. | ||
/// </remarks> | ||
/// <param name="acceptLicenseAgreement">A boolean value indicating whether the Db2 license agreement is accepted.</param> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithAcceptLicenseAgreement(bool acceptLicenseAgreement) | ||
{ | ||
var licenseAgreement = acceptLicenseAgreement ? AcceptLicenseAgreement : DeclineLicenseAgreement; | ||
return WithEnvironment(AcceptLicenseAgreementEnvVar, licenseAgreement); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the Db2 database name. | ||
/// </summary> | ||
/// <param name="database">The Db2 database.</param> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithDatabase(string database) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(database: database)) | ||
.WithEnvironment("DBNAME", database); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the Db2 username. | ||
/// </summary> | ||
/// <param name="username">The Db2 username.</param> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithUsername(string username) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(username: username)) | ||
.WithEnvironment("DB2INSTANCE", username) | ||
.WithTmpfsMount(string.Join("/", string.Empty, "home", username, "data")); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the Db2 password. | ||
/// </summary> | ||
/// <param name="password">The Db2 password.</param> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithPassword(string password) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(password: password)) | ||
.WithEnvironment("DB2INST1_PASSWORD", password); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override Db2Container Build() | ||
{ | ||
Validate(); | ||
return new Db2Container(DockerResourceConfiguration); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override Db2Builder Init() => base.Init() | ||
.WithImage(Db2Image) | ||
.WithPortBinding(Db2Port, true) | ||
.WithDatabase(DefaultDatabase) | ||
.WithUsername(DefaultUsername) | ||
.WithPassword(DefaultPassword) | ||
.WithPrivileged(true) | ||
.WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("Setup has completed.")); | ||
|
||
/// <inheritdoc /> | ||
protected override void Validate() | ||
{ | ||
const string message = "The image '{0}' requires you to accept a license agreement."; | ||
|
||
base.Validate(); | ||
|
||
Predicate<Db2Configuration> licenseAgreementNotAccepted = value => | ||
!value.Environments.TryGetValue(AcceptLicenseAgreementEnvVar, out var licenseAgreementValue) || !AcceptLicenseAgreement.Equals(licenseAgreementValue, StringComparison.Ordinal); | ||
|
||
_ = Guard.Argument(DockerResourceConfiguration, nameof(DockerResourceConfiguration.Image)) | ||
.ThrowIf(argument => licenseAgreementNotAccepted(argument.Value), argument => throw new ArgumentException(string.Format(message, DockerResourceConfiguration.Image.FullName), argument.Name)); | ||
|
||
_ = Guard.Argument(DockerResourceConfiguration.Username, nameof(DockerResourceConfiguration.Username)) | ||
.NotNull() | ||
.NotEmpty(); | ||
|
||
_ = Guard.Argument(DockerResourceConfiguration.Password, nameof(DockerResourceConfiguration.Password)) | ||
.NotNull() | ||
.NotEmpty(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override Db2Builder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(resourceConfiguration)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override Db2Builder Clone(IContainerConfiguration resourceConfiguration) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(resourceConfiguration)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override Db2Builder Merge(Db2Configuration oldValue, Db2Configuration newValue) | ||
{ | ||
return new Db2Builder(new Db2Configuration(oldValue, newValue)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
namespace Testcontainers.Db2; | ||
|
||
/// <inheritdoc cref="ContainerConfiguration" /> | ||
[PublicAPI] | ||
public sealed class Db2Configuration : ContainerConfiguration | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Db2Configuration" /> class. | ||
/// </summary> | ||
/// <param name="database">The Db2 database.</param> | ||
/// <param name="username">The Db2 username.</param> | ||
/// <param name="password">The Db2 password.</param> | ||
public Db2Configuration( | ||
string database = null, | ||
string username = null, | ||
string password = null) | ||
{ | ||
Database = database; | ||
Username = username; | ||
Password = password; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Db2Configuration" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
public Db2Configuration(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="Db2Configuration" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
public Db2Configuration(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="Db2Configuration" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
public Db2Configuration(Db2Configuration resourceConfiguration) | ||
: this(new Db2Configuration(), resourceConfiguration) | ||
{ | ||
// Passes the configuration upwards to the base implementations to create an updated immutable copy. | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Db2Configuration" /> class. | ||
/// </summary> | ||
/// <param name="oldValue">The old Docker resource configuration.</param> | ||
/// <param name="newValue">The new Docker resource configuration.</param> | ||
public Db2Configuration(Db2Configuration oldValue, Db2Configuration newValue) | ||
: base(oldValue, newValue) | ||
{ | ||
Database = BuildConfiguration.Combine(oldValue.Database, newValue.Database); | ||
Username = BuildConfiguration.Combine(oldValue.Username, newValue.Username); | ||
Password = BuildConfiguration.Combine(oldValue.Password, newValue.Password); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the Db2 database. | ||
/// </summary> | ||
public string Database { get; } | ||
|
||
/// <summary> | ||
/// Gets the Db2 username. | ||
/// </summary> | ||
public string Username { get; } | ||
|
||
/// <summary> | ||
/// Gets the Db2 password. | ||
/// </summary> | ||
public string Password { get; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
namespace Testcontainers.Db2; | ||
|
||
/// <inheritdoc cref="DockerContainer" /> | ||
[PublicAPI] | ||
public sealed class Db2Container : DockerContainer, IDatabaseContainer | ||
{ | ||
private readonly Db2Configuration _configuration; | ||
|
||
public Db2Container(Db2Configuration configuration) : base(configuration) | ||
{ | ||
_configuration = configuration; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the Db2 connection string. | ||
/// </summary> | ||
/// <returns>The Db2 connection string.</returns> | ||
public string GetConnectionString() | ||
{ | ||
var properties = new Dictionary<string, string>(); | ||
properties.Add("Server", Hostname + ":" + GetMappedPublicPort(Db2Builder.Db2Port)); | ||
properties.Add("Database", _configuration.Database); | ||
properties.Add("UID", _configuration.Username); | ||
properties.Add("PWD", _configuration.Password); | ||
return string.Join(";", properties.Select(property => string.Join("=", property.Key, property.Value))); | ||
} | ||
|
||
/// <summary> | ||
/// Executes the SQL script in the Db2 container. | ||
/// </summary> | ||
/// <param name="scriptContent">The content of the SQL script to execute.</param> | ||
/// <param name="ct">Cancellation token.</param> | ||
/// <returns>Task that completes when the SQL script has been executed.</returns> | ||
public async Task<ExecResult> ExecScriptAsync(string scriptContent, CancellationToken ct = default) | ||
{ | ||
const string db2ShellCommandFormat = "su - {1} -c \"db2 connect to {0} && db2 -tvf '{2}'\""; | ||
|
||
var scriptFilePath = string.Join("/", string.Empty, "tmp", Guid.NewGuid().ToString("D"), Path.GetRandomFileName()); | ||
|
||
var db2ShellCommand = string.Format(db2ShellCommandFormat, _configuration.Database, _configuration.Username, scriptFilePath); | ||
|
||
await CopyAsync(Encoding.Default.GetBytes(scriptContent), scriptFilePath, Unix.FileMode644, ct) | ||
.ConfigureAwait(false); | ||
|
||
return await ExecAsync(new [] { "/bin/sh", "-c", db2ShellCommand}, ct) | ||
.ConfigureAwait(false); | ||
} | ||
} |
Oops, something went wrong.