Skip to content

Commit 99efb2c

Browse files
committed
feat: implement built-in and configurable azurite docker container into event hubs emulator
1 parent de5d54b commit 99efb2c

File tree

6 files changed

+93
-95
lines changed

6 files changed

+93
-95
lines changed

src/Testcontainers.EventHubs/EventHubsBuilder.cs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public sealed class EventHubsBuilder : ContainerBuilder<EventHubsBuilder, EventH
77
public const string EventHubsImage = "mcr.microsoft.com/azure-messaging/eventhubs-emulator:latest";
88

99
public const ushort EventHubsPort = 5672;
10+
11+
public const string AzuriteNetworkAlias = "azurite";
1012

1113
private const string AcceptLicenseAgreementEnvVar = "ACCEPT_EULA";
1214

@@ -50,39 +52,45 @@ public EventHubsBuilder WithConfigurationBuilder(ConfigurationBuilder configurat
5052
}
5153

5254
/// <summary>
53-
/// Sets the endpoint of the azurite blob service
55+
/// Accepts the license agreement.
5456
/// </summary>
55-
/// <param name="azuriteBlobEndpoint"></param>
56-
/// <returns></returns>
57-
public EventHubsBuilder WithAzuriteBlobEndpoint(string azuriteBlobEndpoint)
57+
/// <remarks>
58+
/// When <paramref name="acceptLicenseAgreement" /> is set to <c>true</c>, the Azure Event Hubs Emulator <see href="https://github.com/Azure/azure-event-hubs-emulator-installer/blob/main/EMULATOR_EULA.md">license</see> is accepted.
59+
/// </remarks>
60+
/// <param name="acceptLicenseAgreement">A boolean value indicating whether the Azure Event Hubs Emulator license agreement is accepted.</param>
61+
/// <returns>A configured instance of <see cref="EventHubsBuilder" />.</returns>
62+
public EventHubsBuilder WithAcceptLicenseAgreement(bool acceptLicenseAgreement)
5863
{
59-
return Merge(DockerResourceConfiguration, new EventHubsConfiguration(azuriteBlobEndpoint: azuriteBlobEndpoint))
60-
.WithEnvironment("BLOB_SERVER", azuriteBlobEndpoint);
64+
var licenseAgreement = acceptLicenseAgreement ? AcceptLicenseAgreement : DeclineLicenseAgreement;
65+
return WithEnvironment(AcceptLicenseAgreementEnvVar, licenseAgreement);
6166
}
6267

6368
/// <summary>
64-
/// Sets the endpoint of the azurite table service
69+
/// Sets the Azurite container for the Event Hubs Emulator.
6570
/// </summary>
66-
/// <param name="azuriteTableEndpoint"></param>
71+
/// <param name="azuriteContainer">docker container</param>
72+
/// <param name="blobEndpoint">blob endpoint</param>
73+
/// <param name="tableEndpoint">table endpoint</param>
6774
/// <returns></returns>
68-
public EventHubsBuilder WithAzuriteTableEndpoint(string azuriteTableEndpoint)
75+
public EventHubsBuilder WithAzurite(AzuriteContainer azuriteContainer, string blobEndpoint, string tableEndpoint)
6976
{
70-
return Merge(DockerResourceConfiguration, new EventHubsConfiguration(azuriteTableEndpoint: azuriteTableEndpoint))
71-
.WithEnvironment("METADATA_SERVER", azuriteTableEndpoint);
77+
return Merge(DockerResourceConfiguration, new EventHubsConfiguration(azuriteContainer: azuriteContainer))
78+
.DependsOn(azuriteContainer)
79+
.WithEnvironment("BLOB_SERVER", blobEndpoint)
80+
.WithEnvironment("METADATA_SERVER", tableEndpoint);
7281
}
7382

7483
/// <summary>
75-
/// Accepts the license agreement.
84+
/// Sets the default Azurite container for the Event Hubs Emulator.
7685
/// </summary>
77-
/// <remarks>
78-
/// When <paramref name="acceptLicenseAgreement" /> is set to <c>true</c>, the Azure Event Hubs Emulator <see href="https://github.com/Azure/azure-event-hubs-emulator-installer/blob/main/EMULATOR_EULA.md">license</see> is accepted.
79-
/// </remarks>
80-
/// <param name="acceptLicenseAgreement">A boolean value indicating whether the Azure Event Hubs Emulator license agreement is accepted.</param>
81-
/// <returns>A configured instance of <see cref="EventHubsBuilder" />.</returns>
82-
public EventHubsBuilder WithAcceptLicenseAgreement(bool acceptLicenseAgreement)
86+
public EventHubsBuilder WithAzurite()
8387
{
84-
var licenseAgreement = acceptLicenseAgreement ? AcceptLicenseAgreement : DeclineLicenseAgreement;
85-
return WithEnvironment(AcceptLicenseAgreementEnvVar, licenseAgreement);
88+
var azuriteContainer = new AzuriteBuilder()
89+
.WithNetwork(DockerResourceConfiguration.Networks.Single())
90+
.WithNetworkAliases(AzuriteNetworkAlias)
91+
.Build();
92+
93+
return WithAzurite(azuriteContainer, AzuriteNetworkAlias, AzuriteNetworkAlias);
8694
}
8795

8896
/// <inheritdoc />
@@ -105,31 +113,22 @@ protected override void Validate()
105113
nameof(DockerResourceConfiguration.ConfigurationBuilder))
106114
.NotNull()
107115
.ThrowIf(x => !x.Value.Validate(), _ => throw new ArgumentException("ConfigurationBuilder is invalid."));
108-
109-
_ = Guard.Argument(DockerResourceConfiguration.AzuriteBlobEndpoint,
110-
nameof(DockerResourceConfiguration.AzuriteBlobEndpoint))
111-
.NotNull()
112-
.NotEmpty();
113116

114-
_ = Guard.Argument(DockerResourceConfiguration.AzuriteTableEndpoint,
115-
nameof(DockerResourceConfiguration.AzuriteTableEndpoint))
116-
.NotNull()
117-
.NotEmpty();
118117
return;
119118

120119
bool LicenseAgreementNotAccepted(EventHubsConfiguration value) =>
121120
!value.Environments.TryGetValue(AcceptLicenseAgreementEnvVar, out var licenseAgreementValue) ||
122121
!AcceptLicenseAgreement.Equals(licenseAgreementValue, StringComparison.Ordinal);
123122
}
124123

125-
126-
127124
/// <inheritdoc />
128125
protected override EventHubsBuilder Init()
129126
{
130127
return base.Init()
131128
.WithImage(EventHubsImage)
129+
.WithNetwork(new NetworkBuilder().Build())
132130
.WithPortBinding(EventHubsPort, true)
131+
.WithAzurite()
133132
.WithWaitStrategy(Wait.ForUnixContainer()
134133
.UntilMessageIsLogged("Emulator Service is Successfully Up!")
135134
.AddCustomWaitStrategy(new WaitTwoSeconds()));;

src/Testcontainers.EventHubs/EventHubsConfiguration.cs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Testcontainers.Azurite;
2+
13
namespace Testcontainers.EventHubs;
24

35
/// <inheritdoc cref="ContainerConfiguration" />
@@ -7,17 +9,13 @@ public sealed class EventHubsConfiguration : ContainerConfiguration
79
/// <summary>
810
/// Initializes a new instance of the <see cref="EventHubsConfiguration" /> class.
911
/// </summary>
12+
/// <param name="azuriteContainer">The Azurite docker container.</param>
1013
/// <param name="configurationBuilder">The configuration builder.</param>
11-
/// <param name="azuriteBlobEndpoint">The Azurite blob endpoint.</param>
12-
/// <param name="azuriteTableEndpoint">The Azurite table endpoint.</param>
13-
public EventHubsConfiguration(
14-
ConfigurationBuilder configurationBuilder = null,
15-
string azuriteBlobEndpoint = null,
16-
string azuriteTableEndpoint = null)
14+
public EventHubsConfiguration(AzuriteContainer azuriteContainer = null,
15+
ConfigurationBuilder configurationBuilder = null)
1716
{
1817
ConfigurationBuilder = configurationBuilder;
19-
AzuriteBlobEndpoint = azuriteBlobEndpoint;
20-
AzuriteTableEndpoint = azuriteTableEndpoint;
18+
AzuriteContainer = azuriteContainer;
2119
}
2220

2321
/// <summary>
@@ -59,22 +57,16 @@ public EventHubsConfiguration(EventHubsConfiguration oldValue, EventHubsConfigur
5957
: base(oldValue, newValue)
6058
{
6159
ConfigurationBuilder = BuildConfiguration.Combine(oldValue.ConfigurationBuilder, newValue.ConfigurationBuilder);
62-
AzuriteBlobEndpoint = BuildConfiguration.Combine(oldValue.AzuriteBlobEndpoint, newValue.AzuriteBlobEndpoint);
63-
AzuriteTableEndpoint = BuildConfiguration.Combine(oldValue.AzuriteTableEndpoint, newValue.AzuriteTableEndpoint);
60+
AzuriteContainer = BuildConfiguration.Combine(oldValue.AzuriteContainer, newValue.AzuriteContainer);
6461
}
6562

6663
/// <summary>
6764
/// Gets the configuration builder
6865
/// </summary>
6966
public ConfigurationBuilder ConfigurationBuilder { get; }
70-
71-
/// <summary>
72-
/// Gets the Azurite blob endpoint
73-
/// </summary>
74-
public string AzuriteBlobEndpoint { get; }
75-
67+
7668
/// <summary>
77-
/// Gets the Azurite table endpoint
69+
/// Gets the Azurite docker container details
7870
/// </summary>
79-
public string AzuriteTableEndpoint { get; }
71+
public AzuriteContainer AzuriteContainer { get; set; }
8072
}

src/Testcontainers.EventHubs/EventHubsContainer.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Threading;
2+
13
namespace Testcontainers.EventHubs;
24

35
/// <inheritdoc cref="DockerContainer" />
@@ -9,6 +11,8 @@ public sealed class EventHubsContainer : DockerContainer
911
private const string SharedAccessKey = "SAS_KEY_VALUE";
1012

1113
private const string UseDevelopmentEmulator = "true";
14+
15+
private readonly EventHubsConfiguration _configuration;
1216

1317
/// <summary>
1418
/// Initializes a new instance of the <see cref="EventHubsContainer" /> class.
@@ -17,6 +21,7 @@ public sealed class EventHubsContainer : DockerContainer
1721
public EventHubsContainer(EventHubsConfiguration configuration)
1822
: base(configuration)
1923
{
24+
_configuration = configuration;
2025
}
2126

2227
/// <summary>
@@ -33,4 +38,39 @@ public string GetConnectionString()
3338
properties.Add("UseDevelopmentEmulator", UseDevelopmentEmulator);
3439
return string.Join(";", properties.Select(property => string.Join("=", property.Key, property.Value)));
3540
}
41+
42+
protected override async Task UnsafeCreateAsync(CancellationToken ct = default)
43+
{
44+
foreach (var network in _configuration.Networks.ToArray())
45+
{
46+
await network.CreateAsync(ct)
47+
.ConfigureAwait(false);
48+
}
49+
50+
await base.UnsafeCreateAsync(ct)
51+
.ConfigureAwait(false);
52+
}
53+
54+
protected override Task UnsafeDeleteAsync(CancellationToken ct = default)
55+
{
56+
return Task.WhenAll(base.UnsafeDeleteAsync(ct), _configuration.AzuriteContainer.DisposeAsync().AsTask());
57+
}
58+
59+
protected override async Task UnsafeStartAsync(CancellationToken ct = default)
60+
{
61+
await _configuration.AzuriteContainer.StartAsync(ct)
62+
.ConfigureAwait(false);
63+
64+
await base.UnsafeStartAsync(ct)
65+
.ConfigureAwait(false);
66+
}
67+
68+
protected override async Task UnsafeStopAsync(CancellationToken ct = default)
69+
{
70+
await base.UnsafeStopAsync(ct)
71+
.ConfigureAwait(false);
72+
73+
await _configuration.AzuriteContainer.StopAsync(ct)
74+
.ConfigureAwait(false);
75+
}
3676
}

src/Testcontainers.EventHubs/Testcontainers.EventHubs.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
</ItemGroup>
99
<ItemGroup>
1010
<ProjectReference Include="../Testcontainers/Testcontainers.csproj"/>
11+
<ProjectReference Include="..\Testcontainers.Azurite\Testcontainers.Azurite.csproj" />
1112
</ItemGroup>
1213
</Project>

src/Testcontainers.EventHubs/Usings.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
global using JetBrains.Annotations;
1111
global using Testcontainers.EventHubs.Configuration;
1212
global using DotNet.Testcontainers;
13-
global using System.Threading.Tasks;
13+
global using System.Threading.Tasks;
14+
global using Testcontainers.Azurite;

tests/Testcontainers.EventHubs.Tests/EventHubsContainerTest.cs

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,20 @@
1-
using System;
2-
using Azure.Messaging.EventHubs.Consumer;
3-
41
namespace Testcontainers.EventHubs;
52

63
public abstract class EventHubsContainerTest : IAsyncLifetime
74
{
8-
private readonly AzuriteContainer _azuriteContainer;
9-
10-
private EventHubsContainer _eventHubsContainer;
11-
12-
private readonly INetwork _network = new NetworkBuilder().Build();
5+
private static readonly ConfigurationBuilder ConfigurationBuilder = ConfigurationBuilder.Create()
6+
.WithEventHub(EventHubName, 2, [EventHubConsumerGroupName]);
137

14-
private const string AzuriteNetworkAlias = "azurite";
15-
16-
private const string EventHubName = "testeventhub";
17-
private const string EventHubConsumerGroupName = "testconsumergroup";
18-
19-
private EventHubsContainerTest()
20-
{
21-
_azuriteContainer = new AzuriteBuilder()
22-
.WithNetwork(_network)
23-
.WithNetworkAliases(AzuriteNetworkAlias)
24-
.Build();
25-
}
26-
27-
public async Task InitializeAsync()
28-
{
29-
await _azuriteContainer.StartAsync();
30-
31-
var configurationBuilder = ConfigurationBuilder
32-
.Create()
33-
.WithEventHub(EventHubName, 2, [EventHubConsumerGroupName]);
8+
private readonly EventHubsContainer _eventHubsContainer = new EventHubsBuilder()
9+
.WithAcceptLicenseAgreement(true)
10+
.WithConfigurationBuilder(ConfigurationBuilder)
11+
.Build();
3412

35-
var builder = new EventHubsBuilder()
36-
.WithAcceptLicenseAgreement(true)
37-
.WithNetwork(_network)
38-
.WithConfigurationBuilder(configurationBuilder)
39-
.WithAzuriteBlobEndpoint(AzuriteNetworkAlias)
40-
.WithAzuriteTableEndpoint(AzuriteNetworkAlias);
41-
42-
_eventHubsContainer = builder.Build();
43-
44-
await _eventHubsContainer.StartAsync();
45-
}
13+
private const string EventHubName = "eh-1";
14+
private const string EventHubConsumerGroupName = "testconsumergroup";
4615

47-
public async Task DisposeAsync()
48-
{
49-
await _eventHubsContainer.DisposeAsync();
50-
51-
await _azuriteContainer.DisposeAsync();
52-
}
16+
public Task InitializeAsync() => _eventHubsContainer.StartAsync();
17+
public Task DisposeAsync() => _eventHubsContainer.DisposeAsync().AsTask();
5318

5419
[Fact]
5520
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]

0 commit comments

Comments
 (0)