Repository: jclouds-labs-openstack
Updated Branches:
  refs/heads/master 1c8233b08 -> a006915f0


JCLOUDS-806: Support OpenStack Poppy Base and Flavor API


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/commit/a006915f
Tree: 
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/tree/a006915f
Diff: 
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/diff/a006915f

Branch: refs/heads/master
Commit: a006915f0fdb1d30fcce36e3566461ae0e78302d
Parents: 1c8233b
Author: Jeremy Daggett <[email protected]>
Authored: Sun Oct 26 09:09:55 2014 -0700
Committer: Jeremy Daggett <[email protected]>
Committed: Wed Jan 21 21:03:15 2015 -0800

----------------------------------------------------------------------
 openstack-poppy/README.md                       |  28 +++
 openstack-poppy/pom.xml                         | 130 ++++++++++
 .../jclouds/openstack/poppy/v1/PoppyApi.java    |  65 +++++
 .../openstack/poppy/v1/PoppyApiMetadata.java    |  92 +++++++
 .../openstack/poppy/v1/PoppyFallbacks.java      |  39 +++
 .../jclouds/openstack/poppy/v1/config/CDN.java  |  33 +++
 .../poppy/v1/config/PoppyHttpApiModule.java     |  53 ++++
 .../openstack/poppy/v1/domain/Flavor.java       |  44 ++++
 .../openstack/poppy/v1/domain/Provider.java     |  42 ++++
 .../openstack/poppy/v1/features/FlavorApi.java  |  62 +++++
 .../poppy/v1/handlers/PoppyErrorHandler.java    |  52 ++++
 .../poppy/v1/PoppyApiMetadataTest.java          |  34 +++
 .../poppy/v1/features/FlavorApiLiveTest.java    |  71 ++++++
 .../poppy/v1/features/FlavorApiMockTest.java    | 104 ++++++++
 .../poppy/v1/features/PoppyApiMockTest.java     |  74 ++++++
 .../poppy/v1/internal/BasePoppyApiLiveTest.java |  45 ++++
 .../poppy/v1/internal/BasePoppyApiMockTest.java |  43 ++++
 openstack-poppy/src/test/resources/access.json  | 242 +++++++++++++++++++
 openstack-poppy/src/test/resources/logback.xml  |  58 +++++
 .../resources/poppy_flavor_get_response.json    |  20 ++
 .../resources/poppy_flavor_list_response.json   |  24 ++
 pom.xml                                         |   1 +
 22 files changed, 1356 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/README.md
----------------------------------------------------------------------
diff --git a/openstack-poppy/README.md b/openstack-poppy/README.md
new file mode 100644
index 0000000..26504da
--- /dev/null
+++ b/openstack-poppy/README.md
@@ -0,0 +1,28 @@
+#OpenStack Poppy
+================
+
+OpenStack Poppy is a modular, vendor-neutral API, that wraps provisioning 
instructions for all CDN vendors that support it.
+
+- REST API for CDN service provisioning
+- Multi-tenant
+- Integrated with Keystone for Authentication
+- Integrated with Designate for dynamic CNAMEing
+- Support for CDN providers (Fastly, MaxCDN, CloudFront, Akamai, Edgecast)
+
+##Running Live Tests
+===
+To run the Poppy live tests, execute the following command with your 
credentials and authentication endpoint:
+
+    $ mvn clean install -Plive -Dtest.openstack-poppy.identity=<username> 
-Dtest.openstack-poppy.credential=<password> 
-Dtest.openstack-poppy.endpoint=<keystone-auth-url>
+
+##Production ready?
+===
+No. The OpenStack Poppy API is a beta API and is subject to change during it's 
development. APIs have `@Beta` annotations where applicable.
+
+##Project Links
+===
+[Wiki](https://wiki.openstack.org/wiki/Poppy)
+
+[PoppyCDN](http://www.poppycdn.org/)
+
+[Sources](https://github.com/stackforge/poppy)

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/pom.xml
----------------------------------------------------------------------
diff --git a/openstack-poppy/pom.xml b/openstack-poppy/pom.xml
new file mode 100644
index 0000000..6eca54d
--- /dev/null
+++ b/openstack-poppy/pom.xml
@@ -0,0 +1,130 @@
+<?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</groupId>
+    <artifactId>jclouds-project</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+    <relativePath />
+  </parent>
+
+  <!-- TODO: when out of labs, switch to org.jclouds.api -->
+  <groupId>org.apache.jclouds.labs</groupId>
+  <artifactId>openstack-poppy</artifactId>
+  <version>2.0.0-SNAPSHOT</version>
+  <name>Apache jclouds :: OpenStack :: Poppy API</name>
+  <description>jclouds components to access an implementation of OpenStack 
Poppy</description>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <!-- keystone endpoint -->
+    
<test.openstack-poppy.endpoint>http://localhost:5000/v2.0/</test.openstack-poppy.endpoint>
+    <test.openstack-poppy.api-version>1</test.openstack-poppy.api-version>
+    <test.openstack-poppy.build-version />
+    
<test.openstack-poppy.identity>FIXME_IDENTITY</test.openstack-poppy.identity>
+    
<test.openstack-poppy.credential>FIXME_CREDENTIALS</test.openstack-poppy.credential>
+    
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+    
<jclouds.osgi.export>org.jclouds.openstack.poppy.v1*;version="${project.version}"</jclouds.osgi.export>
+    
<jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.api</groupId>
+      <artifactId>openstack-keystone</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.api</groupId>
+      <artifactId>openstack-keystone</artifactId>
+      <version>${project.parent.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jclouds.driver</groupId>
+      <artifactId>jclouds-slf4j</artifactId>
+      <version>${project.parent.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.squareup.okhttp</groupId>
+      <artifactId>mockwebserver</artifactId>
+      <scope>test</scope>
+    </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>
+  </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.openstack-poppy.endpoint>${test.openstack-poppy.endpoint}</test.openstack-poppy.endpoint>
+                    
<test.openstack-poppy.api-version>${test.openstack-poppy.api-version}</test.openstack-poppy.api-version>
+                    
<test.openstack-poppy.build-version>${test.openstack-poppy.build-version}</test.openstack-poppy.build-version>
+                    
<test.openstack-poppy.identity>${test.openstack-poppy.identity}</test.openstack-poppy.identity>
+                    
<test.openstack-poppy.credential>${test.openstack-poppy.credential}</test.openstack-poppy.credential>
+                    
<test.jclouds.keystone.credential-type>${test.jclouds.keystone.credential-type}</test.jclouds.keystone.credential-type>
+                  </systemPropertyVariables>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApi.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApi.java 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApi.java
new file mode 100644
index 0000000..ac56f15
--- /dev/null
+++ b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApi.java
@@ -0,0 +1,65 @@
+/*
+ * 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.openstack.poppy.v1;
+
+import java.io.Closeable;
+
+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.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.poppy.v1.PoppyFallbacks.FalseOn500or503;
+import org.jclouds.openstack.poppy.v1.config.CDN;
+import org.jclouds.openstack.poppy.v1.features.FlavorApi;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides access to the OpenStack CDN (Poppy) API.
+ *
+ */
+@Beta
+public interface PoppyApi extends Closeable {
+
+   /**
+    * Pings the server to ensure it is available.
+    *
+    * @return true if the server is responding, false otherwise
+    */
+   @Named("poppy:ping")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Endpoint(CDN.class)
+   @RequestFilters(AuthenticateRequest.class)
+   @Fallback(FalseOn500or503.class)
+   @Path("/ping")
+   boolean ping();
+
+   /**
+    * Provides access to Flavor features.
+    */
+   @Delegate
+   FlavorApi getFlavorApi();
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadata.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadata.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadata.java
new file mode 100644
index 0000000..470b41d
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadata.java
@@ -0,0 +1,92 @@
+/*
+ * 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.openstack.poppy.v1;
+
+import static 
org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static 
org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.openstack.keystone.v2_0.config.AuthenticationApiModule;
+import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
+import 
org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ProviderModule;
+import org.jclouds.openstack.poppy.v1.config.PoppyHttpApiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.auto.service.AutoService;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for the Poppy API.
+ */
+@AutoService(ApiMetadata.class)
+public class PoppyApiMetadata extends BaseHttpApiMetadata<PoppyApi> {
+
+   @Override
+   public Builder toBuilder() {
+      return new Builder().fromApiMetadata(this);
+   }
+
+   public PoppyApiMetadata() {
+      this(new Builder());
+   }
+
+   protected PoppyApiMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
+      properties.setProperty(SERVICE_TYPE, "cdn");
+      properties.setProperty(CREDENTIAL_TYPE, 
CredentialTypes.PASSWORD_CREDENTIALS);
+      return properties;
+   }
+
+   public static class Builder extends BaseHttpApiMetadata.Builder<PoppyApi, 
Builder> {
+
+      protected Builder() {
+          id("openstack-poppy")
+         .name("OpenStack Poppy API")
+         .identityName("${tenantName}:${userName} or ${userName}, if your 
keystone supports a default tenant")
+         .credentialName("${password}")
+         .documentation(URI.create("https://wiki.openstack.org/wiki/Poppy";))
+         .version("1.0")
+         .endpointName("Keystone base url ending in /v2.0/")
+         .defaultEndpoint("http://localhost:5000/v2.0/";)
+         .defaultProperties(PoppyApiMetadata.defaultProperties())
+         .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                           .add(AuthenticationApiModule.class)
+                           .add(KeystoneAuthenticationModule.class)
+                           .add(ProviderModule.class)
+                           .add(PoppyHttpApiModule.class).build());
+      }
+
+      @Override
+      public PoppyApiMetadata build() {
+         return new PoppyApiMetadata(this);
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyFallbacks.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyFallbacks.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyFallbacks.java
new file mode 100644
index 0000000..dc2872f
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/PoppyFallbacks.java
@@ -0,0 +1,39 @@
+/*
+ * 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.openstack.poppy.v1;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.primitives.Ints.asList;
+import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull;
+
+import org.jclouds.Fallback;
+
+public final class PoppyFallbacks {
+   private PoppyFallbacks() {
+   }
+
+   public static class FalseOn500or503 implements Fallback<Boolean> {
+      @Override
+      public Boolean createOrPropagate(Throwable t) throws Exception {
+         if (returnValueOnCodeOrNull(checkNotNull(t, "throwable"), false, 
in(asList(500, 503))) != null)
+            return false;
+         throw propagate(t);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/CDN.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/CDN.java 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/CDN.java
new file mode 100644
index 0000000..a03d27c
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/CDN.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.openstack.poppy.v1.config;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+/**
+ * Represents a component related to OpenStack Poppy.
+ */
+@Retention(value = RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, 
ElementType.METHOD })
+@Qualifier
+public @interface CDN {
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/PoppyHttpApiModule.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/PoppyHttpApiModule.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/PoppyHttpApiModule.java
new file mode 100644
index 0000000..89e9fe9
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/config/PoppyHttpApiModule.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.openstack.poppy.v1.config;
+
+import java.net.URI;
+
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+import org.jclouds.openstack.poppy.v1.PoppyApi;
+import org.jclouds.openstack.poppy.v1.handlers.PoppyErrorHandler;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.base.Supplier;
+import com.google.gson.FieldNamingPolicy;
+import com.google.inject.TypeLiteral;
+
+@ConfiguresHttpApi
+public class PoppyHttpApiModule extends HttpApiModule<PoppyApi> {
+
+   @Override
+   protected void configure() {
+      bind(new TypeLiteral<Supplier<URI>>() 
{}).annotatedWith(CDN.class).to(new TypeLiteral<Supplier<URI>>() {});
+      
bind(FieldNamingPolicy.class).toInstance(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
+      bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+      super.configure();
+   }
+
+   @Override
+   protected void bindErrorHandlers() {
+      
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(PoppyErrorHandler.class);
+      
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(PoppyErrorHandler.class);
+      
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(PoppyErrorHandler.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Flavor.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Flavor.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Flavor.java
new file mode 100644
index 0000000..e2a4e6a
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Flavor.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.openstack.poppy.v1.domain;
+
+import java.util.List;
+import java.util.Set;
+
+import org.jclouds.json.SerializedNames;
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * Representation of an OpenStack Poppy CDN Flavor.
+ */
+@AutoValue
+public abstract class Flavor {
+
+   public abstract String getId();
+   public abstract List<Provider> getProviders();
+   public abstract Set<Link> getLinks();
+
+   @SerializedNames({ "id", "providers", "links" })
+   public static Flavor create(String id, List<Provider> providers, Set<Link> 
links) {
+      return new AutoValue_Flavor(id, providers, links);
+   }
+
+   Flavor() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Provider.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Provider.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Provider.java
new file mode 100644
index 0000000..06be476
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/domain/Provider.java
@@ -0,0 +1,42 @@
+/*
+ * 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.openstack.poppy.v1.domain;
+
+import java.util.Set;
+
+import org.jclouds.json.SerializedNames;
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * Representation of an OpenStack Poppy CDN Provider.
+ */
+@AutoValue
+public abstract class Provider {
+
+   public abstract String getId();
+   public abstract Set<Link> getLinks();
+
+   @SerializedNames({ "provider", "links" })
+   public static Provider create(String id, Set<Link> links) {
+      return new AutoValue_Provider(id, links);
+   }
+
+   Provider() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/features/FlavorApi.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/features/FlavorApi.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/features/FlavorApi.java
new file mode 100644
index 0000000..ee214ad
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/features/FlavorApi.java
@@ -0,0 +1,62 @@
+/*
+ * 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.openstack.poppy.v1.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.poppy.v1.config.CDN;
+import org.jclouds.openstack.poppy.v1.domain.Flavor;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.FluentIterable;
+
+/**
+ * Provides access to Flavor features.
+ */
+@Beta
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+@Endpoint(CDN.class)
+@Path("/flavors")
+public interface FlavorApi {
+
+   @Named("flavor:list")
+   @GET
+   @SelectJson("flavors")
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<Flavor> list();
+
+   @Named("flavor:get")
+   @GET
+   @Path("/{id}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Flavor get(@PathParam("id") String id);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/handlers/PoppyErrorHandler.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/handlers/PoppyErrorHandler.java
 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/handlers/PoppyErrorHandler.java
new file mode 100644
index 0000000..a317772
--- /dev/null
+++ 
b/openstack-poppy/src/main/java/org/jclouds/openstack/poppy/v1/handlers/PoppyErrorHandler.java
@@ -0,0 +1,52 @@
+/*
+ * 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.openstack.poppy.v1.handlers;
+
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.rest.AuthorizationException;
+
+public class PoppyErrorHandler implements HttpErrorHandler {
+
+   @Override
+   public void handleError(HttpCommand command, HttpResponse response) {
+      // it is important to always read fully and close streams
+      byte[] data = closeClientButKeepContentStream(response);
+      Exception exception;
+
+      if (data == null) {
+         exception = new HttpResponseException(command, response);
+      } else {
+         exception = new HttpResponseException(command, response, new 
String(data));
+      }
+
+      switch (response.getStatusCode()) {
+         case 401:
+            exception = new AuthorizationException(exception.getMessage(), 
exception);
+            break;
+         case 409:
+            exception = new IllegalStateException(exception.getMessage(), 
exception);
+            break;
+      }
+
+      command.setException(exception);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadataTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadataTest.java
 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadataTest.java
new file mode 100644
index 0000000..2c8df9b
--- /dev/null
+++ 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/PoppyApiMetadataTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.openstack.poppy.v1;
+
+import org.jclouds.View;
+import org.jclouds.apis.internal.BaseApiMetadataTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Tests the Poppy {@link ApiMetadata}.
+ */
+@Test(groups = "unit", testName = "PoppyApiMetadataTest")
+public class PoppyApiMetadataTest extends BaseApiMetadataTest {
+   public PoppyApiMetadataTest() {
+      super(new PoppyApiMetadata(), ImmutableSet.<TypeToken<? extends View>> 
of());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiLiveTest.java
 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiLiveTest.java
new file mode 100644
index 0000000..508e3fd
--- /dev/null
+++ 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiLiveTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.openstack.poppy.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.jclouds.openstack.poppy.v1.domain.Flavor;
+import org.jclouds.openstack.poppy.v1.internal.BasePoppyApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * OpenStack Poppy Flavor API Live Tests
+ */
+@Test(groups = "live", testName = "FlavorApiLiveTest")
+public class FlavorApiLiveTest extends BasePoppyApiLiveTest {
+
+   /**
+    * Tests retrieval of all Poppy Flavors.
+    *
+    * @throws Exception
+    */
+   public void testListFlavors() throws Exception {
+      FlavorApi flavorApi = api.getFlavorApi();
+      List<Flavor> flavors = flavorApi.list().toList();
+      assertNotNull(flavors);
+      assertFalse(flavors.isEmpty());
+
+      for (Flavor flavor : flavors) {
+         assertNotNull(flavor);
+      }
+
+   }
+
+   /**
+    * Tests retrieval of a single Poppy Flavor.
+    *
+    * @throws Exception
+    */
+   public void testGetFlavor() throws Exception {
+      FlavorApi flavorApi = api.getFlavorApi();
+      List<Flavor> flavors = flavorApi.list().toList();
+      assertNotNull(flavors);
+
+      for (Flavor flavor : flavors) {
+         Flavor oneFlavor = flavorApi.get(flavor.getId());
+         assertNotNull(oneFlavor);
+         assertEquals(oneFlavor.getId(), flavor.getId());
+         assertEquals(oneFlavor.getProviders(), flavor.getProviders());
+         assertEquals(oneFlavor.getLinks(), flavor.getLinks());
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiMockTest.java
 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiMockTest.java
new file mode 100644
index 0000000..bf46acc
--- /dev/null
+++ 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/FlavorApiMockTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.openstack.poppy.v1.features;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import org.jclouds.openstack.poppy.v1.PoppyApi;
+import org.jclouds.openstack.poppy.v1.domain.Flavor;
+import org.jclouds.openstack.poppy.v1.internal.BasePoppyApiMockTest;
+import org.testng.annotations.Test;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Tests annotation parsing of {@code FlavorApi}
+ */
+@Test(groups = "unit", testName = "FlavorApiMockTest")
+public class FlavorApiMockTest extends BasePoppyApiMockTest {
+
+   public void testListFlavors() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new 
MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new 
MockResponse().setResponseCode(200).setBody(stringFromResource("/poppy_flavor_list_response.json"))));
+
+      try {
+         PoppyApi poppyApi = api(server.getUrl("/").toString(), 
"openstack-poppy", overrides);
+         FlavorApi api = poppyApi.getFlavorApi();
+
+         List<Flavor> flavors = api.list().toList();
+
+         assertThat(server.getRequestCount()).isEqualTo(2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", BASE_URI + "/flavors");
+
+         assertThat(flavors).isNotEmpty();
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetFlavor() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new 
MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(
+            new 
MockResponse().setResponseCode(200).setBody(stringFromResource("/poppy_flavor_get_response.json"))));
+
+      try {
+         PoppyApi poppyApi = api(server.getUrl("/").toString(), 
"openstack-poppy", overrides);
+         FlavorApi api = poppyApi.getFlavorApi();
+
+         Flavor oneFlavor  = api.get("cdn");
+
+         assertThat(server.getRequestCount()).isEqualTo(2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", BASE_URI + "/flavors/cdn");
+
+         assertThat(oneFlavor).isNotNull();
+
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testGetFlavorFailOn404() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new 
MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(404)));
+
+      try {
+         PoppyApi poppyApi = api(server.getUrl("/").toString(), 
"openstack-poppy", overrides);
+         FlavorApi api = poppyApi.getFlavorApi();
+
+         Flavor oneFlavor  = api.get("cdn");
+
+         assertThat(server.getRequestCount()).isEqualTo(2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", BASE_URI + "/flavors/cdn");
+
+         assertThat(oneFlavor).isNull();
+
+      } finally {
+         server.shutdown();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/PoppyApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/PoppyApiMockTest.java
 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/PoppyApiMockTest.java
new file mode 100644
index 0000000..ec8eee4
--- /dev/null
+++ 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/features/PoppyApiMockTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.openstack.poppy.v1.features;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.jclouds.openstack.poppy.v1.PoppyApi;
+import org.jclouds.openstack.poppy.v1.internal.BasePoppyApiMockTest;
+import org.testng.annotations.Test;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Tests annotation parsing of {@code PoppyApi}
+ */
+@Test(groups = "unit", testName = "PoppyApiMockTest")
+public class PoppyApiMockTest extends BasePoppyApiMockTest {
+
+   public void testPing() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new 
MockResponse().setBody(stringFromResource("/access.json"))));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(204)));
+
+      try {
+         PoppyApi poppyApi = api(server.getUrl("/").toString(), 
"openstack-poppy", overrides);
+         boolean online = poppyApi.ping();
+
+         assertThat(server.getRequestCount()).isEqualTo(2);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", BASE_URI + "/ping");
+
+         assertThat(online).isTrue();
+      } finally {
+         server.shutdown();
+      }
+   }
+
+   public void testPingFailOn500() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(addCommonHeaders(new 
MockResponse().setBody(stringFromResource("/access.json"))));
+      // queue the initial 500 that forces the retry handler
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(500)));
+      server.enqueue(addCommonHeaders(new 
MockResponse().setResponseCode(500)));
+
+      try {
+         PoppyApi poppyApi = api(server.getUrl("/").toString(), 
"openstack-poppy", overrides);
+         boolean online = poppyApi.ping();
+
+         assertThat(server.getRequestCount()).isEqualTo(3);
+         assertAuthentication(server);
+         assertRequest(server.takeRequest(), "GET", BASE_URI + "/ping");
+
+         assertThat(online).isFalse();
+      } finally {
+         server.shutdown();
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiLiveTest.java
 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiLiveTest.java
new file mode 100644
index 0000000..10d3acd
--- /dev/null
+++ 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiLiveTest.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.openstack.poppy.v1.internal;
+
+import java.util.Properties;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
+import org.jclouds.openstack.poppy.v1.PoppyApi;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@link PoppyApi}.
+ *
+ */
+@Test(groups = "live")
+public class BasePoppyApiLiveTest extends BaseApiLiveTest<PoppyApi> {
+
+   public BasePoppyApiLiveTest() {
+      provider = "openstack-poppy";
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      setIfTestSystemPropertyPresent(props, KeystoneProperties.SERVICE_TYPE);
+      setIfTestSystemPropertyPresent(props, 
KeystoneProperties.CREDENTIAL_TYPE);
+      return props;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiMockTest.java
 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiMockTest.java
new file mode 100644
index 0000000..c57a5e1
--- /dev/null
+++ 
b/openstack-poppy/src/test/java/org/jclouds/openstack/poppy/v1/internal/BasePoppyApiMockTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.openstack.poppy.v1.internal;
+
+import static 
org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
+
+import java.util.Properties;
+
+import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
+import org.jclouds.openstack.poppy.v1.PoppyApi;
+import org.jclouds.openstack.v2_0.internal.BaseOpenStackMockTest;
+
+/**
+ * Base class for writing Poppy Mock tests
+ *
+ */
+public class BasePoppyApiMockTest extends BaseOpenStackMockTest<PoppyApi> {
+   protected Properties overrides;
+
+   protected static String BASE_URI = "/v1.0/123123";
+
+   /**
+    * Base Mock Test
+    */
+   public BasePoppyApiMockTest() {
+      overrides = new Properties();
+      overrides.setProperty(CREDENTIAL_TYPE, 
CredentialTypes.PASSWORD_CREDENTIALS);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/resources/access.json
----------------------------------------------------------------------
diff --git a/openstack-poppy/src/test/resources/access.json 
b/openstack-poppy/src/test/resources/access.json
new file mode 100644
index 0000000..6a759ed
--- /dev/null
+++ b/openstack-poppy/src/test/resources/access.json
@@ -0,0 +1,242 @@
+{
+    "access": {
+        "metadata": {
+            "roles": [
+                "9fe2ff9ee4384b1894a90878d3e92bab",
+                "b926cb0f4e2642678735f86c2b06205e",
+                "33484487e73d4da0918a19b9c7e1f8ae",
+                "f2e54c2105fb49e29479af047115cebc"
+            ],
+            "is_admin": 0
+        },
+        "user": {
+            "name": "joe",
+            "roles": [
+                {
+                    "name": "_member_"
+                },
+                {
+                    "name": "anotherrole"
+                },
+                {
+                    "name": "heat_stack_owner"
+                },
+                {
+                    "name": "Member"
+                }
+            ],
+            "id": "8fbf8e68d36e4ac7bcf912a26213bd49",
+            "roles_links": [],
+            "username": "joe"
+        },
+        "serviceCatalog": [
+            {
+                "name": "nova",
+                "type": "compute",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v2/123123",
+                        "id": "2122bcaa704343c19ad2578410d4961d",
+                        "internalURL": "URL/v2/123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v2/123123"
+                    }
+                ]
+            },
+            {
+                "name": "neutron",
+                "type": "network",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/",
+                        "id": "65a4d3f13cfb49a6a57a04e205cc2158",
+                        "internalURL": "URL/",
+                        "region": "RegionOne",
+                        "adminURL": "URL/"
+                    }
+                ]
+            },
+            {
+                "name": "cinderv2",
+                "type": "volumev2",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v2/123123",
+                        "id": "31fe4d92eac44044b05be21c6f44cebc",
+                        "internalURL": "URL/v2/123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v2/123123"
+                    }
+                ]
+            },
+            {
+                "name": "poppy",
+                "type": "cdn",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v1.0/123123",
+                        "id": "066e05b0c2aa47d486b4018704fe3788",
+                        "internalURL": "URL/v1.0/123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v1.0/123123"
+                    }
+                ]
+            },
+            {
+                "name": "trove",
+                "type": "database",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v1.0/123123",
+                        "id": "06b7a7dbd25c4a01819c879700a9712a",
+                        "internalURL": "URL/v1.0/123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v1.0/123123"
+                    }
+                ]
+            },
+            {
+                "name": "s3",
+                "type": "s3",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL",
+                        "id": "93b0b67091324e8ba01b62ee0584994c",
+                        "internalURL": "URL",
+                        "region": "RegionOne",
+                        "adminURL": "URL"
+                    }
+                ]
+            },
+            {
+                "name": "glance",
+                "type": "image",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL",
+                        "id": "a542e91bcfa046bfa1bf2397356d1414",
+                        "internalURL": "URL",
+                        "region": "RegionOne",
+                        "adminURL": "URL"
+                    }
+                ]
+            },
+            {
+                "name": "novav3",
+                "type": "computev3",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v3",
+                        "id": "9c3e8abb576d483db93bcef70c67bc1d",
+                        "internalURL": "URL/v3",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v3"
+                    }
+                ]
+            },
+            {
+                "name": "heat",
+                "type": "cloudformation",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v1",
+                        "id": "6f4ca5ca9698425b85c300b3fc176c39",
+                        "internalURL": "URL/v1",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v1"
+                    }
+                ]
+            },
+            {
+                "name": "cinder",
+                "type": "volume",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v1/123123",
+                        "id": "037039c676694a35aa28d34fce09e51d",
+                        "internalURL": "URL/v1/123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v1/123123"
+                    }
+                ]
+            },
+            {
+                "name": "ec2",
+                "type": "ec2",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/services/Cloud",
+                        "id": "1d242631bccb4ff4ba7a395dbcb51648",
+                        "internalURL": "URL/services/Cloud",
+                        "region": "RegionOne",
+                        "adminURL": "URL/services/Admin"
+                    }
+                ]
+            },
+            {
+                "name": "heat",
+                "type": "orchestration",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v1/123123",
+                        "id": "199d00075e4a40308a6ad2aa8980d0cd",
+                        "internalURL": "URL/v1/123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v1/123123"
+                    }
+                ]
+            },
+            {
+                "name": "swift",
+                "type": "object-store",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v1/AUTH_123123",
+                        "id": "26b2cb1efb044193b847fc3f2fb12e82",
+                        "internalURL": "URL/v1/AUTH_123123",
+                        "region": "RegionOne",
+                        "adminURL": "URL"
+                    }
+                ]
+            },
+            {
+                "name": "keystone",
+                "type": "identity",
+                "endpoints_links": [],
+                "endpoints": [
+                    {
+                        "publicURL": "URL/v2.0",
+                        "id": "1bbfe80b50df4c4a84040aa782e42140",
+                        "internalURL": "URL/v2.0",
+                        "region": "RegionOne",
+                        "adminURL": "URL/v2.0"
+                    }
+                ]
+            }
+        ],
+        "token": {
+            "tenant": {
+                "name": "jclouds",
+                "id": "123123",
+                "enabled": true,
+                "description": null
+            },
+            "id": "TOKEN",
+            "expires": "2014-04-28T22:48:24Z",
+            "issued_at": "2014-04-28T21:48:24.972896"
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/openstack-poppy/src/test/resources/logback.xml 
b/openstack-poppy/src/test/resources/logback.xml
new file mode 100644
index 0000000..6cb2617
--- /dev/null
+++ b/openstack-poppy/src/test/resources/logback.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<!--
+
+    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.
+
+-->
+<configuration scan="false">
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-wire.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root>
+        <level value="warn" />
+    </root>
+
+    <logger name="org.jclouds">
+        <level value="DEBUG" />
+        <appender-ref ref="FILE" />
+    </logger>
+
+<!--
+    <logger name="jclouds.wire">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+-->
+
+    <logger name="jclouds.headers">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+</configuration>

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/resources/poppy_flavor_get_response.json
----------------------------------------------------------------------
diff --git a/openstack-poppy/src/test/resources/poppy_flavor_get_response.json 
b/openstack-poppy/src/test/resources/poppy_flavor_get_response.json
new file mode 100644
index 0000000..0f9e73a
--- /dev/null
+++ b/openstack-poppy/src/test/resources/poppy_flavor_get_response.json
@@ -0,0 +1,20 @@
+{
+    "id": "cdn",
+    "providers": [
+        {
+            "provider": "akamai",
+            "links": [
+                {
+                    "href": "http://www.akamai.com";,
+                    "rel": "provider_url"
+                }
+            ]
+        }
+    ],
+    "links": [
+        {
+            "href": 
"https://global.cdn.api.rackspacecloud.com/v1.0/123123/flavors/cdn";,
+            "rel": "self"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/openstack-poppy/src/test/resources/poppy_flavor_list_response.json
----------------------------------------------------------------------
diff --git a/openstack-poppy/src/test/resources/poppy_flavor_list_response.json 
b/openstack-poppy/src/test/resources/poppy_flavor_list_response.json
new file mode 100644
index 0000000..7381eac
--- /dev/null
+++ b/openstack-poppy/src/test/resources/poppy_flavor_list_response.json
@@ -0,0 +1,24 @@
+{
+    "flavors": [
+        {
+            "id": "cdn",
+            "providers": [
+                {
+                    "provider": "akamai",
+                    "links": [
+                        {
+                            "href": "http://www.akamai.com";,
+                            "rel": "provider_url"
+                        }
+                    ]
+                }
+            ],
+            "links": [
+                {
+                    "href": 
"https://global.cdn.api.rackspacecloud.com/v1.0/123123/flavors/cdn";,
+                    "rel": "self"
+                }
+            ]
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/a006915f/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 905099b..846fd9d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,7 @@
     <module>openstack-glance</module>
     <module>openstack-heat</module>
     <module>openstack-neutron</module>
+    <module>openstack-poppy</module>
     <module>openstack-marconi</module>
     <module>rackspace-autoscale</module>
     <module>rackspace-autoscale-uk</module>

Reply via email to