Skip to content

Commit

Permalink
fix: Return resolved endpoint from StubSettings' Builder (#2715)
Browse files Browse the repository at this point in the history
  • Loading branch information
lqiu96 authored May 2, 2024
1 parent 8f21be6 commit 32c9995
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,8 @@ private GrpcCallContext(
this.retryableCodes = retryableCodes == null ? null : ImmutableSet.copyOf(retryableCodes);
// Attempt to create an empty, non-functioning EndpointContext by default. The client will have
// a valid EndpointContext with user configurations after the client has been initialized.
try {
this.endpointContext =
endpointContext == null ? EndpointContext.newBuilder().build() : endpointContext;
} catch (IOException ex) {
throw new RuntimeException(ex);
}
this.endpointContext =
endpointContext == null ? EndpointContext.getDefaultInstance() : endpointContext;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,8 @@ private HttpJsonCallContext(
defaultRetryableCodes == null ? null : ImmutableSet.copyOf(defaultRetryableCodes);
// Attempt to create an empty, non-functioning EndpointContext by default. The client will have
// a valid EndpointContext with user configurations after the client has been initialized.
try {
this.endpointContext =
endpointContext == null ? EndpointContext.newBuilder().build() : endpointContext;
} catch (IOException ex) {
throw new RuntimeException(ex);
}
this.endpointContext =
endpointContext == null ? EndpointContext.getDefaultInstance() : endpointContext;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,24 +126,20 @@ public abstract class ClientContext {

/** Create a new ClientContext with default values */
public static Builder newBuilder() {
try {
return new AutoValue_ClientContext.Builder()
.setBackgroundResources(Collections.<BackgroundResource>emptyList())
.setExecutor(Executors.newScheduledThreadPool(0))
.setHeaders(Collections.<String, String>emptyMap())
.setInternalHeaders(Collections.<String, String>emptyMap())
.setClock(NanoClock.getDefaultClock())
.setStreamWatchdog(null)
.setStreamWatchdogCheckInterval(Duration.ZERO)
.setTracerFactory(BaseApiTracerFactory.getInstance())
.setQuotaProjectId(null)
.setGdchApiAudience(null)
// Attempt to create an empty, non-functioning EndpointContext by default. This is
// not exposed to the user via getters/setters.
.setEndpointContext(EndpointContext.newBuilder().build());
} catch (IOException e) {
throw new RuntimeException(e);
}
return new AutoValue_ClientContext.Builder()
.setBackgroundResources(Collections.<BackgroundResource>emptyList())
.setExecutor(Executors.newScheduledThreadPool(0))
.setHeaders(Collections.<String, String>emptyMap())
.setInternalHeaders(Collections.<String, String>emptyMap())
.setClock(NanoClock.getDefaultClock())
.setStreamWatchdog(null)
.setStreamWatchdogCheckInterval(Duration.ZERO)
.setTracerFactory(BaseApiTracerFactory.getInstance())
.setQuotaProjectId(null)
.setGdchApiAudience(null)
// Attempt to create an empty, non-functioning EndpointContext by default. This is
// not exposed to the user via getters/setters.
.setEndpointContext(EndpointContext.getDefaultInstance());
}

public abstract Builder toBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,28 @@
@InternalApi
@AutoValue
public abstract class EndpointContext {

private static final EndpointContext INSTANCE;

// static block initialization for exception handling
static {
try {
INSTANCE = EndpointContext.newBuilder().setServiceName("").build();
} catch (IOException e) {
throw new RuntimeException("Unable to create a default empty EndpointContext", e);
}
}

public static final String GOOGLE_CLOUD_UNIVERSE_DOMAIN = "GOOGLE_CLOUD_UNIVERSE_DOMAIN";
public static final String INVALID_UNIVERSE_DOMAIN_ERROR_TEMPLATE =
"The configured universe domain (%s) does not match the universe domain found in the credentials (%s). If you haven't configured the universe domain explicitly, `googleapis.com` is the default.";
public static final String UNABLE_TO_RETRIEVE_CREDENTIALS_ERROR_MESSAGE =
"Unable to retrieve the Universe Domain from the Credentials.";

public static EndpointContext getDefaultInstance() {
return INSTANCE;
}

/**
* ServiceName is host URI for Google Cloud Services. It follows the format of
* `{ServiceName}.googleapis.com`. For example, speech.googleapis.com would have a ServiceName of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ public abstract static class Builder<
@Nonnull private ApiTracerFactory tracerFactory;
private boolean deprecatedExecutorProviderSet;
private String universeDomain;
private final EndpointContext endpointContext;

/**
* Indicate when creating transport whether it is allowed to use mTLS endpoint instead of the
Expand Down Expand Up @@ -300,6 +301,9 @@ protected Builder(StubSettings settings) {
this.switchToMtlsEndpointAllowed =
settings.getEndpointContext().switchToMtlsEndpointAllowed();
this.universeDomain = settings.getEndpointContext().universeDomain();
// Store the EndpointContext that was already created. This is used to return the state
// of the EndpointContext prior to any new modifications
this.endpointContext = settings.getEndpointContext();
}

/** Get Quota Project ID from Client Context * */
Expand Down Expand Up @@ -327,16 +331,22 @@ protected Builder(ClientContext clientContext) {
this.headerProvider = new NoHeaderProvider();
this.internalHeaderProvider = new NoHeaderProvider();
this.clock = NanoClock.getDefaultClock();
this.clientSettingsEndpoint = null;
this.transportChannelProviderEndpoint = null;
this.mtlsEndpoint = null;
this.quotaProjectId = null;
this.streamWatchdogProvider = InstantiatingWatchdogProvider.create();
this.streamWatchdogCheckInterval = Duration.ofSeconds(10);
this.tracerFactory = BaseApiTracerFactory.getInstance();
this.deprecatedExecutorProviderSet = false;
this.gdchApiAudience = null;

this.clientSettingsEndpoint = null;
this.transportChannelProviderEndpoint = null;
this.mtlsEndpoint = null;
this.switchToMtlsEndpointAllowed = false;
this.universeDomain = null;
// Attempt to create an empty, non-functioning EndpointContext by default. The client will
// have
// a valid EndpointContext with user configurations after the client has been initialized.
this.endpointContext = EndpointContext.getDefaultInstance();
} else {
ExecutorProvider fixedExecutorProvider =
FixedExecutorProvider.create(clientContext.getExecutor());
Expand Down Expand Up @@ -365,6 +375,9 @@ protected Builder(ClientContext clientContext) {
this.switchToMtlsEndpointAllowed =
clientContext.getEndpointContext().switchToMtlsEndpointAllowed();
this.universeDomain = clientContext.getEndpointContext().universeDomain();
// Store the EndpointContext that was already created. This is used to return the state
// of the EndpointContext prior to any new modifications
this.endpointContext = clientContext.getEndpointContext();
}
}

Expand Down Expand Up @@ -584,8 +597,19 @@ public ApiClock getClock() {
return clock;
}

/**
* @return the resolved endpoint when the Builder was created. If invoked after
* `StubSettings.newBuilder()` is called, it will return the clientSettingsEndpoint value.
* If other parameters are then set in the builder, the resolved endpoint is not
* automatically updated. The resolved endpoint will only be recomputed when the
* StubSettings is built again.
*/
public String getEndpoint() {
return clientSettingsEndpoint;
// For the `StubSettings.newBuilder()` case
if (endpointContext.equals(EndpointContext.getDefaultInstance())) {
return clientSettingsEndpoint;
}
return endpointContext.resolvedEndpoint();
}

public String getMtlsEndpoint() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -88,12 +87,8 @@ private FakeCallContext(
this.tracer = tracer;
this.retrySettings = retrySettings;
this.retryableCodes = retryableCodes == null ? null : ImmutableSet.copyOf(retryableCodes);
try {
this.endpointContext =
endpointContext == null ? EndpointContext.newBuilder().build() : endpointContext;
} catch (IOException e) {
throw new RuntimeException(e);
}
this.endpointContext =
endpointContext == null ? EndpointContext.getDefaultInstance() : endpointContext;
}

public static FakeCallContext createDefault() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,17 +416,33 @@ public void universeDomainValidation_noCredentials_userSetUniverseDomain() throw
@Test
public void endpointResolution_defaultViaBuilder() {
EchoSettings.Builder echoSettingsBuilder = EchoSettings.newBuilder();
// The getter in the builder returns the user set value. No configuration
// means the getter will return null
// `StubSettings.newBuilder()` will return the clientSettingsEndpoint
Truth.assertThat(echoSettingsBuilder.getEndpoint()).isEqualTo(null);
}

// User configuration in Builder
@Test
public void endpointResolution_userConfigurationViaBuilder() {
String customEndpoint = "test.com:123";
EchoSettings.Builder echoSettingsBuilder =
EchoSettings.newBuilder().setEndpoint(customEndpoint);
Truth.assertThat(echoSettingsBuilder.getEndpoint()).isEqualTo(customEndpoint);
EchoSettings.newBuilder().setEndpoint("test.com:123");
// `StubSettings.newBuilder()` will return the clientSettingsEndpoint
Truth.assertThat(echoSettingsBuilder.getEndpoint()).isEqualTo("test.com:123");
}

@Test
public void endpointResolution_builderBuilderBackToBuilder() throws IOException {
String customEndpoint = "test.com:123";
EchoStubSettings.Builder echoStubSettingsBuilder =
EchoStubSettings.newBuilder().setEndpoint(customEndpoint);
// `StubSettings.newBuilder()` will return the clientSettingsEndpoint
Truth.assertThat(echoStubSettingsBuilder.getEndpoint()).isEqualTo(customEndpoint);

// EndpointContext is recomputed when the Builder is re-built
EchoStubSettings echoStubSettings = echoStubSettingsBuilder.build();
Truth.assertThat(echoStubSettings.getEndpoint()).isEqualTo(customEndpoint);

// Calling toBuilder on StubSettings keeps the configurations the same
echoStubSettingsBuilder = echoStubSettings.toBuilder();
Truth.assertThat(echoStubSettingsBuilder.getEndpoint()).isEqualTo(customEndpoint);
}
}

0 comments on commit 32c9995

Please sign in to comment.