Skip to content

Commit 7259b97

Browse files
committed
feat(spanner): replaced setting channel provider with setting channel configurator
1 parent 03ce64f commit 7259b97

File tree

2 files changed

+31
-50
lines changed

2 files changed

+31
-50
lines changed

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

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@
2727
import com.google.api.gax.core.GaxProperties;
2828
import com.google.api.gax.grpc.GrpcCallContext;
2929
import com.google.api.gax.grpc.GrpcInterceptorProvider;
30-
import com.google.api.gax.grpc.GrpcTransportChannel;
3130
import com.google.api.gax.longrunning.OperationTimedPollAlgorithm;
3231
import com.google.api.gax.retrying.RetrySettings;
3332
import com.google.api.gax.rpc.ApiCallContext;
34-
import com.google.api.gax.rpc.FixedTransportChannelProvider;
3533
import com.google.api.gax.rpc.TransportChannelProvider;
3634
import com.google.api.gax.tracing.ApiTracerFactory;
3735
import com.google.api.gax.tracing.BaseApiTracerFactory;
@@ -71,19 +69,17 @@
7169
import io.grpc.CompressorRegistry;
7270
import io.grpc.Context;
7371
import io.grpc.ExperimentalApi;
74-
import io.grpc.ManagedChannel;
7572
import io.grpc.ManagedChannelBuilder;
7673
import io.grpc.MethodDescriptor;
7774
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
7875
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
76+
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
7977
import io.opentelemetry.api.GlobalOpenTelemetry;
8078
import io.opentelemetry.api.OpenTelemetry;
8179
import io.opentelemetry.api.common.Attributes;
8280
import java.io.File;
8381
import java.io.IOException;
8482
import java.net.MalformedURLException;
85-
import java.net.URI;
86-
import java.net.URISyntaxException;
8783
import java.net.URL;
8884
import java.time.Duration;
8985
import java.util.ArrayList;
@@ -98,8 +94,6 @@
9894
import java.util.concurrent.ThreadFactory;
9995
import java.util.concurrent.TimeUnit;
10096
import java.util.concurrent.atomic.AtomicInteger;
101-
import java.util.logging.Level;
102-
import java.util.logging.Logger;
10397
import javax.annotation.Nonnull;
10498
import javax.annotation.Nullable;
10599
import javax.annotation.concurrent.GuardedBy;
@@ -952,7 +946,6 @@ public static class Builder
952946
private CloseableExecutorProvider asyncExecutorProvider;
953947
private String compressorName;
954948
private String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST");
955-
private ManagedChannel managedChannel;
956949
private boolean leaderAwareRoutingEnabled = true;
957950
private boolean attemptDirectPath = true;
958951
private DirectedReadOptions directedReadOptions;
@@ -963,6 +956,7 @@ public static class Builder
963956
private boolean enableEndToEndTracing = SpannerOptions.environment.isEnableEndToEndTracing();
964957
private boolean enableBuiltInMetrics = SpannerOptions.environment.isEnableBuiltInMetrics();
965958
private String monitoringHost = SpannerOptions.environment.getMonitoringHost();
959+
private SslContext mTLSContext = null;
966960

967961
private static String createCustomClientLibToken(String token) {
968962
return token + " " + ServiceOptions.getGoogApiClientLibName();
@@ -1496,34 +1490,27 @@ public Builder setEmulatorHost(String emulatorHost) {
14961490
return this;
14971491
}
14981492

1499-
public Builder useClientCert(String host, String clientCertificate, String clientKey) {
1493+
/**
1494+
* Configures mTLS authentication using the provided client certificate and key files. mTLS is
1495+
* only supported for external spanner hosts.
1496+
*
1497+
* @param clientCertificate Path to the client certificate file.
1498+
* @param clientCertificateKey Path to the client private key file.
1499+
* @throws SpannerException If an error occurs while configuring the mTLS context
1500+
*/
1501+
@ExperimentalApi("https://github.com/googleapis/java-spanner/pull/3574")
1502+
public Builder useClientCert(String clientCertificate, String clientCertificateKey) {
15001503
try {
1501-
URI uri = new URI(host);
1502-
managedChannel =
1503-
NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort())
1504-
.sslContext(
1505-
GrpcSslContexts.forClient()
1506-
.keyManager(new File(clientCertificate), new File(clientKey))
1507-
.build())
1504+
this.mTLSContext =
1505+
GrpcSslContexts.forClient()
1506+
.keyManager(new File(clientCertificate), new File(clientCertificateKey))
15081507
.build();
1509-
1510-
setChannelProvider(
1511-
FixedTransportChannelProvider.create(GrpcTransportChannel.create(managedChannel)));
1512-
} catch (URISyntaxException e) {
1513-
throw new IllegalArgumentException(
1514-
"Invalid host format. Expected format: 'protocol://host[:port]'.", e);
15151508
} catch (Exception e) {
1516-
throw new RuntimeException("Unexpected error during mTLS setup.", e);
1509+
throw SpannerExceptionFactory.asSpannerException(e);
15171510
}
15181511
return this;
15191512
}
15201513

1521-
public Builder usePlainText() {
1522-
this.setChannelConfigurator(ManagedChannelBuilder::usePlaintext);
1523-
this.setCredentials(NoCredentials.getInstance());
1524-
return this;
1525-
}
1526-
15271514
/**
15281515
* Sets OpenTelemetry object to be used for Spanner Metrics and Traces. GlobalOpenTelemetry will
15291516
* be used as fallback if this options is not set.
@@ -1632,24 +1619,15 @@ public SpannerOptions build() {
16321619
this.setChannelConfigurator(ManagedChannelBuilder::usePlaintext);
16331620
// As we are using plain text, we should never send any credentials.
16341621
this.setCredentials(NoCredentials.getInstance());
1635-
} else if (managedChannel != null) {
1636-
// Add shutdown hook for the ManagedChannel if created to prevent resource leak
1637-
Runtime.getRuntime()
1638-
.addShutdownHook(
1639-
new Thread(
1640-
() -> {
1641-
final Logger logger = Logger.getLogger(SpannerOptions.class.getName());
1642-
try {
1643-
managedChannel.shutdown();
1644-
logger.log(
1645-
Level.INFO, "[SpannerOptions] ManagedChannel shut down successfully.");
1646-
} catch (Exception e) {
1647-
logger.log(
1648-
Level.WARNING,
1649-
"[SpannerOptions] Failed to shut down ManagedChannel.",
1650-
e);
1651-
}
1652-
}));
1622+
}
1623+
if (mTLSContext != null) {
1624+
this.setChannelConfigurator(
1625+
builder -> {
1626+
if (builder instanceof NettyChannelBuilder) {
1627+
((NettyChannelBuilder) builder).sslContext(mTLSContext);
1628+
}
1629+
return builder;
1630+
});
16531631
}
16541632
if (this.numChannels == null) {
16551633
this.numChannels =

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ static class SpannerPoolKey {
161161
private final Boolean enableExtendedTracing;
162162
private final Boolean enableApiTracing;
163163
private final boolean enableEndToEndTracing;
164+
private final String clientCertificate;
165+
private final String clientCertificateKey;
164166

165167
@VisibleForTesting
166168
static SpannerPoolKey of(ConnectionOptions options) {
@@ -192,6 +194,8 @@ private SpannerPoolKey(ConnectionOptions options) throws IOException {
192194
this.enableExtendedTracing = options.isEnableExtendedTracing();
193195
this.enableApiTracing = options.isEnableApiTracing();
194196
this.enableEndToEndTracing = options.isEndToEndTracingEnabled();
197+
this.clientCertificate = options.getClientCertificate();
198+
this.clientCertificateKey = options.getClientCertificateKey();
195199
}
196200

197201
@Override
@@ -393,9 +397,8 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) {
393397
// Set a custom channel configurator to allow http instead of https.
394398
builder.setChannelConfigurator(ManagedChannelBuilder::usePlaintext);
395399
}
396-
if (options.getClientCertificate() != null && options.getClientCertificateKey() != null) {
397-
builder.useClientCert(
398-
options.getHost(), options.getClientCertificate(), options.getClientCertificateKey());
400+
if (key.clientCertificate != null && key.clientCertificateKey != null) {
401+
builder.useClientCert(key.clientCertificate, key.clientCertificateKey);
399402
}
400403
if (options.getConfigurator() != null) {
401404
options.getConfigurator().configure(builder);

0 commit comments

Comments
 (0)