From eb04d5b251d42d5121513188d5c23fd672c15c47 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Fri, 9 Oct 2026 09:55:52 -0400 Subject: [PATCH] Remove unused DataStax Astra support Remove secure connect bundle parsing, cloud topology, SNI routing, public configuration API, examples, tests, and fixtures. Preserve ScyllaDB client routes and document migration in the 4.19.2.3 guide. Closes #1026 --- core/pom.xml | 5 - .../api/core/config/DefaultDriverOption.java | 8 - .../api/core/config/TypedDriverOption.java | 6 - .../core/session/ProgrammaticArguments.java | 17 - .../api/core/session/SessionBuilder.java | 182 ------- .../internal/core/channel/ChannelFactory.java | 43 -- .../internal/core/channel/DriverChannel.java | 7 - .../core/channel/ProtocolInitHandler.java | 4 +- .../core/config/cloud/CloudConfig.java | 66 --- .../core/config/cloud/CloudConfigFactory.java | 296 ----------- .../config/typesafe/TypesafeDriverConfig.java | 58 -- .../context/DefaultDriverConfigReporter.java | 5 - .../core/context/DefaultDriverContext.java | 13 - .../core/metadata/CloudTopologyMonitor.java | 47 -- .../internal/core/metadata/SniEndPoint.java | 119 ----- .../core/ssl/SniSslEngineFactory.java | 99 ---- .../tracker/W3CContextRequestIdGenerator.java | 4 - core/src/main/resources/reference.conf | 14 - .../driver/api/core/data/CqlVectorTest.java | 10 +- .../ChannelFactoryClusterNameTest.java | 18 +- .../ChannelFactorySupportedOptionsTest.java | 20 +- .../core/channel/ChannelFactoryTestBase.java | 17 +- .../core/channel/ProtocolInitHandlerTest.java | 12 +- .../config/cloud/CloudConfigFactoryTest.java | 235 -------- ...eSafeDriverConfigOverrideDefaultsTest.java | 179 ------- .../ClientRoutesConfigFromFileTest.java | 28 +- .../DefaultDriverConfigReporterTest.java | 2 - .../metadata/DefaultTopologyMonitorTest.java | 2 +- .../metadata/schema/TableMetadataTest.java | 2 +- .../core/metrics/DefaultMetricIdTest.java | 2 +- .../metrics/TaggingMetricIdGeneratorTest.java | 2 +- .../protocol/BytesToSegmentDecoderTest.java | 2 +- .../core/tracker/RequestIdGeneratorTest.java | 8 - .../src/test/resources/config/cloud/creds.zip | Bin 9805 -> 0 bytes .../test/resources/config/cloud/identity.jks | Bin 2493 -> 0 bytes .../test/resources/config/cloud/metadata.json | 1 - .../resources/config/cloud/trustStore.jks | Bin 956 -> 0 bytes .../astra/AstraReadCassandraVersion.java | 81 --- .../mapper/KillrVideoMapperExample.java | 8 +- integration-tests/pom.xml | 5 - .../oss/driver/api/core/cloud/CloudIT.java | 500 ------------------ .../driver/api/core/cloud/SniProxyRule.java | 43 -- .../driver/api/core/cloud/SniProxyServer.java | 150 ------ .../core/connectivity/client_routes/README.md | 6 +- pom.xml | 5 - upgrade_guide/README.md | 33 ++ 46 files changed, 84 insertions(+), 2280 deletions(-) delete mode 100644 core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java delete mode 100644 core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java delete mode 100644 core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java delete mode 100644 core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java delete mode 100644 core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java delete mode 100644 core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java delete mode 100644 core/src/test/java/com/datastax/oss/driver/internal/core/config/typesafe/TypeSafeDriverConfigOverrideDefaultsTest.java delete mode 100644 core/src/test/resources/config/cloud/creds.zip delete mode 100644 core/src/test/resources/config/cloud/identity.jks delete mode 100644 core/src/test/resources/config/cloud/metadata.json delete mode 100644 core/src/test/resources/config/cloud/trustStore.jks delete mode 100644 examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java delete mode 100644 integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java delete mode 100644 integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java delete mode 100644 integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java diff --git a/core/pom.xml b/core/pom.xml index fed8584cdc3..ef1a78ac11e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -185,11 +185,6 @@ testng test - - com.github.tomakehurst - wiremock - test - diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java index f2dd054279e..975b6f34751 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java @@ -885,14 +885,6 @@ public enum DefaultDriverOption implements DriverOption { */ NETTY_DAEMON("advanced.netty.daemon"), - /** - * The location of the cloud secure bundle used to connect to DataStax Apache Cassandra as a - * service. - * - *

Value-type: {@link String} - */ - CLOUD_SECURE_CONNECT_BUNDLE("basic.cloud.secure-connect-bundle"), - /** * Whether the slow replica avoidance should be enabled in the default LBP. * diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java index 450865cd870..3945deab32f 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java @@ -698,12 +698,6 @@ public String toString() { /** Whether the threads created by the driver should be daemon threads. */ public static final TypedDriverOption NETTY_DAEMON = new TypedDriverOption<>(DefaultDriverOption.NETTY_DAEMON, GenericType.BOOLEAN); - /** - * The location of the cloud secure bundle used to connect to DataStax Apache Cassandra as a - * service. - */ - public static final TypedDriverOption CLOUD_SECURE_CONNECT_BUNDLE = - new TypedDriverOption<>(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, GenericType.STRING); /** Whether the slow replica avoidance should be enabled in the default LBP. */ public static final TypedDriverOption LOAD_BALANCING_POLICY_SLOW_AVOIDANCE = new TypedDriverOption<>( diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java b/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java index 4db44655dc2..d70bf780593 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java @@ -36,7 +36,6 @@ import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.net.InetSocketAddress; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -68,7 +67,6 @@ public static Builder builder() { private final ClassLoader classLoader; private final AuthProvider authProvider; private final SslEngineFactory sslEngineFactory; - private final InetSocketAddress cloudProxyAddress; private final UUID startupClientId; private final String startupApplicationName; private final String startupApplicationVersion; @@ -88,7 +86,6 @@ private ProgrammaticArguments( @Nullable ClassLoader classLoader, @Nullable AuthProvider authProvider, @Nullable SslEngineFactory sslEngineFactory, - @Nullable InetSocketAddress cloudProxyAddress, @Nullable UUID startupClientId, @Nullable String startupApplicationName, @Nullable String startupApplicationVersion, @@ -107,7 +104,6 @@ private ProgrammaticArguments( this.classLoader = classLoader; this.authProvider = authProvider; this.sslEngineFactory = sslEngineFactory; - this.cloudProxyAddress = cloudProxyAddress; this.startupClientId = startupClientId; this.startupApplicationName = startupApplicationName; this.startupApplicationVersion = startupApplicationVersion; @@ -173,11 +169,6 @@ public SslEngineFactory getSslEngineFactory() { return sslEngineFactory; } - @Nullable - public InetSocketAddress getCloudProxyAddress() { - return cloudProxyAddress; - } - @Nullable public UUID getStartupClientId() { return startupClientId; @@ -223,7 +214,6 @@ public static class Builder { private ClassLoader classLoader; private AuthProvider authProvider; private SslEngineFactory sslEngineFactory; - private InetSocketAddress cloudProxyAddress; private UUID startupClientId; private String startupApplicationName; private String startupApplicationVersion; @@ -388,12 +378,6 @@ public Builder withClassLoader(@Nullable ClassLoader classLoader) { return this; } - @NonNull - public Builder withCloudProxyAddress(@Nullable InetSocketAddress cloudAddress) { - this.cloudProxyAddress = cloudAddress; - return this; - } - @NonNull public Builder withAuthProvider(@Nullable AuthProvider authProvider) { this.authProvider = authProvider; @@ -456,7 +440,6 @@ public ProgrammaticArguments build() { classLoader, authProvider, sslEngineFactory, - cloudProxyAddress, startupClientId, startupApplicationName, startupApplicationVersion, diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java b/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java index 8375f0ef30b..77c17fc7b41 100644 --- a/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java +++ b/core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java @@ -30,7 +30,6 @@ import com.datastax.oss.driver.api.core.auth.ProgrammaticPlainTextAuthProvider; import com.datastax.oss.driver.api.core.config.ClientRoutesConfig; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverConfig; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.context.DriverContext; @@ -48,24 +47,16 @@ import com.datastax.oss.driver.api.core.type.codec.registry.MutableCodecRegistry; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.datastax.oss.driver.internal.core.ContactPoints; -import com.datastax.oss.driver.internal.core.config.cloud.CloudConfig; -import com.datastax.oss.driver.internal.core.config.cloud.CloudConfigFactory; import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader; import com.datastax.oss.driver.internal.core.context.DefaultDriverContext; import com.datastax.oss.driver.internal.core.context.InternalDriverContext; import com.datastax.oss.driver.internal.core.metadata.DefaultEndPoint; import com.datastax.oss.driver.internal.core.session.DefaultSession; -import com.datastax.oss.driver.internal.core.tracker.W3CContextRequestIdGenerator; import com.datastax.oss.driver.internal.core.util.concurrent.BlockingOperation; import com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.io.InputStream; import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -73,7 +64,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.Callable; import java.util.concurrent.CompletionStage; import java.util.function.Predicate; import javax.net.ssl.SSLContext; @@ -92,8 +82,6 @@ @NotThreadSafe public abstract class SessionBuilder { - public static final String ASTRA_PAYLOAD_KEY = "traceparent"; - private static final Logger LOG = LoggerFactory.getLogger(SessionBuilder.class); @SuppressWarnings("unchecked") @@ -102,11 +90,8 @@ public abstract class SessionBuilder { protected DriverConfigLoader configLoader; protected Set programmaticContactPoints = new HashSet<>(); protected CqlIdentifier keyspace; - protected Callable cloudConfigInputStream; protected ProgrammaticArguments.Builder programmaticArgumentsBuilder = ProgrammaticArguments.builder(); - private boolean programmaticSslFactory = false; - private boolean programmaticLocalDatacenter = false; /** * Sets the configuration loader to use. @@ -427,7 +412,6 @@ public SelfT withCredentials( */ @NonNull public SelfT withSslEngineFactory(@Nullable SslEngineFactory sslEngineFactory) { - this.programmaticSslFactory = true; this.programmaticArgumentsBuilder.withSslEngineFactory(sslEngineFactory); return self; } @@ -465,7 +449,6 @@ public SelfT withSslContext(@Nullable SSLContext sslContext) { * if you use a third-party implementation, refer to their documentation. */ public SelfT withLocalDatacenter(@NonNull String profileName, @NonNull String localDatacenter) { - this.programmaticLocalDatacenter = true; this.programmaticArgumentsBuilder.withLocalDatacenter(profileName, localDatacenter); return self; } @@ -647,31 +630,6 @@ public SelfT withClassLoader(@Nullable ClassLoader classLoader) { return self; } - /** - * Configures this SessionBuilder for Cloud deployments by retrieving connection information from - * the provided {@link Path}. - * - *

To connect to a Cloud database, you must first download the secure database bundle from the - * DataStax Astra console that contains the connection information, then instruct the driver to - * read its contents using either this method or one if its variants. - * - *

For more information, please refer to the DataStax Astra documentation. - * - * @param cloudConfigPath Path to the secure connect bundle zip file. - * @see #withCloudSecureConnectBundle(URL) - * @see #withCloudSecureConnectBundle(InputStream) - */ - @NonNull - public SelfT withCloudSecureConnectBundle(@NonNull Path cloudConfigPath) { - try { - URL cloudConfigUrl = cloudConfigPath.toAbsolutePath().normalize().toUri().toURL(); - this.cloudConfigInputStream = cloudConfigUrl::openStream; - } catch (MalformedURLException e) { - throw new IllegalArgumentException("Incorrect format of cloudConfigPath", e); - } - return self; - } - /** * Registers a CodecRegistry to use for the session. * @@ -684,72 +642,6 @@ public SelfT withCodecRegistry(@Nullable MutableCodecRegistry codecRegistry) { return self; } - /** - * Configures this SessionBuilder for Cloud deployments by retrieving connection information from - * the provided {@link URL}. - * - *

To connect to a Cloud database, you must first download the secure database bundle from the - * DataStax Astra console that contains the connection information, then instruct the driver to - * read its contents using either this method or one if its variants. - * - *

For more information, please refer to the DataStax Astra documentation. - * - * @param cloudConfigUrl URL to the secure connect bundle zip file. - * @see #withCloudSecureConnectBundle(Path) - * @see #withCloudSecureConnectBundle(InputStream) - */ - @NonNull - public SelfT withCloudSecureConnectBundle(@NonNull URL cloudConfigUrl) { - this.cloudConfigInputStream = cloudConfigUrl::openStream; - return self; - } - - /** - * Configures this SessionBuilder for Cloud deployments by retrieving connection information from - * the provided {@link InputStream}. - * - *

To connect to a Cloud database, you must first download the secure database bundle from the - * DataStax Astra console that contains the connection information, then instruct the driver to - * read its contents using either this method or one if its variants. - * - *

For more information, please refer to the DataStax Astra documentation. - * - *

Note that the provided stream will be consumed and closed when either {@link - * #build()} or {@link #buildAsync()} are called; attempting to reuse it afterwards will result in - * an error being thrown. - * - * @param cloudConfigInputStream A stream containing the secure connect bundle zip file. - * @see #withCloudSecureConnectBundle(Path) - * @see #withCloudSecureConnectBundle(URL) - */ - @NonNull - public SelfT withCloudSecureConnectBundle(@NonNull InputStream cloudConfigInputStream) { - this.cloudConfigInputStream = () -> cloudConfigInputStream; - return self; - } - - /** - * Configures this SessionBuilder to use the provided Cloud proxy endpoint. - * - *

Normally, this method should not be called directly; the normal and easiest way to configure - * the driver for Cloud deployments is through a {@linkplain #withCloudSecureConnectBundle(URL) - * secure connect bundle}. - * - *

Setting this option to any non-null address will make the driver use a special topology - * monitor tailored for Cloud deployments. This topology monitor assumes that the target cluster - * should be contacted through the proxy specified here, using SNI routing. - * - *

For more information, please refer to the DataStax Astra documentation. - * - * @param cloudProxyAddress The address of the Cloud proxy to use. - * @see Server Name Indication - */ - @NonNull - public SelfT withCloudProxyAddress(@Nullable InetSocketAddress cloudProxyAddress) { - this.programmaticArgumentsBuilder.withCloudProxyAddress(cloudProxyAddress); - return self; - } - /** * Configures this session to use client routes for cloud private-endpoint deployments. * @@ -910,52 +802,8 @@ protected final CompletionStage buildDefaultSessionAsync() { : defaultConfigLoader(programmaticArguments.getClassLoader()); DriverExecutionProfile defaultConfig = configLoader.getInitialConfig().getDefaultProfile(); - if (cloudConfigInputStream == null) { - String configUrlString = - defaultConfig.getString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, null); - if (configUrlString != null) { - cloudConfigInputStream = () -> getURL(configUrlString).openStream(); - } - } List configContactPoints = defaultConfig.getStringList(DefaultDriverOption.CONTACT_POINTS, Collections.emptyList()); - if (cloudConfigInputStream != null) { - // override request id generator, unless user has already set it - if (programmaticArguments.getRequestIdGenerator() == null) { - programmaticArgumentsBuilder.withRequestIdGenerator( - new W3CContextRequestIdGenerator(ASTRA_PAYLOAD_KEY)); - LOG.debug( - "A secure connect bundle is provided, using W3CContextRequestIdGenerator as request ID generator."); - } - if (!programmaticContactPoints.isEmpty() || !configContactPoints.isEmpty()) { - LOG.info( - "Both a secure connect bundle and contact points were provided. These are mutually exclusive. The contact points from the secure bundle will have priority."); - // clear the contact points provided in the setting file and via addContactPoints - configContactPoints = Collections.emptyList(); - programmaticContactPoints = new HashSet<>(); - } - - if (programmaticSslFactory - || defaultConfig.isDefined(DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS)) { - LOG.info( - "Both a secure connect bundle and SSL options were provided. They are mutually exclusive. The SSL options from the secure bundle will have priority."); - } - CloudConfig cloudConfig = - new CloudConfigFactory().createCloudConfig(cloudConfigInputStream.call()); - addContactEndPoints(cloudConfig.getEndPoints()); - - boolean localDataCenterDefined = - anyProfileHasDatacenterDefined(configLoader.getInitialConfig()); - if (programmaticLocalDatacenter || localDataCenterDefined) { - LOG.info( - "Both a secure connect bundle and a local datacenter were provided. They are mutually exclusive. The local datacenter from the secure bundle will have priority."); - programmaticArgumentsBuilder.clearDatacenters(); - } - withLocalDatacenter(cloudConfig.getLocalDatacenter()); - withSslEngineFactory(cloudConfig.getSslEngineFactory()); - withCloudProxyAddress(cloudConfig.getProxyAddress()); - programmaticArguments = programmaticArgumentsBuilder.build(); - } boolean resolveAddresses = defaultConfig.getBoolean(DefaultDriverOption.RESOLVE_CONTACT_POINTS, false); @@ -980,36 +828,6 @@ protected final CompletionStage buildDefaultSessionAsync() { } } - private boolean anyProfileHasDatacenterDefined(DriverConfig driverConfig) { - for (DriverExecutionProfile driverExecutionProfile : driverConfig.getProfiles().values()) { - if (driverExecutionProfile.isDefined(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER)) { - return true; - } - } - return false; - } - - /** - * Returns URL based on the configUrl setting. If the configUrl has no protocol provided, the - * method will fallback to file:// protocol and return URL that has file protocol specified. - * - * @param configUrl url to config secure bundle - * @return URL with file protocol if there was not explicit protocol provided in the configUrl - * setting - */ - private URL getURL(String configUrl) throws MalformedURLException { - try { - return new URL(configUrl); - } catch (MalformedURLException e1) { - try { - return Paths.get(configUrl).toAbsolutePath().normalize().toUri().toURL(); - } catch (MalformedURLException e2) { - e2.addSuppressed(e1); - throw e2; - } - } - } - /** * This must return an instance of {@code InternalDriverContext} (it's not expressed * directly in the signature to avoid leaking that type through the protected API). diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java index 2d0f696c2b8..3572db68f7e 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ChannelFactory.java @@ -23,11 +23,9 @@ */ package com.datastax.oss.driver.internal.core.channel; -import com.datastax.oss.driver.api.core.ConsistencyLevel; import com.datastax.oss.driver.api.core.ProtocolVersion; import com.datastax.oss.driver.api.core.UnsupportedProtocolVersionException; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverConfig; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; import com.datastax.oss.driver.api.core.context.DriverContext; import com.datastax.oss.driver.api.core.metadata.EndPoint; @@ -35,7 +33,6 @@ import com.datastax.oss.driver.api.core.metadata.NodeShardingInfo; import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; -import com.datastax.oss.driver.internal.core.config.typesafe.TypesafeDriverConfig; import com.datastax.oss.driver.internal.core.context.InternalDriverContext; import com.datastax.oss.driver.internal.core.context.NettyOptions; import com.datastax.oss.driver.internal.core.metadata.DefaultNode; @@ -47,7 +44,6 @@ import com.datastax.oss.driver.shaded.guava.common.annotations.VisibleForTesting; import com.datastax.oss.driver.shaded.guava.common.base.Preconditions; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import com.datastax.oss.protocol.internal.ProtocolFeatures; import edu.umd.cs.findbugs.annotations.Nullable; import io.netty.bootstrap.Bootstrap; @@ -66,7 +62,6 @@ import java.net.ServerSocket; import java.net.SocketAddress; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -90,20 +85,8 @@ public class ChannelFactory { protected void initChannel(Channel channel) {} }; - /** - * A value for {@link #productType} that indicates that we are connected to DataStax Cloud. This - * value matches the one defined at DSE DB server side at {@code ProductType.java}. - */ - private static final String DATASTAX_CLOUD_PRODUCT_TYPE = "DATASTAX_APOLLO"; - private static final AtomicBoolean LOGGED_ORPHAN_WARNING = new AtomicBoolean(); - /** - * A value for {@link #productType} that indicates that the server does not report any product - * type. - */ - private static final String UNKNOWN_PRODUCT_TYPE = "UNKNOWN"; - // The names of the handlers on the pipeline: public static final String SSL_HANDLER_NAME = "ssl"; public static final String INBOUND_TRAFFIC_METER_NAME = "inboundTrafficMeter"; @@ -146,14 +129,6 @@ public static int effectiveMaxOrphanRequests( private volatile String clusterName; - /** - * The value of the {@code PRODUCT_TYPE} option reported by the first channel we opened, in - * response to a {@code SUPPORTED} request. - * - *

If the server does not return that option, the value will be {@link #UNKNOWN_PRODUCT_TYPE}. - */ - @VisibleForTesting volatile String productType; - private final Object resolverLock = new Object(); /** @see #resolverState() */ @@ -484,24 +459,6 @@ private void connect( if (ChannelFactory.this.clusterName == null) { ChannelFactory.this.clusterName = driverChannel.getClusterName(); } - Map> supportedOptions = driverChannel.getOptions(); - if (ChannelFactory.this.productType == null && supportedOptions != null) { - List productTypes = supportedOptions.get("PRODUCT_TYPE"); - String productType = - productTypes != null && !productTypes.isEmpty() - ? productTypes.get(0) - : UNKNOWN_PRODUCT_TYPE; - ChannelFactory.this.productType = productType; - DriverConfig driverConfig = context.getConfig(); - if (driverConfig instanceof TypesafeDriverConfig - && productType.equals(DATASTAX_CLOUD_PRODUCT_TYPE)) { - ((TypesafeDriverConfig) driverConfig) - .overrideDefaults( - ImmutableMap.of( - DefaultDriverOption.REQUEST_CONSISTENCY, - ConsistencyLevel.LOCAL_QUORUM.name())); - } - } resultFuture.complete(driverChannel); } else { Throwable error = connectFuture.cause(); diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/DriverChannel.java b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/DriverChannel.java index ba51469ab2d..557100c13c4 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/DriverChannel.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/DriverChannel.java @@ -49,7 +49,6 @@ import io.netty.util.concurrent.Promise; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; @@ -63,8 +62,6 @@ public class DriverChannel { static final AttributeKey CLUSTER_NAME_KEY = AttributeKey.valueOf("cluster_name"); - static final AttributeKey>> OPTIONS_KEY = - AttributeKey.valueOf("options"); @SuppressWarnings("RedundantStringConstructorCall") static final Object GRACEFUL_CLOSE_MESSAGE = new String("GRACEFUL_CLOSE_MESSAGE"); @@ -181,10 +178,6 @@ public String getClusterName() { return channel.attr(CLUSTER_NAME_KEY).get(); } - public Map> getOptions() { - return channel.attr(OPTIONS_KEY).get(); - } - public ProtocolFeatureStore getSupportedFeatures() { if (featureStore != null) { return featureStore; diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandler.java b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandler.java index dd7630a6530..60181d232cb 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandler.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandler.java @@ -98,8 +98,7 @@ class ProtocolInitHandler extends ConnectInitHandler { /** * @param querySupportedOptions whether to send OPTIONS as the first message, to request which - * protocol options the channel supports. If this is true, the options will be stored as a - * channel attribute, and exposed via {@link DriverChannel#getOptions()}. + * protocol options the channel supports and negotiate Scylla-specific protocol features. */ ProtocolInitHandler( InternalDriverContext context, @@ -229,7 +228,6 @@ void onResponse(Message response) { try { if (step == Step.OPTIONS && response instanceof Supported) { Supported supported = (Supported) response; - channel.attr(DriverChannel.OPTIONS_KEY).set(supported.options); featureStore = ProtocolFeatureStore.parseSupportedOptions(supported.options); featureStore.storeInChannel(channel); step = Step.STARTUP; diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java b/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java deleted file mode 100644 index 1a1076e9d78..00000000000 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.internal.core.config.cloud; - -import com.datastax.oss.driver.api.core.metadata.EndPoint; -import com.datastax.oss.driver.api.core.ssl.SslEngineFactory; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.net.InetSocketAddress; -import java.util.List; -import net.jcip.annotations.ThreadSafe; - -@ThreadSafe -public class CloudConfig { - - private final InetSocketAddress proxyAddress; - private final List endPoints; - private final String localDatacenter; - private final SslEngineFactory sslEngineFactory; - - CloudConfig( - @NonNull InetSocketAddress proxyAddress, - @NonNull List endPoints, - @NonNull String localDatacenter, - @NonNull SslEngineFactory sslEngineFactory) { - this.proxyAddress = proxyAddress; - this.endPoints = ImmutableList.copyOf(endPoints); - this.localDatacenter = localDatacenter; - this.sslEngineFactory = sslEngineFactory; - } - - @NonNull - public InetSocketAddress getProxyAddress() { - return proxyAddress; - } - - @NonNull - public List getEndPoints() { - return endPoints; - } - - @NonNull - public String getLocalDatacenter() { - return localDatacenter; - } - - @NonNull - public SslEngineFactory getSslEngineFactory() { - return sslEngineFactory; - } -} diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java b/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java deleted file mode 100644 index 817b3263d25..00000000000 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactory.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.internal.core.config.cloud; - -import com.datastax.oss.driver.api.core.metadata.EndPoint; -import com.datastax.oss.driver.internal.core.metadata.SniEndPoint; -import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory; -import com.datastax.oss.driver.shaded.guava.common.io.ByteStreams; -import com.datastax.oss.driver.shaded.guava.common.net.HostAndPort; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.ConnectException; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; -import net.jcip.annotations.ThreadSafe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ThreadSafe -public class CloudConfigFactory { - private static final Logger LOG = LoggerFactory.getLogger(CloudConfigFactory.class); - /** - * Creates a {@link CloudConfig} with information fetched from the specified Cloud configuration - * URL. - * - *

The target URL must point to a valid secure connect bundle archive in ZIP format. - * - * @param cloudConfigUrl the URL to fetch the Cloud configuration from; cannot be null. - * @throws IOException If the Cloud configuration cannot be read. - * @throws GeneralSecurityException If the Cloud SSL context cannot be created. - */ - @NonNull - public CloudConfig createCloudConfig(@NonNull URL cloudConfigUrl) - throws IOException, GeneralSecurityException { - Objects.requireNonNull(cloudConfigUrl, "cloudConfigUrl cannot be null"); - return createCloudConfig(cloudConfigUrl.openStream()); - } - - /** - * Creates a {@link CloudConfig} with information fetched from the specified {@link InputStream}. - * - *

The stream must contain a valid secure connect bundle archive in ZIP format. Note that the - * stream will be closed after a call to that method and cannot be used anymore. - * - * @param cloudConfig the stream to read the Cloud configuration from; cannot be null. - * @throws IOException If the Cloud configuration cannot be read. - * @throws GeneralSecurityException If the Cloud SSL context cannot be created. - */ - @NonNull - public CloudConfig createCloudConfig(@NonNull InputStream cloudConfig) - throws IOException, GeneralSecurityException { - Objects.requireNonNull(cloudConfig, "cloudConfig cannot be null"); - JsonNode configJson = null; - ByteArrayOutputStream keyStoreOutputStream = null; - ByteArrayOutputStream trustStoreOutputStream = null; - ObjectMapper mapper = new ObjectMapper().configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); - try (ZipInputStream zipInputStream = new ZipInputStream(cloudConfig)) { - ZipEntry entry; - while ((entry = zipInputStream.getNextEntry()) != null) { - String fileName = entry.getName(); - switch (fileName) { - case "config.json": - configJson = mapper.readTree(zipInputStream); - break; - case "identity.jks": - keyStoreOutputStream = new ByteArrayOutputStream(); - ByteStreams.copy(zipInputStream, keyStoreOutputStream); - break; - case "trustStore.jks": - trustStoreOutputStream = new ByteArrayOutputStream(); - ByteStreams.copy(zipInputStream, trustStoreOutputStream); - break; - } - } - } - if (configJson == null) { - throw new IllegalStateException("Invalid bundle: missing file config.json"); - } - if (keyStoreOutputStream == null) { - throw new IllegalStateException("Invalid bundle: missing file identity.jks"); - } - if (trustStoreOutputStream == null) { - throw new IllegalStateException("Invalid bundle: missing file trustStore.jks"); - } - char[] keyStorePassword = getKeyStorePassword(configJson); - char[] trustStorePassword = getTrustStorePassword(configJson); - ByteArrayInputStream keyStoreInputStream = - new ByteArrayInputStream(keyStoreOutputStream.toByteArray()); - ByteArrayInputStream trustStoreInputStream = - new ByteArrayInputStream(trustStoreOutputStream.toByteArray()); - SSLContext sslContext = - createSslContext( - keyStoreInputStream, keyStorePassword, trustStoreInputStream, trustStorePassword); - URL metadataServiceUrl = getMetadataServiceUrl(configJson); - JsonNode proxyMetadataJson; - try (BufferedReader proxyMetadata = fetchProxyMetadata(metadataServiceUrl, sslContext)) { - proxyMetadataJson = mapper.readTree(proxyMetadata); - } - InetSocketAddress sniProxyAddress = getSniProxyAddress(proxyMetadataJson); - List endPoints = getEndPoints(proxyMetadataJson, sniProxyAddress); - String localDatacenter = getLocalDatacenter(proxyMetadataJson); - SniSslEngineFactory sslEngineFactory = new SniSslEngineFactory(sslContext); - validateIfBundleContainsUsernamePassword(configJson); - return new CloudConfig(sniProxyAddress, endPoints, localDatacenter, sslEngineFactory); - } - - @NonNull - protected char[] getKeyStorePassword(JsonNode configFile) { - if (configFile.has("keyStorePassword")) { - return configFile.get("keyStorePassword").asText().toCharArray(); - } else { - throw new IllegalStateException("Invalid config.json: missing field keyStorePassword"); - } - } - - @NonNull - protected char[] getTrustStorePassword(JsonNode configFile) { - if (configFile.has("trustStorePassword")) { - return configFile.get("trustStorePassword").asText().toCharArray(); - } else { - throw new IllegalStateException("Invalid config.json: missing field trustStorePassword"); - } - } - - @NonNull - protected URL getMetadataServiceUrl(JsonNode configFile) throws MalformedURLException { - if (configFile.has("host")) { - String metadataServiceHost = configFile.get("host").asText(); - if (configFile.has("port")) { - int metadataServicePort = configFile.get("port").asInt(); - return new URL("https", metadataServiceHost, metadataServicePort, "/metadata"); - } else { - throw new IllegalStateException("Invalid config.json: missing field port"); - } - } else { - throw new IllegalStateException("Invalid config.json: missing field host"); - } - } - - protected void validateIfBundleContainsUsernamePassword(JsonNode configFile) { - if (configFile.has("username") || configFile.has("password")) { - LOG.info( - "The bundle contains config.json with username and/or password. Providing it in the bundle is deprecated and ignored."); - } - } - - @NonNull - protected SSLContext createSslContext( - @NonNull ByteArrayInputStream keyStoreInputStream, - @NonNull char[] keyStorePassword, - @NonNull ByteArrayInputStream trustStoreInputStream, - @NonNull char[] trustStorePassword) - throws IOException, GeneralSecurityException { - KeyManagerFactory kmf = createKeyManagerFactory(keyStoreInputStream, keyStorePassword); - TrustManagerFactory tmf = createTrustManagerFactory(trustStoreInputStream, trustStorePassword); - SSLContext sslContext = SSLContext.getInstance("SSL"); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); - return sslContext; - } - - @NonNull - protected KeyManagerFactory createKeyManagerFactory( - @NonNull InputStream keyStoreInputStream, @NonNull char[] keyStorePassword) - throws IOException, GeneralSecurityException { - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(keyStoreInputStream, keyStorePassword); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, keyStorePassword); - Arrays.fill(keyStorePassword, (char) 0); - return kmf; - } - - @NonNull - protected TrustManagerFactory createTrustManagerFactory( - @NonNull InputStream trustStoreInputStream, @NonNull char[] trustStorePassword) - throws IOException, GeneralSecurityException { - KeyStore ts = KeyStore.getInstance("JKS"); - ts.load(trustStoreInputStream, trustStorePassword); - TrustManagerFactory tmf = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ts); - Arrays.fill(trustStorePassword, (char) 0); - return tmf; - } - - @NonNull - protected BufferedReader fetchProxyMetadata( - @NonNull URL metadataServiceUrl, @NonNull SSLContext sslContext) throws IOException { - try { - HttpsURLConnection connection = (HttpsURLConnection) metadataServiceUrl.openConnection(); - connection.setSSLSocketFactory(sslContext.getSocketFactory()); - connection.setRequestMethod("GET"); - return new BufferedReader( - new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); - } catch (ConnectException e) { - throw new IllegalStateException( - "Unable to connect to cloud metadata service. Please make sure your cluster is not parked or terminated", - e); - } catch (UnknownHostException e) { - throw new IllegalStateException( - "Unable to resolve host for cloud metadata service. Please make sure your cluster is not terminated", - e); - } - } - - @NonNull - protected String getLocalDatacenter(@NonNull JsonNode proxyMetadata) { - JsonNode contactInfo = getContactInfo(proxyMetadata); - if (contactInfo.has("local_dc")) { - return contactInfo.get("local_dc").asText(); - } else { - throw new IllegalStateException("Invalid proxy metadata: missing field local_dc"); - } - } - - @NonNull - protected InetSocketAddress getSniProxyAddress(@NonNull JsonNode proxyMetadata) { - JsonNode contactInfo = getContactInfo(proxyMetadata); - if (contactInfo.has("sni_proxy_address")) { - HostAndPort sniProxyHostAndPort = - HostAndPort.fromString(contactInfo.get("sni_proxy_address").asText()); - if (!sniProxyHostAndPort.hasPort()) { - throw new IllegalStateException( - "Invalid proxy metadata: missing port from field sni_proxy_address"); - } - return InetSocketAddress.createUnresolved( - sniProxyHostAndPort.getHost(), sniProxyHostAndPort.getPort()); - } else { - throw new IllegalStateException("Invalid proxy metadata: missing field sni_proxy_address"); - } - } - - @NonNull - protected List getEndPoints( - @NonNull JsonNode proxyMetadata, @NonNull InetSocketAddress sniProxyAddress) { - JsonNode contactInfo = getContactInfo(proxyMetadata); - if (contactInfo.has("contact_points")) { - List endPoints = new ArrayList<>(); - JsonNode hostIdsJson = contactInfo.get("contact_points"); - for (int i = 0; i < hostIdsJson.size(); i++) { - endPoints.add(new SniEndPoint(sniProxyAddress, hostIdsJson.get(i).asText())); - } - return endPoints; - } else { - throw new IllegalStateException("Invalid proxy metadata: missing field contact_points"); - } - } - - @NonNull - protected JsonNode getContactInfo(@NonNull JsonNode proxyMetadata) { - if (proxyMetadata.has("contact_info")) { - return proxyMetadata.get("contact_info"); - } else { - throw new IllegalStateException("Invalid proxy metadata: missing field contact_info"); - } - } -} diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/config/typesafe/TypesafeDriverConfig.java b/core/src/main/java/com/datastax/oss/driver/internal/core/config/typesafe/TypesafeDriverConfig.java index 2337bf82bc2..445049ca1c4 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/config/typesafe/TypesafeDriverConfig.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/config/typesafe/TypesafeDriverConfig.java @@ -21,21 +21,15 @@ import com.datastax.oss.driver.api.core.config.DriverConfig; import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.config.DriverOption; import com.datastax.oss.driver.internal.core.util.Loggers; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import com.typesafe.config.Config; import com.typesafe.config.ConfigObject; -import com.typesafe.config.ConfigOrigin; -import com.typesafe.config.ConfigOriginFactory; import com.typesafe.config.ConfigValue; -import com.typesafe.config.ConfigValueFactory; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import java.net.URL; import java.util.Map; import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; import net.jcip.annotations.ThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,15 +38,10 @@ public class TypesafeDriverConfig implements DriverConfig { private static final Logger LOG = LoggerFactory.getLogger(TypesafeDriverConfig.class); - private static final ConfigOrigin DEFAULT_OVERRIDES_ORIGIN = - ConfigOriginFactory.newSimple("default was overridden programmatically"); - private final ImmutableMap profiles; // Only used to detect if reload saw any change private volatile Config lastLoadedConfig; - private final Map defaultOverrides = new ConcurrentHashMap<>(); - private final TypesafeDriverExecutionProfile.Base defaultProfile; public TypesafeDriverConfig(Config config) { @@ -72,7 +61,6 @@ public TypesafeDriverConfig(Config config) { /** @return whether the configuration changed */ public boolean reload(Config config) { - config = applyDefaultOverrides(config); if (config.equals(lastLoadedConfig)) { return false; } else { @@ -183,50 +171,4 @@ public static Config getRawConfig(@NonNull DriverExecutionProfile profile) { } return null; } - - /** - * Replace the given options, only if the original values came from {@code - * reference.conf}: if the option was set explicitly in {@code application.conf}, then the - * override is ignored. - * - *

The overrides are also taken into account in profiles, and survive reloads. If this method - * is invoked multiple times, the last value for each option will be used. Note that it is - * currently not possible to use {@code null} as a value. - */ - public void overrideDefaults(@NonNull Map overrides) { - defaultOverrides.putAll(overrides); - reload(lastLoadedConfig); - } - - private Config applyDefaultOverrides(Config source) { - Config result = source; - for (Map.Entry entry : defaultOverrides.entrySet()) { - String path = entry.getKey().getPath(); - Object value = entry.getValue(); - if (isDefault(source, path)) { - LOG.debug("Replacing default value for {} by {}", path, value); - result = - result.withValue( - path, ConfigValueFactory.fromAnyRef(value).withOrigin(DEFAULT_OVERRIDES_ORIGIN)); - } else { - LOG.debug( - "Ignoring default override for {} because the user has overridden the value", path); - } - } - return result; - } - - // Whether the value in the given path comes from the reference.conf in the driver JAR. - private static boolean isDefault(Config config, String path) { - if (!config.hasPath(path)) { - return false; - } - ConfigOrigin origin = config.getValue(path).origin(); - if (origin.equals(DEFAULT_OVERRIDES_ORIGIN)) { - // Same default was overridden twice, should use the last value - return true; - } - URL url = origin.url(); - return url != null && url.toString().endsWith("reference.conf"); - } } diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java index f48d686573c..84426d5fe56 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporter.java @@ -41,7 +41,6 @@ import com.datastax.oss.driver.internal.core.specex.NoSpeculativeExecutionPolicy; import com.datastax.oss.driver.internal.core.ssl.DefaultSslEngineFactory; import com.datastax.oss.driver.internal.core.ssl.JdkSslHandlerFactory; -import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory; import com.datastax.oss.driver.internal.core.ssl.SslHandlerFactory; import com.datastax.oss.driver.internal.core.time.AtomicTimestampGenerator; import com.datastax.oss.driver.internal.core.time.ServerSideTimestampGenerator; @@ -1137,10 +1136,6 @@ private static Optional hostnameValidation(@Nullable SslEngineFactory e } else if (engineFactory instanceof ProgrammaticSslEngineFactory) { return Optional.of( ((ProgrammaticSslEngineFactory) engineFactory).isHostnameValidationRequired()); - } else if (engineFactory instanceof SniSslEngineFactory) { - // No accessor to read: SniSslEngineFactory sets the "HTTPS" endpoint identification algorithm - // on every engine it builds, unconditionally. - return Optional.of(true); } return Optional.empty(); } diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java index e6323b6b84c..58c61fb13d0 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/context/DefaultDriverContext.java @@ -62,7 +62,6 @@ import com.datastax.oss.driver.internal.core.config.typesafe.TypesafeDriverConfig; import com.datastax.oss.driver.internal.core.control.ControlConnection; import com.datastax.oss.driver.internal.core.metadata.ClientRoutesTopologyMonitor; -import com.datastax.oss.driver.internal.core.metadata.CloudTopologyMonitor; import com.datastax.oss.driver.internal.core.metadata.DefaultTopologyMonitor; import com.datastax.oss.driver.internal.core.metadata.LoadBalancingPolicyWrapper; import com.datastax.oss.driver.internal.core.metadata.MetadataManager; @@ -114,7 +113,6 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import io.netty.buffer.ByteBuf; -import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -254,7 +252,6 @@ public class DefaultDriverContext implements InternalDriverContext { private final Map> nodeFiltersFromBuilder; private final Map nodeDistanceEvaluatorsFromBuilder; private final ClassLoader classLoader; - private final InetSocketAddress cloudProxyAddress; private final ClientRoutesConfig clientRoutesConfigFromBuilder; private final LazyReference requestLogFormatterRef = new LazyReference<>("requestLogFormatter", this::buildRequestLogFormatter, cycleDetector); @@ -315,7 +312,6 @@ public DefaultDriverContext( this.nodeFiltersFromBuilder = nodeFilters; this.nodeDistanceEvaluatorsFromBuilder = programmaticArguments.getNodeDistanceEvaluators(); this.classLoader = programmaticArguments.getClassLoader(); - this.cloudProxyAddress = programmaticArguments.getCloudProxyAddress(); this.clientRoutesConfigFromBuilder = programmaticArguments.getClientRoutesConfig(); this.startupClientId = programmaticArguments.getStartupClientId(); this.startupApplicationName = programmaticArguments.getStartupApplicationName(); @@ -677,9 +673,6 @@ protected TopologyMonitor buildTopologyMonitor() { ClientRoutesConfig clientRoutesConfig = resolveClientRoutesConfig(); validateClientRoutesConfiguration(clientRoutesConfig); - if (cloudProxyAddress != null) { - return new CloudTopologyMonitor(this, cloudProxyAddress); - } if (clientRoutesConfig != null) { return new ClientRoutesTopologyMonitor(this, clientRoutesConfig); } @@ -690,12 +683,6 @@ private void validateClientRoutesConfiguration(ClientRoutesConfig clientRoutesCo if (clientRoutesConfig == null) { return; } - if (cloudProxyAddress != null) { - throw new IllegalStateException( - "Both a secure connect bundle and client routes configuration were provided. " - + "They are mutually exclusive. Please use either a secure connect bundle OR " - + "client routes configuration, but not both."); - } DriverExecutionProfile defaultProfile = getConfig().getDefaultProfile(); if (defaultProfile.isDefined(DefaultDriverOption.ADDRESS_TRANSLATOR_CLASS)) { String className = defaultProfile.getString(DefaultDriverOption.ADDRESS_TRANSLATOR_CLASS); diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java deleted file mode 100644 index 021824a9b16..00000000000 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/CloudTopologyMonitor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.internal.core.metadata; - -import com.datastax.oss.driver.api.core.metadata.EndPoint; -import com.datastax.oss.driver.internal.core.adminrequest.AdminRow; -import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.net.InetSocketAddress; -import java.util.Objects; -import java.util.UUID; - -public class CloudTopologyMonitor extends DefaultTopologyMonitor { - - private final InetSocketAddress cloudProxyAddress; - - public CloudTopologyMonitor(InternalDriverContext context, InetSocketAddress cloudProxyAddress) { - super(context); - this.cloudProxyAddress = cloudProxyAddress; - } - - @NonNull - @Override - protected EndPoint buildNodeEndPoint( - @NonNull AdminRow row, - @Nullable InetSocketAddress broadcastRpcAddress, - @NonNull EndPoint localEndPoint) { - UUID hostId = Objects.requireNonNull(row.getUuid("host_id")); - return new SniEndPoint(cloudProxyAddress, hostId.toString()); - } -} diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java deleted file mode 100644 index d1ab8eec98d..00000000000 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/metadata/SniEndPoint.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.internal.core.metadata; - -import com.datastax.oss.driver.api.core.metadata.EndPoint; -import com.datastax.oss.driver.shaded.guava.common.primitives.UnsignedBytes; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; - -public class SniEndPoint implements EndPoint { - private static final AtomicInteger OFFSET = new AtomicInteger(); - - private final InetSocketAddress proxyAddress; - private final String serverName; - - /** - * @param proxyAddress the address of the proxy. If it is {@linkplain - * InetSocketAddress#isUnresolved() unresolved}, each call to {@link #resolve()} will - * re-resolve it, fetch all of its A-records, and if there are more than 1 pick one in a - * round-robin fashion. - * @param serverName the SNI server name. In the context of Cloud, this is the string - * representation of the host id. - */ - public SniEndPoint(InetSocketAddress proxyAddress, String serverName) { - this.proxyAddress = Objects.requireNonNull(proxyAddress, "SNI address cannot be null"); - this.serverName = Objects.requireNonNull(serverName, "SNI Server name cannot be null"); - } - - public String getServerName() { - return serverName; - } - - @NonNull - @Override - public InetSocketAddress resolve() { - try { - InetAddress[] aRecords = InetAddress.getAllByName(proxyAddress.getHostName()); - if (aRecords.length == 0) { - // Probably never happens, but the JDK docs don't explicitly say so - throw new IllegalArgumentException( - "Could not resolve proxy address " + proxyAddress.getHostName()); - } - // The order of the returned address is unspecified. Sort by IP to make sure we get a true - // round-robin - Arrays.sort(aRecords, IP_COMPARATOR); - int index = - (aRecords.length == 1) - ? 0 - : OFFSET.getAndUpdate(x -> x == Integer.MAX_VALUE ? 0 : x + 1) % aRecords.length; - return new InetSocketAddress(aRecords[index], proxyAddress.getPort()); - } catch (UnknownHostException e) { - throw new IllegalArgumentException( - "Could not resolve proxy address " + proxyAddress.getHostName(), e); - } - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } else if (other instanceof SniEndPoint) { - SniEndPoint that = (SniEndPoint) other; - return this.proxyAddress.equals(that.proxyAddress) && this.serverName.equals(that.serverName); - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hash(proxyAddress, serverName); - } - - @Override - public String toString() { - // Note that this uses the original proxy address, so if there are multiple A-records it won't - // show which one was selected. If that turns out to be a problem for debugging, we might need - // to store the result of resolve() in Connection and log that instead of the endpoint. - return proxyAddress.toString() + ":" + serverName; - } - - @NonNull - @Override - public String asMetricPrefix() { - String hostString = proxyAddress.getHostString(); - if (hostString == null) { - throw new IllegalArgumentException( - "Could not extract a host string from provided proxy address " + proxyAddress); - } - return hostString.replace('.', '_') + ':' + proxyAddress.getPort() + '_' + serverName; - } - - @SuppressWarnings("UnnecessaryLambda") - private static final Comparator IP_COMPARATOR = - (InetAddress address1, InetAddress address2) -> - UnsignedBytes.lexicographicalComparator() - .compare(address1.getAddress(), address2.getAddress()); -} diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java b/core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java deleted file mode 100644 index 4d2cb69fbfc..00000000000 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/ssl/SniSslEngineFactory.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.datastax.oss.driver.internal.core.ssl; - -import com.datastax.oss.driver.api.core.metadata.EndPoint; -import com.datastax.oss.driver.api.core.ssl.SslEngineFactory; -import com.datastax.oss.driver.internal.core.metadata.SniEndPoint; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.net.InetSocketAddress; -import java.util.concurrent.CopyOnWriteArrayList; -import javax.net.ssl.SNIHostName; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; - -public class SniSslEngineFactory implements SslEngineFactory { - - // An offset that gets added to our "fake" ports (see below). We pick this value because it is the - // start of the ephemeral port range. - private static final int FAKE_PORT_OFFSET = 49152; - - private final SSLContext sslContext; - private final CopyOnWriteArrayList fakePorts = new CopyOnWriteArrayList<>(); - private final boolean allowDnsReverseLookupSan; - - public SniSslEngineFactory(SSLContext sslContext) { - this(sslContext, true); - } - - public SniSslEngineFactory(SSLContext sslContext, boolean allowDnsReverseLookupSan) { - this.sslContext = sslContext; - this.allowDnsReverseLookupSan = allowDnsReverseLookupSan; - } - - @NonNull - @Override - public SSLEngine newSslEngine(@NonNull EndPoint remoteEndpoint) { - if (!(remoteEndpoint instanceof SniEndPoint)) { - throw new IllegalArgumentException( - String.format( - "Configuration error: can only use %s with SNI end points", - this.getClass().getSimpleName())); - } - SniEndPoint sniEndPoint = (SniEndPoint) remoteEndpoint; - InetSocketAddress address = sniEndPoint.resolve(); - String sniServerName = sniEndPoint.getServerName(); - - // When hostname verification is enabled (with setEndpointIdentificationAlgorithm), the SSL - // engine will try to match the server's certificate against the SNI host name; if that doesn't - // work, it will fall back to the "advisory peer host" passed to createSSLEngine. - // - // In our case, the first check will never succeed because our SNI host name is not the DNS name - // (we use the Cassandra host_id instead). So we *must* set the advisory peer information. - // - // However if we use the address as-is, this leads to another issue: the advisory peer - // information is also used to cache SSL sessions internally. All of our nodes share the same - // proxy address, so the JDK tries to reuse SSL sessions across nodes. But it doesn't update the - // SNI host name every time, so it ends up opening connections to the wrong node. - // - // To avoid that, we create a unique "fake" port for every node. We still get session reuse for - // a given node, but not across nodes. This is safe because the advisory port is only used for - // session caching. - String peerHost = allowDnsReverseLookupSan ? address.getHostName() : address.getHostString(); - SSLEngine engine = sslContext.createSSLEngine(peerHost, getFakePort(sniServerName)); - engine.setUseClientMode(true); - SSLParameters parameters = engine.getSSLParameters(); - parameters.setServerNames(ImmutableList.of(new SNIHostName(sniServerName))); - parameters.setEndpointIdentificationAlgorithm("HTTPS"); - engine.setSSLParameters(parameters); - return engine; - } - - private int getFakePort(String sniServerName) { - fakePorts.addIfAbsent(sniServerName); - return FAKE_PORT_OFFSET + fakePorts.indexOf(sniServerName); - } - - @Override - public void close() { - // nothing to do - } -} diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/tracker/W3CContextRequestIdGenerator.java b/core/src/main/java/com/datastax/oss/driver/internal/core/tracker/W3CContextRequestIdGenerator.java index fe15b93bc8e..28890255a02 100644 --- a/core/src/main/java/com/datastax/oss/driver/internal/core/tracker/W3CContextRequestIdGenerator.java +++ b/core/src/main/java/com/datastax/oss/driver/internal/core/tracker/W3CContextRequestIdGenerator.java @@ -35,10 +35,6 @@ public W3CContextRequestIdGenerator(DriverContext context) { payloadKey = RequestIdGenerator.super.getCustomPayloadKey(); } - public W3CContextRequestIdGenerator(String payloadKey) { - this.payloadKey = payloadKey; - } - /** Random 16 bytes, e.g. "4bf92f3577b34da6a3ce929d0e0e4736" */ @Override public String getSessionRequestId() { diff --git a/core/src/main/resources/reference.conf b/core/src/main/resources/reference.conf index fcc7a034380..530011381d0 100644 --- a/core/src/main/resources/reference.conf +++ b/core/src/main/resources/reference.conf @@ -257,20 +257,6 @@ datastax-java-driver { # If this option is not defined, the driver defaults to true. slow-replica-avoidance = true } - basic.cloud { - # The location of the cloud secure bundle used to connect to DataStax Apache Cassandra as a - # service. - # This setting must be a valid URL. - # If the protocol is not specified, it is implicitly assumed to be the `file://` protocol, - # in which case the value is expected to be a valid path on the local filesystem. - # For example, `/a/path/to/bundle` will be interpreted as `file:/a/path/to/bunde`. - # If the protocol is provided explicitly, then the value will be used as is. - # - # Required: no - # Modifiable at runtime: no - # Overridable in a profile: no - // secure-connect-bundle = /location/of/secure/connect/bundle - } # DataStax Insights monitoring. basic.application { diff --git a/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java b/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java index 3e0872cb946..99986e3394d 100644 --- a/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java +++ b/core/src/test/java/com/datastax/oss/driver/api/core/data/CqlVectorTest.java @@ -37,8 +37,6 @@ import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Hex; import org.assertj.core.util.Lists; import org.junit.Test; import org.junit.runner.RunWith; @@ -242,12 +240,12 @@ public int size() { } @Test - public void should_not_use_preallocate_serialized_size() throws DecoderException { + public void should_not_use_preallocate_serialized_size() { // serialized CqlVector(1.0f, 2.5f, 3.0f) with size field adjusted to Integer.MAX_VALUE byte[] suspiciousBytes = - Hex.decodeHex( - "aced000573720042636f6d2e64617461737461782e6f73732e6472697665722e6170692e636f72652e646174612e43716c566563746f722453657269616c697a6174696f6e50726f78790000000000000001030000787077047fffffff7372000f6a6176612e6c616e672e466c6f6174daedc9a2db3cf0ec02000146000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000078703f8000007371007e0002402000007371007e00024040000078" - .toCharArray()); + ByteUtils.getArray( + ByteUtils.fromHexString( + "0xaced000573720042636f6d2e64617461737461782e6f73732e6472697665722e6170692e636f72652e646174612e43716c566563746f722453657269616c697a6174696f6e50726f78790000000000000001030000787077047fffffff7372000f6a6176612e6c616e672e466c6f6174daedc9a2db3cf0ec02000146000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000078703f8000007371007e0002402000007371007e00024040000078")); try { new ObjectInputStream(new ByteArrayInputStream(suspiciousBytes)).readObject(); fail("Should not be able to deserialize bytes with incorrect size field"); diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java index 4734a8ffdeb..d7c21ce8745 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryClusterNameTest.java @@ -23,9 +23,7 @@ import com.datastax.oss.driver.api.core.DefaultProtocolVersion; import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.internal.core.TestResponses; import com.datastax.oss.driver.internal.core.metrics.NoopNodeMetricUpdater; -import com.datastax.oss.protocol.internal.response.Ready; import java.util.concurrent.CompletionStage; import org.junit.Test; @@ -47,10 +45,7 @@ public void should_set_cluster_name_from_first_connection() { DriverChannelOptions.DEFAULT, NoopNodeMetricUpdater.INSTANCE); - writeInboundFrame( - readOutboundFrame(), TestResponses.supportedResponse("mock_key", "mock_value")); - writeInboundFrame(readOutboundFrame(), new Ready()); - writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName")); + completeSimpleChannelInit(); // Then assertThatStage(channelFuture).isSuccess(); @@ -73,10 +68,7 @@ public void should_check_cluster_name_for_next_connections() throws Throwable { DriverChannelOptions.DEFAULT, NoopNodeMetricUpdater.INSTANCE); // open a first connection that will define the cluster name - writeInboundFrame( - readOutboundFrame(), TestResponses.supportedResponse("mock_key", "mock_value")); - writeInboundFrame(readOutboundFrame(), new Ready()); - writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName")); + completeSimpleChannelInit(); assertThatStage(channelFuture).isSuccess(); // open a second connection that returns the same cluster name channelFuture = @@ -86,8 +78,7 @@ public void should_check_cluster_name_for_next_connections() throws Throwable { null, DriverChannelOptions.DEFAULT, NoopNodeMetricUpdater.INSTANCE); - writeInboundFrame(readOutboundFrame(), new Ready()); - writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName")); + completeSimpleChannelInit(); // Then assertThatStage(channelFuture).isSuccess(); @@ -101,8 +92,7 @@ public void should_check_cluster_name_for_next_connections() throws Throwable { null, DriverChannelOptions.DEFAULT, NoopNodeMetricUpdater.INSTANCE); - writeInboundFrame(readOutboundFrame(), new Ready()); - writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("wrongClusterName")); + completeSimpleChannelInit("wrongClusterName"); // Then assertThatStage(channelFuture) diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java index 87407921619..ea8b82025f3 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactorySupportedOptionsTest.java @@ -25,14 +25,13 @@ import com.datastax.oss.driver.api.core.config.DefaultDriverOption; import com.datastax.oss.driver.internal.core.TestResponses; import com.datastax.oss.driver.internal.core.metrics.NoopNodeMetricUpdater; -import com.datastax.oss.protocol.internal.response.Ready; import java.util.concurrent.CompletionStage; import org.junit.Test; public class ChannelFactorySupportedOptionsTest extends ChannelFactoryTestBase { @Test - public void should_query_supported_options_on_first_channel() throws Throwable { + public void should_query_supported_options_on_every_channel() throws Throwable { // Given when(defaultProfile.isDefined(DefaultDriverOption.PROTOCOL_VERSION)).thenReturn(false); when(protocolVersionRegistry.highestNonBeta()).thenReturn(DefaultProtocolVersion.V4); @@ -46,16 +45,16 @@ public void should_query_supported_options_on_first_channel() throws Throwable { null, DriverChannelOptions.DEFAULT, NoopNodeMetricUpdater.INSTANCE); - writeInboundFrame( - readOutboundFrame(), TestResponses.supportedResponse("mock_key", "mock_value")); - writeInboundFrame(readOutboundFrame(), new Ready()); - writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName")); + completeSimpleChannelInit( + TestResponses.supportedResponse( + "SCYLLA_LWT_ADD_METADATA_MARK", "LWT_OPTIMIZATION_META_BIT_MASK=1"), + "mockClusterName"); // Then assertThatStage(channelFuture1).isSuccess(); DriverChannel channel1 = channelFuture1.toCompletableFuture().get(); - assertThat(channel1.getOptions()).containsKey("mock_key"); - assertThat(channel1.getOptions().get("mock_key")).containsOnly("mock_value"); + assertThat(channel1.getSupportedFeatures().getLwtFeatureInfo()).isNotNull(); + assertThat(channel1.getSupportedFeatures().getLwtFeatureInfo().getMask()).isEqualTo(1); // When CompletionStage channelFuture2 = @@ -65,12 +64,11 @@ public void should_query_supported_options_on_first_channel() throws Throwable { null, DriverChannelOptions.DEFAULT, NoopNodeMetricUpdater.INSTANCE); - writeInboundFrame(readOutboundFrame(), new Ready()); - writeInboundFrame(readOutboundFrame(), TestResponses.clusterNameResponse("mockClusterName")); + completeSimpleChannelInit(); // Then assertThatStage(channelFuture2).isSuccess(); DriverChannel channel2 = channelFuture2.toCompletableFuture().get(); - assertThat(channel2.getOptions()).isNull(); + assertThat(channel2.getSupportedFeatures().getLwtFeatureInfo()).isNull(); } } diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java index ed6668a6c83..89d55d471f1 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ChannelFactoryTestBase.java @@ -41,6 +41,7 @@ import com.datastax.oss.protocol.internal.request.Options; import com.datastax.oss.protocol.internal.request.Startup; import com.datastax.oss.protocol.internal.response.Ready; +import com.datastax.oss.protocol.internal.response.Supported; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; @@ -208,16 +209,26 @@ private void writeInboundFrame(Frame requestFrame, Message response, int protoco * keyspace (avoids repeating it in subclasses). */ protected void completeSimpleChannelInit() { + completeSimpleChannelInit( + TestResponses.supportedResponse("mock_key", "mock_value"), "mockClusterName"); + } + + protected void completeSimpleChannelInit(String clusterName) { + completeSimpleChannelInit( + TestResponses.supportedResponse("mock_key", "mock_value"), clusterName); + } + + protected void completeSimpleChannelInit(Supported supportedResponse, String clusterName) { Frame requestFrame = readOutboundFrame(); assertThat(requestFrame.message).isInstanceOf(Options.class); - writeInboundFrame(requestFrame, TestResponses.supportedResponse("mock_key", "mock_value")); + writeInboundFrame(requestFrame, supportedResponse); requestFrame = readOutboundFrame(); assertThat(requestFrame.message).isInstanceOf(Startup.class); writeInboundFrame(requestFrame, new Ready()); requestFrame = readOutboundFrame(); - writeInboundFrame(requestFrame, TestResponses.clusterNameResponse("mockClusterName")); + writeInboundFrame(requestFrame, TestResponses.clusterNameResponse(clusterName)); } ChannelFactory newChannelFactory() { @@ -272,7 +283,7 @@ protected void initChannel(Channel channel) throws Exception { endPoint, options, heartbeatHandler, - productType == null); + true); channel .pipeline() .addLast(ChannelFactory.INFLIGHT_HANDLER_NAME, inFlightHandler) diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandlerTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandlerTest.java index 682caac198d..310d21fe294 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandlerTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/channel/ProtocolInitHandlerTest.java @@ -69,7 +69,6 @@ import java.time.Duration; import java.util.ConcurrentModificationException; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; import org.junit.Before; @@ -270,15 +269,16 @@ public void should_query_supported_options() { assertThat(connectFuture).isNotDone(); // Simulate the SUPPORTED response - writeInboundFrame(requestFrame, TestResponses.supportedResponse("mock_key", "mock_value")); - - Map> supportedOptions = channel.attr(DriverChannel.OPTIONS_KEY).get(); - assertThat(supportedOptions).containsKey("mock_key"); - assertThat(supportedOptions.get("mock_key")).containsOnly("mock_value"); + writeInboundFrame( + requestFrame, + TestResponses.supportedResponse( + "SCYLLA_LWT_ADD_METADATA_MARK", "LWT_OPTIMIZATION_META_BIT_MASK=1")); // It should send a STARTUP message requestFrame = readOutboundFrame(); assertThat(requestFrame.message).isInstanceOf(Startup.class); + assertThat(((Startup) requestFrame.message).options) + .containsEntry("SCYLLA_LWT_ADD_METADATA_MARK", "1"); assertThat(connectFuture).isNotDone(); // Simulate a READY response diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java deleted file mode 100644 index a0db82d298e..00000000000 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/config/cloud/CloudConfigFactoryTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.internal.core.config.cloud; - -import static com.datastax.oss.driver.Assertions.assertThat; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.any; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.assertj.core.api.Assertions.catchThrowable; - -import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.github.tomakehurst.wiremock.common.JettySettings; -import com.github.tomakehurst.wiremock.core.Options; -import com.github.tomakehurst.wiremock.http.AdminRequestHandler; -import com.github.tomakehurst.wiremock.http.HttpServer; -import com.github.tomakehurst.wiremock.http.HttpServerFactory; -import com.github.tomakehurst.wiremock.http.StubRequestHandler; -import com.github.tomakehurst.wiremock.jetty9.JettyHttpServer; -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import com.google.common.base.Joiner; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import org.eclipse.jetty.io.NetworkTrafficListener; -import org.eclipse.jetty.server.ConnectionFactory; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class CloudConfigFactoryTest { - - private static final String BUNDLE_PATH = "/config/cloud/creds.zip"; - - @Rule - public WireMockRule wireMockRule = - new WireMockRule( - wireMockConfig() - .httpsPort(30443) - .dynamicPort() - .httpServerFactory(new HttpsServerFactory()) - .needClientAuth(true) - .keystorePath(path("/config/cloud/identity.jks").toString()) - .keystorePassword("fakePasswordForTests") - .trustStorePath(path("/config/cloud/trustStore.jks").toString()) - .trustStorePassword("fakePasswordForTests2")); - - public CloudConfigFactoryTest() throws URISyntaxException {} - - @Test - public void should_load_config_from_local_filesystem() throws Exception { - // given - URL configFile = getClass().getResource(BUNDLE_PATH); - mockProxyMetadataService(jsonMetadata()); - // when - CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - CloudConfig cloudConfig = cloudConfigFactory.createCloudConfig(configFile); - // then - assertCloudConfig(cloudConfig); - } - - @Test - public void should_load_config_from_external_location() throws Exception { - // given - mockHttpSecureBundle(secureBundle()); - mockProxyMetadataService(jsonMetadata()); - // when - URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); - CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - CloudConfig cloudConfig = cloudConfigFactory.createCloudConfig(configFile); - // then - assertCloudConfig(cloudConfig); - } - - @Test - public void should_throw_when_bundle_not_found() throws Exception { - // given - stubFor(any(urlEqualTo(BUNDLE_PATH)).willReturn(aResponse().withStatus(404))); - // when - URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); - CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile)); - assertThat(t) - .isInstanceOf(FileNotFoundException.class) - .hasMessageContaining(configFile.toExternalForm()); - } - - @Test - public void should_throw_when_bundle_not_readable() throws Exception { - // given - mockHttpSecureBundle("not a zip file".getBytes(StandardCharsets.UTF_8)); - // when - URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); - CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile)); - assertThat(t) - .isInstanceOf(IllegalStateException.class) - .hasMessageContaining("Invalid bundle: missing file config.json"); - } - - @Test - public void should_throw_when_metadata_not_found() throws Exception { - // given - mockHttpSecureBundle(secureBundle()); - stubFor(any(urlPathEqualTo("/metadata")).willReturn(aResponse().withStatus(404))); - // when - URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); - CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile)); - assertThat(t).isInstanceOf(FileNotFoundException.class).hasMessageContaining("metadata"); - } - - @Test - public void should_throw_when_metadata_not_readable() throws Exception { - // given - mockHttpSecureBundle(secureBundle()); - mockProxyMetadataService("not a valid json payload"); - // when - URL configFile = new URL("http", "localhost", wireMockRule.port(), BUNDLE_PATH); - CloudConfigFactory cloudConfigFactory = new CloudConfigFactory(); - Throwable t = catchThrowable(() -> cloudConfigFactory.createCloudConfig(configFile)); - assertThat(t).isInstanceOf(JsonParseException.class).hasMessageContaining("Unrecognized token"); - } - - private void mockHttpSecureBundle(byte[] body) { - stubFor( - any(urlEqualTo(BUNDLE_PATH)) - .willReturn( - aResponse() - .withStatus(200) - .withHeader("Content-Type", "application/octet-stream") - .withBody(body))); - } - - private void mockProxyMetadataService(String jsonMetadata) { - stubFor( - any(urlPathEqualTo("/metadata")) - .willReturn( - aResponse() - .withStatus(200) - .withHeader("Content-Type", "application/json") - .withBody(jsonMetadata))); - } - - private byte[] secureBundle() throws IOException, URISyntaxException { - return Files.readAllBytes(path(BUNDLE_PATH)); - } - - private String jsonMetadata() throws IOException, URISyntaxException { - return Joiner.on('\n') - .join(Files.readAllLines(path("/config/cloud/metadata.json"), StandardCharsets.UTF_8)); - } - - private Path path(String resource) throws URISyntaxException { - return Paths.get(getClass().getResource(resource).toURI()); - } - - private void assertCloudConfig(CloudConfig config) { - InetSocketAddress expectedProxyAddress = InetSocketAddress.createUnresolved("localhost", 30002); - assertThat(config.getLocalDatacenter()).isEqualTo("dc1"); - assertThat(config.getProxyAddress()).isEqualTo(expectedProxyAddress); - assertThat(config.getEndPoints()).extracting("proxyAddress").containsOnly(expectedProxyAddress); - assertThat(config.getEndPoints()) - .extracting("serverName") - .containsExactly( - "4ac06655-f861-49f9-881e-3fee22e69b94", - "2af7c253-3394-4a0d-bfac-f1ad81b5154d", - "b17b6e2a-3f48-4d6a-81c1-20a0a1f3192a"); - assertThat(config.getSslEngineFactory()).isNotNull().isInstanceOf(SniSslEngineFactory.class); - } - - static { - javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier( - (hostname, sslSession) -> hostname.equals("localhost")); - } - - // see https://github.com/tomakehurst/wiremock/issues/874 - private static class HttpsServerFactory implements HttpServerFactory { - @Override - public HttpServer buildHttpServer( - Options options, - AdminRequestHandler adminRequestHandler, - StubRequestHandler stubRequestHandler) { - return new JettyHttpServer(options, adminRequestHandler, stubRequestHandler) { - @Override - protected ServerConnector createServerConnector( - String bindAddress, - JettySettings jettySettings, - int port, - NetworkTrafficListener listener, - ConnectionFactory... connectionFactories) { - if (port == options.httpsSettings().port()) { - SslConnectionFactory sslConnectionFactory = - (SslConnectionFactory) connectionFactories[0]; - SslContextFactory sslContextFactory = sslConnectionFactory.getSslContextFactory(); - sslContextFactory.setKeyStorePassword(options.httpsSettings().keyStorePassword()); - connectionFactories = - new ConnectionFactory[] {sslConnectionFactory, connectionFactories[1]}; - } - return super.createServerConnector( - bindAddress, jettySettings, port, listener, connectionFactories); - } - }; - } - } -} diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/config/typesafe/TypeSafeDriverConfigOverrideDefaultsTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/config/typesafe/TypeSafeDriverConfigOverrideDefaultsTest.java deleted file mode 100644 index 2f2f0a9b3c1..00000000000 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/config/typesafe/TypeSafeDriverConfigOverrideDefaultsTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.internal.core.config.typesafe; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverExecutionProfile; -import com.datastax.oss.driver.api.core.config.DriverOption; -import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; -import java.time.Duration; -import java.util.Map; -import org.junit.Test; - -/** Focuses on {@link TypesafeDriverConfig#overrideDefaults(Map)}. */ -public class TypeSafeDriverConfigOverrideDefaultsTest { - - @Test - public void should_replace_if_value_comes_from_reference() { - // Given - TypesafeDriverConfig config = config(""); - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); - - // When - config.overrideDefaults( - ImmutableMap.of(DefaultDriverOption.REQUEST_CONSISTENCY, "LOCAL_QUORUM")); - - // Then - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_QUORUM"); - } - - @Test - public void should_replace_multiple_times() { - // Given - TypesafeDriverConfig config = config(""); - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); - - // When - config.overrideDefaults( - ImmutableMap.of(DefaultDriverOption.REQUEST_CONSISTENCY, "LOCAL_QUORUM")); - config.overrideDefaults(ImmutableMap.of(DefaultDriverOption.REQUEST_CONSISTENCY, "TWO")); - - // Then - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("TWO"); - } - - @Test - public void should_not_replace_if_overridden_from_application() { - // Given - TypesafeDriverConfig config = - config("datastax-java-driver.basic.request.consistency = LOCAL_ONE"); - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); - - // When - config.overrideDefaults( - ImmutableMap.of(DefaultDriverOption.REQUEST_CONSISTENCY, "LOCAL_QUORUM")); - - // Then - // not replaced because it was set explictly in application.conf - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); - } - - @Test - public void should_handle_reloads() { - // Given - TypesafeDriverConfig config = config(""); - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); - - // When - config.overrideDefaults( - ImmutableMap.of(DefaultDriverOption.REQUEST_CONSISTENCY, "LOCAL_QUORUM")); - reload(config, ""); - - // Then - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_QUORUM"); - - // When - reload(config, "datastax-java-driver.basic.request.consistency = ONE"); - - // Then - // overridden default not used anymore if the reload detected a user change - assertThat(config.getDefaultProfile().getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("ONE"); - } - - @Test - public void should_ignore_non_existent_option() { - // Given - TypesafeDriverConfig config = config(""); - DriverOption nonExistent = () -> "non existent"; - - // When - config.overrideDefaults(ImmutableMap.of(nonExistent, "IRRELEVANT")); - - // Then - assertThat(config.getDefaultProfile().isDefined(nonExistent)).isFalse(); - } - - @Test - public void should_handle_profiles() { - // Given - TypesafeDriverConfig config = - config( - "datastax-java-driver.profiles.profile1.basic.request.consistency = TWO\n" - + "datastax-java-driver.profiles.profile2.basic.request.timeout = 5 seconds"); - DriverExecutionProfile profile1 = config.getProfile("profile1"); - DriverExecutionProfile profile2 = config.getProfile("profile2"); - DriverExecutionProfile derivedProfile21 = - profile2.withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(10)); - DriverExecutionProfile derivedProfile22 = - profile2.withString(DefaultDriverOption.REQUEST_CONSISTENCY, "QUORUM"); - assertThat(profile1.getString(DefaultDriverOption.REQUEST_CONSISTENCY)).isEqualTo("TWO"); - assertThat(profile2.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); // inherited from default profile in reference.conf - assertThat(derivedProfile21.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_ONE"); // inherited from default profile in reference.conf - assertThat(derivedProfile22.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("QUORUM"); // overridden programmatically - - // When - config.overrideDefaults( - ImmutableMap.of(DefaultDriverOption.REQUEST_CONSISTENCY, "LOCAL_QUORUM")); - - // Then - // Unaffected because it was set manually in application.conf: - assertThat(profile1.getString(DefaultDriverOption.REQUEST_CONSISTENCY)).isEqualTo("TWO"); - // Affected because it was using the default from reference.conf: - assertThat(profile2.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_QUORUM"); - // Same: - assertThat(derivedProfile21.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("LOCAL_QUORUM"); - // Unaffected because it was overridden programmatically: - assertThat(derivedProfile22.getString(DefaultDriverOption.REQUEST_CONSISTENCY)) - .isEqualTo("QUORUM"); - } - - // Builds a config based on reference.conf + the given application.conf overrides - private TypesafeDriverConfig config(String application) { - return new TypesafeDriverConfig(rawConfig(application)); - } - - private boolean reload(TypesafeDriverConfig config, String newApplication) { - return config.reload(rawConfig(newApplication)); - } - - private Config rawConfig(String application) { - ConfigFactory.invalidateCaches(); - return ConfigFactory.parseString(application) - .withFallback(ConfigFactory.defaultReference()) - .resolve() - .getConfig(DefaultDriverConfigLoader.DEFAULT_ROOT_PATH); - } -} diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java index 083302494aa..fe2c92e2667 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/context/ClientRoutesConfigFromFileTest.java @@ -27,7 +27,6 @@ import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader; import com.datastax.oss.driver.internal.core.metadata.ClientRoutesTopologyMonitor; import com.typesafe.config.ConfigFactory; -import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import org.junit.After; @@ -72,11 +71,6 @@ public void tearDown() { * reference.conf} merged on top of the supplied extra HOCON string. */ private DefaultDriverContext contextFromHocon(String extraHocon) { - return contextFromHocon(extraHocon, ProgrammaticArguments.builder().build()); - } - - private DefaultDriverContext contextFromHocon( - String extraHocon, ProgrammaticArguments programmaticArguments) { DriverConfigLoader loader = new DefaultDriverConfigLoader( () -> { @@ -86,7 +80,8 @@ private DefaultDriverContext contextFromHocon( ConfigFactory.defaultReference() .getConfig(DefaultDriverConfigLoader.DEFAULT_ROOT_PATH)); }); - DefaultDriverContext ctx = new DefaultDriverContext(loader, programmaticArguments); + DefaultDriverContext ctx = + new DefaultDriverContext(loader, ProgrammaticArguments.builder().build()); createdContexts.add(ctx); return ctx; } @@ -238,25 +233,6 @@ public void should_allow_client_routes_with_qualified_passthrough_address_transl assertThat(ctx.getTopologyMonitor()).isInstanceOf(ClientRoutesTopologyMonitor.class); } - @Test - public void should_throw_when_secure_connect_bundle_and_client_routes_both_configured() { - ProgrammaticArguments args = - ProgrammaticArguments.builder() - .withCloudProxyAddress(new InetSocketAddress("127.0.0.1", 9042)) - .build(); - DefaultDriverContext ctx = - contextFromHocon( - "advanced.client-routes.endpoints = [" - + " { connection-id = \"11111111-1111-1111-1111-111111111111\" }" - + "]", - args); - - assertThatThrownBy(ctx::getTopologyMonitor) - .isInstanceOf(IllegalStateException.class) - .hasMessageContaining("secure connect bundle") - .hasMessageContaining("client routes"); - } - @Test public void should_throw_when_client_routes_and_unloadable_address_translator_class() { DefaultDriverContext ctx = diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java index 4122f82a399..5616734e178 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/context/DefaultDriverConfigReporterTest.java @@ -51,7 +51,6 @@ import com.datastax.oss.driver.internal.core.specex.NoSpeculativeExecutionPolicy; import com.datastax.oss.driver.internal.core.ssl.DefaultSslEngineFactory; import com.datastax.oss.driver.internal.core.ssl.JdkSslHandlerFactory; -import com.datastax.oss.driver.internal.core.ssl.SniSslEngineFactory; import com.datastax.oss.driver.internal.core.ssl.SslHandlerFactory; import com.datastax.oss.driver.internal.core.time.AtomicTimestampGenerator; import com.datastax.oss.driver.internal.core.time.ServerSideTimestampGenerator; @@ -1534,7 +1533,6 @@ public void should_report_every_built_in_engine_factory() throws Exception { // configured one, to the whole option-to-field-to-report chain. assertThat(hostnameVerificationOf(new DefaultSslEngineFactory(policyConstructionContext()))) .isTrue(); - assertThat(hostnameVerificationOf(new SniSslEngineFactory(SSLContext.getDefault()))).isTrue(); assertThat(hostnameVerificationOf(new ProgrammaticSslEngineFactory(SSLContext.getDefault()))) .isFalse(); assertThat( diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java index 892715a47c3..744438c7f71 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/DefaultTopologyMonitorTest.java @@ -52,10 +52,10 @@ import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableSet; import com.datastax.oss.driver.shaded.guava.common.collect.Maps; +import com.datastax.oss.driver.shaded.guava.common.collect.Streams; import com.datastax.oss.protocol.internal.Message; import com.datastax.oss.protocol.internal.ProtocolConstants; import com.datastax.oss.protocol.internal.response.Error; -import com.google.common.collect.Streams; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java index 03d63230992..252ebab38eb 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metadata/schema/TableMetadataTest.java @@ -23,9 +23,9 @@ import com.datastax.oss.driver.api.core.metadata.schema.TableMetadata; import com.datastax.oss.driver.internal.core.type.DefaultVectorType; import com.datastax.oss.driver.internal.core.type.PrimitiveType; +import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableList; import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import com.datastax.oss.protocol.internal.ProtocolConstants.DataType; -import com.google.common.collect.ImmutableList; import java.util.UUID; import org.junit.Test; diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java index 339f9235dc2..8d7998c21f5 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/DefaultMetricIdTest.java @@ -19,7 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.google.common.collect.ImmutableMap; +import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import org.junit.Test; public class DefaultMetricIdTest { diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java index 809a7419ba4..cbc560ee35b 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/metrics/TaggingMetricIdGeneratorTest.java @@ -28,7 +28,7 @@ import com.datastax.oss.driver.api.core.metrics.DefaultNodeMetric; import com.datastax.oss.driver.api.core.metrics.DefaultSessionMetric; import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import com.google.common.collect.ImmutableMap; +import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java index d151da309c1..c493ccc2080 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/protocol/BytesToSegmentDecoderTest.java @@ -21,10 +21,10 @@ import static org.assertj.core.api.Assertions.fail; import com.datastax.oss.driver.api.core.connection.CrcMismatchException; +import com.datastax.oss.driver.shaded.guava.common.base.Strings; import com.datastax.oss.protocol.internal.Compressor; import com.datastax.oss.protocol.internal.Segment; import com.datastax.oss.protocol.internal.SegmentCodec; -import com.google.common.base.Strings; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; diff --git a/core/src/test/java/com/datastax/oss/driver/internal/core/tracker/RequestIdGeneratorTest.java b/core/src/test/java/com/datastax/oss/driver/internal/core/tracker/RequestIdGeneratorTest.java index fb1883e125f..26b5ec35b91 100644 --- a/core/src/test/java/com/datastax/oss/driver/internal/core/tracker/RequestIdGeneratorTest.java +++ b/core/src/test/java/com/datastax/oss/driver/internal/core/tracker/RequestIdGeneratorTest.java @@ -22,7 +22,6 @@ import com.datastax.oss.driver.api.core.cql.Statement; import com.datastax.oss.driver.api.core.tracker.RequestIdGenerator; import com.datastax.oss.driver.internal.core.context.InternalDriverContext; -import org.apache.commons.lang3.RandomStringUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -70,11 +69,4 @@ public void w3c_generator_default_payloadkey() { assertThat(w3cGenerator.getCustomPayloadKey()) .isEqualTo(RequestIdGenerator.DEFAULT_PAYLOAD_KEY); } - - @Test - public void w3c_generator_provided_payloadkey() { - String someString = RandomStringUtils.random(12); - W3CContextRequestIdGenerator w3cGenerator = new W3CContextRequestIdGenerator(someString); - assertThat(w3cGenerator.getCustomPayloadKey()).isEqualTo(someString); - } } diff --git a/core/src/test/resources/config/cloud/creds.zip b/core/src/test/resources/config/cloud/creds.zip deleted file mode 100644 index 3b5d1cb1cbd9d1d805eb3aaf06ace9b224d45b87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9805 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 diff --git a/core/src/test/resources/config/cloud/identity.jks b/core/src/test/resources/config/cloud/identity.jks deleted file mode 100644 index bac5bbaa965be8d543497047d5e05c1f3c12238a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2493 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 GqwxSGx?Cdw diff --git a/examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java b/examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java deleted file mode 100644 index 7f4833c46d8..00000000000 --- a/examples/src/main/java/com/datastax/oss/driver/examples/astra/AstraReadCassandraVersion.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.examples.astra; - -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import com.datastax.oss.driver.api.core.cql.Row; -import java.nio.file.Paths; - -/** - * Connects to a DataStax Astra cluster and extracts basic information from it. - * - *

Preconditions: - * - *

    - *
  • A DataStax Astra cluster is running and accessible. - *
  • A DataStax Astra secure connect bundle for the running cluster. - *
- * - *

Side effects: none. - * - * @see - * Creating an Astra Database (GCP) - * @see - * Providing access to Astra databases (GCP) - * @see - * Obtaining Astra secure connect bundle (GCP) - * @see Java Driver online - * manual - */ -public class AstraReadCassandraVersion { - - public static void main(String[] args) { - - // The Session is what you use to execute queries. It is thread-safe and should be - // reused. - try (CqlSession session = - CqlSession.builder() - // Change the path here to the secure connect bundle location (see javadocs above) - .withCloudSecureConnectBundle(Paths.get("/path/to/secure-connect-database_name.zip")) - // Change the user_name and password here for the Astra instance - .withAuthCredentials("user_name", "fakePasswordForTests") - // Uncomment the next line to use a specific keyspace - // .withKeyspace("keyspace_name") - .build()) { - - // We use execute to send a query to Cassandra. This returns a ResultSet, which - // is essentially a collection of Row objects. - ResultSet rs = session.execute("select release_version from system.local WHERE key='local'"); - // Extract the first row (which is the only one in this case). - Row row = rs.one(); - - // Extract the value of the first (and only) column from the row. - assert row != null; - String releaseVersion = row.getString("release_version"); - System.out.printf("Cassandra version is: %s%n", releaseVersion); - } - // The try-with-resources block automatically close the session after we’re done with it. - // This step is important because it frees underlying resources (TCP connections, thread - // pools...). In a real application, you would typically do this at shutdown - // (for example, when undeploying your webapp). - } -} diff --git a/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java b/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java index 6284b16eac1..0f78821ee07 100644 --- a/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java +++ b/examples/src/main/java/com/datastax/oss/driver/examples/mapper/KillrVideoMapperExample.java @@ -112,9 +112,8 @@ public static void main(String[] args) { Video video = new Video(); video.setUserid(user.getUserid()); - video.setName( - "Getting Started with DataStax Apache Cassandra as a Service on DataStax Astra"); - video.setLocation("https://www.youtube.com/watch?v=68xzKpcZURA"); + video.setName("Getting Started with ScyllaDB Cloud"); + video.setLocation("https://www.youtube.com/watch?v=jnWDMiuy9hM"); Set tags = new HashSet<>(); tags.add("apachecassandra"); tags.add("nosql"); @@ -146,8 +145,7 @@ public static void main(String[] args) { // Update the existing video: Video template = new Video(); template.setVideoid(video.getVideoid()); - template.setName( - "Getting Started with DataStax Apache Cassandra® as a Service on DataStax Astra"); + template.setName("Getting Started with ScyllaDB using the Java driver"); videoDao.update(template); // Reload the whole entity and check the fields video = videoDao.get(video.getVideoid()); diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index a8940cc5cb3..1972e767a0b 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -178,11 +178,6 @@ api-ldap-codec-standalone test - - com.github.tomakehurst - wiremock - test - com.scylladb.oss.simulacron simulacron-native-server diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java deleted file mode 100644 index 81a191779ba..00000000000 --- a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/CloudIT.java +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.api.core.cloud; - -import static com.datastax.oss.driver.internal.core.util.LoggerTest.setupTestLogger; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.any; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import com.datastax.oss.driver.api.core.AllNodesFailedException; -import com.datastax.oss.driver.api.core.CqlSession; -import com.datastax.oss.driver.api.core.auth.AuthenticationException; -import com.datastax.oss.driver.api.core.config.DefaultDriverOption; -import com.datastax.oss.driver.api.core.config.DriverConfigLoader; -import com.datastax.oss.driver.api.core.cql.ResultSet; -import com.datastax.oss.driver.api.core.session.SessionBuilder; -import com.datastax.oss.driver.api.testinfra.session.SessionUtils; -import com.datastax.oss.driver.categories.IsolatedTests; -import com.datastax.oss.driver.internal.core.config.cloud.CloudConfigFactory; -import com.datastax.oss.driver.internal.core.ssl.DefaultSslEngineFactory; -import com.datastax.oss.driver.internal.core.util.LoggerTest; -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetSocketAddress; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.NoSuchAlgorithmException; -import java.util.Collections; -import java.util.List; -import javax.net.ssl.SSLContext; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -@Category(IsolatedTests.class) -@Ignore("Disabled because it is causing trouble in Jenkins CI") -public class CloudIT { - - private static final String BUNDLE_URL_PATH = "/certs/bundles/creds.zip"; - - @ClassRule public static SniProxyRule proxyRule = new SniProxyRule(); - - // Used only to host the secure connect bundle, for tests that require external URLs - @Rule - public WireMockRule wireMockRule = - new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort()); - - @Test - public void should_connect_to_proxy_using_path() { - ResultSet set; - Path bundle = proxyRule.getProxy().getDefaultBundlePath(); - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withCloudSecureConnectBundle(bundle) - .build()) { - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_and_log_info_that_config_json_with_username_password_was_provided() { - ResultSet set; - Path bundle = proxyRule.getProxy().getDefaultBundlePath(); - LoggerTest.LoggerSetup logger = setupTestLogger(CloudConfigFactory.class, Level.INFO); - - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withCloudSecureConnectBundle(bundle) - .build()) { - set = session.execute("select * from system.local where key='local'"); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "The bundle contains config.json with username and/or password. Providing it in the bundle is deprecated and ignored."); - } - assertThat(set).isNotNull(); - } - - @Test - public void - should_fail_with_auth_error_when_connecting_using_bundle_with_username_password_in_config_json() { - Path bundle = proxyRule.getProxy().getDefaultBundlePath(); - - // fails with auth error because username/password from config.json is ignored - AllNodesFailedException exception = null; - try { - CqlSession.builder().withCloudSecureConnectBundle(bundle).build(); - } catch (AllNodesFailedException ex) { - exception = ex; - } - assertThat(exception).isNotNull(); - List errors = exception.getAllErrors().values().iterator().next(); - Throwable firstError = errors.get(0); - assertThat(firstError).isInstanceOf(AuthenticationException.class); - } - - @Test - public void should_connect_to_proxy_without_credentials() { - ResultSet set; - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - try (CqlSession session = - CqlSession.builder() - .withCloudSecureConnectBundle(bundle) - .withAuthCredentials("cassandra", "cassandra") - .build()) { - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_to_proxy_using_non_normalized_path() { - Path bundle = proxyRule.getProxy().getBundlesRootPath().resolve("../bundles/creds-v1.zip"); - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withCloudSecureConnectBundle(bundle) - .build()) { - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_to_proxy_using_input_stream() throws IOException { - InputStream bundle = Files.newInputStream(proxyRule.getProxy().getDefaultBundlePath()); - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withCloudSecureConnectBundle(bundle) - .build()) { - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_to_proxy_using_URL() throws IOException { - // given - byte[] bundle = Files.readAllBytes(proxyRule.getProxy().getDefaultBundlePath()); - stubFor( - any(urlEqualTo(BUNDLE_URL_PATH)) - .willReturn( - aResponse() - .withStatus(200) - .withHeader("Content-Type", "application/octet-stream") - .withBody(bundle))); - URL bundleUrl = - new URL(String.format("http://localhost:%d%s", wireMockRule.port(), BUNDLE_URL_PATH)); - - // when - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withCloudSecureConnectBundle(bundleUrl) - .build()) { - - // then - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_to_proxy_using_absolute_path_provided_in_the_session_setting() { - // given - String bundle = proxyRule.getProxy().getDefaultBundlePath().toString(); - DriverConfigLoader loader = - DriverConfigLoader.programmaticBuilder() - .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundle) - .build(); - // when - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withConfigLoader(loader) - .build()) { - - // then - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_to_proxy_using_non_normalized_path_provided_in_the_session_setting() { - // given - String bundle = - proxyRule.getProxy().getBundlesRootPath().resolve("../bundles/creds-v1.zip").toString(); - DriverConfigLoader loader = - DriverConfigLoader.programmaticBuilder() - .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundle) - .build(); - // when - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withConfigLoader(loader) - .build()) { - - // then - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void - should_connect_to_proxy_using_url_with_file_protocol_provided_in_the_session_setting() { - // given - String bundle = proxyRule.getProxy().getDefaultBundlePath().toString(); - DriverConfigLoader loader = - DriverConfigLoader.programmaticBuilder() - .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundle) - .build(); - // when - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withConfigLoader(loader) - .build()) { - - // then - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void should_connect_to_proxy_using_url_with_http_protocol_provided_in_the_session_setting() - throws IOException { - // given - byte[] bundle = Files.readAllBytes(proxyRule.getProxy().getDefaultBundlePath()); - stubFor( - any(urlEqualTo(BUNDLE_URL_PATH)) - .willReturn( - aResponse() - .withStatus(200) - .withHeader("Content-Type", "application/octet-stream") - .withBody(bundle))); - String bundleUrl = String.format("http://localhost:%d%s", wireMockRule.port(), BUNDLE_URL_PATH); - DriverConfigLoader loader = - DriverConfigLoader.programmaticBuilder() - .withString(DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE, bundleUrl) - .build(); - // when - ResultSet set; - try (CqlSession session = - CqlSession.builder() - .withAuthCredentials("cassandra", "cassandra") - .withConfigLoader(loader) - .build()) { - - // then - set = session.execute("select * from system.local where key='local'"); - } - assertThat(set).isNotNull(); - } - - @Test - public void - should_connect_and_log_info_when_contact_points_and_secure_bundle_used_programmatic() { - // given - LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO); - - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - - try (CqlSession session = - CqlSession.builder() - .withCloudSecureConnectBundle(bundle) - .addContactPoint(new InetSocketAddress("127.0.0.1", 9042)) - .withAuthCredentials("cassandra", "cassandra") - .build(); ) { - - // when - ResultSet set = session.execute("select * from system.local where key='local'"); - // then - assertThat(set).isNotNull(); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "Both a secure connect bundle and contact points were provided. These are mutually exclusive. The contact points from the secure bundle will have priority."); - - } finally { - logger.close(); - } - } - - @Test - public void should_connect_and_log_info_when_contact_points_and_secure_bundle_used_config() { - // given - LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO); - - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withStringList( - DefaultDriverOption.CONTACT_POINTS, Collections.singletonList("localhost:9042")) - .build(); - - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - - try (CqlSession session = - CqlSession.builder() - .withConfigLoader(loader) - .withCloudSecureConnectBundle(bundle) - .withAuthCredentials("cassandra", "cassandra") - .build(); ) { - - // when - ResultSet set = session.execute("select * from system.local where key='local'"); - // then - assertThat(set).isNotNull(); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "Both a secure connect bundle and contact points were provided. These are mutually exclusive. The contact points from the secure bundle will have priority."); - - } finally { - logger.close(); - } - } - - @Test - public void should_connect_and_log_info_when_ssl_context_and_secure_bundle_used_programmatic() - throws NoSuchAlgorithmException { - // given - LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO); - - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - - try (CqlSession session = - CqlSession.builder() - .withCloudSecureConnectBundle(bundle) - .withAuthCredentials("cassandra", "cassandra") - .withSslContext(SSLContext.getInstance("SSL")) - .build()) { - // when - ResultSet set = session.execute("select * from system.local where key='local'"); - // then - assertThat(set).isNotNull(); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "Both a secure connect bundle and SSL options were provided. They are mutually exclusive. The SSL options from the secure bundle will have priority."); - } finally { - logger.close(); - } - } - - @Test - public void should_error_when_ssl_context_and_secure_bundle_used_config() - throws NoSuchAlgorithmException { - // given - LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO); - - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withBoolean(DefaultDriverOption.RECONNECT_ON_INIT, true) - .withClass(DefaultDriverOption.SSL_ENGINE_FACTORY_CLASS, DefaultSslEngineFactory.class) - .build(); - - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - - try (CqlSession session = - CqlSession.builder() - .withConfigLoader(loader) - .withCloudSecureConnectBundle(bundle) - .withAuthCredentials("cassandra", "cassandra") - .build()) { - // when - ResultSet set = session.execute("select * from system.local where key='local'"); - // then - assertThat(set).isNotNull(); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "Both a secure connect bundle and SSL options were provided. They are mutually exclusive. The SSL options from the secure bundle will have priority."); - } finally { - logger.close(); - } - } - - @Test - public void - should_connect_and_log_info_when_local_data_center_and_secure_bundle_used_programmatic() { - // given - LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO); - - DriverConfigLoader loader = - SessionUtils.configLoaderBuilder() - .withString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, "dc-ignore") - .build(); - - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - - try (CqlSession session = - CqlSession.builder() - .withCloudSecureConnectBundle(bundle) - .withConfigLoader(loader) - .withAuthCredentials("cassandra", "cassandra") - .build(); ) { - - // when - ResultSet set = session.execute("select * from system.local where key='local'"); - // then - assertThat(set).isNotNull(); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "Both a secure connect bundle and a local datacenter were provided. They are mutually exclusive. The local datacenter from the secure bundle will have priority."); - - } finally { - logger.close(); - } - } - - @Test - public void should_connect_and_log_info_when_local_data_center_and_secure_bundle_used_config() { - // given - LoggerTest.LoggerSetup logger = setupTestLogger(SessionBuilder.class, Level.INFO); - - Path bundle = proxyRule.getProxy().getBundleWithoutCredentialsPath(); - - try (CqlSession session = - CqlSession.builder() - .withCloudSecureConnectBundle(bundle) - .withLocalDatacenter("dc-ignored") - .withAuthCredentials("cassandra", "cassandra") - .build(); ) { - - // when - ResultSet set = session.execute("select * from system.local where key='local'"); - // then - assertThat(set).isNotNull(); - verify(logger.appender, timeout(500).atLeast(1)) - .doAppend(logger.loggingEventCaptor.capture()); - assertThat( - logger.loggingEventCaptor.getAllValues().stream() - .map(ILoggingEvent::getFormattedMessage)) - .contains( - "Both a secure connect bundle and a local datacenter were provided. They are mutually exclusive. The local datacenter from the secure bundle will have priority."); - - } finally { - logger.close(); - } - } -} diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java b/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java deleted file mode 100644 index fa009de78ae..00000000000 --- a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyRule.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.api.core.cloud; - -import org.junit.rules.ExternalResource; - -public class SniProxyRule extends ExternalResource { - - private final SniProxyServer proxy; - - public SniProxyRule() { - proxy = new SniProxyServer(); - } - - @Override - protected void before() { - proxy.startProxy(); - } - - @Override - protected void after() { - proxy.stopProxy(); - } - - public SniProxyServer getProxy() { - return proxy; - } -} diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java b/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java deleted file mode 100644 index 809354a7daf..00000000000 --- a/integration-tests/src/test/java/com/datastax/oss/driver/api/core/cloud/SniProxyServer.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.datastax.oss.driver.api.core.cloud; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.concurrent.TimeUnit; -import org.apache.commons.exec.CommandLine; -import org.apache.commons.exec.DefaultExecutor; -import org.apache.commons.exec.ExecuteStreamHandler; -import org.apache.commons.exec.ExecuteWatchdog; -import org.apache.commons.exec.Executor; -import org.apache.commons.exec.LogOutputStream; -import org.apache.commons.exec.PumpStreamHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SniProxyServer { - - private static final Logger LOG = LoggerFactory.getLogger(SniProxyServer.class); - - private final Path proxyPath; - private final Path bundlesRootPath; - private final Path defaultBundlePath; - private final Path bundleWithoutCredentialsPath; - private final Path bundleWithoutClientCertificatesPath; - private final Path bundleWithInvalidCAPath; - private final Path bundleWithUnreachableMetadataServicePath; - - private volatile boolean running = false; - - public SniProxyServer() { - this(Paths.get(System.getProperty("proxy.path", "./"))); - } - - public SniProxyServer(Path proxyPath) { - this.proxyPath = proxyPath.normalize().toAbsolutePath(); - bundlesRootPath = proxyPath.resolve("certs/bundles/"); - defaultBundlePath = bundlesRootPath.resolve("creds-v1.zip"); - bundleWithoutCredentialsPath = bundlesRootPath.resolve("creds-v1-wo-creds.zip"); - bundleWithoutClientCertificatesPath = bundlesRootPath.resolve("creds-v1-wo-cert.zip"); - bundleWithInvalidCAPath = bundlesRootPath.resolve("creds-v1-invalid-ca.zip"); - bundleWithUnreachableMetadataServicePath = bundlesRootPath.resolve("creds-v1-unreachable.zip"); - } - - public void startProxy() { - CommandLine run = CommandLine.parse(proxyPath + "/run.sh"); - execute(run); - running = true; - } - - public void stopProxy() { - if (running) { - CommandLine findImageId = - CommandLine.parse("docker ps -a -q --filter ancestor=single_endpoint"); - String id = execute(findImageId); - CommandLine stop = CommandLine.parse("docker kill " + id); - execute(stop); - running = false; - } - } - - /** @return The root folder of the SNI proxy server docker image. */ - public Path getProxyPath() { - return proxyPath; - } - - /** - * @return The root folder where secure connect bundles exposed by this SNI proxy for testing - * purposes can be found. - */ - public Path getBundlesRootPath() { - return bundlesRootPath; - } - - /** - * @return The default secure connect bundle. It contains credentials and all certificates - * required to connect. - */ - public Path getDefaultBundlePath() { - return defaultBundlePath; - } - - /** @return A secure connect bundle without credentials in config.json. */ - public Path getBundleWithoutCredentialsPath() { - return bundleWithoutCredentialsPath; - } - - /** @return A secure connect bundle without client certificates (no identity.jks). */ - public Path getBundleWithoutClientCertificatesPath() { - return bundleWithoutClientCertificatesPath; - } - - /** @return A secure connect bundle with an invalid Certificate Authority. */ - public Path getBundleWithInvalidCAPath() { - return bundleWithInvalidCAPath; - } - - /** @return A secure connect bundle with an invalid address for the Proxy Metadata Service. */ - public Path getBundleWithUnreachableMetadataServicePath() { - return bundleWithUnreachableMetadataServicePath; - } - - private String execute(CommandLine cli) { - LOG.debug("Executing: " + cli); - ExecuteWatchdog watchDog = new ExecuteWatchdog(TimeUnit.MINUTES.toMillis(10)); - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - try (LogOutputStream errStream = - new LogOutputStream() { - @Override - protected void processLine(String line, int logLevel) { - LOG.error("sniendpointerr> {}", line); - } - }) { - Executor executor = new DefaultExecutor(); - ExecuteStreamHandler streamHandler = new PumpStreamHandler(outStream, errStream); - executor.setStreamHandler(streamHandler); - executor.setWatchdog(watchDog); - executor.setWorkingDirectory(proxyPath.toFile()); - int retValue = executor.execute(cli); - if (retValue != 0) { - LOG.error("Non-zero exit code ({}) returned from executing ccm command: {}", retValue, cli); - } - return outStream.toString(); - } catch (IOException ex) { - if (watchDog.killedProcess()) { - throw new RuntimeException("The command '" + cli + "' was killed after 10 minutes"); - } else { - throw new RuntimeException("The command '" + cli + "' failed to execute", ex); - } - } - } -} diff --git a/manual/core/connectivity/client_routes/README.md b/manual/core/connectivity/client_routes/README.md index 5e8b2b63973..2cb6b90cb3a 100644 --- a/manual/core/connectivity/client_routes/README.md +++ b/manual/core/connectivity/client_routes/README.md @@ -27,7 +27,7 @@ through the address the node broadcasts. * `advanced.client-routes` in the configuration, or `SessionBuilder.withClientRoutesConfig()`. * disabled by default. Requires ScyllaDB Enterprise 2026.1 or later. -* mutually exclusive with `advanced.address-translator` and with cloud secure connect bundles. +* mutually exclusive with `advanced.address-translator`. ----- @@ -122,8 +122,8 @@ Refreshing the route map does **not** flush the DNS cache; new hostnames are res - Requires ScyllaDB Enterprise ≥ 2026.1 with `system.client_routes` support (scylladb/scylladb#27323). Not yet available on ScyllaDB OSS. - Not supported on Apache Cassandra. -- Mutually exclusive with a custom `AddressTranslator` and with cloud secure connect bundles: - configuring either one alongside client routes throws an `IllegalStateException`. +- Configuring a custom `AddressTranslator` alongside client routes throws an + `IllegalStateException`. A deployment that is *not* fronted by a per-node endpoint mapping -- one proxy hostname for the whole cluster, one proxy per subnet, or EC2 multi-region -- needs an address translator instead, and diff --git a/pom.xml b/pom.xml index 86a4f798796..54f9596a91d 100644 --- a/pom.xml +++ b/pom.xml @@ -508,11 +508,6 @@ api-ldap-codec-standalone 2.1.7 - - com.github.tomakehurst - wiremock - 2.25.0 - org.graalvm.sdk graal-sdk diff --git a/upgrade_guide/README.md b/upgrade_guide/README.md index a56869dfe5b..4123c1cbdbb 100644 --- a/upgrade_guide/README.md +++ b/upgrade_guide/README.md @@ -19,6 +19,39 @@ under the License. ## Upgrade guide +### 4.19.2.3 + +#### DataStax Astra secure-connect-bundle support was removed + +This release intentionally removes the DataStax Astra secure-connect-bundle integration and its +public API. The following members are no longer available: + +- `SessionBuilder.withCloudSecureConnectBundle(Path)` +- `SessionBuilder.withCloudSecureConnectBundle(URL)` +- `SessionBuilder.withCloudSecureConnectBundle(InputStream)` +- `SessionBuilder.withCloudProxyAddress(InetSocketAddress)` +- `SessionBuilder.cloudConfigInputStream` (protected) +- `ProgrammaticArguments.getCloudProxyAddress()` +- `ProgrammaticArguments.Builder.withCloudProxyAddress(InetSocketAddress)` +- `SessionBuilder.ASTRA_PAYLOAD_KEY` +- `DefaultDriverOption.CLOUD_SECURE_CONNECT_BUNDLE` +- `TypedDriverOption.CLOUD_SECURE_CONNECT_BUNDLE` + +The old `datastax-java-driver.basic.cloud.secure-connect-bundle` configuration key is now an +unknown option and no longer supplies connection information. If that was the only connection +setting, the resulting configuration contains no contact points, so the driver falls back to its +default contact point, `127.0.0.1:9042`. + +This is an intentional binary- and source-compatibility break. This driver no longer has built-in +support for connecting to DataStax Astra. Plain contact points cannot replace an Astra secure +connect bundle because the bundle also provides TLS identity and trust material, metadata, and SNI +proxy routing. Applications that need Astra must use 4.19.2.2 or an earlier release that supports +secure connect bundles, or migrate to an Astra-compatible driver. + +For ScyllaDB deployments, configure explicit `basic.contact-points` or programmatic contact points. +For supported ScyllaDB private-endpoint deployments, use +[client routes](../manual/core/connectivity/client_routes/) together with an explicit contact point. + ### 4.19.2.2 #### The local-DC check no longer inspects contact points