From f48084a15a849bd642064ac6af1afdfcb859abca Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 17:33:29 -0500 Subject: [PATCH 01/52] add ignore for "bin/" for Gradle-Eclipse --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ae08494..1eb96eb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ build Servers .gradle _site +/bin From 0abf58f4918f75129539ae9185f67483bf838c9a Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 17:33:53 -0500 Subject: [PATCH 02/52] remove unused import --- .../java/org/springframework/cloud/config/ServiceScanHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java index bf162c9..deefb6f 100644 --- a/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java +++ b/spring-cloud-spring-service-connector/src/main/java/org/springframework/cloud/config/ServiceScanHelper.java @@ -9,7 +9,6 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.cloud.Cloud; -import org.springframework.cloud.CloudException; import org.springframework.cloud.CloudFactory; import org.springframework.cloud.config.java.ServiceScan; import org.springframework.cloud.service.GenericCloudServiceConnectorFactory; From 502eeeddddd23af4157d6697d6310280cb5f30cf Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 17:35:25 -0500 Subject: [PATCH 03/52] remove unused logger field from public class (used only in secondary top-level) --- .../src/main/java/org/springframework/cloud/Cloud.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java b/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java index 808b903..41fd035 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/Cloud.java @@ -38,8 +38,6 @@ import org.springframework.cloud.service.ServiceInfo.ServiceProperty; * */ public class Cloud { - private static Logger logger = Logger.getLogger(Cloud.class.getName()); - private CloudConnector cloudConnector; private ServiceConnectorCreatorRegistry serviceConnectorCreatorRegistry = new ServiceConnectorCreatorRegistry(); From 839a72569c81e82c696b97d65977db18b9dd1899 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:06:07 -0500 Subject: [PATCH 04/52] pull up KeyValuePair class from HerokuConnector to AbstractCloudConnector --- .../cloud/AbstractCloudConnector.java | 34 ++++++++++--- .../cloud/heroku/HerokuConnector.java | 50 ++++++------------- .../heroku/HerokuServiceInfoCreator.java | 20 ++++---- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java b/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java index 6a73afa..a515766 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java @@ -10,25 +10,25 @@ import org.springframework.cloud.service.ServiceInfo; /** * Helper abstract class to simplify {@link CloudConnector} implementations. - * + * * User the {@link ServiceLoader} approach to looks for file name matching the class passed in constructor * and registers {@link ServiceInfoCreator} found there. - * + * * Implementation of {@link CloudConnector}s that wish to support the recommended service scanning approach * should extends this approach to gain that functionality automatically. - * + * * @author Ramnivas Laddad * */ public abstract class AbstractCloudConnector implements CloudConnector { private static Logger logger = Logger.getLogger(AbstractCloudConnector.class.getName()); - + protected List> serviceInfoCreators = new ArrayList>(); protected abstract List getServicesData(); protected abstract FallbackServiceInfoCreator getFallbackServiceInfoCreator(); - + public AbstractCloudConnector(Class> serviceInfoCreatorClass) { scanServiceInfoCreators(serviceInfoCreatorClass); } @@ -39,7 +39,7 @@ public abstract class AbstractCloudConnector implements CloudConnector { for (SD serviceData : getServicesData()) { serviceInfos.add(getServiceInfo(serviceData)); } - + return serviceInfos; } @@ -54,18 +54,36 @@ public abstract class AbstractCloudConnector implements CloudConnector { registerServiceInfoCreator(serviceInfoCreator); } } - + private ServiceInfo getServiceInfo(SD serviceData) { for (ServiceInfoCreator serviceInfoCreator : serviceInfoCreators) { if (serviceInfoCreator.accept(serviceData)) { return serviceInfoCreator.createServiceInfo(serviceData); } } - + // Fallback with a warning ServiceInfo fallackServiceInfo = getFallbackServiceInfoCreator().createServiceInfo(serviceData); logger.warning("No suitable service info creator found for service " + fallackServiceInfo.getId() + " Did you forget to add a ServiceInfoCreator?"); return fallackServiceInfo; } + + public static class KeyValuePair { + private final String key; + private final String value; + + public KeyValuePair(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + } } \ No newline at end of file diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java index 374b7f8..ac39931 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java @@ -6,30 +6,30 @@ import java.util.List; import java.util.Map; import org.springframework.cloud.AbstractCloudConnector; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; import org.springframework.cloud.CloudException; import org.springframework.cloud.FallbackServiceInfoCreator; import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.app.ApplicationInstanceInfo; -import org.springframework.cloud.heroku.HerokuConnector.KeyValuePair; import org.springframework.cloud.service.BaseServiceInfo; import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.util.EnvironmentAccessor; /** * Implementation of CloudConnector for Heroku - * + * * Currently support Postgres (default provided), Mysql (Cleardb), MongoDb (MongoLab, MongoHQ, MongoSoup), * Redis (RedisToGo, RedisCloud, OpenRedis, RedisGreen), and AMQP (CloudAmqp). - * + * * @author Ramnivas Laddad * */ -public class HerokuConnector extends AbstractCloudConnector { +public class HerokuConnector extends AbstractCloudConnector { private EnvironmentAccessor environment = new EnvironmentAccessor(); - private ApplicationInstanceInfoCreator applicationInstanceInfoCreator + private ApplicationInstanceInfoCreator applicationInstanceInfoCreator = new ApplicationInstanceInfoCreator(environment); - + private List serviceEnvPrefixes; @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -41,28 +41,28 @@ public class HerokuConnector extends AbstractCloudConnector serviceInfoCreator) { + protected void registerServiceInfoCreator(ServiceInfoCreator serviceInfoCreator) { super.registerServiceInfoCreator(serviceInfoCreator); HerokuServiceInfoCreator herokuServiceInfoCreator = (HerokuServiceInfoCreator)serviceInfoCreator; String[] envPrefixes = herokuServiceInfoCreator.getEnvPrefixes(); - + // need to do this since this method gets called during construction and we cannot initialize serviceEnvPrefixes before this if (serviceEnvPrefixes == null) { serviceEnvPrefixes = new ArrayList(); @@ -75,17 +75,17 @@ public class HerokuConnector extends AbstractCloudConnector * Returns map whose key is the env key and value is the associated url *

- * @return information about services bound to the app + * @return information about services bound to the app */ protected List getServicesData() { List serviceData = new ArrayList(); - + Map env = environment.getEnv(); - + for (Map.Entry envEntry : env.entrySet()) { for (String envPrefix : serviceEnvPrefixes) { if (envEntry.getKey().startsWith(envPrefix)) { - serviceData.add(new KeyValuePair(envEntry.getKey(), envEntry.getValue())); + serviceData.add(new KeyValuePair(envEntry.getKey(), envEntry.getValue())); } } } @@ -97,24 +97,6 @@ public class HerokuConnector extends AbstractCloudConnector getFallbackServiceInfoCreator() { return new HerokuFallbackServiceInfoCreator(); } - - public static class KeyValuePair { - private String key; - private String value; - - public KeyValuePair(String key, String value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public String getValue() { - return value; - } - } } class HerokuFallbackServiceInfoCreator extends FallbackServiceInfoCreator { diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java index 15ed4aa..00b6c6b 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java @@ -1,11 +1,11 @@ package org.springframework.cloud.heroku; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; import org.springframework.cloud.ServiceInfoCreator; -import org.springframework.cloud.heroku.HerokuConnector.KeyValuePair; import org.springframework.cloud.service.ServiceInfo; /** - * + * * @author Ramnivas Laddad * */ @@ -16,25 +16,25 @@ public abstract class HerokuServiceInfoCreator implement public HerokuServiceInfoCreator(String urlProtocol) { this.urlProtocol = urlProtocol; } - + public boolean accept(KeyValuePair serviceData) { return serviceData.getValue().toString().startsWith(urlProtocol + "://"); } - + public abstract SI createServiceInfo(String id, String uri); - + public SI createServiceInfo(KeyValuePair serviceData) { return createServiceInfo(serviceData.getKey(), serviceData.getValue()); } - + /** * Get prefixes for env variable with which the associated {@link ServiceInfo} may be created. - * + * * Unlike CloudFoundry which exposes VCAP_SERVICES as a single environment to encompass all services bound * to the app, Heroku expose one environment variable per app. This method allows each info creator to declare - * appropriate env variables. - * - * @return prefixes for the relevant environment variables + * appropriate env variables. + * + * @return prefixes for the relevant environment variables */ public abstract String[] getEnvPrefixes(); } From 6e12152ebfccf15378afb911a253092e2939cf59 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:13:49 -0500 Subject: [PATCH 05/52] pull up URI-based common functionality into core abstract base class --- .../service/UriBasedServiceInfoCreator.java | 26 +++++++++++++++++++ .../heroku/HerokuServiceInfoCreator.java | 21 +++------------ 2 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java new file mode 100644 index 0000000..b856bc0 --- /dev/null +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java @@ -0,0 +1,26 @@ +package org.springframework.cloud.service; + +import org.springframework.cloud.ServiceInfoCreator; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public abstract class UriBasedServiceInfoCreator implements + ServiceInfoCreator { + + private final String uriScheme; + + public UriBasedServiceInfoCreator(String uriScheme) { + this.uriScheme = uriScheme; + } + + @Override + public boolean accept(KeyValuePair serviceData) { + return serviceData.getValue().toString().startsWith(uriScheme + "://"); + } + + public abstract SI createServiceInfo(String id, String uri); + + @Override + public SI createServiceInfo(KeyValuePair serviceData) { + return createServiceInfo(serviceData.getKey(), serviceData.getValue()); + } +} diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java index 00b6c6b..81094eb 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java @@ -1,30 +1,17 @@ package org.springframework.cloud.heroku; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; -import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfoCreator; /** * * @author Ramnivas Laddad * */ -public abstract class HerokuServiceInfoCreator implements ServiceInfoCreator { +public abstract class HerokuServiceInfoCreator extends UriBasedServiceInfoCreator { - private String urlProtocol; - - public HerokuServiceInfoCreator(String urlProtocol) { - this.urlProtocol = urlProtocol; - } - - public boolean accept(KeyValuePair serviceData) { - return serviceData.getValue().toString().startsWith(urlProtocol + "://"); - } - - public abstract SI createServiceInfo(String id, String uri); - - public SI createServiceInfo(KeyValuePair serviceData) { - return createServiceInfo(serviceData.getKey(), serviceData.getValue()); + public HerokuServiceInfoCreator(String uriScheme) { + super(uriScheme); } /** From 82c0dfaaf2a35c86bd36cac0cdf29cdd252580f8 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:23:36 -0500 Subject: [PATCH 06/52] constant for MongoDB URI scheme --- .../cloud/cloudfoundry/MongoServiceInfoCreator.java | 4 ++-- .../cloud/service/common/MongoServiceInfo.java | 11 +++++++---- .../cloud/heroku/MongoServiceInfoCreator.java | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java index 5aeace5..ac963c5 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java @@ -12,8 +12,8 @@ import org.springframework.cloud.service.common.MongoServiceInfo; public class MongoServiceInfoCreator extends CloudFoundryServiceInfoCreator { public MongoServiceInfoCreator() { - super(new Tags("mongodb"), "mongodb"); - + // the literal in the tag is CloudFoundry-specific + super(new Tags("mongodb"), MongoServiceInfo.URI_SCHEME); } public MongoServiceInfo createServiceInfo(Map serviceData) { diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java index b45800f..a332b65 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java @@ -4,23 +4,26 @@ import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("mongo") public class MongoServiceInfo extends UriBasedServiceInfo { + + public static final String URI_SCHEME = "mongodb"; + public MongoServiceInfo(String id, String host, int port, String username, String password, String db) { - super(id, "mongodb", host, port, username, password, db); + super(id, URI_SCHEME, host, port, username, password, db); } public MongoServiceInfo(String id, String uri) { super(id, uri); } - + @ServiceProperty(category="connection") public String getDatabase() { return getUriInfo().getPath(); } - + } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java index bb1e11e..d75299e 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.MongoServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class MongoServiceInfoCreator extends HerokuServiceInfoCreator { public MongoServiceInfoCreator() { - super("mongodb"); + super(MongoServiceInfo.URI_SCHEME); } @Override From 5434952ca60ce56f8f88fad9495e2f40058bb4b1 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:25:57 -0500 Subject: [PATCH 07/52] pull up URI scheme for RabbitMQ --- .../cloudfoundry/AmqpServiceInfoCreator.java | 6 +++--- .../cloud/service/common/AmqpServiceInfo.java | 19 +++++++++++-------- .../cloud/heroku/AmqpServiceInfoCreator.java | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java index 1753c11..af68eee 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java @@ -5,20 +5,20 @@ import java.util.Map; import org.springframework.cloud.service.common.AmqpServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class AmqpServiceInfoCreator extends CloudFoundryServiceInfoCreator { public AmqpServiceInfoCreator() { - super(new Tags("rabbitmq"), "amqp"); + super(new Tags("rabbitmq"), AmqpServiceInfo.URI_SCHEME); } public AmqpServiceInfo createServiceInfo(Map serviceData) { @SuppressWarnings("unchecked") Map credentials = (Map) serviceData.get("credentials"); - + String id = (String) serviceData.get("name"); String uri = getStringFromCredentials(credentials, "uri", "url"); diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java index 5ae72bb..aa7bb98 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java @@ -1,8 +1,8 @@ package org.springframework.cloud.service.common; import org.springframework.cloud.CloudException; -import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; +import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.util.UriInfo; /** @@ -13,29 +13,32 @@ import org.springframework.cloud.util.UriInfo; */ @ServiceLabel("rabbitmq") public class AmqpServiceInfo extends UriBasedServiceInfo { + + public static final String URI_SCHEME = "amqp"; + public AmqpServiceInfo(String id, String host, int port, String username, String password, String virtualHost) { - super(id, "amqp", host, port, username, password, virtualHost); + super(id, URI_SCHEME, host, port, username, password, virtualHost); } - + public AmqpServiceInfo(String id, String uri) throws CloudException { super(id, uri); } - + @ServiceProperty(category="connection") public String getVirtualHost() { return getUriInfo().getPath(); } - + @Override protected UriInfo validateAndCleanUriInfo(UriInfo uriInfo) { - if (!"amqp".equals(uriInfo.getScheme())) { + if (!URI_SCHEME.equals(uriInfo.getScheme())) { throw new IllegalArgumentException("wrong scheme in amqp URI: " + uriInfo); } if (uriInfo.getHost() == null) { throw new IllegalArgumentException("missing authority in amqp URI: " + uriInfo); } - + int port = uriInfo.getPort(); if (port == -1) { port = 5672; @@ -43,7 +46,7 @@ public class AmqpServiceInfo extends UriBasedServiceInfo { String userName = uriInfo.getUserName(); String password = uriInfo.getPassword(); - + if (userName == null || password == null) { throw new IllegalArgumentException("missing userinfo in amqp URI: " + uriInfo); } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java index a139bd6..86621f8 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.AmqpServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class AmqpServiceInfoCreator extends HerokuServiceInfoCreator { public AmqpServiceInfoCreator() { - super("amqp"); + super(AmqpServiceInfo.URI_SCHEME); } @Override From 84ba55aae86fb8b6e01042bfc7fee1f3d2a54fcb Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:26:45 -0500 Subject: [PATCH 08/52] make jdbcUrlDatabaseType final --- .../cloud/service/common/RelationalServiceInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java index 49fe00d..bac6236 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java @@ -7,7 +7,7 @@ import org.springframework.cloud.service.UriBasedServiceInfo; */ public abstract class RelationalServiceInfo extends UriBasedServiceInfo { - protected String jdbcUrlDatabaseType; + protected final String jdbcUrlDatabaseType; public RelationalServiceInfo(String id, String uriString, String jdbcUrlDatabaseType) { super(id, uriString); From 0629e84768c73e007bd5d5349fc306ffff0a2d5f Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:29:07 -0500 Subject: [PATCH 09/52] pull up MySQL URI scheme --- .../cloud/cloudfoundry/MysqlServiceInfoCreator.java | 5 +++-- .../cloud/service/common/MysqlServiceInfo.java | 6 ++++-- .../cloud/heroku/MysqlServiceInfoCreator.java | 4 ++-- .../cloud/heroku/HerokuConnectorMysqlServiceTest.java | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java index aca803e..b5c6e15 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java @@ -3,14 +3,15 @@ package org.springframework.cloud.cloudfoundry; import org.springframework.cloud.service.common.MysqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class MysqlServiceInfoCreator extends RelationalServiceInfoCreator { public MysqlServiceInfoCreator() { - super(new Tags("mysql"), "mysql"); + // the literal in the tag is CloudFoundry-specific + super(new Tags("mysql"), MysqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java index 467a59c..2eccab0 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java @@ -3,14 +3,16 @@ package org.springframework.cloud.service.common; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("mysql") public class MysqlServiceInfo extends RelationalServiceInfo { + public static final String URI_SCHEME = "mysql"; + public MysqlServiceInfo(String id, String url) { - super(id, url, "mysql"); + super(id, url, URI_SCHEME); } } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java index 4318cb0..73bb8eb 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.MysqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class MysqlServiceInfoCreator extends RelationalServiceInfoCreator { public MysqlServiceInfoCreator() { - super("mysql"); + super(MysqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java index 349c738..439a854 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java @@ -13,15 +13,15 @@ import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.service.common.MysqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class HerokuConnectorMysqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest { public HerokuConnectorMysqlServiceTest() { - super("mysql"); + super(MysqlServiceInfo.URI_SCHEME); } - + @Test public void mysqlServiceCreation() { Map env = new HashMap(); From 098a856523ab85261402c22c440657f6a3777fec Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:30:06 -0500 Subject: [PATCH 10/52] pull up Oracle URI scheme --- .../cloud/cloudfoundry/OracleServiceInfoCreator.java | 2 +- .../cloud/service/common/OracleServiceInfo.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java index 1b8159f..1d82ab3 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java @@ -4,7 +4,7 @@ import org.springframework.cloud.service.common.OracleServiceInfo; public class OracleServiceInfoCreator extends RelationalServiceInfoCreator { public OracleServiceInfoCreator() { - super(new Tags(), "oracle"); + super(new Tags(), OracleServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java index 13e0f49..8aef0c4 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java @@ -5,8 +5,10 @@ import org.springframework.cloud.service.ServiceInfo; @ServiceInfo.ServiceLabel("oracle") public class OracleServiceInfo extends RelationalServiceInfo { + public static final String URI_SCHEME = "oracle"; + public OracleServiceInfo(String id, String url) { - super(id, url, "oracle"); + super(id, url, URI_SCHEME); } @Override From a720ab12dc688735861ad2a824628610aaeb4a6b Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:37:23 -0500 Subject: [PATCH 11/52] pull up Postgres URI schema, split out JDBC URL types--this should probably be done in the interface instead of ad-hocky --- .../cloudfoundry/PostgresqlServiceInfoCreator.java | 4 ++-- ...ractCloudFoundryConnectorRelationalServiceTest.java | 5 +++-- .../cloud/service/common/MysqlServiceInfo.java | 10 ++++++---- .../cloud/service/common/OracleServiceInfo.java | 6 ++++-- .../cloud/service/common/PostgresqlServiceInfo.java | 9 +++++++-- .../cloud/heroku/PostgresqlServiceInfoCreator.java | 4 ++-- .../heroku/HerokuConnectorPostgresqlServiceTest.java | 6 +++--- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java index da8be3e..4b38fbf 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.cloudfoundry; import org.springframework.cloud.service.common.PostgresqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super(new Tags("postgresql"), "postgres"); + super(new Tags("postgresql"), PostgresqlServiceInfo.URI_SCHEMA); } @Override diff --git a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java index 35a790a..9588e50 100644 --- a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java +++ b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java @@ -1,7 +1,7 @@ package org.springframework.cloud.cloudfoundry; /** - * + * * @author Ramnivas Laddad * */ @@ -20,12 +20,13 @@ public abstract class AbstractCloudFoundryConnectorRelationalServiceTest extends } protected static String getJdbcUrl(String databaseType, String name) { + // this should be cleaned up more broadly; pull into RelationalServiceInfo interface? String jdbcUrlDatabaseType = databaseType; if (databaseType.equals("postgres")) { jdbcUrlDatabaseType = "postgresql"; } - return "jdbc:" + jdbcUrlDatabaseType + "://" + hostname + ":" + port + "/" + name + + return "jdbc:" + jdbcUrlDatabaseType + "://" + hostname + ":" + port + "/" + name + "?user=" + username + "&password=" + password; } diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java index 2eccab0..f4609eb 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java @@ -10,9 +10,11 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel; @ServiceLabel("mysql") public class MysqlServiceInfo extends RelationalServiceInfo { - public static final String URI_SCHEME = "mysql"; + public static final String JDBC_URL_TYPE = "mysql"; - public MysqlServiceInfo(String id, String url) { - super(id, url, URI_SCHEME); - } + public static final String URI_SCHEME = JDBC_URL_TYPE; + + public MysqlServiceInfo(String id, String url) { + super(id, url, URI_SCHEME); + } } diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java index 8aef0c4..6d2289d 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java @@ -5,10 +5,12 @@ import org.springframework.cloud.service.ServiceInfo; @ServiceInfo.ServiceLabel("oracle") public class OracleServiceInfo extends RelationalServiceInfo { - public static final String URI_SCHEME = "oracle"; + public static final String JDBC_URL_TYPE = "oracle"; + + public static final String URI_SCHEME = JDBC_URL_TYPE; public OracleServiceInfo(String id, String url) { - super(id, url, URI_SCHEME); + super(id, url, JDBC_URL_TYPE); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java index 98e478c..2927782 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java @@ -4,13 +4,18 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("postgresql") public class PostgresqlServiceInfo extends RelationalServiceInfo { + + public static final String JDBC_URL_TYPE = "postgresql"; + + public static final String URI_SCHEMA = "postgres"; + public PostgresqlServiceInfo(String id, String url) { - super(id, url, "postgresql"); + super(id, url, JDBC_URL_TYPE); } } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java index 57a4e67..7a44ea0 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.PostgresqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super("postgres"); + super(PostgresqlServiceInfo.URI_SCHEMA); } @Override diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java index 35bf83b..9915ffa 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java @@ -13,15 +13,15 @@ import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.service.common.PostgresqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class HerokuConnectorPostgresqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest { public HerokuConnectorPostgresqlServiceTest() { - super("postgres"); + super(PostgresqlServiceInfo.URI_SCHEMA); } - + @Test public void postgresqlServiceCreation() { Map env = new HashMap(); From b46aa7addfa2bfdfdcc03e9476aab6a17a8325bc Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:38:52 -0500 Subject: [PATCH 12/52] pull up Redis URI scheme --- .../cloud/cloudfoundry/RedisServiceInfoCreator.java | 3 ++- .../cloud/service/common/RedisServiceInfo.java | 9 ++++++--- .../cloud/heroku/RedisServiceInfoCreator.java | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java index 75e6df1..f8fcfa3 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java @@ -12,7 +12,8 @@ import org.springframework.cloud.service.common.RedisServiceInfo; public class RedisServiceInfoCreator extends CloudFoundryServiceInfoCreator { public RedisServiceInfoCreator() { - super(new Tags("redis"), "redis"); + // the literal in the tag is CloudFoundry-specific + super(new Tags("redis"), RedisServiceInfo.URI_SCHEME); } public RedisServiceInfo createServiceInfo(Map serviceData) { diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java index d31be25..ab35a8e 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java @@ -4,16 +4,19 @@ import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("redis") public class RedisServiceInfo extends UriBasedServiceInfo { + + public static final String URI_SCHEME = "redis"; + public RedisServiceInfo(String id, String host, int port, String password) { - super(id, "redis", host, port, null, password, null); + super(id, URI_SCHEME, host, port, null, password, null); } - + public RedisServiceInfo(String id, String uri) { super(id, uri); } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java index cfa88ad..1757bd7 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.RedisServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class RedisServiceInfoCreator extends HerokuServiceInfoCreator { public RedisServiceInfoCreator() { - super("redis"); + super(RedisServiceInfo.URI_SCHEME); } @Override From 1748257f64f7db1fa8fde5382edaf7b0253a3c23 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:40:42 -0500 Subject: [PATCH 13/52] pull up SMTP URI scheme --- .../cloud/cloudfoundry/SmtpServiceInfoCreator.java | 13 +++++++------ .../cloud/service/common/SmtpServiceInfo.java | 6 ++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java index ccf7560..10bd6e5 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java @@ -6,7 +6,7 @@ import org.springframework.cloud.service.common.SmtpServiceInfo; import org.springframework.cloud.util.UriInfo; /** - * + * * @author Ramnivas Laddad * */ @@ -15,16 +15,17 @@ public class SmtpServiceInfoCreator extends CloudFoundryServiceInfoCreator serviceData) { String id = (String) serviceData.get("name"); - + @SuppressWarnings("unchecked") Map credentials = (Map) serviceData.get("credentials"); String host = (String) credentials.get("hostname"); - + int port = DEFAULT_SMTP_PORT; if (credentials.containsKey("port")) { port = Integer.parseInt(credentials.get("port").toString()); @@ -33,8 +34,8 @@ public class SmtpServiceInfoCreator extends CloudFoundryServiceInfoCreator Date: Thu, 10 Jul 2014 12:34:45 -0500 Subject: [PATCH 14/52] blank new module --- settings.gradle | 3 +- spring-cloud-localconfig-connector/.gitignore | 1 + spring-cloud-localconfig-connector/README.md | 59 +++++++++++++++++++ .../build.gradle | 5 ++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-localconfig-connector/.gitignore create mode 100644 spring-cloud-localconfig-connector/README.md create mode 100644 spring-cloud-localconfig-connector/build.gradle diff --git a/settings.gradle b/settings.gradle index c22faa4..bc6b88f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,5 @@ rootProject.name = "spring-cloud" include "${rootProject.name}-core" include "${rootProject.name}-cloudfoundry-connector" include "${rootProject.name}-spring-service-connector" -include "${rootProject.name}-heroku-connector" \ No newline at end of file +include "${rootProject.name}-heroku-connector" +include "${rootProject.name}-localconfig-connector" diff --git a/spring-cloud-localconfig-connector/.gitignore b/spring-cloud-localconfig-connector/.gitignore new file mode 100644 index 0000000..5e56e04 --- /dev/null +++ b/spring-cloud-localconfig-connector/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/spring-cloud-localconfig-connector/README.md b/spring-cloud-localconfig-connector/README.md new file mode 100644 index 0000000..f9788aa --- /dev/null +++ b/spring-cloud-localconfig-connector/README.md @@ -0,0 +1,59 @@ +Local-configuration connector for Spring Cloud +======================================= + +Provides the ability to configure Spring Cloud services locally for development or testing. +The current implementation reads from Java properties only; in order to prevent dependencies +on the Spring Framework, the placeholder functionality is unavailable in the connector. +Pull requests for also inspecting environment variables are welcome. + +Property sources +---------------- +This connector first attempts to read the system properties generally and a property named +`spring.cloud.propertiesFile` specifically. If the system properties are not readable +(the security manager denies `checkPropertiesAccess`), then they will be treated as empty. +If a system property named `spring.cloud.propertiesFile` is found, that file will be loaded +as a property list. + +###Programmatically supplying properties +You can programmatically supply a property source by calling the static method +`LocalConfigConnector.supplyProperties(InputStream)` before invoking `getCloud()`. +Calling this method will cause the connector to read the stream as a property list +and then close the stream. Calling this method after invoking `getCloud()` will +still read the stream, but the properties will have no effect on the connector +service configuration. Calling this method multiple times will load the supplied +streams onto the same `Properties` object, overwriting duplicates. + +###Property order +To provide the maximum configuration flexibility, the connector will scan the available +property sources in this order: + +- programmatically-supplied properties +- properties read from `spring.cloud.propertiesFile` +- system properties + +The last definition of a specific service ID wins. The connector will log a message at +`INFO` to notify of service overrides for the same type of service and at `WARN` if you +override a service ID with a URI to a different type of service. + +Activating the connector +------------------------ +The Spring Cloud core expects exactly one cloud connector to return `true` for +`isInMatchingCloud()`. This connector identifies the "local cloud" by the presence of +a property named `spring.cloud.appId`, which will be used in the `ApplicationInstanceInfo`. + +Service definitions +------------------- +If the connector is activated, it will iterate through all the available properties +for keys matching the pattern `spring.cloud.{serviceId}`. Each value is interpreted as a URI +to the services, and the type of service is determined from the scheme. All of the standard +`UriBasedServiceInfo`s are supported. + +Supporting additional services +------------------------------ +Please see the documentation for [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector), since the same +mechanism applies to any cloud connector. + +Instance ID +----------- +This connector will create a UUID for use as the instance ID, as Java does not provide +any portable mechanism for reliably determining hostnames or PIDs. \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/build.gradle b/spring-cloud-localconfig-connector/build.gradle new file mode 100644 index 0000000..eb5f5b6 --- /dev/null +++ b/spring-cloud-localconfig-connector/build.gradle @@ -0,0 +1,5 @@ +description = 'Spring Cloud local-configuration connector' + +dependencies { + compile project(':spring-cloud-core') +} From b8bd6989440bc2e34164f2a5dc061ab9ef785d1b Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 13:17:43 -0500 Subject: [PATCH 15/52] pull up fallback BaseServiceInfo creator (just a generic KVP creator) --- .../service/FallbackBaseServiceInfoCreator.java | 11 +++++++++++ .../cloud/heroku/HerokuConnector.java | 12 +++--------- 2 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java new file mode 100644 index 0000000..23a815a --- /dev/null +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java @@ -0,0 +1,11 @@ +package org.springframework.cloud.service; + +import org.springframework.cloud.FallbackServiceInfoCreator; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public class FallbackBaseServiceInfoCreator extends FallbackServiceInfoCreator { + @Override + public BaseServiceInfo createServiceInfo(KeyValuePair serviceData) { + return new BaseServiceInfo(serviceData.getKey()); + } +} diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java index ac39931..ab91ba0 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java @@ -12,6 +12,7 @@ import org.springframework.cloud.FallbackServiceInfoCreator; import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; +import org.springframework.cloud.service.FallbackBaseServiceInfoCreator; import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.util.EnvironmentAccessor; @@ -95,13 +96,6 @@ public class HerokuConnector extends AbstractCloudConnector { @Override protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { - return new HerokuFallbackServiceInfoCreator(); + return new FallbackBaseServiceInfoCreator(); } -} - -class HerokuFallbackServiceInfoCreator extends FallbackServiceInfoCreator { - @Override - public BaseServiceInfo createServiceInfo(KeyValuePair serviceData) { - return new BaseServiceInfo(serviceData.getKey()); - } -} +} \ No newline at end of file From c9fbf933316a6e90bebbc302a0d2e4fe72a3b5fb Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 16:18:31 -0500 Subject: [PATCH 16/52] initial local-config connector implementation; provides ServiceData, still needs converters to ServiceInfo --- spring-cloud-localconfig-connector/README.md | 5 +- .../build.gradle | 1 + .../localconfig/LocalConfigConnector.java | 187 ++++++++++++++++++ .../LocalConfigServiceInfoCreator.java | 11 ++ .../cloud/localconfig/LocalConfigUtil.java | 81 ++++++++ .../localconfig/LocalConfigConnectorTest.java | 145 ++++++++++++++ .../localconfig/LocalConfigUtilTest.java | 74 +++++++ .../src/test/resources/localconfig.properties | 3 + 8 files changed, 504 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.properties diff --git a/spring-cloud-localconfig-connector/README.md b/spring-cloud-localconfig-connector/README.md index f9788aa..1f04dc9 100644 --- a/spring-cloud-localconfig-connector/README.md +++ b/spring-cloud-localconfig-connector/README.md @@ -8,7 +8,7 @@ Pull requests for also inspecting environment variables are welcome. Property sources ---------------- -This connector first attempts to read the system properties generally and a property named +This connector first attempts to read the system properties generally and a system property named `spring.cloud.propertiesFile` specifically. If the system properties are not readable (the security manager denies `checkPropertiesAccess`), then they will be treated as empty. If a system property named `spring.cloud.propertiesFile` is found, that file will be loaded @@ -32,8 +32,7 @@ property sources in this order: - system properties The last definition of a specific service ID wins. The connector will log a message at -`INFO` to notify of service overrides for the same type of service and at `WARN` if you -override a service ID with a URI to a different type of service. +`WARN` if you override a service ID. Activating the connector ------------------------ diff --git a/spring-cloud-localconfig-connector/build.gradle b/spring-cloud-localconfig-connector/build.gradle index eb5f5b6..d020bde 100644 --- a/spring-cloud-localconfig-connector/build.gradle +++ b/spring-cloud-localconfig-connector/build.gradle @@ -2,4 +2,5 @@ description = 'Spring Cloud local-configuration connector' dependencies { compile project(':spring-cloud-core') + testCompile 'com.github.stefanbirkner:system-rules:1.5.0' } diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java new file mode 100644 index 0000000..93bb25f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -0,0 +1,187 @@ +package org.springframework.cloud.localconfig; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Properties; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import org.springframework.cloud.AbstractCloudConnector; +import org.springframework.cloud.FallbackServiceInfoCreator; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.app.ApplicationInstanceInfo; +import org.springframework.cloud.app.BasicApplicationInstanceInfo; +import org.springframework.cloud.service.BaseServiceInfo; +import org.springframework.cloud.service.FallbackBaseServiceInfoCreator; + +/** + * + * @author Christopher Smith + * + */ +public class LocalConfigConnector extends AbstractCloudConnector { + + private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); + + /*--------------- String constants for property keys ---------------*/ + + public static final String PROPERTY_PREFIX = "spring.cloud."; + + public static final Pattern SERVICE_PROPERTY_PATTERN = Pattern.compile("\\A" + Pattern.quote(PROPERTY_PREFIX) + "(.+)" + "\\Z"); + + public static final String APP_ID_PROPERTY = PROPERTY_PREFIX + "appId"; + + public static final String PROPERTIES_FILE_PROPERTY = PROPERTY_PREFIX + "propertiesFile"; + + /** + * These properties configure the connector itself and aren't service definitions. + */ + public static final List META_PROPERTIES = Collections.unmodifiableList( + Arrays.asList(new String[] { APP_ID_PROPERTY, PROPERTIES_FILE_PROPERTY })); + + /*--------------- sources for service-definition properties ---------------*/ + + static Properties programmaticProperties = new Properties(); + + private Properties fileProperties = null; + + /*--------------- API implementation ---------------*/ + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public LocalConfigConnector() { + super((Class) LocalConfigServiceInfoCreator.class); + } + + /** + * Returns {@code true} if a property named {@code spring.cloud.appId} is present in any of the property sources. + * On the first call, attempts to load properties from a file specified in {@code spring.cloud.propertiesFile}. + */ + @Override + public boolean isInMatchingCloud() { + if (fileProperties == null) + readFileProperties(); + + return findProperty(APP_ID_PROPERTY) != null; + } + + @Override + public ApplicationInstanceInfo getApplicationInstanceInfo() { + return new BasicApplicationInstanceInfo(UUID.randomUUID().toString(), findProperty(APP_ID_PROPERTY), + Collections. emptyMap()); + } + + @Override + protected List getServicesData() { + LinkedHashMap propertySources = new LinkedHashMap(); + + propertySources.put("programmatic properties", programmaticProperties); + propertySources.put("properties from file", fileProperties); + try { + propertySources.put("system properties", System.getProperties()); + } catch (SecurityException e) { + logger.log(Level.WARNING, + "couldn't read system properties; no service definitions from system properties will be applied", e); + } + + return LocalConfigUtil.readServicesData(propertySources); + } + + @Override + protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { + return new FallbackBaseServiceInfoCreator(); + } + + /*--------------- methods for manipulating properties and sources ---------------*/ + + /** + * Adds properties to be scanned from the supplied {@link InputStream}, overwriting + * existing properties with the same name. Closes the stream after loading. + * + * @param propertiesInputStream + * a property list + * @throws IOException + * if the underlying load operation throws an exception + */ + public static void supplyProperties(final InputStream propertiesInputStream) throws IOException { + programmaticProperties.load(propertiesInputStream); + propertiesInputStream.close(); + } + + /** + * Checks for the presence of a supplied or system property named {@code spring.cloud.propertiesFile}. If the property + * is present, load its contents into {@link #fileProperties}. If there's a problem, log but continue. + */ + private void readFileProperties() { + fileProperties = new Properties(); + logger.fine("looking for a properties file"); + + String filename = null; + + filename = programmaticProperties.getProperty(PROPERTIES_FILE_PROPERTY); + + try { + filename = System.getProperty(PROPERTIES_FILE_PROPERTY, filename); + } catch (SecurityException e) { + logSystemReadException(PROPERTIES_FILE_PROPERTY, e); + return; + } + + if (filename == null) { + logger.info("did not find a system property " + PROPERTIES_FILE_PROPERTY); + return; + } + + logger.info("loading properties from file " + filename); + + try { + InputStream fis = openFile(filename); + fileProperties.load(fis); + } catch (IOException e) { + logger.log(Level.SEVERE, "exception while loading properties from file " + filename, e); + return; + } + + logger.info("properties loaded successfully"); + } + + /** + * Broken out into a separate method for mocking the filesystem. + * @param filename the file to open + * @return a {@code FileInputStream} to the file + * @throws IOException if opening the file throws + */ + InputStream openFile(String filename) throws IOException { + return new FileInputStream(filename); + } + + /** + * Look for a specific property in programmatically-supplied properties, properties from a file, + * or the system properties. Last source wins. + * + * @param key + * the property to look for + * @return the highest-priority value for the key, or {@code null} if the key is not found + */ + private String findProperty(String key) { + String value = programmaticProperties.getProperty(key); + value = fileProperties.getProperty(key, value); + try { + value = System.getProperty(key, value); + } catch (SecurityException e) { + logSystemReadException(key, e); + } + + return value; + } + + private static void logSystemReadException(String key, SecurityException e) { + logger.log(Level.WARNING, "couldn't read system property " + key, e); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java new file mode 100644 index 0000000..98a8669 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java @@ -0,0 +1,11 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfoCreator; + +public abstract class LocalConfigServiceInfoCreator extends UriBasedServiceInfoCreator { + + protected LocalConfigServiceInfoCreator(String uriScheme) { + super(uriScheme); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java new file mode 100644 index 0000000..bd4d9f3 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -0,0 +1,81 @@ +package org.springframework.cloud.localconfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Logger; +import java.util.regex.Matcher; + +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public final class LocalConfigUtil { + private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); + + private LocalConfigUtil() { + } + + static List readServicesData(LinkedHashMap propertySources) { + // we'll turn this into KVPs to return but need to eliminate duplicates first + Map collectedServices = new HashMap(); + + // iterate over the property sources in order, extracting matching properties + for (Map.Entry propertySource : propertySources.entrySet()) { + logger.info("reading services from " + propertySource.getValue()); + Map services = readServices(propertySource.getValue()); + + // add each of the found services to the list, warning about duplicates + for (Map.Entry service : services.entrySet()) { + String oldUri = collectedServices.put(service.getKey(), service.getValue()); + if (oldUri == null) + logger.info("added service '" + service.getKey() + "' from " + propertySource.getKey()); + else + logger.warning("replaced service '" + service.getKey() + "' with new URI from " + propertySource.getKey()); + } + } + + // now we have a collated set of service IDs and URIs + List serviceData = new ArrayList(collectedServices.size()); + for (Map.Entry serviceInfo : collectedServices.entrySet()) { + serviceData.add(new KeyValuePair(serviceInfo.getKey(), serviceInfo.getValue())); + } + + return serviceData; + } + + /** + * Goes through a {@code Properties} object, finding all service definitions (properties + * prefixed with {@code spring.cloud.} but not in {@code META_PROPERTIES}) and collects {@code (id,URI)} pairs. + * + * @param properties + * the {@code Properties} object to read + * @return all of the service definitions found + */ + static Map readServices(Properties properties) { + Map services = new HashMap(); + + for (String propertyName : properties.stringPropertyNames()) { + if (LocalConfigConnector.META_PROPERTIES.contains(propertyName)) { + logger.finer("skipping meta property " + propertyName); + continue; + } + + Matcher m = LocalConfigConnector.SERVICE_PROPERTY_PATTERN.matcher(propertyName); + if (!m.matches()) { + logger.finest("skipping non-Spring-Cloud property " + propertyName); + continue; + } + + String serviceId = m.group(1); + String serviceUri = properties.getProperty(propertyName); + + // no URI here because they will contain passwords + logger.fine("found service URI for service " + serviceId); + services.put(serviceId, serviceUri); + } + + return services; + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java new file mode 100644 index 0000000..394e851 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -0,0 +1,145 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.ClearSystemProperties; +import org.junit.contrib.java.lang.system.ProvideSystemProperty; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public class LocalConfigConnectorTest { + + static final Charset UTF_8 = Charset.forName("UTF-8"); + + public static final String APP_ID_1 = "appId1"; + public static final String APP_ID_1_PROPERTY = LocalConfigConnector.APP_ID_PROPERTY + ": " + APP_ID_1; + + public static final String APP_ID_2 = "appId2"; + public static final String APP_ID_2_PROPERTY = LocalConfigConnector.APP_ID_PROPERTY + ": " + APP_ID_2; + + public static final String PROPERTY_FILE_NAME = "propFile"; + public static final String PROPERTY_FILE_PROPERTY = LocalConfigConnector.PROPERTIES_FILE_PROPERTY + ": " + PROPERTY_FILE_NAME; + + public static class AppIdTest { + + private LocalConfigConnector connector; + + @Before + public void setup() { + connector = new LocalConfigConnector(); + } + + @After + public void clearProperties() { + LocalConfigConnector.programmaticProperties = new Properties(); + } + + @Rule + public final ClearSystemProperties NO_APP_ID_PROPERTY = new ClearSystemProperties(LocalConfigConnector.APP_ID_PROPERTY); + + @Test + public void testNoAppIdAnywhere() { + assertFalse(connector.isInMatchingCloud()); + } + + @Test + public void testProgrammaticAppId() throws IOException { + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(APP_ID_1_PROPERTY.getBytes(UTF_8))); + assertTrue(connector.isInMatchingCloud()); + assertEquals(APP_ID_1, connector.getApplicationInstanceInfo().getAppId()); + } + + @Test + public void testProgrammaticAndFileAppIds() throws IOException { + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(APP_ID_1_PROPERTY.getBytes(UTF_8))); + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(PROPERTY_FILE_PROPERTY.getBytes(UTF_8))); + + LocalConfigConnector stubConnector = new LocalConfigConnector() { + @Override + InputStream openFile(String filename) throws IOException { + assertEquals(PROPERTY_FILE_NAME, filename); + return new ByteArrayInputStream(APP_ID_2_PROPERTY.getBytes(UTF_8)); + }; + }; + + assertTrue(stubConnector.isInMatchingCloud()); + assertEquals(APP_ID_2, stubConnector.getApplicationInstanceInfo().getAppId()); + } + + @Test + public void testProgrammaticFilenamePlusSystemAppId() throws IOException { + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(PROPERTY_FILE_PROPERTY.getBytes(UTF_8))); + + LocalConfigConnector stubConnector = new LocalConfigConnector() { + @Override + InputStream openFile(String filename) throws IOException { + assertEquals(PROPERTY_FILE_NAME, filename); + return new ByteArrayInputStream(APP_ID_2_PROPERTY.getBytes(UTF_8)); + }; + }; + + System.setProperty(LocalConfigConnector.APP_ID_PROPERTY, "helloApp"); + assertTrue(stubConnector.isInMatchingCloud()); + assertEquals("helloApp", stubConnector.getApplicationInstanceInfo().getAppId()); + } + } + + private LocalConfigConnector connector; + + InputStream propertiesFile; + + @Before + public void setup() { + connector = new LocalConfigConnector(); + propertiesFile = LocalConfigConnectorTest.class.getClassLoader().getResourceAsStream("localconfig.properties"); + } + + @After + public void cleanup() throws IOException { + LocalConfigConnector.programmaticProperties = new Properties(); + propertiesFile.close(); + } + + @Test + public void testLoadFromFile() throws IOException { + LocalConfigConnector.supplyProperties(propertiesFile); + + assertTrue(connector.isInMatchingCloud()); + assertEquals("testApp", connector.getApplicationInstanceInfo().getAppId()); + + List services = connector.getServicesData(); + assertEquals(2, services.size()); + for (KeyValuePair service : services) + if ("foo".equals(service.getKey())) + assertEquals("bar", service.getValue()); + } + + @Rule + public ProvideSystemProperty BAZ_PROPERTY = new ProvideSystemProperty("spring.cloud.baz", "inline!"); + + @Test + public void testLoadFromInputStreamWithOverride() throws IOException { + LocalConfigConnector.supplyProperties(propertiesFile); + + assertTrue(connector.isInMatchingCloud()); + assertEquals("testApp", connector.getApplicationInstanceInfo().getAppId()); + + List services = connector.getServicesData(); + assertEquals(2, services.size()); + for(KeyValuePair service: services) + if("baz".equals(service.getKey())) + assertEquals("inline!", service.getValue()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java new file mode 100644 index 0000000..10eaa58 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java @@ -0,0 +1,74 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.*; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public class LocalConfigUtilTest { + + private Properties first, second; + + private LinkedHashMap propertySources; + + @Before + public void initProperties(){ + first = new Properties(); + second = new Properties(); + + propertySources = new LinkedHashMap(); + propertySources.put("first", first); + propertySources.put("second", second); + } + + @Test + public void testPropertyParsing() { + first.setProperty("spring.cloud.appId", "should skip me because I'm meta"); + first.setProperty("spring.cloud.service1", "one"); + first.setProperty("spring.cloud.", "should skip me because I don't have an ID"); + first.setProperty("spring.cloud.service.two", "two"); + first.setProperty("foobar", "should skip me because I don't match the prefix"); + + Map services = LocalConfigUtil.readServices(first); + assertEquals(2, services.size()); + assertEquals("one", services.get("service1")); + assertEquals("two", services.get("service.two")); + } + + @Test + public void testCollation() { + first.setProperty("spring.cloud.first", "firstUri"); + second.setProperty("spring.cloud.second", "secondUri"); + + List serviceData = LocalConfigUtil.readServicesData(propertySources); + assertEquals(2, serviceData.size()); + boolean foundFirst = false; + + for(KeyValuePair kvp : serviceData) { + if(kvp.getKey().equals("first")) { + assertEquals("firstUri", kvp.getValue()); + foundFirst = true; + } + } + + assertTrue(foundFirst); + } + + @Test + public void testOverride() { + first.setProperty("spring.cloud.duplicate", "firstUri"); + second.setProperty("spring.cloud.duplicate", "secondUri"); + + List serviceData = LocalConfigUtil.readServicesData(propertySources); + assertEquals(1, serviceData.size()); + KeyValuePair kvp = serviceData.get(0); + assertEquals("duplicate", kvp.getKey()); + assertEquals("secondUri", kvp.getValue()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties new file mode 100644 index 0000000..bcc84c3 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties @@ -0,0 +1,3 @@ +spring.cloud.appId: testApp +spring.cloud.foo: bar +spring.cloud.baz: quux \ No newline at end of file From 0c9c2b5ad500525f6c03d5388ef1294f17f229b5 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 16:23:37 -0500 Subject: [PATCH 17/52] typo in constant name --- .../cloud/cloudfoundry/PostgresqlServiceInfoCreator.java | 2 +- .../cloud/service/common/PostgresqlServiceInfo.java | 2 +- .../cloud/heroku/PostgresqlServiceInfoCreator.java | 2 +- .../cloud/heroku/HerokuConnectorPostgresqlServiceTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java index 4b38fbf..abfbde1 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java @@ -10,7 +10,7 @@ import org.springframework.cloud.service.common.PostgresqlServiceInfo; public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super(new Tags("postgresql"), PostgresqlServiceInfo.URI_SCHEMA); + super(new Tags("postgresql"), PostgresqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java index 2927782..edcace5 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java @@ -13,7 +13,7 @@ public class PostgresqlServiceInfo extends RelationalServiceInfo { public static final String JDBC_URL_TYPE = "postgresql"; - public static final String URI_SCHEMA = "postgres"; + public static final String URI_SCHEME = "postgres"; public PostgresqlServiceInfo(String id, String url) { super(id, url, JDBC_URL_TYPE); diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java index 7a44ea0..70f47de 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java @@ -10,7 +10,7 @@ import org.springframework.cloud.service.common.PostgresqlServiceInfo; public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super(PostgresqlServiceInfo.URI_SCHEMA); + super(PostgresqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java index 9915ffa..52d7398 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java @@ -19,7 +19,7 @@ import org.springframework.cloud.service.common.PostgresqlServiceInfo; */ public class HerokuConnectorPostgresqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest { public HerokuConnectorPostgresqlServiceTest() { - super(PostgresqlServiceInfo.URI_SCHEMA); + super(PostgresqlServiceInfo.URI_SCHEME); } @Test From 7fd502d707a354130592c07f874709748249f8cb Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 16:28:06 -0500 Subject: [PATCH 18/52] document Java version requirement --- spring-cloud-core/README.md | 40 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/spring-cloud-core/README.md b/spring-cloud-core/README.md index 52c4d45..80233e4 100644 --- a/spring-cloud-core/README.md +++ b/spring-cloud-core/README.md @@ -2,10 +2,12 @@ Spring Cloud Core Library ========================= The core library to let cloud applications access application information and services. -While Spring applications is one of the main target for this library, it may be used in +While Spring applications is one of the main target for this library, it may be used in non-Spring projects as well. In fact, **this library doesn't even depend on Spring**. -This library is cloud-agnostic. Through connectors, it supports multiple clouds +This library requires Java 6, + +This library is cloud-agnostic. Through connectors, it supports multiple clouds (with Cloud Foundry and Heroku as the example clouds). This library also supports an extension to create services connectors of user-desired types. @@ -13,11 +15,11 @@ This library also supports an extension to create services connectors of user-de Usage pattern: Application Developers ===================================== -> **Note:** If you are using spring-cloud in a Spring application, you should consider using the -[Java config](../spring-cloud-spring-service-connector#the-java-config) or the +> **Note:** If you are using spring-cloud in a Spring application, you should consider using the +[Java config](../spring-cloud-spring-service-connector#the-java-config) or the [XML namespace support](../spring-cloud-spring-service-connector#the-cloud-namespace) instead. -* Create a [`CloudFactory`](src/main/java/org/springframework/cloud/CloudFactory.java) instance. +* Create a [`CloudFactory`](src/main/java/org/springframework/cloud/CloudFactory.java) instance. Creation of a `CloudFactory` instance is a bit expensive, so caching such an instance is recommended. If you are using a dependency injection frameworks such as Spring, creating a bean for `CloudFactory` will achieve the caching effect. @@ -25,45 +27,45 @@ Usage pattern: Application Developers ```java CloudFactory cloudFactory = new CloudFactory(); ``` -* Obtain a suitable [`Cloud`](src/main/java/org/springframework/cloud/Cloud.java) for the environment +* Obtain a suitable [`Cloud`](src/main/java/org/springframework/cloud/Cloud.java) for the environment in which the application is running. - + ```java Cloud cloud = cloudFactory.getCloud(); ``` Note that you must have a `CloudConnector` implementation suitable for the environment in which the application is being deployed in your classpath. For example, if you are - deploying the application in Cloud Foundry, you must add [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) + deploying the application in Cloud Foundry, you must add [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) in your classpath. If no suitable `CloudConnctor` is found, the `getCloud()` method will throw a `CloudException`. -* Use the `Cloud` instance to get access to application info, service infos, and create service +* Use the `Cloud` instance to get access to application info, service infos, and create service connectors. ```java // ServiceInfo has all the information necessary to connect to the underlying service cloud.getServiceInfos(); ``` - + ```java // Alternatively, let the cloud create a service connector for you DataSource ds = cloud.getServiceConnector("inventory-db", DataSource.class, null /* default config */); ``` - + Usage pattern: Cloud and Service Providers ========================================== A cloud provider may extends the functionality in two ways: -1. Add new [`CloudConnector`](src/main/java/org/springframework/cloud/CloudConnector.java)s to make - spring-cloud related libraries work with a new cloud. - See [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) - or [heroku-connector](../spring-cloud-heroku-connector) for an example. +1. Add new [`CloudConnector`](src/main/java/org/springframework/cloud/CloudConnector.java)s to make + spring-cloud related libraries work with a new cloud. + See [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) + or [heroku-connector](../spring-cloud-heroku-connector) for an example. This is done declaratively by adding connector classes to: ``` META-INF/services/org.springframework.cloud.CloudConnector ``` -2. Add new [`ServiceConnectorCreator`](src/main/java/org/springframework/cloud/service/ServiceConnectorCreator.java)s - to allow creation of service connector objects. - See [spring-service-connector](../spring-cloud-spring-service-connector) for an example. - This is done declaratively by adding creator classes to: +2. Add new [`ServiceConnectorCreator`](src/main/java/org/springframework/cloud/service/ServiceConnectorCreator.java)s + to allow creation of service connector objects. + See [spring-service-connector](../spring-cloud-spring-service-connector) for an example. + This is done declaratively by adding creator classes to: ``` META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator ``` \ No newline at end of file From 8afa0cdcbd7d3e30ad320b37ef8e419632bd8c49 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 17:01:14 -0500 Subject: [PATCH 19/52] add ServiceInfoCreators and SPI control files --- .../localconfig/AmqpServiceInfoCreator.java | 20 +++++++++++++++++++ .../localconfig/MongoServiceInfoCreator.java | 20 +++++++++++++++++++ .../localconfig/MysqlServiceInfoCreator.java | 20 +++++++++++++++++++ .../PostgresqlServiceInfoCreator.java | 20 +++++++++++++++++++ .../localconfig/RedisServiceInfoCreator.java | 20 +++++++++++++++++++ .../org.springframework.cloud.CloudConnector | 1 + ....localconfig.LocalConfigServiceInfoCreator | 5 +++++ 7 files changed, 106 insertions(+) create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector create mode 100644 spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java new file mode 100644 index 0000000..b9dc631 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.AmqpServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class AmqpServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public AmqpServiceInfoCreator() { + super(AmqpServiceInfo.URI_SCHEME); + } + + @Override + public AmqpServiceInfo createServiceInfo(String id, String uri) { + return new AmqpServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java new file mode 100644 index 0000000..68671ac --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.MongoServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class MongoServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public MongoServiceInfoCreator() { + super(MongoServiceInfo.URI_SCHEME); + } + + @Override + public MongoServiceInfo createServiceInfo(String id, String uri) { + return new MongoServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java new file mode 100644 index 0000000..0d39262 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.MysqlServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class MysqlServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public MysqlServiceInfoCreator() { + super(MysqlServiceInfo.URI_SCHEME); + } + + @Override + public MysqlServiceInfo createServiceInfo(String id, String uri) { + return new MysqlServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java new file mode 100644 index 0000000..282da2f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.PostgresqlServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class PostgresqlServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public PostgresqlServiceInfoCreator() { + super(PostgresqlServiceInfo.URI_SCHEME); + } + + @Override + public PostgresqlServiceInfo createServiceInfo(String id, String uri) { + return new PostgresqlServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java new file mode 100644 index 0000000..7a9e06f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.RedisServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class RedisServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public RedisServiceInfoCreator() { + super(RedisServiceInfo.URI_SCHEME); + } + + @Override + public RedisServiceInfo createServiceInfo(String id, String uri) { + return new RedisServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector new file mode 100644 index 0000000..2a7adb6 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector @@ -0,0 +1 @@ +org.springframework.cloud.localconfig.LocalConfigConnector \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator new file mode 100644 index 0000000..f8a14d4 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator @@ -0,0 +1,5 @@ +org.springframework.cloud.localconfig.AmqpServiceInfoCreator +org.springframework.cloud.localconfig.MongoServiceInfoCreator +org.springframework.cloud.localconfig.MysqlServiceInfoCreator +org.springframework.cloud.localconfig.PostgresqlServiceInfoCreator +org.springframework.cloud.localconfig.RedisServiceInfoCreator \ No newline at end of file From eb080ce4afc6e1503f748a9cf69b4bb01dfa55d0 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 15:34:38 -0500 Subject: [PATCH 20/52] rename test case for clarity --- .../cloud/localconfig/LocalConfigConnectorTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java index 394e851..40b3913 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -32,7 +32,7 @@ public class LocalConfigConnectorTest { public static final String PROPERTY_FILE_NAME = "propFile"; public static final String PROPERTY_FILE_PROPERTY = LocalConfigConnector.PROPERTIES_FILE_PROPERTY + ": " + PROPERTY_FILE_NAME; - public static class AppIdTest { + public static class DetectAppIdTest { private LocalConfigConnector connector; From 7a686ab0c421e718dbc7c34a0d4af2af4510a30f Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 15:38:09 -0500 Subject: [PATCH 21/52] move property file name into constant, rename --- .../cloud/localconfig/LocalConfigConnectorTest.java | 4 ++-- .../src/test/resources/localconfig.nonsense.properties | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java index 40b3913..dd75a33 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -29,7 +29,7 @@ public class LocalConfigConnectorTest { public static final String APP_ID_2 = "appId2"; public static final String APP_ID_2_PROPERTY = LocalConfigConnector.APP_ID_PROPERTY + ": " + APP_ID_2; - public static final String PROPERTY_FILE_NAME = "propFile"; + public static final String PROPERTY_FILE_NAME = "localconfig.nonsense.properties"; public static final String PROPERTY_FILE_PROPERTY = LocalConfigConnector.PROPERTIES_FILE_PROPERTY + ": " + PROPERTY_FILE_NAME; public static class DetectAppIdTest { @@ -103,7 +103,7 @@ public class LocalConfigConnectorTest { @Before public void setup() { connector = new LocalConfigConnector(); - propertiesFile = LocalConfigConnectorTest.class.getClassLoader().getResourceAsStream("localconfig.properties"); + propertiesFile = LocalConfigConnectorTest.class.getClassLoader().getResourceAsStream(PROPERTY_FILE_NAME); } @After diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties new file mode 100644 index 0000000..bcc84c3 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties @@ -0,0 +1,3 @@ +spring.cloud.appId: testApp +spring.cloud.foo: bar +spring.cloud.baz: quux \ No newline at end of file From 5b95a2b616595aff129a6e07e0ca2d40039699e0 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:00:08 -0500 Subject: [PATCH 22/52] constant wasn't final --- .../cloud/heroku/AbstractHerokuConnectorTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java index 7b88bf9..576dcfc 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java @@ -10,7 +10,7 @@ import org.springframework.cloud.util.EnvironmentAccessor; /** * Base test class that provides setup and utility methods to generate test payload - * + * * @author Ramnivas Laddad * */ @@ -20,7 +20,7 @@ public abstract class AbstractHerokuConnectorTest { protected static final String hostname = "10.20.30.40"; protected static final int port = 1234; - protected static String username = "myuser"; + protected static final String username = "myuser"; protected static final String password = "mypass"; @Before @@ -28,7 +28,7 @@ public abstract class AbstractHerokuConnectorTest { MockitoAnnotations.initMocks(this); testCloudConnector.setCloudEnvironment(mockEnvironment); } - + protected static ServiceInfo getServiceInfo(List serviceInfos, String serviceId) { for (ServiceInfo serviceInfo : serviceInfos) { if (serviceInfo.getId().equals(serviceId)) { From 1a782670b1a8a7d2648a94b88b826ab104e27496 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:18:29 -0500 Subject: [PATCH 23/52] add getScheme() and a useful toString() --- .../cloud/service/UriBasedServiceInfo.java | 146 ++++++++++-------- 1 file changed, 79 insertions(+), 67 deletions(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java index 78828de..fda552c 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java @@ -6,84 +6,96 @@ import org.springframework.cloud.util.UriInfoFactory; /** * Common class for all {@link ServiceInfo}s - * + * * @author Ramnivas Laddad * */ public abstract class UriBasedServiceInfo extends BaseServiceInfo { - private UriInfo uriInfo; + private UriInfo uriInfo; - private static UriInfoFactory uriFactory = new StandardUriInfoFactory(); + private static UriInfoFactory uriFactory = new StandardUriInfoFactory(); - public UriBasedServiceInfo(String id, String scheme, String host, int port, String username, String password, String path) { - super(id); - this.uriInfo = getUriInfoFactory().createUri(scheme, host, port, username, password, path); - this.uriInfo = validateAndCleanUriInfo(uriInfo); - } - - public UriBasedServiceInfo(String id, String uriString) { - super(id); - this.uriInfo = getUriInfoFactory().createUri(uriString); - this.uriInfo = validateAndCleanUriInfo(uriInfo); - } + public UriBasedServiceInfo(String id, String scheme, String host, int port, String username, String password, String path) { + super(id); + this.uriInfo = getUriInfoFactory().createUri(scheme, host, port, username, password, path); + this.uriInfo = validateAndCleanUriInfo(uriInfo); + } - /** - * For URI-based (@link ServiceInfo}s which don't conform to the standard URI - * format, override this method in your own ServiceInfo class to return a - * {@link UriInfoFactory} which will create the appropriate URIs. - * - * @return your special UriInfoFactory - */ - public UriInfoFactory getUriInfoFactory() { - return uriFactory; - } + public UriBasedServiceInfo(String id, String uriString) { + super(id); + this.uriInfo = getUriInfoFactory().createUri(uriString); + this.uriInfo = validateAndCleanUriInfo(uriInfo); + } - @ServiceProperty(category="connection") - public String getUri() { - return uriInfo.getUri().toString(); - } - - @ServiceProperty(category="connection") - public String getUserName() { - return uriInfo.getUserName(); - } - - @ServiceProperty(category="connection") - public String getPassword() { - return uriInfo.getPassword(); - } + /** + * For URI-based (@link ServiceInfo}s which don't conform to the standard URI + * format, override this method in your own ServiceInfo class to return a {@link UriInfoFactory} which will create the + * appropriate URIs. + * + * @return your special UriInfoFactory + */ + public UriInfoFactory getUriInfoFactory() { + return uriFactory; + } - @ServiceProperty(category="connection") - public String getHost() { - return uriInfo.getHost(); - } + @ServiceProperty(category = "connection") + public String getUri() { + return uriInfo.getUri().toString(); + } - @ServiceProperty(category="connection") - public int getPort() { - return uriInfo.getPort(); - } + @ServiceProperty(category = "connection") + public String getUserName() { + return uriInfo.getUserName(); + } - @ServiceProperty(category="connection") - public String getPath() { - return uriInfo.getPath(); - } + @ServiceProperty(category = "connection") + public String getPassword() { + return uriInfo.getPassword(); + } - @ServiceProperty(category="connection") - public String getQuery() { - return uriInfo.getQuery(); - } + @ServiceProperty(category = "connection") + public String getHost() { + return uriInfo.getHost(); + } - /** - * Validate the URI and clean it up by using defaults for any missing information, if possible. - * - * @param uriInfo uri info based on parsed payload - * @return cleaned up uri info - */ - protected UriInfo validateAndCleanUriInfo(UriInfo uriInfo) { - return uriInfo; - } - - protected UriInfo getUriInfo() { - return uriInfo; - } + @ServiceProperty(category = "connection") + public int getPort() { + return uriInfo.getPort(); + } + + @ServiceProperty(category = "connection") + public String getPath() { + return uriInfo.getPath(); + } + + @ServiceProperty(category = "connection") + public String getQuery() { + return uriInfo.getQuery(); + } + + @ServiceProperty(category = "connection") + public String getScheme() { + return uriInfo.getScheme(); + } + + /** + * Validate the URI and clean it up by using defaults for any missing information, if possible. + * + * @param uriInfo + * uri info based on parsed payload + * @return cleaned up uri info + */ + protected UriInfo validateAndCleanUriInfo(UriInfo uriInfo) { + return uriInfo; + } + + protected UriInfo getUriInfo() { + return uriInfo; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getScheme() + "://" + getUserName() + ":****@" + getHost() + ":" + getPort() + + "/" + getPath() + "]"; + } } From e7ddcadb9adc3c946d004521040a0bdeaab52449 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:28:09 -0500 Subject: [PATCH 24/52] tests for all ServiceInfoCreators --- .../localconfig/LocalConfigConnector.java | 3 ++ .../cloud/localconfig/LocalConfigUtil.java | 6 ++- .../AbstractLocalConfigConnectorTest.java | 54 +++++++++++++++++++ .../LocalConfigConnectorAmqpServiceTest.java | 23 ++++++++ .../LocalConfigConnectorMongoServiceTest.java | 23 ++++++++ .../LocalConfigConnectorMysqlServiceTest.java | 23 ++++++++ ...lConfigConnectorPostgresqlServiceTest.java | 23 ++++++++ .../LocalConfigConnectorRedisServiceTest.java | 23 ++++++++ .../src/test/resources/localconfig.properties | 3 -- .../resources/localconfig.testuris.properties | 6 +++ 10 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java delete mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.properties create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java index 93bb25f..babc2c0 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -79,6 +79,9 @@ public class LocalConfigConnector extends AbstractCloudConnector { @Override protected List getServicesData() { + if(fileProperties == null) + throw new IllegalStateException("isInMatchingCloud() must be called first to initialize connector"); + LinkedHashMap propertySources = new LinkedHashMap(); propertySources.put("programmatic properties", programmaticProperties); diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java index bd4d9f3..c2a4e82 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -23,7 +23,11 @@ public final class LocalConfigUtil { // iterate over the property sources in order, extracting matching properties for (Map.Entry propertySource : propertySources.entrySet()) { - logger.info("reading services from " + propertySource.getValue()); + if(propertySource.getValue().isEmpty()) { + logger.info("no " + propertySource.getKey()); + continue; + } + logger.info("reading services from " + propertySource.getKey()); Map services = readServices(propertySource.getValue()); // add each of the found services to the list, warning about duplicates diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java new file mode 100644 index 0000000..9313717 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java @@ -0,0 +1,54 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfo; + +public class AbstractLocalConfigConnectorTest { + + public static final String PROPERTIES_FILE = "localconfig.testuris.properties"; + + protected LocalConfigConnector connector = new LocalConfigConnector(); + + protected static final String HOSTNAME = "10.20.30.40"; + protected static final int PORT = 1234; + protected static final String USERNAME = "myuser"; + protected static final String PASSWORD = "mypass"; + + @Before + public void init() throws IOException { + InputStream propertiesFile = getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); + LocalConfigConnector.supplyProperties(propertiesFile); + assertTrue(connector.isInMatchingCloud()); + } + + @After + public void clearProperties() { + LocalConfigConnector.programmaticProperties = new Properties(); + } + + protected static ServiceInfo getServiceInfo(List serviceInfos, String serviceId) { + for (ServiceInfo serviceInfo : serviceInfos) { + if (serviceInfo.getId().equals(serviceId)) { + return serviceInfo; + } + } + return null; + } + + protected static void assertUriParameters(UriBasedServiceInfo serviceInfo) { + assertEquals(HOSTNAME, serviceInfo.getHost()); + assertEquals(PORT, serviceInfo.getPort()); + assertEquals(USERNAME, serviceInfo.getUserName()); + assertEquals(PASSWORD, serviceInfo.getPassword()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java new file mode 100644 index 0000000..a515741 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.AmqpServiceInfo; + +public class LocalConfigConnectorAmqpServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "rabbit"); + assertNotNull(service); + assertTrue(service instanceof AmqpServiceInfo); + assertUriParameters((AmqpServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java new file mode 100644 index 0000000..5fec86f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MongoServiceInfo; + +public class LocalConfigConnectorMongoServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "candygram"); + assertNotNull(service); + assertTrue(service instanceof MongoServiceInfo); + assertUriParameters((MongoServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java new file mode 100644 index 0000000..4e305dd --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MysqlServiceInfo; + +public class LocalConfigConnectorMysqlServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "maria"); + assertNotNull(service); + assertTrue(service instanceof MysqlServiceInfo); + assertUriParameters((MysqlServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java new file mode 100644 index 0000000..13123a5 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.PostgresqlServiceInfo; + +public class LocalConfigConnectorPostgresqlServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "ingres"); + assertNotNull(service); + assertTrue(service instanceof PostgresqlServiceInfo); + assertUriParameters((PostgresqlServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java new file mode 100644 index 0000000..29dd550 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.RedisServiceInfo; + +public class LocalConfigConnectorRedisServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "blue"); + assertNotNull(service); + assertTrue(service instanceof RedisServiceInfo); + assertUriParameters((RedisServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties deleted file mode 100644 index bcc84c3..0000000 --- a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.cloud.appId: testApp -spring.cloud.foo: bar -spring.cloud.baz: quux \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties new file mode 100644 index 0000000..94bb5d9 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties @@ -0,0 +1,6 @@ +spring.cloud.appId: testAppWithUris +spring.cloud.rabbit: amqp://myuser:mypass@10.20.30.40:1234/queue +spring.cloud.maria: mysql://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.candygram: mongodb://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.ingres: postgres://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.blue: redis://myuser:mypass@10.20.30.40:1234/dbname \ No newline at end of file From 646a99fb34668b08becd56d7ede40de5d598cfc6 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:28:09 -0500 Subject: [PATCH 25/52] tests for all ServiceInfoCreators fixes #45 --- .../localconfig/LocalConfigConnector.java | 3 ++ .../cloud/localconfig/LocalConfigUtil.java | 6 ++- .../AbstractLocalConfigConnectorTest.java | 54 +++++++++++++++++++ .../LocalConfigConnectorAmqpServiceTest.java | 23 ++++++++ .../LocalConfigConnectorMongoServiceTest.java | 23 ++++++++ .../LocalConfigConnectorMysqlServiceTest.java | 23 ++++++++ ...lConfigConnectorPostgresqlServiceTest.java | 23 ++++++++ .../LocalConfigConnectorRedisServiceTest.java | 23 ++++++++ .../src/test/resources/localconfig.properties | 3 -- .../resources/localconfig.testuris.properties | 6 +++ 10 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java delete mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.properties create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java index 93bb25f..babc2c0 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -79,6 +79,9 @@ public class LocalConfigConnector extends AbstractCloudConnector { @Override protected List getServicesData() { + if(fileProperties == null) + throw new IllegalStateException("isInMatchingCloud() must be called first to initialize connector"); + LinkedHashMap propertySources = new LinkedHashMap(); propertySources.put("programmatic properties", programmaticProperties); diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java index bd4d9f3..c2a4e82 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -23,7 +23,11 @@ public final class LocalConfigUtil { // iterate over the property sources in order, extracting matching properties for (Map.Entry propertySource : propertySources.entrySet()) { - logger.info("reading services from " + propertySource.getValue()); + if(propertySource.getValue().isEmpty()) { + logger.info("no " + propertySource.getKey()); + continue; + } + logger.info("reading services from " + propertySource.getKey()); Map services = readServices(propertySource.getValue()); // add each of the found services to the list, warning about duplicates diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java new file mode 100644 index 0000000..9313717 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java @@ -0,0 +1,54 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfo; + +public class AbstractLocalConfigConnectorTest { + + public static final String PROPERTIES_FILE = "localconfig.testuris.properties"; + + protected LocalConfigConnector connector = new LocalConfigConnector(); + + protected static final String HOSTNAME = "10.20.30.40"; + protected static final int PORT = 1234; + protected static final String USERNAME = "myuser"; + protected static final String PASSWORD = "mypass"; + + @Before + public void init() throws IOException { + InputStream propertiesFile = getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); + LocalConfigConnector.supplyProperties(propertiesFile); + assertTrue(connector.isInMatchingCloud()); + } + + @After + public void clearProperties() { + LocalConfigConnector.programmaticProperties = new Properties(); + } + + protected static ServiceInfo getServiceInfo(List serviceInfos, String serviceId) { + for (ServiceInfo serviceInfo : serviceInfos) { + if (serviceInfo.getId().equals(serviceId)) { + return serviceInfo; + } + } + return null; + } + + protected static void assertUriParameters(UriBasedServiceInfo serviceInfo) { + assertEquals(HOSTNAME, serviceInfo.getHost()); + assertEquals(PORT, serviceInfo.getPort()); + assertEquals(USERNAME, serviceInfo.getUserName()); + assertEquals(PASSWORD, serviceInfo.getPassword()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java new file mode 100644 index 0000000..a515741 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.AmqpServiceInfo; + +public class LocalConfigConnectorAmqpServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "rabbit"); + assertNotNull(service); + assertTrue(service instanceof AmqpServiceInfo); + assertUriParameters((AmqpServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java new file mode 100644 index 0000000..5fec86f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MongoServiceInfo; + +public class LocalConfigConnectorMongoServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "candygram"); + assertNotNull(service); + assertTrue(service instanceof MongoServiceInfo); + assertUriParameters((MongoServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java new file mode 100644 index 0000000..4e305dd --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MysqlServiceInfo; + +public class LocalConfigConnectorMysqlServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "maria"); + assertNotNull(service); + assertTrue(service instanceof MysqlServiceInfo); + assertUriParameters((MysqlServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java new file mode 100644 index 0000000..13123a5 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.PostgresqlServiceInfo; + +public class LocalConfigConnectorPostgresqlServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "ingres"); + assertNotNull(service); + assertTrue(service instanceof PostgresqlServiceInfo); + assertUriParameters((PostgresqlServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java new file mode 100644 index 0000000..29dd550 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.RedisServiceInfo; + +public class LocalConfigConnectorRedisServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "blue"); + assertNotNull(service); + assertTrue(service instanceof RedisServiceInfo); + assertUriParameters((RedisServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties deleted file mode 100644 index bcc84c3..0000000 --- a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.cloud.appId: testApp -spring.cloud.foo: bar -spring.cloud.baz: quux \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties new file mode 100644 index 0000000..94bb5d9 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties @@ -0,0 +1,6 @@ +spring.cloud.appId: testAppWithUris +spring.cloud.rabbit: amqp://myuser:mypass@10.20.30.40:1234/queue +spring.cloud.maria: mysql://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.candygram: mongodb://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.ingres: postgres://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.blue: redis://myuser:mypass@10.20.30.40:1234/dbname \ No newline at end of file From f392a80a90af9697df51ebf25a5a942f51281907 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:41:18 -0500 Subject: [PATCH 26/52] Add test to override programmatic definition from system properties. fixes #45 --- .../LocalConfigServiceOverrideTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java new file mode 100644 index 0000000..980067a --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java @@ -0,0 +1,34 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.ProvideSystemProperty; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MongoServiceInfo; + +public class LocalConfigServiceOverrideTest extends AbstractLocalConfigConnectorTest { + + @Rule + public final ProvideSystemProperty OVERRIDE_MYSQL = + new ProvideSystemProperty( + "spring.cloud.candygram", + "mongodb://youruser:yourpass@40.30.20.10:4321/dbname"); + + @Test + public void serviceOverride() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "candygram"); + assertNotNull(service); + assertTrue(service instanceof MongoServiceInfo); + MongoServiceInfo mongo = (MongoServiceInfo) service; + assertEquals("youruser", mongo.getUserName()); + assertEquals(4321, mongo.getPort()); + } + +} From ad74820e36fae2700b8f5be396578b0883bb00b6 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:57:17 -0500 Subject: [PATCH 27/52] improved documentation --- spring-cloud-localconfig-connector/README.md | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/spring-cloud-localconfig-connector/README.md b/spring-cloud-localconfig-connector/README.md index 1f04dc9..128d2c3 100644 --- a/spring-cloud-localconfig-connector/README.md +++ b/spring-cloud-localconfig-connector/README.md @@ -6,6 +6,28 @@ The current implementation reads from Java properties only; in order to prevent on the Spring Framework, the placeholder functionality is unavailable in the connector. Pull requests for also inspecting environment variables are welcome. +Quick start +----------- +Since service URIs contain passwords and should not be stored in code, this connector does not +attempt to read properties out of the classpath. You can provide a filename with service definitions +by setting the `spring.cloud.propertiesFile` property or by passing in an open `InputStream`: + +````java +InputStream propertyStream = new FileInputStream("/path/to/spring-cloud.properties"); +LocalConfigConnector.supplyProperties(propertyStream); +Cloud cloud = new CloudFactory().getCloud(); +```` + +The property file should contain an application ID and the desired services in this format: + +````properties +spring.cloud.appId: myApp +; spring.cloud.{id}: URI +spring.cloud.database: mysql://user:pass@host:1234/dbname +```` + +Service type is determined by the URI scheme. + Property sources ---------------- This connector first attempts to read the system properties generally and a system property named From 99302432e94400d6f1c8dee2e04085ee970a44ef Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:06:07 -0500 Subject: [PATCH 28/52] pull up KeyValuePair class from HerokuConnector to AbstractCloudConnector --- .../cloud/AbstractCloudConnector.java | 34 ++++++++++--- .../cloud/heroku/HerokuConnector.java | 50 ++++++------------- .../heroku/HerokuServiceInfoCreator.java | 20 ++++---- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java b/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java index 6a73afa..a515766 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java @@ -10,25 +10,25 @@ import org.springframework.cloud.service.ServiceInfo; /** * Helper abstract class to simplify {@link CloudConnector} implementations. - * + * * User the {@link ServiceLoader} approach to looks for file name matching the class passed in constructor * and registers {@link ServiceInfoCreator} found there. - * + * * Implementation of {@link CloudConnector}s that wish to support the recommended service scanning approach * should extends this approach to gain that functionality automatically. - * + * * @author Ramnivas Laddad * */ public abstract class AbstractCloudConnector implements CloudConnector { private static Logger logger = Logger.getLogger(AbstractCloudConnector.class.getName()); - + protected List> serviceInfoCreators = new ArrayList>(); protected abstract List getServicesData(); protected abstract FallbackServiceInfoCreator getFallbackServiceInfoCreator(); - + public AbstractCloudConnector(Class> serviceInfoCreatorClass) { scanServiceInfoCreators(serviceInfoCreatorClass); } @@ -39,7 +39,7 @@ public abstract class AbstractCloudConnector implements CloudConnector { for (SD serviceData : getServicesData()) { serviceInfos.add(getServiceInfo(serviceData)); } - + return serviceInfos; } @@ -54,18 +54,36 @@ public abstract class AbstractCloudConnector implements CloudConnector { registerServiceInfoCreator(serviceInfoCreator); } } - + private ServiceInfo getServiceInfo(SD serviceData) { for (ServiceInfoCreator serviceInfoCreator : serviceInfoCreators) { if (serviceInfoCreator.accept(serviceData)) { return serviceInfoCreator.createServiceInfo(serviceData); } } - + // Fallback with a warning ServiceInfo fallackServiceInfo = getFallbackServiceInfoCreator().createServiceInfo(serviceData); logger.warning("No suitable service info creator found for service " + fallackServiceInfo.getId() + " Did you forget to add a ServiceInfoCreator?"); return fallackServiceInfo; } + + public static class KeyValuePair { + private final String key; + private final String value; + + public KeyValuePair(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + } } \ No newline at end of file diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java index 374b7f8..ac39931 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java @@ -6,30 +6,30 @@ import java.util.List; import java.util.Map; import org.springframework.cloud.AbstractCloudConnector; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; import org.springframework.cloud.CloudException; import org.springframework.cloud.FallbackServiceInfoCreator; import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.app.ApplicationInstanceInfo; -import org.springframework.cloud.heroku.HerokuConnector.KeyValuePair; import org.springframework.cloud.service.BaseServiceInfo; import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.util.EnvironmentAccessor; /** * Implementation of CloudConnector for Heroku - * + * * Currently support Postgres (default provided), Mysql (Cleardb), MongoDb (MongoLab, MongoHQ, MongoSoup), * Redis (RedisToGo, RedisCloud, OpenRedis, RedisGreen), and AMQP (CloudAmqp). - * + * * @author Ramnivas Laddad * */ -public class HerokuConnector extends AbstractCloudConnector { +public class HerokuConnector extends AbstractCloudConnector { private EnvironmentAccessor environment = new EnvironmentAccessor(); - private ApplicationInstanceInfoCreator applicationInstanceInfoCreator + private ApplicationInstanceInfoCreator applicationInstanceInfoCreator = new ApplicationInstanceInfoCreator(environment); - + private List serviceEnvPrefixes; @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -41,28 +41,28 @@ public class HerokuConnector extends AbstractCloudConnector serviceInfoCreator) { + protected void registerServiceInfoCreator(ServiceInfoCreator serviceInfoCreator) { super.registerServiceInfoCreator(serviceInfoCreator); HerokuServiceInfoCreator herokuServiceInfoCreator = (HerokuServiceInfoCreator)serviceInfoCreator; String[] envPrefixes = herokuServiceInfoCreator.getEnvPrefixes(); - + // need to do this since this method gets called during construction and we cannot initialize serviceEnvPrefixes before this if (serviceEnvPrefixes == null) { serviceEnvPrefixes = new ArrayList(); @@ -75,17 +75,17 @@ public class HerokuConnector extends AbstractCloudConnector * Returns map whose key is the env key and value is the associated url *

- * @return information about services bound to the app + * @return information about services bound to the app */ protected List getServicesData() { List serviceData = new ArrayList(); - + Map env = environment.getEnv(); - + for (Map.Entry envEntry : env.entrySet()) { for (String envPrefix : serviceEnvPrefixes) { if (envEntry.getKey().startsWith(envPrefix)) { - serviceData.add(new KeyValuePair(envEntry.getKey(), envEntry.getValue())); + serviceData.add(new KeyValuePair(envEntry.getKey(), envEntry.getValue())); } } } @@ -97,24 +97,6 @@ public class HerokuConnector extends AbstractCloudConnector getFallbackServiceInfoCreator() { return new HerokuFallbackServiceInfoCreator(); } - - public static class KeyValuePair { - private String key; - private String value; - - public KeyValuePair(String key, String value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public String getValue() { - return value; - } - } } class HerokuFallbackServiceInfoCreator extends FallbackServiceInfoCreator { diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java index 15ed4aa..00b6c6b 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java @@ -1,11 +1,11 @@ package org.springframework.cloud.heroku; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; import org.springframework.cloud.ServiceInfoCreator; -import org.springframework.cloud.heroku.HerokuConnector.KeyValuePair; import org.springframework.cloud.service.ServiceInfo; /** - * + * * @author Ramnivas Laddad * */ @@ -16,25 +16,25 @@ public abstract class HerokuServiceInfoCreator implement public HerokuServiceInfoCreator(String urlProtocol) { this.urlProtocol = urlProtocol; } - + public boolean accept(KeyValuePair serviceData) { return serviceData.getValue().toString().startsWith(urlProtocol + "://"); } - + public abstract SI createServiceInfo(String id, String uri); - + public SI createServiceInfo(KeyValuePair serviceData) { return createServiceInfo(serviceData.getKey(), serviceData.getValue()); } - + /** * Get prefixes for env variable with which the associated {@link ServiceInfo} may be created. - * + * * Unlike CloudFoundry which exposes VCAP_SERVICES as a single environment to encompass all services bound * to the app, Heroku expose one environment variable per app. This method allows each info creator to declare - * appropriate env variables. - * - * @return prefixes for the relevant environment variables + * appropriate env variables. + * + * @return prefixes for the relevant environment variables */ public abstract String[] getEnvPrefixes(); } From 83245841b362d670792a6b35e59ef635032535f9 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:13:49 -0500 Subject: [PATCH 29/52] pull up URI-based common functionality into core abstract base class --- .../service/UriBasedServiceInfoCreator.java | 26 +++++++++++++++++++ .../heroku/HerokuServiceInfoCreator.java | 21 +++------------ 2 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java new file mode 100644 index 0000000..b856bc0 --- /dev/null +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java @@ -0,0 +1,26 @@ +package org.springframework.cloud.service; + +import org.springframework.cloud.ServiceInfoCreator; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public abstract class UriBasedServiceInfoCreator implements + ServiceInfoCreator { + + private final String uriScheme; + + public UriBasedServiceInfoCreator(String uriScheme) { + this.uriScheme = uriScheme; + } + + @Override + public boolean accept(KeyValuePair serviceData) { + return serviceData.getValue().toString().startsWith(uriScheme + "://"); + } + + public abstract SI createServiceInfo(String id, String uri); + + @Override + public SI createServiceInfo(KeyValuePair serviceData) { + return createServiceInfo(serviceData.getKey(), serviceData.getValue()); + } +} diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java index 00b6c6b..81094eb 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuServiceInfoCreator.java @@ -1,30 +1,17 @@ package org.springframework.cloud.heroku; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; -import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfoCreator; /** * * @author Ramnivas Laddad * */ -public abstract class HerokuServiceInfoCreator implements ServiceInfoCreator { +public abstract class HerokuServiceInfoCreator extends UriBasedServiceInfoCreator { - private String urlProtocol; - - public HerokuServiceInfoCreator(String urlProtocol) { - this.urlProtocol = urlProtocol; - } - - public boolean accept(KeyValuePair serviceData) { - return serviceData.getValue().toString().startsWith(urlProtocol + "://"); - } - - public abstract SI createServiceInfo(String id, String uri); - - public SI createServiceInfo(KeyValuePair serviceData) { - return createServiceInfo(serviceData.getKey(), serviceData.getValue()); + public HerokuServiceInfoCreator(String uriScheme) { + super(uriScheme); } /** From 5ce0b402bfc3b9269469252949669855099f97e1 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:23:36 -0500 Subject: [PATCH 30/52] constant for MongoDB URI scheme --- .../cloud/cloudfoundry/MongoServiceInfoCreator.java | 4 ++-- .../cloud/service/common/MongoServiceInfo.java | 11 +++++++---- .../cloud/heroku/MongoServiceInfoCreator.java | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java index 5aeace5..ac963c5 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MongoServiceInfoCreator.java @@ -12,8 +12,8 @@ import org.springframework.cloud.service.common.MongoServiceInfo; public class MongoServiceInfoCreator extends CloudFoundryServiceInfoCreator { public MongoServiceInfoCreator() { - super(new Tags("mongodb"), "mongodb"); - + // the literal in the tag is CloudFoundry-specific + super(new Tags("mongodb"), MongoServiceInfo.URI_SCHEME); } public MongoServiceInfo createServiceInfo(Map serviceData) { diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java index b45800f..a332b65 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MongoServiceInfo.java @@ -4,23 +4,26 @@ import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("mongo") public class MongoServiceInfo extends UriBasedServiceInfo { + + public static final String URI_SCHEME = "mongodb"; + public MongoServiceInfo(String id, String host, int port, String username, String password, String db) { - super(id, "mongodb", host, port, username, password, db); + super(id, URI_SCHEME, host, port, username, password, db); } public MongoServiceInfo(String id, String uri) { super(id, uri); } - + @ServiceProperty(category="connection") public String getDatabase() { return getUriInfo().getPath(); } - + } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java index bb1e11e..d75299e 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MongoServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.MongoServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class MongoServiceInfoCreator extends HerokuServiceInfoCreator { public MongoServiceInfoCreator() { - super("mongodb"); + super(MongoServiceInfo.URI_SCHEME); } @Override From 5987c05c6e614d69d1892bb011cd88c626d71e6f Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:25:57 -0500 Subject: [PATCH 31/52] pull up URI scheme for RabbitMQ --- .../cloudfoundry/AmqpServiceInfoCreator.java | 6 +++--- .../cloud/service/common/AmqpServiceInfo.java | 19 +++++++++++-------- .../cloud/heroku/AmqpServiceInfoCreator.java | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java index 1753c11..af68eee 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/AmqpServiceInfoCreator.java @@ -5,20 +5,20 @@ import java.util.Map; import org.springframework.cloud.service.common.AmqpServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class AmqpServiceInfoCreator extends CloudFoundryServiceInfoCreator { public AmqpServiceInfoCreator() { - super(new Tags("rabbitmq"), "amqp"); + super(new Tags("rabbitmq"), AmqpServiceInfo.URI_SCHEME); } public AmqpServiceInfo createServiceInfo(Map serviceData) { @SuppressWarnings("unchecked") Map credentials = (Map) serviceData.get("credentials"); - + String id = (String) serviceData.get("name"); String uri = getStringFromCredentials(credentials, "uri", "url"); diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java index 5ae72bb..aa7bb98 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/AmqpServiceInfo.java @@ -1,8 +1,8 @@ package org.springframework.cloud.service.common; import org.springframework.cloud.CloudException; -import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; +import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.util.UriInfo; /** @@ -13,29 +13,32 @@ import org.springframework.cloud.util.UriInfo; */ @ServiceLabel("rabbitmq") public class AmqpServiceInfo extends UriBasedServiceInfo { + + public static final String URI_SCHEME = "amqp"; + public AmqpServiceInfo(String id, String host, int port, String username, String password, String virtualHost) { - super(id, "amqp", host, port, username, password, virtualHost); + super(id, URI_SCHEME, host, port, username, password, virtualHost); } - + public AmqpServiceInfo(String id, String uri) throws CloudException { super(id, uri); } - + @ServiceProperty(category="connection") public String getVirtualHost() { return getUriInfo().getPath(); } - + @Override protected UriInfo validateAndCleanUriInfo(UriInfo uriInfo) { - if (!"amqp".equals(uriInfo.getScheme())) { + if (!URI_SCHEME.equals(uriInfo.getScheme())) { throw new IllegalArgumentException("wrong scheme in amqp URI: " + uriInfo); } if (uriInfo.getHost() == null) { throw new IllegalArgumentException("missing authority in amqp URI: " + uriInfo); } - + int port = uriInfo.getPort(); if (port == -1) { port = 5672; @@ -43,7 +46,7 @@ public class AmqpServiceInfo extends UriBasedServiceInfo { String userName = uriInfo.getUserName(); String password = uriInfo.getPassword(); - + if (userName == null || password == null) { throw new IllegalArgumentException("missing userinfo in amqp URI: " + uriInfo); } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java index a139bd6..86621f8 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/AmqpServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.AmqpServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class AmqpServiceInfoCreator extends HerokuServiceInfoCreator { public AmqpServiceInfoCreator() { - super("amqp"); + super(AmqpServiceInfo.URI_SCHEME); } @Override From a5e6d6ad72367336c788c21b54362abf22cb22ff Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:26:45 -0500 Subject: [PATCH 32/52] make jdbcUrlDatabaseType final --- .../cloud/service/common/RelationalServiceInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java index 49fe00d..bac6236 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RelationalServiceInfo.java @@ -7,7 +7,7 @@ import org.springframework.cloud.service.UriBasedServiceInfo; */ public abstract class RelationalServiceInfo extends UriBasedServiceInfo { - protected String jdbcUrlDatabaseType; + protected final String jdbcUrlDatabaseType; public RelationalServiceInfo(String id, String uriString, String jdbcUrlDatabaseType) { super(id, uriString); From 9ef5d5da70864e33a3dcd118d3c1b909cb66dae9 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:29:07 -0500 Subject: [PATCH 33/52] pull up MySQL URI scheme --- .../cloud/cloudfoundry/MysqlServiceInfoCreator.java | 5 +++-- .../cloud/service/common/MysqlServiceInfo.java | 6 ++++-- .../cloud/heroku/MysqlServiceInfoCreator.java | 4 ++-- .../cloud/heroku/HerokuConnectorMysqlServiceTest.java | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java index aca803e..b5c6e15 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/MysqlServiceInfoCreator.java @@ -3,14 +3,15 @@ package org.springframework.cloud.cloudfoundry; import org.springframework.cloud.service.common.MysqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class MysqlServiceInfoCreator extends RelationalServiceInfoCreator { public MysqlServiceInfoCreator() { - super(new Tags("mysql"), "mysql"); + // the literal in the tag is CloudFoundry-specific + super(new Tags("mysql"), MysqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java index 467a59c..2eccab0 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java @@ -3,14 +3,16 @@ package org.springframework.cloud.service.common; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("mysql") public class MysqlServiceInfo extends RelationalServiceInfo { + public static final String URI_SCHEME = "mysql"; + public MysqlServiceInfo(String id, String url) { - super(id, url, "mysql"); + super(id, url, URI_SCHEME); } } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java index 4318cb0..73bb8eb 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/MysqlServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.MysqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class MysqlServiceInfoCreator extends RelationalServiceInfoCreator { public MysqlServiceInfoCreator() { - super("mysql"); + super(MysqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java index 349c738..439a854 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorMysqlServiceTest.java @@ -13,15 +13,15 @@ import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.service.common.MysqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class HerokuConnectorMysqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest { public HerokuConnectorMysqlServiceTest() { - super("mysql"); + super(MysqlServiceInfo.URI_SCHEME); } - + @Test public void mysqlServiceCreation() { Map env = new HashMap(); From dfa8b87670ffb3039a1854d4311a488b2e4b1571 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:30:06 -0500 Subject: [PATCH 34/52] pull up Oracle URI scheme --- .../cloud/cloudfoundry/OracleServiceInfoCreator.java | 2 +- .../cloud/service/common/OracleServiceInfo.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java index 1b8159f..1d82ab3 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/OracleServiceInfoCreator.java @@ -4,7 +4,7 @@ import org.springframework.cloud.service.common.OracleServiceInfo; public class OracleServiceInfoCreator extends RelationalServiceInfoCreator { public OracleServiceInfoCreator() { - super(new Tags(), "oracle"); + super(new Tags(), OracleServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java index 13e0f49..8aef0c4 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java @@ -5,8 +5,10 @@ import org.springframework.cloud.service.ServiceInfo; @ServiceInfo.ServiceLabel("oracle") public class OracleServiceInfo extends RelationalServiceInfo { + public static final String URI_SCHEME = "oracle"; + public OracleServiceInfo(String id, String url) { - super(id, url, "oracle"); + super(id, url, URI_SCHEME); } @Override From eb732d792e8212218401b8085c74942a995fd2d5 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:37:23 -0500 Subject: [PATCH 35/52] pull up Postgres URI schema, split out JDBC URL types--this should probably be done in the interface instead of ad-hocky --- .../cloudfoundry/PostgresqlServiceInfoCreator.java | 4 ++-- ...ractCloudFoundryConnectorRelationalServiceTest.java | 5 +++-- .../cloud/service/common/MysqlServiceInfo.java | 10 ++++++---- .../cloud/service/common/OracleServiceInfo.java | 6 ++++-- .../cloud/service/common/PostgresqlServiceInfo.java | 9 +++++++-- .../cloud/heroku/PostgresqlServiceInfoCreator.java | 4 ++-- .../heroku/HerokuConnectorPostgresqlServiceTest.java | 6 +++--- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java index da8be3e..4b38fbf 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.cloudfoundry; import org.springframework.cloud.service.common.PostgresqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super(new Tags("postgresql"), "postgres"); + super(new Tags("postgresql"), PostgresqlServiceInfo.URI_SCHEMA); } @Override diff --git a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java index 35a790a..9588e50 100644 --- a/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java +++ b/spring-cloud-cloudfoundry-connector/src/test/java/org/springframework/cloud/cloudfoundry/AbstractCloudFoundryConnectorRelationalServiceTest.java @@ -1,7 +1,7 @@ package org.springframework.cloud.cloudfoundry; /** - * + * * @author Ramnivas Laddad * */ @@ -20,12 +20,13 @@ public abstract class AbstractCloudFoundryConnectorRelationalServiceTest extends } protected static String getJdbcUrl(String databaseType, String name) { + // this should be cleaned up more broadly; pull into RelationalServiceInfo interface? String jdbcUrlDatabaseType = databaseType; if (databaseType.equals("postgres")) { jdbcUrlDatabaseType = "postgresql"; } - return "jdbc:" + jdbcUrlDatabaseType + "://" + hostname + ":" + port + "/" + name + + return "jdbc:" + jdbcUrlDatabaseType + "://" + hostname + ":" + port + "/" + name + "?user=" + username + "&password=" + password; } diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java index 2eccab0..f4609eb 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/MysqlServiceInfo.java @@ -10,9 +10,11 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel; @ServiceLabel("mysql") public class MysqlServiceInfo extends RelationalServiceInfo { - public static final String URI_SCHEME = "mysql"; + public static final String JDBC_URL_TYPE = "mysql"; - public MysqlServiceInfo(String id, String url) { - super(id, url, URI_SCHEME); - } + public static final String URI_SCHEME = JDBC_URL_TYPE; + + public MysqlServiceInfo(String id, String url) { + super(id, url, URI_SCHEME); + } } diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java index 8aef0c4..6d2289d 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/OracleServiceInfo.java @@ -5,10 +5,12 @@ import org.springframework.cloud.service.ServiceInfo; @ServiceInfo.ServiceLabel("oracle") public class OracleServiceInfo extends RelationalServiceInfo { - public static final String URI_SCHEME = "oracle"; + public static final String JDBC_URL_TYPE = "oracle"; + + public static final String URI_SCHEME = JDBC_URL_TYPE; public OracleServiceInfo(String id, String url) { - super(id, url, URI_SCHEME); + super(id, url, JDBC_URL_TYPE); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java index 98e478c..2927782 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java @@ -4,13 +4,18 @@ import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("postgresql") public class PostgresqlServiceInfo extends RelationalServiceInfo { + + public static final String JDBC_URL_TYPE = "postgresql"; + + public static final String URI_SCHEMA = "postgres"; + public PostgresqlServiceInfo(String id, String url) { - super(id, url, "postgresql"); + super(id, url, JDBC_URL_TYPE); } } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java index 57a4e67..7a44ea0 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.PostgresqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super("postgres"); + super(PostgresqlServiceInfo.URI_SCHEMA); } @Override diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java index 35bf83b..9915ffa 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java @@ -13,15 +13,15 @@ import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.service.common.PostgresqlServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class HerokuConnectorPostgresqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest { public HerokuConnectorPostgresqlServiceTest() { - super("postgres"); + super(PostgresqlServiceInfo.URI_SCHEMA); } - + @Test public void postgresqlServiceCreation() { Map env = new HashMap(); From 0fcfa7c653bfbc8c81a22aa7e0c390259df41650 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:38:52 -0500 Subject: [PATCH 36/52] pull up Redis URI scheme --- .../cloud/cloudfoundry/RedisServiceInfoCreator.java | 3 ++- .../cloud/service/common/RedisServiceInfo.java | 9 ++++++--- .../cloud/heroku/RedisServiceInfoCreator.java | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java index 75e6df1..f8fcfa3 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/RedisServiceInfoCreator.java @@ -12,7 +12,8 @@ import org.springframework.cloud.service.common.RedisServiceInfo; public class RedisServiceInfoCreator extends CloudFoundryServiceInfoCreator { public RedisServiceInfoCreator() { - super(new Tags("redis"), "redis"); + // the literal in the tag is CloudFoundry-specific + super(new Tags("redis"), RedisServiceInfo.URI_SCHEME); } public RedisServiceInfo createServiceInfo(Map serviceData) { diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java index d31be25..ab35a8e 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/RedisServiceInfo.java @@ -4,16 +4,19 @@ import org.springframework.cloud.service.UriBasedServiceInfo; import org.springframework.cloud.service.ServiceInfo.ServiceLabel; /** - * + * * @author Ramnivas Laddad * */ @ServiceLabel("redis") public class RedisServiceInfo extends UriBasedServiceInfo { + + public static final String URI_SCHEME = "redis"; + public RedisServiceInfo(String id, String host, int port, String password) { - super(id, "redis", host, port, null, password, null); + super(id, URI_SCHEME, host, port, null, password, null); } - + public RedisServiceInfo(String id, String uri) { super(id, uri); } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java index cfa88ad..1757bd7 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/RedisServiceInfoCreator.java @@ -3,14 +3,14 @@ package org.springframework.cloud.heroku; import org.springframework.cloud.service.common.RedisServiceInfo; /** - * + * * @author Ramnivas Laddad * */ public class RedisServiceInfoCreator extends HerokuServiceInfoCreator { public RedisServiceInfoCreator() { - super("redis"); + super(RedisServiceInfo.URI_SCHEME); } @Override From a184e7b0d825b50bf6eba7baddb7e06dc788e82b Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Wed, 9 Jul 2014 19:40:42 -0500 Subject: [PATCH 37/52] pull up SMTP URI scheme --- .../cloud/cloudfoundry/SmtpServiceInfoCreator.java | 13 +++++++------ .../cloud/service/common/SmtpServiceInfo.java | 6 ++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java index ccf7560..10bd6e5 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/SmtpServiceInfoCreator.java @@ -6,7 +6,7 @@ import org.springframework.cloud.service.common.SmtpServiceInfo; import org.springframework.cloud.util.UriInfo; /** - * + * * @author Ramnivas Laddad * */ @@ -15,16 +15,17 @@ public class SmtpServiceInfoCreator extends CloudFoundryServiceInfoCreator serviceData) { String id = (String) serviceData.get("name"); - + @SuppressWarnings("unchecked") Map credentials = (Map) serviceData.get("credentials"); String host = (String) credentials.get("hostname"); - + int port = DEFAULT_SMTP_PORT; if (credentials.containsKey("port")) { port = Integer.parseInt(credentials.get("port").toString()); @@ -33,8 +34,8 @@ public class SmtpServiceInfoCreator extends CloudFoundryServiceInfoCreator Date: Thu, 10 Jul 2014 12:34:45 -0500 Subject: [PATCH 38/52] blank new module --- settings.gradle | 3 +- spring-cloud-localconfig-connector/.gitignore | 1 + spring-cloud-localconfig-connector/README.md | 59 +++++++++++++++++++ .../build.gradle | 5 ++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-localconfig-connector/.gitignore create mode 100644 spring-cloud-localconfig-connector/README.md create mode 100644 spring-cloud-localconfig-connector/build.gradle diff --git a/settings.gradle b/settings.gradle index c22faa4..bc6b88f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,5 @@ rootProject.name = "spring-cloud" include "${rootProject.name}-core" include "${rootProject.name}-cloudfoundry-connector" include "${rootProject.name}-spring-service-connector" -include "${rootProject.name}-heroku-connector" \ No newline at end of file +include "${rootProject.name}-heroku-connector" +include "${rootProject.name}-localconfig-connector" diff --git a/spring-cloud-localconfig-connector/.gitignore b/spring-cloud-localconfig-connector/.gitignore new file mode 100644 index 0000000..5e56e04 --- /dev/null +++ b/spring-cloud-localconfig-connector/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/spring-cloud-localconfig-connector/README.md b/spring-cloud-localconfig-connector/README.md new file mode 100644 index 0000000..f9788aa --- /dev/null +++ b/spring-cloud-localconfig-connector/README.md @@ -0,0 +1,59 @@ +Local-configuration connector for Spring Cloud +======================================= + +Provides the ability to configure Spring Cloud services locally for development or testing. +The current implementation reads from Java properties only; in order to prevent dependencies +on the Spring Framework, the placeholder functionality is unavailable in the connector. +Pull requests for also inspecting environment variables are welcome. + +Property sources +---------------- +This connector first attempts to read the system properties generally and a property named +`spring.cloud.propertiesFile` specifically. If the system properties are not readable +(the security manager denies `checkPropertiesAccess`), then they will be treated as empty. +If a system property named `spring.cloud.propertiesFile` is found, that file will be loaded +as a property list. + +###Programmatically supplying properties +You can programmatically supply a property source by calling the static method +`LocalConfigConnector.supplyProperties(InputStream)` before invoking `getCloud()`. +Calling this method will cause the connector to read the stream as a property list +and then close the stream. Calling this method after invoking `getCloud()` will +still read the stream, but the properties will have no effect on the connector +service configuration. Calling this method multiple times will load the supplied +streams onto the same `Properties` object, overwriting duplicates. + +###Property order +To provide the maximum configuration flexibility, the connector will scan the available +property sources in this order: + +- programmatically-supplied properties +- properties read from `spring.cloud.propertiesFile` +- system properties + +The last definition of a specific service ID wins. The connector will log a message at +`INFO` to notify of service overrides for the same type of service and at `WARN` if you +override a service ID with a URI to a different type of service. + +Activating the connector +------------------------ +The Spring Cloud core expects exactly one cloud connector to return `true` for +`isInMatchingCloud()`. This connector identifies the "local cloud" by the presence of +a property named `spring.cloud.appId`, which will be used in the `ApplicationInstanceInfo`. + +Service definitions +------------------- +If the connector is activated, it will iterate through all the available properties +for keys matching the pattern `spring.cloud.{serviceId}`. Each value is interpreted as a URI +to the services, and the type of service is determined from the scheme. All of the standard +`UriBasedServiceInfo`s are supported. + +Supporting additional services +------------------------------ +Please see the documentation for [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector), since the same +mechanism applies to any cloud connector. + +Instance ID +----------- +This connector will create a UUID for use as the instance ID, as Java does not provide +any portable mechanism for reliably determining hostnames or PIDs. \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/build.gradle b/spring-cloud-localconfig-connector/build.gradle new file mode 100644 index 0000000..eb5f5b6 --- /dev/null +++ b/spring-cloud-localconfig-connector/build.gradle @@ -0,0 +1,5 @@ +description = 'Spring Cloud local-configuration connector' + +dependencies { + compile project(':spring-cloud-core') +} From f7269144bd9deb156dcd06b46101f354bccf2af8 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 13:17:43 -0500 Subject: [PATCH 39/52] pull up fallback BaseServiceInfo creator (just a generic KVP creator) --- .../service/FallbackBaseServiceInfoCreator.java | 11 +++++++++++ .../cloud/heroku/HerokuConnector.java | 12 +++--------- 2 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java new file mode 100644 index 0000000..23a815a --- /dev/null +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java @@ -0,0 +1,11 @@ +package org.springframework.cloud.service; + +import org.springframework.cloud.FallbackServiceInfoCreator; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public class FallbackBaseServiceInfoCreator extends FallbackServiceInfoCreator { + @Override + public BaseServiceInfo createServiceInfo(KeyValuePair serviceData) { + return new BaseServiceInfo(serviceData.getKey()); + } +} diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java index ac39931..ab91ba0 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java @@ -12,6 +12,7 @@ import org.springframework.cloud.FallbackServiceInfoCreator; import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; +import org.springframework.cloud.service.FallbackBaseServiceInfoCreator; import org.springframework.cloud.service.ServiceInfo; import org.springframework.cloud.util.EnvironmentAccessor; @@ -95,13 +96,6 @@ public class HerokuConnector extends AbstractCloudConnector { @Override protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { - return new HerokuFallbackServiceInfoCreator(); + return new FallbackBaseServiceInfoCreator(); } -} - -class HerokuFallbackServiceInfoCreator extends FallbackServiceInfoCreator { - @Override - public BaseServiceInfo createServiceInfo(KeyValuePair serviceData) { - return new BaseServiceInfo(serviceData.getKey()); - } -} +} \ No newline at end of file From c9cd0c9e64b4151b2809e5eb99711f1c23d3d24c Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 16:18:31 -0500 Subject: [PATCH 40/52] initial local-config connector implementation; provides ServiceData, still needs converters to ServiceInfo --- spring-cloud-localconfig-connector/README.md | 5 +- .../build.gradle | 1 + .../localconfig/LocalConfigConnector.java | 187 ++++++++++++++++++ .../LocalConfigServiceInfoCreator.java | 11 ++ .../cloud/localconfig/LocalConfigUtil.java | 81 ++++++++ .../localconfig/LocalConfigConnectorTest.java | 145 ++++++++++++++ .../localconfig/LocalConfigUtilTest.java | 74 +++++++ .../src/test/resources/localconfig.properties | 3 + 8 files changed, 504 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.properties diff --git a/spring-cloud-localconfig-connector/README.md b/spring-cloud-localconfig-connector/README.md index f9788aa..1f04dc9 100644 --- a/spring-cloud-localconfig-connector/README.md +++ b/spring-cloud-localconfig-connector/README.md @@ -8,7 +8,7 @@ Pull requests for also inspecting environment variables are welcome. Property sources ---------------- -This connector first attempts to read the system properties generally and a property named +This connector first attempts to read the system properties generally and a system property named `spring.cloud.propertiesFile` specifically. If the system properties are not readable (the security manager denies `checkPropertiesAccess`), then they will be treated as empty. If a system property named `spring.cloud.propertiesFile` is found, that file will be loaded @@ -32,8 +32,7 @@ property sources in this order: - system properties The last definition of a specific service ID wins. The connector will log a message at -`INFO` to notify of service overrides for the same type of service and at `WARN` if you -override a service ID with a URI to a different type of service. +`WARN` if you override a service ID. Activating the connector ------------------------ diff --git a/spring-cloud-localconfig-connector/build.gradle b/spring-cloud-localconfig-connector/build.gradle index eb5f5b6..d020bde 100644 --- a/spring-cloud-localconfig-connector/build.gradle +++ b/spring-cloud-localconfig-connector/build.gradle @@ -2,4 +2,5 @@ description = 'Spring Cloud local-configuration connector' dependencies { compile project(':spring-cloud-core') + testCompile 'com.github.stefanbirkner:system-rules:1.5.0' } diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java new file mode 100644 index 0000000..93bb25f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -0,0 +1,187 @@ +package org.springframework.cloud.localconfig; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Properties; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import org.springframework.cloud.AbstractCloudConnector; +import org.springframework.cloud.FallbackServiceInfoCreator; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.app.ApplicationInstanceInfo; +import org.springframework.cloud.app.BasicApplicationInstanceInfo; +import org.springframework.cloud.service.BaseServiceInfo; +import org.springframework.cloud.service.FallbackBaseServiceInfoCreator; + +/** + * + * @author Christopher Smith + * + */ +public class LocalConfigConnector extends AbstractCloudConnector { + + private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); + + /*--------------- String constants for property keys ---------------*/ + + public static final String PROPERTY_PREFIX = "spring.cloud."; + + public static final Pattern SERVICE_PROPERTY_PATTERN = Pattern.compile("\\A" + Pattern.quote(PROPERTY_PREFIX) + "(.+)" + "\\Z"); + + public static final String APP_ID_PROPERTY = PROPERTY_PREFIX + "appId"; + + public static final String PROPERTIES_FILE_PROPERTY = PROPERTY_PREFIX + "propertiesFile"; + + /** + * These properties configure the connector itself and aren't service definitions. + */ + public static final List META_PROPERTIES = Collections.unmodifiableList( + Arrays.asList(new String[] { APP_ID_PROPERTY, PROPERTIES_FILE_PROPERTY })); + + /*--------------- sources for service-definition properties ---------------*/ + + static Properties programmaticProperties = new Properties(); + + private Properties fileProperties = null; + + /*--------------- API implementation ---------------*/ + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public LocalConfigConnector() { + super((Class) LocalConfigServiceInfoCreator.class); + } + + /** + * Returns {@code true} if a property named {@code spring.cloud.appId} is present in any of the property sources. + * On the first call, attempts to load properties from a file specified in {@code spring.cloud.propertiesFile}. + */ + @Override + public boolean isInMatchingCloud() { + if (fileProperties == null) + readFileProperties(); + + return findProperty(APP_ID_PROPERTY) != null; + } + + @Override + public ApplicationInstanceInfo getApplicationInstanceInfo() { + return new BasicApplicationInstanceInfo(UUID.randomUUID().toString(), findProperty(APP_ID_PROPERTY), + Collections. emptyMap()); + } + + @Override + protected List getServicesData() { + LinkedHashMap propertySources = new LinkedHashMap(); + + propertySources.put("programmatic properties", programmaticProperties); + propertySources.put("properties from file", fileProperties); + try { + propertySources.put("system properties", System.getProperties()); + } catch (SecurityException e) { + logger.log(Level.WARNING, + "couldn't read system properties; no service definitions from system properties will be applied", e); + } + + return LocalConfigUtil.readServicesData(propertySources); + } + + @Override + protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { + return new FallbackBaseServiceInfoCreator(); + } + + /*--------------- methods for manipulating properties and sources ---------------*/ + + /** + * Adds properties to be scanned from the supplied {@link InputStream}, overwriting + * existing properties with the same name. Closes the stream after loading. + * + * @param propertiesInputStream + * a property list + * @throws IOException + * if the underlying load operation throws an exception + */ + public static void supplyProperties(final InputStream propertiesInputStream) throws IOException { + programmaticProperties.load(propertiesInputStream); + propertiesInputStream.close(); + } + + /** + * Checks for the presence of a supplied or system property named {@code spring.cloud.propertiesFile}. If the property + * is present, load its contents into {@link #fileProperties}. If there's a problem, log but continue. + */ + private void readFileProperties() { + fileProperties = new Properties(); + logger.fine("looking for a properties file"); + + String filename = null; + + filename = programmaticProperties.getProperty(PROPERTIES_FILE_PROPERTY); + + try { + filename = System.getProperty(PROPERTIES_FILE_PROPERTY, filename); + } catch (SecurityException e) { + logSystemReadException(PROPERTIES_FILE_PROPERTY, e); + return; + } + + if (filename == null) { + logger.info("did not find a system property " + PROPERTIES_FILE_PROPERTY); + return; + } + + logger.info("loading properties from file " + filename); + + try { + InputStream fis = openFile(filename); + fileProperties.load(fis); + } catch (IOException e) { + logger.log(Level.SEVERE, "exception while loading properties from file " + filename, e); + return; + } + + logger.info("properties loaded successfully"); + } + + /** + * Broken out into a separate method for mocking the filesystem. + * @param filename the file to open + * @return a {@code FileInputStream} to the file + * @throws IOException if opening the file throws + */ + InputStream openFile(String filename) throws IOException { + return new FileInputStream(filename); + } + + /** + * Look for a specific property in programmatically-supplied properties, properties from a file, + * or the system properties. Last source wins. + * + * @param key + * the property to look for + * @return the highest-priority value for the key, or {@code null} if the key is not found + */ + private String findProperty(String key) { + String value = programmaticProperties.getProperty(key); + value = fileProperties.getProperty(key, value); + try { + value = System.getProperty(key, value); + } catch (SecurityException e) { + logSystemReadException(key, e); + } + + return value; + } + + private static void logSystemReadException(String key, SecurityException e) { + logger.log(Level.WARNING, "couldn't read system property " + key, e); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java new file mode 100644 index 0000000..98a8669 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigServiceInfoCreator.java @@ -0,0 +1,11 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfoCreator; + +public abstract class LocalConfigServiceInfoCreator extends UriBasedServiceInfoCreator { + + protected LocalConfigServiceInfoCreator(String uriScheme) { + super(uriScheme); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java new file mode 100644 index 0000000..bd4d9f3 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -0,0 +1,81 @@ +package org.springframework.cloud.localconfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.logging.Logger; +import java.util.regex.Matcher; + +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public final class LocalConfigUtil { + private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); + + private LocalConfigUtil() { + } + + static List readServicesData(LinkedHashMap propertySources) { + // we'll turn this into KVPs to return but need to eliminate duplicates first + Map collectedServices = new HashMap(); + + // iterate over the property sources in order, extracting matching properties + for (Map.Entry propertySource : propertySources.entrySet()) { + logger.info("reading services from " + propertySource.getValue()); + Map services = readServices(propertySource.getValue()); + + // add each of the found services to the list, warning about duplicates + for (Map.Entry service : services.entrySet()) { + String oldUri = collectedServices.put(service.getKey(), service.getValue()); + if (oldUri == null) + logger.info("added service '" + service.getKey() + "' from " + propertySource.getKey()); + else + logger.warning("replaced service '" + service.getKey() + "' with new URI from " + propertySource.getKey()); + } + } + + // now we have a collated set of service IDs and URIs + List serviceData = new ArrayList(collectedServices.size()); + for (Map.Entry serviceInfo : collectedServices.entrySet()) { + serviceData.add(new KeyValuePair(serviceInfo.getKey(), serviceInfo.getValue())); + } + + return serviceData; + } + + /** + * Goes through a {@code Properties} object, finding all service definitions (properties + * prefixed with {@code spring.cloud.} but not in {@code META_PROPERTIES}) and collects {@code (id,URI)} pairs. + * + * @param properties + * the {@code Properties} object to read + * @return all of the service definitions found + */ + static Map readServices(Properties properties) { + Map services = new HashMap(); + + for (String propertyName : properties.stringPropertyNames()) { + if (LocalConfigConnector.META_PROPERTIES.contains(propertyName)) { + logger.finer("skipping meta property " + propertyName); + continue; + } + + Matcher m = LocalConfigConnector.SERVICE_PROPERTY_PATTERN.matcher(propertyName); + if (!m.matches()) { + logger.finest("skipping non-Spring-Cloud property " + propertyName); + continue; + } + + String serviceId = m.group(1); + String serviceUri = properties.getProperty(propertyName); + + // no URI here because they will contain passwords + logger.fine("found service URI for service " + serviceId); + services.put(serviceId, serviceUri); + } + + return services; + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java new file mode 100644 index 0000000..394e851 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -0,0 +1,145 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.ClearSystemProperties; +import org.junit.contrib.java.lang.system.ProvideSystemProperty; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public class LocalConfigConnectorTest { + + static final Charset UTF_8 = Charset.forName("UTF-8"); + + public static final String APP_ID_1 = "appId1"; + public static final String APP_ID_1_PROPERTY = LocalConfigConnector.APP_ID_PROPERTY + ": " + APP_ID_1; + + public static final String APP_ID_2 = "appId2"; + public static final String APP_ID_2_PROPERTY = LocalConfigConnector.APP_ID_PROPERTY + ": " + APP_ID_2; + + public static final String PROPERTY_FILE_NAME = "propFile"; + public static final String PROPERTY_FILE_PROPERTY = LocalConfigConnector.PROPERTIES_FILE_PROPERTY + ": " + PROPERTY_FILE_NAME; + + public static class AppIdTest { + + private LocalConfigConnector connector; + + @Before + public void setup() { + connector = new LocalConfigConnector(); + } + + @After + public void clearProperties() { + LocalConfigConnector.programmaticProperties = new Properties(); + } + + @Rule + public final ClearSystemProperties NO_APP_ID_PROPERTY = new ClearSystemProperties(LocalConfigConnector.APP_ID_PROPERTY); + + @Test + public void testNoAppIdAnywhere() { + assertFalse(connector.isInMatchingCloud()); + } + + @Test + public void testProgrammaticAppId() throws IOException { + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(APP_ID_1_PROPERTY.getBytes(UTF_8))); + assertTrue(connector.isInMatchingCloud()); + assertEquals(APP_ID_1, connector.getApplicationInstanceInfo().getAppId()); + } + + @Test + public void testProgrammaticAndFileAppIds() throws IOException { + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(APP_ID_1_PROPERTY.getBytes(UTF_8))); + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(PROPERTY_FILE_PROPERTY.getBytes(UTF_8))); + + LocalConfigConnector stubConnector = new LocalConfigConnector() { + @Override + InputStream openFile(String filename) throws IOException { + assertEquals(PROPERTY_FILE_NAME, filename); + return new ByteArrayInputStream(APP_ID_2_PROPERTY.getBytes(UTF_8)); + }; + }; + + assertTrue(stubConnector.isInMatchingCloud()); + assertEquals(APP_ID_2, stubConnector.getApplicationInstanceInfo().getAppId()); + } + + @Test + public void testProgrammaticFilenamePlusSystemAppId() throws IOException { + LocalConfigConnector.supplyProperties(new ByteArrayInputStream(PROPERTY_FILE_PROPERTY.getBytes(UTF_8))); + + LocalConfigConnector stubConnector = new LocalConfigConnector() { + @Override + InputStream openFile(String filename) throws IOException { + assertEquals(PROPERTY_FILE_NAME, filename); + return new ByteArrayInputStream(APP_ID_2_PROPERTY.getBytes(UTF_8)); + }; + }; + + System.setProperty(LocalConfigConnector.APP_ID_PROPERTY, "helloApp"); + assertTrue(stubConnector.isInMatchingCloud()); + assertEquals("helloApp", stubConnector.getApplicationInstanceInfo().getAppId()); + } + } + + private LocalConfigConnector connector; + + InputStream propertiesFile; + + @Before + public void setup() { + connector = new LocalConfigConnector(); + propertiesFile = LocalConfigConnectorTest.class.getClassLoader().getResourceAsStream("localconfig.properties"); + } + + @After + public void cleanup() throws IOException { + LocalConfigConnector.programmaticProperties = new Properties(); + propertiesFile.close(); + } + + @Test + public void testLoadFromFile() throws IOException { + LocalConfigConnector.supplyProperties(propertiesFile); + + assertTrue(connector.isInMatchingCloud()); + assertEquals("testApp", connector.getApplicationInstanceInfo().getAppId()); + + List services = connector.getServicesData(); + assertEquals(2, services.size()); + for (KeyValuePair service : services) + if ("foo".equals(service.getKey())) + assertEquals("bar", service.getValue()); + } + + @Rule + public ProvideSystemProperty BAZ_PROPERTY = new ProvideSystemProperty("spring.cloud.baz", "inline!"); + + @Test + public void testLoadFromInputStreamWithOverride() throws IOException { + LocalConfigConnector.supplyProperties(propertiesFile); + + assertTrue(connector.isInMatchingCloud()); + assertEquals("testApp", connector.getApplicationInstanceInfo().getAppId()); + + List services = connector.getServicesData(); + assertEquals(2, services.size()); + for(KeyValuePair service: services) + if("baz".equals(service.getKey())) + assertEquals("inline!", service.getValue()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java new file mode 100644 index 0000000..10eaa58 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java @@ -0,0 +1,74 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.*; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; + +public class LocalConfigUtilTest { + + private Properties first, second; + + private LinkedHashMap propertySources; + + @Before + public void initProperties(){ + first = new Properties(); + second = new Properties(); + + propertySources = new LinkedHashMap(); + propertySources.put("first", first); + propertySources.put("second", second); + } + + @Test + public void testPropertyParsing() { + first.setProperty("spring.cloud.appId", "should skip me because I'm meta"); + first.setProperty("spring.cloud.service1", "one"); + first.setProperty("spring.cloud.", "should skip me because I don't have an ID"); + first.setProperty("spring.cloud.service.two", "two"); + first.setProperty("foobar", "should skip me because I don't match the prefix"); + + Map services = LocalConfigUtil.readServices(first); + assertEquals(2, services.size()); + assertEquals("one", services.get("service1")); + assertEquals("two", services.get("service.two")); + } + + @Test + public void testCollation() { + first.setProperty("spring.cloud.first", "firstUri"); + second.setProperty("spring.cloud.second", "secondUri"); + + List serviceData = LocalConfigUtil.readServicesData(propertySources); + assertEquals(2, serviceData.size()); + boolean foundFirst = false; + + for(KeyValuePair kvp : serviceData) { + if(kvp.getKey().equals("first")) { + assertEquals("firstUri", kvp.getValue()); + foundFirst = true; + } + } + + assertTrue(foundFirst); + } + + @Test + public void testOverride() { + first.setProperty("spring.cloud.duplicate", "firstUri"); + second.setProperty("spring.cloud.duplicate", "secondUri"); + + List serviceData = LocalConfigUtil.readServicesData(propertySources); + assertEquals(1, serviceData.size()); + KeyValuePair kvp = serviceData.get(0); + assertEquals("duplicate", kvp.getKey()); + assertEquals("secondUri", kvp.getValue()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties new file mode 100644 index 0000000..bcc84c3 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties @@ -0,0 +1,3 @@ +spring.cloud.appId: testApp +spring.cloud.foo: bar +spring.cloud.baz: quux \ No newline at end of file From 488cd6aaeb34fd5adfe2c4a9cb0fc865bdf4464c Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 16:23:37 -0500 Subject: [PATCH 41/52] typo in constant name --- .../cloud/cloudfoundry/PostgresqlServiceInfoCreator.java | 2 +- .../cloud/service/common/PostgresqlServiceInfo.java | 2 +- .../cloud/heroku/PostgresqlServiceInfoCreator.java | 2 +- .../cloud/heroku/HerokuConnectorPostgresqlServiceTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java index 4b38fbf..abfbde1 100644 --- a/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-cloudfoundry-connector/src/main/java/org/springframework/cloud/cloudfoundry/PostgresqlServiceInfoCreator.java @@ -10,7 +10,7 @@ import org.springframework.cloud.service.common.PostgresqlServiceInfo; public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super(new Tags("postgresql"), PostgresqlServiceInfo.URI_SCHEMA); + super(new Tags("postgresql"), PostgresqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java index 2927782..edcace5 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/common/PostgresqlServiceInfo.java @@ -13,7 +13,7 @@ public class PostgresqlServiceInfo extends RelationalServiceInfo { public static final String JDBC_URL_TYPE = "postgresql"; - public static final String URI_SCHEMA = "postgres"; + public static final String URI_SCHEME = "postgres"; public PostgresqlServiceInfo(String id, String url) { super(id, url, JDBC_URL_TYPE); diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java index 7a44ea0..70f47de 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/PostgresqlServiceInfoCreator.java @@ -10,7 +10,7 @@ import org.springframework.cloud.service.common.PostgresqlServiceInfo; public class PostgresqlServiceInfoCreator extends RelationalServiceInfoCreator { public PostgresqlServiceInfoCreator() { - super(PostgresqlServiceInfo.URI_SCHEMA); + super(PostgresqlServiceInfo.URI_SCHEME); } @Override diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java index 9915ffa..52d7398 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/HerokuConnectorPostgresqlServiceTest.java @@ -19,7 +19,7 @@ import org.springframework.cloud.service.common.PostgresqlServiceInfo; */ public class HerokuConnectorPostgresqlServiceTest extends AbstractHerokuConnectorRelationalServiceTest { public HerokuConnectorPostgresqlServiceTest() { - super(PostgresqlServiceInfo.URI_SCHEMA); + super(PostgresqlServiceInfo.URI_SCHEME); } @Test From 21489526b5d6bf950b1baffab521359af5de4d37 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 16:28:06 -0500 Subject: [PATCH 42/52] document Java version requirement --- spring-cloud-core/README.md | 40 +++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/spring-cloud-core/README.md b/spring-cloud-core/README.md index 52c4d45..80233e4 100644 --- a/spring-cloud-core/README.md +++ b/spring-cloud-core/README.md @@ -2,10 +2,12 @@ Spring Cloud Core Library ========================= The core library to let cloud applications access application information and services. -While Spring applications is one of the main target for this library, it may be used in +While Spring applications is one of the main target for this library, it may be used in non-Spring projects as well. In fact, **this library doesn't even depend on Spring**. -This library is cloud-agnostic. Through connectors, it supports multiple clouds +This library requires Java 6, + +This library is cloud-agnostic. Through connectors, it supports multiple clouds (with Cloud Foundry and Heroku as the example clouds). This library also supports an extension to create services connectors of user-desired types. @@ -13,11 +15,11 @@ This library also supports an extension to create services connectors of user-de Usage pattern: Application Developers ===================================== -> **Note:** If you are using spring-cloud in a Spring application, you should consider using the -[Java config](../spring-cloud-spring-service-connector#the-java-config) or the +> **Note:** If you are using spring-cloud in a Spring application, you should consider using the +[Java config](../spring-cloud-spring-service-connector#the-java-config) or the [XML namespace support](../spring-cloud-spring-service-connector#the-cloud-namespace) instead. -* Create a [`CloudFactory`](src/main/java/org/springframework/cloud/CloudFactory.java) instance. +* Create a [`CloudFactory`](src/main/java/org/springframework/cloud/CloudFactory.java) instance. Creation of a `CloudFactory` instance is a bit expensive, so caching such an instance is recommended. If you are using a dependency injection frameworks such as Spring, creating a bean for `CloudFactory` will achieve the caching effect. @@ -25,45 +27,45 @@ Usage pattern: Application Developers ```java CloudFactory cloudFactory = new CloudFactory(); ``` -* Obtain a suitable [`Cloud`](src/main/java/org/springframework/cloud/Cloud.java) for the environment +* Obtain a suitable [`Cloud`](src/main/java/org/springframework/cloud/Cloud.java) for the environment in which the application is running. - + ```java Cloud cloud = cloudFactory.getCloud(); ``` Note that you must have a `CloudConnector` implementation suitable for the environment in which the application is being deployed in your classpath. For example, if you are - deploying the application in Cloud Foundry, you must add [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) + deploying the application in Cloud Foundry, you must add [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) in your classpath. If no suitable `CloudConnctor` is found, the `getCloud()` method will throw a `CloudException`. -* Use the `Cloud` instance to get access to application info, service infos, and create service +* Use the `Cloud` instance to get access to application info, service infos, and create service connectors. ```java // ServiceInfo has all the information necessary to connect to the underlying service cloud.getServiceInfos(); ``` - + ```java // Alternatively, let the cloud create a service connector for you DataSource ds = cloud.getServiceConnector("inventory-db", DataSource.class, null /* default config */); ``` - + Usage pattern: Cloud and Service Providers ========================================== A cloud provider may extends the functionality in two ways: -1. Add new [`CloudConnector`](src/main/java/org/springframework/cloud/CloudConnector.java)s to make - spring-cloud related libraries work with a new cloud. - See [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) - or [heroku-connector](../spring-cloud-heroku-connector) for an example. +1. Add new [`CloudConnector`](src/main/java/org/springframework/cloud/CloudConnector.java)s to make + spring-cloud related libraries work with a new cloud. + See [cloudfoundry-connector](../spring-cloud-cloudfoundry-connector) + or [heroku-connector](../spring-cloud-heroku-connector) for an example. This is done declaratively by adding connector classes to: ``` META-INF/services/org.springframework.cloud.CloudConnector ``` -2. Add new [`ServiceConnectorCreator`](src/main/java/org/springframework/cloud/service/ServiceConnectorCreator.java)s - to allow creation of service connector objects. - See [spring-service-connector](../spring-cloud-spring-service-connector) for an example. - This is done declaratively by adding creator classes to: +2. Add new [`ServiceConnectorCreator`](src/main/java/org/springframework/cloud/service/ServiceConnectorCreator.java)s + to allow creation of service connector objects. + See [spring-service-connector](../spring-cloud-spring-service-connector) for an example. + This is done declaratively by adding creator classes to: ``` META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator ``` \ No newline at end of file From 7d894c2c082b8422cb67b1f788218094073362fe Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 10 Jul 2014 17:01:14 -0500 Subject: [PATCH 43/52] add ServiceInfoCreators and SPI control files --- .../localconfig/AmqpServiceInfoCreator.java | 20 +++++++++++++++++++ .../localconfig/MongoServiceInfoCreator.java | 20 +++++++++++++++++++ .../localconfig/MysqlServiceInfoCreator.java | 20 +++++++++++++++++++ .../PostgresqlServiceInfoCreator.java | 20 +++++++++++++++++++ .../localconfig/RedisServiceInfoCreator.java | 20 +++++++++++++++++++ .../org.springframework.cloud.CloudConnector | 1 + ....localconfig.LocalConfigServiceInfoCreator | 5 +++++ 7 files changed, 106 insertions(+) create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java create mode 100644 spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector create mode 100644 spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java new file mode 100644 index 0000000..b9dc631 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/AmqpServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.AmqpServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class AmqpServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public AmqpServiceInfoCreator() { + super(AmqpServiceInfo.URI_SCHEME); + } + + @Override + public AmqpServiceInfo createServiceInfo(String id, String uri) { + return new AmqpServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java new file mode 100644 index 0000000..68671ac --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MongoServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.MongoServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class MongoServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public MongoServiceInfoCreator() { + super(MongoServiceInfo.URI_SCHEME); + } + + @Override + public MongoServiceInfo createServiceInfo(String id, String uri) { + return new MongoServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java new file mode 100644 index 0000000..0d39262 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/MysqlServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.MysqlServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class MysqlServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public MysqlServiceInfoCreator() { + super(MysqlServiceInfo.URI_SCHEME); + } + + @Override + public MysqlServiceInfo createServiceInfo(String id, String uri) { + return new MysqlServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java new file mode 100644 index 0000000..282da2f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/PostgresqlServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.PostgresqlServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class PostgresqlServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public PostgresqlServiceInfoCreator() { + super(PostgresqlServiceInfo.URI_SCHEME); + } + + @Override + public PostgresqlServiceInfo createServiceInfo(String id, String uri) { + return new PostgresqlServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java new file mode 100644 index 0000000..7a9e06f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/RedisServiceInfoCreator.java @@ -0,0 +1,20 @@ +package org.springframework.cloud.localconfig; + +import org.springframework.cloud.service.common.RedisServiceInfo; + +/** + * + * @author Christopher Smith + * + */ +public class RedisServiceInfoCreator extends LocalConfigServiceInfoCreator{ + + public RedisServiceInfoCreator() { + super(RedisServiceInfo.URI_SCHEME); + } + + @Override + public RedisServiceInfo createServiceInfo(String id, String uri) { + return new RedisServiceInfo(id, uri); + } +} diff --git a/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector new file mode 100644 index 0000000..2a7adb6 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.CloudConnector @@ -0,0 +1 @@ +org.springframework.cloud.localconfig.LocalConfigConnector \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator new file mode 100644 index 0000000..f8a14d4 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/main/resources/META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator @@ -0,0 +1,5 @@ +org.springframework.cloud.localconfig.AmqpServiceInfoCreator +org.springframework.cloud.localconfig.MongoServiceInfoCreator +org.springframework.cloud.localconfig.MysqlServiceInfoCreator +org.springframework.cloud.localconfig.PostgresqlServiceInfoCreator +org.springframework.cloud.localconfig.RedisServiceInfoCreator \ No newline at end of file From bbe8c6728d7846a6df7582027e854a4573f6eb9f Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 15:34:38 -0500 Subject: [PATCH 44/52] rename test case for clarity --- .../cloud/localconfig/LocalConfigConnectorTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java index 394e851..40b3913 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -32,7 +32,7 @@ public class LocalConfigConnectorTest { public static final String PROPERTY_FILE_NAME = "propFile"; public static final String PROPERTY_FILE_PROPERTY = LocalConfigConnector.PROPERTIES_FILE_PROPERTY + ": " + PROPERTY_FILE_NAME; - public static class AppIdTest { + public static class DetectAppIdTest { private LocalConfigConnector connector; From 3c4b5196f9fc1622993a1c3dfd94ee7103a7d40a Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 15:38:09 -0500 Subject: [PATCH 45/52] move property file name into constant, rename --- .../cloud/localconfig/LocalConfigConnectorTest.java | 4 ++-- .../src/test/resources/localconfig.nonsense.properties | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java index 40b3913..dd75a33 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -29,7 +29,7 @@ public class LocalConfigConnectorTest { public static final String APP_ID_2 = "appId2"; public static final String APP_ID_2_PROPERTY = LocalConfigConnector.APP_ID_PROPERTY + ": " + APP_ID_2; - public static final String PROPERTY_FILE_NAME = "propFile"; + public static final String PROPERTY_FILE_NAME = "localconfig.nonsense.properties"; public static final String PROPERTY_FILE_PROPERTY = LocalConfigConnector.PROPERTIES_FILE_PROPERTY + ": " + PROPERTY_FILE_NAME; public static class DetectAppIdTest { @@ -103,7 +103,7 @@ public class LocalConfigConnectorTest { @Before public void setup() { connector = new LocalConfigConnector(); - propertiesFile = LocalConfigConnectorTest.class.getClassLoader().getResourceAsStream("localconfig.properties"); + propertiesFile = LocalConfigConnectorTest.class.getClassLoader().getResourceAsStream(PROPERTY_FILE_NAME); } @After diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties new file mode 100644 index 0000000..bcc84c3 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.nonsense.properties @@ -0,0 +1,3 @@ +spring.cloud.appId: testApp +spring.cloud.foo: bar +spring.cloud.baz: quux \ No newline at end of file From b4fc3cc62453d371e4a60df9940bf8834f936ebb Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:00:08 -0500 Subject: [PATCH 46/52] constant wasn't final --- .../cloud/heroku/AbstractHerokuConnectorTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java index 7b88bf9..576dcfc 100644 --- a/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java +++ b/spring-cloud-heroku-connector/src/test/java/org/springframework/cloud/heroku/AbstractHerokuConnectorTest.java @@ -10,7 +10,7 @@ import org.springframework.cloud.util.EnvironmentAccessor; /** * Base test class that provides setup and utility methods to generate test payload - * + * * @author Ramnivas Laddad * */ @@ -20,7 +20,7 @@ public abstract class AbstractHerokuConnectorTest { protected static final String hostname = "10.20.30.40"; protected static final int port = 1234; - protected static String username = "myuser"; + protected static final String username = "myuser"; protected static final String password = "mypass"; @Before @@ -28,7 +28,7 @@ public abstract class AbstractHerokuConnectorTest { MockitoAnnotations.initMocks(this); testCloudConnector.setCloudEnvironment(mockEnvironment); } - + protected static ServiceInfo getServiceInfo(List serviceInfos, String serviceId) { for (ServiceInfo serviceInfo : serviceInfos) { if (serviceInfo.getId().equals(serviceId)) { From 7cf18cce1b3577c90ce11dced08bf5bf9de141e9 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:18:29 -0500 Subject: [PATCH 47/52] add getScheme() and a useful toString() --- .../cloud/service/UriBasedServiceInfo.java | 146 ++++++++++-------- 1 file changed, 79 insertions(+), 67 deletions(-) diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java index 78828de..fda552c 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfo.java @@ -6,84 +6,96 @@ import org.springframework.cloud.util.UriInfoFactory; /** * Common class for all {@link ServiceInfo}s - * + * * @author Ramnivas Laddad * */ public abstract class UriBasedServiceInfo extends BaseServiceInfo { - private UriInfo uriInfo; + private UriInfo uriInfo; - private static UriInfoFactory uriFactory = new StandardUriInfoFactory(); + private static UriInfoFactory uriFactory = new StandardUriInfoFactory(); - public UriBasedServiceInfo(String id, String scheme, String host, int port, String username, String password, String path) { - super(id); - this.uriInfo = getUriInfoFactory().createUri(scheme, host, port, username, password, path); - this.uriInfo = validateAndCleanUriInfo(uriInfo); - } - - public UriBasedServiceInfo(String id, String uriString) { - super(id); - this.uriInfo = getUriInfoFactory().createUri(uriString); - this.uriInfo = validateAndCleanUriInfo(uriInfo); - } + public UriBasedServiceInfo(String id, String scheme, String host, int port, String username, String password, String path) { + super(id); + this.uriInfo = getUriInfoFactory().createUri(scheme, host, port, username, password, path); + this.uriInfo = validateAndCleanUriInfo(uriInfo); + } - /** - * For URI-based (@link ServiceInfo}s which don't conform to the standard URI - * format, override this method in your own ServiceInfo class to return a - * {@link UriInfoFactory} which will create the appropriate URIs. - * - * @return your special UriInfoFactory - */ - public UriInfoFactory getUriInfoFactory() { - return uriFactory; - } + public UriBasedServiceInfo(String id, String uriString) { + super(id); + this.uriInfo = getUriInfoFactory().createUri(uriString); + this.uriInfo = validateAndCleanUriInfo(uriInfo); + } - @ServiceProperty(category="connection") - public String getUri() { - return uriInfo.getUri().toString(); - } - - @ServiceProperty(category="connection") - public String getUserName() { - return uriInfo.getUserName(); - } - - @ServiceProperty(category="connection") - public String getPassword() { - return uriInfo.getPassword(); - } + /** + * For URI-based (@link ServiceInfo}s which don't conform to the standard URI + * format, override this method in your own ServiceInfo class to return a {@link UriInfoFactory} which will create the + * appropriate URIs. + * + * @return your special UriInfoFactory + */ + public UriInfoFactory getUriInfoFactory() { + return uriFactory; + } - @ServiceProperty(category="connection") - public String getHost() { - return uriInfo.getHost(); - } + @ServiceProperty(category = "connection") + public String getUri() { + return uriInfo.getUri().toString(); + } - @ServiceProperty(category="connection") - public int getPort() { - return uriInfo.getPort(); - } + @ServiceProperty(category = "connection") + public String getUserName() { + return uriInfo.getUserName(); + } - @ServiceProperty(category="connection") - public String getPath() { - return uriInfo.getPath(); - } + @ServiceProperty(category = "connection") + public String getPassword() { + return uriInfo.getPassword(); + } - @ServiceProperty(category="connection") - public String getQuery() { - return uriInfo.getQuery(); - } + @ServiceProperty(category = "connection") + public String getHost() { + return uriInfo.getHost(); + } - /** - * Validate the URI and clean it up by using defaults for any missing information, if possible. - * - * @param uriInfo uri info based on parsed payload - * @return cleaned up uri info - */ - protected UriInfo validateAndCleanUriInfo(UriInfo uriInfo) { - return uriInfo; - } - - protected UriInfo getUriInfo() { - return uriInfo; - } + @ServiceProperty(category = "connection") + public int getPort() { + return uriInfo.getPort(); + } + + @ServiceProperty(category = "connection") + public String getPath() { + return uriInfo.getPath(); + } + + @ServiceProperty(category = "connection") + public String getQuery() { + return uriInfo.getQuery(); + } + + @ServiceProperty(category = "connection") + public String getScheme() { + return uriInfo.getScheme(); + } + + /** + * Validate the URI and clean it up by using defaults for any missing information, if possible. + * + * @param uriInfo + * uri info based on parsed payload + * @return cleaned up uri info + */ + protected UriInfo validateAndCleanUriInfo(UriInfo uriInfo) { + return uriInfo; + } + + protected UriInfo getUriInfo() { + return uriInfo; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getScheme() + "://" + getUserName() + ":****@" + getHost() + ":" + getPort() + + "/" + getPath() + "]"; + } } From 14272c8b104eb757d50a6a7fa0b3bfa71bf6334a Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:28:09 -0500 Subject: [PATCH 48/52] tests for all ServiceInfoCreators --- .../localconfig/LocalConfigConnector.java | 3 ++ .../cloud/localconfig/LocalConfigUtil.java | 6 ++- .../AbstractLocalConfigConnectorTest.java | 54 +++++++++++++++++++ .../LocalConfigConnectorAmqpServiceTest.java | 23 ++++++++ .../LocalConfigConnectorMongoServiceTest.java | 23 ++++++++ .../LocalConfigConnectorMysqlServiceTest.java | 23 ++++++++ ...lConfigConnectorPostgresqlServiceTest.java | 23 ++++++++ .../LocalConfigConnectorRedisServiceTest.java | 23 ++++++++ .../src/test/resources/localconfig.properties | 3 -- .../resources/localconfig.testuris.properties | 6 +++ 10 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java delete mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.properties create mode 100644 spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java index 93bb25f..babc2c0 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -79,6 +79,9 @@ public class LocalConfigConnector extends AbstractCloudConnector { @Override protected List getServicesData() { + if(fileProperties == null) + throw new IllegalStateException("isInMatchingCloud() must be called first to initialize connector"); + LinkedHashMap propertySources = new LinkedHashMap(); propertySources.put("programmatic properties", programmaticProperties); diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java index bd4d9f3..c2a4e82 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -23,7 +23,11 @@ public final class LocalConfigUtil { // iterate over the property sources in order, extracting matching properties for (Map.Entry propertySource : propertySources.entrySet()) { - logger.info("reading services from " + propertySource.getValue()); + if(propertySource.getValue().isEmpty()) { + logger.info("no " + propertySource.getKey()); + continue; + } + logger.info("reading services from " + propertySource.getKey()); Map services = readServices(propertySource.getValue()); // add each of the found services to the list, warning about duplicates diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java new file mode 100644 index 0000000..9313717 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/AbstractLocalConfigConnectorTest.java @@ -0,0 +1,54 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceInfo; + +public class AbstractLocalConfigConnectorTest { + + public static final String PROPERTIES_FILE = "localconfig.testuris.properties"; + + protected LocalConfigConnector connector = new LocalConfigConnector(); + + protected static final String HOSTNAME = "10.20.30.40"; + protected static final int PORT = 1234; + protected static final String USERNAME = "myuser"; + protected static final String PASSWORD = "mypass"; + + @Before + public void init() throws IOException { + InputStream propertiesFile = getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); + LocalConfigConnector.supplyProperties(propertiesFile); + assertTrue(connector.isInMatchingCloud()); + } + + @After + public void clearProperties() { + LocalConfigConnector.programmaticProperties = new Properties(); + } + + protected static ServiceInfo getServiceInfo(List serviceInfos, String serviceId) { + for (ServiceInfo serviceInfo : serviceInfos) { + if (serviceInfo.getId().equals(serviceId)) { + return serviceInfo; + } + } + return null; + } + + protected static void assertUriParameters(UriBasedServiceInfo serviceInfo) { + assertEquals(HOSTNAME, serviceInfo.getHost()); + assertEquals(PORT, serviceInfo.getPort()); + assertEquals(USERNAME, serviceInfo.getUserName()); + assertEquals(PASSWORD, serviceInfo.getPassword()); + } +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java new file mode 100644 index 0000000..a515741 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorAmqpServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.AmqpServiceInfo; + +public class LocalConfigConnectorAmqpServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "rabbit"); + assertNotNull(service); + assertTrue(service instanceof AmqpServiceInfo); + assertUriParameters((AmqpServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java new file mode 100644 index 0000000..5fec86f --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMongoServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MongoServiceInfo; + +public class LocalConfigConnectorMongoServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "candygram"); + assertNotNull(service); + assertTrue(service instanceof MongoServiceInfo); + assertUriParameters((MongoServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java new file mode 100644 index 0000000..4e305dd --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorMysqlServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MysqlServiceInfo; + +public class LocalConfigConnectorMysqlServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "maria"); + assertNotNull(service); + assertTrue(service instanceof MysqlServiceInfo); + assertUriParameters((MysqlServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java new file mode 100644 index 0000000..13123a5 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorPostgresqlServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.PostgresqlServiceInfo; + +public class LocalConfigConnectorPostgresqlServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "ingres"); + assertNotNull(service); + assertTrue(service instanceof PostgresqlServiceInfo); + assertUriParameters((PostgresqlServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java new file mode 100644 index 0000000..29dd550 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorRedisServiceTest.java @@ -0,0 +1,23 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.RedisServiceInfo; + +public class LocalConfigConnectorRedisServiceTest extends AbstractLocalConfigConnectorTest { + + @Test + public void serviceCreation() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "blue"); + assertNotNull(service); + assertTrue(service instanceof RedisServiceInfo); + assertUriParameters((RedisServiceInfo) service); + } + +} diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties deleted file mode 100644 index bcc84c3..0000000 --- a/spring-cloud-localconfig-connector/src/test/resources/localconfig.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring.cloud.appId: testApp -spring.cloud.foo: bar -spring.cloud.baz: quux \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties b/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties new file mode 100644 index 0000000..94bb5d9 --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/resources/localconfig.testuris.properties @@ -0,0 +1,6 @@ +spring.cloud.appId: testAppWithUris +spring.cloud.rabbit: amqp://myuser:mypass@10.20.30.40:1234/queue +spring.cloud.maria: mysql://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.candygram: mongodb://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.ingres: postgres://myuser:mypass@10.20.30.40:1234/dbname +spring.cloud.blue: redis://myuser:mypass@10.20.30.40:1234/dbname \ No newline at end of file From c42a8e3ba7ffe9cb043bc4e869cb90a2ab17d5f4 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:41:18 -0500 Subject: [PATCH 49/52] Add test to override programmatic definition from system properties. fixes #45 --- .../LocalConfigServiceOverrideTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java new file mode 100644 index 0000000..980067a --- /dev/null +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigServiceOverrideTest.java @@ -0,0 +1,34 @@ +package org.springframework.cloud.localconfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.ProvideSystemProperty; +import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.common.MongoServiceInfo; + +public class LocalConfigServiceOverrideTest extends AbstractLocalConfigConnectorTest { + + @Rule + public final ProvideSystemProperty OVERRIDE_MYSQL = + new ProvideSystemProperty( + "spring.cloud.candygram", + "mongodb://youruser:yourpass@40.30.20.10:4321/dbname"); + + @Test + public void serviceOverride() { + List services = connector.getServiceInfos(); + ServiceInfo service = getServiceInfo(services, "candygram"); + assertNotNull(service); + assertTrue(service instanceof MongoServiceInfo); + MongoServiceInfo mongo = (MongoServiceInfo) service; + assertEquals("youruser", mongo.getUserName()); + assertEquals(4321, mongo.getPort()); + } + +} From 73ba54d3d29b5b29cb15ff4c13ded4ef8741518b Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Fri, 11 Jul 2014 16:57:17 -0500 Subject: [PATCH 50/52] improved documentation --- spring-cloud-localconfig-connector/README.md | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/spring-cloud-localconfig-connector/README.md b/spring-cloud-localconfig-connector/README.md index 1f04dc9..128d2c3 100644 --- a/spring-cloud-localconfig-connector/README.md +++ b/spring-cloud-localconfig-connector/README.md @@ -6,6 +6,28 @@ The current implementation reads from Java properties only; in order to prevent on the Spring Framework, the placeholder functionality is unavailable in the connector. Pull requests for also inspecting environment variables are welcome. +Quick start +----------- +Since service URIs contain passwords and should not be stored in code, this connector does not +attempt to read properties out of the classpath. You can provide a filename with service definitions +by setting the `spring.cloud.propertiesFile` property or by passing in an open `InputStream`: + +````java +InputStream propertyStream = new FileInputStream("/path/to/spring-cloud.properties"); +LocalConfigConnector.supplyProperties(propertyStream); +Cloud cloud = new CloudFactory().getCloud(); +```` + +The property file should contain an application ID and the desired services in this format: + +````properties +spring.cloud.appId: myApp +; spring.cloud.{id}: URI +spring.cloud.database: mysql://user:pass@host:1234/dbname +```` + +Service type is determined by the URI scheme. + Property sources ---------------- This connector first attempts to read the system properties generally and a system property named From 40b2f647be425ce1b4a295556b0d4eb90732195a Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Mon, 14 Jul 2014 15:28:59 -0500 Subject: [PATCH 51/52] pull out KeyValuePair as top-level class --- .../cloud/AbstractCloudConnector.java | 18 ------------------ .../springframework/cloud/KeyValuePair.java | 19 +++++++++++++++++++ .../FallbackBaseServiceInfoCreator.java | 2 +- .../service/UriBasedServiceInfoCreator.java | 2 +- .../cloud/heroku/HerokuConnector.java | 2 +- .../localconfig/LocalConfigConnector.java | 2 +- .../cloud/localconfig/LocalConfigUtil.java | 2 +- .../localconfig/LocalConfigConnectorTest.java | 2 +- .../localconfig/LocalConfigUtilTest.java | 2 +- 9 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java b/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java index a515766..eb8291d 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/AbstractCloudConnector.java @@ -68,22 +68,4 @@ public abstract class AbstractCloudConnector implements CloudConnector { + " Did you forget to add a ServiceInfoCreator?"); return fallackServiceInfo; } - - public static class KeyValuePair { - private final String key; - private final String value; - - public KeyValuePair(String key, String value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public String getValue() { - return value; - } - } } \ No newline at end of file diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java b/spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java new file mode 100644 index 0000000..9a7a9c1 --- /dev/null +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java @@ -0,0 +1,19 @@ +package org.springframework.cloud; + +public class KeyValuePair { + private final String key; + private final String value; + + public KeyValuePair(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } +} \ No newline at end of file diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java index 23a815a..11dc842 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java @@ -1,7 +1,7 @@ package org.springframework.cloud.service; import org.springframework.cloud.FallbackServiceInfoCreator; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.KeyValuePair; public class FallbackBaseServiceInfoCreator extends FallbackServiceInfoCreator { @Override diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java index b856bc0..ee011d7 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java @@ -1,7 +1,7 @@ package org.springframework.cloud.service; +import org.springframework.cloud.KeyValuePair; import org.springframework.cloud.ServiceInfoCreator; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; public abstract class UriBasedServiceInfoCreator implements ServiceInfoCreator { diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java index ab91ba0..ee74fe6 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java @@ -6,9 +6,9 @@ import java.util.List; import java.util.Map; import org.springframework.cloud.AbstractCloudConnector; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; import org.springframework.cloud.CloudException; import org.springframework.cloud.FallbackServiceInfoCreator; +import org.springframework.cloud.KeyValuePair; import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java index babc2c0..9634ab4 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -15,7 +15,7 @@ import java.util.regex.Pattern; import org.springframework.cloud.AbstractCloudConnector; import org.springframework.cloud.FallbackServiceInfoCreator; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.KeyValuePair; import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.app.BasicApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java index c2a4e82..7951212 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -9,7 +9,7 @@ import java.util.Properties; import java.util.logging.Logger; import java.util.regex.Matcher; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.KeyValuePair; public final class LocalConfigUtil { private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java index dd75a33..6512695 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -17,7 +17,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.ClearSystemProperties; import org.junit.contrib.java.lang.system.ProvideSystemProperty; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.KeyValuePair; public class LocalConfigConnectorTest { diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java index 10eaa58..82e39e1 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java @@ -9,7 +9,7 @@ import java.util.Properties; import org.junit.Before; import org.junit.Test; -import org.springframework.cloud.AbstractCloudConnector.KeyValuePair; +import org.springframework.cloud.KeyValuePair; public class LocalConfigUtilTest { From 8f5a346023129294dcff3a92f39bce9311bcd606 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 15 Jul 2014 16:41:39 -0500 Subject: [PATCH 52/52] rename KeyValuePair to UriBasedServiceData and rename "value" field --- .../springframework/cloud/KeyValuePair.java | 19 ------------------- .../FallbackBaseServiceInfoCreator.java | 5 ++--- .../cloud/service/UriBasedServiceData.java | 19 +++++++++++++++++++ .../service/UriBasedServiceInfoCreator.java | 11 +++++------ .../cloud/heroku/HerokuConnector.java | 14 +++++++------- .../localconfig/LocalConfigConnector.java | 8 ++++---- .../cloud/localconfig/LocalConfigUtil.java | 8 ++++---- .../localconfig/LocalConfigConnectorTest.java | 14 +++++++------- .../localconfig/LocalConfigUtilTest.java | 14 +++++++------- 9 files changed, 55 insertions(+), 57 deletions(-) delete mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java create mode 100644 spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceData.java diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java b/spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java deleted file mode 100644 index 9a7a9c1..0000000 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/KeyValuePair.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.springframework.cloud; - -public class KeyValuePair { - private final String key; - private final String value; - - public KeyValuePair(String key, String value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public String getValue() { - return value; - } -} \ No newline at end of file diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java index 11dc842..e819b76 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/FallbackBaseServiceInfoCreator.java @@ -1,11 +1,10 @@ package org.springframework.cloud.service; import org.springframework.cloud.FallbackServiceInfoCreator; -import org.springframework.cloud.KeyValuePair; -public class FallbackBaseServiceInfoCreator extends FallbackServiceInfoCreator { +public class FallbackBaseServiceInfoCreator extends FallbackServiceInfoCreator { @Override - public BaseServiceInfo createServiceInfo(KeyValuePair serviceData) { + public BaseServiceInfo createServiceInfo(UriBasedServiceData serviceData) { return new BaseServiceInfo(serviceData.getKey()); } } diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceData.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceData.java new file mode 100644 index 0000000..67d02a2 --- /dev/null +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceData.java @@ -0,0 +1,19 @@ +package org.springframework.cloud.service; + +public class UriBasedServiceData { + private final String key; + private final String uri; + + public UriBasedServiceData(String key, String uri) { + this.key = key; + this.uri = uri; + } + + public String getKey() { + return key; + } + + public String getUri() { + return uri; + } +} \ No newline at end of file diff --git a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java index ee011d7..a76ab3b 100644 --- a/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java +++ b/spring-cloud-core/src/main/java/org/springframework/cloud/service/UriBasedServiceInfoCreator.java @@ -1,10 +1,9 @@ package org.springframework.cloud.service; -import org.springframework.cloud.KeyValuePair; import org.springframework.cloud.ServiceInfoCreator; public abstract class UriBasedServiceInfoCreator implements - ServiceInfoCreator { + ServiceInfoCreator { private final String uriScheme; @@ -13,14 +12,14 @@ public abstract class UriBasedServiceInfoCreator impleme } @Override - public boolean accept(KeyValuePair serviceData) { - return serviceData.getValue().toString().startsWith(uriScheme + "://"); + public boolean accept(UriBasedServiceData serviceData) { + return serviceData.getUri().toString().startsWith(uriScheme + "://"); } public abstract SI createServiceInfo(String id, String uri); @Override - public SI createServiceInfo(KeyValuePair serviceData) { - return createServiceInfo(serviceData.getKey(), serviceData.getValue()); + public SI createServiceInfo(UriBasedServiceData serviceData) { + return createServiceInfo(serviceData.getKey(), serviceData.getUri()); } } diff --git a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java index ee74fe6..55d1cba 100644 --- a/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java +++ b/spring-cloud-heroku-connector/src/main/java/org/springframework/cloud/heroku/HerokuConnector.java @@ -8,12 +8,12 @@ import java.util.Map; import org.springframework.cloud.AbstractCloudConnector; import org.springframework.cloud.CloudException; import org.springframework.cloud.FallbackServiceInfoCreator; -import org.springframework.cloud.KeyValuePair; import org.springframework.cloud.ServiceInfoCreator; import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; import org.springframework.cloud.service.FallbackBaseServiceInfoCreator; import org.springframework.cloud.service.ServiceInfo; +import org.springframework.cloud.service.UriBasedServiceData; import org.springframework.cloud.util.EnvironmentAccessor; /** @@ -25,7 +25,7 @@ import org.springframework.cloud.util.EnvironmentAccessor; * @author Ramnivas Laddad * */ -public class HerokuConnector extends AbstractCloudConnector { +public class HerokuConnector extends AbstractCloudConnector { private EnvironmentAccessor environment = new EnvironmentAccessor(); private ApplicationInstanceInfoCreator applicationInstanceInfoCreator @@ -59,7 +59,7 @@ public class HerokuConnector extends AbstractCloudConnector { } @Override - protected void registerServiceInfoCreator(ServiceInfoCreator serviceInfoCreator) { + protected void registerServiceInfoCreator(ServiceInfoCreator serviceInfoCreator) { super.registerServiceInfoCreator(serviceInfoCreator); HerokuServiceInfoCreator herokuServiceInfoCreator = (HerokuServiceInfoCreator)serviceInfoCreator; String[] envPrefixes = herokuServiceInfoCreator.getEnvPrefixes(); @@ -78,15 +78,15 @@ public class HerokuConnector extends AbstractCloudConnector { *

* @return information about services bound to the app */ - protected List getServicesData() { - List serviceData = new ArrayList(); + protected List getServicesData() { + List serviceData = new ArrayList(); Map env = environment.getEnv(); for (Map.Entry envEntry : env.entrySet()) { for (String envPrefix : serviceEnvPrefixes) { if (envEntry.getKey().startsWith(envPrefix)) { - serviceData.add(new KeyValuePair(envEntry.getKey(), envEntry.getValue())); + serviceData.add(new UriBasedServiceData(envEntry.getKey(), envEntry.getValue())); } } } @@ -95,7 +95,7 @@ public class HerokuConnector extends AbstractCloudConnector { } @Override - protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { + protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { return new FallbackBaseServiceInfoCreator(); } } \ No newline at end of file diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java index 9634ab4..3a8251a 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigConnector.java @@ -15,18 +15,18 @@ import java.util.regex.Pattern; import org.springframework.cloud.AbstractCloudConnector; import org.springframework.cloud.FallbackServiceInfoCreator; -import org.springframework.cloud.KeyValuePair; import org.springframework.cloud.app.ApplicationInstanceInfo; import org.springframework.cloud.app.BasicApplicationInstanceInfo; import org.springframework.cloud.service.BaseServiceInfo; import org.springframework.cloud.service.FallbackBaseServiceInfoCreator; +import org.springframework.cloud.service.UriBasedServiceData; /** * * @author Christopher Smith * */ -public class LocalConfigConnector extends AbstractCloudConnector { +public class LocalConfigConnector extends AbstractCloudConnector { private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); @@ -78,7 +78,7 @@ public class LocalConfigConnector extends AbstractCloudConnector { } @Override - protected List getServicesData() { + protected List getServicesData() { if(fileProperties == null) throw new IllegalStateException("isInMatchingCloud() must be called first to initialize connector"); @@ -97,7 +97,7 @@ public class LocalConfigConnector extends AbstractCloudConnector { } @Override - protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { + protected FallbackServiceInfoCreator getFallbackServiceInfoCreator() { return new FallbackBaseServiceInfoCreator(); } diff --git a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java index 7951212..3dbc38f 100644 --- a/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java +++ b/spring-cloud-localconfig-connector/src/main/java/org/springframework/cloud/localconfig/LocalConfigUtil.java @@ -9,7 +9,7 @@ import java.util.Properties; import java.util.logging.Logger; import java.util.regex.Matcher; -import org.springframework.cloud.KeyValuePair; +import org.springframework.cloud.service.UriBasedServiceData; public final class LocalConfigUtil { private static final Logger logger = Logger.getLogger(LocalConfigConnector.class.getName()); @@ -17,7 +17,7 @@ public final class LocalConfigUtil { private LocalConfigUtil() { } - static List readServicesData(LinkedHashMap propertySources) { + static List readServicesData(LinkedHashMap propertySources) { // we'll turn this into KVPs to return but need to eliminate duplicates first Map collectedServices = new HashMap(); @@ -41,9 +41,9 @@ public final class LocalConfigUtil { } // now we have a collated set of service IDs and URIs - List serviceData = new ArrayList(collectedServices.size()); + List serviceData = new ArrayList(collectedServices.size()); for (Map.Entry serviceInfo : collectedServices.entrySet()) { - serviceData.add(new KeyValuePair(serviceInfo.getKey(), serviceInfo.getValue())); + serviceData.add(new UriBasedServiceData(serviceInfo.getKey(), serviceInfo.getValue())); } return serviceData; diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java index 6512695..9bf3f1d 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigConnectorTest.java @@ -17,7 +17,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.ClearSystemProperties; import org.junit.contrib.java.lang.system.ProvideSystemProperty; -import org.springframework.cloud.KeyValuePair; +import org.springframework.cloud.service.UriBasedServiceData; public class LocalConfigConnectorTest { @@ -119,11 +119,11 @@ public class LocalConfigConnectorTest { assertTrue(connector.isInMatchingCloud()); assertEquals("testApp", connector.getApplicationInstanceInfo().getAppId()); - List services = connector.getServicesData(); + List services = connector.getServicesData(); assertEquals(2, services.size()); - for (KeyValuePair service : services) + for (UriBasedServiceData service : services) if ("foo".equals(service.getKey())) - assertEquals("bar", service.getValue()); + assertEquals("bar", service.getUri()); } @Rule @@ -136,10 +136,10 @@ public class LocalConfigConnectorTest { assertTrue(connector.isInMatchingCloud()); assertEquals("testApp", connector.getApplicationInstanceInfo().getAppId()); - List services = connector.getServicesData(); + List services = connector.getServicesData(); assertEquals(2, services.size()); - for(KeyValuePair service: services) + for(UriBasedServiceData service: services) if("baz".equals(service.getKey())) - assertEquals("inline!", service.getValue()); + assertEquals("inline!", service.getUri()); } } diff --git a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java index 82e39e1..306e5db 100644 --- a/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java +++ b/spring-cloud-localconfig-connector/src/test/java/org/springframework/cloud/localconfig/LocalConfigUtilTest.java @@ -9,7 +9,7 @@ import java.util.Properties; import org.junit.Before; import org.junit.Test; -import org.springframework.cloud.KeyValuePair; +import org.springframework.cloud.service.UriBasedServiceData; public class LocalConfigUtilTest { @@ -46,13 +46,13 @@ public class LocalConfigUtilTest { first.setProperty("spring.cloud.first", "firstUri"); second.setProperty("spring.cloud.second", "secondUri"); - List serviceData = LocalConfigUtil.readServicesData(propertySources); + List serviceData = LocalConfigUtil.readServicesData(propertySources); assertEquals(2, serviceData.size()); boolean foundFirst = false; - for(KeyValuePair kvp : serviceData) { + for(UriBasedServiceData kvp : serviceData) { if(kvp.getKey().equals("first")) { - assertEquals("firstUri", kvp.getValue()); + assertEquals("firstUri", kvp.getUri()); foundFirst = true; } } @@ -65,10 +65,10 @@ public class LocalConfigUtilTest { first.setProperty("spring.cloud.duplicate", "firstUri"); second.setProperty("spring.cloud.duplicate", "secondUri"); - List serviceData = LocalConfigUtil.readServicesData(propertySources); + List serviceData = LocalConfigUtil.readServicesData(propertySources); assertEquals(1, serviceData.size()); - KeyValuePair kvp = serviceData.get(0); + UriBasedServiceData kvp = serviceData.get(0); assertEquals("duplicate", kvp.getKey()); - assertEquals("secondUri", kvp.getValue()); + assertEquals("secondUri", kvp.getUri()); } }