diff --git a/spring-cloud-gcp-autoconfigure/pom.xml b/spring-cloud-gcp-autoconfigure/pom.xml
index ea4bbe4ef2..0c38edfe8e 100644
--- a/spring-cloud-gcp-autoconfigure/pom.xml
+++ b/spring-cloud-gcp-autoconfigure/pom.xml
@@ -369,7 +369,7 @@
maven-failsafe-plugin
- spring-cloud-gcp-ci-firestore
+ firestoredb
diff --git a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/it/FirestoreIntegrationTestsConfiguration.java b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/it/FirestoreIntegrationTestsConfiguration.java
index f1751e1429..1e3a1a3e86 100644
--- a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/it/FirestoreIntegrationTestsConfiguration.java
+++ b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/it/FirestoreIntegrationTestsConfiguration.java
@@ -16,7 +16,10 @@
package com.google.cloud.spring.data.firestore.it;
+import com.google.api.client.util.escape.PercentEscaper;
+import com.google.api.gax.rpc.internal.Headers;
import com.google.auth.oauth2.GoogleCredentials;
+import com.google.cloud.spring.core.DefaultGcpProjectIdProvider;
import com.google.cloud.spring.data.firestore.FirestoreTemplate;
import com.google.cloud.spring.data.firestore.entities.UserRepository;
import com.google.cloud.spring.data.firestore.mapping.FirestoreClassMapper;
@@ -26,11 +29,15 @@
import com.google.cloud.spring.data.firestore.transaction.ReactiveFirestoreTransactionManager;
import com.google.firestore.v1.FirestoreGrpc;
import io.grpc.CallCredentials;
+import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
+import io.grpc.Metadata;
import io.grpc.auth.MoreCallCredentials;
+import io.grpc.stub.MetadataUtils;
import java.io.IOException;
import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
@@ -44,17 +51,34 @@
@EnableReactiveFirestoreRepositories(basePackageClasses = UserRepository.class)
@EnableTransactionManagement
public class FirestoreIntegrationTestsConfiguration {
- @Value("projects/${test.integration.firestore.project-id}/databases/(default)/documents")
String defaultParent;
+ String projectId;
+
+ String databaseId;
+
+ @Autowired
+ public FirestoreIntegrationTestsConfiguration(
+ @Value("${test.integration.firestore.database-id:(default)}") String databaseId) {
+ this.projectId = new DefaultGcpProjectIdProvider().getProjectId();
+ this.databaseId = databaseId;
+ this.defaultParent =
+ String.format("projects/%s/databases/%s/documents", this.projectId, databaseId);
+ }
+
+ private static final PercentEscaper PERCENT_ESCAPER = new PercentEscaper("._-~");
+
@Bean
- FirestoreGrpc.FirestoreStub firestoreStub() throws IOException {
+ FirestoreGrpc.FirestoreStub firestoreStub(ClientInterceptor firestoreRoutingHeadersInterceptor)
+ throws IOException {
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
CallCredentials callCredentials = MoreCallCredentials.from(credentials);
// Create a channel
ManagedChannel channel =
- ManagedChannelBuilder.forTarget("dns:///firestore.googleapis.com:443").build();
+ ManagedChannelBuilder.forTarget("dns:///firestore.googleapis.com:443")
+ .intercept(firestoreRoutingHeadersInterceptor)
+ .build();
return FirestoreGrpc.newStub(channel).withCallCredentials(callCredentials);
}
@@ -72,6 +96,24 @@ public FirestoreTemplate firestoreTemplate(
firestoreStub, this.defaultParent, classMapper, firestoreMappingContext);
}
+ @Bean
+ @ConditionalOnMissingBean(name = "firestoreRoutingHeadersInterceptor")
+ public ClientInterceptor firestoreRoutingHeadersInterceptor() {
+ // add routing header for custom database id
+ Metadata routingHeader = new Metadata();
+ if (projectId != null && databaseId != null) {
+ Metadata.Key key =
+ Metadata.Key.of(Headers.DYNAMIC_ROUTING_HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER);
+ routingHeader.put(
+ key,
+ "project_id="
+ + PERCENT_ESCAPER.escape(projectId)
+ + "&database_id="
+ + PERCENT_ESCAPER.escape(databaseId));
+ }
+ return MetadataUtils.newAttachHeadersInterceptor(routingHeader);
+ }
+
@Bean
@ConditionalOnMissingBean
public ReactiveFirestoreTransactionManager firestoreTransactionManager(
diff --git a/spring-cloud-gcp-data-firestore/src/test/resources/application-test.properties b/spring-cloud-gcp-data-firestore/src/test/resources/application-test.properties
index ca4cfd0603..fa007f1025 100644
--- a/spring-cloud-gcp-data-firestore/src/test/resources/application-test.properties
+++ b/spring-cloud-gcp-data-firestore/src/test/resources/application-test.properties
@@ -1 +1 @@
-test.integration.firestore.project-id=spring-cloud-gcp-ci-firestore
+test.integration.firestore.database-id=firestoredb
diff --git a/spring-cloud-gcp-samples/spring-cloud-gcp-data-firestore-sample/src/test/resources/application-test.properties b/spring-cloud-gcp-samples/spring-cloud-gcp-data-firestore-sample/src/test/resources/application-test.properties
index 21dd41714f..edc6d2bef0 100644
--- a/spring-cloud-gcp-samples/spring-cloud-gcp-data-firestore-sample/src/test/resources/application-test.properties
+++ b/spring-cloud-gcp-samples/spring-cloud-gcp-data-firestore-sample/src/test/resources/application-test.properties
@@ -1,2 +1 @@
-spring.cloud.gcp.firestore.project-id=spring-cloud-gcp-ci
spring.cloud.gcp.firestore.database-id=firestoredb
\ No newline at end of file
diff --git a/spring-cloud-gcp-samples/spring-cloud-gcp-starter-firestore-sample/src/test/resources/application-test.properties b/spring-cloud-gcp-samples/spring-cloud-gcp-starter-firestore-sample/src/test/resources/application-test.properties
index 32c8585e05..918db35743 100644
--- a/spring-cloud-gcp-samples/spring-cloud-gcp-starter-firestore-sample/src/test/resources/application-test.properties
+++ b/spring-cloud-gcp-samples/spring-cloud-gcp-starter-firestore-sample/src/test/resources/application-test.properties
@@ -1 +1 @@
-spring.cloud.gcp.firestore.project-id=spring-cloud-gcp-ci-firestore
+spring.cloud.gcp.firestore.database-id=firestoredb