-
Notifications
You must be signed in to change notification settings - Fork 336
feat: add properties to set universe domain and endpoint in bigquery #3158
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
Changes from 5 commits
929844e
bf6887b
e86aa9e
7e1f734
9419b7b
8364de1
a8b8ad2
8e7b4bf
83f0fff
c3ebe7c
4b34ff3
2309417
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,11 @@ public class GcpBigQueryAutoConfiguration { | |
|
||
private int threadPoolSize; | ||
|
||
private String universeDomain; | ||
private String jsonWriterEndpoint; | ||
|
||
private String host; | ||
|
||
GcpBigQueryAutoConfiguration( | ||
GcpBigQueryProperties gcpBigQueryProperties, | ||
GcpProjectIdProvider projectIdProvider, | ||
|
@@ -78,6 +83,10 @@ public class GcpBigQueryAutoConfiguration { | |
this.jsonWriterBatchSize = gcpBigQueryProperties.getJsonWriterBatchSize(); | ||
|
||
this.threadPoolSize = getThreadPoolSize(gcpBigQueryProperties.getThreadPoolSize()); | ||
|
||
this.universeDomain = gcpBigQueryProperties.getUniverseDomain(); | ||
this.jsonWriterEndpoint = gcpBigQueryProperties.getJsonWriterEndpoint(); | ||
this.host = gcpBigQueryProperties.getHost(); | ||
} | ||
|
||
/** | ||
|
@@ -97,25 +106,35 @@ private int getThreadPoolSize(int threadPoolSize) { | |
@Bean | ||
@ConditionalOnMissingBean | ||
public BigQuery bigQuery() throws IOException { | ||
BigQueryOptions bigQueryOptions = | ||
BigQueryOptions.Builder bigQueryOptionsBuilder = | ||
BigQueryOptions.newBuilder() | ||
.setProjectId(this.projectId) | ||
.setCredentials(this.credentialsProvider.getCredentials()) | ||
.setHeaderProvider(new UserAgentHeaderProvider(GcpBigQueryAutoConfiguration.class)) | ||
.build(); | ||
return bigQueryOptions.getService(); | ||
.setHeaderProvider(new UserAgentHeaderProvider(GcpBigQueryAutoConfiguration.class)); | ||
if (this.universeDomain != null) { | ||
bigQueryOptionsBuilder.setUniverseDomain(this.universeDomain); | ||
} | ||
if (this.host != null) { | ||
bigQueryOptionsBuilder.setHost(this.host); | ||
} | ||
return bigQueryOptionsBuilder.build().getService(); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
public BigQueryWriteClient bigQueryWriteClient() throws IOException { | ||
BigQueryWriteSettings bigQueryWriteSettings = | ||
BigQueryWriteSettings.Builder bigQueryWriteSettingsBuilder = | ||
BigQueryWriteSettings.newBuilder() | ||
.setCredentialsProvider(this.credentialsProvider) | ||
.setQuotaProjectId(this.projectId) | ||
.setHeaderProvider(new UserAgentHeaderProvider(GcpBigQueryAutoConfiguration.class)) | ||
.build(); | ||
return BigQueryWriteClient.create(bigQueryWriteSettings); | ||
.setHeaderProvider(new UserAgentHeaderProvider(GcpBigQueryAutoConfiguration.class)); | ||
if (this.universeDomain != null) { | ||
bigQueryWriteSettingsBuilder.setUniverseDomain(this.universeDomain); | ||
} | ||
if (this.jsonWriterEndpoint != null) { | ||
bigQueryWriteSettingsBuilder.setEndpoint(this.jsonWriterEndpoint); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right, it's only used for BigqueryWriteClient (bigquery storage). We can expose However, the concern I have with this is that it would prevent us from making endpoint/host configurable on a per-service basis. In fact, looking at the code again, I'm wondering if it was a mistake to make universe domain shared between bigquery and bigquerystorage. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we share anything else between Bigquery and Bigquerystorage client? Ideally they should be separate as they are two different services, but looks like we are treating them the same in spring-cloud-gcp. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a good question - you're right, they do seem pretty interconnected in spring-cloud-gcp.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we have two options
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As discussed offline, considering that both bigquery and bigquerystorage are wrapped as one product in spring-cloud-gcp, we will expose global endpoint and universe domain properties. The port will be omitted from the endpoint when set to the bigquery client. |
||
} | ||
return BigQueryWriteClient.create(bigQueryWriteSettingsBuilder.build()); | ||
} | ||
|
||
@Bean | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
import com.google.auth.oauth2.GoogleCredentials; | ||
import com.google.cloud.bigquery.BigQuery; | ||
import com.google.cloud.bigquery.BigQueryOptions; | ||
import com.google.cloud.bigquery.storage.v1.BigQueryWriteClient; | ||
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration; | ||
import com.google.cloud.spring.bigquery.core.BigQueryTemplate; | ||
import org.junit.jupiter.api.Test; | ||
|
@@ -60,6 +61,107 @@ void testSettingBigQueryOptions() { | |
}); | ||
} | ||
|
||
@Test | ||
void testBigQuery_universeDomain() { | ||
this.contextRunner | ||
.withPropertyValues("spring.cloud.gcp.bigquery.universe-domain=myUniverseDomain") | ||
.run( | ||
ctx -> { | ||
BigQueryOptions options = ctx.getBean(BigQuery.class).getOptions(); | ||
assertThat(options.getUniverseDomain()).isEqualTo("myUniverseDomain"); | ||
assertThat(options.getResolvedApiaryHost("bigquery")) | ||
.isEqualTo("https://bigquery.myUniverseDomain/"); | ||
}); | ||
} | ||
|
||
@Test | ||
void testBigQuery_noUniverseDomainAndHostSet_useClientDefault() { | ||
this.contextRunner.run( | ||
ctx -> { | ||
BigQueryOptions options = ctx.getBean(BigQuery.class).getOptions(); | ||
assertThat(options.getUniverseDomain()).isNull(); | ||
assertThat(options.getResolvedApiaryHost("bigquery")) | ||
.isEqualTo("https://bigquery.googleapis.com/"); | ||
}); | ||
} | ||
|
||
@Test | ||
void testBigQuery_host() { | ||
this.contextRunner | ||
.withPropertyValues("spring.cloud.gcp.bigquery.host=bigquery.example.com") | ||
.run( | ||
ctx -> { | ||
BigQueryOptions options = ctx.getBean(BigQuery.class).getOptions(); | ||
assertThat(options.getResolvedApiaryHost("bigquery")) | ||
.isEqualTo("bigquery.example.com"); | ||
}); | ||
} | ||
|
||
@Test | ||
void testBigQuery_bothHostAndUniverseDomainSet() { | ||
this.contextRunner | ||
.withPropertyValues("spring.cloud.gcp.bigquery.host=bigquery.example.com") | ||
.withPropertyValues("spring.cloud.gcp.bigquery.universe-domain=myUniverseDomain") | ||
.run( | ||
ctx -> { | ||
BigQueryOptions options = ctx.getBean(BigQuery.class).getOptions(); | ||
assertThat(options.getResolvedApiaryHost("bigquery")) | ||
.isEqualTo("bigquery.example.com"); | ||
assertThat(options.getUniverseDomain()).isEqualTo("myUniverseDomain"); | ||
}); | ||
} | ||
|
||
@Test | ||
void testBigQueryWrite_universeDomain() { | ||
this.contextRunner | ||
.withPropertyValues("spring.cloud.gcp.bigquery.universe-domain=myUniverseDomain") | ||
.run( | ||
ctx -> { | ||
BigQueryWriteClient writeClient = ctx.getBean(BigQueryWriteClient.class); | ||
assertThat(writeClient.getSettings().getUniverseDomain()) | ||
.isEqualTo("myUniverseDomain"); | ||
}); | ||
} | ||
|
||
@Test | ||
void testBigQueryWrite_endpoint() { | ||
this.contextRunner | ||
.withPropertyValues( | ||
"spring.cloud.gcp.bigquery.jsonWriterEndpoint=bigquerystorage.example.com:123") | ||
.run( | ||
ctx -> { | ||
BigQueryWriteClient client = ctx.getBean(BigQueryWriteClient.class); | ||
assertThat(client.getSettings().getEndpoint()) | ||
.isEqualTo("bigquerystorage.example.com:123"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please verify that it's intended to have getEndpoint not return the URI scheme, but getResolvedApiaryHost does return the URI scheme. LGTM There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, returning endpoint with this pattern is intended for Bigquerystorage which will otherwise throw an exception if it doesn't follow a specific convention. For example, passing in
On the other hand bigquery accepts either accepts user-provided endpoint as-is if one is provided or builds the host in the |
||
}); | ||
} | ||
|
||
@Test | ||
void testBigQueryWrite_bothUniverseDomainAndEndpointSet() { | ||
this.contextRunner | ||
.withPropertyValues("spring.cloud.gcp.bigquery.universe-domain=myUniverseDomain") | ||
.withPropertyValues( | ||
"spring.cloud.gcp.bigquery.jsonWriterEndpoint=bigquerystorage.example.com:123") | ||
.run( | ||
ctx -> { | ||
BigQueryWriteClient client = ctx.getBean(BigQueryWriteClient.class); | ||
assertThat(client.getSettings().getUniverseDomain()).isEqualTo("myUniverseDomain"); | ||
assertThat(client.getSettings().getEndpoint()) | ||
.isEqualTo("bigquerystorage.example.com:123"); | ||
}); | ||
} | ||
|
||
@Test | ||
void testBigQueryWrite_noUniverseDomainOrEndpointSet_useClientDefault() { | ||
this.contextRunner.run( | ||
ctx -> { | ||
BigQueryWriteClient client = ctx.getBean(BigQueryWriteClient.class); | ||
assertThat(client.getSettings().getUniverseDomain()).isEqualTo("googleapis.com"); | ||
assertThat(client.getSettings().getEndpoint()) | ||
.isEqualTo("bigquerystorage.googleapis.com:443"); | ||
}); | ||
} | ||
|
||
/** Spring Boot config for tests. */ | ||
@AutoConfigurationPackage | ||
static class TestConfiguration { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling out the addition of this property since this is a deviation from our original design of exposing universe domain and endpoint. Apiary libraries such as Bigquery and Storage only allow for customizing
host
(which is essentially endpoint without the port) instead ofendpoint
so we are doing the same in the Spring Cloud GCP layer. For context: googleapis/sdk-platform-java#2329@burkedavison @blakeli0