This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push: new a1a1cd85e2 Use Pinecone emulator for integration testing a1a1cd85e2 is described below commit a1a1cd85e220abb432728f4be3876b9d42448685 Author: Jono Morris <jono.mor...@xtra.co.nz> AuthorDate: Sat Apr 12 00:08:13 2025 +1200 Use Pinecone emulator for integration testing * use pinecone emulator for testing * Add profile for windows build --- integration-tests/pinecone/pom.xml | 27 ++++++++++++ .../component/pinecone/it/PineconeResource.java | 31 ++------------ .../component/pinecone/it/PineconeTest.java | 38 +++++++---------- .../pinecone/it/PineconeTestResource.java | 48 ++++++++++++++++------ ...dexes-0cb5785f-987c-481d-b49a-51dac8cc4a5a.json | 29 ------------- ...dexes-293cf644-849f-4860-809f-13278d509acb.json | 30 -------------- ...dexes-5854cd4f-0384-40dd-bfa5-bf36592d3a9b.json | 33 --------------- ...index-92a8d520-01e3-48ae-89eb-1f51beed3276.json | 26 ------------ pom.xml | 1 + 9 files changed, 83 insertions(+), 180 deletions(-) diff --git a/integration-tests/pinecone/pom.xml b/integration-tests/pinecone/pom.xml index c8707b0f41..2ce380fa1a 100644 --- a/integration-tests/pinecone/pom.xml +++ b/integration-tests/pinecone/pom.xml @@ -57,6 +57,22 @@ </dependency> <!-- test dependencies --> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>pinecone</artifactId> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit4-mock</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> @@ -144,6 +160,17 @@ </dependency> </dependencies> </profile> + <profile> + <id>skip-testcontainers-tests</id> + <activation> + <property> + <name>skip-testcontainers-tests</name> + </property> + </activation> + <properties> + <skipTests>true</skipTests> + </properties> + </profile> </profiles> </project> diff --git a/integration-tests/pinecone/src/main/java/org/apache/camel/quarkus/component/pinecone/it/PineconeResource.java b/integration-tests/pinecone/src/main/java/org/apache/camel/quarkus/component/pinecone/it/PineconeResource.java index 9f2d7da503..bf937ea3c4 100644 --- a/integration-tests/pinecone/src/main/java/org/apache/camel/quarkus/component/pinecone/it/PineconeResource.java +++ b/integration-tests/pinecone/src/main/java/org/apache/camel/quarkus/component/pinecone/it/PineconeResource.java @@ -16,9 +16,7 @@ */ package org.apache.camel.quarkus.component.pinecone.it; -import java.io.IOException; import java.util.List; -import java.util.Optional; import io.pinecone.clients.Pinecone; import io.pinecone.proto.UpsertResponse; @@ -35,15 +33,10 @@ import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; import org.apache.camel.ProducerTemplate; import org.apache.camel.component.pinecone.PineconeVectorDbComponent; import org.apache.camel.component.pinecone.PineconeVectorDbConfiguration; import org.eclipse.microprofile.config.ConfigProvider; -import org.jetbrains.annotations.NotNull; import org.openapitools.db_control.client.model.IndexModel; @Path("/pinecone") @@ -100,26 +93,10 @@ public class PineconeResource { } static Pinecone createPineconeClient() { - Optional<String> wireMockUrl = ConfigProvider.getConfig().getOptionalValue("wiremock.url", String.class); - String apiKey = ConfigProvider.getConfig().getValue("camel.component.pinecone.token", String.class); - Pinecone.Builder builder = new Pinecone.Builder(apiKey); - if (wireMockUrl.isPresent()) { - String baseUri = wireMockUrl.get(); - OkHttpClient client = new OkHttpClient.Builder() - .addInterceptor(new Interceptor() { - @NotNull - @Override - public Response intercept(@NotNull Interceptor.Chain chain) throws IOException { - Request originalRequest = chain.request(); - Request wireMockedRequest = originalRequest.newBuilder() - .url(baseUri + originalRequest.url().encodedPath()) - .build(); - return chain.proceed(wireMockedRequest); - } - }) - .build(); - return builder.withOkHttpClient(client).build(); - } + String endpoint = ConfigProvider.getConfig().getValue("pinecone.emulator.endpoint", String.class); + Pinecone.Builder builder = new Pinecone.Builder("pclocal") + .withHost(endpoint) + .withTlsEnabled(false); return builder.build(); } } diff --git a/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTest.java b/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTest.java index 3f5fc4f2f4..2884e1be44 100644 --- a/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTest.java +++ b/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTest.java @@ -18,14 +18,12 @@ package org.apache.camel.quarkus.component.pinecone.it; import java.time.Duration; import java.util.List; -import java.util.Optional; import io.pinecone.clients.Pinecone; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.eclipse.microprofile.config.ConfigProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.openapitools.db_control.client.model.IndexModel; @@ -70,32 +68,26 @@ class PineconeTest { .anyMatch(status -> status.getState().equals(READY)); }); - // Some index endpoints are not mocked: - // - They use a dynamic host, separate from the core pinecone API endpoints - // - They are gRPC endpoints - Optional<String> wireMockUrl = ConfigProvider.getConfig().getOptionalValue("wiremock.url", String.class); - if (!wireMockUrl.isPresent()) { - // Upsert - List<Float> vectors = List.of(1.0f, 2.0f, 3.0f); + // Upsert + List<Float> vectors = List.of(1.0f, 2.0f, 3.0f); + RestAssured.given() + .contentType(ContentType.JSON) + .body(vectors) + .put("/pinecone/index") + .then() + .statusCode(200) + .body(is("1")); + + // Query upserted data by vector + await().pollInterval(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(30)).untilAsserted(() -> { RestAssured.given() .contentType(ContentType.JSON) .body(vectors) - .put("/pinecone/index") + .get("/pinecone/index") .then() .statusCode(200) - .body(is("1")); - - // Query upserted data by vector - await().pollInterval(Duration.ofSeconds(1)).atMost(Duration.ofSeconds(30)).untilAsserted(() -> { - RestAssured.given() - .contentType(ContentType.JSON) - .body(vectors) - .get("/pinecone/index") - .then() - .statusCode(200) - .body(startsWith("0.9")); - }); - } + .body(startsWith("0.9")); + }); } finally { RestAssured.given() .delete("/pinecone/index") diff --git a/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTestResource.java b/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTestResource.java index a639c6d6ff..b884ada52f 100644 --- a/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTestResource.java +++ b/integration-tests/pinecone/src/test/java/org/apache/camel/quarkus/component/pinecone/it/PineconeTestResource.java @@ -16,28 +16,52 @@ */ package org.apache.camel.quarkus.component.pinecone.it; +import java.util.List; import java.util.Map; -import org.apache.camel.quarkus.test.wiremock.WireMockTestResourceLifecycleManager; +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import org.apache.camel.util.CollectionHelper; +import org.eclipse.microprofile.config.ConfigProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.pinecone.PineconeLocalContainer; -public class PineconeTestResource extends WireMockTestResourceLifecycleManager { - public static final String PINECONE_API_BASE_URL = "https://api.pinecone.io"; - private static final String PINECONE_API_KEY_ENV = "PINECONE_API_KEY"; +public class PineconeTestResource implements QuarkusTestResourceLifecycleManager { + + private static final Logger log = LoggerFactory.getLogger(PineconeTestResource.class); + private static final String PINECONE_IMAGE = ConfigProvider.getConfig().getValue("pinecone.container.image", String.class); + + private PineconeLocalContainer container; @Override public Map<String, String> start() { - return CollectionHelper.mergeMaps(super.start(), CollectionHelper.mapOf( - "camel.component.pinecone.token", envOrDefault(PINECONE_API_KEY_ENV, "test-pinecone-api-key"))); - } + try { + container = new PineconeLocalContainer(PINECONE_IMAGE) + .withLogConsumer(new Slf4jLogConsumer(log)) + .waitingFor(Wait.forListeningPort()); - @Override - protected String getRecordTargetBaseUrl() { - return PINECONE_API_BASE_URL; + // port 5081 for the index + container.setPortBindings(List.of("5080:5080", "5081:5081")); + + container.start(); + + return CollectionHelper.mapOf("pinecone.emulator.endpoint", container.getEndpoint()); + + } catch (Exception e) { + throw new RuntimeException(e); + } } @Override - protected boolean isMockingEnabled() { - return !envVarsPresent("PINECONE_API_KEY"); + public void stop() { + try { + if (container != null) { + container.stop(); + } + } catch (Exception e) { + // ignored + } } } diff --git a/integration-tests/pinecone/src/test/resources/mappings/indexes-0cb5785f-987c-481d-b49a-51dac8cc4a5a.json b/integration-tests/pinecone/src/test/resources/mappings/indexes-0cb5785f-987c-481d-b49a-51dac8cc4a5a.json deleted file mode 100644 index fbcfc19f22..0000000000 --- a/integration-tests/pinecone/src/test/resources/mappings/indexes-0cb5785f-987c-481d-b49a-51dac8cc4a5a.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "id" : "0cb5785f-987c-481d-b49a-51dac8cc4a5a", - "name" : "indexes", - "request" : { - "url" : "/indexes", - "method" : "GET" - }, - "response" : { - "status" : 200, - "body" : "{\"indexes\":[]}", - "headers" : { - "X-Cloud-Trace-Context" : "bd4d9cb6698e7373332f57eaeeea6592", - "access-control-allow-origin" : "*", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "Google Frontend", - "vary" : "origin,access-control-request-method,access-control-request-headers", - "content-type" : "application/json", - "Date" : "Fri, 22 Nov 2024 09:23:39 GMT", - "Via" : "1.1 google", - "x-pinecone-api-version" : "2024-10", - "access-control-expose-headers" : "*" - } - }, - "uuid" : "0cb5785f-987c-481d-b49a-51dac8cc4a5a", - "persistent" : true, - "scenarioName" : "scenario-1-indexes", - "requiredScenarioState" : "scenario-1-indexes-2", - "insertionIndex" : 1 -} \ No newline at end of file diff --git a/integration-tests/pinecone/src/test/resources/mappings/indexes-293cf644-849f-4860-809f-13278d509acb.json b/integration-tests/pinecone/src/test/resources/mappings/indexes-293cf644-849f-4860-809f-13278d509acb.json deleted file mode 100644 index 39aef73586..0000000000 --- a/integration-tests/pinecone/src/test/resources/mappings/indexes-293cf644-849f-4860-809f-13278d509acb.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id" : "293cf644-849f-4860-809f-13278d509acb", - "name" : "indexes", - "request" : { - "url" : "/indexes", - "method" : "GET" - }, - "response" : { - "status" : 200, - "body" : "{\"indexes\":[{\"name\":\"test-index\",\"metric\":\"cosine\",\"dimension\":3,\"status\":{\"ready\":true,\"state\":\"Ready\"},\"host\":\"test-index-3ncz9x1.svc.aped-4627-b74a.pinecone.io\",\"spec\":{\"serverless\":{\"region\":\"us-east-1\",\"cloud\":\"aws\"}},\"deletion_protection\":\"disabled\",\"tags\":null}]}", - "headers" : { - "X-Cloud-Trace-Context" : "5d76189a457047bf315cdd0913392ffe", - "access-control-allow-origin" : "*", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "Google Frontend", - "vary" : "origin,access-control-request-method,access-control-request-headers", - "content-type" : "application/json", - "Date" : "Fri, 22 Nov 2024 09:23:37 GMT", - "Via" : "1.1 google", - "x-pinecone-api-version" : "2024-10", - "access-control-expose-headers" : "*" - } - }, - "uuid" : "293cf644-849f-4860-809f-13278d509acb", - "persistent" : true, - "scenarioName" : "scenario-1-indexes", - "requiredScenarioState" : "Started", - "newScenarioState" : "scenario-1-indexes-2", - "insertionIndex" : 3 -} \ No newline at end of file diff --git a/integration-tests/pinecone/src/test/resources/mappings/indexes-5854cd4f-0384-40dd-bfa5-bf36592d3a9b.json b/integration-tests/pinecone/src/test/resources/mappings/indexes-5854cd4f-0384-40dd-bfa5-bf36592d3a9b.json deleted file mode 100644 index 6fa62e106d..0000000000 --- a/integration-tests/pinecone/src/test/resources/mappings/indexes-5854cd4f-0384-40dd-bfa5-bf36592d3a9b.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id" : "5854cd4f-0384-40dd-bfa5-bf36592d3a9b", - "name" : "indexes", - "request" : { - "url" : "/indexes", - "method" : "POST", - "bodyPatterns" : [ { - "equalToJson" : "{\"name\":\"test-index\",\"dimension\":3,\"metric\":\"cosine\",\"deletion_protection\":\"disabled\",\"spec\":{\"serverless\":{\"cloud\":\"aws\",\"region\":\"us-east-1\"}}}", - "ignoreArrayOrder" : true, - "ignoreExtraElements" : true - } ] - }, - "response" : { - "status" : 201, - "body" : "{\"name\":\"test-index\",\"metric\":\"cosine\",\"dimension\":3,\"status\":{\"ready\":false,\"state\":\"Initializing\"},\"host\":\"test-index-3ncz9x1.svc.aped-4627-b74a.pinecone.io\",\"spec\":{\"serverless\":{\"region\":\"us-east-1\",\"cloud\":\"aws\"}},\"deletion_protection\":\"disabled\",\"tags\":null}", - "headers" : { - "X-Cloud-Trace-Context" : "7cae6b2507fa30364f1f71182f9319aa", - "access-control-allow-origin" : "*", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "Google Frontend", - "vary" : "origin,access-control-request-method,access-control-request-headers", - "content-type" : "application/json", - "x-pinecone-operation-id" : "4e23a028-63e6-430d-9c8a-bbfab9596819", - "Date" : "Fri, 22 Nov 2024 09:23:35 GMT", - "Via" : "1.1 google", - "x-pinecone-api-version" : "2024-10", - "access-control-expose-headers" : "*" - } - }, - "uuid" : "5854cd4f-0384-40dd-bfa5-bf36592d3a9b", - "persistent" : true, - "insertionIndex" : 4 -} \ No newline at end of file diff --git a/integration-tests/pinecone/src/test/resources/mappings/indexes_test-index-92a8d520-01e3-48ae-89eb-1f51beed3276.json b/integration-tests/pinecone/src/test/resources/mappings/indexes_test-index-92a8d520-01e3-48ae-89eb-1f51beed3276.json deleted file mode 100644 index 28585d8222..0000000000 --- a/integration-tests/pinecone/src/test/resources/mappings/indexes_test-index-92a8d520-01e3-48ae-89eb-1f51beed3276.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id" : "92a8d520-01e3-48ae-89eb-1f51beed3276", - "name" : "indexes_test-index", - "request" : { - "url" : "/indexes/test-index", - "method" : "DELETE" - }, - "response" : { - "status" : 202, - "headers" : { - "X-Cloud-Trace-Context" : "99e9c93ac1094bbc1a4df5f322b49a40", - "access-control-allow-origin" : "*", - "Alt-Svc" : "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000", - "Server" : "Google Frontend", - "vary" : "origin,access-control-request-method,access-control-request-headers", - "Date" : "Fri, 22 Nov 2024 09:23:37 GMT", - "Via" : "1.1 google", - "Content-Type" : "text/html", - "x-pinecone-api-version" : "2024-10", - "access-control-expose-headers" : "*" - } - }, - "uuid" : "92a8d520-01e3-48ae-89eb-1f51beed3276", - "persistent" : true, - "insertionIndex" : 2 -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index a9e6047406..1a14a17272 100644 --- a/pom.xml +++ b/pom.xml @@ -256,6 +256,7 @@ <mongodb.container.image>mirror.gcr.io/mongo:7.0</mongodb.container.image> <nats.container.image>mirror.gcr.io/nats:2.10.18</nats.container.image> <openssh-server.container.image>mirror.gcr.io/linuxserver/openssh-server:version-9.7_p1-r4</openssh-server.container.image> + <pinecone.container.image>ghcr.io/pinecone-io/pinecone-local:v0.7.0</pinecone.container.image> <postgres.container.image>mirror.gcr.io/postgres:15.0</postgres.container.image> <postgres-debezium.container.image>mirror.gcr.io/debezium/postgres:15-alpine</postgres-debezium.container.image> <qdrant.container.image>mirror.gcr.io/qdrant/qdrant:v1.9.7-unprivileged</qdrant.container.image>