Skip to content

Commit

Permalink
Add Azurite container to Azure module
Browse files Browse the repository at this point in the history
- Fix code review findings

Signed-off-by: Esta Nagy <[email protected]>
  • Loading branch information
nagyesta committed Dec 24, 2024
1 parent eaaa094 commit 2c83a05
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 100 deletions.
8 changes: 1 addition & 7 deletions docs/modules/azure.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@ Start Azurite Emulator during a test:
<!--/codeinclude-->

!!! note
SSL configuration is possible using the `withSsl(File, String)` and `withSsl(File, File)` methods.

Get the connection string from the container:

<!--codeinclude-->
[Get connection string](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:getConnectionString
<!--/codeinclude-->
SSL configuration is possible using the `withSsl(MountableFile, String)` and `withSsl(MountableFile, MountableFile)` methods.

#### Using with Blob

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package org.testcontainers.azure;

import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;

import java.io.File;
import org.testcontainers.utility.MountableFile;

/**
* Testcontainers implementation for Azurite Emulator.
Expand All @@ -17,8 +15,6 @@
* <li>10001 (queue port)</li>
* <li>10002 (table port)</li>
* </ul>
* <p>
* See command line options <a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage#command-line-options">here</a>.
*/
public class AzuriteContainer extends GenericContainer<AzuriteContainer> {

Expand All @@ -38,12 +34,12 @@ public class AzuriteContainer extends GenericContainer<AzuriteContainer> {
/**
* The account name of the default credentials.
*/
public static final String WELL_KNOWN_ACCOUNT_NAME = "devstoreaccount1";
private static final String WELL_KNOWN_ACCOUNT_NAME = "devstoreaccount1";

/**
* The account key of the default credentials.
*/
public static final String WELL_KNOWN_ACCOUNT_KEY =
private static final String WELL_KNOWN_ACCOUNT_KEY =
"Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse(
Expand All @@ -52,11 +48,11 @@ public class AzuriteContainer extends GenericContainer<AzuriteContainer> {

private String host = DEFAULT_HOST;

private File cert = null;
private MountableFile cert = null;

private String certExtension = null;

private File key = null;
private MountableFile key = null;

private String pwd = null;

Expand All @@ -66,6 +62,7 @@ public class AzuriteContainer extends GenericContainer<AzuriteContainer> {
public AzuriteContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
withExposedPorts(DEFAULT_BLOB_PORT, DEFAULT_QUEUE_PORT, DEFAULT_TABLE_PORT);
}

/**
Expand All @@ -75,7 +72,7 @@ public AzuriteContainer(final DockerImageName dockerImageName) {
* @param password The password securing the certificate
* @return this
*/
public AzuriteContainer withSsl(final File pfxCert, final String password) {
public AzuriteContainer withSsl(final MountableFile pfxCert, final String password) {
cert = pfxCert;
pwd = password;
certExtension = ".pfx";
Expand All @@ -89,7 +86,7 @@ public AzuriteContainer withSsl(final File pfxCert, final String password) {
* @param pemKey The PEM key file
* @return this
*/
public AzuriteContainer withSsl(final File pemCert, final File pemKey) {
public AzuriteContainer withSsl(final MountableFile pemCert, final MountableFile pemKey) {
cert = pemCert;
key = pemKey;
certExtension = ".pem";
Expand All @@ -109,19 +106,15 @@ public AzuriteContainer withHost(final String host) {

@Override
protected void configure() {
withEnv("AZURITE_ACCOUNTS", WELL_KNOWN_ACCOUNT_NAME + ":" + WELL_KNOWN_ACCOUNT_KEY);
withCommand(getCommandLine());
if (cert != null) {
final String certAbsolutePath = cert.getAbsolutePath();
logger().info("Using path for cert file: '{}'", certAbsolutePath);
withFileSystemBind(certAbsolutePath, "/cert" + certExtension, BindMode.READ_ONLY);
logger().info("Using path for cert file: '{}'", cert);
withCopyFileToContainer(cert, "/cert" + certExtension);
if (key != null) {
final String keyAbsolutePath = key.getAbsolutePath();
logger().info("Using path for key file: '{}'", keyAbsolutePath);
withFileSystemBind(keyAbsolutePath, "/key.pem", BindMode.READ_ONLY);
logger().info("Using path for key file: '{}'", key);
withCopyFileToContainer(key, "/key.pem");
}
}
withExposedPorts(DEFAULT_BLOB_PORT, DEFAULT_QUEUE_PORT, DEFAULT_TABLE_PORT);
}

/**
Expand Down Expand Up @@ -164,10 +157,9 @@ public String getConnectionString(final String accountName, final String account

String getCommandLine() {
final StringBuilder args = new StringBuilder("azurite");
args.append(" --blobHost ").append(ALLOW_ALL_CONNECTIONS).append(" --blobPort ").append(DEFAULT_BLOB_PORT);
args.append(" --queueHost ").append(ALLOW_ALL_CONNECTIONS).append(" --queuePort ").append(DEFAULT_QUEUE_PORT);
args.append(" --tableHost ").append(ALLOW_ALL_CONNECTIONS).append(" --tablePort ").append(DEFAULT_TABLE_PORT);
args.append(" --location ").append("/data");
args.append(" --blobHost ").append(ALLOW_ALL_CONNECTIONS);
args.append(" --queueHost ").append(ALLOW_ALL_CONNECTIONS);
args.append(" --tableHost ").append(ALLOW_ALL_CONNECTIONS);
if (cert != null) {
args.append(" --cert ").append("/cert").append(certExtension);
if (pwd != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,16 @@
import com.azure.storage.queue.QueueServiceClientBuilder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.MountableFile;

import java.io.File;
import java.net.URL;
import java.util.Optional;
import java.util.Properties;

import static org.assertj.core.api.Assertions.assertThat;

public class AzuriteContainerTest {

private static final File PFX_STORE_FILE = getResourceFile("/keystore.pfx");

private static final File PEM_CERT_FILE = getResourceFile("/certificate.pem");

private static final File PEM_KEY_FILE = getResourceFile("/key.pem");

private static final String PASSWORD = "changeit";

private static final String LOOPBACK_IP = "127.0.0.1";
Expand All @@ -39,7 +30,10 @@ public class AzuriteContainerTest {
@BeforeClass
public static void captureOriginalSystemProperties() {
originalSystemProperties = (Properties) System.getProperties().clone();
System.setProperty("javax.net.ssl.trustStore", PFX_STORE_FILE.getAbsolutePath());
System.setProperty(
"javax.net.ssl.trustStore",
MountableFile.forClasspathResource("/keystore.pfx").getFilesystemPath()
);
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
}
Expand All @@ -49,119 +43,167 @@ public static void restoreOriginalSystemProperties() {
System.setProperties(originalSystemProperties);
}

@Rule
// emulatorContainer {
public AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite")
);

// }

@Rule
public AzuriteContainer pfxEmulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite")
)
.withSsl(PFX_STORE_FILE, PASSWORD)
.withHost(LOOPBACK_IP);

@Rule
public AzuriteContainer pemEmulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite")
)
.withSsl(PEM_CERT_FILE, PEM_KEY_FILE)
.withHost(LOOPBACK_IP);

@Test
public void testWithBlobServiceClient() {
// getConnectionString {
final String connectionString = emulator.getDefaultConnectionString();
// }
testBlob(connectionString);
try (
// emulatorContainer {
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
);
// }
) {
emulator.start();
testBlob(emulator);
}
}

@Test
public void testWithQueueServiceClient() {
final String connectionString = emulator.getDefaultConnectionString();
testQueue(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
);
) {
emulator.start();
testQueue(emulator);
}
}

@Test
public void testWithTableServiceClient() {
final String connectionString = emulator.getDefaultConnectionString();
testTable(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
);
) {
emulator.start();
testTable(emulator);
}
}

@Test
public void testWithBlobServiceClientWithSslUsingPfx() {
final String connectionString = pfxEmulator.getDefaultConnectionString();
testBlob(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
)
.withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD)
.withHost(LOOPBACK_IP);
) {
emulator.start();
testBlob(emulator);
}
}

@Test
public void testWithQueueServiceClientWithSslUsingPfx() {
final String connectionString = pfxEmulator.getDefaultConnectionString();
testQueue(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
)
.withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD)
.withHost(LOOPBACK_IP);
) {
emulator.start();
testQueue(emulator);
}
}

@Test
public void testWithTableServiceClientWithSslUsingPfx() {
final String connectionString = pfxEmulator.getDefaultConnectionString();
testTable(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
)
.withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD)
.withHost(LOOPBACK_IP);
) {
emulator.start();
testTable(emulator);
}
}

@Test
public void testWithBlobServiceClientWithSslUsingPem() {
final String connectionString = pemEmulator.getDefaultConnectionString();
testBlob(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
)
.withSsl(
MountableFile.forClasspathResource("/certificate.pem"),
MountableFile.forClasspathResource("/key.pem")
)
.withHost(LOOPBACK_IP);
) {
emulator.start();
testBlob(emulator);
}
}

@Test
public void testWithQueueServiceClientWithSslUsingPem() {
final String connectionString = pemEmulator.getDefaultConnectionString();
testQueue(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
)
.withSsl(
MountableFile.forClasspathResource("/certificate.pem"),
MountableFile.forClasspathResource("/key.pem")
)
.withHost(LOOPBACK_IP);
) {
emulator.start();
testQueue(emulator);
}
}

@Test
public void testWithTableServiceClientWithSslUsingPem() {
final String connectionString = pemEmulator.getDefaultConnectionString();
testTable(connectionString);
try (
AzuriteContainer emulator = new AzuriteContainer(
DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0")
)
.withSsl(
MountableFile.forClasspathResource("/certificate.pem"),
MountableFile.forClasspathResource("/key.pem")
)
.withHost(LOOPBACK_IP);
) {
emulator.start();
testTable(emulator);
}
}

private void testBlob(final String connectionString) {
private void testBlob(AzuriteContainer container) {
// createBlobClient {
final BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.connectionString(connectionString)
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.connectionString(container.getDefaultConnectionString())
.buildClient();
// }
final BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container");
BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container");

assertThat(containerClient.exists()).isTrue();
}

private void testQueue(final String connectionString) {
private void testQueue(AzuriteContainer container) {
// createQueueClient {
final QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
.connectionString(connectionString)
QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
.connectionString(container.getDefaultConnectionString())
.buildClient();
// }
final QueueClient queueClient = queueServiceClient.createQueue("test-queue");
QueueClient queueClient = queueServiceClient.createQueue("test-queue");

assertThat(queueClient.getQueueUrl()).isNotNull();
}

private void testTable(final String connectionString) {
private void testTable(AzuriteContainer container) {
// createTableClient {
final TableServiceClient tableServiceClient = new TableServiceClientBuilder()
.connectionString(connectionString)
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
.connectionString(container.getDefaultConnectionString())
.buildClient();
// }
final TableClient tableClient = tableServiceClient.createTable("testtable");
TableClient tableClient = tableServiceClient.createTable("testtable");

assertThat(tableClient.getTableEndpoint()).isNotNull();
}

private static File getResourceFile(final String resourceName) {
final URL resource = AzuriteContainerTest.class.getResource(resourceName);
return Optional.ofNullable(resource).map(URL::getFile).map(File::new).orElse(null);
}
}

0 comments on commit 2c83a05

Please sign in to comment.