From 940358ff1a6a60f82c25679fffcf734bf67be423 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 26 Mar 2013 16:05:40 -0500 Subject: [PATCH 1/5] Move Archaius bindings to this repository. --- pom.xml | 1 + service-registry-archaius/README.md | 25 ++++ service-registry-archaius/pom.xml | 79 +++++++++++ .../config/sources/ServiceRegistryClient.java | 12 ++ .../ServiceRegistryClientProvider.java | 24 ++++ .../ServiceRegistryConfigurationProvider.java | 87 ++++++++++++ ...viceRegistryConfigurationProviderTest.java | 134 ++++++++++++++++++ ...tServiceRegistryConfigurationProvider.java | 40 ++++++ .../src/test/resources/config.properties | 1 + .../src/test/resources/logback-test.xml | 11 ++ 10 files changed, 414 insertions(+) create mode 100644 service-registry-archaius/README.md create mode 100644 service-registry-archaius/pom.xml create mode 100644 service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClient.java create mode 100644 service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java create mode 100644 service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java create mode 100644 service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java create mode 100644 service-registry-archaius/src/test/java/com/netflix/config/sources/test/TestServiceRegistryConfigurationProvider.java create mode 100644 service-registry-archaius/src/test/resources/config.properties create mode 100644 service-registry-archaius/src/test/resources/logback-test.xml diff --git a/pom.xml b/pom.xml index 34e4b74..23a4b95 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,7 @@ service-registry-client service-registry-examples service-registry-curator + service-registry-archaius diff --git a/service-registry-archaius/README.md b/service-registry-archaius/README.md new file mode 100644 index 0000000..4f77986 --- /dev/null +++ b/service-registry-archaius/README.md @@ -0,0 +1,25 @@ +# Service Registry Provider for Archaius + +This library provides bindings for the [Archaius Library](https://github.com/Netflix/archaius). That library provides a set of configuration management API's for +managing values. + +This particular extension provides a new `source` called the `ServiceRegistryConfigurationProvider`. It +provides a configuration source backed by [Rackspace Service Registry](http://www.rackspace.com/blog/keep-track-of-your-services-and-applications-with-the-new-rackspace-service-registry/). +It works in an idiomatic archaius way which plugs in with the rest of the system. + +Here is a snippet of example code + +```java +final Client client = new Client(System.getProperty("rackspace.serviceregistry.username"), + System.getProperty("rackspace.serviceregistry.apikey"), + Region.US); +PolledConfigurationSource configSource = new ServiceRegistryConfigurationProvider(client); +AbstractPollingScheduler scheduler = new FixedDelayPollingScheduler(); +DynamicConfiguration config = new DynamicConfiguration(configSource, scheduler); +``` + +# TODO + +* Upload a maven artifact +* Add more tests +* Add docs around the service bindings diff --git a/service-registry-archaius/pom.xml b/service-registry-archaius/pom.xml new file mode 100644 index 0000000..70cc184 --- /dev/null +++ b/service-registry-archaius/pom.xml @@ -0,0 +1,79 @@ + + 4.0.0 + + + com.rackspacecloud + service-registry-parent + 2.0.0-SNAPSHOT + + + Service Registry Client Archaius Bindings + service-registry-archaius + 0.0.1-SNAPSHOT + jar + http://maven.apache.org + + + UTF-8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + + + + sonatype-nexus-snapshots + Nexus Snapshots Repository + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + + junit + junit + 4.11 + test + + + com.netflix.archaius + archaius-core + 0.5.3 + + + org.slf4j + slf4j-api + + + + + com.rackspacecloud + service-registry-client + 1.0.0-SNAPSHOT + + + org.slf4j + slf4j-api + 1.7.2 + + + ch.qos.logback + logback-classic + 1.0.9 + test + + + diff --git a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClient.java b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClient.java new file mode 100644 index 0000000..2353eb9 --- /dev/null +++ b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClient.java @@ -0,0 +1,12 @@ +package com.netflix.config.sources; + +import com.rackspacecloud.client.service_registry.objects.ConfigurationValue; +import com.rackspacecloud.client.service_registry.objects.Service; + +import java.util.List; + +public interface ServiceRegistryClient { + List getServices(String tag) throws Exception; + + List getConfiguration() throws Exception; +} diff --git a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java new file mode 100644 index 0000000..c0dda3b --- /dev/null +++ b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java @@ -0,0 +1,24 @@ +package com.netflix.config.sources; + +import com.rackspacecloud.client.service_registry.Client; +import com.rackspacecloud.client.service_registry.objects.ConfigurationValue; +import com.rackspacecloud.client.service_registry.objects.Service; + +import java.util.List; + +public class ServiceRegistryClientProvider implements ServiceRegistryClient { + private final Client client; + + public ServiceRegistryClientProvider(String user, String key, String region) { + client = new Client(user, key, region); + } + @Override + public List getServices(String tag) throws Exception { + return client.services.list(null, tag); + } + + @Override + public List getConfiguration() throws Exception { + return client.configuration.list(null); + } +} diff --git a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java new file mode 100644 index 0000000..5147fb4 --- /dev/null +++ b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java @@ -0,0 +1,87 @@ +package com.netflix.config.sources; + +import com.netflix.config.DynamicPropertyFactory; +import com.netflix.config.DynamicStringProperty; +import com.netflix.config.PollResult; +import com.netflix.config.PolledConfigurationSource; +import com.rackspacecloud.client.service_registry.objects.ConfigurationValue; +import com.rackspacecloud.client.service_registry.objects.Service; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetSocketAddress; +import java.util.*; + +public class ServiceRegistryConfigurationProvider implements PolledConfigurationSource { + + private static Logger logger = LoggerFactory.getLogger(ServiceRegistryConfigurationProvider.class); + + private static final String DELIMITER ="."; + public static final String PREFIX = "serverset"; + public static final String INTEREST = PREFIX + DELIMITER + "interest"; + private static final String SEPARATOR = ","; + private static final String SUFFIX = "addresses"; + + public static final DynamicStringProperty dynamicServiceTags = DynamicPropertyFactory.getInstance().getStringProperty(INTEREST, ""); + + private final ServiceRegistryClient client; + + public ServiceRegistryConfigurationProvider(ServiceRegistryClient client) { + this.client = client; + } + + @Override + public PollResult poll(boolean initial, Object checkPoint) + throws Exception { + + Map map = new HashMap(); + for (ConfigurationValue value : client.getConfiguration()) { + map.put(value.getId(), value.getValue()); + } + + // Do a query to get all the service tags we're interested in, + // once we have that we'll namespace the parameters + String tags = dynamicServiceTags.get(); + if (!tags.isEmpty()) { + Set serviceTags = new HashSet(Arrays.asList(tags.split(SEPARATOR))); + for (String tag: serviceTags) { + Set pairs = new HashSet(); + String key = PREFIX + DELIMITER + tag + DELIMITER + SUFFIX; + for (Service service : client.getServices(tag)) { + pairs.add(getHostPortPair(service)); + } + if (!pairs.isEmpty()) { + map.put(key, StringUtils.join(pairs, SEPARATOR)); + } + } + } + return PollResult.createFull(map); + } + + @Override + public String toString() { + return "ServiceRegistryConfigurationProvider [client=" + client.toString() + "]"; + } + + /** + * Safely get the information from our convention + * @param svc + * @return + */ + public static InetSocketAddress getHostPortPair(Service svc) { + try { + return new InetSocketAddress(svc.getMetadata().get("service.host"), + Integer.parseInt(svc.getMetadata().get("service.port"))); + } catch (Exception e) { + logger.error("Exception extracting metadata from service instance {}", svc, e); + return null; + } + } + + public static Service setHostPortPair(String host, int port, Service svc) { + svc.getMetadata().put("service.host", host); + svc.getMetadata().put("service.port", String.valueOf(port)); + return svc; + } +} diff --git a/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java b/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java new file mode 100644 index 0000000..6b97ad5 --- /dev/null +++ b/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java @@ -0,0 +1,134 @@ +package com.netflix.config.sources.test; + + +import com.netflix.config.*; +import com.netflix.config.sources.ServiceRegistryConfigurationProvider; +import com.rackspacecloud.client.service_registry.objects.Service; +import org.apache.commons.configuration.AbstractConfiguration; +import org.apache.commons.lang.StringUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +public class ServiceRegistryConfigurationProviderTest { + + private static TestServiceRegistryConfigurationProvider testInstance; + private static PolledConfigurationSource src; + private static final Logger logger = LoggerFactory.getLogger(ServiceRegistryConfigurationProviderTest.class); + private static AbstractPollingScheduler simplePollingScheduler; + private static DynamicConfiguration dynamicConfiguration; + + public String getRandomTag() { + byte diff = 'z' - 'a'; + byte[] bytes = new byte[5]; + StringBuilder sb = new StringBuilder(); + new Random().nextBytes(bytes); + for (byte b : bytes) { + sb.append((char)('a' + Math.abs(b % diff))); + } + logger.info("Random tag generated '{}'", sb.toString()); + return sb.toString(); + } + public void pollOnce() { + dynamicConfiguration.startPolling(src, simplePollingScheduler); + } + + @BeforeClass + public static void beforeClass() { + testInstance = new TestServiceRegistryConfigurationProvider(); + src = new ServiceRegistryConfigurationProvider(testInstance); + simplePollingScheduler = new AbstractPollingScheduler() { + @Override + protected void schedule(Runnable pollingRunnable) { + logger.info("Scheduling poller"); + pollingRunnable.run(); + } + + @Override + public void stop() { + logger.info("Stopping logger"); + } + }; + + // Inject initial properties + HashMap cfg = new HashMap(); + + AbstractConfiguration configuration = new ConcurrentMapConfiguration(cfg); + dynamicConfiguration = new DynamicConfiguration(src, simplePollingScheduler); + + ConcurrentCompositeConfiguration finalConfig = new ConcurrentCompositeConfiguration(); + + // add them in this order to make dynamicConfig override configuration + finalConfig.addConfiguration(dynamicConfiguration); + finalConfig.addConfiguration(configuration); + + ConfigurationManager.install(finalConfig); + + } + + @Test + public void testPolling() throws Exception { + String host = "host"; + int port = 92; + String tag = getRandomTag(); + + ConfigurationManager.getConfigInstance().setProperty(ServiceRegistryConfigurationProvider.INTEREST, tag); + + for (int i = 0; i < 10; i++) { + testInstance.addService(tag, ServiceRegistryConfigurationProvider.setHostPortPair( + host, + port, + new Service("faux" + i, "fauxSession", Collections.singletonList(tag), new HashMap()))); + } + String key = ServiceRegistryConfigurationProvider.PREFIX + "." + tag + ".addresses"; + pollOnce(); + + Assert.assertEquals(new InetSocketAddress(host, port).toString(), + ConfigurationManager.getConfigInstance().getString(key)); + } + + @Test + public void testPollingChanging() throws Exception { + String host = "localhost"; + int port = 92; + String[] tags = {getRandomTag(), getRandomTag()}; + ConfigurationManager.getConfigInstance().setProperty( + ServiceRegistryConfigurationProvider.INTEREST, StringUtils.join(tags, ",")); + Map scoreboard = new HashMap(); + + for (int i = 0; i < tags.length; i++) { + for (int j = 0; j < 5; j++) { + String realHost = host + i + j; + testInstance.addService(tags[i], ServiceRegistryConfigurationProvider.setHostPortPair( + host + i + j, + port, + new Service("faux" + i + j, "fauxSession", Collections.singletonList(tags[i]), new HashMap()))); + + + Integer score = scoreboard.get(tags[i]); + if (score == null) { + scoreboard.put(tags[i], 1); + } else { + scoreboard.put(tags[i], score + 1); + } + } + } + + String firstKey = ServiceRegistryConfigurationProvider.PREFIX + "." + tags[0] + ".addresses"; + String secondKey = ServiceRegistryConfigurationProvider.PREFIX + "." + tags[1] + ".addresses"; + pollOnce(); + + Assert.assertEquals((Object) scoreboard.get(tags[0]), + ConfigurationManager.getConfigInstance().getList(firstKey).size()); + Assert.assertEquals((Object) scoreboard.get(tags[1]), + ConfigurationManager.getConfigInstance().getList(secondKey).size()); + } +} diff --git a/service-registry-archaius/src/test/java/com/netflix/config/sources/test/TestServiceRegistryConfigurationProvider.java b/service-registry-archaius/src/test/java/com/netflix/config/sources/test/TestServiceRegistryConfigurationProvider.java new file mode 100644 index 0000000..340733a --- /dev/null +++ b/service-registry-archaius/src/test/java/com/netflix/config/sources/test/TestServiceRegistryConfigurationProvider.java @@ -0,0 +1,40 @@ +package com.netflix.config.sources.test; + +import com.netflix.config.sources.ServiceRegistryClient; +import com.rackspacecloud.client.service_registry.objects.ConfigurationValue; +import com.rackspacecloud.client.service_registry.objects.Service; + +import java.util.*; + +public class TestServiceRegistryConfigurationProvider implements ServiceRegistryClient { + + Map> services = new HashMap>(); + List configurationValues = new ArrayList(); + + public void addService(String tag, Service svc) { + List svcs = services.get(tag); + if (svcs == null) { + svcs = new ArrayList(); + } + svcs.add(svc); + services.put(tag, svcs); + } + + public void addConfigurationValue(ConfigurationValue cfg) { + configurationValues.add(cfg); + } + + @Override + public List getServices(String tag) throws Exception { + List result = services.get(tag); + if (result == null) { + return Collections.emptyList(); + } + return result; + } + + @Override + public List getConfiguration() throws Exception { + return configurationValues; + } +} diff --git a/service-registry-archaius/src/test/resources/config.properties b/service-registry-archaius/src/test/resources/config.properties new file mode 100644 index 0000000..a8d3ae3 --- /dev/null +++ b/service-registry-archaius/src/test/resources/config.properties @@ -0,0 +1 @@ +test.more="foo" \ No newline at end of file diff --git a/service-registry-archaius/src/test/resources/logback-test.xml b/service-registry-archaius/src/test/resources/logback-test.xml new file mode 100644 index 0000000..8de3d38 --- /dev/null +++ b/service-registry-archaius/src/test/resources/logback-test.xml @@ -0,0 +1,11 @@ + + + + false + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + \ No newline at end of file From 298ca2cd6762b0a2be40b38fdb8e9e6104b0fcb7 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 26 Mar 2013 16:15:42 -0500 Subject: [PATCH 2/5] Upgrade readme. --- README.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dee583a..2141eb9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Java Rackspace Service Registry client +# Java Rackspace Service Registry Client Java client for Rackspace Service Registry. ## Build and run tests - mvn install + mvn install ## Using the client @@ -27,12 +27,12 @@ Add the following lines in the `repositories` and `dependencies` section in your If you're using ivy, this needs to be in your ivysettings.xml: ```xml - + changingPattern="SNAPSHOT*"/> ``` This lines are necessary because artifacts are currently only stored on Sonatype staging Maven servers. @@ -56,10 +56,18 @@ Released versions of the library are integrated into Maven Central. There is no com.rackspacecloud service-registry-client 1.0.0 - + ``` -Other modules you may be interested in include `service-registry-curator` and `service-registry-examples`. +### Other Modules + +This repository also includes other modules: + +`service-registry-curator` - Service Registry bindings for Netflix Curator +library +`service-registry-archaius` - Service Registry bindings for Netflix Archaius +library +`service-registry-examples` - Usage examples ### Examples From 6ea4f3de5868b740d0fee87d4b93438ff7a19ee4 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Tue, 26 Mar 2013 16:28:56 -0500 Subject: [PATCH 3/5] Upgrade client to 2.0.0 and update affected code. --- service-registry-archaius/pom.xml | 2 +- .../netflix/config/sources/ServiceRegistryClientProvider.java | 4 ++-- .../test/ServiceRegistryConfigurationProviderTest.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/service-registry-archaius/pom.xml b/service-registry-archaius/pom.xml index 70cc184..6567b5b 100644 --- a/service-registry-archaius/pom.xml +++ b/service-registry-archaius/pom.xml @@ -62,7 +62,7 @@ com.rackspacecloud service-registry-client - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT org.slf4j diff --git a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java index c0dda3b..ef329bf 100644 --- a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java +++ b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java @@ -14,11 +14,11 @@ public ServiceRegistryClientProvider(String user, String key, String region) { } @Override public List getServices(String tag) throws Exception { - return client.services.list(null, tag); + return client.getServicesClient().list(null, tag); } @Override public List getConfiguration() throws Exception { - return client.configuration.list(null); + return client.getConfigurationClient().list(null); } } diff --git a/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java b/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java index 6b97ad5..25b2d25 100644 --- a/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java +++ b/service-registry-archaius/src/test/java/com/netflix/config/sources/test/ServiceRegistryConfigurationProviderTest.java @@ -86,7 +86,7 @@ public void testPolling() throws Exception { testInstance.addService(tag, ServiceRegistryConfigurationProvider.setHostPortPair( host, port, - new Service("faux" + i, "fauxSession", Collections.singletonList(tag), new HashMap()))); + new Service("faux" + i, 15, Collections.singletonList(tag), new HashMap()))); } String key = ServiceRegistryConfigurationProvider.PREFIX + "." + tag + ".addresses"; pollOnce(); @@ -110,7 +110,7 @@ public void testPollingChanging() throws Exception { testInstance.addService(tags[i], ServiceRegistryConfigurationProvider.setHostPortPair( host + i + j, port, - new Service("faux" + i + j, "fauxSession", Collections.singletonList(tags[i]), new HashMap()))); + new Service("faux" + i + j, 15, Collections.singletonList(tags[i]), new HashMap()))); Integer score = scoreboard.get(tags[i]); From 6e1f74607e7633850f7456090b7e18f49853bad7 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Wed, 27 Mar 2013 08:54:43 -0500 Subject: [PATCH 4/5] Style. --- .../netflix/config/sources/ServiceRegistryClientProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java index ef329bf..6a166ba 100644 --- a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java +++ b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java @@ -12,6 +12,7 @@ public class ServiceRegistryClientProvider implements ServiceRegistryClient { public ServiceRegistryClientProvider(String user, String key, String region) { client = new Client(user, key, region); } + @Override public List getServices(String tag) throws Exception { return client.getServicesClient().list(null, tag); From 6d9f1a49b54fd8253479ab45359b4b32ab78f977 Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Wed, 27 Mar 2013 08:55:41 -0500 Subject: [PATCH 5/5] Add a null check. --- .../sources/ServiceRegistryConfigurationProvider.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java index 5147fb4..aef3630 100644 --- a/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java +++ b/service-registry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java @@ -48,9 +48,15 @@ public PollResult poll(boolean initial, Object checkPoint) for (String tag: serviceTags) { Set pairs = new HashSet(); String key = PREFIX + DELIMITER + tag + DELIMITER + SUFFIX; + for (Service service : client.getServices(tag)) { - pairs.add(getHostPortPair(service)); + InetSocketAddress pair = getHostPortPair(service); + + if (pair != null) { + pairs.add(pair); + } } + if (!pairs.isEmpty()) { map.put(key, StringUtils.join(pairs, SEPARATOR)); }