Skip to content

Commit ad29f9b

Browse files
committed
chore(spanner): deprecate experimental host option/parameter to replace with spanner omni
1 parent e5e5f14 commit ad29f9b

25 files changed

Lines changed: 305 additions & 138 deletions

java-spanner/google-cloud-spanner/clirr-ignored-differences.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -910,21 +910,21 @@
910910
<method>java.lang.Object runTransaction(com.google.cloud.spanner.connection.Connection$TransactionCallable)</method>
911911
</difference>
912912

913-
<!-- Added experimental host option -->
913+
<!-- Added Spanner Omni option -->
914914
<difference>
915915
<differenceType>7012</differenceType>
916916
<className>com/google/cloud/spanner/SpannerOptions$SpannerEnvironment</className>
917-
<method>com.google.auth.oauth2.GoogleCredentials getDefaultExperimentalHostCredentials()</method>
917+
<method>com.google.auth.oauth2.GoogleCredentials getDefaultSpannerOmniCredentials()</method>
918918
</difference>
919919
<difference>
920920
<differenceType>7002</differenceType>
921921
<className>com/google/cloud/spanner/SpannerOptions$SpannerEnvironment</className>
922-
<method>com.google.auth.oauth2.GoogleCredentials getDefaultExternalHostCredentials()</method>
922+
<method>com.google.auth.oauth2.GoogleCredentials getDefaultSpannerOmniCredentials()</method>
923923
</difference>
924924
<difference>
925925
<differenceType>7002</differenceType>
926926
<className>com/google/cloud/spanner/SpannerOptions</className>
927-
<method>com.google.auth.oauth2.GoogleCredentials getDefaultExternalHostCredentialsFromSysEnv()</method>
927+
<method>com.google.auth.oauth2.GoogleCredentials getDefaultSpannerOmniCredentialsFromSysEnv()</method>
928928
</difference>
929929

930930
<!-- Default sequence kind -->

java-spanner/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ public class SpannerOptions extends ServiceOptions<Spanner, SpannerOptions> {
126126
private static final String API_SHORT_NAME = "Spanner";
127127
private static final String SPANNER_SERVICE_NAME = "spanner";
128128
private static final String GOOGLE_DEFAULT_UNIVERSE = "googleapis.com";
129-
private static final String EXPERIMENTAL_HOST_PROJECT_ID = "default";
129+
public static final String SPANNER_OMNI_PROJECT_ID = "default";
130+
public static final String DEFAULT_SPANNER_OMNI_INSTANCE_ID = "default";
130131

131132
static final ImmutableSet<String> SCOPES =
132133
ImmutableSet.of(
@@ -314,6 +315,18 @@ enum TracingFramework {
314315
OPEN_TELEMETRY
315316
}
316317

318+
/**
319+
* Specifies the type of Spanner instance to connect to (CLOUD, OMNI, or EMULATOR). Currently,
320+
* this is a no-op for most types, but setting it to OMNI is mandatory when connecting to a
321+
* Spanner Omni instance.
322+
*/
323+
public enum InstanceType {
324+
UNSPECIFIED,
325+
CLOUD,
326+
OMNI,
327+
EMULATOR
328+
}
329+
317330
private static final Object lock = new Object();
318331

319332
@GuardedBy("lock")
@@ -924,16 +937,17 @@ protected SpannerOptions(Builder builder) {
924937

925938
// Dynamic channel pooling is disabled by default.
926939
// It is only enabled when:
927-
// 1. enableDynamicChannelPool() was explicitly called (or experimentalHost is set and DCP was
940+
// 1. enableDynamicChannelPool() was explicitly called (or instance is set to OMNI and DCP was
928941
// not explicitly disabled), AND
929942
// 2. grpc-gcp extension is enabled, AND
930943
// 3. numChannels was not explicitly set
931944
boolean dcpRequested =
932945
builder.dynamicChannelPoolEnabled != null
933946
? builder.dynamicChannelPoolEnabled
934-
: builder.experimentalHost != null;
947+
: builder.instanceType == InstanceType.OMNI;
935948
if (dcpRequested) {
936-
// DCP was enabled (explicitly or via experimentalHost), but respect numChannels if set
949+
// DCP was enabled (explicitly or via instance type being OMNI), but respect numChannels if
950+
// set
937951
dynamicChannelPoolEnabled = grpcGcpExtensionEnabled && !builder.numChannelsExplicitlySet;
938952
} else {
939953
// DCP is disabled by default, or was explicitly disabled
@@ -976,14 +990,14 @@ protected SpannerOptions(Builder builder) {
976990
openTelemetry = builder.openTelemetry;
977991
enableApiTracing = builder.enableApiTracing;
978992
enableExtendedTracing = builder.enableExtendedTracing;
979-
if (builder.experimentalHost != null) {
993+
if (builder.instanceType == InstanceType.OMNI) {
980994
enableBuiltInMetrics = false;
981995
} else {
982996
enableBuiltInMetrics = builder.enableBuiltInMetrics;
983997
}
984-
// Enable location API when experimental host is set, unless explicitly disabled
998+
// Enable location API when InstanceType is OMNI, unless explicitly disabled
985999
// via GOOGLE_SPANNER_EXPERIMENTAL_LOCATION_API=false.
986-
if (builder.experimentalHost != null) {
1000+
if (builder.instanceType == InstanceType.OMNI) {
9871001
String locationApiEnvValue = System.getenv(EXPERIMENTAL_LOCATION_API_ENV_VAR);
9881002
enableLocationApi = locationApiEnvValue == null || Boolean.parseBoolean(locationApiEnvValue);
9891003
} else {
@@ -1072,13 +1086,12 @@ default String getMonitoringHost() {
10721086
return null;
10731087
}
10741088

1075-
default GoogleCredentials getDefaultExperimentalHostCredentials() {
1089+
default GoogleCredentials getDefaultSpannerOmniCredentials() {
10761090
return null;
10771091
}
10781092
}
10791093

1080-
static final String DEFAULT_SPANNER_EXPERIMENTAL_HOST_CREDENTIALS =
1081-
"SPANNER_EXPERIMENTAL_HOST_AUTH_TOKEN";
1094+
static final String DEFAULT_SPANNER_OMNI_CREDENTIALS = "SPANNER_OMNI_AUTH_TOKEN";
10821095

10831096
/**
10841097
* Default implementation of {@link SpannerEnvironment}. Reads all configuration from environment
@@ -1174,8 +1187,8 @@ public String getMonitoringHost() {
11741187
}
11751188

11761189
@Override
1177-
public GoogleCredentials getDefaultExperimentalHostCredentials() {
1178-
return getOAuthTokenFromFile(System.getenv(DEFAULT_SPANNER_EXPERIMENTAL_HOST_CREDENTIALS));
1190+
public GoogleCredentials getDefaultSpannerOmniCredentials() {
1191+
return getOAuthTokenFromFile(System.getenv(DEFAULT_SPANNER_OMNI_CREDENTIALS));
11791192
}
11801193
}
11811194

@@ -1252,10 +1265,11 @@ public static class Builder
12521265
private boolean enableLocationApi = SpannerOptions.environment.isEnableLocationApi();
12531266
private String monitoringHost = SpannerOptions.environment.getMonitoringHost();
12541267
private SslContext mTLSContext = null;
1255-
private String experimentalHost = null;
12561268
private boolean usePlainText = false;
12571269
private TransactionOptions defaultTransactionOptions = TransactionOptions.getDefaultInstance();
12581270
private RequestOptions.ClientContext clientContext;
1271+
private InstanceType instanceType = InstanceType.UNSPECIFIED;
1272+
private String host = null;
12591273

12601274
private static String createCustomClientLibToken(String token) {
12611275
return token + " " + ServiceOptions.getGoogApiClientLibName();
@@ -1795,26 +1809,49 @@ public Builder setDecodeMode(DecodeMode decodeMode) {
17951809
@Override
17961810
public Builder setHost(String host) {
17971811
super.setHost(host);
1812+
this.host = host;
17981813
// Setting a host should override any SPANNER_EMULATOR_HOST setting.
17991814
setEmulatorHost(null);
18001815
return this;
18011816
}
18021817

1818+
/** @deprecated Use {@link #setType(InstanceType)} instead. */
1819+
@Deprecated
1820+
@ObsoleteApi("Use setHost(String).setType(InstanceType.OMNI) instead")
18031821
@ExperimentalApi("https://github.com/googleapis/java-spanner/pull/3676")
18041822
public Builder setExperimentalHost(String host) {
1805-
if (this.usePlainText) {
1806-
Preconditions.checkArgument(
1807-
!host.startsWith("https:"),
1808-
"Please remove the 'https:' protocol prefix from the host string when using plain text"
1809-
+ " communication");
1810-
if (!host.startsWith("http")) {
1811-
host = "http://" + host;
1823+
setHost(host);
1824+
if (!Strings.isNullOrEmpty(host)) {
1825+
setType(InstanceType.OMNI);
1826+
}
1827+
return this;
1828+
}
1829+
1830+
/**
1831+
* Specifies the type of Spanner instance to connect to (CLOUD, OMNI, or EMULATOR). Currently,
1832+
* this is a no-op for most types, but setting it to OMNI is mandatory when connecting to a
1833+
* Spanner Omni instance.
1834+
*/
1835+
public Builder setType(InstanceType instanceType) {
1836+
this.instanceType = instanceType;
1837+
if (instanceType == InstanceType.OMNI) {
1838+
if (Strings.isNullOrEmpty(this.host)) {
1839+
throw new IllegalStateException("Host must be set before setting Type to OMNI");
1840+
}
1841+
if (this.usePlainText) {
1842+
Preconditions.checkArgument(
1843+
!this.host.startsWith("https:"),
1844+
"Please remove the 'https:' protocol prefix from the host string when using plain text"
1845+
+ " communication");
1846+
if (!this.host.startsWith("http")) {
1847+
this.host = "http://" + this.host;
1848+
setHost(this.host);
1849+
}
18121850
}
1851+
setBuiltInMetricsEnabled(false);
1852+
super.setProjectId(SPANNER_OMNI_PROJECT_ID);
1853+
setSessionPoolOption(SessionPoolOptions.newBuilder().setExperimentalHost().build());
18131854
}
1814-
super.setHost(host);
1815-
super.setProjectId(EXPERIMENTAL_HOST_PROJECT_ID);
1816-
setSessionPoolOption(SessionPoolOptions.newBuilder().setExperimentalHost().build());
1817-
this.experimentalHost = host;
18181855
return this;
18191856
}
18201857

@@ -1916,14 +1953,13 @@ public Builder setEmulatorHost(String emulatorHost) {
19161953
}
19171954

19181955
/**
1919-
* Configures mTLS authentication using the provided client certificate and key files. mTLS is
1920-
* only supported for experimental spanner hosts.
1956+
* Configures mTLS authentication using the provided client certificate and key files. mTLS via
1957+
* useClientCert is only supported for Spanner Omni instances.
19211958
*
19221959
* @param clientCertificate Path to the client certificate file.
19231960
* @param clientCertificateKey Path to the client private key file.
19241961
* @throws SpannerException If an error occurs while configuring the mTLS context
19251962
*/
1926-
@ExperimentalApi("https://github.com/googleapis/java-spanner/pull/3574")
19271963
public Builder useClientCert(String clientCertificate, String clientCertificateKey) {
19281964
try {
19291965
this.mTLSContext =
@@ -1941,14 +1977,13 @@ public Builder useClientCert(String clientCertificate, String clientCertificateK
19411977
* credentials to {@link com.google.cloud.NoCredentials} to avoid sending authentication over an
19421978
* unsecured channel.
19431979
*/
1944-
@ExperimentalApi("https://github.com/googleapis/java-spanner/pull/4264")
19451980
public Builder usePlainText() {
19461981
this.usePlainText = true;
19471982
this.setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
19481983
.setCredentials(NoCredentials.getInstance());
1949-
if (this.experimentalHost != null) {
1984+
if (this.instanceType == InstanceType.OMNI && !Strings.isNullOrEmpty(this.host)) {
19501985
// Re-apply host settings to ensure http:// is prepended.
1951-
setExperimentalHost(this.experimentalHost);
1986+
setType(InstanceType.OMNI);
19521987
}
19531988
return this;
19541989
}
@@ -2124,7 +2159,7 @@ public Builder setDefaultClientContext(RequestOptions.ClientContext clientContex
21242159
@Override
21252160
public SpannerOptions build() {
21262161
// Set the host of emulator has been set.
2127-
if (emulatorHost != null && experimentalHost == null) {
2162+
if (emulatorHost != null && this.instanceType != InstanceType.OMNI) {
21282163
if (!emulatorHost.startsWith("http")) {
21292164
emulatorHost = "http://" + emulatorHost;
21302165
}
@@ -2134,8 +2169,8 @@ public SpannerOptions build() {
21342169
this.setChannelConfigurator(ManagedChannelBuilder::usePlaintext);
21352170
// As we are using plain text, we should never send any credentials.
21362171
this.setCredentials(NoCredentials.getInstance());
2137-
} else if (experimentalHost != null && credentials == null) {
2138-
credentials = environment.getDefaultExperimentalHostCredentials();
2172+
} else if (this.instanceType == InstanceType.OMNI && credentials == null) {
2173+
credentials = environment.getDefaultSpannerOmniCredentials();
21392174
}
21402175
if (this.numChannels == null) {
21412176
this.numChannels =
@@ -2177,8 +2212,8 @@ public static void useDefaultEnvironment() {
21772212
}
21782213

21792214
@InternalApi
2180-
public static GoogleCredentials getDefaultExperimentalCredentialsFromSysEnv() {
2181-
return getOAuthTokenFromFile(System.getenv(DEFAULT_SPANNER_EXPERIMENTAL_HOST_CREDENTIALS));
2215+
public static GoogleCredentials getDefaultSpannerOmniCredentialsFromSysEnv() {
2216+
return getOAuthTokenFromFile(System.getenv(DEFAULT_SPANNER_OMNI_CREDENTIALS));
21822217
}
21832218

21842219
private static @Nullable GoogleCredentials getOAuthTokenFromFile(@Nullable String file) {

java-spanner/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementValueConverters.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.cloud.spanner.Options.RpcPriority;
2727
import com.google.cloud.spanner.SpannerException;
2828
import com.google.cloud.spanner.SpannerExceptionFactory;
29+
import com.google.cloud.spanner.SpannerOptions;
2930
import com.google.cloud.spanner.TimestampBound;
3031
import com.google.cloud.spanner.TimestampBound.Mode;
3132
import com.google.cloud.spanner.connection.PgTransactionMode.AccessMode;
@@ -895,4 +896,31 @@ public Dialect convert(String value) {
895896
return values.get(value);
896897
}
897898
}
899+
900+
static class InstanceTypeConverter
901+
implements ClientSideStatementValueConverter<SpannerOptions.InstanceType> {
902+
static final InstanceTypeConverter INSTANCE = new InstanceTypeConverter();
903+
904+
private final CaseInsensitiveEnumMap<SpannerOptions.InstanceType> values =
905+
new CaseInsensitiveEnumMap<>(SpannerOptions.InstanceType.class);
906+
907+
private InstanceTypeConverter() {}
908+
909+
/** Constructor needed for reflection. */
910+
public InstanceTypeConverter(String allowedValues) {}
911+
912+
@Override
913+
public Class<SpannerOptions.InstanceType> getParameterClass() {
914+
return SpannerOptions.InstanceType.class;
915+
}
916+
917+
@Override
918+
public SpannerOptions.InstanceType convert(String value) {
919+
SpannerOptions.InstanceType converted = values.get(value);
920+
if (converted == SpannerOptions.InstanceType.UNSPECIFIED) {
921+
return null;
922+
}
923+
return converted;
924+
}
925+
}
898926
}

0 commit comments

Comments
 (0)