You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2015/08/05 16:39:56 UTC
jclouds-labs git commit: JCLOUDS-971: add etcd provider. For this
initial commit we are only addressing the miscellaneous and statistics API's.
Repository: jclouds-labs
Updated Branches:
refs/heads/master 9c19ee0c8 -> 9cd3cfa50
JCLOUDS-971: add etcd provider. For this initial commit we are only addressing the miscellaneous and statistics API's.
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/9cd3cfa5
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/9cd3cfa5
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/9cd3cfa5
Branch: refs/heads/master
Commit: 9cd3cfa50bdc7621c1398413c8aae29b797958cd
Parents: 9c19ee0
Author: Christopher Dancy <da...@pega.com>
Authored: Mon Jul 27 13:30:57 2015 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Aug 5 15:48:19 2015 +0200
----------------------------------------------------------------------
etcd/pom.xml | 123 ++++++++++++++
.../src/main/java/org/jclouds/etcd/EtcdApi.java | 33 ++++
.../java/org/jclouds/etcd/EtcdApiMetadata.java | 88 ++++++++++
.../jclouds/etcd/config/EtcdHttpApiModule.java | 35 ++++
.../etcd/domain/miscellaneous/Version.java | 38 +++++
.../jclouds/etcd/domain/statistics/Counts.java | 38 +++++
.../etcd/domain/statistics/Follower.java | 38 +++++
.../jclouds/etcd/domain/statistics/Latency.java | 45 ++++++
.../jclouds/etcd/domain/statistics/Leader.java | 41 +++++
.../etcd/domain/statistics/LeaderInfo.java | 40 +++++
.../jclouds/etcd/domain/statistics/Self.java | 55 +++++++
.../jclouds/etcd/domain/statistics/Store.java | 68 ++++++++
.../jclouds/etcd/features/MiscellaneousApi.java | 49 ++++++
.../jclouds/etcd/features/StatisticsApi.java | 48 ++++++
.../org/jclouds/etcd/BaseEtcdApiLiveTest.java | 46 ++++++
.../org/jclouds/etcd/EtcdApiMetadataTest.java | 50 ++++++
.../etcd/features/MiscellaneousApiLiveTest.java | 53 ++++++
.../etcd/features/MiscellaneousApiMockTest.java | 88 ++++++++++
.../etcd/features/StatisticsApiLiveTest.java | 44 +++++
.../etcd/features/StatisticsApiMockTest.java | 91 +++++++++++
.../jclouds/etcd/internal/BaseEtcdMockTest.java | 102 ++++++++++++
etcd/src/test/resources/health.json | 1 +
etcd/src/test/resources/leader.json | 31 ++++
etcd/src/test/resources/metrics.txt | 160 +++++++++++++++++++
etcd/src/test/resources/self.json | 15 ++
etcd/src/test/resources/store.json | 16 ++
etcd/src/test/resources/version.json | 4 +
pom.xml | 1 +
28 files changed, 1441 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/pom.xml
----------------------------------------------------------------------
diff --git a/etcd/pom.xml b/etcd/pom.xml
new file mode 100644
index 0000000..f83e72c
--- /dev/null
+++ b/etcd/pom.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>jclouds-labs</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- TODO: when out of labs, switch to org.jclouds.api -->
+ <artifactId>etcd</artifactId>
+ <name>jclouds etcd api</name>
+ <description>jclouds components to access an implementation of etcd</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <test.etcd.endpoint>http://127.0.0.1:2379</test.etcd.endpoint>
+ <test.etcd.identity>FIXME</test.etcd.identity>
+ <test.etcd.credential>FIXME</test.etcd.credential>
+ <test.etcd.api-version>v2</test.etcd.api-version>
+ <jclouds.osgi.export>org.jclouds.etcd*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>
+ org.jclouds*;version="${jclouds.version}",
+ *
+ </jclouds.osgi.import>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${jclouds.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.auto.service</groupId>
+ <artifactId>auto-service</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.auto.value</groupId>
+ <artifactId>auto-value</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${jclouds.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.driver</groupId>
+ <artifactId>jclouds-slf4j</artifactId>
+ <version>${jclouds.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>live</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>integration</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <systemPropertyVariables>
+ <test.etcd.endpoint>${test.etcd.endpoint}</test.etcd.endpoint>
+ <test.etcd.identity>${test.etcd.identity}</test.etcd.identity>
+ <test.etcd.credential>${test.etcd.credential}</test.etcd.credential>
+ <test.etcd.api-version>${test.etcd.api-version}</test.etcd.api-version>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/EtcdApi.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/EtcdApi.java b/etcd/src/main/java/org/jclouds/etcd/EtcdApi.java
new file mode 100644
index 0000000..dc3e0cb
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/EtcdApi.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd;
+
+import java.io.Closeable;
+
+import org.jclouds.etcd.features.StatisticsApi;
+import org.jclouds.etcd.features.MiscellaneousApi;
+import org.jclouds.rest.annotations.Delegate;
+
+public interface EtcdApi extends Closeable {
+
+ @Delegate
+ StatisticsApi statisticsApi();
+
+ @Delegate
+ MiscellaneousApi miscellaneousApi();
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/EtcdApiMetadata.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/EtcdApiMetadata.java b/etcd/src/main/java/org/jclouds/etcd/EtcdApiMetadata.java
new file mode 100644
index 0000000..acec91a
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/EtcdApiMetadata.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.etcd.config.EtcdHttpApiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.auto.service.AutoService;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+@AutoService(ApiMetadata.class)
+public class EtcdApiMetadata extends BaseHttpApiMetadata<EtcdApi> {
+
+ public static final String API_VERSION = "v2";
+ public static final String BUILD_VERSION = "2.1.1";
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ public EtcdApiMetadata() {
+ this(new Builder());
+ }
+
+ protected EtcdApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseHttpApiMetadata.defaultProperties();
+ return properties;
+ }
+
+ public static class Builder extends BaseHttpApiMetadata.Builder<EtcdApi, Builder> {
+
+ protected Builder() {
+ super(EtcdApi.class);
+ id("etcd").
+ name("Etcd API").
+ identityName("Optional Username").
+ credentialName("Optional Password").
+ defaultIdentity("N/A").
+ defaultCredential("N/A").
+ documentation(URI.create("https://github.com/coreos/etcd/blob/master/Documentation/api.md")).
+ version(API_VERSION).
+ buildVersion(BUILD_VERSION).
+ defaultEndpoint("http://127.0.0.1:2379").
+ defaultProperties(EtcdApiMetadata.defaultProperties()).
+ defaultModules(ImmutableSet.<Class<? extends Module>> of(EtcdHttpApiModule.class));
+ }
+
+ @Override
+ public EtcdApiMetadata build() {
+ return new EtcdApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ @Override
+ public Builder fromApiMetadata(ApiMetadata in) {
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/config/EtcdHttpApiModule.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/config/EtcdHttpApiModule.java b/etcd/src/main/java/org/jclouds/etcd/config/EtcdHttpApiModule.java
new file mode 100644
index 0000000..db492b4
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/config/EtcdHttpApiModule.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.config;
+
+import org.jclouds.etcd.EtcdApi;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+@ConfiguresHttpApi
+public class EtcdHttpApiModule extends HttpApiModule<EtcdApi> {
+
+ @Override
+ protected void bindErrorHandlers() {
+
+ }
+
+ protected void configure() {
+ super.configure();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/miscellaneous/Version.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/miscellaneous/Version.java b/etcd/src/main/java/org/jclouds/etcd/domain/miscellaneous/Version.java
new file mode 100644
index 0000000..60d05ed
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/miscellaneous/Version.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.miscellaneous;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Version {
+
+ public abstract String etcdServer();
+
+ public abstract String etcdCluster();
+
+ Version() {
+ }
+
+ @SerializedNames({ "etcdserver", "etcdcluster" })
+ public static Version create(String etcdserver, String etcdcluster) {
+ return new AutoValue_Version(etcdserver, etcdcluster);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Counts.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Counts.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Counts.java
new file mode 100644
index 0000000..e1d4fda
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Counts.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Counts {
+
+ public abstract int fail();
+
+ public abstract int success();
+
+ Counts() {
+ }
+
+ @SerializedNames({ "fail", "success" })
+ public static Counts create(int fail, int success) {
+ return new AutoValue_Counts(fail, success);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Follower.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Follower.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Follower.java
new file mode 100644
index 0000000..a7204f2
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Follower.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Follower {
+
+ public abstract Counts counts();
+
+ public abstract Latency latency();
+
+ Follower() {
+ }
+
+ @SerializedNames({ "counts", "latency" })
+ public static Follower create(Counts counts, Latency latency) {
+ return new AutoValue_Follower(counts, latency);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Latency.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Latency.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Latency.java
new file mode 100644
index 0000000..20797b0
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Latency.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Latency {
+
+ public abstract double average();
+
+ public abstract double current();
+
+ public abstract double maximum();
+
+ public abstract double minimum();
+
+ public abstract double standardDeviation();
+
+ Latency() {
+ }
+
+ @SerializedNames({ "average", "current", "maximum", "minimum", "standardDeviation" })
+ public static Latency create(double average, double current, double maximum, double minimum,
+ double standardDeviation) {
+ return new AutoValue_Latency(average, current, maximum, minimum, standardDeviation);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Leader.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Leader.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Leader.java
new file mode 100644
index 0000000..b537c53
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Leader.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import java.util.Map;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+
+@AutoValue
+public abstract class Leader {
+
+ public abstract String leader();
+
+ public abstract Map<String, Follower> followers();
+
+ Leader() {
+ }
+
+ @SerializedNames({ "leader", "followers" })
+ public static Leader create(String leader, Map<String, Follower> followers) {
+ return new AutoValue_Leader(leader, ImmutableMap.copyOf(followers));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/LeaderInfo.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/LeaderInfo.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/LeaderInfo.java
new file mode 100644
index 0000000..c220463
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/LeaderInfo.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class LeaderInfo {
+
+ public abstract String leader();
+
+ public abstract String startTime();
+
+ public abstract String uptime();
+
+ LeaderInfo() {
+ }
+
+ @SerializedNames({ "leader", "startTime", "uptime" })
+ public static LeaderInfo create(String leader, String startTime, String uptime) {
+ return new AutoValue_LeaderInfo(leader, startTime, uptime);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Self.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Self.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Self.java
new file mode 100644
index 0000000..bfe9bc2
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Self.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Self {
+
+ public abstract String id();
+
+ public abstract LeaderInfo leaderInfo();
+
+ public abstract String name();
+
+ public abstract double recvAppendRequestCnt();
+
+ public abstract double sendAppendRequestCnt();
+
+ public abstract double sendBandwidthRate();
+
+ public abstract double sendPkgRate();
+
+ public abstract String startTime();
+
+ public abstract String state();
+
+ Self() {
+ }
+
+ @SerializedNames({ "id", "leaderInfo", "name", "recvAppendRequestCnt", "sendAppendRequestCnt", "sendBandwidthRate",
+ "sendPkgRate", "startTime", "state" })
+ public static Self create(String id, LeaderInfo leaderInfo, String name, double recvAppendRequestCnt,
+ double sendAppendRequestCnt, double sendBandwidthRate, double sendPkgRate, String startTime, String state) {
+ return new AutoValue_Self(id, leaderInfo, name, recvAppendRequestCnt, sendAppendRequestCnt, sendBandwidthRate,
+ sendPkgRate, startTime, state);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Store.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Store.java b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Store.java
new file mode 100644
index 0000000..7bb78a3
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/domain/statistics/Store.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.domain.statistics;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Store {
+
+ public abstract int compareAndSwapFail();
+
+ public abstract int compareAndSwapSuccess();
+
+ public abstract int createFail();
+
+ public abstract int createSuccess();
+
+ public abstract int deleteFail();
+
+ public abstract int deleteSuccess();
+
+ public abstract int expireCount();
+
+ public abstract int getsFail();
+
+ public abstract int getsSuccess();
+
+ public abstract int setsFail();
+
+ public abstract int setsSuccess();
+
+ public abstract int updateFail();
+
+ public abstract int updateSuccess();
+
+ public abstract int watchers();
+
+ Store() {
+ }
+
+ @SerializedNames({ "compareAndSwapFail", "compareAndSwapSuccess", "createFail", "createSuccess", "deleteFail",
+ "deleteSuccess", "expireCount", "getsFail", "getsSuccess", "setsFail", "setsSuccess", "updateFail",
+ "updateSuccess", "watchers" })
+ public static Store create(int compareAndSwapFail, int compareAndSwapSuccess, int createFail, int createSuccess,
+ int deleteFail, int deleteSuccess, int expireCount, int getsFail, int getsSuccess, int setsFail,
+ int setsSuccess, int updateFail, int updateSuccess, int watchers) {
+ return new AutoValue_Store(compareAndSwapFail, compareAndSwapSuccess, createFail, createSuccess, deleteFail,
+ deleteSuccess, expireCount, getsFail, getsSuccess, setsFail, setsSuccess, updateFail, updateSuccess,
+ watchers);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/features/MiscellaneousApi.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/features/MiscellaneousApi.java b/etcd/src/main/java/org/jclouds/etcd/features/MiscellaneousApi.java
new file mode 100644
index 0000000..ba8d898
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/features/MiscellaneousApi.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.etcd.domain.miscellaneous.Version;
+import org.jclouds.rest.annotations.SelectJson;
+
+public interface MiscellaneousApi {
+
+ @Named("miscellaneous:version")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/version")
+ @GET
+ Version version();
+
+ @Named("miscellaneous:health")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/health")
+ @SelectJson("health")
+ @GET
+ boolean health();
+
+ @Named("miscellaneous:metrics")
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Path("/metrics")
+ @GET
+ String metrics();
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/main/java/org/jclouds/etcd/features/StatisticsApi.java
----------------------------------------------------------------------
diff --git a/etcd/src/main/java/org/jclouds/etcd/features/StatisticsApi.java b/etcd/src/main/java/org/jclouds/etcd/features/StatisticsApi.java
new file mode 100644
index 0000000..859fac1
--- /dev/null
+++ b/etcd/src/main/java/org/jclouds/etcd/features/StatisticsApi.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.etcd.domain.statistics.Leader;
+import org.jclouds.etcd.domain.statistics.Self;
+import org.jclouds.etcd.domain.statistics.Store;
+
+@Consumes(MediaType.APPLICATION_JSON)
+@Path("/{jclouds.api-version}/stats")
+public interface StatisticsApi {
+
+ @Named("statistics:leader")
+ @GET
+ @Path("/leader")
+ Leader leader();
+
+ @Named("statistics:self")
+ @GET
+ @Path("/self")
+ Self self();
+
+ @Named("statistics:store")
+ @GET
+ @Path("/store")
+ Store store();
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/BaseEtcdApiLiveTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/BaseEtcdApiLiveTest.java b/etcd/src/test/java/org/jclouds/etcd/BaseEtcdApiLiveTest.java
new file mode 100644
index 0000000..ac7431d
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/BaseEtcdApiLiveTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.etcd;
+
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.apis.BaseApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+@Test(groups = "live")
+public class BaseEtcdApiLiveTest extends BaseApiLiveTest<EtcdApi> {
+
+ public BaseEtcdApiLiveTest() {
+ provider = "etcd";
+ }
+
+ @Override
+ protected Iterable<Module> setupModules() {
+ return ImmutableSet.<Module> of(getLoggingModule());
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties overrides = super.setupProperties();
+ overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "0");
+ return overrides;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/EtcdApiMetadataTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/EtcdApiMetadataTest.java b/etcd/src/test/java/org/jclouds/etcd/EtcdApiMetadataTest.java
new file mode 100644
index 0000000..475a5b5
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/EtcdApiMetadataTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.HashSet;
+import org.jclouds.View;
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.apis.Apis;
+import org.jclouds.apis.internal.BaseApiMetadataTest;
+import org.testng.annotations.Test;
+
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Unit tests for the {@link EtcdApiMetadata} class.
+ */
+@Test(groups = "unit", testName = "EtcdApiMetadataTest")
+public class EtcdApiMetadataTest extends BaseApiMetadataTest {
+
+ public EtcdApiMetadataTest() {
+ super(new EtcdApiMetadata(), new HashSet<TypeToken<? extends View>>());
+ }
+
+ public void testEtcdApiRegistered() {
+ ApiMetadata api = Apis.withId("etcd");
+
+ assertNotNull(api);
+ assertTrue(api instanceof EtcdApiMetadata);
+ assertEquals(api.getId(), "etcd");
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiLiveTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiLiveTest.java b/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiLiveTest.java
new file mode 100644
index 0000000..ec955c3
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiLiveTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.etcd.features;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import org.jclouds.etcd.BaseEtcdApiLiveTest;
+import org.jclouds.etcd.domain.miscellaneous.Version;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "MiscellaneousApiLiveTest")
+public class MiscellaneousApiLiveTest extends BaseEtcdApiLiveTest {
+
+ private final String versionRegex = "^\\d+\\.\\d+\\.\\d+$";
+
+ @Test
+ public void testGetVersion() {
+ Version version = api().version();
+ assertNotNull(version);
+ assertTrue(version.etcdServer().matches(versionRegex));
+ assertTrue(version.etcdCluster().matches(versionRegex));
+ }
+
+ @Test
+ public void testGetHealth() {
+ boolean health = api().health();
+ assertTrue(health);
+ }
+
+ @Test
+ public void testGetMetrics() {
+ String metrics = api().metrics();
+ assertNotNull(metrics);
+ }
+
+ private MiscellaneousApi api() {
+ return api.miscellaneousApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiMockTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiMockTest.java b/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiMockTest.java
new file mode 100644
index 0000000..abd239d
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/features/MiscellaneousApiMockTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.etcd.features;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.etcd.EtcdApi;
+import org.jclouds.etcd.domain.miscellaneous.Version;
+import org.jclouds.etcd.internal.BaseEtcdMockTest;
+import org.testng.annotations.Test;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Mock tests for the {@link org.jclouds.etcd.features.MiscellaneousApi} class.
+ */
+@Test(groups = "unit", testName = "MiscellaneousApiMockTest")
+public class MiscellaneousApiMockTest extends BaseEtcdMockTest {
+
+ private final String versionRegex = "^\\d+\\.\\d+\\.\\d+$";
+
+ public void testGetVersion() throws Exception {
+ MockWebServer server = mockEtcdJavaWebServer();
+
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/version.json")).setResponseCode(200));
+ EtcdApi etcdJavaApi = api(server.getUrl("/"));
+ MiscellaneousApi api = etcdJavaApi.miscellaneousApi();
+ try {
+ Version version = api.version();
+ assertNotNull(version);
+ assertTrue(version.etcdServer().matches(versionRegex));
+ assertTrue(version.etcdCluster().matches(versionRegex));
+ assertSent(server, "GET", "/version");
+ } finally {
+ etcdJavaApi.close();
+ server.shutdown();
+ }
+ }
+
+ public void testGetHealth() throws Exception {
+ MockWebServer server = mockEtcdJavaWebServer();
+
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/health.json")).setResponseCode(200));
+ EtcdApi etcdJavaApi = api(server.getUrl("/"));
+ MiscellaneousApi api = etcdJavaApi.miscellaneousApi();
+ try {
+ boolean health = api.health();
+ assertTrue(health);
+ assertSent(server, "GET", "/health");
+ } finally {
+ etcdJavaApi.close();
+ server.shutdown();
+ }
+ }
+
+ public void testGetMetrics() throws Exception {
+ MockWebServer server = mockEtcdJavaWebServer();
+
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/metrics.txt")).setResponseCode(200));
+ EtcdApi etcdJavaApi = api(server.getUrl("/"));
+ MiscellaneousApi api = etcdJavaApi.miscellaneousApi();
+ try {
+ String metrics = api.metrics();
+ assertNotNull(metrics);
+ assertSentAcceptText(server, "GET", "/metrics");
+ } finally {
+ etcdJavaApi.close();
+ server.shutdown();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiLiveTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiLiveTest.java b/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiLiveTest.java
new file mode 100644
index 0000000..b02370d
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiLiveTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.etcd.features;
+
+import static org.testng.Assert.assertNotNull;
+import org.jclouds.etcd.BaseEtcdApiLiveTest;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "StatisticsApiLiveTest")
+public class StatisticsApiLiveTest extends BaseEtcdApiLiveTest {
+
+ @Test
+ public void testGetLeader() throws Exception {
+ assertNotNull(api().leader());
+ }
+
+ @Test
+ public void testGetSelf() throws Exception {
+ assertNotNull(api().self());
+ }
+
+ @Test
+ public void testGetStore() throws Exception {
+ assertNotNull(api().store());
+ }
+
+ private StatisticsApi api() {
+ return api.statisticsApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiMockTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiMockTest.java b/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiMockTest.java
new file mode 100644
index 0000000..fc5bdc7
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/features/StatisticsApiMockTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.etcd.features;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotNull;
+
+import org.jclouds.etcd.EtcdApi;
+import org.jclouds.etcd.EtcdApiMetadata;
+import org.jclouds.etcd.domain.statistics.Leader;
+import org.jclouds.etcd.domain.statistics.Self;
+import org.jclouds.etcd.domain.statistics.Store;
+import org.jclouds.etcd.internal.BaseEtcdMockTest;
+
+import org.testng.annotations.Test;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Mock tests for the {@link org.jclouds.etcd.features.StatisticsApi} class.
+ */
+@Test(groups = "unit", testName = "StatisticsApiMockTest")
+public class StatisticsApiMockTest extends BaseEtcdMockTest {
+
+ public void testGetLeader() throws Exception {
+ MockWebServer server = mockEtcdJavaWebServer();
+
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/leader.json")).setResponseCode(200));
+ EtcdApi etcdJavaApi = api(server.getUrl("/"));
+ StatisticsApi api = etcdJavaApi.statisticsApi();
+ try {
+ Leader leader = api.leader();
+ assertNotNull(leader);
+ assertTrue(leader.followers().size() == 2);
+ assertTrue(leader.leader().equals("924e2e83e93f2560"));
+ assertSent(server, "GET", "/" + EtcdApiMetadata.API_VERSION + "/stats/leader");
+ } finally {
+ etcdJavaApi.close();
+ server.shutdown();
+ }
+ }
+
+ public void testGetSelf() throws Exception {
+ MockWebServer server = mockEtcdJavaWebServer();
+
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/self.json")).setResponseCode(200));
+ EtcdApi etcdJavaApi = api(server.getUrl("/"));
+ StatisticsApi api = etcdJavaApi.statisticsApi();
+ try {
+ Self self = api.self();
+ assertNotNull(self);
+ assertTrue(self.leaderInfo().leader().equals("924e2e83e93f2560"));
+ assertSent(server, "GET", "/" + EtcdApiMetadata.API_VERSION + "/stats/self");
+ } finally {
+ etcdJavaApi.close();
+ server.shutdown();
+ }
+ }
+
+ public void testGetStore() throws Exception {
+ MockWebServer server = mockEtcdJavaWebServer();
+
+ server.enqueue(new MockResponse().setBody(payloadFromResource("/store.json")).setResponseCode(200));
+ EtcdApi etcdJavaApi = api(server.getUrl("/"));
+ StatisticsApi api = etcdJavaApi.statisticsApi();
+ try {
+ Store store = api.store();
+ assertNotNull(store);
+ assertTrue(store.getsSuccess() == 75);
+ assertSent(server, "GET", "/" + EtcdApiMetadata.API_VERSION + "/stats/store");
+ } finally {
+ etcdJavaApi.close();
+ server.shutdown();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/java/org/jclouds/etcd/internal/BaseEtcdMockTest.java
----------------------------------------------------------------------
diff --git a/etcd/src/test/java/org/jclouds/etcd/internal/BaseEtcdMockTest.java b/etcd/src/test/java/org/jclouds/etcd/internal/BaseEtcdMockTest.java
new file mode 100644
index 0000000..8cd85eb
--- /dev/null
+++ b/etcd/src/test/java/org/jclouds/etcd/internal/BaseEtcdMockTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.etcd.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.util.Strings2.toStringAndClose;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Constants;
+import org.jclouds.ContextBuilder;
+import org.jclouds.etcd.EtcdApi;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Throwables;
+import com.google.gson.JsonParser;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import com.squareup.okhttp.mockwebserver.RecordedRequest;
+
+/**
+ * Base class for all Etcd mock tests.
+ */
+public class BaseEtcdMockTest {
+
+ protected String provider;
+ private final JsonParser parser = new JsonParser();
+
+ public BaseEtcdMockTest() {
+ provider = "etcd";
+ }
+
+ public EtcdApi api(URL url) {
+ return ContextBuilder.newBuilder(provider).endpoint(url.toString()).overrides(setupProperties())
+ .buildApi(EtcdApi.class);
+ }
+
+ protected Properties setupProperties() {
+ Properties properties = new Properties();
+ properties.setProperty(Constants.PROPERTY_MAX_RETRIES, "0");
+ return properties;
+ }
+
+ public static MockWebServer mockEtcdJavaWebServer() throws IOException {
+ MockWebServer server = new MockWebServer();
+ server.play();
+ return server;
+ }
+
+ public String payloadFromResource(String resource) {
+ try {
+ return new String(toStringAndClose(getClass().getResourceAsStream(resource)).getBytes(Charsets.UTF_8));
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ protected RecordedRequest assertSent(MockWebServer server, String method, String path) throws InterruptedException {
+ RecordedRequest request = server.takeRequest();
+ assertThat(request.getMethod()).isEqualTo(method);
+ assertThat(request.getPath()).isEqualTo(path);
+ assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON);
+ return request;
+ }
+
+ protected RecordedRequest assertSentAcceptText(MockWebServer server, String method, String path)
+ throws InterruptedException {
+ RecordedRequest request = server.takeRequest();
+ assertThat(request.getMethod()).isEqualTo(method);
+ assertThat(request.getPath()).isEqualTo(path);
+ assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.TEXT_PLAIN);
+ return request;
+ }
+
+ protected RecordedRequest assertSent(MockWebServer server, String method, String path, String json)
+ throws InterruptedException {
+ RecordedRequest request = assertSent(server, method, path);
+ assertEquals(request.getHeader("Content-Type"), APPLICATION_JSON);
+ assertEquals(parser.parse(request.getUtf8Body()), parser.parse(json));
+ return request;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/resources/health.json
----------------------------------------------------------------------
diff --git a/etcd/src/test/resources/health.json b/etcd/src/test/resources/health.json
new file mode 100644
index 0000000..fdc9176
--- /dev/null
+++ b/etcd/src/test/resources/health.json
@@ -0,0 +1 @@
+{"health": "true"}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/resources/leader.json
----------------------------------------------------------------------
diff --git a/etcd/src/test/resources/leader.json b/etcd/src/test/resources/leader.json
new file mode 100644
index 0000000..496f904
--- /dev/null
+++ b/etcd/src/test/resources/leader.json
@@ -0,0 +1,31 @@
+{
+ "followers": {
+ "6e3bd23ae5f1eae0": {
+ "counts": {
+ "fail": 0,
+ "success": 745
+ },
+ "latency": {
+ "average": 0.017039507382550306,
+ "current": 0.000138,
+ "maximum": 1.007649,
+ "minimum": 0,
+ "standardDeviation": 0.05289178277920594
+ }
+ },
+ "a8266ecf031671f3": {
+ "counts": {
+ "fail": 0,
+ "success": 735
+ },
+ "latency": {
+ "average": 0.012124141496598642,
+ "current": 0.000559,
+ "maximum": 0.791547,
+ "minimum": 0,
+ "standardDeviation": 0.04187900156583733
+ }
+ }
+ },
+ "leader": "924e2e83e93f2560"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/resources/metrics.txt
----------------------------------------------------------------------
diff --git a/etcd/src/test/resources/metrics.txt b/etcd/src/test/resources/metrics.txt
new file mode 100644
index 0000000..e59f2d6
--- /dev/null
+++ b/etcd/src/test/resources/metrics.txt
@@ -0,0 +1,160 @@
+# HELP etcd_rafthttp_message_sent_latency_microseconds message sent latency distributions.
+# TYPE etcd_rafthttp_message_sent_latency_microseconds summary
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.5"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.9"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.99"} NaN
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="message"} 84
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="message"} 1
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="msgappv2",quantile="0.5"} 50
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="msgappv2",quantile="0.9"} 78
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="msgappv2",quantile="0.99"} 98
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="msgappv2"} 2.045591e+06
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgApp",remoteID="96d5f4741cf7499e",sendingType="msgappv2"} 34607
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.5"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.9"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.99"} NaN
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="message"} 45
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="message"} 1
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="msgappv2",quantile="0.5"} 35
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="msgappv2",quantile="0.9"} 51
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="msgappv2",quantile="0.99"} 83
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="msgappv2"} 1.426621e+06
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgApp",remoteID="f992d9b00b6adf2f",sendingType="msgappv2"} 34664
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgHeartbeat",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.5"} 60
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgHeartbeat",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.9"} 91
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgHeartbeat",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.99"} 101
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgHeartbeat",remoteID="96d5f4741cf7499e",sendingType="message"} 548492
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgHeartbeat",remoteID="96d5f4741cf7499e",sendingType="message"} 7076
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgHeartbeat",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.5"} 39
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgHeartbeat",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.9"} 58
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgHeartbeat",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.99"} 93
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgHeartbeat",remoteID="f992d9b00b6adf2f",sendingType="message"} 335711
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgHeartbeat",remoteID="f992d9b00b6adf2f",sendingType="message"} 7076
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="message",quantile="0.5"} 53
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="message",quantile="0.9"} 65
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="message",quantile="0.99"} 71
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="message"} 455136
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="message"} 8578
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="msgappv2",quantile="0.5"} 54
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="msgappv2",quantile="0.9"} 69
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="msgappv2",quantile="0.99"} 93
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="msgappv2"} 482458
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgLinkHeartbeat",remoteID="0",sendingType="msgappv2"} 8578
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVote",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.5"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVote",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.9"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVote",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.99"} NaN
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgVote",remoteID="96d5f4741cf7499e",sendingType="message"} 162
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgVote",remoteID="96d5f4741cf7499e",sendingType="message"} 1
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVote",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.5"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVote",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.9"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVote",remoteID="f992d9b00b6adf2f",sendingType="message",quantile="0.99"} NaN
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgVote",remoteID="f992d9b00b6adf2f",sendingType="message"} 57
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgVote",remoteID="f992d9b00b6adf2f",sendingType="message"} 1
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVoteResp",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.5"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVoteResp",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.9"} NaN
+etcd_rafthttp_message_sent_latency_microseconds{msgType="MsgVoteResp",remoteID="96d5f4741cf7499e",sendingType="message",quantile="0.99"} NaN
+etcd_rafthttp_message_sent_latency_microseconds_sum{msgType="MsgVoteResp",remoteID="96d5f4741cf7499e",sendingType="message"} 54
+etcd_rafthttp_message_sent_latency_microseconds_count{msgType="MsgVoteResp",remoteID="96d5f4741cf7499e",sendingType="message"} 1
+# HELP etcd_server_file_descriptors_used_total The total number of file descriptors used.
+# TYPE etcd_server_file_descriptors_used_total gauge
+etcd_server_file_descriptors_used_total 18
+# HELP etcd_server_pending_proposal_total The total number of pending proposals.
+# TYPE etcd_server_pending_proposal_total gauge
+etcd_server_pending_proposal_total 0
+# HELP etcd_server_proposal_durations_milliseconds The latency distributions of committing proposal.
+# TYPE etcd_server_proposal_durations_milliseconds summary
+etcd_server_proposal_durations_milliseconds{quantile="0.5"} NaN
+etcd_server_proposal_durations_milliseconds{quantile="0.9"} NaN
+etcd_server_proposal_durations_milliseconds{quantile="0.99"} NaN
+etcd_server_proposal_durations_milliseconds_sum 3678
+etcd_server_proposal_durations_milliseconds_count 2
+# HELP etcd_server_proposal_failed_total The total number of failed proposals.
+# TYPE etcd_server_proposal_failed_total counter
+etcd_server_proposal_failed_total 1
+# HELP etcd_snapshot_save_total_durations_microseconds The total latency distributions of save called by snapshot.
+# TYPE etcd_snapshot_save_total_durations_microseconds summary
+etcd_snapshot_save_total_durations_microseconds{quantile="0.5"} NaN
+etcd_snapshot_save_total_durations_microseconds{quantile="0.9"} NaN
+etcd_snapshot_save_total_durations_microseconds{quantile="0.99"} NaN
+etcd_snapshot_save_total_durations_microseconds_sum 258
+etcd_snapshot_save_total_durations_microseconds_count 1
+# HELP etcd_store_expires_total Total number of expired keys.
+# TYPE etcd_store_expires_total counter
+etcd_store_expires_total 0
+# HELP etcd_store_reads_total Total number of reads action by (get/getRecursive), local to this member.
+# TYPE etcd_store_reads_total counter
+etcd_store_reads_total{action="getRecursive"} 5
+# HELP etcd_store_watch_requests_total Total number of incoming watch requests (new or reestablished).
+# TYPE etcd_store_watch_requests_total counter
+etcd_store_watch_requests_total 0
+# HELP etcd_store_watchers Count of currently active watchers.
+# TYPE etcd_store_watchers gauge
+etcd_store_watchers 0
+# HELP etcd_store_writes_total Total number of writes (e.g. set/compareAndDelete) seen by this member.
+# TYPE etcd_store_writes_total counter
+etcd_store_writes_total{action="create"} 3
+etcd_store_writes_total{action="set"} 4
+# HELP etcd_wal_fsync_durations_microseconds The latency distributions of fsync called by wal.
+# TYPE etcd_wal_fsync_durations_microseconds summary
+etcd_wal_fsync_durations_microseconds{quantile="0.5"} 41299
+etcd_wal_fsync_durations_microseconds{quantile="0.9"} 120044
+etcd_wal_fsync_durations_microseconds{quantile="0.99"} 563066
+etcd_wal_fsync_durations_microseconds_sum 1.862452899e+09
+etcd_wal_fsync_durations_microseconds_count 27906
+# HELP etcd_wal_last_index_saved The index of the last entry saved by wal.
+# TYPE etcd_wal_last_index_saved gauge
+etcd_wal_last_index_saved 13970
+# HELP go_gc_duration_seconds A summary of the GC invocation durations.
+# TYPE go_gc_duration_seconds summary
+go_gc_duration_seconds{quantile="0"} 0.000199168
+go_gc_duration_seconds{quantile="0.25"} 0.011117938
+go_gc_duration_seconds{quantile="0.5"} 0.013050367
+go_gc_duration_seconds{quantile="0.75"} 0.015054046000000001
+go_gc_duration_seconds{quantile="1"} 0.020298544
+go_gc_duration_seconds_sum 0.8452645520000001
+go_gc_duration_seconds_count 71
+# HELP go_goroutines Number of goroutines that currently exist.
+# TYPE go_goroutines gauge
+go_goroutines 69
+# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.
+# TYPE http_request_duration_microseconds summary
+http_request_duration_microseconds{handler="prometheus",quantile="0.5"} NaN
+http_request_duration_microseconds{handler="prometheus",quantile="0.9"} NaN
+http_request_duration_microseconds{handler="prometheus",quantile="0.99"} NaN
+http_request_duration_microseconds_sum{handler="prometheus"} 11850.234
+http_request_duration_microseconds_count{handler="prometheus"} 2
+# HELP http_request_size_bytes The HTTP request sizes in bytes.
+# TYPE http_request_size_bytes summary
+http_request_size_bytes{handler="prometheus",quantile="0.5"} NaN
+http_request_size_bytes{handler="prometheus",quantile="0.9"} NaN
+http_request_size_bytes{handler="prometheus",quantile="0.99"} NaN
+http_request_size_bytes_sum{handler="prometheus"} 680
+http_request_size_bytes_count{handler="prometheus"} 2
+# HELP http_requests_total Total number of HTTP requests made.
+# TYPE http_requests_total counter
+http_requests_total{code="200",handler="prometheus",method="get"} 2
+# HELP http_response_size_bytes The HTTP response sizes in bytes.
+# TYPE http_response_size_bytes summary
+http_response_size_bytes{handler="prometheus",quantile="0.5"} NaN
+http_response_size_bytes{handler="prometheus",quantile="0.9"} NaN
+http_response_size_bytes{handler="prometheus",quantile="0.99"} NaN
+http_response_size_bytes_sum{handler="prometheus"} 3494
+http_response_size_bytes_count{handler="prometheus"} 2
+# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
+# TYPE process_cpu_seconds_total counter
+process_cpu_seconds_total 48.72
+# HELP process_max_fds Maximum number of open file descriptors.
+# TYPE process_max_fds gauge
+process_max_fds 1024
+# HELP process_open_fds Number of open file descriptors.
+# TYPE process_open_fds gauge
+process_open_fds 19
+# HELP process_resident_memory_bytes Resident memory size in bytes.
+# TYPE process_resident_memory_bytes gauge
+process_resident_memory_bytes 2.8459008e+07
+# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
+# TYPE process_start_time_seconds gauge
+process_start_time_seconds 1.43810894456e+09
+# HELP process_virtual_memory_bytes Virtual memory size in bytes.
+# TYPE process_virtual_memory_bytes gauge
+process_virtual_memory_bytes 3.749888e+07
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/resources/self.json
----------------------------------------------------------------------
diff --git a/etcd/src/test/resources/self.json b/etcd/src/test/resources/self.json
new file mode 100644
index 0000000..72b15d5
--- /dev/null
+++ b/etcd/src/test/resources/self.json
@@ -0,0 +1,15 @@
+{
+ "id": "924e2e83e93f2560",
+ "leaderInfo": {
+ "leader": "924e2e83e93f2560",
+ "startTime": "2015-02-09T11:38:30.177534688-08:00",
+ "uptime": "9m33.891343412s"
+ },
+ "name": "infra3",
+ "recvAppendRequestCnt": 0,
+ "sendAppendRequestCnt": 6535,
+ "sendBandwidthRate": 824.1758351191694,
+ "sendPkgRate": 11.111234716807138,
+ "startTime": "2015-02-09T11:38:28.972034204-08:00",
+ "state": "StateLeader"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/resources/store.json
----------------------------------------------------------------------
diff --git a/etcd/src/test/resources/store.json b/etcd/src/test/resources/store.json
new file mode 100644
index 0000000..03e6e3d
--- /dev/null
+++ b/etcd/src/test/resources/store.json
@@ -0,0 +1,16 @@
+{
+ "compareAndSwapFail": 0,
+ "compareAndSwapSuccess": 0,
+ "createFail": 0,
+ "createSuccess": 2,
+ "deleteFail": 0,
+ "deleteSuccess": 0,
+ "expireCount": 0,
+ "getsFail": 4,
+ "getsSuccess": 75,
+ "setsFail": 2,
+ "setsSuccess": 4,
+ "updateFail": 0,
+ "updateSuccess": 0,
+ "watchers": 0
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/etcd/src/test/resources/version.json
----------------------------------------------------------------------
diff --git a/etcd/src/test/resources/version.json b/etcd/src/test/resources/version.json
new file mode 100644
index 0000000..f5c5e12
--- /dev/null
+++ b/etcd/src/test/resources/version.json
@@ -0,0 +1,4 @@
+{
+ "etcdserver":"2.1.1",
+ "etcdcluster":"2.1.0"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/9cd3cfa5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 023f3e4..2a6bf43 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,7 @@
<modules>
<module>azurecompute</module>
+ <module>etcd</module>
<module>docker</module>
<module>cdmi</module>
<module>cloudsigma2</module>