Skip to content

Commit 559952f

Browse files
authored
feat: enable setting ipType connection option for r2dbc drivers (#937)
1 parent e4f7e82 commit 559952f

File tree

13 files changed

+565
-24
lines changed

13 files changed

+565
-24
lines changed

core/src/main/java/com/google/cloud/sql/core/CoreSocketFactory.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public final class CoreSocketFactory {
7878

7979
private static final Logger logger = Logger.getLogger(CoreSocketFactory.class.getName());
8080

81-
private static final String DEFAULT_IP_TYPES = "PUBLIC,PRIVATE";
81+
public static final String DEFAULT_IP_TYPES = "PUBLIC,PRIVATE";
8282

8383
// Test properties, not for end-user use. May be changed or removed without notice.
8484
private static final String API_ROOT_URL_PROPERTY = "_CLOUD_SQL_API_ROOT_URL";
@@ -152,25 +152,17 @@ public static synchronized CoreSocketFactory getInstance() throws IOException {
152152
return coreSocketFactory;
153153
}
154154

155-
private CloudSqlInstance getCloudSqlInstance(String instanceName, boolean enableIamAuth) {
156-
return instances.computeIfAbsent(
157-
instanceName,
158-
k -> {
159-
try {
160-
return new CloudSqlInstance(k, adminApi, enableIamAuth, credentialFactory, executor,
161-
localKeyPair);
162-
} catch (IOException e) {
163-
throw new RuntimeException(e);
164-
}
165-
});
155+
@VisibleForTesting
156+
CloudSqlInstance getCloudSqlInstance(String instanceName) {
157+
return getCloudSqlInstance(instanceName, false);
166158
}
167159

168-
private CloudSqlInstance getCloudSqlInstance(String instanceName) {
160+
private CloudSqlInstance getCloudSqlInstance(String instanceName, boolean enableIamAuth) {
169161
return instances.computeIfAbsent(
170162
instanceName,
171163
k -> {
172164
try {
173-
return new CloudSqlInstance(k, adminApi, false, credentialFactory, executor,
165+
return new CloudSqlInstance(k, adminApi, enableIamAuth, credentialFactory, executor,
174166
localKeyPair);
175167
} catch (IOException e) {
176168
throw new RuntimeException(e);
@@ -273,18 +265,28 @@ public static SslData getSslData(String csqlInstanceName, boolean enableIamAuth)
273265
return getInstance().getCloudSqlInstance(csqlInstanceName, enableIamAuth).getSslData();
274266
}
275267

268+
/**
269+
* Returns data that can be used to establish Cloud SQL SSL connection.
270+
*/
276271
public static SslData getSslData(String csqlInstanceName) throws IOException {
277272
return getSslData(csqlInstanceName, false);
278273
}
279274

280275
/**
281-
* Returns preferred ip address that can be used to establish Cloud SQL connection.
276+
* Returns default ip address that can be used to establish Cloud SQL connection.
282277
*/
283278
public static String getHostIp(String csqlInstanceName) throws IOException {
284279
return getInstance().getHostIp(csqlInstanceName, listIpTypes(DEFAULT_IP_TYPES));
285280
}
286281

287-
private String getHostIp(String instanceName, List<String> ipTypes) {
282+
/**
283+
* Returns preferred ip address that can be used to establish Cloud SQL connection.
284+
*/
285+
public static String getHostIp(String csqlInstanceName, String ipTypes) throws IOException {
286+
return getInstance().getHostIp(csqlInstanceName, listIpTypes(ipTypes));
287+
}
288+
289+
private String getHostIp(String instanceName, List<String> ipTypes) {
288290
CloudSqlInstance instance = getCloudSqlInstance(instanceName);
289291
return instance.getPreferredIp(ipTypes);
290292
}

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,10 @@
272272
Necessary to allow guava into the assembly jars
273273
com.google.guava:guava
274274
275-
Global test dependencies unused in r2dbc core (no tests currently):
276-
junit:junit,com.google.truth:truth
275+
Global test dependencies unused in r2dbc core:
276+
junit:junit,com.google.truth:truth,org.bouncycastle:bcpkix-jdk15on
277277
-->
278-
org.ow2.asm:asm-util,com.github.jnr:jnr-unixsocket,org.postgresql:postgresql,junit:junit,com.google.truth:truth,com.microsoft.sqlserver:mssql-jdbc,com.google.guava:guava
278+
org.ow2.asm:asm-util,com.github.jnr:jnr-unixsocket,org.postgresql:postgresql,junit:junit,com.google.truth:truth,com.microsoft.sqlserver:mssql-jdbc,com.google.guava:guava,org.bouncycastle:bcpkix-jdk15on
279279
</ignoredDependencies>
280280
</configuration>
281281
<executions>

r2dbc/core/pom.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,48 @@
132132
<artifactId>netty-handler</artifactId>
133133
<version>4.1.84.Final</version>
134134
</dependency>
135+
<dependency>
136+
<groupId>junit</groupId>
137+
<artifactId>junit</artifactId>
138+
<version>4.13.2</version>
139+
<scope>test</scope>
140+
</dependency>
141+
<dependency>
142+
<groupId>org.mockito</groupId>
143+
<artifactId>mockito-core</artifactId>
144+
<version>4.11.0</version>
145+
<scope>test</scope>
146+
</dependency>
147+
<dependency>
148+
<groupId>org.bouncycastle</groupId>
149+
<artifactId>bcpkix-jdk15on</artifactId>
150+
<version>1.70</version>
151+
<scope>test</scope>
152+
</dependency>
153+
<dependency>
154+
<groupId>com.google.apis</groupId>
155+
<artifactId>google-api-services-sqladmin</artifactId>
156+
<version>v1beta4-rev20230111-2.0.0</version>
157+
<scope>test</scope>
158+
</dependency>
135159
</dependencies>
160+
<build>
161+
<plugins>
162+
<plugin>
163+
<groupId>org.apache.maven.plugins</groupId>
164+
<artifactId>maven-jar-plugin</artifactId>
165+
<version>3.3.0</version>
166+
<executions>
167+
<execution>
168+
<goals>
169+
<goal>test-jar</goal>
170+
</goals>
171+
</execution>
172+
</executions>
173+
</plugin>
174+
</plugins>
175+
176+
</build>
136177

137178
<repositories>
138179
<repository>

r2dbc/core/src/main/java/com/google/cloud/sql/core/CloudSqlConnectionFactory.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static io.r2dbc.spi.ConnectionFactoryOptions.HOST;
2020
import static io.r2dbc.spi.ConnectionFactoryOptions.PORT;
2121

22+
import com.google.common.annotations.VisibleForTesting;
2223
import io.r2dbc.spi.Connection;
2324
import io.r2dbc.spi.ConnectionFactory;
2425
import io.r2dbc.spi.ConnectionFactoryMetadata;
@@ -36,15 +37,18 @@ public class CloudSqlConnectionFactory implements ConnectionFactory {
3637
private Function<ConnectionFactoryOptions, ConnectionFactory> connectionFactoryFactory;
3738
private ConnectionFactoryOptions.Builder builder;
3839
private String csqlHostName;
40+
private String ipTypes;
3941

4042
/**
4143
* Creates an instance of ConnectionFactory that pulls and sets host ip before delegating.
4244
*/
4345
public CloudSqlConnectionFactory(
4446
Function<ConnectionFactoryOptions, ConnectionFactory> connectionFactoryFactory,
47+
String ipTypes,
4548
Builder builder,
4649
String csqlHostName) {
4750
this.connectionFactoryFactory = connectionFactoryFactory;
51+
this.ipTypes = ipTypes;
4852
this.builder = builder;
4953
this.csqlHostName = csqlHostName;
5054
}
@@ -67,9 +71,20 @@ public ConnectionFactoryMetadata getMetadata() {
6771
}
6872
}
6973

70-
private ConnectionFactory getConnectionFactory() throws IOException {
71-
String hostIp = CoreSocketFactory.getHostIp(csqlHostName);
74+
@VisibleForTesting
75+
void setBuilderHostAndPort() throws IOException {
76+
String hostIp = CoreSocketFactory.getHostIp(csqlHostName, ipTypes);
7277
builder.option(HOST, hostIp).option(PORT, CoreSocketFactory.getDefaultServerProxyPort());
78+
}
79+
80+
@VisibleForTesting
81+
ConnectionFactoryOptions.Builder getBuilder() throws IOException {
82+
return builder;
83+
}
84+
85+
86+
private ConnectionFactory getConnectionFactory() throws IOException {
87+
setBuilderHostAndPort();
7388
return connectionFactoryFactory.apply(builder.build());
7489
}
7590
}

r2dbc/core/src/main/java/com/google/cloud/sql/core/GcpConnectionFactoryProvider.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
public abstract class GcpConnectionFactoryProvider implements ConnectionFactoryProvider {
3838

3939
public static final Option<String> UNIX_SOCKET = Option.valueOf("UNIX_SOCKET");
40+
public static final Option<String> IP_TYPES = Option.valueOf("IP_TYPES");
4041
public static final Option<Boolean> ENABLE_IAM_AUTH = Option.valueOf("ENABLE_IAM_AUTH");
4142

4243
private static Function<SslContextBuilder, SslContextBuilder> createSslCustomizer(
@@ -72,6 +73,7 @@ private static Function<SslContextBuilder, SslContextBuilder> createSslCustomize
7273
*/
7374
abstract ConnectionFactory tcpConnectionFactory(
7475
Builder optionBuilder,
76+
String ipTypes,
7577
Function<SslContextBuilder, SslContextBuilder> customizer,
7678
String csqlHostName);
7779

@@ -110,7 +112,12 @@ public ConnectionFactory create(ConnectionFactoryOptions connectionFactoryOption
110112
private ConnectionFactory createFactory(
111113
ConnectionFactoryOptions connectionFactoryOptions) throws IOException {
112114
String connectionName = (String) connectionFactoryOptions.getRequiredValue(HOST);
113-
String socket = (String) connectionFactoryOptions.getValue(UNIX_SOCKET);
115+
116+
String ipTypes = CoreSocketFactory.DEFAULT_IP_TYPES;
117+
Object ipTypesObj = connectionFactoryOptions.getValue(IP_TYPES);
118+
if (ipTypesObj != null) {
119+
ipTypes = (String) ipTypesObj;
120+
}
114121

115122
Object iamAuthObj = connectionFactoryOptions.getValue(ENABLE_IAM_AUTH);
116123
Boolean enableIamAuth = false;
@@ -122,15 +129,17 @@ private ConnectionFactory createFactory(
122129

123130
Builder optionBuilder = createBuilder(connectionFactoryOptions);
124131

125-
126132
// Precompute SSL Data to trigger the initial refresh to happen immediately,
127133
// and ensure enableIAMAuth is set correctly.
128134
CoreSocketFactory.getSslData(connectionName, enableIamAuth);
129135

136+
String socket = (String) connectionFactoryOptions.getValue(UNIX_SOCKET);
130137
if (socket != null) {
131138
return socketConnectionFactory(optionBuilder, socket);
132139
}
133-
return tcpConnectionFactory(optionBuilder, createSslCustomizer(connectionName, enableIamAuth),
140+
141+
return tcpConnectionFactory(optionBuilder, ipTypes,
142+
createSslCustomizer(connectionName, enableIamAuth),
134143
connectionName);
135144
}
136145

0 commit comments

Comments
 (0)