-
-
Notifications
You must be signed in to change notification settings - Fork 274
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
root = true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
using System.Text; | ||
using Testcontainers.Pulsar; | ||
|
||
/// <inheritdoc cref="ContainerBuilder{TBuilderEntity, TContainerEntity, TConfigurationEntity}" /> | ||
[PublicAPI] | ||
public sealed class PulsarBuilder : ContainerBuilder<PulsarBuilder, PulsarContainer, PulsarConfiguration> | ||
{ | ||
private const string AuthenticationPlugin = "org.apache.pulsar.client.impl.auth.AuthenticationToken"; | ||
private const string SecretKeyPath = "/pulsar/secret.key"; | ||
private const string UserName = "test-user"; | ||
private const string PulsarImage = "apachepulsar/pulsar:3.0.2"; | ||
private const string AdminClustersEndpoint = "/admin/v2/clusters"; | ||
internal const string Enabled = "Enabled"; | ||
|
||
private Dictionary<string, string> _environmentVariables = new Dictionary<string, string> | ||
{ | ||
{ "PULSAR_PREFIX_tokenSecretKey", $"file://{SecretKeyPath}" }, | ||
{ "PULSAR_PREFIX_authenticationRefreshCheckSeconds", "5" }, | ||
{ "superUserRoles", UserName }, | ||
{ "authenticationEnabled", "true" }, | ||
{ "authorizationEnabled", "true" }, | ||
{ "authenticationProviders", "org.apache.pulsar.broker.authentication.AuthenticationProviderToken" }, | ||
{ "authenticateOriginalAuthData", "false" }, | ||
{ "brokerClientAuthenticationPlugin", AuthenticationPlugin }, | ||
{ "CLIENT_PREFIX_authPlugin", AuthenticationPlugin } | ||
}; | ||
|
||
public const ushort PulsarBrokerPort = 6650; | ||
public const ushort PulsarBrokerHttpPort = 8080; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PulsarBuilder" /> class. | ||
/// </summary> | ||
public PulsarBuilder() | ||
: this(new PulsarConfiguration()) | ||
{ | ||
DockerResourceConfiguration = Init().DockerResourceConfiguration; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PulsarBuilder" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
private PulsarBuilder(PulsarConfiguration resourceConfiguration) | ||
: base(resourceConfiguration) | ||
{ | ||
DockerResourceConfiguration = resourceConfiguration; | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override PulsarConfiguration DockerResourceConfiguration { get; } | ||
|
||
/// <inheritdoc /> | ||
public override PulsarContainer Build() | ||
{ | ||
Validate(); | ||
var pulsarStartupCommands = String.Empty; | ||
if (DockerResourceConfiguration.Authentication == Enabled) | ||
{ | ||
pulsarStartupCommands = $"bin/pulsar tokens create-secret-key --output {SecretKeyPath} && " + | ||
$"export brokerClientAuthenticationParameters=token:$(bin/pulsar tokens create --secret-key {SecretKeyPath} --subject {UserName}) && " + | ||
$"export CLIENT_PREFIX_authParams=$brokerClientAuthenticationParameters && bin/apply-config-from-env.py conf/standalone.conf && " + | ||
$"bin/apply-config-from-env-with-prefix.py CLIENT_PREFIX_ conf/client.conf && "; | ||
} | ||
pulsarStartupCommands += "bin/pulsar standalone"; | ||
|
||
if (DockerResourceConfiguration.Functions != Enabled) | ||
pulsarStartupCommands += " --no-functions-worker"; | ||
|
||
var pulsarBuilder = WithCommand("/bin/bash", "-c",pulsarStartupCommands); | ||
return new PulsarContainer(pulsarBuilder.DockerResourceConfiguration, TestcontainersSettings.Logger); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override PulsarBuilder Init() | ||
{ | ||
return base.Init() | ||
.WithImage(PulsarImage) | ||
.WithPortBinding(PulsarBrokerPort, true) | ||
.WithPortBinding(PulsarBrokerHttpPort, true) | ||
.WithWaitStrategy(Wait.ForUnixContainer() | ||
.UntilCommandIsCompleted(["/bin/bash", "-c", "bin/pulsar-admin clusters list"])); | ||
} | ||
|
||
public PulsarBuilder WithTokenAuthentication() | ||
{ | ||
return Merge(DockerResourceConfiguration, new PulsarConfiguration(authentication: Enabled)) | ||
.WithEnvironment(_environmentVariables); | ||
} | ||
|
||
public PulsarBuilder WithFunctions() | ||
{ | ||
return Merge(DockerResourceConfiguration, new PulsarConfiguration(functions: Enabled)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override PulsarBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration) | ||
{ | ||
return Merge(DockerResourceConfiguration, new PulsarConfiguration(resourceConfiguration)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override PulsarBuilder Clone(IContainerConfiguration resourceConfiguration) | ||
{ | ||
return Merge(DockerResourceConfiguration, new PulsarConfiguration(resourceConfiguration)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override PulsarBuilder Merge(PulsarConfiguration oldValue, PulsarConfiguration newValue) | ||
{ | ||
return new PulsarBuilder(new PulsarConfiguration(oldValue, newValue)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
namespace Testcontainers.Pulsar; | ||
|
||
/// <inheritdoc cref="ContainerConfiguration" /> | ||
[PublicAPI] | ||
public sealed class PulsarConfiguration : ContainerConfiguration | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PulsarConfiguration" /> class. | ||
/// </summary> | ||
public PulsarConfiguration(string authentication = null, | ||
Check warning on line 10 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 10 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 10 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (windows-2022)
|
||
string functions = null) | ||
Check warning on line 11 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 11 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 11 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (windows-2022)
|
||
{ | ||
Authentication = authentication; | ||
Functions = functions; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PulsarConfiguration" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
public PulsarConfiguration(IResourceConfiguration<CreateContainerParameters> resourceConfiguration) | ||
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (windows-2022)
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (windows-2022)
Check warning on line 21 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (windows-2022)
|
||
: 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="PulsarConfiguration" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
public PulsarConfiguration(IContainerConfiguration resourceConfiguration) | ||
Check warning on line 31 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 31 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (ubuntu-22.04)
Check warning on line 31 in src/Testcontainers.Pulsar/PulsarConfiguration.cs GitHub Actions / build (windows-2022)
|
||
: 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="PulsarConfiguration" /> class. | ||
/// </summary> | ||
/// <param name="resourceConfiguration">The Docker resource configuration.</param> | ||
public PulsarConfiguration(PulsarConfiguration resourceConfiguration) | ||
: this(new PulsarConfiguration(), resourceConfiguration) | ||
{ | ||
// Passes the configuration upwards to the base implementations to create an updated immutable copy. | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PulsarConfiguration" /> class. | ||
/// </summary> | ||
/// <param name="oldValue">The old Docker resource configuration.</param> | ||
/// <param name="newValue">The new Docker resource configuration.</param> | ||
public PulsarConfiguration(PulsarConfiguration oldValue, PulsarConfiguration newValue) | ||
: base(oldValue, newValue) | ||
{ | ||
Authentication = BuildConfiguration.Combine(oldValue.Authentication, newValue.Authentication); | ||
Functions = BuildConfiguration.Combine(oldValue.Functions, newValue.Functions); | ||
} | ||
|
||
/// <summary> | ||
/// Gets authentication. | ||
/// </summary> | ||
public string Authentication { get; } | ||
|
||
/// <summary> | ||
/// Gets functions. | ||
/// </summary> | ||
public string Functions { get; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
namespace Testcontainers.Pulsar; | ||
|
||
/// <inheritdoc cref="DockerContainer" /> | ||
[PublicAPI] | ||
public sealed class PulsarContainer : DockerContainer | ||
{ | ||
private readonly PulsarConfiguration _configuration; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="PulsarContainer" /> class. | ||
/// </summary> | ||
/// <param name="configuration">The container configuration.</param> | ||
/// <param name="logger">The logger.</param> | ||
public PulsarContainer(PulsarConfiguration configuration, ILogger logger) | ||
: base(configuration, logger) | ||
{ | ||
_configuration = configuration; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the Pulsar broker url. | ||
/// </summary> | ||
/// <returns>The Pulsar broker url.</returns> | ||
public string GetPulsarBrokerUrl() => | ||
new UriBuilder("pulsar://", Hostname, GetMappedPublicPort(PulsarBuilder.PulsarBrokerPort)).ToString(); | ||
|
||
/// <summary> | ||
/// Gets the Pulsar service url. | ||
/// </summary> | ||
/// <returns>The Pulsar service url.</returns> | ||
public string GetHttpServiceUrl() => | ||
new UriBuilder("http", Hostname, GetMappedPublicPort(PulsarBuilder.PulsarBrokerHttpPort)).ToString(); | ||
|
||
/// <summary> | ||
/// Creates Authentication token | ||
/// </summary> | ||
/// <param name="expiryTime">Relative expiry time for the token (eg: 1h, 3d, 10y)</param> | ||
/// <param name="cancellationToken"></param> | ||
/// <returns>Authentication token</returns> | ||
/// <exception cref="Exception"></exception> | ||
public async Task<string> CreateToken(TimeSpan expiryTime, CancellationToken cancellationToken = default) | ||
{ | ||
if (_configuration.Authentication != PulsarBuilder.Enabled) | ||
throw new Exception($"Could not create the token, because WithAuthentication is not used."); | ||
|
||
var arguments = $"bin/pulsar tokens create --secret-key /pulsar/secret.key --subject test-user"; | ||
|
||
if (expiryTime != Timeout.InfiniteTimeSpan) | ||
arguments += $" --expiry-time {expiryTime.TotalSeconds}s"; | ||
|
||
var result = await ExecAsync(new[] { "/bin/bash", "-c", arguments }, cancellationToken); | ||
|
||
if (result.ExitCode != 0) | ||
throw new Exception($"Could not create the token: {result.Stderr}"); | ||
|
||
return result.Stdout; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<TargetFrameworks>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> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
global using System; | ||
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 Microsoft.Extensions.Logging; |