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: Parse Host Service Name #2300

Merged
merged 14 commits into from Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -57,6 +57,9 @@ public class SettingsCommentComposer {

public static final CommentStatement DEFAULT_EXECUTOR_PROVIDER_BUILDER_METHOD_COMMENT =
toSimpleComment("Returns a builder for the default ExecutorProvider for this service.");

public static final CommentStatement DEFAULT_SERVICE_NAME_METHOD_COMMENT =
toSimpleComment("Returns the default service name.");
public static final CommentStatement DEFAULT_SERVICE_ENDPOINT_METHOD_COMMENT =
toSimpleComment("Returns the default service endpoint.");
public static final CommentStatement DEFAULT_SERVICE_MTLS_ENDPOINT_METHOD_COMMENT =
Expand Down
Expand Up @@ -97,6 +97,7 @@
import com.google.api.generator.gapic.model.Service;
import com.google.api.generator.gapic.utils.JavaStyle;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -1137,9 +1138,27 @@ private MethodDefinition createCreateStubMethod(Service service, TypeStore typeS
private List<MethodDefinition> createDefaultHelperAndGetterMethods(
Service service, TypeStore typeStore) {
List<MethodDefinition> javaMethods = new ArrayList<>();
TypeNode returnType;

// Create the getServiceName method.
if (!Strings.isNullOrEmpty(service.hostServiceName())) {
returnType = TypeNode.STRING;
javaMethods.add(
MethodDefinition.builder()
.setHeaderCommentStatements(
SettingsCommentComposer.DEFAULT_SERVICE_NAME_METHOD_COMMENT)
.setIsOverride(true)
.setScope(ScopeNode.PUBLIC)
.setIsStatic(false)
.setReturnType(returnType)
.setName("getServiceName")
.setReturnExpr(
ValueExpr.withValue(StringObjectValue.withValue(service.hostServiceName())))
.build());
}

// Create the defaultExecutorProviderBuilder method.
TypeNode returnType =
returnType =
TypeNode.withReference(
ConcreteReference.withClazz(InstantiatingExecutorProvider.Builder.class));
javaMethods.add(
Expand Down
Expand Up @@ -52,6 +52,12 @@ public boolean hasDescription() {
return !Strings.isNullOrEmpty(description());
}

public String hostServiceName() {
// Host Service Name is guaranteed to exist and be non-null and non-empty
// Parser will fail if the default host is not supplied
return parseHostServiceName(defaultHost());
}

public String apiShortName() {
if (!Strings.isNullOrEmpty(defaultHost())) {
return parseApiShortName(defaultHost());
Expand Down Expand Up @@ -184,6 +190,17 @@ private static String parseApiVersion(String protoPackage) {
return apiVersion;
}

// Parse the service name from the default host configured in the protos
// or service yaml file. For Google Cloud Services, the default host value
// is expected to contain `.googleapis.com`. Exceptions may exist (i.e. localhost),
// in which case we will return an empty string.
private static String parseHostServiceName(String defaultHost) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I know we are already testing this method indirectly through golden tests. Since this is in Service not composers, and we can easily mock the input, it would be great if we can have unit tests testing it directly as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added some tests for parsing, thanks!

if (defaultHost.contains(".googleapis.com")) {
return Iterables.getFirst(Splitter.on(".").split(defaultHost), defaultHost);
}
return "";
}

// Parse defaultHost for apiShortName for the RegionTag. Need to account for regional default
// endpoints like
// "us-east1-pubsub.googleapis.com".
Expand Down
Expand Up @@ -422,6 +422,12 @@ public class LoggingServiceV2StubSettings extends StubSettings<LoggingServiceV2S
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "logging";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -431,6 +431,12 @@ public class PublisherStubSettings extends StubSettings<PublisherStubSettings> {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "pubsub";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -177,4 +177,17 @@ public void hasAnyEnabledMethodsForTransport_shouldThrowExceptionForGRPCRESTTran
Service testService = testServiceBuilder.build();
testService.hasAnyEnabledMethodsForTransport(Transport.GRPC_REST);
}

@Test
public void hostServiceName_googleApisDefaultHost() {
Service service = testServiceBuilder.setDefaultHost("test.googleapis.com").build();
assertThat(service.hostServiceName()).isEqualTo("test");
}

@Test
public void hostServiceName_nonGoogleApisDefaultHost() {
// Default Host is localhost:7469
Service service = testServiceBuilder.build();
assertThat(service.hostServiceName()).isEqualTo("");
}
}
Expand Up @@ -100,6 +100,10 @@ public abstract class ClientContext {
@Nonnull
public abstract Duration getStreamWatchdogCheckInterval();

// Package-Private scope for internal use only. Shared between StubSettings and ClientContext
@Nullable
abstract String getServiceName();

@Nullable
public abstract String getEndpoint();

Expand Down Expand Up @@ -202,6 +206,7 @@ public static ClientContext create(StubSettings settings) throws IOException {
}
EndpointContext endpointContext =
EndpointContext.newBuilder()
.setServiceName(settings.getServiceName())
.setClientSettingsEndpoint(settings.getEndpoint())
.setTransportChannelProviderEndpoint(
settings.getTransportChannelProvider().getEndpoint())
Expand Down Expand Up @@ -258,6 +263,7 @@ public static ClientContext create(StubSettings settings) throws IOException {
.setInternalHeaders(ImmutableMap.copyOf(settings.getInternalHeaderProvider().getHeaders()))
.setClock(clock)
.setDefaultCallContext(defaultCallContext)
.setServiceName(settings.getServiceName())
.setEndpoint(settings.getEndpoint())
.setQuotaProjectId(settings.getQuotaProjectId())
.setStreamWatchdog(watchdog)
Expand Down Expand Up @@ -323,6 +329,9 @@ public abstract static class Builder {

public abstract Builder setDefaultCallContext(ApiCallContext defaultCallContext);

// Package-Private scope for internal use only. Shared between StubSettings and ClientContext
abstract Builder setServiceName(String serviceName);

public abstract Builder setEndpoint(String endpoint);

public abstract Builder setQuotaProjectId(String QuotaProjectId);
Expand Down
Expand Up @@ -40,6 +40,14 @@
@InternalApi
@AutoValue
public abstract class EndpointContext {
/**
* 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
* speech and cloudasset.googleapis.com would have a ServiceName of cloudasset.
*/
@Nullable
public abstract String serviceName();

/**
* ClientSettingsEndpoint is the endpoint value set via the ClientSettings/StubSettings classes.
*/
Expand Down Expand Up @@ -117,6 +125,13 @@ public String getResolvedEndpoint() {

@AutoValue.Builder
public abstract static class Builder {
/**
* 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 speech and cloudasset.googleapis.com would have a ServiceName of cloudasset.
*/
public abstract Builder setServiceName(String serviceName);

/**
* ClientSettingsEndpoint is the endpoint value set via the ClientSettings/StubSettings classes.
*/
Expand Down
Expand Up @@ -32,6 +32,7 @@
import com.google.api.core.ApiClock;
import com.google.api.core.ApiFunction;
import com.google.api.core.BetaApi;
import com.google.api.core.InternalApi;
import com.google.api.core.NanoClock;
import com.google.api.gax.core.CredentialsProvider;
import com.google.api.gax.core.ExecutorProvider;
Expand Down Expand Up @@ -70,6 +71,7 @@ public abstract class StubSettings<SettingsT extends StubSettings<SettingsT>> {
private final HeaderProvider internalHeaderProvider;
private final TransportChannelProvider transportChannelProvider;
private final ApiClock clock;
private final String serviceName;
private final String endpoint;
private final String mtlsEndpoint;
private final String quotaProjectId;
Expand All @@ -96,6 +98,7 @@ protected StubSettings(Builder builder) {
this.headerProvider = builder.headerProvider;
this.internalHeaderProvider = builder.internalHeaderProvider;
this.clock = builder.clock;
this.serviceName = builder.serviceName;
this.endpoint = builder.endpoint;
this.mtlsEndpoint = builder.mtlsEndpoint;
this.switchToMtlsEndpointAllowed = builder.switchToMtlsEndpointAllowed;
Expand Down Expand Up @@ -137,6 +140,13 @@ public final ApiClock getClock() {
return clock;
}

// Intended for Internal Use and Overriden by generated ServiceStubSettings classes.
// Meant to be shared between StubSettings and ClientContext.
@InternalApi
public String getServiceName() {
return "";
}
Comment on lines +143 to +148
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ClientContext.create() takes in the root StubSettings (not the subclasses). Create a default method that generated subclasses can override.


public final String getEndpoint() {
return endpoint;
}
Expand Down Expand Up @@ -211,6 +221,7 @@ public abstract static class Builder<
private HeaderProvider internalHeaderProvider;
private TransportChannelProvider transportChannelProvider;
private ApiClock clock;
private String serviceName;
private String endpoint;
private String mtlsEndpoint;
private String quotaProjectId;
Expand All @@ -236,6 +247,7 @@ protected Builder(StubSettings settings) {
this.headerProvider = settings.headerProvider;
this.internalHeaderProvider = settings.internalHeaderProvider;
this.clock = settings.clock;
this.serviceName = settings.serviceName;
this.endpoint = settings.endpoint;
this.mtlsEndpoint = settings.mtlsEndpoint;
this.switchToMtlsEndpointAllowed = settings.switchToMtlsEndpointAllowed;
Expand Down Expand Up @@ -272,6 +284,7 @@ protected Builder(ClientContext clientContext) {
this.headerProvider = new NoHeaderProvider();
this.internalHeaderProvider = new NoHeaderProvider();
this.clock = NanoClock.getDefaultClock();
this.serviceName = null;
this.endpoint = null;
this.mtlsEndpoint = null;
this.quotaProjectId = null;
Expand All @@ -292,6 +305,7 @@ protected Builder(ClientContext clientContext) {
this.internalHeaderProvider =
FixedHeaderProvider.create(clientContext.getInternalHeaders());
this.clock = clientContext.getClock();
this.serviceName = clientContext.getServiceName();
this.endpoint = clientContext.getEndpoint();
if (this.endpoint != null) {
this.mtlsEndpoint = this.endpoint.replace("googleapis.com", "mtls.googleapis.com");
Expand Down
Expand Up @@ -182,6 +182,12 @@ public ConnectionServiceStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "apigeeconnect";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -102,6 +102,12 @@ public TetherStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "apigeeconnect";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -571,6 +571,12 @@ public AssetServiceStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "cloudasset";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -166,6 +166,12 @@ public BigtableStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "bigtable";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -289,6 +289,12 @@ public AddressesStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "compute";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -114,6 +114,12 @@ public RegionOperationsStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "compute";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -140,6 +140,12 @@ public IamCredentialsStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "iamcredentials";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -119,6 +119,12 @@ public IAMPolicyStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "iam-meta-api";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -639,6 +639,12 @@ public KeyManagementServiceStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "cloudkms";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down
Expand Up @@ -306,6 +306,12 @@ public LibraryServiceStub createStub() throws IOException {
"Transport not supported: %s", getTransportChannelProvider().getTransportName()));
}

/** Returns the default service name. */
@Override
public String getServiceName() {
return "library-example";
}

/** Returns a builder for the default ExecutorProvider for this service. */
public static InstantiatingExecutorProvider.Builder defaultExecutorProviderBuilder() {
return InstantiatingExecutorProvider.newBuilder();
Expand Down