-
-
Notifications
You must be signed in to change notification settings - Fork 301
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
534 additions
and
96 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
Large diffs are not rendered by default.
Oops, something went wrong.
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,191 @@ | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
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:latest"; | ||
|
||
public const ushort Db2Port = 50000; | ||
|
||
public const string DefaultDatabase = "test"; | ||
|
||
public const string DefaultUsername = "db2inst1"; | ||
|
||
public const string DefaultPassword = "test123"; | ||
|
||
public const string DefaultLicenseAgreement = "accept"; | ||
|
||
/// <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> | ||
/// 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); | ||
} | ||
|
||
/// <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); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the Db2 archive logs. | ||
/// </summary> | ||
/// <param name="archiveLogs">The Db2 archive logs setting.</param> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithArchiveLogs(bool archiveLogs) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(archiveLogs: archiveLogs)) | ||
.WithEnvironment("ARCHIVE_LOGS", archiveLogs.ToString()); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the Db2 autoconfig setting. | ||
/// </summary> | ||
/// <param name="autoConfig">The Db2 autoconfig setting.</param> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithAutoconfig(bool autoConfig) | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(autoConfig: autoConfig)) | ||
.WithEnvironment("AUTOCONFIG", autoConfig.ToString()); | ||
} | ||
|
||
/// <summary> | ||
/// Accepts the Db2 license agreement. | ||
/// </summary> | ||
/// <returns>A configured instance of <see cref="Db2Builder" />.</returns> | ||
public Db2Builder WithLicenseAgreement() | ||
{ | ||
return Merge(DockerResourceConfiguration, new Db2Configuration(licenseAgreement: DefaultLicenseAgreement)) | ||
.WithEnvironment("LICENSE", DefaultLicenseAgreement); | ||
} | ||
|
||
/// <summary> | ||
/// <inheritdoc /> | ||
public override Db2Container Build() | ||
{ | ||
Validate(); | ||
|
||
// By default, the base builder waits until the container is running. However, for MySql, a more advanced waiting strategy is necessary that requires access to the configured database, username and password. | ||
// If the user does not provide a custom waiting strategy, append the default MySql waiting strategy. | ||
var db2Builder = DockerResourceConfiguration.WaitStrategies.Count() > 1 | ||
? this | ||
: WithWaitStrategy(Wait.ForUnixContainer() | ||
.UntilMessageIsLogged("All databases are now active") | ||
.UntilMessageIsLogged("Setup has completed.") | ||
.AddCustomWaitStrategy(new WaitUntil(DockerResourceConfiguration)) | ||
); | ||
|
||
return new Db2Container(db2Builder.DockerResourceConfiguration); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override Db2Builder Init() => base.Init() | ||
.WithImage(Db2Image) | ||
.WithPortBinding(Db2Port, true) | ||
.WithDatabase(DefaultDatabase) | ||
.WithUsername(DefaultUsername) | ||
.WithPassword(DefaultPassword) | ||
.WithLicenseAgreement() | ||
.WithPrivileged(true); | ||
|
||
/// <inheritdoc /> | ||
protected override void Validate() | ||
{ | ||
base.Validate(); | ||
|
||
_ = 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)); | ||
} | ||
|
||
/// <inheritdoc cref="IWaitUntil" /> | ||
private sealed class WaitUntil : IWaitUntil | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="WaitUntil" /> class. | ||
/// </summary> | ||
/// <param name="configuration">The container configuration.</param> | ||
public WaitUntil(Db2Configuration configuration) | ||
{ | ||
} | ||
|
||
/// <inheritdoc /> | ||
public async Task<bool> UntilAsync(IContainer container) | ||
{ | ||
var db2Container = (Db2Container)container; | ||
|
||
var execResult = await db2Container.ExecScriptAsync("SELECT 1 FROM SYSIBM.SYSDUMMY1").ConfigureAwait(false); | ||
|
||
return 0L.Equals(execResult.ExitCode); | ||
} | ||
} | ||
} |
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,96 @@ | ||
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> | ||
/// <param name="archiveLogs">The Db2 archive logs setting.</param> | ||
/// <param name="autoConfig">The Db2 auto config setting.</param> | ||
/// <param name="licenseAgreement">The Db2 license agreement.</param> | ||
public Db2Configuration( | ||
string database = null, | ||
string username = null, | ||
string password = null, | ||
bool archiveLogs = false, | ||
bool autoConfig = false, | ||
string licenseAgreement = null) | ||
{ | ||
Database = database; | ||
Username = username; | ||
Password = password; | ||
ArchiveLogs = archiveLogs; | ||
AutoConfig = autoConfig; | ||
LicenseAgreement = licenseAgreement; | ||
} | ||
|
||
/// <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; } | ||
|
||
public bool ArchiveLogs { get; } | ||
|
||
public bool AutoConfig { get; } | ||
|
||
public string LicenseAgreement { 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,42 @@ | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Testcontainers.Db2 | ||
{ | ||
/// <inheritdoc cref="DockerContainer" /> | ||
[PublicAPI] | ||
public sealed class Db2Container : DockerContainer, IDatabaseContainer | ||
{ | ||
private static string Db2CommandPath = "/opt/ibm/db2/*/bin/db2"; | ||
|
||
private readonly Db2Configuration _configuration; | ||
|
||
private const char ConnectionStringDelimiter = ';'; | ||
|
||
public Db2Container(Db2Configuration configuration) : base(configuration) | ||
{ | ||
_configuration = configuration; | ||
} | ||
|
||
public string GetConnectionString() => new StringBuilder() | ||
.Append("Server=").Append(Hostname).Append(":").Append(GetMappedPublicPort(Db2Builder.Db2Port).ToString()).Append(ConnectionStringDelimiter) | ||
.Append("Database=").Append(_configuration.Database).Append(ConnectionStringDelimiter) | ||
.Append("UID=").Append(_configuration.Username).Append(ConnectionStringDelimiter) | ||
.Append("PWD=").Append(_configuration.Password).Append(ConnectionStringDelimiter) | ||
.ToString(); | ||
|
||
public async Task<ExecResult> ExecScriptAsync(string scriptContent, CancellationToken cancellationToken = default) | ||
{ | ||
string[] command = ["su", "db2inst1", "-c", new StringBuilder() | ||
.Append(Db2CommandPath).Append(" connect to ").Append(_configuration.Database) | ||
.Append(" user ").Append(_configuration.Username).Append(" using ").Append(_configuration.Password) | ||
.Append("; ") | ||
.Append(Db2CommandPath).Append(" ").Append(scriptContent) | ||
.ToString() | ||
]; | ||
|
||
return await ExecAsync(command).ConfigureAwait(false); | ||
} | ||
} | ||
} |
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,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFrameworks>net6.0;net8.0;netstandard2.0;netstandard2.1</TargetFrameworks> | ||
<LangVersion>latest</LangVersion> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="JetBrains.Annotations" VersionOverride="2023.3.0" PrivateAssets="All"/> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="../Testcontainers/Testcontainers.csproj"/> | ||
</ItemGroup> | ||
</Project> |
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,7 @@ | ||
global using Docker.DotNet.Models; | ||
global using DotNet.Testcontainers; | ||
global using DotNet.Testcontainers.Builders; | ||
global using DotNet.Testcontainers.Configurations; | ||
global using DotNet.Testcontainers.Containers; | ||
global using JetBrains.Annotations; | ||
global using System; |
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 |
Oops, something went wrong.