oscerd commented on code in PR #29249: URL: https://github.com/apache/camel/pull/29249#discussion_r4511022820
########## test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java: ########## @@ -0,0 +1,151 @@ +/* + * 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.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import com.azure.cosmos.CosmosAsyncClient; +import com.azure.cosmos.CosmosClientBuilder; +import org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties; + +public final class AzureCosmosDbClientUtils { + private static final String TRUST_STORE = "javax.net.ssl.trustStore"; + private static final String TRUST_STORE_TYPE = "javax.net.ssl.trustStoreType"; + private static final String TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword"; + private static final String TRUST_STORE_PROVIDER = "javax.net.ssl.trustStoreProvider"; + + 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. + */ + public static CosmosAsyncClient createAsyncClient() { + CosmosClientBuilder builder = new CosmosClientBuilder() + .endpoint(System.getProperty(AzureCosmosDbProperties.ENDPOINT)) + .key(System.getProperty(AzureCosmosDbProperties.ACCESS_KEY)) + .contentResponseOnWriteEnabled(true); + + String instanceType = System.getProperty(AzureCosmosDbProperties.INSTANCE_TYPE); + if (instanceType == null || instanceType.equals("local-azure-container")) { + // Floci AZ emulates the gateway API only, and the client keeps to the endpoint whatever locations the + // emulator advertises + builder.gatewayMode() + .endpointDiscoveryEnabled(false); + + return buildTrusting(builder, System.getProperty(AzureCosmosDbProperties.CERTIFICATE_URL)); + } + + return builder.buildAsyncClient(); + } + + /* + * The Cosmos DB SDK has no option for the certificates a client trusts: a client trusts the default trust store of + * the JVM, which it loads when it is built. The default trust store holds the certificate of the emulator, next to the + * certificates the JVM trusts, only while the client is built: the client trusts the emulator, and the trust of the + * JVM is the same once the client is built. + */ + private static synchronized CosmosAsyncClient buildTrusting(CosmosClientBuilder builder, String certificateUrl) { + Map<String, String> previous = new HashMap<>(); + for (String name : new String[] { TRUST_STORE, TRUST_STORE_TYPE, TRUST_STORE_PASSWORD, TRUST_STORE_PROVIDER }) { + previous.put(name, System.getProperty(name)); + } + + Path trustStoreFile = null; + try { + String password = UUID.randomUUID().toString(); + trustStoreFile = Files.createTempFile("floci-az-cosmos-trust", ".p12"); + try (OutputStream out = Files.newOutputStream(trustStoreFile)) { + trustStore(readCertificate(certificateUrl)).store(out, password.toCharArray()); + } + + System.setProperty(TRUST_STORE, trustStoreFile.toString()); + System.setProperty(TRUST_STORE_TYPE, "PKCS12"); + System.setProperty(TRUST_STORE_PASSWORD, password); + System.clearProperty(TRUST_STORE_PROVIDER); + + return builder.buildAsyncClient(); Review Comment: No longer applies after 58115fec3209: the client builds no temporary trust store any more. It sets the emulator switch of the Cosmos DB SDK, which the SDK reads when the client is built, so there is no file to delete and no reliance on when the SDK loads its `SslContext`. _Claude Code on behalf of Andrea Cosentino_ ########## components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/operations/CosmosDbContainerOperationsIT.java: ########## @@ -50,38 +49,31 @@ 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(); + @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(); + // only testCaptureChangeFeed creates the lease database, and it does not always run + clientWrapper.readAllDatabases() + .filter(database -> LEASE_DATABASE_NAME.equals(database.getId())) + .flatMap(database -> clientWrapper.getDatabase(LEASE_DATABASE_NAME).delete()) + .blockLast(); } Review Comment: Fixed in 58115fec3209: the cleanup is best effort. It deletes each database directly, ignores a 404 (the lease database exists only when the change feed test ran), and logs any other failure at WARN instead of throwing it. _Claude Code on behalf of Andrea Cosentino_ ########## test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java: ########## @@ -0,0 +1,151 @@ +/* + * 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.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import com.azure.cosmos.CosmosAsyncClient; +import com.azure.cosmos.CosmosClientBuilder; +import org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties; + +public final class AzureCosmosDbClientUtils { + private static final String TRUST_STORE = "javax.net.ssl.trustStore"; + private static final String TRUST_STORE_TYPE = "javax.net.ssl.trustStoreType"; + private static final String TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword"; + private static final String TRUST_STORE_PROVIDER = "javax.net.ssl.trustStoreProvider"; + + 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. + */ + public static CosmosAsyncClient createAsyncClient() { + CosmosClientBuilder builder = new CosmosClientBuilder() + .endpoint(System.getProperty(AzureCosmosDbProperties.ENDPOINT)) + .key(System.getProperty(AzureCosmosDbProperties.ACCESS_KEY)) + .contentResponseOnWriteEnabled(true); + + String instanceType = System.getProperty(AzureCosmosDbProperties.INSTANCE_TYPE); + if (instanceType == null || instanceType.equals("local-azure-container")) { + // Floci AZ emulates the gateway API only, and the client keeps to the endpoint whatever locations the + // emulator advertises + builder.gatewayMode() + .endpointDiscoveryEnabled(false); + + return buildTrusting(builder, System.getProperty(AzureCosmosDbProperties.CERTIFICATE_URL)); Review Comment: No longer applies after 58115fec3209: the certificate URL property is gone with the trust store. The client now requires the endpoint property with a message that names it (`Objects.requireNonNull`). _Claude Code on behalf of Andrea Cosentino_ ########## test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbInfraService.java: ########## @@ -0,0 +1,36 @@ +/* + * 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 + */ +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(); Review Comment: Thanks for trying it. With 58115fec3209 there is no certificate to fetch any more: a client needs the gateway mode and the emulator switch of the SDK (`COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED`, or the `COSMOS_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED` environment variable for `camel infra run` users). The Javadoc of the interface and of the local service, and the PR description, now say so, including that a route needs a `cosmosAsyncClient` of its own because the component builds a direct-mode client. The connection-mode option is [CAMEL-26763](https://issues.apache.org/jira/browse/CAMEL-26763). _Claude Code on behalf of Andrea Cosentino_ ########## test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java: ########## @@ -0,0 +1,151 @@ +/* + * 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.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import com.azure.cosmos.CosmosAsyncClient; +import com.azure.cosmos.CosmosClientBuilder; +import org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties; + +public final class AzureCosmosDbClientUtils { + private static final String TRUST_STORE = "javax.net.ssl.trustStore"; + private static final String TRUST_STORE_TYPE = "javax.net.ssl.trustStoreType"; + private static final String TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword"; + private static final String TRUST_STORE_PROVIDER = "javax.net.ssl.trustStoreProvider"; + + 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. + */ + public static CosmosAsyncClient createAsyncClient() { + CosmosClientBuilder builder = new CosmosClientBuilder() + .endpoint(System.getProperty(AzureCosmosDbProperties.ENDPOINT)) + .key(System.getProperty(AzureCosmosDbProperties.ACCESS_KEY)) + .contentResponseOnWriteEnabled(true); + + String instanceType = System.getProperty(AzureCosmosDbProperties.INSTANCE_TYPE); + if (instanceType == null || instanceType.equals("local-azure-container")) { + // Floci AZ emulates the gateway API only, and the client keeps to the endpoint whatever locations the + // emulator advertises + builder.gatewayMode() + .endpointDiscoveryEnabled(false); + + return buildTrusting(builder, System.getProperty(AzureCosmosDbProperties.CERTIFICATE_URL)); + } + + return builder.buildAsyncClient(); + } + + /* + * The Cosmos DB SDK has no option for the certificates a client trusts: a client trusts the default trust store of + * the JVM, which it loads when it is built. The default trust store holds the certificate of the emulator, next to the + * certificates the JVM trusts, only while the client is built: the client trusts the emulator, and the trust of the + * JVM is the same once the client is built. + */ + private static synchronized CosmosAsyncClient buildTrusting(CosmosClientBuilder builder, String certificateUrl) { Review Comment: Thanks, adopted in 58115fec3209: the client sets `COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED`, plus `COSMOS.EMULATOR_HOST` when the Docker host is not a local one. The trust-store swap, the CA download and the PKCS12 file are gone. Against Floci AZ 16 ITs pass and 6 are remote only, as before. _Claude Code on behalf of Andrea Cosentino_ -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
