This is an automated email from the ASF dual-hosted git repository. ppalaga pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/master by this push: new 8bbc95d Allow running the Azure test against the real Azure API in addition to local Azurite instance 8bbc95d is described below commit 8bbc95d95a0b20f2bf18c8b3e1442937be9f7912 Author: Peter Palaga <ppal...@redhat.com> AuthorDate: Wed Jan 13 15:55:07 2021 +0100 Allow running the Azure test against the real Azure API in addition to local Azurite instance --- .../test/mock/backend/MockBackendUtils.java | 12 ++- integration-tests/azure/README.adoc | 16 ++++ integration-tests/azure/pom.xml | 5 ++ .../component/azure/it/AzureBlobResource.java | 39 +++++---- .../component/azure/it/AzureQueueResource.java | 27 ++++-- .../src/main/resources/application.properties | 25 ++++++ .../component/azure/it/AzureTestResource.java | 97 +++++++++++++++++----- 7 files changed, 175 insertions(+), 46 deletions(-) diff --git a/integration-tests-support/mock-backend/src/main/java/org/apache/camel/quarkus/test/mock/backend/MockBackendUtils.java b/integration-tests-support/mock-backend/src/main/java/org/apache/camel/quarkus/test/mock/backend/MockBackendUtils.java index 52163b3..0bd5e77 100644 --- a/integration-tests-support/mock-backend/src/main/java/org/apache/camel/quarkus/test/mock/backend/MockBackendUtils.java +++ b/integration-tests-support/mock-backend/src/main/java/org/apache/camel/quarkus/test/mock/backend/MockBackendUtils.java @@ -28,12 +28,20 @@ public class MockBackendUtils { public static void logBackendUsed() { if (startMockBackend) { - LOG.infof("Mock backend will be used"); + logMockBackendUsed(); } else { - LOG.infof("Real backend will be used"); + logRealBackendUsed(); } } + public static void logRealBackendUsed() { + LOG.infof("Real backend will be used"); + } + + public static void logMockBackendUsed() { + LOG.infof("Mock backend will be used"); + } + public static boolean startMockBackend() { return startMockBackend(false); } diff --git a/integration-tests/azure/README.adoc b/integration-tests/azure/README.adoc new file mode 100644 index 0000000..d8f2f82 --- /dev/null +++ b/integration-tests/azure/README.adoc @@ -0,0 +1,16 @@ +== Camel Quarkus Azure (deprecated client v8) integration tests + +By default the integration tests run against a local https://github.com/Azure/Azurite[Azurite] container. + +To run the tests against the real remote Azure API, you need the following: + +* A https://docs.microsoft.com/en-us/azure/storage/common/storage-account-create?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&tabs=azure-portal[general-purpose v2 Azure storage account] +* View the https://docs.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?tabs=azure-portal#view-account-access-keys[account keys] and set the following environment variables: ++ +[source,shell] +---- +export AZURE_STORAGE_ACCOUNT_NAME=my-account-name +export AZURE_STORAGE_ACCOUNT_KEY=my-account-key +---- + +You may want to `export CAMEL_QUARKUS_START_MOCK_BACKEND=false` to avoid starting he the local Azurite container and make sure that you test against the real remote Azure API. diff --git a/integration-tests/azure/pom.xml b/integration-tests/azure/pom.xml index d7e2a7e..fd53846 100644 --- a/integration-tests/azure/pom.xml +++ b/integration-tests/azure/pom.xml @@ -55,6 +55,11 @@ <artifactId>camel-quarkus-integration-testcontainers-support</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-test-support-mock-backend</artifactId> + <scope>test</scope> + </dependency> <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> <dependency> diff --git a/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureBlobResource.java b/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureBlobResource.java index 9ca15a0..825c544 100644 --- a/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureBlobResource.java +++ b/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureBlobResource.java @@ -20,7 +20,6 @@ import java.io.ByteArrayInputStream; import java.net.URI; import java.nio.charset.StandardCharsets; -import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.inject.Named; @@ -35,33 +34,39 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.microsoft.azure.storage.StorageCredentials; +import com.microsoft.azure.storage.StorageCredentialsAccountAndKey; import com.microsoft.azure.storage.blob.CloudBlob; -import com.microsoft.azure.storage.blob.CloudBlobContainer; import com.microsoft.azure.storage.blob.CloudBlockBlob; import org.apache.camel.Exchange; import org.apache.camel.ProducerTemplate; import org.apache.camel.component.azure.blob.BlobBlock; +import org.eclipse.microprofile.config.inject.ConfigProperty; @Path("/azure") @ApplicationScoped public class AzureBlobResource { + private static final String BLOB_NAME = "test"; @Inject ProducerTemplate producerTemplate; - @PostConstruct - public void init() throws Exception { - StorageCredentials credentials = StorageCredentials.tryParseCredentials(System.getProperty("azurite.credentials")); - URI uri = new URI(System.getProperty("azurite.blob.service.url") + "camel-test"); - CloudBlobContainer container = new CloudBlobContainer(uri, credentials); - container.create(); - } + @ConfigProperty(name = "camel.component.azure-blob.credentials-account-name") + String azureStorageAccountName; + + @ConfigProperty(name = "camel.component.azure-blob.credentials-account-key") + String azureStorageAccountKey; + + @ConfigProperty(name = "azure.blob.service.url") + String azureBlobServiceUrl; + + @ConfigProperty(name = "azure.blob.container.name") + String azureBlobContainerName; @javax.enterprise.inject.Produces @Named("azureBlobClient") public CloudBlob createBlobClient() throws Exception { - StorageCredentials credentials = StorageCredentials.tryParseCredentials(System.getProperty("azurite.credentials")); - URI uri = new URI(System.getProperty("azurite.blob.service.url") + "camel-test/test"); + URI uri = new URI(azureBlobServiceUrl + "/" + BLOB_NAME); + StorageCredentials credentials = new StorageCredentialsAccountAndKey(azureStorageAccountName, azureStorageAccountKey); CloudBlockBlob cloudBlockBlob = new CloudBlockBlob(uri, credentials); return cloudBlockBlob; } @@ -72,7 +77,8 @@ public class AzureBlobResource { public Response createBlob(String message) throws Exception { BlobBlock blob = new BlobBlock(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8))); producerTemplate.sendBody( - "azure-blob://devstoreaccount1/camel-test/test?operation=uploadBlobBlocks&azureBlobClient=#azureBlobClient&validateClientURI=false", + "azure-blob://" + azureStorageAccountName + "/" + azureBlobContainerName + "/" + BLOB_NAME + + "?operation=uploadBlobBlocks&azureBlobClient=#azureBlobClient&validateClientURI=false", blob); return Response.created(new URI("https://camel.apache.org/")).build(); } @@ -82,7 +88,8 @@ public class AzureBlobResource { @Produces(MediaType.TEXT_PLAIN) public String readBlob() throws Exception { return producerTemplate.requestBodyAndHeader( - "azure-blob://devstoreaccount1/camel-test/test?operation=getBlob&azureBlobClient=#azureBlobClient&validateClientURI=false", + "azure-blob://" + azureStorageAccountName + "/" + azureBlobContainerName + "/" + BLOB_NAME + + "?operation=getBlob&azureBlobClient=#azureBlobClient&validateClientURI=false", null, Exchange.CHARSET_NAME, StandardCharsets.UTF_8.name(), String.class); } @@ -91,7 +98,8 @@ public class AzureBlobResource { @Consumes(MediaType.TEXT_PLAIN) public Response updateBlob(String message) throws Exception { producerTemplate.sendBody( - "azure-blob://devstoreaccount1/camel-test/test?operation=updateBlockBlob&azureBlobClient=#azureBlobClient&validateClientURI=false", + "azure-blob://" + azureStorageAccountName + "/" + azureBlobContainerName + "/" + BLOB_NAME + + "?operation=updateBlockBlob&azureBlobClient=#azureBlobClient&validateClientURI=false", message); return Response.ok().build(); } @@ -100,7 +108,8 @@ public class AzureBlobResource { @DELETE public Response deleteBlob() throws Exception { producerTemplate.sendBody( - "azure-blob://devstoreaccount1/camel-test/test?operation=deleteBlob&azureBlobClient=#azureBlobClient&validateClientURI=false", + "azure-blob://" + azureStorageAccountName + "/" + azureBlobContainerName + "/" + BLOB_NAME + + "?operation=deleteBlob&azureBlobClient=#azureBlobClient&validateClientURI=false", null); return Response.noContent().build(); } diff --git a/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureQueueResource.java b/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureQueueResource.java index 70e5379..0407aa8 100644 --- a/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureQueueResource.java +++ b/integration-tests/azure/src/main/java/org/apache/camel/quarkus/component/azure/it/AzureQueueResource.java @@ -32,24 +32,37 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import com.microsoft.azure.storage.StorageCredentials; +import com.microsoft.azure.storage.StorageCredentialsAccountAndKey; import com.microsoft.azure.storage.queue.CloudQueue; import com.microsoft.azure.storage.queue.CloudQueueMessage; +import io.quarkus.arc.Unremovable; import org.apache.camel.ProducerTemplate; +import org.eclipse.microprofile.config.inject.ConfigProperty; @Path("/azure") @ApplicationScoped public class AzureQueueResource { - private static final String QUEUE_NAME = UUID.randomUUID().toString(); + private static final String QUEUE_NAME = "camel-quarkus-" + UUID.randomUUID().toString(); @Inject ProducerTemplate producerTemplate; + @ConfigProperty(name = "camel.component.azure-blob.credentials-account-name") + String azureStorageAccountName; + + @ConfigProperty(name = "camel.component.azure-blob.credentials-account-key") + String azureStorageAccountKey; + + @ConfigProperty(name = "azure.queue.service.url") + String azureQueueServiceUrl; + @javax.enterprise.inject.Produces @Named("azureQueueClient") + @Unremovable public CloudQueue createQueueClient() throws Exception { - StorageCredentials credentials = StorageCredentials.tryParseCredentials(System.getProperty("azurite.credentials")); - URI uri = new URI(System.getProperty("azurite.queue.service.url") + QUEUE_NAME); + URI uri = new URI(azureQueueServiceUrl + "/" + QUEUE_NAME); + StorageCredentials credentials = new StorageCredentialsAccountAndKey(azureStorageAccountName, azureStorageAccountKey); return new CloudQueue(uri, credentials); } @@ -57,7 +70,7 @@ public class AzureQueueResource { @POST public Response createQueue() throws Exception { producerTemplate.sendBody( - "azure-queue://devstoreaccount1/" + QUEUE_NAME + "azure-queue://" + azureStorageAccountName + "/" + QUEUE_NAME + "?operation=createQueue&azureQueueClient=#azureQueueClient&validateClientURI=false", null); return Response.created(new URI("https://camel.apache.org/")).build(); @@ -68,7 +81,7 @@ public class AzureQueueResource { @Produces(MediaType.TEXT_PLAIN) public String retrieveMessage() throws Exception { CloudQueueMessage message = producerTemplate.requestBody( - "azure-queue://devstoreaccount1/" + QUEUE_NAME + "azure-queue://" + azureStorageAccountName + "/" + QUEUE_NAME + "?operation=retrieveMessage&azureQueueClient=#azureQueueClient&validateClientURI=false", null, CloudQueueMessage.class); return message.getMessageContentAsString(); @@ -79,7 +92,7 @@ public class AzureQueueResource { @Consumes(MediaType.TEXT_PLAIN) public Response addMessage(String message) throws Exception { producerTemplate.sendBody( - "azure-queue://devstoreaccount1/" + QUEUE_NAME + "azure-queue://" + azureStorageAccountName + "/" + QUEUE_NAME + "?operation=addMessage&azureQueueClient=#azureQueueClient&validateClientURI=false", message); return Response.created(new URI("https://camel.apache.org/")).build(); @@ -89,7 +102,7 @@ public class AzureQueueResource { @DELETE public Response deleteQueue() throws Exception { producerTemplate.sendBody( - "azure-queue://devstoreaccount1/" + QUEUE_NAME + "azure-queue://" + azureStorageAccountName + "/" + QUEUE_NAME + "?operation=deleteQueue&azureQueueClient=#azureQueueClient&validateClientURI=false", null); return Response.noContent().build(); diff --git a/integration-tests/azure/src/main/resources/application.properties b/integration-tests/azure/src/main/resources/application.properties new file mode 100644 index 0000000..8624940 --- /dev/null +++ b/integration-tests/azure/src/main/resources/application.properties @@ -0,0 +1,25 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- +# + + +# Azurite test account credentials +azurite.storage.account.name = devstoreaccount1 +azurite.storage.account.key = Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== + +camel.component.azure-blob.credentials-account-name = ${AZURE_STORAGE_ACCOUNT_NAME:${azurite.storage.account.name}} +camel.component.azure-blob.credentials-account-key = ${AZURE_STORAGE_ACCOUNT_KEY:${azurite.storage.account.key}} diff --git a/integration-tests/azure/src/test/java/org/apache/camel/quarkus/component/azure/it/AzureTestResource.java b/integration-tests/azure/src/test/java/org/apache/camel/quarkus/component/azure/it/AzureTestResource.java index 7bd102c..0f6696d 100644 --- a/integration-tests/azure/src/test/java/org/apache/camel/quarkus/component/azure/it/AzureTestResource.java +++ b/integration-tests/azure/src/test/java/org/apache/camel/quarkus/component/azure/it/AzureTestResource.java @@ -17,10 +17,20 @@ package org.apache.camel.quarkus.component.azure.it; -import java.util.HashMap; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Map; +import java.util.UUID; +import com.microsoft.azure.storage.StorageCredentials; +import com.microsoft.azure.storage.StorageCredentialsAccountAndKey; +import com.microsoft.azure.storage.StorageException; +import com.microsoft.azure.storage.blob.CloudBlobContainer; +import io.quarkus.runtime.configuration.ConfigUtils; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import io.smallrye.config.SmallRyeConfig; +import org.apache.camel.quarkus.test.mock.backend.MockBackendUtils; +import org.apache.camel.util.CollectionHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testcontainers.containers.GenericContainer; @@ -29,42 +39,85 @@ import org.testcontainers.containers.wait.strategy.Wait; public class AzureTestResource implements QuarkusTestResourceLifecycleManager { private static final Logger LOGGER = LoggerFactory.getLogger(AzureTestResource.class); - private static final String AZURITE_IMAGE = "mcr.microsoft.com/azure-storage/azurite:3.6.0"; - private static final String AZURITE_CREDENTIALS = "DefaultEndpointsProtocol=http;AccountName=" - + "devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" - + "BlobEndpoint=%s;QueueEndpoint=%s;"; + private static final String AZURITE_IMAGE = "mcr.microsoft.com/azure-storage/azurite:3.9.0"; private static final int BLOB_SERVICE_PORT = 10000; private static final int QUEUE_SERVICE_PORT = 10001; private GenericContainer<?> container; + private CloudBlobContainer blobContainer; @Override public Map<String, String> start() { - try { - container = new GenericContainer<>(AZURITE_IMAGE) - .withExposedPorts(BLOB_SERVICE_PORT, QUEUE_SERVICE_PORT) - .withLogConsumer(new Slf4jLogConsumer(LOGGER)) - .waitingFor(Wait.forListeningPort()); - container.start(); - String baseServiceUrl = "http://%s:%d/devstoreaccount1/"; - String blobServiceUrl = String.format(baseServiceUrl, container.getContainerIpAddress(), - container.getMappedPort(BLOB_SERVICE_PORT)); - String queueServiceUrl = String.format(baseServiceUrl, container.getContainerIpAddress(), - container.getMappedPort(QUEUE_SERVICE_PORT)); + final SmallRyeConfig config = ConfigUtils.configBuilder(true).build(); - Map<String, String> configuration = new HashMap<>(); - configuration.put("azurite.blob.service.url", blobServiceUrl); - configuration.put("azurite.queue.service.url", queueServiceUrl); - configuration.put("azurite.credentials", String.format(AZURITE_CREDENTIALS, blobServiceUrl, queueServiceUrl)); - return configuration; - } catch (Exception e) { + final String realAzureStorageAccountName = System.getenv("AZURE_STORAGE_ACCOUNT_NAME"); + final boolean realCredentialsProvided = realAzureStorageAccountName != null + && System.getenv("AZURE_STORAGE_ACCOUNT_KEY") != null; + + final String azureBlobContainername = "camel-quarkus-" + UUID.randomUUID().toString(); + + final String azureStorageAccountName = config + .getValue("camel.component.azure-blob.credentials-account-name", String.class); + final String azureStorageAccountKey = config + .getValue("camel.component.azure-blob.credentials-account-key", String.class); + final Map<String, String> result; + final boolean startMockBackend = MockBackendUtils.startMockBackend(false); + if (startMockBackend && !realCredentialsProvided) { + MockBackendUtils.logMockBackendUsed(); + try { + container = new GenericContainer<>(AZURITE_IMAGE) + .withExposedPorts(BLOB_SERVICE_PORT, QUEUE_SERVICE_PORT) + .withLogConsumer(new Slf4jLogConsumer(LOGGER)) + .waitingFor(Wait.forListeningPort()); + container.start(); + + final String blobServiceUrl = "http://" + container.getContainerIpAddress() + ":" + + container.getMappedPort(BLOB_SERVICE_PORT) + "/" + azureStorageAccountName + "/" + + azureBlobContainername; + final String queueServiceUrl = "http://" + container.getContainerIpAddress() + ":" + + container.getMappedPort(QUEUE_SERVICE_PORT) + "/" + azureStorageAccountName; + + result = CollectionHelper.mapOf( + "azure.blob.container.name", azureBlobContainername, + "azure.blob.service.url", blobServiceUrl, + "azure.queue.service.url", queueServiceUrl); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + if (!startMockBackend && !realCredentialsProvided) { + throw new IllegalStateException( + "Set AZURE_STORAGE_ACCOUNT_NAME and AZURE_STORAGE_ACCOUNT_KEY env vars if you set CAMEL_QUARKUS_START_MOCK_BACKEND=false"); + } + MockBackendUtils.logRealBackendUsed(); + result = CollectionHelper.mapOf( + "azure.blob.container.name", azureBlobContainername, + "azure.blob.service.url", + "https://" + realAzureStorageAccountName + ".blob.core.windows.net/" + azureBlobContainername, + "azure.queue.service.url", "https://" + realAzureStorageAccountName + ".queue.core.windows.net"); + } + + final StorageCredentials credentials = new StorageCredentialsAccountAndKey(azureStorageAccountName, + azureStorageAccountKey); + try { + blobContainer = new CloudBlobContainer(new URI(result.get("azure.blob.service.url")), credentials); + blobContainer.create(); + } catch (StorageException | URISyntaxException e) { throw new RuntimeException(e); } + return result; } @Override public void stop() { + if (blobContainer != null) { + try { + blobContainer.delete(); + } catch (StorageException e) { + throw new RuntimeException(e); + } + } try { if (container != null) { container.stop();