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: Full Endpoint Resolution from EndpointContext #2313

Merged
merged 7 commits into from Jan 2, 2024
Merged

Conversation

lqiu96
Copy link
Contributor

@lqiu96 lqiu96 commented Dec 19, 2023

Features:

  • Introduces the concept of Universe Domain
  • Endpoint + Universe Domain resolution is determined solely by the EndpointContext
  • Support and compatibility for GDC-H, DirectPath, and mTLS

@product-auto-label product-auto-label bot added the size: l Pull request size is large. label Dec 19, 2023
@lqiu96 lqiu96 added the owlbot:run Add this label to trigger the Owlbot post processor. label Dec 19, 2023
@gcf-owl-bot gcf-owl-bot bot removed the owlbot:run Add this label to trigger the Owlbot post processor. label Dec 19, 2023
Comment on lines +184 to +185
} else if (!Strings.isNullOrEmpty(endpoint)) {
audienceString = endpoint;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Confirm this behavior is correct

Copy link
Contributor Author

@lqiu96 lqiu96 Dec 20, 2023

Choose a reason for hiding this comment

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

The GDC-H audienceString's endpoint should match with endpoint set inside the TransportChannelProvider.

The logic is that for a GDC-H flow, the resolved endpoint will be either the clientsettings endpoint or transportchannel endpoint if set. This matches the behavior below as either the clientSettings or transportchannel's endpoint.

ClientSettings will only be set to the Transportchannel if it doesn't have an endpoint already set by the user. EndpointContext's resolvedEndpoint already takes this into consideration.

Copy link
Contributor Author

@lqiu96 lqiu96 Dec 20, 2023

Choose a reason for hiding this comment

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

The else block is kept as the custom endpoint could be set as "" (empty string). URI.create("") does not throw an exception, so it is caught in this else block.

@lqiu96 lqiu96 requested a review from blakeli0 December 19, 2023 22:48
@lqiu96 lqiu96 force-pushed the endpoint-resolution branch 2 times, most recently from 3bc8392 to bdbaab1 Compare December 20, 2023 21:02
@lqiu96 lqiu96 marked this pull request as ready for review December 20, 2023 21:29
@lqiu96 lqiu96 requested a review from a team as a code owner December 20, 2023 21:29
@lqiu96 lqiu96 added the owlbot:run Add this label to trigger the Owlbot post processor. label Dec 20, 2023
@gcf-owl-bot gcf-owl-bot bot removed the owlbot:run Add this label to trigger the Owlbot post processor. label Dec 20, 2023
throw new IllegalArgumentException("The universe domain value cannot be empty.");
}
// Universe Domain defaults to the GDU if it's not provided by the user.
resolvedUniverseDomain = universeDomain() != null ? universeDomain() : GOOGLE_DEFAULT_UNIVERSE;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we default the universe domain to GDU instead of introducing a new field resolvedUniverseDomain? In addition, can we move the universe domain resolution logic to build()? The validation above can be done there as well. I know this method is already being called from build(), but determining universe domain feels like a separate step that should be done before determining endpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good, will do.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we default the universe domain to GDU instead of introducing a new field resolvedUniverseDomain?

Do we still need resolvedUniverseDomain?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I planned to remove it and use GDU by default, but I think there is a small edge case. Found it when running the IT GDCH tests, specifically regarding:

settings = settings.toBuilder().setGdchApiAudience(testAudience).build();
context = ClientContext.create(settings);
stubSettings = EchoStubSettings.newBuilder(context).build();
client = EchoClient.create(stubSettings.createStub());
.

L190's ClientContext.create(...) creates an EndpointContext. Nothing is passed in via the universeDomain getter as it's a GDC-H flow, but the universe domain would be set to GDU by default.

L192's createStub() will create the Stub and it takes the params from the ClientContext (which has the GDU as the universe domain) and it will fail the GDC-H logic block.

I'm not sure the way that the IT GDC-H tests are set is makes sense (or if I'm missing something), specifically regarding explicitly creating the ClientSettings -> ClientContext -> StubSettings steps. But I think it shows that doing this is possible by the user.

I learned towards keeping the resolvedUniverseDomain so that the user can differentiate between what the user configuration and what the resolved universe domain is (null, GDU, user configured). This would possibly be done in a future enhancement as a getter.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I learned towards keeping the resolvedUniverseDomain so that the user can differentiate between what the user configuration and what the resolved universe domain is (null, GDU, user configured)

Makes sense. Please see my new comments regarding resolvedUniverseDomain, I think it's better to make it not nullable, but maybe there is a edge case preventing us from doing so.

@@ -104,6 +104,9 @@ public abstract class ClientContext {
@Nullable
abstract String getServiceName();

@Nullable
public abstract String getUniverseDomain();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need to expose a getter for universe domain? I guess it is for StubSettings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is for the for logic that connects ClientContext <-> StubSettings. I believe it was added a while back for reasons and this getter is (ideally) only for StubSettings usage.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, for every new ClientSettings, it seems that we have to duplicate it in StubSettings as well.

@lqiu96 lqiu96 requested a review from blakeli0 December 28, 2023 16:14
private String determineUniverseDomain() {
// Do not set the universe domain for GDC-H
if (usingGDCH()) {
return null;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we return GDU here instead of null? And make resolvedUniverseDomain not nullable? I see that resolvedUniverseDomain is used multiple places later, it is probably good now but may easily introduce null pointer exceptions later.

Copy link
Contributor Author

@lqiu96 lqiu96 Dec 29, 2023

Choose a reason for hiding this comment

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

The resolvedUniverseDomain is what is stored in the ClientContext and StubSettings (not the user configured universe domain). Following the GDC-H case above, it's possible to manually construct the StubSettings and ClientContext and each would construct the EndpointContext. If we set the resolvedUniverseDomain to the GDU by default, then it would fail every case as the Universe Domain can never be set for GDC-H (must be null).

--
Edit: I updated the logic so that it is non-null

throw new IllegalArgumentException(
"Universe domain configuration is incompatible with GDC-H");
} else if (customEndpoint == null) {
return buildEndpointTemplate(serviceName(), GOOGLE_DEFAULT_UNIVERSE);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we use resolvedUniverseDomain if we default it to GDU?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. Thanks!

throw new IllegalArgumentException("The universe domain value cannot be empty.");
}
// Universe Domain defaults to the GDU if it's not provided by the user.
resolvedUniverseDomain = universeDomain() != null ? universeDomain() : GOOGLE_DEFAULT_UNIVERSE;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I learned towards keeping the resolvedUniverseDomain so that the user can differentiate between what the user configuration and what the resolved universe domain is (null, GDU, user configured)

Makes sense. Please see my new comments regarding resolvedUniverseDomain, I think it's better to make it not nullable, but maybe there is a edge case preventing us from doing so.

@@ -104,6 +104,9 @@ public abstract class ClientContext {
@Nullable
abstract String getServiceName();

@Nullable
public abstract String getUniverseDomain();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, for every new ClientSettings, it seems that we have to duplicate it in StubSettings as well.

return new AutoValue_EndpointContext.Builder().setSwitchToMtlsEndpointAllowed(false);
}
@Nullable
public abstract String resolvedUniverseDomain();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we expect resolvedUniverseDomain to be used by anything outside of this class? If not, I think we can make the this method and the setter in the builder package private (I don't think we can make it completed private though due to AutoValue limitations).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually on second thought, I think you're right. I've made it package private. I originally used it as the value I set in the ClientContext, but I can just follow what we are doing with endpoint and pass the user set values for that. This way the resolvedUniverseDomain can be non-null (default to GDU).

Copy link
Collaborator

@blakeli0 blakeli0 left a comment

Choose a reason for hiding this comment

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

LGTM. Please add Javadocs before merging.

@@ -48,6 +51,9 @@ public abstract class EndpointContext {
@Nullable
public abstract String serviceName();

@Nullable
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please add some Javadocs to the getter here and setter below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Thanks

Copy link

sonarcloud bot commented Jan 2, 2024

Quality Gate Failed Quality Gate failed for 'gapic-generator-java-root'

Failed conditions

14.3% Coverage on New Code (required ≥ 80%)

See analysis details on SonarCloud

Copy link

sonarcloud bot commented Jan 2, 2024

Quality Gate Failed Quality Gate failed for 'java_showcase_integration_tests'

Failed conditions

63.8% Coverage on New Code (required ≥ 80%)

See analysis details on SonarCloud

@lqiu96 lqiu96 merged commit f499ced into main Jan 2, 2024
36 of 38 checks passed
@lqiu96 lqiu96 deleted the endpoint-resolution branch January 2, 2024 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: l Pull request size is large.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants