If a jdbcUrl field is present in the credentials field in relational service connectors, prefer to use it unchanged over building a jdbcUrl from other credentials fields.

This commit is contained in:
Scott Frederick
2015-05-11 18:56:17 -05:00
parent 06b9fd1bb4
commit b6882df6ae
14 changed files with 196 additions and 60 deletions

View File

@@ -5,6 +5,8 @@ import java.util.Map;
import org.springframework.cloud.service.common.RelationalServiceInfo;
import org.springframework.cloud.util.UriInfo;
import static org.springframework.cloud.service.common.RelationalServiceInfo.JDBC_PREFIX;
/**
*
* @author Ramnivas Laddad
@@ -16,13 +18,42 @@ public abstract class RelationalServiceInfoCreator<SI extends RelationalServiceI
super(tags, uriSchemes);
}
@Override
public boolean accept(Map<String, Object> serviceData) {
return jdbcUrlMatchesScheme(serviceData) || super.accept(serviceData);
}
protected boolean jdbcUrlMatchesScheme(Map<String, Object> serviceData) {
if (getUriSchemes() == null) {
return false;
}
Map<String, Object> credentials = getCredentials(serviceData);
String jdbcUrl = getStringFromCredentials(credentials, "jdbcUrl");
if (jdbcUrl != null) {
for (String uriScheme : getUriSchemes()) {
if (jdbcUrl.startsWith(JDBC_PREFIX + uriScheme + ":")) {
return true;
}
}
}
return false;
}
public abstract SI createServiceInfo(String id, String uri);
public SI createServiceInfo(Map<String, Object> serviceData) {
String id = (String) serviceData.get("name");
Map<String,Object> credentials = getCredentials(serviceData);
String uri = getUriFromCredentials(credentials);
String uri = getStringFromCredentials(credentials, "jdbcUrl");
if (uri == null) {
uri = getUriFromCredentials(credentials);
}
if (uri == null) {
String host = getStringFromCredentials(credentials, "hostname", "host");

View File

@@ -2,6 +2,7 @@ package org.springframework.cloud.cloudfoundry;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.service.common.RelationalServiceInfo.JDBC_PREFIX;
import java.util.List;
@@ -76,8 +77,8 @@ public class CloudFoundryConnectorMysqlServiceTest extends AbstractCloudFoundryC
String name2 = "database-2";
when(mockEnvironment.getEnvValue("VCAP_SERVICES"))
.thenReturn(getServicesPayload(
getMysqlServicePayloadWithLabelNoUri("mysql-1", hostname, port, username, password, name1),
getMysqlServicePayloadWithLabelNoUri("mysql-2", hostname, port, username, password, name2)));
getMysqlServicePayloadWithLabelNoUri("mysql-1", hostname, port, username, password, name1),
getMysqlServicePayloadWithLabelNoUri("mysql-2", hostname, port, username, password, name2)));
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
MysqlServiceInfo info1 = (MysqlServiceInfo) getServiceInfo(serviceInfos, "mysql-1");
@@ -88,6 +89,24 @@ public class CloudFoundryConnectorMysqlServiceTest extends AbstractCloudFoundryC
assertEquals(getJdbcUrl("mysql", name2), info2.getJdbcUrl());
}
@Test
public void mysqlServiceCreationWithJdbcUrl() {
String name1 = "database-1";
String name2 = "database-2";
when(mockEnvironment.getEnvValue("VCAP_SERVICES"))
.thenReturn(getServicesPayload(
getMysqlServicePayloadWithJdbcUrl("mysql-1", hostname, port, username, password, name1),
getMysqlServicePayloadWithJdbcUrl("mysql-2", hostname, port, username, password, name2)));
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
MysqlServiceInfo info1 = (MysqlServiceInfo) getServiceInfo(serviceInfos, "mysql-1");
MysqlServiceInfo info2 = (MysqlServiceInfo) getServiceInfo(serviceInfos, "mysql-2");
assertServiceFoundOfType(info1, MysqlServiceInfo.class);
assertServiceFoundOfType(info2, MysqlServiceInfo.class);
assertEquals(JDBC_PREFIX + "mysql://rawjdbcurl", info1.getJdbcUrl());
assertEquals(JDBC_PREFIX + "mysql://rawjdbcurl", info2.getJdbcUrl());
}
private String getMysqlServicePayload(String serviceName,
String hostname, int port,
String user, String password, String name) {
@@ -115,5 +134,11 @@ public class CloudFoundryConnectorMysqlServiceTest extends AbstractCloudFoundryC
return getRelationalPayload("test-mysql-info-with-label-no-uri.json", serviceName,
hostname, port, user, password, name);
}
private String getMysqlServicePayloadWithJdbcUrl(String serviceName,
String hostname, int port,
String user, String password, String name) {
return getRelationalPayload("test-mysql-info-jdbc-url.json", serviceName,
hostname, port, user, password, name);
}
}

View File

@@ -5,6 +5,7 @@ import org.springframework.cloud.service.BaseServiceInfo;
import org.springframework.cloud.service.ServiceInfo;
import org.springframework.cloud.service.common.MysqlServiceInfo;
import org.springframework.cloud.service.common.OracleServiceInfo;
import org.springframework.cloud.service.common.RelationalServiceInfo;
import java.util.List;
@@ -43,6 +44,25 @@ public class CloudFoundryConnectorOracleServiceTest extends AbstractUserProvided
assertNotNull(info);
}
@Test
public void oracleServiceCreationWithJdbcUrl() {
when(mockEnvironment.getEnvValue("VCAP_SERVICES"))
.thenReturn(getServicesPayload(
getOracleServicePayloadWithJdbcurl(SERVICE_NAME, hostname, port, username, password, INSTANCE_NAME, ORACLE_SCHEME)));
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
OracleServiceInfo info = (OracleServiceInfo) getServiceInfo(serviceInfos, SERVICE_NAME);
assertServiceFoundOfType(info, OracleServiceInfo.class);
assertEquals(RelationalServiceInfo.JDBC_PREFIX + "oracle:rawjdbcurl", info.getJdbcUrl());
}
protected String getOracleServicePayloadWithJdbcurl(String serviceName, String hostname, int port,
String user, String password, String name, String scheme) {
String payload = getRelationalPayload("test-oracle-info-jdbc-url.json", serviceName,
hostname, port, user, password, name);
return payload.replace("$scheme", scheme);
}
private String getOracleJdbcUrl(String name) {
return "jdbc:oracle:thin:" + username + "/" + password + "@" + hostname + ":" + port + "/" + name;
}

View File

@@ -2,6 +2,7 @@ package org.springframework.cloud.cloudfoundry;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static org.springframework.cloud.service.common.RelationalServiceInfo.JDBC_PREFIX;
import java.util.List;
@@ -52,6 +53,25 @@ public class CloudFoundryConnectorPostgresqlServiceTest extends AbstractCloudFou
assertEquals(getJdbcUrl("postgres", name2), info2.getJdbcUrl());
}
@Test
public void postgresqlServiceCreationWithJdbcUrl() {
String name1 = "database-1";
String name2 = "database-2";
when(mockEnvironment.getEnvValue("VCAP_SERVICES"))
.thenReturn(getServicesPayload(
getPostgresqlServicePayloadWithJdbcUrl("postgresql-1", hostname, port, username, password, name1),
getPostgresqlServicePayloadWithJdbcUrl("postgresql-2", hostname, port, username, password, name2)));
List<ServiceInfo> serviceInfos = testCloudConnector.getServiceInfos();
PostgresqlServiceInfo info1 = (PostgresqlServiceInfo) getServiceInfo(serviceInfos, "postgresql-1");
PostgresqlServiceInfo info2 = (PostgresqlServiceInfo) getServiceInfo(serviceInfos, "postgresql-2");
assertServiceFoundOfType(info1, PostgresqlServiceInfo.class);
assertServiceFoundOfType(info2, PostgresqlServiceInfo.class);
assertEquals(JDBC_PREFIX + "postgres://rawjdbcurl", info1.getJdbcUrl());
assertEquals(JDBC_PREFIX + "postgres://rawjdbcurl", info2.getJdbcUrl());
}
private String getPostgresqlServicePayload(String serviceName,
String hostname, int port,
String user, String password, String name) {
@@ -66,4 +86,11 @@ public class CloudFoundryConnectorPostgresqlServiceTest extends AbstractCloudFou
hostname, port, user, password, name);
}
private String getPostgresqlServicePayloadWithJdbcUrl(String serviceName,
String hostname, int port,
String user, String password, String name) {
return getRelationalPayload("test-postgresql-info-jdbc-url.json", serviceName,
hostname, port, user, password, name);
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "$serviceName",
"credentials": {
"jdbcUrl": "jdbc:mysql://rawjdbcurl",
"uri": "mysql://$user:$password@$hostname:$port/$name"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "$serviceName",
"credentials":{
"uri" : "mysql://$user:$password@$hostname:$port/$name"
}
"name": "$serviceName",
"credentials": {
"uri": "mysql://$user:$password@$hostname:$port/$name"
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "$serviceName",
"credentials": {
"jdbcUrl": "jdbc:oracle:rawjdbcurl",
"uri": "oracle://$user:$password@$hostname:$port/$name"
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "$serviceName",
"credentials": {
"jdbcUrl": "jdbc:postgres://rawjdbcurl",
"uri": "postgres://$user:$password@$hostname:$port/$name"
}
}

View File

@@ -15,6 +15,10 @@ public class OracleServiceInfo extends RelationalServiceInfo {
@Override
public String getJdbcUrl() {
if (getUriInfo().getRawUriString().startsWith(JDBC_PREFIX)) {
return getUriInfo().getRawUriString();
}
return String.format("jdbc:%s:thin:%s/%s@%s:%d/%s",
jdbcUrlDatabaseType, getUserName(), getPassword(),
getHost(), getPort(), getPath());

View File

@@ -1,12 +1,19 @@
package org.springframework.cloud.service.common;
import org.springframework.cloud.service.UriBasedServiceInfo;
import org.springframework.cloud.util.StandardUriInfoFactory;
import org.springframework.cloud.util.UriInfo;
import org.springframework.cloud.util.UriInfoFactory;
/**
* @author Ramnivas Laddad
* @author Scott Frederick
*/
public abstract class RelationalServiceInfo extends UriBasedServiceInfo {
public static final String JDBC_PREFIX = "jdbc:";
private static JdbcUriInfoFactory jdbcUriInfoFactory = new JdbcUriInfoFactory();
protected final String jdbcUrlDatabaseType;
public RelationalServiceInfo(String id, String uriString, String jdbcUrlDatabaseType) {
@@ -14,9 +21,18 @@ public abstract class RelationalServiceInfo extends UriBasedServiceInfo {
this.jdbcUrlDatabaseType = jdbcUrlDatabaseType;
}
@Override
public UriInfoFactory getUriInfoFactory() {
return jdbcUriInfoFactory;
}
@ServiceProperty(category = "connection")
public String getJdbcUrl() {
return String.format("jdbc:%s://%s%s/%s%s%s", jdbcUrlDatabaseType, getHost(), formatPort(),
if (getUriInfo().getRawUriString().startsWith(JDBC_PREFIX)) {
return getUriInfo().getRawUriString();
}
return String.format("%s%s://%s%s/%s%s%s", JDBC_PREFIX, jdbcUrlDatabaseType, getHost(), formatPort(),
getPath(), formatUserinfo(), formatQuery());
}
@@ -47,4 +63,20 @@ public abstract class RelationalServiceInfo extends UriBasedServiceInfo {
}
return "";
}
public static class JdbcUriInfoFactory extends StandardUriInfoFactory {
@Override
public UriInfo createUri(String uriString) {
if (uriString.startsWith(JDBC_PREFIX)) {
return new JdbcUriInfo(uriString);
}
return super.createUri(uriString);
}
}
public static class JdbcUriInfo extends UriInfo {
public JdbcUriInfo(String rawUriString) {
super(rawUriString);
}
}
}

View File

@@ -7,12 +7,10 @@ import java.net.URLDecoder;
/**
* Factory for standard Cloud Foundry URIs, which all conform to the format:
* <p>
* {@code [jdbc:]scheme://[user:pass]@authority[:port]/path}
* {@code scheme://[user:pass]@authority[:port]/path}
*/
public class StandardUriInfoFactory implements UriInfoFactory {
public static final String JDBC_PREFIX = "jdbc:";
@Override
public UriInfo createUri(String scheme, String host, int port, String username, String password, String path) {
return new UriInfo(scheme, host, port, username, password, path);
@@ -20,10 +18,7 @@ public class StandardUriInfoFactory implements UriInfoFactory {
@Override
public UriInfo createUri(String uriString) {
uriString = trimJdbcScheme(uriString);
URI tmpUri = createTmpUri(uriString);
URI tmpUri = uriFromString(uriString);
String[] userInfo = parseUserinfo(tmpUri);
String userName = uriDecode(userInfo[0]);
@@ -33,21 +28,14 @@ public class StandardUriInfoFactory implements UriInfoFactory {
userName, password, parsePath(tmpUri), tmpUri.getRawQuery(), uriString);
}
private URI createTmpUri(String uriString) {
private URI uriFromString(String uriString) {
try {
return new URI(uriString);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
throw new IllegalArgumentException("Invalid URI " + uriString, e);
}
}
private String trimJdbcScheme(String uriString) {
if (uriString.startsWith(JDBC_PREFIX)) {
uriString = uriString.substring(JDBC_PREFIX.length());
}
return uriString;
}
private String[] parseUserinfo(URI uri) {
String userInfo = uri.getRawUserInfo();

View File

@@ -44,6 +44,10 @@ public class UriInfo {
this.uri = buildUri();
}
public UriInfo(String rawUriString) {
this.rawUriString = rawUriString;
}
public String getScheme() {
return scheme;
}

View File

@@ -12,31 +12,24 @@ package org.springframework.cloud.util;
*/
public interface UriInfoFactory {
/**
* Create a {@link UriInfo} based on a URI string
*
* @param uriString
* the URI string to parse
* @return a {@link UriInfo}
*/
public UriInfo createUri(String uriString);
/**
* Create a {@link UriInfo} based on a URI string
*
* @param uriString the URI string to parse
* @return a {@link UriInfo}
*/
UriInfo createUri(String uriString);
/**
* Create a {@link UriInfo} based on explicit components of the URI
*
* @param scheme
* the URI scheme for this service
* @param host
* the host for this service
* @param port
* the port for this service
* @param username
* the authentication username for this service
* @param password
* the authentication password for this service
* @param path
* the path to this service resource on the server
* @return a {@link UriInfo}
*/
public UriInfo createUri(String scheme, String host, int port, String username, String password, String path);
/**
* Create a {@link UriInfo} based on explicit components of the URI
*
* @param scheme the URI scheme for this service
* @param host the host for this service
* @param port the port for this service
* @param username the authentication username for this service
* @param password the authentication password for this service
* @param path the path to this service resource on the server
* @return a {@link UriInfo}
*/
UriInfo createUri(String scheme, String host, int port, String username, String password, String path);
}

View File

@@ -31,15 +31,6 @@ public class StandardUriInfoFactoryTest {
assertEquals(uri, result.getUri().toString());
}
@Test
public void createWithJdbcUri() {
String uri = "mysql://joe:joes_password@localhost:1527/big_db";
UriInfo result = factory.createUri("jdbc:" + uri);
assertUriInfoEquals(result, "localhost", 1527, "joe", "joes_password", "big_db", null);
assertEquals(uri, result.getUri().toString());
}
@Test
public void createNoUsernamePassword() {
String uri = "mysql://localhost:1527/big_db";