From ebef98adf02fc152ac59dc2abc112b8442237e8e Mon Sep 17 00:00:00 2001 From: Gary Wong <8075192+garywg04@users.noreply.github.com> Date: Mon, 9 Aug 2021 21:21:09 +0100 Subject: [PATCH] Use NoCredentialsProvider when firestore emulator enabled (#555) Fixes: #501. --- .../GcpFirestoreAutoConfiguration.java | 18 +++- .../firestore/GcpFirestoreProperties.java | 28 ++++++ ...restoreEmulatorAutoConfigurationTests.java | 89 +++++++++++++++++++ 3 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreEmulatorAutoConfigurationTests.java diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfiguration.java index ab8650767a..81ab2850e3 100644 --- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfiguration.java +++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfiguration.java @@ -19,6 +19,7 @@ import java.io.IOException; import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.cloud.firestore.Firestore; import com.google.cloud.firestore.FirestoreOptions; @@ -81,9 +82,15 @@ public class GcpFirestoreAutoConfiguration { ? gcpFirestoreProperties.getProjectId() : projectIdProvider.getProjectId(); - this.credentialsProvider = (gcpFirestoreProperties.getCredentials().hasKey() - ? new DefaultCredentialsProvider(gcpFirestoreProperties) - : credentialsProvider); + if (gcpFirestoreProperties.getEmulator().isEnabled()) { + // if the emulator is enabled, create CredentialsProvider for this particular case. + this.credentialsProvider = NoCredentialsProvider.create(); + } + else { + this.credentialsProvider = (gcpFirestoreProperties.getCredentials().hasKey() + ? new DefaultCredentialsProvider(gcpFirestoreProperties) + : credentialsProvider); + } this.hostPort = gcpFirestoreProperties.getHostPort(); this.firestoreRootPath = String.format(ROOT_PATH_FORMAT, this.projectId); @@ -109,6 +116,10 @@ public Firestore firestore(FirestoreOptions firestoreOptions) { return firestoreOptions.getService(); } + CredentialsProvider getCredentialsProvider() { + return credentialsProvider; + } + /** * The Firestore reactive template and data repositories support auto-configuration. */ @@ -160,4 +171,5 @@ public ManagedChannel firestoreManagedChannel() { .build(); } } + } diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreProperties.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreProperties.java index 0ffc3f93f9..9578e092ed 100644 --- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreProperties.java +++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreProperties.java @@ -45,6 +45,9 @@ public class GcpFirestoreProperties implements CredentialsSupplier { */ private String hostPort = "firestore.googleapis.com:443"; + @NestedConfigurationProperty + private FirestoreEmulatorProperties emulator = new FirestoreEmulatorProperties(); + @Override public Credentials getCredentials() { return this.credentials; @@ -65,4 +68,29 @@ public String getHostPort() { public void setHostPort(String hostPort) { this.hostPort = hostPort; } + + public FirestoreEmulatorProperties getEmulator() { + return emulator; + } + + public void setEmulator(FirestoreEmulatorProperties emulator) { + this.emulator = emulator; + } + + public static class FirestoreEmulatorProperties { + + /** + * Enables autoconfiguration to use the Firestore 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 + */ + private boolean enabled = false; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + } } diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreEmulatorAutoConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreEmulatorAutoConfigurationTests.java new file mode 100644 index 0000000000..2da2766ee8 --- /dev/null +++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreEmulatorAutoConfigurationTests.java @@ -0,0 +1,89 @@ +/* + * Copyright 2017-2020 the original author or authors. + * + * Licensed 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 + * + * https://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 com.google.cloud.spring.autoconfigure.firestore; + +import com.google.api.gax.core.CredentialsProvider; +import com.google.api.gax.core.NoCredentialsProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.auth.Credentials; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for the Firestore emulator config. + * + * @author Gary Wong + */ +class GcpFirestoreEmulatorAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + GcpContextAutoConfiguration.class, + GcpFirestoreEmulatorAutoConfiguration.class, + GcpFirestoreAutoConfiguration.class)); + + @Test + void testEmulatorEnabledConfig() { + this.contextRunner.withPropertyValues( + "spring.cloud.gcp.firestore.projectId=test-project", + "spring.cloud.gcp.firestore.emulator.enabled=true", + "spring.cloud.gcp.firestore.host-port=localhost:8080" + ).run(context -> { + CredentialsProvider defaultCredentialsProvider = context.getBean(CredentialsProvider.class); + assertThat(defaultCredentialsProvider).isNotInstanceOf(NoCredentialsProvider.class); + + GcpFirestoreAutoConfiguration firestoreAutoConfiguration = context.getBean(GcpFirestoreAutoConfiguration.class); + assertThat(firestoreAutoConfiguration.getCredentialsProvider()).isInstanceOf(NoCredentialsProvider.class); + + FirestoreOptions datastoreOptions = context.getBean(Firestore.class).getOptions(); + assertThat(datastoreOptions.getProjectId()).isEqualTo("test-project"); + + InstantiatingGrpcChannelProvider channelProvider = (InstantiatingGrpcChannelProvider) datastoreOptions.getTransportChannelProvider(); + assertThat(channelProvider.getEndpoint()).isEqualTo("localhost:8080"); + }); + } + + @Test + void testDefaultConfig() { + CredentialsProvider mockedCredentialsProvider = () -> mock(Credentials.class); + + this.contextRunner.withPropertyValues( + "spring.cloud.gcp.firestore.projectId=test-project" + ).withBean("mockedCredentialsProvider", CredentialsProvider.class, () -> mockedCredentialsProvider) + .run(context -> { + GcpFirestoreProperties gcpFirestoreProperties = context.getBean(GcpFirestoreProperties.class); + assertThat(gcpFirestoreProperties.getEmulator().isEnabled()).isFalse(); + + GcpFirestoreAutoConfiguration firestoreAutoConfiguration = context.getBean(GcpFirestoreAutoConfiguration.class); + assertThat(firestoreAutoConfiguration.getCredentialsProvider()).isEqualTo(mockedCredentialsProvider); + + FirestoreOptions datastoreOptions = context.getBean(Firestore.class).getOptions(); + assertThat(datastoreOptions.getProjectId()).isEqualTo("test-project"); + + InstantiatingGrpcChannelProvider channelProvider = (InstantiatingGrpcChannelProvider) datastoreOptions.getTransportChannelProvider(); + assertThat(channelProvider.getEndpoint()).isEqualTo("firestore.googleapis.com:443"); + }); + } +}