Permalink
Browse files

Move Archaius bindings to this repository.

  • Loading branch information...
Kami committed Mar 26, 2013
1 parent 5626904 commit 940358ff1a6a60f82c25679fffcf734bf67be423
View
@@ -19,6 +19,7 @@
<module>service-registry-client</module>
<module>service-registry-examples</module>
<module>service-registry-curator</module>
<module>service-registry-archaius</module>
</modules>
<developers>
@@ -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
@@ -0,0 +1,79 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.rackspacecloud</groupId>
<artifactId>service-registry-parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<name>Service Registry Client Archaius Bindings</name>
<artifactId>service-registry-archaius</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Nexus Snapshots Repository</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
<version>0.5.3</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.rackspacecloud</groupId>
<artifactId>service-registry-client</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.9</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -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<Service> getServices(String tag) throws Exception;
List<ConfigurationValue> getConfiguration() throws Exception;
}
@@ -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<Service> getServices(String tag) throws Exception {
return client.services.list(null, tag);
}
@Override
public List<ConfigurationValue> getConfiguration() throws Exception {
return client.configuration.list(null);
}
}
@@ -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<String, Object> map = new HashMap<String, Object>();
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<String> serviceTags = new HashSet<String>(Arrays.asList(tags.split(SEPARATOR)));
for (String tag: serviceTags) {
Set<InetSocketAddress> pairs = new HashSet<InetSocketAddress>();
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;
}
}
@@ -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<String, Object> cfg = new HashMap<String, Object>();
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, String>())));
}
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<String, Integer> scoreboard = new HashMap<String, Integer>();
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<String, String>())));
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());
}
}
Oops, something went wrong.

0 comments on commit 940358f

Please sign in to comment.