Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for Firestore database id configuration #2164

Merged
merged 11 commits into from
Sep 19, 2023
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/datastore.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ The following configuration options are available:
| Name | Description | Required | Default value
| `spring.cloud.gcp.datastore.enabled` | Enables the Cloud Datastore client | No | `true`
| `spring.cloud.gcp.datastore.project-id` | Google Cloud project ID where the Google Cloud Datastore API is hosted, if different from the one in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No |
| `spring.cloud.gcp.datastore.database-id` | Google Cloud project can host multiple databases. You can specify which database will be used. | No |
| `spring.cloud.gcp.datastore.database-id` | Google Cloud project can host multiple databases. You can specify which database will be used. If not specified, the database id will be "(default)". | No |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Default value" column is missing.

| `spring.cloud.gcp.datastore.credentials.location` | OAuth2 credentials for authenticating with the Google Cloud Datastore API, if different from the ones in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No |
| `spring.cloud.gcp.datastore.credentials.encoded-key` | Base64-encoded OAuth2 credentials for authenticating with the Google Cloud Datastore API, if different from the ones in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No |
| `spring.cloud.gcp.datastore.credentials.scopes` | https://developers.google.com/identity/protocols/googlescopes[OAuth2 scope] for Spring Framework on Google CloudDatastore credentials | No | https://www.googleapis.com/auth/datastore
Expand Down
1 change: 1 addition & 0 deletions docs/src/main/asciidoc/firestore.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The Spring Boot starter for Google Cloud Firestore provides the following config
| Name | Description | Required | Default value
| `spring.cloud.gcp.firestore.enabled` | Enables or disables Firestore auto-configuration | No | `true`
| `spring.cloud.gcp.firestore.project-id` | Google Cloud project ID where the Google Cloud Firestore API is hosted, if different from the one in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No |
| `spring.cloud.gcp.firestore.database-id` | Google Cloud project can host multiple databases. You can specify which database will be used. If not specified, the database id will be "(default)". | No |
| `spring.cloud.gcp.firestore.emulator.enabled` | Enables the usage of an emulator. If this is set to true, then you should set the `spring.cloud.gcp.firestore.host-port` to the host:port of your locally running emulator instance | No | `false`
| `spring.cloud.gcp.firestore.host-port` | The host and port of the Firestore service; can be overridden to specify connecting to an already-running https://firebase.google.com/docs/emulator-suite/install_and_configure[Firestore emulator] instance. | No | `firestore.googleapis.com:443` (the host/port of official Firestore service)
| `spring.cloud.gcp.firestore.credentials.location` | OAuth2 credentials for authenticating with the Google Cloud Firestore API, if different from the ones in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public class GcpFirestoreAutoConfiguration {

private final String projectId;

private final String databaseId;

private final CredentialsProvider credentialsProvider;

private final String hostPort;
Expand All @@ -74,6 +76,7 @@ public class GcpFirestoreAutoConfiguration {
throws IOException {

this.projectId = gcpFirestoreProperties.getResolvedProjectId(projectIdProvider);
this.databaseId = gcpFirestoreProperties.getDatabaseId();

if (gcpFirestoreProperties.getEmulator().isEnabled()) {
// if the emulator is enabled, create CredentialsProvider for this particular case.
Expand All @@ -92,13 +95,19 @@ public class GcpFirestoreAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public FirestoreOptions firestoreOptions() {
return FirestoreOptions.getDefaultInstance().toBuilder()

FirestoreOptions.Builder builder = FirestoreOptions.getDefaultInstance().toBuilder()
.setCredentialsProvider(this.credentialsProvider)
.setProjectId(this.projectId)
.setHeaderProvider(USER_AGENT_HEADER_PROVIDER)
.setChannelProvider(
InstantiatingGrpcChannelProvider.newBuilder().setEndpoint(this.hostPort).build())
.build();
InstantiatingGrpcChannelProvider.newBuilder().setEndpoint(this.hostPort).build());

if (databaseId != null) {
blakeli0 marked this conversation as resolved.
Show resolved Hide resolved
builder.setDatabaseId(databaseId);
}

return builder.build();
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*/
@ConfigurationProperties("spring.cloud.gcp.firestore")
public class GcpFirestoreProperties implements CredentialsSupplier {
private static final String ROOT_PATH_FORMAT = "projects/%s/databases/(default)/documents";
private static final String ROOT_PATH_FORMAT = "projects/%s/databases/%s/documents";

/**
* Overrides the GCP OAuth2 credentials specified in the Core module. Uses same URL as Datastore
Expand All @@ -40,6 +40,8 @@ public class GcpFirestoreProperties implements CredentialsSupplier {

private String projectId;

private String databaseId;

/**
* The host and port of the Firestore emulator service; can be overridden to specify an emulator.
*/
Expand All @@ -65,6 +67,14 @@ public void setProjectId(String projectId) {
this.projectId = projectId;
}

public String getDatabaseId() {
return databaseId;
}

public void setDatabaseId(String databaseId) {
this.databaseId = databaseId;
}

public String getHostPort() {
return hostPort;
}
Expand All @@ -82,7 +92,8 @@ public void setEmulator(FirestoreEmulatorProperties emulator) {
}

public String getFirestoreRootPath(GcpProjectIdProvider projectIdProvider) {
return String.format(ROOT_PATH_FORMAT, this.getResolvedProjectId(projectIdProvider));
return String.format(ROOT_PATH_FORMAT, this.getResolvedProjectId(projectIdProvider),
this.getDatabaseId() == null ? "(default)" : this.getDatabaseId());
meltsufin marked this conversation as resolved.
Show resolved Hide resolved
}

public static class FirestoreEmulatorProperties {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ class GcpFirestoreAutoConfigurationTests {
.withPropertyValues("spring.cloud.gcp.firestore.project-id=test-project");

@Test
void testDatastoreOptionsCorrectlySet() {
void testFirestoreOptionsCorrectlySet() {
this.contextRunner.run(
context -> {
FirestoreOptions datastoreOptions = context.getBean(Firestore.class).getOptions();
assertThat(datastoreOptions.getProjectId()).isEqualTo("test-project");
assertThat(datastoreOptions.getDatabaseId()).isEqualTo("(default)");
meltsufin marked this conversation as resolved.
Show resolved Hide resolved
});
}

Expand Down Expand Up @@ -95,6 +96,20 @@ void testTransactionManagerExcludedWithoutAutoConfiguration() {
});
}

@Test
void testDatabaseId() {
meltsufin marked this conversation as resolved.
Show resolved Hide resolved
contextRunner
.withPropertyValues("spring.cloud.gcp.firestore.database-id=mydb")
.run(
context -> {
FirestoreOptions datastoreOptions = context.getBean(Firestore.class).getOptions();
assertThat(datastoreOptions.getDatabaseId()).isEqualTo("mydb");
String rootPath = context.getBean(GcpFirestoreProperties.class)
.getFirestoreRootPath(() -> "test");
assertThat(rootPath).isEqualTo("projects/test/databases/mydb/documents");
});
}

/** Spring Boot config for tests. */
@AutoConfigurationPackage
static class TestConfiguration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ void testSortQuery_methodName_sortByDocumentId() {
@Configuration
@EnableReactiveFirestoreRepositories(basePackageClasses = UserRepository.class)
static class FirestoreRepositoryTestsConfiguration {
private static final String DEFAULT_PARENT =
"projects/my-project/databases/(default)/documents";

@Bean
public FirestoreMappingContext firestoreMappingContext() {
Expand Down
Loading