This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 0eebd4977602 CAMEL-26616: camel-azure-cosmosdb - run the integration 
tests on Floci AZ (#29249)
0eebd4977602 is described below

commit 0eebd4977602cc98d27b100bec64d0d793ebe1f9
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Nov 9 13:41:40 2026 +0100

    CAMEL-26616: camel-azure-cosmosdb - run the integration tests on Floci AZ 
(#29249)
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../catalog/docs/azure-cosmosdb-component.adoc     | 19 ++++-
 .../apache/camel/catalog/test-infra/metadata.json  | 11 +++
 .../camel-azure/camel-azure-cosmosdb/pom.xml       |  9 +++
 .../src/main/docs/azure-cosmosdb-component.adoc    | 19 ++++-
 .../azure/cosmosdb/CosmosDbTestUtils.java          | 41 ++++++----
 .../integration/BaseCamelCosmosDbTestSupport.java  |  5 ++
 .../cosmosdb/integration/CosmosDbConsumerIT.java   |  9 +--
 .../cosmosdb/integration/CosmosDbProducerIT.java   | 11 +--
 .../operations/CosmosDbClientOperationsIT.java     | 29 +++----
 .../operations/CosmosDbContainerOperationsIT.java  | 54 ++++++++-----
 .../operations/CosmosDbDatabaseOperationsIT.java   | 29 +++----
 test-infra/camel-test-infra-all/pom.xml            | 11 +++
 .../src/generated/resources/META-INF/metadata.json | 11 +++
 test-infra/camel-test-infra-azure-cosmosdb/pom.xml | 58 ++++++++++++++
 .../cosmosdb/clients/AzureCosmosDbClientUtils.java | 87 ++++++++++++++++++++
 .../cosmosdb/common/AzureCosmosDbProperties.java   | 38 +++++++++
 .../services/AzureCosmosDbInfraService.java        | 37 +++++++++
 .../AzureCosmosDbLocalContainerInfraService.java   | 93 ++++++++++++++++++++++
 .../services/AzureCosmosDbRemoteInfraService.java  | 52 ++++++++++++
 .../cosmosdb/services/AzureCosmosDbService.java    | 24 ++++++
 .../services/AzureCosmosDbServiceFactory.java      | 78 ++++++++++++++++++
 .../src/main/resources/META-INF/MANIFEST.MF        |  0
 test-infra/pom.xml                                 |  1 +
 23 files changed, 627 insertions(+), 99 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/azure-cosmosdb-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/azure-cosmosdb-component.adoc
index 9234de22d05e..0235305ad4ec 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/azure-cosmosdb-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/azure-cosmosdb-component.adoc
@@ -907,14 +907,27 @@ YAML::
 
 == Important Development Notes
 
-When developing on this component, you will need to obtain your Azure 
accessKey in order to run the integration tests. In addition to the mocked unit 
tests,
+When developing on this component, in addition to the mocked unit tests,
 you *will need to run the integration tests with every change you make or even 
client upgrade as the Azure client can break things even on minor versions 
upgrade.*
-To run the integration tests, on this component directory, run the following 
maven command:
+The integration tests run against a local 
https://github.com/floci-io/floci-az[Floci AZ] container, which needs Docker.
+To run them, on this component directory, run the following maven command:
 
 [source,bash]
 ----
-mvn clean install -Dendpoint={{dbaddress}} -DaccessKey={{accessKey}}
+mvn verify
 ----
+
+Floci AZ does not emulate the change feed, the throughput of the databases, 
and the queries of the databases and containers,
+so six tests run against an Azure Cosmos DB account only: 
`CosmosDbConsumerIT`, `CosmosDbContainerOperationsIT.testCaptureChangeFeed`,
+`CosmosDbProducerIT.testReplaceDatabaseThroughput`, 
`CosmosDbProducerIT.testQueryContainers`,
+`CosmosDbClientOperationsIT.testQueryAndReadAllDatabases` and 
`CosmosDbDatabaseOperationsIT.testQueryAndReadAllContainers`.
+To run all the integration tests against an account in Azure, run the 
following maven command instead:
+
+[source,bash]
+----
+mvn verify -Dendpoint={{dbaddress}} -DaccessKey={{accessKey}}
+----
+
 Whereby `endpoint` is your Azure CosmosDB endpoint name and `accessKey` is the 
access key being generated from Azure CosmosDB portal.
 
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
index cc8303394261..4e20c62fb386 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
@@ -900,6 +900,17 @@
   "version" : "4.24.0-SNAPSHOT",
   "serviceVersion" : "v1.0.0.rc0",
   "uiSupported" : false
+}, {
+  "service" : 
"org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbInfraService",
+  "description" : "Local Azure Cosmos DB service with Floci AZ",
+  "implementation" : 
"org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbLocalContainerInfraService",
+  "alias" : [ "azure" ],
+  "aliasImplementation" : [ "cosmos-db" ],
+  "groupId" : "org.apache.camel",
+  "artifactId" : "camel-test-infra-azure-cosmosdb",
+  "version" : "4.24.0-SNAPSHOT",
+  "serviceVersion" : "0.16.0",
+  "uiSupported" : false
 }, {
   "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService",
   "description" : "Embedded FTP Server",
diff --git a/components/camel-azure/camel-azure-cosmosdb/pom.xml 
b/components/camel-azure/camel-azure-cosmosdb/pom.xml
index d733962c4ba9..a055ba8e4785 100644
--- a/components/camel-azure/camel-azure-cosmosdb/pom.xml
+++ b/components/camel-azure/camel-azure-cosmosdb/pom.xml
@@ -33,6 +33,9 @@
     <description>Camel Azure CosmosDB Component</description>
 
     <properties>
+        <!-- Floci AZ is not available on these platforms -->
+        <skipITs.ppc64le>true</skipITs.ppc64le>
+        <skipITs.s390x>true</skipITs.s390x>
     </properties>
 
     <dependencies>
@@ -84,5 +87,11 @@
             <artifactId>commons-lang3</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-azure-cosmosdb</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc
 
b/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc
index 9234de22d05e..0235305ad4ec 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc
@@ -907,14 +907,27 @@ YAML::
 
 == Important Development Notes
 
-When developing on this component, you will need to obtain your Azure 
accessKey in order to run the integration tests. In addition to the mocked unit 
tests,
+When developing on this component, in addition to the mocked unit tests,
 you *will need to run the integration tests with every change you make or even 
client upgrade as the Azure client can break things even on minor versions 
upgrade.*
-To run the integration tests, on this component directory, run the following 
maven command:
+The integration tests run against a local 
https://github.com/floci-io/floci-az[Floci AZ] container, which needs Docker.
+To run them, on this component directory, run the following maven command:
 
 [source,bash]
 ----
-mvn clean install -Dendpoint={{dbaddress}} -DaccessKey={{accessKey}}
+mvn verify
 ----
+
+Floci AZ does not emulate the change feed, the throughput of the databases, 
and the queries of the databases and containers,
+so six tests run against an Azure Cosmos DB account only: 
`CosmosDbConsumerIT`, `CosmosDbContainerOperationsIT.testCaptureChangeFeed`,
+`CosmosDbProducerIT.testReplaceDatabaseThroughput`, 
`CosmosDbProducerIT.testQueryContainers`,
+`CosmosDbClientOperationsIT.testQueryAndReadAllDatabases` and 
`CosmosDbDatabaseOperationsIT.testQueryAndReadAllContainers`.
+To run all the integration tests against an account in Azure, run the 
following maven command instead:
+
+[source,bash]
+----
+mvn verify -Dendpoint={{dbaddress}} -DaccessKey={{accessKey}}
+----
+
 Whereby `endpoint` is your Azure CosmosDB endpoint name and `accessKey` is the 
access key being generated from Azure CosmosDB portal.
 
 
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/CosmosDbTestUtils.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/CosmosDbTestUtils.java
index 87c31165df27..2ae9c114914f 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/CosmosDbTestUtils.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/CosmosDbTestUtils.java
@@ -22,8 +22,12 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import com.azure.cosmos.CosmosAsyncClient;
-import com.azure.cosmos.CosmosClientBuilder;
+import 
org.apache.camel.test.infra.azure.cosmosdb.clients.AzureCosmosDbClientUtils;
+import 
org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties;
+import 
org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbService;
+import 
org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbServiceFactory;
 import org.apache.camel.test.junit6.TestSupport;
+import org.apache.camel.util.ObjectHelper;
 import org.awaitility.Awaitility;
 import org.junit.jupiter.api.function.Executable;
 
@@ -38,26 +42,29 @@ public final class CosmosDbTestUtils {
         return TestSupport.loadExternalProperties(CosmosDbTestUtils.class, 
"azure_key.properties");
     }
 
-    public static Properties loadAzureAccessFromJvmEnv() throws Exception {
-        final Properties properties = new Properties();
-        if (System.getProperty("endpoint") == null || 
System.getProperty("accessKey") == null) {
-            throw new Exception(
-                    "Make sure to supply azure CosmosDB endpoint and 
accessKey, e.g:  mvn verify -Dendpoint=myacc-azure.com -DaccessKey=mykey");
+    /**
+     * The Cosmos DB account the integration tests run against: a local Floci 
AZ container, unless the endpoint and
+     * accessKey system properties give an account on Azure, for example
+     * {@code mvn verify -Dendpoint=https://myaccount.documents.azure.com:443/ 
-DaccessKey=mykey}
+     */
+    public static AzureCosmosDbService createService() {
+        final String endpoint = System.getProperty("endpoint");
+        final String accessKey = System.getProperty("accessKey");
+
+        if (ObjectHelper.isNotEmpty(endpoint) && 
ObjectHelper.isNotEmpty(accessKey)) {
+            System.setProperty(AzureCosmosDbProperties.ENDPOINT, endpoint);
+            System.setProperty(AzureCosmosDbProperties.ACCESS_KEY, accessKey);
+            System.setProperty(AzureCosmosDbProperties.INSTANCE_TYPE, 
"remote");
         }
-        properties.setProperty("endpoint", System.getProperty("endpoint"));
-        properties.setProperty("access_key", System.getProperty("accessKey"));
 
-        return properties;
+        return AzureCosmosDbServiceFactory.createSingletonService();
     }
 
-    public static CosmosAsyncClient createAsyncClient() throws Exception {
-        final Properties properties = loadAzureAccessFromJvmEnv();
-
-        return new CosmosClientBuilder()
-                .key(properties.getProperty("access_key"))
-                .endpoint(properties.getProperty("endpoint"))
-                .contentResponseOnWriteEnabled(true)
-                .buildAsyncClient();
+    /**
+     * A client of the account of {@link #createService()}
+     */
+    public static CosmosAsyncClient createAsyncClient() {
+        return AzureCosmosDbClientUtils.createAsyncClient();
     }
 
     public static void assertIllegalArgumentException(final Executable 
executable) {
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/BaseCamelCosmosDbTestSupport.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/BaseCamelCosmosDbTestSupport.java
index 01833bff3486..3de616aec07d 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/BaseCamelCosmosDbTestSupport.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/BaseCamelCosmosDbTestSupport.java
@@ -20,10 +20,15 @@ import com.azure.cosmos.CosmosAsyncClient;
 import org.apache.camel.CamelContext;
 import org.apache.camel.component.azure.cosmosdb.CosmosDbComponent;
 import org.apache.camel.component.azure.cosmosdb.CosmosDbTestUtils;
+import 
org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbService;
 import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 public abstract class BaseCamelCosmosDbTestSupport extends CamelTestSupport {
 
+    @RegisterExtension
+    static AzureCosmosDbService service = CosmosDbTestUtils.createService();
+
     protected CosmosAsyncClient client;
 
     @Override
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbConsumerIT.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbConsumerIT.java
index 9078aa4b9cdd..16c99e026f6c 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbConsumerIT.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbConsumerIT.java
@@ -27,17 +27,12 @@ import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-@EnabledIfSystemProperties({
-        @EnabledIfSystemProperty(named = "endpoint", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB endpoint, e.g: mvn clean install -Dendpoint="),
-        @EnabledIfSystemProperty(named = "accessKey", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB accessKey, e.g: mvn clean install -DaccessKey=")
-})
+@EnabledIfSystemProperty(named = "azure.instance.type", matches = "remote",
+                         disabledReason = "Floci AZ does not emulate the 
change feed: supply a Cosmos DB account, e.g: mvn verify -Dendpoint=... 
-DaccessKey=...")
 class CosmosDbConsumerIT extends BaseCamelCosmosDbTestSupport {
 
     private static final String DATABASE_NAME = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbProducerIT.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbProducerIT.java
index c028a12dc4a6..b7d46b599d35 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbProducerIT.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbProducerIT.java
@@ -33,19 +33,12 @@ import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@EnabledIfSystemProperties({
-        @EnabledIfSystemProperty(named = "endpoint", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB endpoint, e.g: mvn clean install -Dendpoint="),
-        @EnabledIfSystemProperty(named = "accessKey", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB accessKey, e.g: mvn clean install -DaccessKey=")
-})
 public class CosmosDbProducerIT extends BaseCamelCosmosDbTestSupport {
     @EndpointInject
     private ProducerTemplate template;
@@ -191,6 +184,8 @@ public class CosmosDbProducerIT extends 
BaseCamelCosmosDbTestSupport {
     }
 
     @Test
+    @EnabledIfSystemProperty(named = "azure.instance.type", matches = "remote",
+                             disabledReason = "Floci AZ does not emulate the 
throughput (offers) of the databases: supply a Cosmos DB account, e.g: mvn 
verify -Dendpoint=... -DaccessKey=...")
     void testReplaceDatabaseThroughput() throws InterruptedException {
         final String databaseName = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
 
@@ -214,6 +209,8 @@ public class CosmosDbProducerIT extends 
BaseCamelCosmosDbTestSupport {
     }
 
     @Test
+    @EnabledIfSystemProperty(named = "azure.instance.type", matches = "remote",
+                             disabledReason = "Floci AZ does not emulate the 
queries of the containers: supply a Cosmos DB account, e.g: mvn verify 
-Dendpoint=... -DaccessKey=...")
     void testQueryContainers() throws InterruptedException {
         // create bunch of containers to test
         final String prefixContainerNames = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbClientOperationsIT.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbClientOperationsIT.java
index e0a5c125fb26..926218a786c6 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbClientOperationsIT.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbClientOperationsIT.java
@@ -16,49 +16,36 @@
  */
 package org.apache.camel.component.azure.cosmosdb.integration.operations;
 
-import java.util.Properties;
-
-import com.azure.cosmos.CosmosAsyncClient;
-import com.azure.cosmos.CosmosClientBuilder;
 import com.azure.cosmos.models.CosmosDatabaseProperties;
 import com.azure.cosmos.models.CosmosDatabaseResponse;
 import org.apache.camel.component.azure.cosmosdb.CosmosDbTestUtils;
 import 
org.apache.camel.component.azure.cosmosdb.client.CosmosAsyncClientWrapper;
 import 
org.apache.camel.component.azure.cosmosdb.operations.CosmosDbClientOperations;
+import 
org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbService;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@EnabledIfSystemProperties({
-        @EnabledIfSystemProperty(named = "endpoint", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB endpoint, e.g: mvn clean install -Dendpoint="),
-        @EnabledIfSystemProperty(named = "accessKey", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB accessKey, e.g: mvn clean install -DaccessKey=")
-})
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 class CosmosDbClientOperationsIT {
 
+    @RegisterExtension
+    static AzureCosmosDbService service = CosmosDbTestUtils.createService();
+
     private CosmosAsyncClientWrapper clientWrapper;
 
     @BeforeAll
-    void prepare() throws Exception {
-        final Properties properties = 
CosmosDbTestUtils.loadAzureAccessFromJvmEnv();
-
-        final CosmosAsyncClient client = new CosmosClientBuilder()
-                .key(properties.getProperty("access_key"))
-                .endpoint(properties.getProperty("endpoint"))
-                .buildAsyncClient();
-
-        clientWrapper = new CosmosAsyncClientWrapper(client);
+    void prepare() {
+        clientWrapper = new 
CosmosAsyncClientWrapper(CosmosDbTestUtils.createAsyncClient());
     }
 
     @AfterEach
@@ -121,6 +108,8 @@ class CosmosDbClientOperationsIT {
     }
 
     @Test
+    @EnabledIfSystemProperty(named = "azure.instance.type", matches = "remote",
+                             disabledReason = "Floci AZ does not emulate the 
queries of the databases: supply a Cosmos DB account, e.g: mvn verify 
-Dendpoint=... -DaccessKey=...")
     void testQueryAndReadAllDatabases() {
         // create bunch of databases
         final String prefixDatabaseNames = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbContainerOperationsIT.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbContainerOperationsIT.java
index 3fc43442d95d..075a4cd62b52 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbContainerOperationsIT.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbContainerOperationsIT.java
@@ -20,13 +20,11 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 import java.util.function.Consumer;
 
 import com.azure.cosmos.ChangeFeedProcessor;
-import com.azure.cosmos.CosmosAsyncClient;
 import com.azure.cosmos.CosmosAsyncContainer;
-import com.azure.cosmos.CosmosClientBuilder;
+import com.azure.cosmos.CosmosException;
 import com.azure.cosmos.models.CosmosItemResponse;
 import com.azure.cosmos.models.PartitionKey;
 import org.apache.camel.component.azure.cosmosdb.CosmosDbTestUtils;
@@ -34,14 +32,17 @@ import 
org.apache.camel.component.azure.cosmosdb.client.CosmosAsyncClientWrapper
 import 
org.apache.camel.component.azure.cosmosdb.operations.CosmosDbClientOperations;
 import 
org.apache.camel.component.azure.cosmosdb.operations.CosmosDbContainerOperations;
 import 
org.apache.camel.component.azure.cosmosdb.operations.CosmosDbOperationsBuilder;
+import 
org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbService;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
@@ -50,38 +51,45 @@ import static 
org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@EnabledIfSystemProperties({
-        @EnabledIfSystemProperty(named = "endpoint", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB endpoint, e.g: mvn clean install -Dendpoint="),
-        @EnabledIfSystemProperty(named = "accessKey", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB accessKey, e.g: mvn clean install -DaccessKey=")
-})
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 class CosmosDbContainerOperationsIT {
     private static final String DATABASE_NAME = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
     private static final String LEASE_DATABASE_NAME = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
+    private static final Logger LOG = 
LoggerFactory.getLogger(CosmosDbContainerOperationsIT.class);
+
+    @RegisterExtension
+    static AzureCosmosDbService service = CosmosDbTestUtils.createService();
 
     private CosmosAsyncClientWrapper clientWrapper;
     private CosmosDbContainerOperations containerOperations;
     private String containerId;
 
     @BeforeAll
-    void prepare() throws Exception {
-        final Properties properties = 
CosmosDbTestUtils.loadAzureAccessFromJvmEnv();
-
-        final CosmosAsyncClient client = new CosmosClientBuilder()
-                .contentResponseOnWriteEnabled(true)
-                .key(properties.getProperty("access_key"))
-                .endpoint(properties.getProperty("endpoint"))
-                .buildAsyncClient();
-
-        clientWrapper = new CosmosAsyncClientWrapper(client);
+    void prepare() {
+        clientWrapper = new 
CosmosAsyncClientWrapper(CosmosDbTestUtils.createAsyncClient());
     }
 
     @AfterAll
     void cleanup() {
-        clientWrapper.getDatabase(DATABASE_NAME).delete().block();
-        clientWrapper.getDatabase(LEASE_DATABASE_NAME).delete().block();
+        if (clientWrapper == null) {
+            return;
+        }
+        deleteDatabase(DATABASE_NAME);
+        // only testCaptureChangeFeed creates the lease database, and it does 
not always run
+        deleteDatabase(LEASE_DATABASE_NAME);
+    }
+
+    // best effort, so that a failed cleanup does not hide the failure of a 
test
+    private void deleteDatabase(String name) {
+        try {
+            clientWrapper.getDatabase(name).delete().block();
+        } catch (CosmosException e) {
+            if (e.getStatusCode() != 404) {
+                LOG.warn("Cannot delete the database {}: {}", name, 
e.getMessage());
+            }
+        } catch (RuntimeException e) {
+            LOG.warn("Cannot delete the database {}: {}", name, 
e.getMessage());
+        }
     }
 
     @BeforeEach
@@ -295,6 +303,8 @@ class CosmosDbContainerOperationsIT {
     }
 
     @Test
+    @EnabledIfSystemProperty(named = "azure.instance.type", matches = "remote",
+                             disabledReason = "Floci AZ does not emulate the 
change feed: supply a Cosmos DB account, e.g: mvn verify -Dendpoint=... 
-DaccessKey=...")
     void testCaptureChangeFeed() {
         // we create our lease container first with our lease database
         final Mono<CosmosAsyncContainer> leaseContainer = 
CosmosDbOperationsBuilder.withClient(clientWrapper)
diff --git 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbDatabaseOperationsIT.java
 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbDatabaseOperationsIT.java
index 8ec287aab0a4..5e9e4976e450 100644
--- 
a/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbDatabaseOperationsIT.java
+++ 
b/components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbDatabaseOperationsIT.java
@@ -16,10 +16,6 @@
  */
 package org.apache.camel.component.azure.cosmosdb.integration.operations;
 
-import java.util.Properties;
-
-import com.azure.cosmos.CosmosAsyncClient;
-import com.azure.cosmos.CosmosClientBuilder;
 import com.azure.cosmos.models.CosmosContainerProperties;
 import com.azure.cosmos.models.CosmosContainerResponse;
 import com.azure.cosmos.models.IndexingMode;
@@ -28,42 +24,33 @@ import 
org.apache.camel.component.azure.cosmosdb.CosmosDbTestUtils;
 import 
org.apache.camel.component.azure.cosmosdb.client.CosmosAsyncClientWrapper;
 import 
org.apache.camel.component.azure.cosmosdb.operations.CosmosDbClientOperations;
 import 
org.apache.camel.component.azure.cosmosdb.operations.CosmosDbDatabaseOperations;
+import 
org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbService;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.condition.EnabledIfSystemProperties;
 import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@EnabledIfSystemProperties({
-        @EnabledIfSystemProperty(named = "endpoint", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB endpoint, e.g: mvn clean install -Dendpoint="),
-        @EnabledIfSystemProperty(named = "accessKey", matches = ".*",
-                                 disabledReason = "Make sure you supply 
CosmosDB accessKey, e.g: mvn clean install -DaccessKey=")
-})
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 class CosmosDbDatabaseOperationsIT {
     private static final String DATABASE_NAME = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
 
+    @RegisterExtension
+    static AzureCosmosDbService service = CosmosDbTestUtils.createService();
+
     private CosmosAsyncClientWrapper clientWrapper;
     private CosmosDbDatabaseOperations operations;
 
     @BeforeAll
-    void prepare() throws Exception {
-        final Properties properties = 
CosmosDbTestUtils.loadAzureAccessFromJvmEnv();
-
-        final CosmosAsyncClient client = new CosmosClientBuilder()
-                .key(properties.getProperty("access_key"))
-                .endpoint(properties.getProperty("endpoint"))
-                .buildAsyncClient();
-
-        clientWrapper = new CosmosAsyncClientWrapper(client);
+    void prepare() {
+        clientWrapper = new 
CosmosAsyncClientWrapper(CosmosDbTestUtils.createAsyncClient());
 
         // create our testing database
         clientWrapper.createDatabase(DATABASE_NAME).block();
@@ -127,6 +114,8 @@ class CosmosDbDatabaseOperationsIT {
     }
 
     @Test
+    @EnabledIfSystemProperty(named = "azure.instance.type", matches = "remote",
+                             disabledReason = "Floci AZ does not emulate the 
queries of the containers: supply a Cosmos DB account, e.g: mvn verify 
-Dendpoint=... -DaccessKey=...")
     void testQueryAndReadAllContainers() {
         // create bunch of containers
         final String prefixContainerNames = 
RandomStringUtils.secure().nextAlphabetic(10).toLowerCase();
diff --git a/test-infra/camel-test-infra-all/pom.xml 
b/test-infra/camel-test-infra-all/pom.xml
index b01eac332f60..bea09ffe17a5 100644
--- a/test-infra/camel-test-infra-all/pom.xml
+++ b/test-infra/camel-test-infra-all/pom.xml
@@ -71,6 +71,11 @@
             <artifactId>camel-test-infra-rabbitmq</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-azure-cosmosdb</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-test-infra-azure-eventgrid</artifactId>
@@ -443,6 +448,12 @@
                                         
<artifactId>camel-test-infra-rabbitmq</artifactId>
                                     </dependency>
                                 </fileSet>
+                                <fileSet>
+                                    <dependency>
+                                        <groupId>org.apache.camel</groupId>
+                                        
<artifactId>camel-test-infra-azure-cosmosdb</artifactId>
+                                    </dependency>
+                                </fileSet>
                                 <fileSet>
                                     <dependency>
                                         <groupId>org.apache.camel</groupId>
diff --git 
a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
 
b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
index cc8303394261..4e20c62fb386 100644
--- 
a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
+++ 
b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
@@ -900,6 +900,17 @@
   "version" : "4.24.0-SNAPSHOT",
   "serviceVersion" : "v1.0.0.rc0",
   "uiSupported" : false
+}, {
+  "service" : 
"org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbInfraService",
+  "description" : "Local Azure Cosmos DB service with Floci AZ",
+  "implementation" : 
"org.apache.camel.test.infra.azure.cosmosdb.services.AzureCosmosDbLocalContainerInfraService",
+  "alias" : [ "azure" ],
+  "aliasImplementation" : [ "cosmos-db" ],
+  "groupId" : "org.apache.camel",
+  "artifactId" : "camel-test-infra-azure-cosmosdb",
+  "version" : "4.24.0-SNAPSHOT",
+  "serviceVersion" : "0.16.0",
+  "uiSupported" : false
 }, {
   "service" : "org.apache.camel.test.infra.ftp.services.FtpInfraService",
   "description" : "Embedded FTP Server",
diff --git a/test-infra/camel-test-infra-azure-cosmosdb/pom.xml 
b/test-infra/camel-test-infra-azure-cosmosdb/pom.xml
new file mode 100644
index 000000000000..df2d6f78cd63
--- /dev/null
+++ b/test-infra/camel-test-infra-azure-cosmosdb/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>camel-test-infra-parent</artifactId>
+        <groupId>org.apache.camel</groupId>
+        <relativePath>../camel-test-infra-parent/pom.xml</relativePath>
+        <version>4.24.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <name>Camel :: Test Infra :: Azure Cosmos DB</name>
+    <artifactId>camel-test-infra-azure-cosmosdb</artifactId>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.azure</groupId>
+                <artifactId>azure-sdk-bom</artifactId>
+                <version>${azure-sdk-bom-version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-infra-azure-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- azure sdk -->
+        <dependency>
+            <groupId>com.azure</groupId>
+            <artifactId>azure-cosmos</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java
new file mode 100644
index 000000000000..c8f515c431c5
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.clients;
+
+import java.net.URI;
+import java.util.Objects;
+import java.util.Set;
+
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import 
org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties;
+
+public final class AzureCosmosDbClientUtils {
+    /**
+     * The switch of the Cosmos DB SDK that skips the validation of the TLS 
certificate of an emulator
+     */
+    public static final String EMULATOR_CERTIFICATE_VALIDATION_DISABLED
+            = "COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED";
+    /**
+     * The host of the emulator, for the SDK, when it is not a local one
+     */
+    public static final String EMULATOR_HOST = "COSMOS.EMULATOR_HOST";
+
+    // the hosts that the SDK takes as an emulator without COSMOS.EMULATOR_HOST
+    private static final Set<String> LOCAL_HOSTS = Set.of("localhost", 
"127.0.0.1", "[::1]");
+
+    private AzureCosmosDbClientUtils() {
+
+    }
+
+    /**
+     * Builds a client of the account the tests run against: the local Floci 
AZ container, unless the
+     * {@link AzureCosmosDbProperties#INSTANCE_TYPE} system property is {@code 
remote}. Like the clients the
+     * azure-cosmosdb component builds by default, it returns the items it 
writes.
+     * <p>
+     * For Floci AZ, the client works in gateway mode, the only one that Floci 
AZ emulates (the component builds a
+     * direct-mode client, so a route uses the service through a client like 
this one, set as its
+     * {@code cosmosAsyncClient}), keeps to the endpoint whatever locations 
the emulator advertises, and does not
+     * validate the certificate that Floci AZ issues itself for its TLS.
+     */
+    public static CosmosAsyncClient createAsyncClient() {
+        String endpoint = 
Objects.requireNonNull(System.getProperty(AzureCosmosDbProperties.ENDPOINT),
+                "The system property " + AzureCosmosDbProperties.ENDPOINT + " 
gives the endpoint of the account");
+
+        CosmosClientBuilder builder = new CosmosClientBuilder()
+                .endpoint(endpoint)
+                .key(System.getProperty(AzureCosmosDbProperties.ACCESS_KEY))
+                .contentResponseOnWriteEnabled(true);
+
+        String instanceType = 
System.getProperty(AzureCosmosDbProperties.INSTANCE_TYPE);
+        if (instanceType == null || 
instanceType.equals("local-azure-container")) {
+            trustEmulator(endpoint);
+            builder.gatewayMode()
+                    .endpointDiscoveryEnabled(false);
+        }
+
+        return builder.buildAsyncClient();
+    }
+
+    /*
+     * The Cosmos DB SDK does not validate the certificate of an emulator, the 
host localhost, 127.0.0.1, [::1] or the
+     * one of COSMOS.EMULATOR_HOST, when 
COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED is true. It reads both
+     * when a client is built, so they apply to the clients built afterwards, 
and to the emulator host only.
+     */
+    private static void trustEmulator(String endpoint) {
+        System.setProperty(EMULATOR_CERTIFICATE_VALIDATION_DISABLED, "true");
+        String host = URI.create(endpoint).getHost();
+        if (!LOCAL_HOSTS.contains(host)) {
+            System.setProperty(EMULATOR_HOST, host);
+        }
+    }
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/common/AzureCosmosDbProperties.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/common/AzureCosmosDbProperties.java
new file mode 100644
index 000000000000..834757c20524
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/common/AzureCosmosDbProperties.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.common;
+
+public final class AzureCosmosDbProperties {
+    /**
+     * The endpoint of the Cosmos DB account: registered by the local service, 
read by the remote one
+     */
+    public static final String ENDPOINT = "azure.cosmosdb.endpoint";
+    /**
+     * The key of the Cosmos DB account: registered by the local service, read 
by the remote one
+     */
+    public static final String ACCESS_KEY = "azure.cosmosdb.access.key";
+    /**
+     * The type of the service the tests run against: the local Floci AZ 
container by default, {@code remote} for the
+     * account given by {@link #ENDPOINT} and {@link #ACCESS_KEY}
+     */
+    public static final String INSTANCE_TYPE = "azure.instance.type";
+
+    private AzureCosmosDbProperties() {
+
+    }
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbInfraService.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbInfraService.java
new file mode 100644
index 000000000000..3abf05b2e02f
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbInfraService.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.services;
+
+import org.apache.camel.test.infra.common.services.InfrastructureService;
+
+/**
+ * A Cosmos DB for NoSQL account. For the local one, of Floci AZ, a client 
needs the gateway mode and the emulator
+ * certificate switch of the Cosmos DB SDK: see {@code 
AzureCosmosDbLocalContainerInfraService}.
+ */
+public interface AzureCosmosDbInfraService extends InfrastructureService {
+
+    /**
+     * The endpoint of the account (the databaseEndpoint option of the 
azure-cosmosdb component)
+     */
+    String endpoint();
+
+    /**
+     * The key of the account (the accountKey option of the azure-cosmosdb 
component)
+     */
+    String accessKey();
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbLocalContainerInfraService.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbLocalContainerInfraService.java
new file mode 100644
index 000000000000..31a3c5fd5fa8
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbLocalContainerInfraService.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.services;
+
+import org.apache.camel.spi.annotations.InfraService;
+import org.apache.camel.test.infra.azure.common.AzureCredentialsHolder;
+import org.apache.camel.test.infra.azure.common.services.FlociAzContainer;
+import org.apache.camel.test.infra.azure.common.services.FlociAzInfraService;
+import 
org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties;
+
+/**
+ * A local Cosmos DB for NoSQL account: Floci AZ emulates the gateway API of 
the account in process (databases,
+ * containers, items and their SQL queries). The Java SDK connects to the 
gateway over TLS only, so the container serves
+ * HTTPS next to HTTP on its port, with a certificate it issues when it starts.
+ * <p>
+ * A client of the service works in gateway mode, and skips the validation of 
the certificate of the emulator with the
+ * {@code COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED} system 
property, or the
+ * {@code COSMOS_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED} environment 
variable, set to {@code true}:
+ * {@code AzureCosmosDbClientUtils} builds such a client. The azure-cosmosdb 
component builds a direct-mode client,
+ * which Floci AZ does not serve, so a route uses the service through a client 
of its own, set as its
+ * {@code cosmosAsyncClient}.
+ * <p>
+ * Floci AZ does not emulate the change feed, the throughput of the databases 
and containers, nor the queries of the
+ * databases and containers.
+ */
+@InfraService(service = AzureCosmosDbInfraService.class,
+              description = "Local Azure Cosmos DB service with Floci AZ",
+              serviceAlias = "azure", serviceImplementationAlias = "cosmos-db")
+public class AzureCosmosDbLocalContainerInfraService extends 
FlociAzInfraService implements AzureCosmosDbInfraService {
+    /**
+     * The well-known key of the Cosmos DB emulator (Floci AZ accepts any key)
+     */
+    public static final String EMULATOR_KEY
+            = 
"C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
+
+    @Override
+    protected FlociAzContainer initContainer(String imageName) {
+        return super.initContainer(imageName)
+                .withEnv("FLOCI_AZ_TLS_ENABLED", "true");
+    }
+
+    @Override
+    public void registerProperties() {
+        super.registerProperties();
+        System.setProperty(AzureCosmosDbProperties.ENDPOINT, endpoint());
+        System.setProperty(AzureCosmosDbProperties.ACCESS_KEY, accessKey());
+    }
+
+    /**
+     * The endpoint of the account, for example {@code 
https://localhost:32768/devstoreaccount1-cosmos}. The Java SDK
+     * sends its requests to the root path of the endpoint, which Floci AZ 
serves for this account too.
+     */
+    @Override
+    public String endpoint() {
+        return String.format("https://%s:%d/%s-cosmos";, host(), port(), 
accountName());
+    }
+
+    @Override
+    public String accessKey() {
+        return EMULATOR_KEY;
+    }
+
+    @Override
+    public AzureCredentialsHolder azureCredentials() {
+        String accountName = accountName();
+        return new AzureCredentialsHolder() {
+            @Override
+            public String accountName() {
+                return accountName;
+            }
+
+            @Override
+            public String accountKey() {
+                return EMULATOR_KEY;
+            }
+        };
+    }
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbRemoteInfraService.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbRemoteInfraService.java
new file mode 100644
index 000000000000..c2ee62c73686
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbRemoteInfraService.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.services;
+
+import 
org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties;
+
+/**
+ * A Cosmos DB account on Azure, given by the {@link 
AzureCosmosDbProperties#ENDPOINT} and
+ * {@link AzureCosmosDbProperties#ACCESS_KEY} system properties
+ */
+public class AzureCosmosDbRemoteInfraService implements 
AzureCosmosDbInfraService {
+
+    @Override
+    public void registerProperties() {
+        // NO-OP
+    }
+
+    @Override
+    public void initialize() {
+        registerProperties();
+    }
+
+    @Override
+    public void shutdown() {
+        // NO-OP
+    }
+
+    @Override
+    public String endpoint() {
+        return System.getProperty(AzureCosmosDbProperties.ENDPOINT);
+    }
+
+    @Override
+    public String accessKey() {
+        return System.getProperty(AzureCosmosDbProperties.ACCESS_KEY);
+    }
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbService.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbService.java
new file mode 100644
index 000000000000..cd77f81de224
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbService.java
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.services;
+
+import org.apache.camel.test.infra.common.services.ContainerTestService;
+import org.apache.camel.test.infra.common.services.TestService;
+
+public interface AzureCosmosDbService extends AzureCosmosDbInfraService, 
TestService, ContainerTestService {
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbServiceFactory.java
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbServiceFactory.java
new file mode 100644
index 000000000000..7055d9412494
--- /dev/null
+++ 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbServiceFactory.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.services;
+
+import org.apache.camel.test.infra.common.services.SimpleTestServiceBuilder;
+import org.apache.camel.test.infra.common.services.SingletonService;
+
+public final class AzureCosmosDbServiceFactory {
+
+    private static class SingletonAzureCosmosDbService extends 
SingletonService<AzureCosmosDbService>
+            implements AzureCosmosDbService {
+        public SingletonAzureCosmosDbService(AzureCosmosDbService service, 
String name) {
+            super(service, name);
+        }
+
+        @Override
+        public String endpoint() {
+            return getService().endpoint();
+        }
+
+        @Override
+        public String accessKey() {
+            return getService().accessKey();
+        }
+    }
+
+    private AzureCosmosDbServiceFactory() {
+
+    }
+
+    public static SimpleTestServiceBuilder<AzureCosmosDbService> builder() {
+        return new SimpleTestServiceBuilder<>("azure");
+    }
+
+    public static AzureCosmosDbService createService() {
+        return builder()
+                .addLocalMapping(AzureCosmosDbLocalContainerService::new)
+                .addRemoteMapping(AzureCosmosDbRemoteService::new)
+                .build();
+    }
+
+    public static AzureCosmosDbService createSingletonService() {
+        return SingletonServiceHolder.INSTANCE;
+    }
+
+    private static class SingletonServiceHolder {
+        static final AzureCosmosDbService INSTANCE;
+        static {
+            SimpleTestServiceBuilder<AzureCosmosDbService> instance = 
builder();
+            instance.addLocalMapping(
+                    () -> new SingletonAzureCosmosDbService(new 
AzureCosmosDbLocalContainerService(), "azure-cosmos-db"))
+                    .addRemoteMapping(AzureCosmosDbRemoteService::new);
+            INSTANCE = instance.build();
+        }
+    }
+
+    static class AzureCosmosDbLocalContainerService extends 
AzureCosmosDbLocalContainerInfraService
+            implements AzureCosmosDbService {
+    }
+
+    static class AzureCosmosDbRemoteService extends 
AzureCosmosDbRemoteInfraService implements AzureCosmosDbService {
+    }
+}
diff --git 
a/test-infra/camel-test-infra-azure-cosmosdb/src/main/resources/META-INF/MANIFEST.MF
 
b/test-infra/camel-test-infra-azure-cosmosdb/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/test-infra/pom.xml b/test-infra/pom.xml
index 95570efda9ef..e8da1e527977 100644
--- a/test-infra/pom.xml
+++ b/test-infra/pom.xml
@@ -51,6 +51,7 @@
         <module>camel-test-infra-mongodb</module>
         <module>camel-test-infra-rabbitmq</module>
         <module>camel-test-infra-azure-common</module>
+        <module>camel-test-infra-azure-cosmosdb</module>
         <module>camel-test-infra-azure-eventgrid</module>
         <module>camel-test-infra-azure-eventhubs</module>
         <module>camel-test-infra-azure-functions</module>

Reply via email to