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 properties to customize universe-domain and host in Storage #3287

Merged
merged 20 commits into from
Oct 14, 2024

Conversation

mpeddada1
Copy link
Contributor

@mpeddada1 mpeddada1 commented Oct 4, 2024

Notable Changes

  • Introduced spring.cloud.gcp.storage.universe-domain property to customize universe domain in StorageOptions, if provided.
  • Introduced spring.cloud.gcp.storage.host property to customize the host in StorageOptions. Note that it the host doesn't follow the ``https://${service}.${domain}/` format, we run into the following error:
com.google.cloud.storage.StorageException: java.lang.IllegalArgumentException: java.net.MalformedURLException: no protocol: storage.example.com/storage/v1/b?project=PROJECT_ID&projection=full
	at com.google.cloud.storage.StorageException.getStorageException(StorageException.java:101) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.google.cloud.storage.StorageException.coalesce(StorageException.java:124) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.google.cloud.storage.Retrying.run(Retrying.java:68) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.google.cloud.storage.StorageImpl.listBuckets(StorageImpl.java:453) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.google.cloud.storage.StorageImpl.list(StorageImpl.java:440) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.example.StorageUniverseDomain.listBuckets(StorageUniverseDomain.java:32) ~[classes/:na]
	at com.example.StorageUniverseDomain.lambda$commandLineRunner$0(StorageUniverseDomain.java:27) ~[classes/:na]
	at org.springframework.boot.SpringApplication.lambda$callRunner$5(SpringApplication.java:790) ~[spring-boot-3.3.4.jar:3.3.4]
	at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:83) ~[spring-core-6.1.13.jar:6.1.13]
	at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[spring-core-6.1.13.jar:6.1.13]
	at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:88) ~[spring-core-6.1.13.jar:6.1.13]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-3.3.4.jar:3.3.4]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:789) ~[spring-boot-3.3.4.jar:3.3.4]
	at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:774) ~[spring-boot-3.3.4.jar:3.3.4]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:na]
	at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:774) ~[spring-boot-3.3.4.jar:3.3.4]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:342) ~[spring-boot-3.3.4.jar:3.3.4]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.4.jar:3.3.4]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.4.jar:3.3.4]
	at com.example.StorageUniverseDomain.main(StorageUniverseDomain.java:20) ~[classes/:na]
Caused by: java.lang.IllegalArgumentException: java.net.MalformedURLException: no protocol: storage.example.com/storage/v1/b?project=PROJECT_ID&projection=full
	at com.google.api.client.http.GenericUrl.parseURL(GenericUrl.java:679) ~[google-http-client-1.45.0.jar:1.45.0]
	at com.google.api.client.http.GenericUrl.<init>(GenericUrl.java:125) ~[google-http-client-1.45.0.jar:1.45.0]
	at com.google.api.client.http.GenericUrl.<init>(GenericUrl.java:108) ~[google-http-client-1.45.0.jar:1.45.0]
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequestUrl(AbstractGoogleClientRequest.java:424) ~[google-api-client-2.7.0.jar:2.7.0]
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequest(AbstractGoogleClientRequest.java:455) ~[google-api-client-2.7.0.jar:2.7.0]
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:565) ~[google-api-client-2.7.0.jar:2.7.0]
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:506) ~[google-api-client-2.7.0.jar:2.7.0]
	at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:616) ~[google-api-client-2.7.0.jar:2.7.0]
	at com.google.cloud.storage.spi.v1.HttpStorageRpc.list(HttpStorageRpc.java:432) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.google.cloud.storage.StorageImpl.lambda$listBuckets$6(StorageImpl.java:456) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	at com.google.api.gax.retrying.DirectRetryingExecutor.submit(DirectRetryingExecutor.java:102) ~[gax-2.54.1.jar:2.54.1]
	at com.google.cloud.RetryHelper.run(RetryHelper.java:76) ~[google-cloud-core-2.44.1.jar:2.44.1]
	at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:50) ~[google-cloud-core-2.44.1.jar:2.44.1]
	at com.google.cloud.storage.Retrying.run(Retrying.java:65) ~[google-cloud-storage-2.43.1.jar:2.43.1]
	... 24 common frames omitted
Caused by: java.net.MalformedURLException: no protocol: storage.example.com/storage/v1/b?project=PROJECT_ID&projection=full
	at java.base/java.net.URL.<init>(URL.java:772) ~[na:na]
	at java.base/java.net.URL.<init>(URL.java:654) ~[na:na]
	at java.base/java.net.URL.<init>(URL.java:590) ~[na:na]
	at com.google.api.client.http.GenericUrl.parseURL(GenericUrl.java:677) ~[google-http-client-1.45.0.jar:1.45.0]
	... 37 common frames omitted


  • Since the MalformedURLException doesn't provide sufficient messaging to help troubleshoot host formatting issues, added validation to verify that the host starts with https:// or otherwise throws an IllegalArgumentException.
  • Added documentation for the properties and expected format.
    Integration testing has been manually recorded in a separate test plan document.
  • Included some minor refactoring to the kms and bigquery properties files to include more consistent documentation of universe domain and endpoint.

@mpeddada1 mpeddada1 changed the title feat: add properties to customize universe-domain and endpoint in Storage feat: add properties to customize universe-domain and host in Storage Oct 4, 2024
@mpeddada1 mpeddada1 marked this pull request as ready for review October 4, 2024 19:41
@mpeddada1 mpeddada1 requested a review from a team as a code owner October 4, 2024 19:41
@burkedavison
Copy link
Member

LGTM with minor comment adjustments

mpeddada1 and others added 7 commits October 9, 2024 10:20
Co-authored-by: Burke Davison <[email protected]>
Co-authored-by: Burke Davison <[email protected]>
Co-authored-by: Burke Davison <[email protected]>
Co-authored-by: Burke Davison <[email protected]>
Co-authored-by: Burke Davison <[email protected]>
Co-authored-by: Burke Davison <[email protected]>
+ host
+ ". Please verify that the specified host follows the 'https://${service}.${universeDomain}' format");
}
return url.getProtocol() + "://" + url.getHost() + "/";
Copy link
Contributor

Choose a reason for hiding this comment

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

Did we get this format from Storage client library code?

Copy link
Contributor

@blakeli0 blakeli0 Oct 9, 2024

Choose a reason for hiding this comment

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

I know we have it in java-core, is it where get it from? But we don't have the ending slash in java-core

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah thanks for the question. From doing a check with breakpoints in a spring storage app, Storage calls getResolvedApiaryHost() when setting the host at https://github.com/googleapis/java-storage/blob/7d47307d10e285f92b3e2125c4993b6a292001bf/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageOptions.java#L267.

getResolvedApiaryHost() returns a host with a / so applied the same behavior here.

Copy link
Contributor

@blakeli0 blakeli0 Oct 9, 2024

Choose a reason for hiding this comment

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

Thanks! Do you mind adding some comment regarding where we get the format from? I think a link to the implementation of getResolvedApiaryHost() in java-core should be good enough.
In addition, anywhere we mention the format of host, we should always have an ending slash, which I see that it is missing in the Javadoc of universeDomain.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup! Added a javadoc and also modified other locations where we mention host follow a consistent style.

@@ -119,6 +119,8 @@ The Spring Boot Starter for Google Cloud Storage provides the following configur
Base64-encoded contents of OAuth2 account private key for authenticating with the Google Cloud Storage API, if different from the ones in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No |
| `spring.cloud.gcp.storage.credentials.scopes` |
https://developers.google.com/identity/protocols/googlescopes[OAuth2 scope] for Spring Framework on Google Cloud Storage credentials | No | https://www.googleapis.com/auth/devstorage.read_write
| `spring.cloud.gcp.storage.universe-domain` | Universe domain of the Storage service. The universe domain is a part of the host that is formatted as `https://${service}.${universeDomain}` | No | Relies on client library’s default universe domain which is `googleapis.com`
| `spring.cloud.gcp.storage.host` | Host of the Storage service which expects `https://${service}.${universeDomain}` as the format. | No | Relies on client library’s default host which is `https://storage.googleapis.com`
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have any documentation in Storage to describe the relationship between host and universeDomain? If yes, maybe we can link it here so customers know which one to configure? I know we don't have it yet in pure GAPICs(which is a gap).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't have any storage-specific documentation on universe domain and host but looks like this is the closest page there is to providing that info? https://cloud.google.com/java/docs/reference/google-cloud-core/latest/com.google.cloud.ServiceOptions.Builder#com_google_cloud_ServiceOptions_Builder_setUniverseDomain_java_lang_String_

*/
private String universeDomain;

/** Host of the Storage client that is formatted as `https://${service}.${universeDomain}/`. */
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that we have an ending slash here but not in the format example above for universeDomain, which one we should go for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, modified the documentation to be consistent.

Copy link

sonarcloud bot commented Oct 9, 2024

@mpeddada1 mpeddada1 merged commit f5879d9 into main Oct 14, 2024
68 of 76 checks passed
@mpeddada1 mpeddada1 deleted the storage-universeDomain branch October 14, 2024 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants