From 9cca5368343342e149bc452c473c52445637466c Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Thu, 19 Dec 2024 22:23:27 +0100 Subject: [PATCH 01/13] Add Azurite container to Azure module - Add AzuriteContainer to Azure module - Implement new tests - Update Azure documentation Signed-off-by: Esta Nagy --- docs/modules/azure.md | 83 ++- modules/azure/build.gradle | 3 + .../AzuriteConnectionStringBuilder.java | 93 +++ .../containers/AzuriteContainer.java | 529 ++++++++++++++++++ .../containers/AzuriteContainerTest.java | 102 ++++ 5 files changed, 809 insertions(+), 1 deletion(-) create mode 100644 modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java create mode 100644 modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java create mode 100644 modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java diff --git a/docs/modules/azure.md b/docs/modules/azure.md index 5e80270e90c..b6178f99840 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -5,14 +5,95 @@ This module is INCUBATING. While it is ready for use and operational in the curr Testcontainers module for the Microsoft Azure's [SDK](https://github.com/Azure/azure-sdk-for-java). -Currently, the module supports `CosmosDB` emulator. In order to use it, you should use the following class: +Currently, the module supports `Azurite` and `CosmosDB` emulators. In order to use them, you should use the following classes: Class | Container Image -|- +AzuriteContainer | [mcr.microsoft.com/azure-storage/azurite](https://github.com/microsoft/containerregistry) CosmosDBEmulatorContainer | [mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator](https://github.com/microsoft/containerregistry) ## Usage example +### Azurite Storage Emulator + +#### Using Blobs + +Start Azurite Emulator during a test using Blob functionality: + + +[Starting a Azurite Blob container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:blobEmulatorContainer + + +Get the connection string from the container: + + +[Get connection string](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:getBlobConnectionString + + +Build Azure Blob client: + + +[Build Azure Blob Service client](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:createBlobClient + + +Test against the Emulator: + + +[Testing against Azurite container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:testWithBlobClient + + +#### Using Queues + +Start Azurite Emulator during a test using Queue functionality: + + +[Starting a Azurite Queue container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:queueEmulatorContainer + + +Get the connection string from the container: + + +[Get connection string](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:getQueueConnectionString + + +Build Azure Queue client: + + +[Build Azure Queue Service client](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:createQueueClient + + +Test against the Emulator: + + +[Testing against Azurite container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:testWithQueueClient + + +#### Using Table + +Start Azurite Emulator during a test using Table functionality: + + +[Starting a Azurite Table container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:tableEmulatorContainer + + +Get the connection string from the container: + + +[Get connection string](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:getBlobConnectionString + + +Build Azure Table client: + + +[Build Azure Table Service client](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:createTableClient + + +Test against the Emulator: + + +[Testing against Azurite container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:testWithTableClient + + ### CosmosDB Start Azure CosmosDB Emulator during a test: diff --git a/modules/azure/build.gradle b/modules/azure/build.gradle index d31a549abe5..c6cfb6738d0 100644 --- a/modules/azure/build.gradle +++ b/modules/azure/build.gradle @@ -7,4 +7,7 @@ dependencies { testImplementation 'org.assertj:assertj-core:3.26.3' testImplementation 'com.azure:azure-cosmos:4.63.3' + testImplementation 'com.azure:azure-storage-blob:12.29.0' + testImplementation 'com.azure:azure-storage-queue:12.24.0' + testImplementation 'com.azure:azure-data-tables:12.5.0' } diff --git a/modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java b/modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java new file mode 100644 index 00000000000..d010fb44da9 --- /dev/null +++ b/modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java @@ -0,0 +1,93 @@ +package org.testcontainers.containers; + +import org.rnorth.ducttape.Preconditions; + +/** + * Builds connection strings for the {@link AzuriteContainer}. + */ +class AzuriteConnectionStringBuilder { + + private static final String CONNECTION_PROTOCOL_FORMAT = "DefaultEndpointsProtocol=%s;"; + + private static final String ACCOUNT_DETAILS_FORMAT = "AccountName=%s;AccountKey=%s;"; + + private static final String BLOB_ENDPOINT_FORMAT = "BlobEndpoint=%s://%s:%d/%s;"; + + private static final String QUEUE_ENDPOINT_FORMAT = "QueueEndpoint=%s://%s:%d/%s;"; + + private static final String TABLE_ENDPOINT_FORMAT = "TableEndpoint=%s://%s:%d/%s;"; + + private String protocol = "http"; + + private String accountName = AzuriteContainer.WELL_KNOWN_ACCOUNT_NAME; + + private String accountKey = AzuriteContainer.WELL_KNOWN_ACCOUNT_KEY; + + private boolean useBlob = true; + + private String blobHost = AzuriteContainer.DEFAULT_HOST; + + private int blobPort = AzuriteContainer.DEFAULT_BLOB_PORT; + + private boolean useQueue = true; + + private String queueHost = AzuriteContainer.DEFAULT_HOST; + + private int queuePort = AzuriteContainer.DEFAULT_QUEUE_PORT; + + private boolean useTable = true; + + private String tableHost = AzuriteContainer.DEFAULT_HOST; + + private int tablePort = AzuriteContainer.DEFAULT_TABLE_PORT; + + AzuriteConnectionStringBuilder useSsl(final boolean useSsl) { + protocol = useSsl ? "https" : "http"; + return this; + } + + AzuriteConnectionStringBuilder accountCredentials(final String accountName, final String accountKey) { + this.accountName = accountName; + this.accountKey = accountKey; + return this; + } + + AzuriteConnectionStringBuilder blobEndpoint(final String host, final int port, final boolean enabled) { + blobHost = host; + blobPort = port; + useBlob = enabled; + return this; + } + + AzuriteConnectionStringBuilder queueEndpoint(final String host, final int port, final boolean enabled) { + queueHost = host; + queuePort = port; + useQueue = enabled; + return this; + } + + AzuriteConnectionStringBuilder tableEndpoint(final String host, final int port, final boolean enabled) { + tableHost = host; + tablePort = port; + useTable = enabled; + return this; + } + + String build() { + Preconditions.check("At least one of the blob, queue or table must be used!", useBlob || useQueue || useTable); + + final StringBuilder stringBuilder = new StringBuilder() + .append(String.format(CONNECTION_PROTOCOL_FORMAT, protocol)) + .append(String.format(ACCOUNT_DETAILS_FORMAT, accountName, accountKey)); + if (useBlob) { + stringBuilder.append(String.format(BLOB_ENDPOINT_FORMAT, protocol, blobHost, blobPort, accountName)); + } + if (useQueue) { + stringBuilder.append(String.format(QUEUE_ENDPOINT_FORMAT, protocol, queueHost, queuePort, accountName)); + } + if (useTable) { + stringBuilder.append(String.format(TABLE_ENDPOINT_FORMAT, protocol, tableHost, tablePort, accountName)); + } + return stringBuilder.toString(); + } +} diff --git a/modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java new file mode 100644 index 00000000000..5b5503bc83a --- /dev/null +++ b/modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java @@ -0,0 +1,529 @@ +package org.testcontainers.containers; + +import org.testcontainers.utility.DockerImageName; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Testcontainers implementation for Azurite Emulator. + *

+ * Supported image: {@code mcr.microsoft.com/azure-storage/azurite} + *

+ * Exposed ports: + *

+ *

+ * See command line options here. + */ +public class AzuriteContainer extends GenericContainer { + + static final String DEFAULT_HOST = "127.0.0.1"; + + static final int DEFAULT_BLOB_PORT = 10000; + + static final int DEFAULT_QUEUE_PORT = 10001; + + static final int DEFAULT_TABLE_PORT = 10002; + + static final String DEFAULT_LOCATION = "/data"; + + /** + * The account name of the default credentials. + */ + public static final String WELL_KNOWN_ACCOUNT_NAME = "devstoreaccount1"; + + /** + * The account key of the default credentials. + */ + public static final String WELL_KNOWN_ACCOUNT_KEY = + "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; + + static final int NO_LIMIT = 0; + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "mcr.microsoft.com/azure-storage/azurite" + ); + + private boolean useBlob = true; + + private String blobHost = DEFAULT_HOST; + + private int blobPort = DEFAULT_BLOB_PORT; + + private boolean useQueue = true; + + private String queueHost = DEFAULT_HOST; + + private int queuePort = DEFAULT_QUEUE_PORT; + + private boolean useTable = true; + + private String tableHost = DEFAULT_HOST; + + private int tablePort = DEFAULT_TABLE_PORT; + + private String location = DEFAULT_LOCATION; + + private boolean silent = false; + + private String debug = null; + + private boolean loose = false; + + private boolean version = false; + + private File cert = null; + + private String certExtension = null; + + private File key = null; + + private String pwd = null; + + private String oauth = null; + + private boolean skipApiVersionCheck = false; + + private boolean disableProductStyleUrl = false; + + private boolean inMemoryPersistence = false; + + private long extentMemoryLimit = NO_LIMIT; + + private final List azuriteAccounts = new ArrayList<>(); + + /** + * @param dockerImageName specified docker image name to run + */ + public AzuriteContainer(final DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + } + + /** + * Configure SSL with a custom certificate and password. + * + * @param pfxCert The PFX certificate file + * @param password The password securing the certificate + * @return this + */ + public AzuriteContainer withSsl(final File pfxCert, final String password) { + cert = pfxCert; + pwd = password; + certExtension = ".pfx"; + return this; + } + + /** + * Configure SSL with a custom certificate and private key. + * + * @param pemCert The PEM certificate file + * @param pemKey The PEM key file + * @return this + */ + public AzuriteContainer withSsl(final File pemCert, final File pemKey) { + cert = pemCert; + key = pemKey; + certExtension = ".pem"; + return this; + } + + /** + * Disable Blob functionality. + * + * @return this + */ + public AzuriteContainer withoutBlob() { + this.useBlob = false; + return this; + } + + /** + * Disables Queue functionality. + * + * @return this + */ + public AzuriteContainer withoutQueue() { + this.useQueue = false; + return this; + } + + /** + * Disables Table functionality. + * + * @return this + */ + public AzuriteContainer withoutTable() { + this.useTable = false; + return this; + } + + /** + * Sets the hostname we want to use to connect to our emulator. (default: {@link #DEFAULT_HOST}) + * + * @param host The host name + * @return this + */ + public AzuriteContainer withHost(final String host) { + blobHost = host; + queueHost = host; + tableHost = host; + return this; + } + + /** + * Sets the container port we want to use for the Blob functionality. (default: {@link #DEFAULT_BLOB_PORT}) + * + * @param port The Blob port + * @return this + */ + public AzuriteContainer withBlobPort(final int port) { + blobPort = port; + return this; + } + + /** + * Sets the container port we want to use for the Queue functionality. (default: {@link #DEFAULT_QUEUE_PORT}) + * + * @param port The Queue port + * @return this + */ + public AzuriteContainer withQueuePort(final int port) { + queuePort = port; + return this; + } + + /** + * Sets the container port we want to use for the Table functionality. (default: {@link #DEFAULT_TABLE_PORT}) + * + * @param port The Table port + * @return this + */ + public AzuriteContainer withTablePort(final int port) { + tablePort = port; + return this; + } + + /** + * Sets the host name and the container port we want to use for the Blob functionality. + * (default: {@link #DEFAULT_HOST} and {@link #DEFAULT_BLOB_PORT}) + * + * @param host The host name + * @param port The Blob port + * @return this + */ + public AzuriteContainer withBlobEndpoint(final String host, final int port) { + blobHost = host; + blobPort = port; + return this; + } + + /** + * Sets the host name and the container port we want to use for the Queue functionality. + * (default: {@link #DEFAULT_HOST} and {@link #DEFAULT_QUEUE_PORT}) + * + * @param host The host name + * @param port The Queue port + * @return this + */ + public AzuriteContainer withQueueEndpoint(final String host, final int port) { + queueHost = host; + queuePort = port; + return this; + } + + /** + * Sets the host name and the container port we want to use for the Table functionality. + * (default: {@link #DEFAULT_HOST} and {@link #DEFAULT_TABLE_PORT}) + * + * @param host The host name + * @param port The Table port + * @return this + */ + public AzuriteContainer withTableEndpoint(final String host, final int port) { + tableHost = host; + tablePort = port; + return this; + } + + /** + * Sets the file system location where the data should be stored in the container. + * (default: {@link #DEFAULT_LOCATION}) + * + * @param location The file system location. + * @return this + */ + public AzuriteContainer withLocation(final String location) { + this.location = location; + return this; + } + + /** + * Tells Azurite to use silent mode. + * + * @return this + */ + public AzuriteContainer withSilentMode() { + this.silent = true; + return this; + } + + /** + * Defines the file system path where the debug logs should be saved in the container. + * + * @param debugLog The path of the debug log. + * @return this + */ + public AzuriteContainer withDebugLog(final String debugLog) { + this.debug = debugLog; + return this; + } + + /** + * Tells Azurite to use loose mode. + * + * @return this + */ + public AzuriteContainer withLooseMode() { + this.loose = true; + return this; + } + + /** + * Tells Azurite to print the version to the output. + * + * @return this + */ + public AzuriteContainer withPrintVersion() { + this.version = true; + return this; + } + + /** + * Enables OAuth authentication. Requires SSL as well. + * {@link #withSsl(File, String)} + * {@link #withSsl(File, File)} + * + * @param oauth The OAuth parameter + * @return this + */ + public AzuriteContainer withOauth(final String oauth) { + this.oauth = oauth; + return this; + } + + /** + * Tells Azurite to skip checking the API version. + * + * @return this + */ + public AzuriteContainer withSkipApiVersionCheck() { + this.skipApiVersionCheck = true; + return this; + } + + /** + * Tells Azurite to disable product style URLs. + * + * @return this + */ + public AzuriteContainer withDisableProductStyleUrl() { + this.disableProductStyleUrl = true; + return this; + } + + /** + * Tells Azurite to store content in memory using the default limits. + * + * @return this + */ + public AzuriteContainer withInMemoryPersistence() { + this.inMemoryPersistence = true; + return this; + } + + /** + * Tells Azurite to store content in memory using a custom limit. + * + * @param limit The memory limit in MBs + * @return this + */ + public AzuriteContainer withInMemoryPersistence(final long limit) { + this.inMemoryPersistence = true; + this.extentMemoryLimit = limit; + return this; + } + + /** + * Adds an account name and account key to be able to use them for authentication. + * (default name: {@link #WELL_KNOWN_ACCOUNT_NAME}) + * (default key: {@link #WELL_KNOWN_ACCOUNT_KEY}) + * + * @param accountName The name of the account + * @param primaryKey The account key + * @return this + */ + public AzuriteContainer addAccountCredentials(final String accountName, final String primaryKey) { + return addAccountCredentials(accountName, primaryKey, null); + } + + /** + * Adds an account name and account keys to be able to use them for authentication. + * (default name: {@link #WELL_KNOWN_ACCOUNT_NAME}) + * (default key: {@link #WELL_KNOWN_ACCOUNT_KEY}) + * + * @param accountName The name of the account + * @param primaryKey The primary account key + * @param secondaryKey The secondary account key (optional) + * @return this + */ + public AzuriteContainer addAccountCredentials( + final String accountName, + final String primaryKey, + final String secondaryKey + ) { + final StringBuilder credentialBuilder = new StringBuilder().append(accountName).append(":").append(primaryKey); + Optional.ofNullable(secondaryKey).ifPresent(s -> credentialBuilder.append(":").append(s)); + this.azuriteAccounts.add(credentialBuilder.toString()); + return this; + } + + @Override + protected void configure() { + super.configure(); + withEnv("AZURITE_ACCOUNTS", getAccounts()); + 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); + if (key != null) { + final String keyAbsolutePath = key.getAbsolutePath(); + logger().info("Using path for key file: '{}'", keyAbsolutePath); + withFileSystemBind(keyAbsolutePath, "/key.pem", BindMode.READ_ONLY); + } + } + exposeRelevantPorts(); + } + + /** + * Returns the connection string for the default credentials. + * + * @return connection string + */ + public String getDefaultConnectionString() { + return getConnectionString(WELL_KNOWN_ACCOUNT_NAME, WELL_KNOWN_ACCOUNT_KEY); + } + + /** + * Returns the connection string for the account name and key specified. + * + * @param accountName The name of the account + * @param accountKey The account key + * @return connection string + */ + public String getConnectionString(final String accountName, final String accountKey) { + return new AzuriteConnectionStringBuilder() + .accountCredentials(accountName, accountKey) + .useSsl(cert != null) + .blobEndpoint(blobHost, getPortNumberFor(blobPort), useBlob) + .queueEndpoint(queueHost, getPortNumberFor(queuePort), useQueue) + .tableEndpoint(tableHost, getPortNumberFor(tablePort), useTable) + .build(); + } + + String getCommandLine() { + final StringBuilder args = new StringBuilder(getExecutableName()); + if (useBlob) { + args.append(" --blobHost ").append(blobHost).append(" --blobPort ").append(blobPort); + } + if (useQueue) { + args.append(" --queueHost ").append(queueHost).append(" --queuePort ").append(queuePort); + } + if (useTable) { + args.append(" --tableHost ").append(tableHost).append(" --tablePort ").append(tablePort); + } + if (silent) { + args.append(" --silent"); + } + if (version) { + args.append(" --version"); + } + if (debug != null) { + args.append(" --debug ").append(debug); + } + if (loose) { + args.append(" --loose"); + } + if (disableProductStyleUrl) { + args.append(" --disableProductStyleUrl"); + } + if (skipApiVersionCheck) { + args.append(" --skipApiVersionCheck"); + } + if (inMemoryPersistence) { + args.append(" --inMemoryPersistence"); + if (extentMemoryLimit > NO_LIMIT) { + args.append(" --extentMemoryLimit ").append(extentMemoryLimit); + } + } else { + args.append(" --location ").append(location); + } + if (cert != null) { + args.append(" --cert ").append("/cert").append(certExtension); + if (pwd != null) { + args.append(" --pwd ").append(pwd); + } else { + args.append(" --key ").append("/key.pem"); + } + if (oauth != null) { + args.append(" --oauth ").append(oauth); + } + } + final String cmd = args.toString(); + logger().debug("Using command line: '{}'", cmd); + return cmd; + } + + private void exposeRelevantPorts() { + if (useBlob) { + addExposedPort(blobPort); + } + if (useQueue) { + addExposedPort(queuePort); + } + if (useTable) { + addExposedPort(tablePort); + } + } + + private int getPortNumberFor(final int port) { + int mappedPort = port; + if (getExposedPorts().contains(port)) { + mappedPort = getMappedPort(port); + } + return mappedPort; + } + + private String getAccounts() { + return String.join(";", azuriteAccounts); + } + + private String getExecutableName() { + String executable = "azurite"; + if (useBlob && !useQueue && !useTable) { + executable = "azurite-blob"; + } else if (!useBlob && useQueue && !useTable) { + executable = "azurite-queue"; + } else if (!useBlob && !useQueue && useTable) { + executable = "azurite-table"; + } + return executable; + } +} diff --git a/modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java new file mode 100644 index 00000000000..6108392e258 --- /dev/null +++ b/modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java @@ -0,0 +1,102 @@ +package org.testcontainers.containers; + +import com.azure.data.tables.TableClient; +import com.azure.data.tables.TableServiceClient; +import com.azure.data.tables.TableServiceClientBuilder; +import com.azure.storage.blob.BlobContainerClient; +import com.azure.storage.blob.BlobServiceClient; +import com.azure.storage.blob.BlobServiceClientBuilder; +import com.azure.storage.queue.QueueClient; +import com.azure.storage.queue.QueueServiceClient; +import com.azure.storage.queue.QueueServiceClientBuilder; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.testcontainers.utility.DockerImageName; + +public class AzuriteContainerTest { + + @Rule + // blobEmulatorContainer { + public AzuriteContainer blobEmulator = new AzuriteContainer( + DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite") + ) + .withBlobPort(10000) + .withoutQueue() + .withoutTable(); + + // } + + @Rule + // queueEmulatorContainer { + public AzuriteContainer queueEmulator = new AzuriteContainer( + DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite") + ) + .withQueuePort(10001) + .withoutBlob() + .withoutTable(); + + // } + + @Rule + // tableEmulatorContainer { + public AzuriteContainer tableEmulator = new AzuriteContainer( + DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite") + ) + .withTablePort(10002) + .withoutBlob() + .withoutQueue(); + + // } + + @Test + public void testWithBlobServiceClient() { + // getBlobConnectionString { + final String connectionString = blobEmulator.getDefaultConnectionString(); + // } + // createBlobClient { + final BlobServiceClient blobServiceClient = new BlobServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // } + // testWithBlobClient { + final BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container"); + + Assert.assertTrue(containerClient.exists()); + // } + } + + @Test + public void testWithQueueServiceClient() { + // getQueueConnectionString { + final String connectionString = blobEmulator.getDefaultConnectionString(); + // } + // createQueueClient { + final QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // } + // testWithQueueClient { + final QueueClient queueClient = queueServiceClient.createQueue("test-queue"); + + Assert.assertNotNull(queueClient.getQueueUrl()); + // } + } + + @Test + public void testWithTableServiceClient() { + // getTableConnectionString { + final String connectionString = blobEmulator.getDefaultConnectionString(); + // } + // createTableClient { + final TableServiceClient tableServiceClient = new TableServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // } + // testWithTableClient { + final TableClient tableClient = tableServiceClient.createTable("testtable"); + + Assert.assertNotNull(tableClient.getTableEndpoint()); + // } + } +} From f7ac9a97f628ecf6719ef28054daa0ea766e9ec0 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Fri, 20 Dec 2024 20:47:15 +0100 Subject: [PATCH 02/13] Add Azurite container to Azure module - Move Azurite container to Azure specific package - Move Connection String builder to AzuriteContainer - Remove unnecessary configuration options - Add tests for SSL configuration - Remove duplications and unnecessary details from Azure module documentation Signed-off-by: Esta Nagy --- docs/modules/azure.md | 65 +-- .../azure/AzuriteContainer.java | 181 ++++++ .../AzuriteConnectionStringBuilder.java | 93 --- .../containers/AzuriteContainer.java | 529 ------------------ .../azure/AzuriteContainerTest.java | 168 ++++++ .../containers/AzuriteContainerTest.java | 102 ---- .../azure/src/test/resources/certificate.pem | 23 + modules/azure/src/test/resources/key.pem | 32 ++ modules/azure/src/test/resources/keystore.pfx | Bin 0 -> 2606 bytes 9 files changed, 417 insertions(+), 776 deletions(-) create mode 100644 modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java delete mode 100644 modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java delete mode 100644 modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java create mode 100644 modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java delete mode 100644 modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java create mode 100644 modules/azure/src/test/resources/certificate.pem create mode 100644 modules/azure/src/test/resources/key.pem create mode 100644 modules/azure/src/test/resources/keystore.pfx diff --git a/docs/modules/azure.md b/docs/modules/azure.md index b6178f99840..487bf345918 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -16,82 +16,43 @@ CosmosDBEmulatorContainer | [mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emula ### Azurite Storage Emulator -#### Using Blobs - -Start Azurite Emulator during a test using Blob functionality: - - -[Starting a Azurite Blob container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:blobEmulatorContainer - - -Get the connection string from the container: - - -[Get connection string](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:getBlobConnectionString - - -Build Azure Blob client: +Start Azurite Emulator during a test: -[Build Azure Blob Service client](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:createBlobClient +[Starting a Azurite Blob container](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainer -Test against the Emulator: - - -[Testing against Azurite container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:testWithBlobClient - - -#### Using Queues - -Start Azurite Emulator during a test using Queue functionality: - - -[Starting a Azurite Queue container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:queueEmulatorContainer - +> [!TIP] +> SSL configuration is possible using the `withSsl(File, String)` and `withSsl(File, File)` methods. Get the connection string from the container: -[Get connection string](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:getQueueConnectionString +[Get connection string](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:getConnectionString -Build Azure Queue client: +#### Using with Blob - -[Build Azure Queue Service client](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:createQueueClient - - -Test against the Emulator: +Build Azure Blob client: -[Testing against Azurite container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:testWithQueueClient +[Build Azure Blob Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createBlobClient -#### Using Table +#### Using with Queue -Start Azurite Emulator during a test using Table functionality: +Build Azure Queue client: -[Starting a Azurite Table container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:tableEmulatorContainer +[Build Azure Queue Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createQueueClient -Get the connection string from the container: - - -[Get connection string](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:getBlobConnectionString - +#### Using with Table Build Azure Table client: -[Build Azure Table Service client](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:createTableClient - - -Test against the Emulator: - - -[Testing against Azurite container](../../modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java) inside_block:testWithTableClient +[Build Azure Table Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createTableClient ### CosmosDB diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java new file mode 100644 index 00000000000..0bea1692854 --- /dev/null +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -0,0 +1,181 @@ +package org.testcontainers.azure; + +import org.testcontainers.containers.BindMode; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; + +import java.io.File; + +/** + * Testcontainers implementation for Azurite Emulator. + *

+ * Supported image: {@code mcr.microsoft.com/azure-storage/azurite} + *

+ * Exposed ports: + *

+ *

+ * See command line options here. + */ +public class AzuriteContainer extends GenericContainer { + + private static final String DEFAULT_HOST = "127.0.0.1"; + + private static final int DEFAULT_BLOB_PORT = 10000; + + private static final int DEFAULT_QUEUE_PORT = 10001; + + private static final int DEFAULT_TABLE_PORT = 10002; + + private static final String CONNECTION_STRING_FORMAT = + "DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s://%s:%d/%s;QueueEndpoint=%s://%s:%d/%s;TableEndpoint=%s://%s:%d/%s;"; + + /** + * The account name of the default credentials. + */ + public static final String WELL_KNOWN_ACCOUNT_NAME = "devstoreaccount1"; + + /** + * The account key of the default credentials. + */ + public static final String WELL_KNOWN_ACCOUNT_KEY = + "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; + + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( + "mcr.microsoft.com/azure-storage/azurite" + ); + + private String host = DEFAULT_HOST; + + private File cert = null; + + private String certExtension = null; + + private File key = null; + + private String pwd = null; + + /** + * @param dockerImageName specified docker image name to run + */ + public AzuriteContainer(final DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + } + + /** + * Configure SSL with a custom certificate and password. + * + * @param pfxCert The PFX certificate file + * @param password The password securing the certificate + * @return this + */ + public AzuriteContainer withSsl(final File pfxCert, final String password) { + cert = pfxCert; + pwd = password; + certExtension = ".pfx"; + return this; + } + + /** + * Configure SSL with a custom certificate and private key. + * + * @param pemCert The PEM certificate file + * @param pemKey The PEM key file + * @return this + */ + public AzuriteContainer withSsl(final File pemCert, final File pemKey) { + cert = pemCert; + key = pemKey; + certExtension = ".pem"; + return this; + } + + /** + * Sets the hostname we want to use to connect to our emulator. (default: {@link #DEFAULT_HOST}) + * + * @param host The host name + * @return this + */ + public AzuriteContainer withHost(final String host) { + this.host = host; + return this; + } + + @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); + if (key != null) { + final String keyAbsolutePath = key.getAbsolutePath(); + logger().info("Using path for key file: '{}'", keyAbsolutePath); + withFileSystemBind(keyAbsolutePath, "/key.pem", BindMode.READ_ONLY); + } + } + withExposedPorts(DEFAULT_BLOB_PORT, DEFAULT_QUEUE_PORT, DEFAULT_TABLE_PORT); + } + + /** + * Returns the connection string for the default credentials. + * + * @return connection string + */ + public String getDefaultConnectionString() { + return getConnectionString(WELL_KNOWN_ACCOUNT_NAME, WELL_KNOWN_ACCOUNT_KEY); + } + + /** + * Returns the connection string for the account name and key specified. + * + * @param accountName The name of the account + * @param accountKey The account key + * @return connection string + */ + public String getConnectionString(final String accountName, final String accountKey) { + final String protocol = cert != null ? "https" : "http"; + return String.format( + CONNECTION_STRING_FORMAT, + protocol, + accountName, + accountKey, + protocol, + host, + getMappedPort(DEFAULT_BLOB_PORT), + accountName, + protocol, + host, + getMappedPort(DEFAULT_QUEUE_PORT), + accountName, + protocol, + host, + getMappedPort(DEFAULT_TABLE_PORT), + accountName + ); + } + + String getCommandLine() { + final StringBuilder args = new StringBuilder("azurite"); + args.append(" --blobHost ").append(host).append(" --blobPort ").append(DEFAULT_BLOB_PORT); + args.append(" --queueHost ").append(host).append(" --queuePort ").append(DEFAULT_QUEUE_PORT); + args.append(" --tableHost ").append(host).append(" --tablePort ").append(DEFAULT_TABLE_PORT); + args.append(" --location ").append("/data"); + if (cert != null) { + args.append(" --cert ").append("/cert").append(certExtension); + if (pwd != null) { + args.append(" --pwd ").append(pwd); + } else { + args.append(" --key ").append("/key.pem"); + } + } + final String cmd = args.toString(); + logger().debug("Using command line: '{}'", cmd); + return cmd; + } +} diff --git a/modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java b/modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java deleted file mode 100644 index d010fb44da9..00000000000 --- a/modules/azure/src/main/java/org/testcontainers/containers/AzuriteConnectionStringBuilder.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.testcontainers.containers; - -import org.rnorth.ducttape.Preconditions; - -/** - * Builds connection strings for the {@link AzuriteContainer}. - */ -class AzuriteConnectionStringBuilder { - - private static final String CONNECTION_PROTOCOL_FORMAT = "DefaultEndpointsProtocol=%s;"; - - private static final String ACCOUNT_DETAILS_FORMAT = "AccountName=%s;AccountKey=%s;"; - - private static final String BLOB_ENDPOINT_FORMAT = "BlobEndpoint=%s://%s:%d/%s;"; - - private static final String QUEUE_ENDPOINT_FORMAT = "QueueEndpoint=%s://%s:%d/%s;"; - - private static final String TABLE_ENDPOINT_FORMAT = "TableEndpoint=%s://%s:%d/%s;"; - - private String protocol = "http"; - - private String accountName = AzuriteContainer.WELL_KNOWN_ACCOUNT_NAME; - - private String accountKey = AzuriteContainer.WELL_KNOWN_ACCOUNT_KEY; - - private boolean useBlob = true; - - private String blobHost = AzuriteContainer.DEFAULT_HOST; - - private int blobPort = AzuriteContainer.DEFAULT_BLOB_PORT; - - private boolean useQueue = true; - - private String queueHost = AzuriteContainer.DEFAULT_HOST; - - private int queuePort = AzuriteContainer.DEFAULT_QUEUE_PORT; - - private boolean useTable = true; - - private String tableHost = AzuriteContainer.DEFAULT_HOST; - - private int tablePort = AzuriteContainer.DEFAULT_TABLE_PORT; - - AzuriteConnectionStringBuilder useSsl(final boolean useSsl) { - protocol = useSsl ? "https" : "http"; - return this; - } - - AzuriteConnectionStringBuilder accountCredentials(final String accountName, final String accountKey) { - this.accountName = accountName; - this.accountKey = accountKey; - return this; - } - - AzuriteConnectionStringBuilder blobEndpoint(final String host, final int port, final boolean enabled) { - blobHost = host; - blobPort = port; - useBlob = enabled; - return this; - } - - AzuriteConnectionStringBuilder queueEndpoint(final String host, final int port, final boolean enabled) { - queueHost = host; - queuePort = port; - useQueue = enabled; - return this; - } - - AzuriteConnectionStringBuilder tableEndpoint(final String host, final int port, final boolean enabled) { - tableHost = host; - tablePort = port; - useTable = enabled; - return this; - } - - String build() { - Preconditions.check("At least one of the blob, queue or table must be used!", useBlob || useQueue || useTable); - - final StringBuilder stringBuilder = new StringBuilder() - .append(String.format(CONNECTION_PROTOCOL_FORMAT, protocol)) - .append(String.format(ACCOUNT_DETAILS_FORMAT, accountName, accountKey)); - if (useBlob) { - stringBuilder.append(String.format(BLOB_ENDPOINT_FORMAT, protocol, blobHost, blobPort, accountName)); - } - if (useQueue) { - stringBuilder.append(String.format(QUEUE_ENDPOINT_FORMAT, protocol, queueHost, queuePort, accountName)); - } - if (useTable) { - stringBuilder.append(String.format(TABLE_ENDPOINT_FORMAT, protocol, tableHost, tablePort, accountName)); - } - return stringBuilder.toString(); - } -} diff --git a/modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java deleted file mode 100644 index 5b5503bc83a..00000000000 --- a/modules/azure/src/main/java/org/testcontainers/containers/AzuriteContainer.java +++ /dev/null @@ -1,529 +0,0 @@ -package org.testcontainers.containers; - -import org.testcontainers.utility.DockerImageName; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * Testcontainers implementation for Azurite Emulator. - *

- * Supported image: {@code mcr.microsoft.com/azure-storage/azurite} - *

- * Exposed ports: - *

- *

- * See command line options here. - */ -public class AzuriteContainer extends GenericContainer { - - static final String DEFAULT_HOST = "127.0.0.1"; - - static final int DEFAULT_BLOB_PORT = 10000; - - static final int DEFAULT_QUEUE_PORT = 10001; - - static final int DEFAULT_TABLE_PORT = 10002; - - static final String DEFAULT_LOCATION = "/data"; - - /** - * The account name of the default credentials. - */ - public static final String WELL_KNOWN_ACCOUNT_NAME = "devstoreaccount1"; - - /** - * The account key of the default credentials. - */ - public static final String WELL_KNOWN_ACCOUNT_KEY = - "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; - - static final int NO_LIMIT = 0; - - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( - "mcr.microsoft.com/azure-storage/azurite" - ); - - private boolean useBlob = true; - - private String blobHost = DEFAULT_HOST; - - private int blobPort = DEFAULT_BLOB_PORT; - - private boolean useQueue = true; - - private String queueHost = DEFAULT_HOST; - - private int queuePort = DEFAULT_QUEUE_PORT; - - private boolean useTable = true; - - private String tableHost = DEFAULT_HOST; - - private int tablePort = DEFAULT_TABLE_PORT; - - private String location = DEFAULT_LOCATION; - - private boolean silent = false; - - private String debug = null; - - private boolean loose = false; - - private boolean version = false; - - private File cert = null; - - private String certExtension = null; - - private File key = null; - - private String pwd = null; - - private String oauth = null; - - private boolean skipApiVersionCheck = false; - - private boolean disableProductStyleUrl = false; - - private boolean inMemoryPersistence = false; - - private long extentMemoryLimit = NO_LIMIT; - - private final List azuriteAccounts = new ArrayList<>(); - - /** - * @param dockerImageName specified docker image name to run - */ - public AzuriteContainer(final DockerImageName dockerImageName) { - super(dockerImageName); - dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); - } - - /** - * Configure SSL with a custom certificate and password. - * - * @param pfxCert The PFX certificate file - * @param password The password securing the certificate - * @return this - */ - public AzuriteContainer withSsl(final File pfxCert, final String password) { - cert = pfxCert; - pwd = password; - certExtension = ".pfx"; - return this; - } - - /** - * Configure SSL with a custom certificate and private key. - * - * @param pemCert The PEM certificate file - * @param pemKey The PEM key file - * @return this - */ - public AzuriteContainer withSsl(final File pemCert, final File pemKey) { - cert = pemCert; - key = pemKey; - certExtension = ".pem"; - return this; - } - - /** - * Disable Blob functionality. - * - * @return this - */ - public AzuriteContainer withoutBlob() { - this.useBlob = false; - return this; - } - - /** - * Disables Queue functionality. - * - * @return this - */ - public AzuriteContainer withoutQueue() { - this.useQueue = false; - return this; - } - - /** - * Disables Table functionality. - * - * @return this - */ - public AzuriteContainer withoutTable() { - this.useTable = false; - return this; - } - - /** - * Sets the hostname we want to use to connect to our emulator. (default: {@link #DEFAULT_HOST}) - * - * @param host The host name - * @return this - */ - public AzuriteContainer withHost(final String host) { - blobHost = host; - queueHost = host; - tableHost = host; - return this; - } - - /** - * Sets the container port we want to use for the Blob functionality. (default: {@link #DEFAULT_BLOB_PORT}) - * - * @param port The Blob port - * @return this - */ - public AzuriteContainer withBlobPort(final int port) { - blobPort = port; - return this; - } - - /** - * Sets the container port we want to use for the Queue functionality. (default: {@link #DEFAULT_QUEUE_PORT}) - * - * @param port The Queue port - * @return this - */ - public AzuriteContainer withQueuePort(final int port) { - queuePort = port; - return this; - } - - /** - * Sets the container port we want to use for the Table functionality. (default: {@link #DEFAULT_TABLE_PORT}) - * - * @param port The Table port - * @return this - */ - public AzuriteContainer withTablePort(final int port) { - tablePort = port; - return this; - } - - /** - * Sets the host name and the container port we want to use for the Blob functionality. - * (default: {@link #DEFAULT_HOST} and {@link #DEFAULT_BLOB_PORT}) - * - * @param host The host name - * @param port The Blob port - * @return this - */ - public AzuriteContainer withBlobEndpoint(final String host, final int port) { - blobHost = host; - blobPort = port; - return this; - } - - /** - * Sets the host name and the container port we want to use for the Queue functionality. - * (default: {@link #DEFAULT_HOST} and {@link #DEFAULT_QUEUE_PORT}) - * - * @param host The host name - * @param port The Queue port - * @return this - */ - public AzuriteContainer withQueueEndpoint(final String host, final int port) { - queueHost = host; - queuePort = port; - return this; - } - - /** - * Sets the host name and the container port we want to use for the Table functionality. - * (default: {@link #DEFAULT_HOST} and {@link #DEFAULT_TABLE_PORT}) - * - * @param host The host name - * @param port The Table port - * @return this - */ - public AzuriteContainer withTableEndpoint(final String host, final int port) { - tableHost = host; - tablePort = port; - return this; - } - - /** - * Sets the file system location where the data should be stored in the container. - * (default: {@link #DEFAULT_LOCATION}) - * - * @param location The file system location. - * @return this - */ - public AzuriteContainer withLocation(final String location) { - this.location = location; - return this; - } - - /** - * Tells Azurite to use silent mode. - * - * @return this - */ - public AzuriteContainer withSilentMode() { - this.silent = true; - return this; - } - - /** - * Defines the file system path where the debug logs should be saved in the container. - * - * @param debugLog The path of the debug log. - * @return this - */ - public AzuriteContainer withDebugLog(final String debugLog) { - this.debug = debugLog; - return this; - } - - /** - * Tells Azurite to use loose mode. - * - * @return this - */ - public AzuriteContainer withLooseMode() { - this.loose = true; - return this; - } - - /** - * Tells Azurite to print the version to the output. - * - * @return this - */ - public AzuriteContainer withPrintVersion() { - this.version = true; - return this; - } - - /** - * Enables OAuth authentication. Requires SSL as well. - * {@link #withSsl(File, String)} - * {@link #withSsl(File, File)} - * - * @param oauth The OAuth parameter - * @return this - */ - public AzuriteContainer withOauth(final String oauth) { - this.oauth = oauth; - return this; - } - - /** - * Tells Azurite to skip checking the API version. - * - * @return this - */ - public AzuriteContainer withSkipApiVersionCheck() { - this.skipApiVersionCheck = true; - return this; - } - - /** - * Tells Azurite to disable product style URLs. - * - * @return this - */ - public AzuriteContainer withDisableProductStyleUrl() { - this.disableProductStyleUrl = true; - return this; - } - - /** - * Tells Azurite to store content in memory using the default limits. - * - * @return this - */ - public AzuriteContainer withInMemoryPersistence() { - this.inMemoryPersistence = true; - return this; - } - - /** - * Tells Azurite to store content in memory using a custom limit. - * - * @param limit The memory limit in MBs - * @return this - */ - public AzuriteContainer withInMemoryPersistence(final long limit) { - this.inMemoryPersistence = true; - this.extentMemoryLimit = limit; - return this; - } - - /** - * Adds an account name and account key to be able to use them for authentication. - * (default name: {@link #WELL_KNOWN_ACCOUNT_NAME}) - * (default key: {@link #WELL_KNOWN_ACCOUNT_KEY}) - * - * @param accountName The name of the account - * @param primaryKey The account key - * @return this - */ - public AzuriteContainer addAccountCredentials(final String accountName, final String primaryKey) { - return addAccountCredentials(accountName, primaryKey, null); - } - - /** - * Adds an account name and account keys to be able to use them for authentication. - * (default name: {@link #WELL_KNOWN_ACCOUNT_NAME}) - * (default key: {@link #WELL_KNOWN_ACCOUNT_KEY}) - * - * @param accountName The name of the account - * @param primaryKey The primary account key - * @param secondaryKey The secondary account key (optional) - * @return this - */ - public AzuriteContainer addAccountCredentials( - final String accountName, - final String primaryKey, - final String secondaryKey - ) { - final StringBuilder credentialBuilder = new StringBuilder().append(accountName).append(":").append(primaryKey); - Optional.ofNullable(secondaryKey).ifPresent(s -> credentialBuilder.append(":").append(s)); - this.azuriteAccounts.add(credentialBuilder.toString()); - return this; - } - - @Override - protected void configure() { - super.configure(); - withEnv("AZURITE_ACCOUNTS", getAccounts()); - 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); - if (key != null) { - final String keyAbsolutePath = key.getAbsolutePath(); - logger().info("Using path for key file: '{}'", keyAbsolutePath); - withFileSystemBind(keyAbsolutePath, "/key.pem", BindMode.READ_ONLY); - } - } - exposeRelevantPorts(); - } - - /** - * Returns the connection string for the default credentials. - * - * @return connection string - */ - public String getDefaultConnectionString() { - return getConnectionString(WELL_KNOWN_ACCOUNT_NAME, WELL_KNOWN_ACCOUNT_KEY); - } - - /** - * Returns the connection string for the account name and key specified. - * - * @param accountName The name of the account - * @param accountKey The account key - * @return connection string - */ - public String getConnectionString(final String accountName, final String accountKey) { - return new AzuriteConnectionStringBuilder() - .accountCredentials(accountName, accountKey) - .useSsl(cert != null) - .blobEndpoint(blobHost, getPortNumberFor(blobPort), useBlob) - .queueEndpoint(queueHost, getPortNumberFor(queuePort), useQueue) - .tableEndpoint(tableHost, getPortNumberFor(tablePort), useTable) - .build(); - } - - String getCommandLine() { - final StringBuilder args = new StringBuilder(getExecutableName()); - if (useBlob) { - args.append(" --blobHost ").append(blobHost).append(" --blobPort ").append(blobPort); - } - if (useQueue) { - args.append(" --queueHost ").append(queueHost).append(" --queuePort ").append(queuePort); - } - if (useTable) { - args.append(" --tableHost ").append(tableHost).append(" --tablePort ").append(tablePort); - } - if (silent) { - args.append(" --silent"); - } - if (version) { - args.append(" --version"); - } - if (debug != null) { - args.append(" --debug ").append(debug); - } - if (loose) { - args.append(" --loose"); - } - if (disableProductStyleUrl) { - args.append(" --disableProductStyleUrl"); - } - if (skipApiVersionCheck) { - args.append(" --skipApiVersionCheck"); - } - if (inMemoryPersistence) { - args.append(" --inMemoryPersistence"); - if (extentMemoryLimit > NO_LIMIT) { - args.append(" --extentMemoryLimit ").append(extentMemoryLimit); - } - } else { - args.append(" --location ").append(location); - } - if (cert != null) { - args.append(" --cert ").append("/cert").append(certExtension); - if (pwd != null) { - args.append(" --pwd ").append(pwd); - } else { - args.append(" --key ").append("/key.pem"); - } - if (oauth != null) { - args.append(" --oauth ").append(oauth); - } - } - final String cmd = args.toString(); - logger().debug("Using command line: '{}'", cmd); - return cmd; - } - - private void exposeRelevantPorts() { - if (useBlob) { - addExposedPort(blobPort); - } - if (useQueue) { - addExposedPort(queuePort); - } - if (useTable) { - addExposedPort(tablePort); - } - } - - private int getPortNumberFor(final int port) { - int mappedPort = port; - if (getExposedPorts().contains(port)) { - mappedPort = getMappedPort(port); - } - return mappedPort; - } - - private String getAccounts() { - return String.join(";", azuriteAccounts); - } - - private String getExecutableName() { - String executable = "azurite"; - if (useBlob && !useQueue && !useTable) { - executable = "azurite-blob"; - } else if (!useBlob && useQueue && !useTable) { - executable = "azurite-queue"; - } else if (!useBlob && !useQueue && useTable) { - executable = "azurite-table"; - } - return executable; - } -} diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java new file mode 100644 index 00000000000..4bba16f23a4 --- /dev/null +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -0,0 +1,168 @@ +package org.testcontainers.azure; + +import com.azure.data.tables.TableClient; +import com.azure.data.tables.TableServiceClient; +import com.azure.data.tables.TableServiceClientBuilder; +import com.azure.storage.blob.BlobContainerClient; +import com.azure.storage.blob.BlobServiceClient; +import com.azure.storage.blob.BlobServiceClientBuilder; +import com.azure.storage.queue.QueueClient; +import com.azure.storage.queue.QueueServiceClient; +import com.azure.storage.queue.QueueServiceClientBuilder; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.testcontainers.utility.DockerImageName; + +import java.io.File; +import java.net.URL; +import java.util.Optional; +import java.util.Properties; + +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"; + + private static Properties originalSystemProperties; + + @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.trustStorePassword", PASSWORD); + System.setProperty("javax.net.ssl.trustStoreType", "PKCS12"); + } + + @AfterClass + 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); + } + + @Test + public void testWithQueueServiceClient() { + final String connectionString = emulator.getDefaultConnectionString(); + testQueue(connectionString); + } + + @Test + public void testWithTableServiceClient() { + // getTableConnectionString { + final String connectionString = emulator.getDefaultConnectionString(); + // } + testTable(connectionString); + } + + @Test + public void testWithBlobServiceClientWithSslUsingPfx() { + final String connectionString = pfxEmulator.getDefaultConnectionString(); + testBlob(connectionString); + } + + @Test + public void testWithQueueServiceClientWithSslUsingPfx() { + final String connectionString = pfxEmulator.getDefaultConnectionString(); + testQueue(connectionString); + } + + @Test + public void testWithTableServiceClientWithSslUsingPfx() { + final String connectionString = pfxEmulator.getDefaultConnectionString(); + testTable(connectionString); + } + + @Test + public void testWithBlobServiceClientWithSslUsingPem() { + final String connectionString = pemEmulator.getDefaultConnectionString(); + testBlob(connectionString); + } + + @Test + public void testWithQueueServiceClientWithSslUsingPem() { + final String connectionString = pemEmulator.getDefaultConnectionString(); + testQueue(connectionString); + } + + @Test + public void testWithTableServiceClientWithSslUsingPem() { + final String connectionString = pemEmulator.getDefaultConnectionString(); + testTable(connectionString); + } + + private void testBlob(final String connectionString) { + // createBlobClient { + final BlobServiceClient blobServiceClient = new BlobServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // } + final BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container"); + + Assert.assertTrue(containerClient.exists()); + } + + private void testQueue(final String connectionString) { + // createQueueClient { + final QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // } + final QueueClient queueClient = queueServiceClient.createQueue("test-queue"); + + Assert.assertNotNull(queueClient.getQueueUrl()); + } + + private void testTable(final String connectionString) { + // createTableClient { + final TableServiceClient tableServiceClient = new TableServiceClientBuilder() + .connectionString(connectionString) + .buildClient(); + // } + final TableClient tableClient = tableServiceClient.createTable("testtable"); + + Assert.assertNotNull(tableClient.getTableEndpoint()); + } + + 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); + } +} diff --git a/modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java deleted file mode 100644 index 6108392e258..00000000000 --- a/modules/azure/src/test/java/org/testcontainers/containers/AzuriteContainerTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.testcontainers.containers; - -import com.azure.data.tables.TableClient; -import com.azure.data.tables.TableServiceClient; -import com.azure.data.tables.TableServiceClientBuilder; -import com.azure.storage.blob.BlobContainerClient; -import com.azure.storage.blob.BlobServiceClient; -import com.azure.storage.blob.BlobServiceClientBuilder; -import com.azure.storage.queue.QueueClient; -import com.azure.storage.queue.QueueServiceClient; -import com.azure.storage.queue.QueueServiceClientBuilder; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.testcontainers.utility.DockerImageName; - -public class AzuriteContainerTest { - - @Rule - // blobEmulatorContainer { - public AzuriteContainer blobEmulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite") - ) - .withBlobPort(10000) - .withoutQueue() - .withoutTable(); - - // } - - @Rule - // queueEmulatorContainer { - public AzuriteContainer queueEmulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite") - ) - .withQueuePort(10001) - .withoutBlob() - .withoutTable(); - - // } - - @Rule - // tableEmulatorContainer { - public AzuriteContainer tableEmulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite") - ) - .withTablePort(10002) - .withoutBlob() - .withoutQueue(); - - // } - - @Test - public void testWithBlobServiceClient() { - // getBlobConnectionString { - final String connectionString = blobEmulator.getDefaultConnectionString(); - // } - // createBlobClient { - final BlobServiceClient blobServiceClient = new BlobServiceClientBuilder() - .connectionString(connectionString) - .buildClient(); - // } - // testWithBlobClient { - final BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container"); - - Assert.assertTrue(containerClient.exists()); - // } - } - - @Test - public void testWithQueueServiceClient() { - // getQueueConnectionString { - final String connectionString = blobEmulator.getDefaultConnectionString(); - // } - // createQueueClient { - final QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() - .connectionString(connectionString) - .buildClient(); - // } - // testWithQueueClient { - final QueueClient queueClient = queueServiceClient.createQueue("test-queue"); - - Assert.assertNotNull(queueClient.getQueueUrl()); - // } - } - - @Test - public void testWithTableServiceClient() { - // getTableConnectionString { - final String connectionString = blobEmulator.getDefaultConnectionString(); - // } - // createTableClient { - final TableServiceClient tableServiceClient = new TableServiceClientBuilder() - .connectionString(connectionString) - .buildClient(); - // } - // testWithTableClient { - final TableClient tableClient = tableServiceClient.createTable("testtable"); - - Assert.assertNotNull(tableClient.getTableEndpoint()); - // } - } -} diff --git a/modules/azure/src/test/resources/certificate.pem b/modules/azure/src/test/resources/certificate.pem new file mode 100644 index 00000000000..30bedc29f45 --- /dev/null +++ b/modules/azure/src/test/resources/certificate.pem @@ -0,0 +1,23 @@ +Bag Attributes + friendlyName: localhost + localKeyID: 54 69 6D 65 20 31 37 33 34 37 32 32 33 32 31 33 31 39 +subject=CN = localhost +issuer=CN = localhost +-----BEGIN CERTIFICATE----- +MIIC5zCCAc+gAwIBAgIILe7i2bhRE5cwDQYJKoZIhvcNAQEMBQAwFDESMBAGA1UE +AxMJbG9jYWxob3N0MB4XDTI0MTIyMDE5MTg0MVoXDTQ0MTIxNTE5MTg0MVowFDES +MBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAoqYNmLl8IiIoYrXdcoWiMQaM0lOHcV9v3A/THMremHxsR+JPm3FIOAuilFcy +my16kuXIWHfisPxUWr9Vbf8wP/WwZutoOofJrqmruZoorQcNLCs8mQweguRmL1ju +/lDh/9bP626vP9OjwStC4UO4f8Jga8ENoH1U+j1RsIAswYnkk3YIN6YrYv66UvtH +IfR0ERgid2LMBIM+2KD2zw4QRyqXH7Qvo7sCsxdYYHGa6GXfza4vgvce9kJwGqn5 +wiF0Uw9XQbr/LarnR2GCy020OB81KweQJNIh27FZSRLtT+XpsjDRcC2aLBd8CRHd +hwO2zAPI04dLbLM5XAHlEdfT7wIDAQABoz0wOzAdBgNVHQ4EFgQUPqY5isb6Q11Q +t6dbXYHEupxADdMwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3 +DQEBDAUAA4IBAQA2katMXrTJBukiNh9yceLO/MewsxvU3KOO/O89ngfjhKXm9T8E +RtENCmp7hLbj1Aj4PRZx3AbmUt9+tRu8fmrRXJQWgUDSHJWjDwSTBOaHcC5LDWSU +Ex4co5Mnxvrimg7tqQg82Hw/yLH9j6gyTyh6v45QETP7IUkTZe4fg75/kPjng7Xg +wp/QXFUx/f0dbvGRl2Fdgg0SnYFqHS3MFIjjFjv8SQlV7rZe+CD1Lxqy/Z6Fd/Fa +33TzTuJeSAG43vdkGAvsNK/KdnxAW03T4l3pVHpNPcvsIvJUMeKOwYOjwHF/eowk +tGrKbpUYFxUr9iKHTfu14t1oExhAsnda2Fcs +-----END CERTIFICATE----- diff --git a/modules/azure/src/test/resources/key.pem b/modules/azure/src/test/resources/key.pem new file mode 100644 index 00000000000..7c635f5a278 --- /dev/null +++ b/modules/azure/src/test/resources/key.pem @@ -0,0 +1,32 @@ +Bag Attributes + friendlyName: localhost + localKeyID: 54 69 6D 65 20 31 37 33 34 37 32 32 33 32 31 33 31 39 +Key Attributes: +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCipg2YuXwiIihi +td1yhaIxBozSU4dxX2/cD9Mcyt6YfGxH4k+bcUg4C6KUVzKbLXqS5chYd+Kw/FRa +v1Vt/zA/9bBm62g6h8muqau5miitBw0sKzyZDB6C5GYvWO7+UOH/1s/rbq8/06PB +K0LhQ7h/wmBrwQ2gfVT6PVGwgCzBieSTdgg3piti/rpS+0ch9HQRGCJ3YswEgz7Y +oPbPDhBHKpcftC+juwKzF1hgcZroZd/Nri+C9x72QnAaqfnCIXRTD1dBuv8tqudH +YYLLTbQ4HzUrB5Ak0iHbsVlJEu1P5emyMNFwLZosF3wJEd2HA7bMA8jTh0tsszlc +AeUR19PvAgMBAAECggEAFT8dzZKFTawqnGJncBtWyZKyeJMiwUOXSCblDADQPRkb +x/QfNA4DQhb7AOe3G6BAP8o2dqAKg9YiasxNq5XHRsOgbIFZ1zN/vAo7/X3OzHN8 +XAW138Q+hBiz5IF4js4gB5yXAokt6WeLH6O4E9cV1dKdZ9YLIqjcnee+sRC9R/a3 +CexqLfC6b77JFbtePfq+5cn2RiK540tO/4k+F+kfJtTg78Wf2RB3A0pBAunhPSd5 +eyjiSvOZtTcvl4GdYw9nKf24I1/WUvt9FH/r1XG0CM5iwuGodbBz1iSUDaQGi5Lf +hFWofXt7eebgsPEKciG4xTyk51p9fy9y8asY+jCbkQKBgQDG2UqJToR8G4Fk6uaO +/XJa15TibIwQDEota0OdlXg2ZR4864fkIBv+UTbymZEM/EBuSdMM1CUBDvYHcFQX +Aj8p1LUyKP2QYwxV/OoPfJ5fBqxqONNR1fLFg7xCxnf9kSvsni2WFneQUrTDl8+7 +qnHm4IKPkAxZ4Orxl5qIBmlpGQKBgQDRZUL3cHIVLLg/aZACpo6SYDYg2bztXmz4 +lRk9j17q1uS83Umzd2lPFmSt/Nr85EKraxXZ/lYPKrP/r1pf1/35eXOWqmYBWgo/ +Hh7OzL12bhvv9UWEY/TvW+wNJNtXlJSjEFRN4tjoG2amYumyhwMO1lIulplUWvtw +ymm8hDjeRwKBgCq7n60KVqZlMtWBNbMc/GpRUgmm0iLQwVApcQp4iLEH4gutgjKg +Q+PPiENyhR2JSD9rVhO3s4warvzCQw/+x5wxvg7diEBzSL9h7tsNKOu6/2qEc8Vu +eRHBUb/37ulrPUlIZPuQMHmvjHFMOrRV2MyJCwXXKxBVqafpsKfy2MxhAoGBAIHH +Cswk6u/ouYDDwjeCVxatfp65lHhhb5RZhD09IIzYBwhu9gC+34veyyNydZ8LMa7g +PbjQAzJ/OvQbEB4a1hPKjDMzBOmNjpAz8NAm4L4H3FTKZP16nhHDnPdAgpkzQzQV +KMrk755bbTFuWH0HZIPLnT+2ou0/PltXeFUYdc59AoGBAIGfWgSOiw7aXbSQZFrO +4S0v3VTwTaiGDVS4pkNRLlhEJUhy8+gbLv/zYDmFmGtqVhXTb/nd6DOdylp+W/HS +8xNWBMWdlX/hVdSK7M0TdJvAaCaMidlquf5qZ2tGNNDeTUN1qbRH26pm8vdNZ3gr +Y/WWJGo0iEmwyB8RcFhvNmuJ +-----END PRIVATE KEY----- diff --git a/modules/azure/src/test/resources/keystore.pfx b/modules/azure/src/test/resources/keystore.pfx new file mode 100644 index 0000000000000000000000000000000000000000..3fd2975d3e84b093f213e0813d99e304c1c5c852 GIT binary patch literal 2606 zcma)8S5y-U5+#*hLJ>re{^*cU9vuYfAXTamqz9yk^bd-H)*X;RdHlqaG{Z&IX7 zdoe_sR3(5?Oj!2p9^dZQ?#G;&xik0v%{>Fh(1-y6AUKA47D_FasGs(u_S)qxWfx#MY7TGY2J_cZ3PGvWu;dD@{e<=c~Arx?KDD~Y$eSkX%3=jh| znelIctPA{%*x!yxLAjjW!5HwQE5ET?%9T>uvL=IB)q6*nnK-HFL9Q{cG#Xvyq3s94 zEX0MHl?GKaB<8(e?GURr3BvZ;TZYY5-Yyzeh$kNZfeksdBV}x8j&J=xp*+!A+Mqkg1}TgxS1buTSJ z0mQDj)m{5kc!K)P)FVQ2BTVAt&&2~cePc3;SM$oA%GJkBgR4dAqdhs!(q(4A*$2vi zz(Dj$o5;7r8Z9dvzxb0HsfBTETy4O7=m;^4>mY^7id55X`sMH}IQ>nkCIjk4r)4Bs zfn&;<9lEg?ZnIRQ?OY}k6IUzp>cu;MPre`0{N!ipy6@LqyW)K zP*&ZRvjh2w8_iLzLVBuEk$~}J%J`j?> zmJ@J2I3JW3jm3gYZIEN>^3vqhXf8~|L&0l2bNZvX#g%70p5E%a&Cj+UBajzj5VL{+7xBg8qTwc_xEj#bxLEh=ngs?JP^ulUfC z;O{RiQb#+zMpRpi?0s)c_>U=lq#Wv67cSUn2|alT30|w%cJA5ftuQ_ z2Pq_FLW|Ct(RWzT&d**>KEqVRBV3(K*WzkxnBT-@slPv0F#8o%GLfBo0+(0TA7zV z*XEFLw{F~LD|USFII0TZ$~j1fi&x9WsC;CR76RL3YSb^sShiU+8k3MrO$2>>WGKkj zXZJPyuJOKR@~)L+Pn*fN9?RAVA(3^4IT1e}3&R%5KT1+gm^GR-yrI)lVy38UgF-ck z0r{?}s#@L`lFa+}(r<$lpD3SP6q|fL`1lAH09AVQmYyomJFneulPH-$A#P*apuLv@ zj)&!i4bJ@4oEj-^EL_A4y0guFBR!Tepu(E2vha1N#J&MnhK{*o$&c^FQA)G)M~VG2 zIbIFt!G*8`*^cmLe*#_giWGel4_2-2*Y9EdDTqAEAh_t zEXQ2YDfEC?3nFW`1srd(_!8emMBJL);c-8)-S*R4rr{Jya(Mpi#Zxn2&n%0UqHjoi=MK)icL!N*So&yB z{3E56|HjsWML*R2QR_BXU_gOA(O#z2Jb97vzRdf0frq31X#)70dn+DXd~1OuhQ)ql zeHJrh4xM(v+1ho$)&zqwwDZ#<1&TLWjEhg23<*B5^gGk?Q?L%d3bgE0P&a-Q2u>oL zRv~oZe823Hniau%oteUi!k@yG!uc|zE~`L_p#NN9L$HFGZ+rQ=^CA>vF*DOnWp|CsgI z+X|&Zfp#Z(TJrhz1So3^26R6woshp$lX>v6`2N^)M{^eKjCg5tbidz_`#cY3ZEr2S ze#`!+gidJp^(b_{RPH0jgrQVS=Z zTiE_LbTGjNqfv^UnHFO?`IB;H?9F-pPZ=C5u#vMROO@16yZLQ7Dwd-Q+@@nef}Z0x zdjfZF{~NQ>(ES|QfN4X?n>F4m&yth-CQE*ht-}PI%k>n?d*1w%5YJWrTB;+gVvKto zos&!ZQ}dHv$9etdlVsuS#=0f9g<$-^kWd$CxW1ddXp2R=L`REsc|r`YVrxKkEfZTW z+0FV0&-1uP9L(CsD5(&zsV#=Nis-Ft7U1;~{^23iBKrAkg`}Lh(Hu(y}PcY5w#{M0|h%iB4a{xxOtRC*fV zQ1b1-*Xm(~GF!ny&pmWrfGQ_Fxslv`m#)hLSs-nHqcH@iK#w>~(?#%@9c<_>e|=YZ z+qpi8aodQ?+Nv`uAv@e9vo+&9gdMr!)iFXP-gYP%4ax8Gy~iQfkr#7}(OT8klG0Sz zknW{C@$6-iEgfe;ax4dTgI0jn@^(ahKE}`9mU(npUCE)DAp22Zv**Qq zs7Buw3XgHHqDh2|N$w32McC(74JgE zK#Y0a_p%~``30+H(3r@qqM2(+@Syad9avV+Px^=U1bN;yL{xGnFQDH{= zheF Date: Fri, 20 Dec 2024 20:49:24 +0100 Subject: [PATCH 03/13] Add Azurite container to Azure module - Remove unnecessary comment Signed-off-by: Esta Nagy --- .../java/org/testcontainers/azure/AzuriteContainerTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index 4bba16f23a4..4c17385f646 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -86,9 +86,7 @@ public void testWithQueueServiceClient() { @Test public void testWithTableServiceClient() { - // getTableConnectionString { final String connectionString = emulator.getDefaultConnectionString(); - // } testTable(connectionString); } From 2035435fa15118981ef99a091a657964424dbc00 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Fri, 20 Dec 2024 23:56:25 +0100 Subject: [PATCH 04/13] Add Azurite container to Azure module - Fix note formatting Signed-off-by: Esta Nagy --- docs/modules/azure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/azure.md b/docs/modules/azure.md index 487bf345918..dff57fd7c54 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -22,8 +22,8 @@ Start Azurite Emulator during a test: [Starting a Azurite Blob container](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainer -> [!TIP] -> SSL configuration is possible using the `withSsl(File, String)` and `withSsl(File, File)` methods. +!!! note + SSL configuration is possible using the `withSsl(File, String)` and `withSsl(File, File)` methods. Get the connection string from the container: From 55c7212d425ed30a8b099e02ce6d3c49dc959bcf Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Sat, 21 Dec 2024 00:02:07 +0100 Subject: [PATCH 05/13] Add Azurite container to Azure module - Use AssertJ in tests Signed-off-by: Esta Nagy --- .../org/testcontainers/azure/AzuriteContainerTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index 4c17385f646..993cf693395 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -10,7 +10,6 @@ import com.azure.storage.queue.QueueServiceClient; import com.azure.storage.queue.QueueServiceClientBuilder; import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; @@ -21,6 +20,8 @@ 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"); @@ -134,7 +135,7 @@ private void testBlob(final String connectionString) { // } final BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container"); - Assert.assertTrue(containerClient.exists()); + assertThat(containerClient.exists()).isTrue(); } private void testQueue(final String connectionString) { @@ -145,7 +146,7 @@ private void testQueue(final String connectionString) { // } final QueueClient queueClient = queueServiceClient.createQueue("test-queue"); - Assert.assertNotNull(queueClient.getQueueUrl()); + assertThat(queueClient.getQueueUrl()).isNotNull(); } private void testTable(final String connectionString) { @@ -156,7 +157,7 @@ private void testTable(final String connectionString) { // } final TableClient tableClient = tableServiceClient.createTable("testtable"); - Assert.assertNotNull(tableClient.getTableEndpoint()); + assertThat(tableClient.getTableEndpoint()).isNotNull(); } private static File getResourceFile(final String resourceName) { From 4c6ec20cf35520ceba6e981692baaaae3d579839 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Mon, 23 Dec 2024 01:02:41 +0100 Subject: [PATCH 06/13] Add Azurite container to Azure module - Fix configuration issue (to allow connections from any IP) Signed-off-by: Esta Nagy --- .../azure/AzuriteContainer.java | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index 0bea1692854..77091f8074a 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -24,6 +24,8 @@ public class AzuriteContainer extends GenericContainer { private static final String DEFAULT_HOST = "127.0.0.1"; + private static final String ALLOW_ALL_CONNECTIONS = "0.0.0.0"; + private static final int DEFAULT_BLOB_PORT = 10000; private static final int DEFAULT_QUEUE_PORT = 10001; @@ -31,7 +33,7 @@ public class AzuriteContainer extends GenericContainer { private static final int DEFAULT_TABLE_PORT = 10002; private static final String CONNECTION_STRING_FORMAT = - "DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s://%s:%d/%s;QueueEndpoint=%s://%s:%d/%s;TableEndpoint=%s://%s:%d/%s;"; + "DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s://%s:%d/%s;QueueEndpoint=%s://%s:%d/%s;TableEndpoint=%s://%s:%d/%s;"; /** * The account name of the default credentials. @@ -42,10 +44,10 @@ public class AzuriteContainer extends GenericContainer { * The account key of the default credentials. */ public static final String WELL_KNOWN_ACCOUNT_KEY = - "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; + "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( - "mcr.microsoft.com/azure-storage/azurite" + "mcr.microsoft.com/azure-storage/azurite" ); private String host = DEFAULT_HOST; @@ -141,30 +143,30 @@ public String getDefaultConnectionString() { public String getConnectionString(final String accountName, final String accountKey) { final String protocol = cert != null ? "https" : "http"; return String.format( - CONNECTION_STRING_FORMAT, - protocol, - accountName, - accountKey, - protocol, - host, - getMappedPort(DEFAULT_BLOB_PORT), - accountName, - protocol, - host, - getMappedPort(DEFAULT_QUEUE_PORT), - accountName, - protocol, - host, - getMappedPort(DEFAULT_TABLE_PORT), - accountName + CONNECTION_STRING_FORMAT, + protocol, + accountName, + accountKey, + protocol, + host, + getMappedPort(DEFAULT_BLOB_PORT), + accountName, + protocol, + host, + getMappedPort(DEFAULT_QUEUE_PORT), + accountName, + protocol, + host, + getMappedPort(DEFAULT_TABLE_PORT), + accountName ); } String getCommandLine() { final StringBuilder args = new StringBuilder("azurite"); - args.append(" --blobHost ").append(host).append(" --blobPort ").append(DEFAULT_BLOB_PORT); - args.append(" --queueHost ").append(host).append(" --queuePort ").append(DEFAULT_QUEUE_PORT); - args.append(" --tableHost ").append(host).append(" --tablePort ").append(DEFAULT_TABLE_PORT); + 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"); if (cert != null) { args.append(" --cert ").append("/cert").append(certExtension); From eaaa0949febfa9d8e259413ef69a799ece81cedf Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Mon, 23 Dec 2024 01:05:57 +0100 Subject: [PATCH 07/13] Add Azurite container to Azure module - Fix formatting Signed-off-by: Esta Nagy --- .../azure/AzuriteContainer.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index 77091f8074a..552fa68e30e 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -33,7 +33,7 @@ public class AzuriteContainer extends GenericContainer { private static final int DEFAULT_TABLE_PORT = 10002; private static final String CONNECTION_STRING_FORMAT = - "DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s://%s:%d/%s;QueueEndpoint=%s://%s:%d/%s;TableEndpoint=%s://%s:%d/%s;"; + "DefaultEndpointsProtocol=%s;AccountName=%s;AccountKey=%s;BlobEndpoint=%s://%s:%d/%s;QueueEndpoint=%s://%s:%d/%s;TableEndpoint=%s://%s:%d/%s;"; /** * The account name of the default credentials. @@ -44,10 +44,10 @@ public class AzuriteContainer extends GenericContainer { * The account key of the default credentials. */ public static final String WELL_KNOWN_ACCOUNT_KEY = - "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; + "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse( - "mcr.microsoft.com/azure-storage/azurite" + "mcr.microsoft.com/azure-storage/azurite" ); private String host = DEFAULT_HOST; @@ -143,22 +143,22 @@ public String getDefaultConnectionString() { public String getConnectionString(final String accountName, final String accountKey) { final String protocol = cert != null ? "https" : "http"; return String.format( - CONNECTION_STRING_FORMAT, - protocol, - accountName, - accountKey, - protocol, - host, - getMappedPort(DEFAULT_BLOB_PORT), - accountName, - protocol, - host, - getMappedPort(DEFAULT_QUEUE_PORT), - accountName, - protocol, - host, - getMappedPort(DEFAULT_TABLE_PORT), - accountName + CONNECTION_STRING_FORMAT, + protocol, + accountName, + accountKey, + protocol, + host, + getMappedPort(DEFAULT_BLOB_PORT), + accountName, + protocol, + host, + getMappedPort(DEFAULT_QUEUE_PORT), + accountName, + protocol, + host, + getMappedPort(DEFAULT_TABLE_PORT), + accountName ); } From 2c83a055d725f70dba3614b6fa9a02c8e9e1d238 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Tue, 24 Dec 2024 21:34:55 +0100 Subject: [PATCH 08/13] Add Azurite container to Azure module - Fix code review findings Signed-off-by: Esta Nagy --- docs/modules/azure.md | 8 +- .../azure/AzuriteContainer.java | 38 ++-- .../azure/AzuriteContainerTest.java | 182 +++++++++++------- 3 files changed, 128 insertions(+), 100 deletions(-) diff --git a/docs/modules/azure.md b/docs/modules/azure.md index dff57fd7c54..5d3da034f94 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -23,13 +23,7 @@ Start Azurite Emulator during a test: !!! note - SSL configuration is possible using the `withSsl(File, String)` and `withSsl(File, File)` methods. - -Get the connection string from the container: - - -[Get connection string](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:getConnectionString - + SSL configuration is possible using the `withSsl(MountableFile, String)` and `withSsl(MountableFile, MountableFile)` methods. #### Using with Blob diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index 552fa68e30e..b2338a29608 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -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. @@ -17,8 +15,6 @@ *

  • 10001 (queue port)
  • *
  • 10002 (table port)
  • * - *

    - * See command line options here. */ public class AzuriteContainer extends GenericContainer { @@ -38,12 +34,12 @@ public class AzuriteContainer extends GenericContainer { /** * 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( @@ -52,11 +48,11 @@ public class AzuriteContainer extends GenericContainer { 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; @@ -66,6 +62,7 @@ public class AzuriteContainer extends GenericContainer { public AzuriteContainer(final DockerImageName dockerImageName) { super(dockerImageName); dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); + withExposedPorts(DEFAULT_BLOB_PORT, DEFAULT_QUEUE_PORT, DEFAULT_TABLE_PORT); } /** @@ -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"; @@ -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"; @@ -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); } /** @@ -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) { diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index 993cf693395..5d200a56ab7 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -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"; @@ -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"); } @@ -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); - } } From e197419a1cfaa85efad9adbade211526ee093412 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Mon, 6 Jan 2025 23:50:47 +0100 Subject: [PATCH 09/13] Add Azurite container to Azure module - Fix code review findings Signed-off-by: Esta Nagy --- .../testcontainers/azure/AzuriteContainer.java | 6 +++--- .../azure/AzuriteContainerTest.java | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index b2338a29608..0fd12c314c2 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -141,15 +141,15 @@ public String getConnectionString(final String accountName, final String account accountName, accountKey, protocol, - host, + getHost(), getMappedPort(DEFAULT_BLOB_PORT), accountName, protocol, - host, + getHost(), getMappedPort(DEFAULT_QUEUE_PORT), accountName, protocol, - host, + getHost(), getMappedPort(DEFAULT_TABLE_PORT), accountName ); diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index 5d200a56ab7..ff4ab3a2972 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -49,7 +49,7 @@ public void testWithBlobServiceClient() { // emulatorContainer { AzuriteContainer emulator = new AzuriteContainer( DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ); + ) // } ) { emulator.start(); @@ -62,7 +62,7 @@ public void testWithQueueServiceClient() { try ( AzuriteContainer emulator = new AzuriteContainer( DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ); + ) ) { emulator.start(); testQueue(emulator); @@ -74,7 +74,7 @@ public void testWithTableServiceClient() { try ( AzuriteContainer emulator = new AzuriteContainer( DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ); + ) ) { emulator.start(); testTable(emulator); @@ -88,7 +88,7 @@ public void testWithBlobServiceClientWithSslUsingPfx() { DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") ) .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) - .withHost(LOOPBACK_IP); + .withHost(LOOPBACK_IP) ) { emulator.start(); testBlob(emulator); @@ -102,7 +102,7 @@ public void testWithQueueServiceClientWithSslUsingPfx() { DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") ) .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) - .withHost(LOOPBACK_IP); + .withHost(LOOPBACK_IP) ) { emulator.start(); testQueue(emulator); @@ -116,7 +116,7 @@ public void testWithTableServiceClientWithSslUsingPfx() { DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") ) .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) - .withHost(LOOPBACK_IP); + .withHost(LOOPBACK_IP) ) { emulator.start(); testTable(emulator); @@ -133,7 +133,7 @@ public void testWithBlobServiceClientWithSslUsingPem() { MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) - .withHost(LOOPBACK_IP); + .withHost(LOOPBACK_IP) ) { emulator.start(); testBlob(emulator); @@ -150,7 +150,7 @@ public void testWithQueueServiceClientWithSslUsingPem() { MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) - .withHost(LOOPBACK_IP); + .withHost(LOOPBACK_IP) ) { emulator.start(); testQueue(emulator); @@ -167,7 +167,7 @@ public void testWithTableServiceClientWithSslUsingPem() { MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) - .withHost(LOOPBACK_IP); + .withHost(LOOPBACK_IP) ) { emulator.start(); testTable(emulator); From b971004b66ba2aa4d306141195c465b9015a84d5 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Tue, 7 Jan 2025 00:10:24 +0100 Subject: [PATCH 10/13] Add Azurite container to Azure module - Remove host configuration Signed-off-by: Esta Nagy --- .../org/testcontainers/azure/AzuriteContainer.java | 13 ------------- .../testcontainers/azure/AzuriteContainerTest.java | 8 -------- 2 files changed, 21 deletions(-) diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index 0fd12c314c2..eb7435f0ead 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -46,8 +46,6 @@ public class AzuriteContainer extends GenericContainer { "mcr.microsoft.com/azure-storage/azurite" ); - private String host = DEFAULT_HOST; - private MountableFile cert = null; private String certExtension = null; @@ -93,17 +91,6 @@ public AzuriteContainer withSsl(final MountableFile pemCert, final MountableFile return this; } - /** - * Sets the hostname we want to use to connect to our emulator. (default: {@link #DEFAULT_HOST}) - * - * @param host The host name - * @return this - */ - public AzuriteContainer withHost(final String host) { - this.host = host; - return this; - } - @Override protected void configure() { withCommand(getCommandLine()); diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index ff4ab3a2972..655f61555ff 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -23,8 +23,6 @@ public class AzuriteContainerTest { private static final String PASSWORD = "changeit"; - private static final String LOOPBACK_IP = "127.0.0.1"; - private static Properties originalSystemProperties; @BeforeClass @@ -88,7 +86,6 @@ public void testWithBlobServiceClientWithSslUsingPfx() { DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") ) .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) - .withHost(LOOPBACK_IP) ) { emulator.start(); testBlob(emulator); @@ -102,7 +99,6 @@ public void testWithQueueServiceClientWithSslUsingPfx() { DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") ) .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) - .withHost(LOOPBACK_IP) ) { emulator.start(); testQueue(emulator); @@ -116,7 +112,6 @@ public void testWithTableServiceClientWithSslUsingPfx() { DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") ) .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) - .withHost(LOOPBACK_IP) ) { emulator.start(); testTable(emulator); @@ -133,7 +128,6 @@ public void testWithBlobServiceClientWithSslUsingPem() { MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) - .withHost(LOOPBACK_IP) ) { emulator.start(); testBlob(emulator); @@ -150,7 +144,6 @@ public void testWithQueueServiceClientWithSslUsingPem() { MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) - .withHost(LOOPBACK_IP) ) { emulator.start(); testQueue(emulator); @@ -167,7 +160,6 @@ public void testWithTableServiceClientWithSslUsingPem() { MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) - .withHost(LOOPBACK_IP) ) { emulator.start(); testTable(emulator); From 0f11e4b1bbd8101f53f11c57fb8493240e7005ae Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Tue, 7 Jan 2025 00:13:08 +0100 Subject: [PATCH 11/13] Add Azurite container to Azure module - Remove unused constant Signed-off-by: Esta Nagy --- .../main/java/org/testcontainers/azure/AzuriteContainer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index eb7435f0ead..5ef51b15967 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -18,8 +18,6 @@ */ public class AzuriteContainer extends GenericContainer { - private static final String DEFAULT_HOST = "127.0.0.1"; - private static final String ALLOW_ALL_CONNECTIONS = "0.0.0.0"; private static final int DEFAULT_BLOB_PORT = 10000; From 4a522bac62df8f8bb1903fb04a0cae212cc3d9e7 Mon Sep 17 00:00:00 2001 From: Esta Nagy Date: Tue, 7 Jan 2025 22:15:07 +0100 Subject: [PATCH 12/13] Add Azurite container to Azure module - Add test cases and examples for non-default credential use Signed-off-by: Esta Nagy --- docs/modules/azure.md | 23 +++++ .../azure/AzuriteContainerTest.java | 83 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/docs/modules/azure.md b/docs/modules/azure.md index 5d3da034f94..dc591596ad0 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -25,6 +25,17 @@ Start Azurite Emulator during a test: !!! note SSL configuration is possible using the `withSsl(MountableFile, String)` and `withSsl(MountableFile, MountableFile)` methods. +If the tested application needs to use more than one set of credentials, the container can be configured to use custom credentials. +Please see some examples below. + + +[Starting a Azurite Blob container with one account and two keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainerWithTwoAccountKeys + + + +[Starting a Azurite Blob container with more accounts and keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:useEmulatorContainerWithMoreAccounts + + #### Using with Blob Build Azure Blob client: @@ -33,6 +44,12 @@ Build Azure Blob client: [Build Azure Blob Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createBlobClient +In case the application needs to use custom credentials, we can obtain them with a different method: + + +[Obtain connection string with non-default credentials](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:useNonDefaultCredentials + + #### Using with Queue Build Azure Queue client: @@ -41,6 +58,9 @@ Build Azure Queue client: [Build Azure Queue Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createQueueClient +!!! note + We can use custom credentials the same way as defined in the Blob section. + #### Using with Table Build Azure Table client: @@ -49,6 +69,9 @@ Build Azure Table client: [Build Azure Table Service client](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:createTableClient +!!! note + We can use custom credentials the same way as defined in the Blob section. + ### CosmosDB Start Azure CosmosDB Emulator during a test: diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index 655f61555ff..d5ef2dd84eb 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -1,8 +1,10 @@ package org.testcontainers.azure; +import com.azure.core.util.BinaryData; import com.azure.data.tables.TableClient; import com.azure.data.tables.TableServiceClient; import com.azure.data.tables.TableServiceClientBuilder; +import com.azure.storage.blob.BlobClient; import com.azure.storage.blob.BlobContainerClient; import com.azure.storage.blob.BlobServiceClient; import com.azure.storage.blob.BlobServiceClientBuilder; @@ -166,6 +168,87 @@ public void testWithTableServiceClientWithSslUsingPem() { } } + @Test + public void testTwoAccountKeysWithBlobServiceClient() { + try ( + // emulatorContainerWithTwoAccountKeys { + AzuriteContainer emulator = new AzuriteContainer( + DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") + ) + .withEnv("AZURITE_ACCOUNTS", "account1:key1:key2") + // } + ) { + emulator.start(); + + String connectionString1 = emulator.getConnectionString("account1", "key1"); + // the second accuont will have access to the same container using a different key + String connectionString2 = emulator.getConnectionString("account1", "key2"); + + BlobServiceClient blobServiceClient1 = new BlobServiceClientBuilder() + .connectionString(connectionString1) + .buildClient(); + + BlobContainerClient containerClient1 = blobServiceClient1.createBlobContainer("test-container"); + BlobClient blobClient1 = containerClient1.getBlobClient("test-blob.txt"); + blobClient1.upload(BinaryData.fromString("content")); + boolean existsWithAccount1 = blobClient1.exists(); + String contentWithAccount1 = blobClient1.downloadContent().toString(); + + BlobServiceClient blobServiceClient2 = new BlobServiceClientBuilder() + .connectionString(connectionString2) + .buildClient(); + BlobContainerClient containerClient2 = blobServiceClient2.getBlobContainerClient("test-container"); + BlobClient blobClient2 = containerClient2.getBlobClient("test-blob.txt"); + boolean existsWithAccount2 = blobClient2.exists(); + String contentWithAccount2 = blobClient2.downloadContent().toString(); + + assertThat(existsWithAccount1).isTrue(); + assertThat(contentWithAccount1).isEqualTo("content"); + assertThat(existsWithAccount2).isTrue(); + assertThat(contentWithAccount2).isEqualTo("content"); + } + } + + @Test + public void testMultipleAccountsWithBlobServiceClient() { + try ( + // emulatorContainerWithMoreAccounts { + AzuriteContainer emulator = new AzuriteContainer( + DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") + ) + .withEnv("AZURITE_ACCOUNTS", "account1:key1;account2:key2") + // } + ) { + emulator.start(); + + // useNonDefaultCredentials { + String connectionString1 = emulator.getConnectionString("account1", "key1"); + // the second accuont will not have access to the same container + String connectionString2 = emulator.getConnectionString("account2", "key2"); + // } + BlobServiceClient blobServiceClient1 = new BlobServiceClientBuilder() + .connectionString(connectionString1) + .buildClient(); + + BlobContainerClient containerClient1 = blobServiceClient1.createBlobContainer("test-container"); + BlobClient blobClient1 = containerClient1.getBlobClient("test-blob.txt"); + blobClient1.upload(BinaryData.fromString("content")); + boolean existsWithAccount1 = blobClient1.exists(); + String contentWithAccount1 = blobClient1.downloadContent().toString(); + + BlobServiceClient blobServiceClient2 = new BlobServiceClientBuilder() + .connectionString(connectionString2) + .buildClient(); + BlobContainerClient containerClient2 = blobServiceClient2.createBlobContainer("test-container"); + BlobClient blobClient2 = containerClient2.getBlobClient("test-blob.txt"); + boolean existsWithAccount2 = blobClient2.exists(); + + assertThat(existsWithAccount1).isTrue(); + assertThat(contentWithAccount1).isEqualTo("content"); + assertThat(existsWithAccount2).isFalse(); + } + } + private void testBlob(AzuriteContainer container) { // createBlobClient { BlobServiceClient blobServiceClient = new BlobServiceClientBuilder() From 7541c38218befcf64e71f505954c2a27c847e2bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez?= Date: Wed, 8 Jan 2025 10:38:21 -0500 Subject: [PATCH 13/13] Polish --- docs/modules/azure.md | 6 +- .../azure/AzuriteContainer.java | 49 +++++++------ .../azure/AzuriteContainerTest.java | 72 +++++++------------ 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/docs/modules/azure.md b/docs/modules/azure.md index dc591596ad0..19c141c7639 100644 --- a/docs/modules/azure.md +++ b/docs/modules/azure.md @@ -19,7 +19,7 @@ CosmosDBEmulatorContainer | [mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emula Start Azurite Emulator during a test: -[Starting a Azurite Blob container](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainer +[Starting a Azurite container](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainer !!! note @@ -29,11 +29,11 @@ If the tested application needs to use more than one set of credentials, the con Please see some examples below. -[Starting a Azurite Blob container with one account and two keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:emulatorContainerWithTwoAccountKeys +[Starting a Azurite Blob container with one account and two keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:withTwoAccountKeys -[Starting a Azurite Blob container with more accounts and keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:useEmulatorContainerWithMoreAccounts +[Starting a Azurite Blob container with more accounts and keys](../../modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java) inside_block:withMoreAccounts #### Using with Blob diff --git a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java index 5ef51b15967..56c58df1f1d 100644 --- a/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java +++ b/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java @@ -11,9 +11,9 @@ *

    * Exposed ports: *

    */ public class AzuriteContainer extends GenericContainer { @@ -55,7 +55,14 @@ public class AzuriteContainer extends GenericContainer { /** * @param dockerImageName specified docker image name to run */ - public AzuriteContainer(final DockerImageName dockerImageName) { + public AzuriteContainer(String dockerImageName) { + this(DockerImageName.parse(dockerImageName)); + } + + /** + * @param dockerImageName specified docker image name to run + */ + public AzuriteContainer(DockerImageName dockerImageName) { super(dockerImageName); dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME); withExposedPorts(DEFAULT_BLOB_PORT, DEFAULT_QUEUE_PORT, DEFAULT_TABLE_PORT); @@ -69,9 +76,9 @@ public AzuriteContainer(final DockerImageName dockerImageName) { * @return this */ public AzuriteContainer withSsl(final MountableFile pfxCert, final String password) { - cert = pfxCert; - pwd = password; - certExtension = ".pfx"; + this.cert = pfxCert; + this.pwd = password; + this.certExtension = ".pfx"; return this; } @@ -83,21 +90,21 @@ public AzuriteContainer withSsl(final MountableFile pfxCert, final String passwo * @return this */ public AzuriteContainer withSsl(final MountableFile pemCert, final MountableFile pemKey) { - cert = pemCert; - key = pemKey; - certExtension = ".pem"; + this.cert = pemCert; + this.key = pemKey; + this.certExtension = ".pem"; return this; } @Override protected void configure() { withCommand(getCommandLine()); - if (cert != null) { - logger().info("Using path for cert file: '{}'", cert); - withCopyFileToContainer(cert, "/cert" + certExtension); - if (key != null) { - logger().info("Using path for key file: '{}'", key); - withCopyFileToContainer(key, "/key.pem"); + if (this.cert != null) { + logger().info("Using path for cert file: '{}'", this.cert); + withCopyFileToContainer(this.cert, "/cert" + this.certExtension); + if (this.key != null) { + logger().info("Using path for key file: '{}'", this.key); + withCopyFileToContainer(this.key, "/key.pem"); } } } @@ -107,7 +114,7 @@ protected void configure() { * * @return connection string */ - public String getDefaultConnectionString() { + public String getConnectionString() { return getConnectionString(WELL_KNOWN_ACCOUNT_NAME, WELL_KNOWN_ACCOUNT_KEY); } @@ -145,10 +152,10 @@ String getCommandLine() { 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) { - args.append(" --pwd ").append(pwd); + if (this.cert != null) { + args.append(" --cert ").append("/cert").append(this.certExtension); + if (this.pwd != null) { + args.append(" --pwd ").append(this.pwd); } else { args.append(" --key ").append("/key.pem"); } diff --git a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java index d5ef2dd84eb..2bf0ad856d3 100644 --- a/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java +++ b/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java @@ -14,7 +14,6 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; import java.util.Properties; @@ -47,36 +46,29 @@ public static void restoreOriginalSystemProperties() { public void testWithBlobServiceClient() { try ( // emulatorContainer { - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") // } ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("BlobEndpoint=http://"); testBlob(emulator); } } @Test public void testWithQueueServiceClient() { - try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) - ) { + try (AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("QueueEndpoint=http://"); testQueue(emulator); } } @Test public void testWithTableServiceClient() { - try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) - ) { + try (AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0")) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("TableEndpoint=http://"); testTable(emulator); } } @@ -84,12 +76,11 @@ public void testWithTableServiceClient() { @Test public void testWithBlobServiceClientWithSslUsingPfx() { try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("BlobEndpoint=https://"); testBlob(emulator); } } @@ -97,12 +88,11 @@ public void testWithBlobServiceClientWithSslUsingPfx() { @Test public void testWithQueueServiceClientWithSslUsingPfx() { try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("QueueEndpoint=https://"); testQueue(emulator); } } @@ -110,12 +100,11 @@ public void testWithQueueServiceClientWithSslUsingPfx() { @Test public void testWithTableServiceClientWithSslUsingPfx() { try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withSsl(MountableFile.forClasspathResource("/keystore.pfx"), PASSWORD) ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("TableEndpoint=https://"); testTable(emulator); } } @@ -123,15 +112,14 @@ public void testWithTableServiceClientWithSslUsingPfx() { @Test public void testWithBlobServiceClientWithSslUsingPem() { try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withSsl( MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("BlobEndpoint=https://"); testBlob(emulator); } } @@ -139,15 +127,14 @@ public void testWithBlobServiceClientWithSslUsingPem() { @Test public void testWithQueueServiceClientWithSslUsingPem() { try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withSsl( MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("QueueEndpoint=https://"); testQueue(emulator); } } @@ -155,15 +142,14 @@ public void testWithQueueServiceClientWithSslUsingPem() { @Test public void testWithTableServiceClientWithSslUsingPem() { try ( - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withSsl( MountableFile.forClasspathResource("/certificate.pem"), MountableFile.forClasspathResource("/key.pem") ) ) { emulator.start(); + assertThat(emulator.getConnectionString()).contains("TableEndpoint=https://"); testTable(emulator); } } @@ -171,17 +157,15 @@ public void testWithTableServiceClientWithSslUsingPem() { @Test public void testTwoAccountKeysWithBlobServiceClient() { try ( - // emulatorContainerWithTwoAccountKeys { - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + // withTwoAccountKeys { + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withEnv("AZURITE_ACCOUNTS", "account1:key1:key2") // } ) { emulator.start(); String connectionString1 = emulator.getConnectionString("account1", "key1"); - // the second accuont will have access to the same container using a different key + // the second account will have access to the same container using a different key String connectionString2 = emulator.getConnectionString("account1", "key2"); BlobServiceClient blobServiceClient1 = new BlobServiceClientBuilder() @@ -212,10 +196,8 @@ public void testTwoAccountKeysWithBlobServiceClient() { @Test public void testMultipleAccountsWithBlobServiceClient() { try ( - // emulatorContainerWithMoreAccounts { - AzuriteContainer emulator = new AzuriteContainer( - DockerImageName.parse("mcr.microsoft.com/azure-storage/azurite:3.33.0") - ) + // withMoreAccounts { + AzuriteContainer emulator = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withEnv("AZURITE_ACCOUNTS", "account1:key1;account2:key2") // } ) { @@ -223,7 +205,7 @@ public void testMultipleAccountsWithBlobServiceClient() { // useNonDefaultCredentials { String connectionString1 = emulator.getConnectionString("account1", "key1"); - // the second accuont will not have access to the same container + // the second account will not have access to the same container String connectionString2 = emulator.getConnectionString("account2", "key2"); // } BlobServiceClient blobServiceClient1 = new BlobServiceClientBuilder() @@ -252,7 +234,7 @@ public void testMultipleAccountsWithBlobServiceClient() { private void testBlob(AzuriteContainer container) { // createBlobClient { BlobServiceClient blobServiceClient = new BlobServiceClientBuilder() - .connectionString(container.getDefaultConnectionString()) + .connectionString(container.getConnectionString()) .buildClient(); // } BlobContainerClient containerClient = blobServiceClient.createBlobContainer("test-container"); @@ -263,7 +245,7 @@ private void testBlob(AzuriteContainer container) { private void testQueue(AzuriteContainer container) { // createQueueClient { QueueServiceClient queueServiceClient = new QueueServiceClientBuilder() - .connectionString(container.getDefaultConnectionString()) + .connectionString(container.getConnectionString()) .buildClient(); // } QueueClient queueClient = queueServiceClient.createQueue("test-queue"); @@ -274,7 +256,7 @@ private void testQueue(AzuriteContainer container) { private void testTable(AzuriteContainer container) { // createTableClient { TableServiceClient tableServiceClient = new TableServiceClientBuilder() - .connectionString(container.getDefaultConnectionString()) + .connectionString(container.getConnectionString()) .buildClient(); // } TableClient tableClient = tableServiceClient.createTable("testtable");