Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move archaius bindings here #25

Merged
merged 6 commits into from Mar 27, 2013
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 15 additions & 7 deletions 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

Expand All @@ -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.
Expand All @@ -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

Expand Down
1 change: 1 addition & 0 deletions pom.xml
Expand Up @@ -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>
Expand Down
25 changes: 25 additions & 0 deletions 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
79 changes: 79 additions & 0 deletions 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>1.0.0-SNAPSHOT</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that version correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

</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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you probably care about this more than me: newline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

}
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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

This one is just moving it into the same repository.

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;
}
}