Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Move archaius bindings here #25

Merged
merged 6 commits into from

2 participants

@Kami

This is primarily for consistency reasons (Curator bindings already live in this repository).

I see us eventually moving Curator and Archaius outside of this into a separate repository (it should be relatively easy and painless) again.

service-registry-archaius/pom.xml
((50 lines not shown))
+ </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>

is that version correct?

@Kami
Kami added a note

Yes, there is a different PR (based on this one) which bumps it to 2.0.0 and updates the affected code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...lix/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

you probably care about this more than me: newline.

@Kami
Kami added a note

I do, but I avoid doing most of the "style" stuff in this pr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...fig/sources/ServiceRegistryConfigurationProvider.java
((37 lines not shown))
+
+ 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));

getHostPortPair() can return null. This will be bad for pairs.add(). It is probably best to use a local and do a null check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@gdusbabek gdusbabek commented on the diff
...fig/sources/ServiceRegistryConfigurationProvider.java
((57 lines not shown))
+ }
+ }
+ 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) {

Is the premise that users will not query for a tag that does not have the appropriate metdata? If so, then I think it is ok to log at ERROR. But if there is no such premise, we ought to log at DEBUG.

@Kami
Kami added a note

That's an old stuff which I want to avoid touching in this PR.

This one is just moving it into the same repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@Kami

@gdusbabek Opened a separate PR for 2.0.0 upgrades and style changes and improvements which is based on this branch - #29

@Kami Kami merged commit efb95af into master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 26, 2013
  1. @Kami
  2. @Kami

    Upgrade readme.

    Kami authored
Commits on Mar 27, 2013
  1. @Kami
  2. @Kami

    Style.

    Kami authored
  3. @Kami

    Add a null check.

    Kami authored
  4. @Kami

    Merge pull request #29 from racker/upgrade_to_2.0.0_and_improve_stuff

    Kami authored
    Upgrade to 2.0.0 and improve stuff
This page is out of date. Refresh to see the latest.
View
22 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
- <ibiblio name="sonatype"
- m2compatible="true"
+ <ibiblio name="sonatype"
+ m2compatible="true"
usepoms="true"
root="https://oss.sonatype.org/content/repositories/snapshots/"
pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
- changingPattern="SNAPSHOT*"/>
+ 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
<groupId>com.rackspacecloud</groupId>
<artifactId>service-registry-client</artifactId>
<version>1.0.0</version>
- </dependency>
+ </dependency>
```
-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
View
1  pom.xml
@@ -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>
View
25 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
View
79 service-registry-archaius/pom.xml
@@ -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>2.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>
View
12 ...ice-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<Service> getServices(String tag) throws Exception;
+
+ List<ConfigurationValue> getConfiguration() throws Exception;
+}
View
25 ...stry-archaius/src/main/java/com/netflix/config/sources/ServiceRegistryClientProvider.java
@@ -0,0 +1,25 @@
+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.getServicesClient().list(null, tag);
+ }
+
+ @Override
+ public List<ConfigurationValue> getConfiguration() throws Exception {
+ return client.getConfigurationClient().list(null);
+ }
+}
View
93 ...chaius/src/main/java/com/netflix/config/sources/ServiceRegistryConfigurationProvider.java
@@ -0,0 +1,93 @@
+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)) {
+ InetSocketAddress pair = getHostPortPair(service);
+
+ if (pair != null) {
+ pairs.add(pair);
+ }
+ }
+
+ 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) {

Is the premise that users will not query for a tag that does not have the appropriate metdata? If so, then I think it is ok to log at ERROR. But if there is no such premise, we ought to log at DEBUG.

@Kami
Kami added a note

That's an old stuff which I want to avoid touching in this PR.

This one is just moving it into the same repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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;
+ }
+}
View
134 ...c/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<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, 15, 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, 15, 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());
+ }
+}
View
40 ...c/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<String, List<Service>> services = new HashMap<String, List<Service>>();
+ List<ConfigurationValue> configurationValues = new ArrayList<ConfigurationValue>();
+
+ public void addService(String tag, Service svc) {
+ List<Service> svcs = services.get(tag);
+ if (svcs == null) {
+ svcs = new ArrayList<Service>();
+ }
+ svcs.add(svc);
+ services.put(tag, svcs);
+ }
+
+ public void addConfigurationValue(ConfigurationValue cfg) {
+ configurationValues.add(cfg);
+ }
+
+ @Override
+ public List<Service> getServices(String tag) throws Exception {
+ List<Service> result = services.get(tag);
+ if (result == null) {
+ return Collections.emptyList();
+ }
+ return result;
+ }
+
+ @Override
+ public List<ConfigurationValue> getConfiguration() throws Exception {
+ return configurationValues;
+ }
+}
View
1  service-registry-archaius/src/test/resources/config.properties
@@ -0,0 +1 @@
+test.more="foo"
View
11 service-registry-archaius/src/test/resources/logback-test.xml
@@ -0,0 +1,11 @@
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <outputPatternAsHeader>false</outputPatternAsHeader>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+ <root level="info">
+ <appender-ref ref="STDOUT"/>
+ </root>
+</configuration>
Something went wrong with that request. Please try again.