Adds support for Rackspace Cloud Big Data
diff --git a/pom.xml b/pom.xml
index 213b719..1f900d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,8 @@
<module>rackspace-autoscale-us</module>
<module>rackspace-cloudqueues-us</module>
<module>rackspace-cloudqueues-uk</module>
+ <module>rackspace-cloudbigdata</module>
+ <module>rackspace-cloudbigdata-us</module>
</modules>
<build>
diff --git a/rackspace-cloudbigdata-us/README.md b/rackspace-cloudbigdata-us/README.md
new file mode 100644
index 0000000..620fcf2
--- /dev/null
+++ b/rackspace-cloudbigdata-us/README.md
@@ -0,0 +1,7 @@
+Rackspace Cloud Auto Scale US
+=============================
+
+The Rackspace Cloud Big Data Provider for the US zones.
+
+Production ready?
+No
diff --git a/rackspace-cloudbigdata-us/pom.xml b/rackspace-cloudbigdata-us/pom.xml
new file mode 100644
index 0000000..c825171
--- /dev/null
+++ b/rackspace-cloudbigdata-us/pom.xml
@@ -0,0 +1,163 @@
+<?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>1.8.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- TODO: when out of labs, switch to org.jclouds.api -->
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-cloudbigdata-us</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <name>jclouds rackspace-cloudbigdata api provider</name>
+ <description>jclouds components to access Rackspace Autoscale</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- keystone endpoint -->
+ <test.rackspace-cloudbigdata.endpoint>http://localhost:5000/v2.0/</test.rackspace-cloudbigdata.endpoint>
+ <!-- keystone version -->
+ <test.rackspace-cloudbigdata.api-version>2.0</test.rackspace-cloudbigdata.api-version>
+ <test.rackspace-cloudbigdata.build-version />
+ <test.rackspace-cloudbigdata.identity>FIXME_IDENTITY</test.rackspace-cloudbigdata.identity>
+ <test.rackspace-cloudbigdata.credential>FIXME_CREDENTIALS</test.rackspace-cloudbigdata.credential>
+ <test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+
+ <jclouds.osgi.export>org.jclouds.rackspace.cloudbigdata.v1_0*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>
+ org.jclouds.rest.internal;version="${jclouds.version}",
+ org.jclouds.labs*;version="${project.version}",
+ org.jclouds*;version="${jclouds.version}",
+ *
+ </jclouds.osgi.import>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>apache-snapshots</id>
+ <url>https://repository.apache.org/content/repositories/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-cloudbigdata</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-cloudbigdata</artifactId>
+ <version>${project.parent.version}</version>
+ </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</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <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.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>org.apache.jclouds.api</groupId>
+ <artifactId>rackspace-cloudidentity</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>mockwebserver</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>
+ <forkCount>5</forkCount>
+ <reuseForks>true</reuseForks>
+ <parallel>classes</parallel>
+ <systemPropertyVariables>
+ <test.rackspace-cloudbigdata.endpoint>${test.rackspace-cloudbigdata-us.endpoint}</test.rackspace-cloudbigdata.endpoint>
+ <test.rackspace-cloudbigdata.api-version>${test.rackspace-cloudbigdata-us.api-version}</test.rackspace-cloudbigdata.api-version>
+ <test.rackspace-cloudbigdata.build-version>${test.rackspace-cloudbigdata-us.build-version}</test.rackspace-cloudbigdata.build-version>
+ <test.rackspace-cloudbigdata.identity>${test.rackspace-cloudbigdata-us.identity}</test.rackspace-cloudbigdata.identity>
+ <test.rackspace-cloudbigdata.credential>${test.rackspace-cloudbigdata-us.credential}</test.rackspace-cloudbigdata.credential>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/rackspace-cloudbigdata-us/src/main/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderMetadata.java b/rackspace-cloudbigdata-us/src/main/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderMetadata.java
new file mode 100644
index 0000000..a2dbf72
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/main/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderMetadata.java
@@ -0,0 +1,131 @@
+/*
+ * 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.rackspace.cloudbigdata.us.v1;
+
+import static org.jclouds.location.reference.LocationConstants.ISO3166_CODES;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONE;
+import static org.jclouds.location.reference.LocationConstants.PROPERTY_ZONES;
+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.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApiMetadata;
+import org.jclouds.rackspace.cloudbigdata.v1.config.CloudBigDataHttpApiModule;
+import org.jclouds.rackspace.cloudbigdata.v1.config.CloudBigDataParserModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ProviderMetadata} for Rackspace CloudBigData API
+ *
+ * @author Zack Shoylev
+ */
+public class CloudBigDataUSProviderMetadata extends BaseProviderMetadata {
+
+ /**
+ * @return The builder object.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return builder().fromProviderMetadata(this);
+ }
+
+ /**
+ * Provider constructor.
+ */
+ public CloudBigDataUSProviderMetadata() {
+ super(builder());
+ }
+
+ /**
+ * @param builder Builder for the provider.
+ */
+ public CloudBigDataUSProviderMetadata(Builder builder) {
+ super(builder);
+ }
+
+ // NOTE: SYD is disabled for now. Enable when service is enabled in SYD
+ /**
+ * @return Default provider properties.
+ */
+ public static Properties defaultProperties() {
+ Properties properties = new Properties();
+ properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
+ properties.setProperty(SERVICE_TYPE, "rax:bigdata");
+ //properties.setProperty(PROPERTY_ZONES, "ORD,DFW,SYD");
+ properties.setProperty(PROPERTY_ZONES, "ORD");
+ properties.setProperty(PROPERTY_ZONE + ".ORD." + ISO3166_CODES, "US-IL");
+ //properties.setProperty(PROPERTY_ZONE + ".DFW." + ISO3166_CODES, "US-TX");
+ //properties.setProperty(PROPERTY_ZONE + ".SYD." + ISO3166_CODES, "AU-NSW");
+ return properties;
+ }
+
+ /**
+ * Builder pattern class.
+ */
+ public static class Builder extends BaseProviderMetadata.Builder {
+
+ protected Builder(){
+ id("rackspace-cloudbigdata-us")
+ .name("Rackspace CloudBigData US")
+ .apiMetadata(new CloudBigDataApiMetadata().toBuilder()
+ .identityName("${userName}")
+ .credentialName("${apiKey}")
+ .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
+ .endpointName("identity service url ending in /v2.0/")
+ .documentation(URI.create("http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/overview.html"))
+ .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+ .add(CloudIdentityAuthenticationApiModule.class)
+ .add(CloudIdentityAuthenticationModule.class)
+ .add(ZoneModule.class)
+ .add(CloudBigDataParserModule.class)
+ .add(CloudBigDataHttpApiModule.class).build())
+ .build())
+ .homepage(URI.create("http://www.rackspace.com/big-data/"))
+ .console(URI.create("https://mycloud.rackspace.com"))
+ .linkedServices("rackspace-cloudservers-us", "cloudfiles-us")
+ //.iso3166Codes("US-IL", "US-TX", "AU-NSW")
+ .iso3166Codes("US-IL")
+ .endpoint("https://identity.api.rackspacecloud.com/v2.0/")
+ .defaultProperties(CloudBigDataUSProviderMetadata.defaultProperties());
+ }
+
+ @Override
+ public CloudBigDataUSProviderMetadata build() {
+ return new CloudBigDataUSProviderMetadata(this);
+ }
+
+ @Override
+ public Builder fromProviderMetadata(ProviderMetadata in) {
+ super.fromProviderMetadata(in);
+ return this;
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/rackspace-cloudbigdata-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..b588e53
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.jclouds.rackspace.cloudbigdata.us.v1.CloudBigDataUSProviderMetadata
diff --git a/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderMetadataMockTest.java b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderMetadataMockTest.java
new file mode 100644
index 0000000..8d2a9d3
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderMetadataMockTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.rackspace.cloudbigdata.us.v1;
+
+import org.jclouds.rackspace.cloudbigdata.v1.internal.BaseCloudBigDataApiMockTest;
+import org.testng.annotations.Test;
+
+/**
+ * This test ensures that the wiring in {@link CloudBigDataUSProviderMetadata} is correct.
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSProviderMetadataExpectTest")
+public class CloudBigDataUSProviderMetadataMockTest extends BaseCloudBigDataApiMockTest {
+}
diff --git a/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderTest.java b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderTest.java
new file mode 100644
index 0000000..0ca4045
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/CloudBigDataUSProviderTest.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.rackspace.cloudbigdata.us.v1;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApiMetadata;
+import org.testng.annotations.Test;
+
+/**
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSProviderTest")
+public class CloudBigDataUSProviderTest extends BaseProviderMetadataTest {
+
+ /**
+ * CloudBigDataUSProviderTest
+ */
+ public CloudBigDataUSProviderTest() {
+ super(new CloudBigDataUSProviderMetadata(), new CloudBigDataApiMetadata());
+ }
+}
diff --git a/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/features/CloudBigDataUSClusterApiLiveTest.java b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/features/CloudBigDataUSClusterApiLiveTest.java
new file mode 100644
index 0000000..e41863e
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/features/CloudBigDataUSClusterApiLiveTest.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.rackspace.cloudbigdata.us.v1.features;
+
+import org.jclouds.rackspace.cloudbigdata.v1.features.ClusterApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests GroupApi - live
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "live", testName = "AutoscaleUSGroupApiLiveTest", singleThreaded = true)
+public class CloudBigDataUSClusterApiLiveTest extends ClusterApiLiveTest {
+ /**
+ * Ensures parent tests are executed for this provider.
+ */
+ public CloudBigDataUSClusterApiLiveTest() {
+ provider = "rackspace-cloudbigdata-us";
+ }
+}
diff --git a/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/features/CloudBigDataUSProfileApiLiveTest.java b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/features/CloudBigDataUSProfileApiLiveTest.java
new file mode 100644
index 0000000..a7a655e
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/test/java/org/jclouds/rackspace/cloudbigdata/us/v1/features/CloudBigDataUSProfileApiLiveTest.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.rackspace.cloudbigdata.us.v1.features;
+
+import org.jclouds.rackspace.cloudbigdata.v1.features.ProfileApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests GroupApi - live
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "live", testName = "AutoscaleUSGroupApiLiveTest", singleThreaded = true)
+public class CloudBigDataUSProfileApiLiveTest extends ProfileApiLiveTest {
+ /**
+ * Ensures parent tests are executed for this provider.
+ */
+ public CloudBigDataUSProfileApiLiveTest() {
+ provider = "rackspace-cloudbigdata-us";
+ }
+}
diff --git a/rackspace-cloudbigdata-us/src/test/resources/access_rax_us.json b/rackspace-cloudbigdata-us/src/test/resources/access_rax_us.json
new file mode 100644
index 0000000..9fbd1ef
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/test/resources/access_rax_us.json
@@ -0,0 +1,260 @@
+{
+ "access":{
+ "token":{
+ "id":"bb03a23aa8271291a7aaa9aaa2aaaaaa",
+ "expires":"2013-08-02T16:55:24.229-05:00",
+ "tenant":{
+ "id":"888888",
+ "name":"888888"
+ },
+ "RAX-AUTH:authenticatedBy":[
+ "PASSWORD"
+ ]
+ },
+ "serviceCatalog":[
+ {
+ "name":"cloudFilesCDN",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"https:\/\/cdn2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"https:\/\/cdn1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"SYD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"https:\/\/cdn4.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ }
+ ],
+ "type":"rax:object-cdn"
+ },
+ {
+ "name":"cloudBigData",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:bigdata"
+ },
+ {
+ "name":"cloudFiles",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"https:\/\/storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "internalURL":"https:\/\/snet-storage101.ord1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"https:\/\/storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "internalURL":"https:\/\/snet-storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"SYD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"https:\/\/storage101.syd2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "internalURL":"https:\/\/snet-storage101.syd2.clouddrive.com\/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ }
+ ],
+ "type":"object-store"
+ },
+ {
+ "name":"cloudLoadBalancers",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/syd.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/dfw.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/ord.loadbalancers.api.rackspacecloud.com\/v1.0\/888888"
+ }
+ ],
+ "type":"rax:load-balancer"
+ },
+ {
+ "name":"cloudDatabases",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/syd.databases.api.rackspacecloud.com\/v1.0\/888888"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/dfw.databases.api.rackspacecloud.com\/v1.0\/888888"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/ord.databases.api.rackspacecloud.com\/v1.0\/888888"
+ }
+ ],
+ "type":"rax:database"
+ },
+ {
+ "name":"cloudBlockStorage",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/syd.blockstorage.api.rackspacecloud.com\/v1\/888888"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/dfw.blockstorage.api.rackspacecloud.com\/v1\/888888"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/ord.blockstorage.api.rackspacecloud.com\/v1\/888888"
+ }
+ ],
+ "type":"volume"
+ },
+ {
+ "name":"cloudServersOpenStack",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/syd.servers.api.rackspacecloud.com\/v2\/888888",
+ "versionInfo":"https:\/\/syd.servers.api.rackspacecloud.com\/v2",
+ "versionList":"https:\/\/syd.servers.api.rackspacecloud.com\/",
+ "versionId":"2"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2\/888888",
+ "versionInfo":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2",
+ "versionList":"https:\/\/dfw.servers.api.rackspacecloud.com\/",
+ "versionId":"2"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/ord.servers.api.rackspacecloud.com\/v2\/888888",
+ "versionInfo":"https:\/\/ord.servers.api.rackspacecloud.com\/v2",
+ "versionList":"https:\/\/ord.servers.api.rackspacecloud.com\/",
+ "versionId":"2"
+ }
+ ],
+ "type":"compute"
+ },
+ {
+ "name":"autoscale",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/ord.autoscale.api.rackspacecloud.com\/v1.0\/888888",
+ "versionInfo":null,
+ "versionList":null,
+ "versionId":"1.0"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"https:\/\/dfw.autoscale.api.rackspacecloud.com\/v1.0\/888888",
+ "versionInfo":null,
+ "versionList":null,
+ "versionId":"1.0"
+ }
+ ],
+ "type":"rax:autoscale"
+ },
+ {
+ "name":"cloudMonitoring",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"https:\/\/monitoring.api.rackspacecloud.com\/v1.0\/888888"
+ }
+ ],
+ "type":"rax:monitor"
+ },
+ {
+ "name":"cloudBackup",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"https:\/\/backup.api.rackspacecloud.com\/v1.0\/888888"
+ }
+ ],
+ "type":"rax:backup"
+ },
+ {
+ "name":"cloudServers",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"https:\/\/servers.api.rackspacecloud.com\/v1.0\/888888",
+ "versionInfo":"https:\/\/servers.api.rackspacecloud.com\/v1.0",
+ "versionList":"https:\/\/servers.api.rackspacecloud.com\/",
+ "versionId":"1.0"
+ }
+ ],
+ "type":"compute"
+ },
+ {
+ "name":"cloudDNS",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"https:\/\/dns.api.rackspacecloud.com\/v1.0\/888888"
+ }
+ ],
+ "type":"rax:dns"
+ }
+ ],
+ "user":{
+ "id":"335853",
+ "roles":[
+ {
+ "id":"10000150",
+ "description":"Checkmate Access role",
+ "name":"checkmate"
+ },
+ {
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "id":"5",
+ "description":"A Role that allows a user access to keystone Service methods",
+ "name":"object-store:default"
+ },
+ {
+ "tenantId":"888888",
+ "id":"6",
+ "description":"A Role that allows a user access to keystone Service methods",
+ "name":"compute:default"
+ },
+ {
+ "id":"3",
+ "description":"User Admin Role.",
+ "name":"identity:user-admin"
+ }
+ ],
+ "name":"test",
+ "RAX-AUTH:defaultRegion":"ORD"
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata-us/src/test/resources/logback.xml b/rackspace-cloudbigdata-us/src/test/resources/logback.xml
new file mode 100644
index 0000000..6559c23
--- /dev/null
+++ b/rackspace-cloudbigdata-us/src/test/resources/logback.xml
@@ -0,0 +1,69 @@
+<?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>
+
+ <appender name="BLOBSTOREFILE" class="ch.qos.logback.core.FileAppender">
+ <file>target/test-data/jclouds-blobstore.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>
+
+ <logger name="jclouds.blobstore">
+ <level value="DEBUG" />
+ <appender-ref ref="BLOBSTOREFILE" />
+ </logger>
+
+</configuration>
diff --git a/rackspace-cloudbigdata/README.md b/rackspace-cloudbigdata/README.md
new file mode 100644
index 0000000..afd0df3
--- /dev/null
+++ b/rackspace-cloudbigdata/README.md
@@ -0,0 +1,7 @@
+Rackspace Cloud Big Data
+==========================
+
+The Rackspace Cloud Big Data service.
+
+Production ready?
+No
diff --git a/rackspace-cloudbigdata/pom.xml b/rackspace-cloudbigdata/pom.xml
new file mode 100644
index 0000000..88406c3
--- /dev/null
+++ b/rackspace-cloudbigdata/pom.xml
@@ -0,0 +1,157 @@
+<?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>1.8.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- TODO: when out of labs, switch to org.jclouds.api -->
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-cloudbigdata</artifactId>
+ <version>1.8.0-SNAPSHOT</version>
+ <name>jclouds rackspace-cloudbigdata api</name>
+ <description>jclouds components to access Rackspace Cloud Big Data</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- keystone endpoint -->
+ <test.rackspace-cloudbigdata.endpoint>http://localhost:5000/v2.0/</test.rackspace-cloudbigdata.endpoint>
+ <!-- keystone version -->
+ <test.rackspace-cloudbigdata.api-version>2.0</test.rackspace-cloudbigdata.api-version>
+ <test.rackspace-cloudbigdata.build-version />
+ <test.rackspace-cloudbigdata.identity>FIXME_IDENTITY</test.rackspace-cloudbigdata.identity>
+ <test.rackspace-cloudbigdata.credential>FIXME_CREDENTIALS</test.rackspace-cloudbigdata.credential>
+ <test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+
+ <jclouds.osgi.export>org.jclouds.rackspace.cloudbigdata.v1_0*;version="${project.version}"</jclouds.osgi.export>
+ <jclouds.osgi.import>
+ org.jclouds.rest.internal;version="${jclouds.version}",
+ org.jclouds.labs*;version="${project.version}",
+ org.jclouds*;version="${jclouds.version}",
+ *
+ </jclouds.osgi.import>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>apache-snapshots</id>
+ <url>https://repository.apache.org/content/repositories/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-compute</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.api</groupId>
+ <artifactId>openstack-keystone</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds</groupId>
+ <artifactId>jclouds-core</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <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>
+ <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>org.apache.jclouds.api</groupId>
+ <artifactId>rackspace-cloudidentity</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>mockwebserver</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>
+ <forkCount>5</forkCount>
+ <reuseForks>true</reuseForks>
+ <parallel>classes</parallel>
+ <systemPropertyVariables>
+ <test.rackspace-cloudbigdata.endpoint>${test.rackspace-cloudbigdata.endpoint}</test.rackspace-cloudbigdata.endpoint>
+ <test.rackspace-cloudbigdata.api-version>${test.rackspace-cloudbigdata.api-version}</test.rackspace-cloudbigdata.api-version>
+ <test.rackspace-cloudbigdata.build-version>${test.rackspace-cloudbigdata.build-version}</test.rackspace-cloudbigdata.build-version>
+ <test.rackspace-cloudbigdata.identity>${test.rackspace-cloudbigdata.identity}</test.rackspace-cloudbigdata.identity>
+ <test.rackspace-cloudbigdata.credential>${test.rackspace-cloudbigdata.credential}</test.rackspace-cloudbigdata.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>
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/CloudBigDataApi.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/CloudBigDataApi.java
new file mode 100644
index 0000000..bded167
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/CloudBigDataApi.java
@@ -0,0 +1,63 @@
+/*
+ * 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.rackspace.cloudbigdata.v1;
+
+import java.io.Closeable;
+import java.util.Set;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.ZoneToEndpoint;
+import org.jclouds.rackspace.cloudbigdata.v1.features.ClusterApi;
+import org.jclouds.rackspace.cloudbigdata.v1.features.ProfileApi;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.inject.Provides;
+
+/**
+ * Provides access to Rackspace Cloud Big Data.
+ * Rackspace Cloud Big Data is an on-demand Apache Hadoop service on the Rackspace open cloud. The service supports a RESTful API and alleviates the pain associated with deploying, managing, and scaling Hadoop clusters.
+ * @see <a href="http://docs.rackspace.com/cbd/api/v1.0/cbd-devguide/content/overview.html">API Doc</a>
+ * @author Zack Shoylev
+ */
+public interface CloudBigDataApi extends Closeable{
+ /**
+ * Provides a set of all zones available.
+ *
+ * @return the Zone codes configured
+ */
+ @Provides
+ @Zone
+ Set<String> getConfiguredZones();
+
+ /**
+ * Provides access to all Profile features.
+ * @param zone The zone (region) for the profile API.
+ * @return A profile API context.
+ */
+ @Delegate
+ ProfileApi getProfileApiForZone(@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
+
+ /**
+ * Provides access to all Cluster features.
+ * @param zone The zone (region) for the profile API.
+ * @return A cluster API context.
+ */
+ @Delegate
+ ClusterApi getClusterApiForZone(@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/CloudBigDataApiMetadata.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/CloudBigDataApiMetadata.java
new file mode 100644
index 0000000..12a8f5d
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/CloudBigDataApiMetadata.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.rackspace.cloudbigdata.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.CredentialTypes;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
+import org.jclouds.rackspace.cloudbigdata.v1.config.CloudBigDataHttpApiModule;
+import org.jclouds.rackspace.cloudbigdata.v1.config.CloudBigDataParserModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for the Rackspace Cloud Big Data API
+ *
+ * @see CloudBigDataApi
+ * @author Zack Shoylev
+ */
+public class CloudBigDataApiMetadata extends BaseHttpApiMetadata<CloudBigDataApi> {
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ /**
+ *
+ */
+ public CloudBigDataApiMetadata() {
+ this(new Builder());
+ }
+
+ protected CloudBigDataApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseHttpApiMetadata.defaultProperties();
+ properties.setProperty(SERVICE_TYPE, "rax:bigdata");
+ properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
+ return properties;
+ }
+
+ /**
+ * Metadata setup
+ */
+ public static class Builder extends BaseHttpApiMetadata.Builder<CloudBigDataApi, Builder> {
+
+ protected Builder() {
+ id("rackspace-cloudbigdata")
+ .name("Rackspace Cloud Big Data API")
+ .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
+ .credentialName("${password}")
+ .endpointName("Keystone base URL ending in /v2.0/")
+ .documentation(URI.create("http://api.openstack.org/"))
+ .version("1.0")
+ .defaultEndpoint("http://localhost:5000/v2.0/")
+ .defaultProperties(CloudBigDataApiMetadata.defaultProperties())
+ .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+ .add(CloudIdentityAuthenticationApiModule.class)
+ .add(CloudIdentityAuthenticationModule.class)
+ .add(ZoneModule.class)
+ .add(CloudBigDataParserModule.class)
+ .add(CloudBigDataHttpApiModule.class)
+ .build());
+ }
+
+ @Override
+ public CloudBigDataApiMetadata build() {
+ return new CloudBigDataApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/config/CloudBigDataHttpApiModule.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/config/CloudBigDataHttpApiModule.java
new file mode 100644
index 0000000..01fa3f5
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/config/CloudBigDataHttpApiModule.java
@@ -0,0 +1,82 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.config;
+
+import java.net.URI;
+
+import javax.inject.Singleton;
+
+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.openstack.keystone.v2_0.domain.Access;
+import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApi;
+import org.jclouds.rackspace.cloudbigdata.v1.handlers.CloudBigDataErrorHandler;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
+import com.google.inject.Provides;
+
+/**
+ * Configures the Cloud Big Data connection.
+ *
+ * @author Zack Shoylev
+ */
+@ConfiguresHttpApi
+public class CloudBigDataHttpApiModule extends HttpApiModule<CloudBigDataApi> {
+
+ @Override
+ protected void configure() {
+ super.configure();
+ }
+
+ /**
+ * @return Aliases
+ */
+ @Provides
+ @Singleton
+ public Multimap<URI, URI> aliases() {
+ return ImmutableMultimap.<URI, URI>builder().build();
+ }
+
+ @Override
+ protected void bindErrorHandlers() {
+ bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(CloudBigDataErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(CloudBigDataErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(CloudBigDataErrorHandler.class);
+ }
+
+ @Provides
+ Supplier<Optional<Tenant>> supplyTenant(Supplier<Access> access) {
+ return Suppliers.compose(GetTenant.INSTANCE, access);
+ }
+
+ private static enum GetTenant implements Function<Access, Optional<Tenant>> {
+ INSTANCE;
+ public Optional<Tenant> apply(Access in){
+ return in.getToken().getTenant();
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/config/CloudBigDataParserModule.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/config/CloudBigDataParserModule.java
new file mode 100644
index 0000000..76e6052
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/config/CloudBigDataParserModule.java
@@ -0,0 +1,32 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.config;
+
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.json.config.GsonModule.DateAdapter;
+
+import com.google.inject.AbstractModule;
+
+/**
+ * @author Zack Shoylev
+ */
+public class CloudBigDataParserModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/Cluster.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/Cluster.java
new file mode 100644
index 0000000..c59d967
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/Cluster.java
@@ -0,0 +1,259 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.cloudbigdata.v1.features.ClusterApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Cloud Big Data Cluster.
+ * Contains information about a Cloud Big Data cluster.
+ * @see ClusterApi#create
+ * @author Zack Shoylev
+ */
+public class Cluster extends CreateCluster {
+ private final String id;
+ private final Date created;
+ private final Date updated;
+ private final ScriptStatus postInitScriptStatus;
+ private final float progress;
+ private final Status status;
+ private final ImmutableList<Link> links;
+
+ @ConstructorProperties({
+ "name", "clusterType", "flavorId", "nodeCount", "pointInitScript",
+ "id", "created", "updated", "postInitScriptStatus", "progress", "status", "links"
+ })
+ protected Cluster(String name, String clusterType, String flavorId, int nodeCount, URI pointInitScript,
+ String id, Date created, Date updated, ScriptStatus postInitScriptStatus, float progress, Status status, ImmutableList<Link> links) {
+ super(name, clusterType, flavorId, nodeCount, pointInitScript);
+ this.id = checkNotNull(id, "id must not be null");
+ this.created = checkNotNull(created, "created must not be null");
+ this.updated = checkNotNull(updated, "updated must not be null");
+ this.postInitScriptStatus = postInitScriptStatus;
+ this.progress = progress;
+ this.status = checkNotNull(status, "status must not be null");
+ this.links = checkNotNull(links, "links must not be null");
+ }
+
+ /**
+ * @return the id for this cluster
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @return the timestamp when this cluster was created.
+ */
+ public Date getCreated() {
+ return created;
+ }
+
+ /**
+ * @return the timestamp when this cluster was updated. This can be empty.
+ */
+ public Date getUpdated() {
+ return updated;
+ }
+
+ /**
+ * @return The status of the execution of the init script.
+ */
+ public ScriptStatus getPostInitScriptStatus() {
+ return postInitScriptStatus;
+ }
+
+ /**
+ * @return The operation progress of this cluster (completion percent).
+ * The way this completion is calculated is subject to change.
+ * Currently this is calculated based on the number of nodes in the cluster and their progress through configuration:
+ * <br>BUILDING: progress = 0.5 * configuring_count / len(self.nodes)
+ * <br>CONFIGURING/RESIZING: progress = 0.5 + (0.5 * active_count / len(self.nodes))
+ * <br>ACTIVE: progress = 1.0
+ */
+ public float getProgress() {
+ return progress;
+ }
+
+ /**
+ * @return the current status.
+ */
+ public Status getStatus() {
+ return status;
+ }
+
+ /**
+ * @return the links for this cluster.
+ */
+ public ImmutableList<Link> getLinks() {
+ return links;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), id, created, updated, postInitScriptStatus, progress, status, links);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Cluster that = Cluster.class.cast(obj);
+ return Objects.equal(this.id, that.id) &&
+ Objects.equal(this.created, that.created) &&
+ Objects.equal(this.updated, that.updated) &&
+ Objects.equal(this.postInitScriptStatus, that.postInitScriptStatus) &&
+ Objects.equal(this.progress, that.progress) &&
+ Objects.equal(this.status, that.status) &&
+ Objects.equal(this.links, that.links) &&
+ super.equals(obj);
+ }
+
+ protected ToStringHelper string() {
+ return super.string()
+ .add("id", id)
+ .add("created", created)
+ .add("updated", updated)
+ .add("postInitScriptStatus", postInitScriptStatus)
+ .add("progress", progress)
+ .add("status", status)
+ .add("links", links);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ /**
+ * Lists possible Cluster status.
+ */
+ public static enum Status {
+ /**
+ * The cluster is in the process of being created. Servers are being created and booted.
+ */
+ BUILDING,
+ /**
+ * The cluster is still in the process of being created. All servers are booted and are now being provisioned.
+ */
+ CONFIGURING,
+ /**
+ * The cluster is operational. All nodes are provisioned and ready for use.
+ */
+ ACTIVE,
+ /**
+ * Cluster is changing configuration (resizing, etc) at customers request.
+ */
+ UPDATING,
+ /**
+ * Customer has requested an operation that failed but cluster is still operational. e.g. resize up but can't acquire more nodes
+ */
+ IMPAIRED,
+ /**
+ * Customer has requested the cluster be deleted but the operation hasn't yet completed.
+ */
+ DELETING,
+ /**
+ * The cluster is deleted.
+ */
+ DELETED,
+ /**
+ * A fatal error has occurred during cluster provisioning.
+ */
+ ERROR,
+ /**
+ * Unrecognized status response.
+ */
+ UNRECOGNIZED;
+
+ @Override
+ public String toString() {
+ return name();
+ }
+
+ /**
+ * @param status The string representation of a Status
+ * @return The corresponding Status.
+ */
+ public static Status fromValue(String status) {
+ try {
+ return valueOf(checkNotNull(status, "status"));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+ }
+
+ /**
+ * Lists possible Cluster script status.
+ * This is the current status of the init script.
+ */
+ public static enum ScriptStatus {
+ /**
+ * The init script has failed.
+ */
+ FAILED,
+ /**
+ * The init script has not started executing.
+ */
+ PENDING,
+ /**
+ * The init script has been uploaded.
+ */
+ DELIVERED,
+ /**
+ * The init script is executing.
+ */
+ RUNNING,
+ /**
+ * The init script has finished successfully.
+ */
+ SUCCEEDED,
+ /**
+ * Unrecognized status response.
+ */
+ UNRECOGNIZED;
+
+ @Override
+ public String toString() {
+ return name();
+ }
+
+ /**
+ * @param scriptStatus The string representation of a ScriptStatus
+ * @return The corresponding ScriptStatus.
+ */
+ public static ScriptStatus fromValue(String scriptStatus) {
+ try {
+ return valueOf(checkNotNull(scriptStatus, "scriptStatus"));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/CreateCluster.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/CreateCluster.java
new file mode 100644
index 0000000..b4b7c6d
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/CreateCluster.java
@@ -0,0 +1,268 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+
+import org.jclouds.rackspace.cloudbigdata.v1.features.ClusterApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Cloud Big Data CreateCluster.
+ * This is used to describe how to create a Cloud Big Data cluster, a collection of machines that can be used to run distributed data processing.
+ * This class implements the Builder pattern.
+ * @see ClusterApi#create
+ * @author Zack Shoylev
+ */
+public class CreateCluster implements Comparable<CreateCluster> {
+ private final String name;
+ private final String clusterType;
+ private final String flavorId;
+ private final int nodeCount;
+ private final URI postInitScript;
+
+
+ @ConstructorProperties({
+ "name", "clusterType", "flavorId", "nodeCount", "postInitScript"
+ })
+ protected CreateCluster(String name, String clusterType, String flavorId, int nodeCount, URI postInitScript) {
+ this.name = checkNotNull(name, "name required");
+ this.clusterType = checkNotNull(clusterType, "clusterType required");
+ this.flavorId = checkNotNull(flavorId, "flavorId required");
+ this.nodeCount = nodeCount;
+ this.postInitScript = postInitScript; // Not necessarily present in the response
+ }
+
+ /**
+ * @return the name for this cluster
+ * @see CreateCluster.Builder#name(String)
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the ClusterType for this cluster
+ * @see CreateCluster.Builder#clusterType(String)
+ */
+ public String getClusterType() {
+ return clusterType;
+ }
+
+ /**
+ * @return the flavor id for this cluster. All cluster machines will use this flavor.
+ * @see CreateCluster.Builder#flavorId(String)
+ */
+ public String getFlavorId() {
+ return flavorId;
+ }
+
+ /**
+ * @return the number of nodes on this cluster.
+ * @see CreateCluster.Builder#nodeCount(int)
+ */
+ public int getNodeCount() {
+ return nodeCount;
+ }
+
+ /**
+ * @return the URI to the init script. Example: http://example.com/configure_cluster.sh
+ * @see CreateCluster.Builder#postInitScript(URI)
+ */
+ public URI getPostInitScript() {
+ return postInitScript;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, clusterType, flavorId, nodeCount, postInitScript);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ CreateCluster that = CreateCluster.class.cast(obj);
+ return Objects.equal(this.name, that.name) &&
+ Objects.equal(this.clusterType, that.clusterType) &&
+ Objects.equal(this.flavorId, that.flavorId) &&
+ Objects.equal(this.nodeCount, that.nodeCount) &&
+ Objects.equal(this.postInitScript, that.postInitScript);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("name", name)
+ .add("clusterType", clusterType)
+ .add("flavorId", flavorId)
+ .add("nodeCount", nodeCount)
+ .add("postInitScript", postInitScript);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ /**
+ * @return The builder object for this class.
+ * This Builder is then used to create a CreateCluster object, which contains all information needed to configure and setup a cluster.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * @return The Builder object. Extracts a Builder object that can be used to generate another CreateCluster object.
+ */
+ public Builder toBuilder() {
+ return new Builder().fromCreateCluster(this);
+ }
+
+ /**
+ * Implements the Builder pattern.
+ */
+ public static class Builder {
+ protected String name;
+ protected String clusterType;
+ protected String flavorId;
+ protected int nodeCount;
+ protected URI postInitScript;
+
+ /**
+ * @param name The name of this Cluster.
+ * @return The builder object.
+ * @see CreateCluster#getName()
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param clusterType The type of this Cluster. Multiple types are supported. These types might change. Supported cluster types can be discovered.
+ * @return The builder object.
+ * @see CreateCluster#getClusterType()
+ */
+ public Builder clusterType(String clusterType) {
+ this.clusterType = clusterType;
+ return this;
+ }
+
+ /**
+ * @param flavorId The flavor id to be used for this cluster. This specifies an identifier for the type of machine to be used for each cluster node.
+ * @return The builder object.
+ * @see CreateCluster#getFlavorId()
+ */
+ public Builder flavorId(String flavorId) {
+ this.flavorId = flavorId;
+ return this;
+ }
+
+ /**
+ * @param nodeCount The size of this cluster. This size might be limited by your account quota. This is the number of nodes of the type specified by flavorId.
+ * @return The builder object.
+ * @see CreateCluster#getNodeCount()
+ */
+ public Builder nodeCount(int nodeCount) {
+ this.nodeCount = nodeCount;
+ return this;
+ }
+
+ /**
+ * @param postInitScript The URI to the init script. An init script can be executed on your cluster while configuring. This is used to specify the location of that script.
+ * @return The builder object.
+ * @see CreateCluster#getPostInitScript()
+ */
+ public Builder postInitScript(URI postInitScript) {
+ this.postInitScript = postInitScript;
+ return this;
+ }
+
+ /**
+ * @return A new CreateCluster object.
+ */
+ public CreateCluster build() {
+ return new CreateCluster(name, clusterType, flavorId, nodeCount, postInitScript);
+ }
+
+ /**
+ * @param in The CreateCluster
+ * @return The CreateCluster Builder
+ */
+ public Builder fromCreateCluster(CreateCluster in) {
+ return this
+ .name(in.getName())
+ .clusterType(in.getClusterType())
+ .flavorId(in.getFlavorId())
+ .nodeCount(in.getNodeCount())
+ .postInitScript(in.getPostInitScript());
+ }
+ }
+
+ @Override
+ public int compareTo(CreateCluster that) {
+ return this.getName().compareTo(that.getName());
+ }
+
+ /**
+ * Enumerates different types of clusters.
+ * This is just an example. Supported cluster types can be discovered through the API.
+ */
+ public static enum ClusterType {
+ /**
+ * Hadoop Hortonworks Data Platform 1.1
+ * No longer supported.
+ */
+ HADOOP_HDP1_1,
+ /**
+ * Hadoop Hortonworks Data Platform 1.3
+ */
+ HADOOP_HDP1_3,
+ /**
+ * HBase Hortonworks Data Platform 1.1
+ * Currently not enabled.
+ */
+ HBASE_HDP1_1,
+ /**
+ * Unrecognized value.
+ */
+ UNRECOGNIZED;
+
+ @Override
+ public String toString() {
+ return name();
+ }
+
+ /**
+ * @param type The string representation of a ClusterType
+ * @return The corresponding ClusterType.
+ */
+ public static ClusterType fromValue(String type) {
+ try {
+ return valueOf(checkNotNull(type, "type"));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/CreateProfile.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/CreateProfile.java
new file mode 100644
index 0000000..2227b66
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/CreateProfile.java
@@ -0,0 +1,238 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import javax.inject.Named;
+
+import org.jclouds.rackspace.cloudbigdata.v1.features.ProfileApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Cloud Big Data CreateProfile.
+ * This class is used when creating a new Profile.
+ * You must create a profile before you can manage clusters for an account.
+ * @see ProfileApi#create
+ * @author Zack Shoylev
+ */
+public class CreateProfile implements Comparable<CreateProfile> {
+ private final String username;
+ private final String password;
+ @Named("sshkeys")
+ private final ImmutableList<ProfileSSHKey> sshKeys;
+ private final CloudCredentials cloudCredentials;
+
+ @ConstructorProperties({
+ "username", "password", "sshkeys", "cloudCredentials"
+ })
+ protected CreateProfile(String username, String password, ImmutableList<ProfileSSHKey> sshKeys, CloudCredentials cloudCredentials) {
+ this.username = checkNotNull(username, "username required");
+ this.password = checkNotNull(password, "password required");
+ this.sshKeys = sshKeys;
+ this.cloudCredentials = cloudCredentials;
+ }
+
+ /**
+ * @return the username for this profile.
+ * @see CreateProfile.Builder#username(String)
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * The profile password.
+ * @return the password for this CreateProfile object; empty in the response.
+ * @see CreateProfile.Builder#username(String)
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * @return the username for this profile's cloud credentials
+ * @see CreateProfile.Builder#credentialsUsername(String)
+ */
+ public String getCredentialsUsername() {
+ return cloudCredentials.username;
+ }
+
+ /**
+ * @return the api key for this profile's cloud credentials
+ * @see CreateProfile.Builder#credentialsApiKey(String)
+ */
+ public String getCredentialsApiKey() {
+ return cloudCredentials.apikey;
+ }
+
+ /**
+ * @return the list of ssh keys
+ */
+ public ImmutableList<ProfileSSHKey> getSSHKeys() {
+ return sshKeys;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(username, password, cloudCredentials.username, cloudCredentials.apikey, sshKeys);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ CreateProfile that = CreateProfile.class.cast(obj);
+ return Objects.equal(this.username, that.username) &&
+ Objects.equal(this.password, that.password) &&
+ Objects.equal(this.cloudCredentials.username, that.cloudCredentials.username) &&
+ Objects.equal(this.cloudCredentials.apikey, that.cloudCredentials.apikey) &&
+ Objects.equal(this.sshKeys, that.sshKeys);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("username", username)
+ .add("password", password)
+ .add("credentialsUsername", cloudCredentials.username)
+ .add("credentialsApikey", cloudCredentials.apikey)
+ .add("sshkeys", sshKeys);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ /**
+ * @return The builder object for this class
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * @return The Builder object
+ */
+ public Builder toBuilder() {
+ return new Builder().fromCreateProfile(this);
+ }
+
+ /**
+ * Implements the Builder pattern
+ */
+ public static class Builder {
+ protected String username;
+ protected String password;
+ protected ImmutableList<ProfileSSHKey> sshKeys;
+ protected String credentialsUsername;
+ protected String credentialsApikey;
+
+ /**
+ * @param username The name of this Profile.
+ * @return The builder object.
+ * @see CreateProfile#getUsername()
+ */
+ public Builder username(String username) {
+ this.username = username;
+ return this;
+ }
+
+ /**
+ * @param password The password for this Profile.
+ * @return The builder object.
+ * @see CreateProfile#getPassword()
+ */
+ public Builder password(String password) {
+ this.password = password;
+ return this;
+ }
+
+ /**
+ * @param credentialsUsername The login name of this Profile.
+ * @return The builder object.
+ * @see CreateProfile#getCredentialsUsername()
+ */
+ public Builder credentialsUsername(String credentialsUsername) {
+ this.credentialsUsername = credentialsUsername;
+ return this;
+ }
+
+ /**
+ * @param credentialsApikey The name of this Profile.
+ * @return The builder object.
+ * @see CreateProfile#getCredentialsApiKey()
+ */
+ public Builder credentialsApiKey(String credentialsApikey) {
+ this.credentialsApikey = credentialsApikey;
+ return this;
+ }
+
+ /**
+ * @param sshKeys The list of SSH keys for this Profile.
+ * @return The builder object.
+ * @see CreateProfile#getSSHKeys()
+ */
+ public Builder sshKeys(ImmutableList<ProfileSSHKey> sshKeys) {
+ this.sshKeys = sshKeys;
+ return this;
+ }
+
+ /**
+ * @return A new CreateProfile object.
+ */
+ public CreateProfile build() {
+ return new CreateProfile(username, password, sshKeys, new CloudCredentials(credentialsUsername, credentialsApikey));
+ }
+
+ /**
+ * @param in The target CreateProfile
+ * @return The CreateProfile Builder
+ */
+ public Builder fromCreateProfile(CreateProfile in) {
+ return this
+ .username(in.getUsername())
+ .password(in.getPassword())
+ .sshKeys(in.getSSHKeys())
+ .credentialsUsername(in.getCredentialsUsername())
+ .credentialsApiKey(in.getCredentialsApiKey());
+ }
+ }
+
+ @Override
+ public int compareTo(CreateProfile that) {
+ return this.getUsername().compareTo(that.getUsername());
+ }
+
+ protected static class CloudCredentials {
+ String username;
+ String apikey;
+
+ @ConstructorProperties({
+ "username", "apikey"
+ })
+ protected CloudCredentials(String username, String apikey) {
+ this.username = checkNotNull(username, "username required");
+ this.apikey = apikey; // Optional in response.
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/Profile.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/Profile.java
new file mode 100644
index 0000000..812634c
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/Profile.java
@@ -0,0 +1,100 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.cloudbigdata.v1.features.ProfileApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Cloud Big Data Profile. A Profile describes account settings for Cloud Big Data.
+ * A Profile must be created before Clusters can be created.
+ *
+ * @see ProfileApi#create
+ * @author Zack Shoylev
+ */
+public class Profile extends CreateProfile {
+ private final String userId;
+ private final String tenantId;
+ private final ImmutableList<Link> links;
+
+ @ConstructorProperties({
+ "username", "password", "sshkeys", "cloudCredentials", "userId", "tenantId", "links"
+ })
+ protected Profile(String username, String password, ImmutableList<ProfileSSHKey> sshKeys, CloudCredentials cloudCredentials, String userId, String tenantId, ImmutableList<Link> links) {
+ super(username, "", sshKeys, cloudCredentials); // Password not returned in response
+ this.userId = checkNotNull(userId, "user id required");
+ this.tenantId = checkNotNull(tenantId, "tenant id required");
+ this.links = checkNotNull(links, "links required");
+ }
+
+ /**
+ * @return the user id of this Profile.
+ */
+ public String getUserId() {
+ return this.userId;
+ }
+
+ /**
+ * @return the tenant id of this Profile.
+ */
+ public String getTenantId() {
+ return this.tenantId;
+ }
+
+ /**
+ * @return the links to this Profile.
+ */
+ public ImmutableList<Link> getLinks() {
+ return this.links;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), links, userId, tenantId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Profile that = Profile.class.cast(obj);
+ return Objects.equal(this.userId, that.userId) &&
+ Objects.equal(this.tenantId, that.tenantId) &&
+ Objects.equal(this.links, that.links) &&
+ super.equals(obj);
+ }
+
+ protected ToStringHelper string() {
+ return super.string()
+ .add("userId", userId)
+ .add("tenantId", tenantId)
+ .add("links", links);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/ProfileSSHKey.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/ProfileSSHKey.java
new file mode 100644
index 0000000..521148e
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/domain/ProfileSSHKey.java
@@ -0,0 +1,144 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Cloud Big Data ProfileSSHKey.
+ * Used to provide a key pair for a Profile.
+ * @author Zack Shoylev
+ */
+public class ProfileSSHKey implements Comparable<ProfileSSHKey> {
+ private String name;
+ private String publicKey;
+
+ @ConstructorProperties({
+ "name", "publicKey"
+ })
+ protected ProfileSSHKey(String name, String publicKey) {
+ this.name = checkNotNull(name, "name required");
+ this.publicKey = checkNotNull(publicKey, "public key required");
+ }
+
+ /**
+ * @return the name of this SSH key
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @return the public SSH key
+ */
+ public String getPublicKey() {
+ return this.publicKey;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, publicKey);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ ProfileSSHKey that = ProfileSSHKey.class.cast(obj);
+ return Objects.equal(this.name, that.name) &&
+ Objects.equal(this.publicKey, that.publicKey);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("name", name)
+ .add("publicKey", publicKey);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ /**
+ * @return A new builder object
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * @return A new Builder object from another ProfileSSHKey
+ */
+ public Builder toBuilder() {
+ return new Builder().fromProfileSSHKey(this);
+ }
+
+ /**
+ * Implements the Builder pattern for this class
+ */
+ public static class Builder {
+ protected String name;
+ protected String publicKey;
+
+ /**
+ * @param name The name of this ProfileSSHKey.
+ * @return The builder object.
+ * @see ProfileSSHKey#getName()
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param publicKey The publicKey for this ProfileSSHKey.
+ * @return The builder object.
+ */
+ public Builder publicKey(String publicKey) {
+ this.publicKey = publicKey;
+ return this;
+ }
+
+ /**
+ * @return A new ProfileSSHKey object.
+ */
+ public ProfileSSHKey build() {
+ return new ProfileSSHKey(name, publicKey);
+ }
+
+ /**
+ * @param in The target ProfileSSHKey
+ * @return A Builder from the provided ProfileSSHKey
+ */
+ public Builder fromProfileSSHKey(ProfileSSHKey in) {
+ return this
+ .name(in.getName())
+ .publicKey(in.getPublicKey());
+ }
+ }
+
+ @Override
+ public int compareTo(ProfileSSHKey that) {
+ return this.getName().compareTo(that.getName());
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApi.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApi.java
new file mode 100644
index 0000000..b42e5b0
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApi.java
@@ -0,0 +1,121 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.features;
+
+import java.io.Closeable;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateCluster;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
+
+import com.google.common.collect.FluentIterable;
+
+/**
+ * The API for controlling clusters.
+ * A cluster is a group of servers (nodes). In Cloud Big Data, the servers are virtual.
+ * @author Zack Shoylev
+ */
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface ClusterApi extends Closeable {
+
+ /**
+ * Create a Cluster.
+ * Before creating a cluster, a profile has to be created.
+ * @param cluster An object containing information about the cluster to be created.
+ * @return Cluster The cluster created by this call.
+ * @see Cluster
+ * @see CreateCluster
+ */
+ @Named("Cluster:create")
+ @POST
+ @Path("/clusters")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("cluster")
+ Cluster create(@WrapWith("cluster") CreateCluster cluster);
+
+ /**
+ * List all clusters.
+ * @return A list containing information about all the clusters.
+ * @see Cluster
+ */
+ @Named("Cluster:list")
+ @GET
+ @Path("/clusters")
+ @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+ @SelectJson("clusters")
+ FluentIterable<Cluster> list();
+
+ /**
+ * Get information about a specific cluster.
+ * @param clusterId The id of the cluster queried.
+ * @return Detailed information about a specific cluster.
+ * @see Cluster
+ */
+ @Named("Cluster:get")
+ @GET
+ @Path("/clusters/{clusterId}")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("cluster")
+ Cluster get(@PathParam("clusterId") String clusterId);
+
+ /**
+ * Delete a cluster.
+ * @param clusterId The id of the cluster to be deleted.
+ * @return Detailed information about the cluster to be deleted.
+ * @see Cluster
+ */
+ @Named("Cluster:delete")
+ @DELETE
+ @Path("/clusters/{clusterId}")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("cluster")
+ Cluster delete(@PathParam("clusterId") String clusterId);
+
+ /**
+ * Resize a cluster. Changes the number of nodes for this cluster.
+ * @param clusterId The id of the cluster to be deleted.
+ * @param nodeCount The target number of cluster nodes.
+ * @return Detailed information about the cluster to be resized.
+ * @see Cluster
+ */
+ @Named("Cluster:resize")
+ @POST
+ @Path("/clusters/{clusterId}/action")
+ @WrapWith("resize")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("cluster")
+ Cluster resize(@PathParam("clusterId") String clusterId, @PayloadParam("nodeCount") int nodeCount);
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApi.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApi.java
new file mode 100644
index 0000000..a8d431c
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApi.java
@@ -0,0 +1,79 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.features;
+
+import java.io.Closeable;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateProfile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Profile;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
+
+/**
+ * The API for controlling profiles.
+ * Your Cloud Big Data profile is different from your cloud account. Your profile has the following characteristics and requirements:
+ * A profile is the configuration for the administration and login account for the cluster.
+ * Only one profile is allowed for each user or account.
+ * Any updates or additions override the existing profile.
+ * @author Zack Shoylev
+ */
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface ProfileApi extends Closeable {
+
+ /**
+ * Create a Profile.
+ * Before creating a cluster, a profile has to be created.
+ * @param profile A CreateProfile object containing information about the profile to be created.
+ * @return Profile The profile created by this call.
+ * @see Profile
+ * @see CreateProfile
+ */
+ @Named("Profile:create")
+ @POST
+ @Path("/profile")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("profile")
+ Profile create(@WrapWith("profile") CreateProfile profile);
+
+ /**
+ * This operation returns detailed profile information for the current user.
+ * Before creating a cluster, a profile has to be created.
+ * @return Detailed profile information for the current user.
+ * @see Profile
+ * @see CreateProfile
+ */
+ @Named("Profile:get")
+ @GET
+ @Path("/profile")
+ @Fallback(NullOnNotFoundOr404.class)
+ @SelectJson("profile")
+ Profile get();
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/handlers/CloudBigDataErrorHandler.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/handlers/CloudBigDataErrorHandler.java
new file mode 100644
index 0000000..76df9fe
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/handlers/CloudBigDataErrorHandler.java
@@ -0,0 +1,67 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.handlers;
+
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+import javax.inject.Singleton;
+
+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;
+import org.jclouds.rest.InsufficientResourcesException;
+import org.jclouds.rest.ResourceNotFoundException;
+
+/**
+ * This will parse and set an appropriate exception on the command object.
+ * @author Zack Shoylev
+ */
+@Singleton
+public class CloudBigDataErrorHandler implements HttpErrorHandler {
+
+ public void handleError(HttpCommand command, HttpResponse response) {
+ // it is important to always read fully and close streams
+ byte[] data = closeClientButKeepContentStream(response);
+ String message = data != null ? new String(data) : null;
+
+ Exception exception = message != null ? new HttpResponseException(command, response, message)
+ : new HttpResponseException(command, response);
+ message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
+ response.getStatusLine());
+ switch (response.getStatusCode()) {
+ case 400:
+ if (message.contains("quota exceeded"))
+ exception = new InsufficientResourcesException(message, exception);
+ break;
+ case 401:
+ case 403:
+ exception = new AuthorizationException(message, exception);
+ break;
+ case 404:
+ if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+ exception = new ResourceNotFoundException(message, exception);
+ }
+ break;
+ case 413:
+ exception = new InsufficientResourcesException(message, exception);
+ break;
+ }
+ command.setException(exception);
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/predicates/ClusterPredicates.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/predicates/ClusterPredicates.java
new file mode 100644
index 0000000..3d8e7fe
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/predicates/ClusterPredicates.java
@@ -0,0 +1,146 @@
+package org.jclouds.rackspace.cloudbigdata.v1.predicates;
+/*
+ * 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.
+ */
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.util.Predicates2.retry;
+
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster.Status;
+import org.jclouds.rackspace.cloudbigdata.v1.features.ClusterApi;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Tests to see if Cluster has reached status. This class is most useful when paired with a RetryablePredicate as
+ * in the code below. This class can be used to block execution until the Cluster status has reached a desired state.
+ * This is useful when your Cluster needs to be 100% ready before you can continue with execution.
+ *
+ * <pre>
+ * {@code
+ * Cluster Cluster = ClusterApi.create(100);
+ *
+ * RetryablePredicate<String> awaitAvailable = RetryablePredicate.create(
+ * ClusterPredicates.available(ClusterApi), 600, 10, 10, TimeUnit.SECONDS);
+ *
+ * if (!awaitAvailable.apply(Cluster.getId())) {
+ * throw new TimeoutException("Timeout on Cluster: " + Cluster);
+ * }
+ * }
+ * </pre>
+ *
+ * You can also use the static convenience methods as follows.
+ *
+ * <pre>
+ * {@code
+ * Cluster Cluster = ClusterApi.create(100);
+ *
+ * if (!ClusterPredicates.awaitAvailable(ClusterApi).apply(Cluster.getId())) {
+ * throw new TimeoutException("Timeout on Cluster: " + Cluster);
+ * }
+ * }
+ * </pre>
+ *
+ * @author Zack Shoylev
+ */
+public class ClusterPredicates {
+ /**
+ * Wait until an Cluster is Available.
+ *
+ * @param clusterApi The ClusterApi in the zone where your Cluster resides.
+ * @return RetryablePredicate That will check the status every 5 seconds for a maxiumum of 10 minutes.
+ */
+ public static Predicate<Cluster> awaitAvailable(ClusterApi clusterApi) {
+ StatusUpdatedPredicate statusPredicate = new StatusUpdatedPredicate(clusterApi, Cluster.Status.ACTIVE);
+ return retry(statusPredicate, 600, 5, 5, SECONDS);
+ }
+
+ /**
+ * Wait until an Cluster no longer exists.
+ *
+ * @param clusterApi The ClusterApi in the zone where your Cluster resides.
+ * @return RetryablePredicate That will check whether the Cluster exists.
+ * every 5 seconds for a maximum of 10 minutes.
+ */
+ public static Predicate<Cluster> awaitDeleted(ClusterApi clusterApi) {
+ DeletedPredicate deletedPredicate = new DeletedPredicate(clusterApi);
+ return retry(deletedPredicate, 600, 5, 5, SECONDS);
+ }
+
+ /**
+ * Wait until Cluster is in the status specified.
+ *
+ * @param clusterApi The ClusterApi in the zone where your Cluster resides.
+ * @param status Wait until Cluster in in this status.
+ * @param maxWaitInSec Maximum time to wait.
+ * @param periodInSec Interval between retries.
+ * @return RetryablePredicate That will check whether the Cluster exists.
+ */
+ public static Predicate<Cluster> awaitStatus(
+ ClusterApi clusterApi, Cluster.Status status, long maxWaitInSec, long periodInSec) {
+ StatusUpdatedPredicate statusPredicate = new StatusUpdatedPredicate(clusterApi, status);
+ return retry(statusPredicate, maxWaitInSec, periodInSec, periodInSec, SECONDS);
+ }
+
+ private static class StatusUpdatedPredicate implements Predicate<Cluster> {
+ private ClusterApi clusterApi;
+ private Status status;
+
+ public StatusUpdatedPredicate(ClusterApi clusterApi, Cluster.Status status) {
+ this.clusterApi = checkNotNull(clusterApi, "ClusterApi must be defined");
+ this.status = checkNotNull(status, "status must be defined");
+ }
+
+ /**
+ * @return boolean Return true when the Cluster reaches status, false otherwise.
+ */
+ @Override
+ public boolean apply(Cluster cluster) {
+ checkNotNull(cluster, "Cluster must be defined");
+
+ if (status.equals(cluster.getStatus())) {
+ return true;
+ }
+ else {
+ Cluster ClusterUpdated = clusterApi.get(cluster.getId());
+ checkNotNull(ClusterUpdated, "Cluster %s not found.", cluster.getId());
+
+ return status.equals(ClusterUpdated.getStatus());
+ }
+ }
+ }
+
+ private static class DeletedPredicate implements Predicate<Cluster> {
+ private ClusterApi clusterApi;
+
+ public DeletedPredicate(ClusterApi clusterApi) {
+ this.clusterApi = checkNotNull(clusterApi, "ClusterApi must be defined");
+ }
+
+ /**
+ * @return boolean Return true when the snapshot is deleted, false otherwise.
+ */
+ @Override
+ public boolean apply(Cluster cluster) {
+ checkNotNull(cluster, "Cluster must be defined");
+
+ return clusterApi.get(cluster.getId()) == null;
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/utils/CloudBigDataUtils.java b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/utils/CloudBigDataUtils.java
new file mode 100644
index 0000000..4dcd013
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/java/org/jclouds/rackspace/cloudbigdata/v1/utils/CloudBigDataUtils.java
@@ -0,0 +1,25 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.utils;
+
+/**
+ * @author Zack Shoylev
+ *
+ */
+public class CloudBigDataUtils {
+
+}
diff --git a/rackspace-cloudbigdata/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/rackspace-cloudbigdata/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
new file mode 100644
index 0000000..24df0eb
--- /dev/null
+++ b/rackspace-cloudbigdata/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApiMetadata
diff --git a/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApiLiveTest.java b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApiLiveTest.java
new file mode 100644
index 0000000..7e7a738
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApiLiveTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster.Status;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateCluster;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateProfile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Profile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.ProfileSSHKey;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateCluster.ClusterType;
+import org.jclouds.rackspace.cloudbigdata.v1.internal.BaseCloudBigDataApiLiveTest;
+import org.jclouds.rackspace.cloudbigdata.v1.predicates.ClusterPredicates;
+import org.jclouds.ssh.SshKeys;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Profile live test
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "live", testName = "ProfileApiLiveTest", singleThreaded = true)
+@SuppressWarnings("javadoc")
+public class ClusterApiLiveTest extends BaseCloudBigDataApiLiveTest {
+
+ @Override
+ @BeforeClass(groups = { "integration", "live" })
+ public void setup() {
+ super.setup();
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ClusterApi clusterApi = api.getClusterApiForZone(zone);
+
+ CreateCluster createCluster = null;
+ try {
+ // A Profile must exist before a cluster is created.
+
+ ProfileApi profileApi = api.getProfileApiForZone(zone);
+
+ CreateProfile createProfile = CreateProfile.builder()
+ .username("john.doe")
+ .password("1Aa+" + UUID.randomUUID().toString())
+ .sshKeys(ImmutableList.of(ProfileSSHKey.builder().name("t@test")
+ .publicKey(SshKeys.generate().get("public"))
+ .build()))
+ .credentialsUsername("jdoe")
+ .credentialsApiKey(UUID.randomUUID().toString())
+ .build();
+
+ Profile profile = profileApi.create(createProfile);
+
+ assertNotNull(profile);
+ assertEquals(profile.getUsername(),"john.doe");
+ assertEquals(profile.getSSHKeys().get(0).getName(),"t@test");
+ assertEquals(profile.getCredentialsUsername(),"jdoe");
+ assertNull(profile.getCredentialsApiKey());
+
+ createCluster = CreateCluster.builder()
+ .name("slice")
+ .clusterType(ClusterType.HADOOP_HDP1_3.name())
+ .flavorId("hadoop1-7")
+ .nodeCount(1)
+ .postInitScript(new URI("http://example.com/configure_cluster.sh"))
+ .build();
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ fail("Unexpected URI exception");
+ }
+
+ Cluster cluster = clusterApi.create(createCluster);
+ ClusterPredicates.awaitAvailable(clusterApi).apply(cluster);
+ cluster = clusterApi.get(cluster.getId()); // update cluster for status
+
+ assertNotNull(cluster);
+ assertNotNull(cluster.getId());
+ assertNotNull(cluster.getCreated());
+ assertEquals(cluster.getName(), "slice");
+ assertEquals(cluster.getClusterType(), ClusterType.HADOOP_HDP1_3.name());
+ assertEquals(cluster.getFlavorId(), "hadoop1-7");
+ assertEquals(cluster.getNodeCount(), 1);
+ assertEquals(cluster.getPostInitScriptStatus(), "PENDING");
+ assertTrue(cluster.getProgress() >= 0.0F);
+ assertEquals(cluster.getStatus(), Status.ACTIVE);
+ }
+ }
+
+ @Test
+ public void getCluster() {
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ClusterApi clusterApi = api.getClusterApiForZone(zone);
+
+ Cluster clusterFromList = clusterApi.list().get(0);
+ Cluster clusterFromGet = clusterApi.get(clusterFromList.getId());
+ assertNotNull(clusterFromGet.getId());
+ assertNotNull(clusterFromGet.getName());
+ assertEquals(clusterFromGet, clusterFromList);
+ }
+ }
+
+ @Test
+ public void resizeCluster() {
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ClusterApi clusterApi = api.getClusterApiForZone(zone);
+
+ Cluster cluster = clusterApi.list().get(0);
+ Cluster clusterResized = clusterApi.resize(cluster.getId(), 2);
+ ClusterPredicates.awaitAvailable(clusterApi).apply(cluster);
+ cluster = clusterApi.get(cluster.getId()); // update cluster for status
+
+ assertEquals(clusterResized.getNodeCount(), 2);
+ }
+ }
+
+ @Override
+ @AfterClass(groups = { "integration", "live" })
+ public void tearDown() {
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ClusterApi clusterApi = api.getClusterApiForZone(zone);
+ for(Cluster cluster : clusterApi.list()) {
+ ClusterPredicates.awaitAvailable(clusterApi).apply(cluster);
+ clusterApi.delete(cluster.getId());
+ }
+ }
+ super.tearDown();
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApiMockTest.java b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApiMockTest.java
new file mode 100644
index 0000000..bb13ded
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ClusterApiMockTest.java
@@ -0,0 +1,387 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.TimeZone;
+
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApi;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Cluster.Status;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateCluster;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateCluster.ClusterType;
+import org.jclouds.rackspace.cloudbigdata.v1.internal.BaseCloudBigDataApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Tests ProfileApi Guice wiring and parsing
+ *
+ * @author Zack Shoylev
+ */
+@SuppressWarnings("javadoc")
+@Test
+public class ClusterApiMockTest extends BaseCloudBigDataApiMockTest {
+
+ public void testCreateCluster() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/cluster_create_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ CreateCluster createCluster = CreateCluster.builder()
+ .name("slice")
+ .clusterType(ClusterType.HADOOP_HDP1_1.name())
+ .flavorId("4fba3bca-7c76-11e2-b737-beeffa00040e")
+ .nodeCount(5)
+ .postInitScript(new URI("http://example.com/configure_cluster.sh"))
+ .build();
+
+ Cluster cluster = api.create(createCluster);
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", "/v1.0/888888/clusters", "/cluster_create_request.json");
+
+ /*
+ * Check response
+ */
+ assertNotNull(cluster);
+ assertEquals(cluster.getId(), "db478fc1-2d86-4597-8010-cbe787bbbc41");
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
+ assertEquals(cluster.getCreated().toString(), "Thu Dec 27 10:10:10 GMT+00:00 2012");
+ assertEquals(cluster.getUpdated().toString(), "Fri Dec 27 10:10:10 GMT+00:00 2013");
+ assertEquals(cluster.getName(), "slice");
+ assertEquals(cluster.getClusterType(), ClusterType.HADOOP_HDP1_1.name());
+ assertEquals(cluster.getFlavorId(), "4fba3bca-7c76-11e2-b737-beeffa00040e");
+ assertEquals(cluster.getNodeCount(), 5);
+ assertEquals(cluster.getPostInitScriptStatus().toString(), "PENDING");
+ assertEquals(cluster.getProgress(), 0.0F);
+ assertEquals(cluster.getStatus(), Status.BUILDING);
+ assertEquals(cluster.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testCreateClusterFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/cluster_create_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ CreateCluster createCluster = CreateCluster.builder()
+ .name("slice")
+ .clusterType(ClusterType.HADOOP_HDP1_1.name())
+ .flavorId("4fba3bca-7c76-11e2-b737-beeffa00040e")
+ .nodeCount(5)
+ .postInitScript(new URI("http://example.com/configure_cluster.sh"))
+ .build();
+
+ Cluster cluster = api.create(createCluster);
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", "/v1.0/888888/clusters", "/cluster_create_request.json");
+
+ /*
+ * Check response
+ */
+ assertNull(cluster);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetCluster() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/cluster_get_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ Cluster cluster = api.get("5");
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", "/v1.0/888888/clusters/5");
+
+ /*
+ * Check response
+ */
+ assertNotNull(cluster);
+ assertEquals(cluster.getId(), "db478fc1-2d86-4597-8010-cbe787bbbc41");
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
+ assertEquals(cluster.getCreated().toString(), "Thu Dec 27 10:10:10 GMT+00:00 2012");
+ assertEquals(cluster.getUpdated().toString(), "Fri Dec 27 10:10:10 GMT+00:00 2013");
+ assertEquals(cluster.getName(), "slice");
+ assertEquals(cluster.getClusterType(), ClusterType.HADOOP_HDP1_1.name());
+ assertEquals(cluster.getFlavorId(), "4fba3bca-7c76-11e2-b737-beeffa00040e");
+ assertEquals(cluster.getNodeCount(), 5);
+ assertEquals(cluster.getPostInitScriptStatus().toString(), "PENDING");
+ assertEquals(cluster.getProgress(), 1.0F);
+ assertEquals(cluster.getStatus(), Status.ACTIVE);
+ assertEquals(cluster.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetClusterFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/cluster_get_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ Cluster cluster = api.get("5");
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", "/v1.0/888888/clusters/5");
+
+ /*
+ * Check response
+ */
+ assertNull(cluster);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListClusters() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/cluster_list_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ FluentIterable<Cluster> clusters = api.list();
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", "/v1.0/888888/clusters");
+
+ /*
+ * Check response
+ */
+ assertNotNull(clusters);
+ assertEquals(clusters.size(), 2);
+ Cluster cluster = clusters.get(0);
+ assertEquals(cluster.getId(), "db478fc1-2d86-4597-8010-cbe787bbbc41");
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
+ assertEquals(cluster.getCreated().toString(), "Thu Dec 27 10:10:10 GMT+00:00 2012");
+ assertEquals(cluster.getUpdated().toString(), "Fri Dec 27 10:10:10 GMT+00:00 2013");
+ assertEquals(cluster.getName(), "slice");
+ assertEquals(cluster.getClusterType(), ClusterType.HADOOP_HDP1_1.name());
+ assertEquals(cluster.getFlavorId(), "4fba3bca-7c76-11e2-b737-beeffa00040e");
+ assertEquals(cluster.getNodeCount(), 5);
+ assertEquals(cluster.getPostInitScriptStatus().toString(), "SUCCEEDED");
+ assertEquals(cluster.getProgress(), 1.0F);
+ assertEquals(cluster.getStatus(), Status.ACTIVE);
+ assertEquals(cluster.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListClustersFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/cluster_list_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ FluentIterable<Cluster> clusters = api.list();
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", "/v1.0/888888/clusters");
+
+ /*
+ * Check response
+ */
+ assertNotNull(clusters);
+ assertEquals(clusters.size(), 0);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testDeleteCluster() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/cluster_delete_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ Cluster cluster = api.delete("5");
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "DELETE", "/v1.0/888888/clusters/5");
+
+ /*
+ * Check response
+ */
+ assertNotNull(cluster);
+ assertEquals(cluster.getId(), "db478fc1-2d86-4597-8010-cbe787bbbc41");
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
+ assertEquals(cluster.getCreated().toString(), "Thu Dec 27 10:10:10 GMT+00:00 2012");
+ assertEquals(cluster.getUpdated().toString(), "Fri Dec 27 10:10:10 GMT+00:00 2013");
+ assertEquals(cluster.getName(), "slice");
+ assertEquals(cluster.getClusterType(), ClusterType.HADOOP_HDP1_1.name());
+ assertEquals(cluster.getFlavorId(), "4fba3bca-7c76-11e2-b737-beeffa00040e");
+ assertEquals(cluster.getNodeCount(), 5);
+ assertEquals(cluster.getPostInitScriptStatus(), null);
+ assertEquals(cluster.getProgress(), 0.0F);
+ assertEquals(cluster.getStatus(), Status.DELETING);
+ assertEquals(cluster.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testDeleteClusterFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/cluster_delete_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ Cluster cluster = api.delete("5");
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "DELETE", "/v1.0/888888/clusters/5");
+
+ /*
+ * Check response
+ */
+ assertNull(cluster);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testResizeCluster() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/cluster_resize_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ Cluster cluster = api.resize("5", 10);
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", "/v1.0/888888/clusters/5/action", "/cluster_resize_request.json");
+
+ /*
+ * Check response
+ */
+ assertNotNull(cluster);
+ assertEquals(cluster.getId(), "db478fc1-2d86-4597-8010-cbe787bbbc41");
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT+0"));
+ assertEquals(cluster.getCreated().toString(), "Thu Dec 27 10:10:10 GMT+00:00 2012");
+ assertEquals(cluster.getUpdated().toString(), "Fri Dec 27 10:10:10 GMT+00:00 2013");
+ assertEquals(cluster.getName(), "slice");
+ assertEquals(cluster.getClusterType(), ClusterType.HADOOP_HDP1_1.name());
+ assertEquals(cluster.getFlavorId(), "4fba3bca-7c76-11e2-b737-beeffa00040e");
+ assertEquals(cluster.getNodeCount(), 10);
+ assertEquals(cluster.getPostInitScriptStatus().toString(), "PENDING");
+ assertEquals(cluster.getProgress(), 0.5F);
+ assertEquals(cluster.getStatus(), Status.UPDATING);
+ assertEquals(cluster.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testResizeClusterFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/cluster_resize_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ClusterApi api = cbdApi.getClusterApiForZone("ORD");
+
+ Cluster cluster = api.resize("5", 10);
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", "/v1.0/888888/clusters/5/action", "/cluster_resize_request.json");
+
+ /*
+ * Check response
+ */
+ assertNull(cluster);
+ } finally {
+ server.shutdown();
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApiLiveTest.java b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApiLiveTest.java
new file mode 100644
index 0000000..8151c14
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApiLiveTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.util.UUID;
+
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateProfile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Profile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.ProfileSSHKey;
+import org.jclouds.rackspace.cloudbigdata.v1.internal.BaseCloudBigDataApiLiveTest;
+import org.jclouds.ssh.SshKeys;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Profile live test
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "live", testName = "ProfileApiLiveTest", singleThreaded = true)
+@SuppressWarnings("javadoc")
+public class ProfileApiLiveTest extends BaseCloudBigDataApiLiveTest {
+
+ @Override
+ @BeforeClass(groups = { "integration", "live" })
+ public void setup() {
+ super.setup();
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ProfileApi profileApi = api.getProfileApiForZone(zone);
+
+ CreateProfile createProfile = CreateProfile.builder()
+ .username("john.doe")
+ .password("1Aa+" + UUID.randomUUID().toString())
+ .sshKeys(ImmutableList.of(ProfileSSHKey.builder().name("t@test")
+ .publicKey(SshKeys.generate().get("public"))
+ .build()))
+ .credentialsUsername("jdoe")
+ .credentialsApiKey(UUID.randomUUID().toString())
+ .build();
+
+ Profile profile = profileApi.create(createProfile);
+
+ assertNotNull(profile);
+ assertEquals(profile.getUsername(),"john.doe");
+ assertEquals(profile.getSSHKeys().get(0).getName(),"t@test");
+ assertEquals(profile.getCredentialsUsername(),"jdoe");
+ assertNull(profile.getCredentialsApiKey());
+ }
+ }
+
+ @Test
+ public void updateProfile() {
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ProfileApi profileApi = api.getProfileApiForZone(zone);
+
+ CreateProfile createProfile = CreateProfile.builder()
+ .username("john.doe2")
+ .password("1Aa+" + UUID.randomUUID().toString())
+ .sshKeys(ImmutableList.of(ProfileSSHKey.builder().name("t@test")
+ .publicKey(SshKeys.generate().get("public"))
+ .build()))
+ .credentialsUsername("jdoe")
+ .credentialsApiKey(UUID.randomUUID().toString())
+ .build();
+
+ Profile profile = profileApi.create(createProfile);
+
+ assertNotNull(profile);
+ assertEquals(profile.getUsername(),"john.doe2");
+ assertEquals(profile.getSSHKeys().get(0).getName(),"t@test");
+ assertEquals(profile.getCredentialsUsername(),"jdoe");
+ }
+ }
+
+ @Test
+ public void getProfile() {
+ for (String zone : filterZones(api.getConfiguredZones())) {
+ ProfileApi profileApi = api.getProfileApiForZone(zone);
+
+ Profile profile = profileApi.get();
+
+ assertNotNull(profile);
+ assertEquals(profile.getSSHKeys().get(0).getName(),"t@test");
+ assertEquals(profile.getCredentialsUsername(),"jdoe");
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApiMockTest.java b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApiMockTest.java
new file mode 100644
index 0000000..5b88156
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/features/ProfileApiMockTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.rackspace.cloudbigdata.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApi;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.CreateProfile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.Profile;
+import org.jclouds.rackspace.cloudbigdata.v1.domain.ProfileSSHKey;
+import org.jclouds.rackspace.cloudbigdata.v1.internal.BaseCloudBigDataApiMockTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Tests ProfileApi Guice wiring and parsing
+ *
+ * @author Zack Shoylev
+ */
+@SuppressWarnings("javadoc")
+@Test
+public class ProfileApiMockTest extends BaseCloudBigDataApiMockTest {
+
+ public void testCreateProfile() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/profile_create_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ProfileApi api = cbdApi.getProfileApiForZone("ORD");
+
+ CreateProfile createProfile = CreateProfile.builder()
+ .username("john.doe")
+ .password("j0Hnd03")
+ .sshKeys(ImmutableList.of(ProfileSSHKey.builder().name("t@test")
+ .publicKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtUFnkFrqDDCgEqW1akQkpMOX\n" +
+ "Owwvg73PLn5Z5QgvxjvJhRCg9ZTR/OWXpWcYqFVNagH4Zs8NOb9921TyQ+ydMnatOM\n" +
+ "haxMh1ZwTgaUcvndOF8fY+kcERiw1l0iT95w42F8IdUH42Z+8KihZM8gVsbMS6qYTi\n" +
+ "OM29WHX7y37wuJIzqf3N2TiVXrqfjwugvY/bZ+47EUn78uk6aPZYJGXdDgaFqnIXUV\n" +
+ "N+hRFYXgKnU0Ui0aQkuYwnAW8KmanLoNU2xodrb6/XqWnSAAmwl7aoGKFunQsT6xDW\n" +
+ "yQk+ncUHUcdofDUqgd3lXmHGrTmQW97vqexDEnhsJ+AwbLGD5dukr t@test")
+ .build()))
+ .credentialsUsername("jdoe")
+ .credentialsApiKey("df23gkh34h52gkdgfakgf")
+ .build();
+
+ Profile profile = api.create(createProfile);
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", "/v1.0/888888/profile", "/profile_create_request.json");
+
+ /*
+ * Check response
+ */
+ assertNotNull(profile);
+ assertEquals(profile.getUsername(),"john.doe");
+ assertEquals(profile.getUserId(),"12346");
+ assertEquals(profile.getTenantId(),"123456");
+ assertEquals(profile.getSSHKeys().get(0).getName(),"t@test");
+ assertEquals(profile.getSSHKeys().get(0).getPublicKey(),"ssh-rsa .....");
+ assertEquals(profile.getCredentialsUsername(),"jdoe");
+ assertNull(profile.getCredentialsApiKey());
+ assertEquals(profile.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/123456/profile"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testCreateProfileFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/profile_create_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ProfileApi api = cbdApi.getProfileApiForZone("ORD");
+
+ CreateProfile createProfile = CreateProfile.builder()
+ .username("john.doe")
+ .password("j0Hnd03")
+ .sshKeys(ImmutableList.of(ProfileSSHKey.builder().name("t@test")
+ .publicKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtUFnkFrqDDCgEqW1akQkpMOX\n" +
+ "Owwvg73PLn5Z5QgvxjvJhRCg9ZTR/OWXpWcYqFVNagH4Zs8NOb9921TyQ+ydMnatOM\n" +
+ "haxMh1ZwTgaUcvndOF8fY+kcERiw1l0iT95w42F8IdUH42Z+8KihZM8gVsbMS6qYTi\n" +
+ "OM29WHX7y37wuJIzqf3N2TiVXrqfjwugvY/bZ+47EUn78uk6aPZYJGXdDgaFqnIXUV\n" +
+ "N+hRFYXgKnU0Ui0aQkuYwnAW8KmanLoNU2xodrb6/XqWnSAAmwl7aoGKFunQsT6xDW\n" +
+ "yQk+ncUHUcdofDUqgd3lXmHGrTmQW97vqexDEnhsJ+AwbLGD5dukr t@test")
+ .build()))
+ .credentialsUsername("jdoe")
+ .credentialsApiKey("df23gkh34h52gkdgfakgf")
+ .build();
+
+ Profile profile = api.create(createProfile);
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", "/v1.0/888888/profile", "/profile_create_request.json");
+
+ /*
+ * Check response
+ */
+ assertNull(profile);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetProfile() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(201).setBody(stringFromResource("/profile_get_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ProfileApi api = cbdApi.getProfileApiForZone("ORD");
+ Profile profile = api.get();
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", "/v1.0/888888/profile");
+
+ /*
+ * Check response
+ */
+ assertNotNull(profile);
+ assertEquals(profile.getUsername(),"john.doe");
+ assertEquals(profile.getUserId(),"12346");
+ assertEquals(profile.getTenantId(),"123456");
+ assertEquals(profile.getSSHKeys().get(0).getName(),"t@test");
+ assertEquals(profile.getSSHKeys().get(0).getPublicKey(),"ssh-rsa .....");
+ assertEquals(profile.getCredentialsUsername(),"jdoe");
+ assertNull(profile.getCredentialsApiKey());
+ assertEquals(profile.getLinks().get(0).getHref(), new URI("https://dfw.bigdata.api.rackspacecloud.com/v1.0/123456/profile"));
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetProfileFail() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404).setBody(stringFromResource("/profile_get_response.json"))));
+
+ try {
+ CloudBigDataApi cbdApi = api(server.getUrl("/").toString(), "rackspace-cloudbigdata", overrides);
+ ProfileApi api = cbdApi.getProfileApiForZone("ORD");
+ Profile profile = api.get();
+
+ /*
+ * Check request
+ */
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", "/v1.0/888888/profile");
+
+ /*
+ * Check response
+ */
+ assertNull(profile);
+ } finally {
+ server.shutdown();
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/internal/BaseCloudBigDataApiLiveTest.java b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/internal/BaseCloudBigDataApiLiveTest.java
new file mode 100644
index 0000000..8457d05
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/internal/BaseCloudBigDataApiLiveTest.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.rackspace.cloudbigdata.v1.internal;
+
+import java.util.Properties;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApi;
+
+/**
+ * Tests behavior of CLoud Big Data live.
+ *
+ * @author Zack Shoylev
+ */
+public class BaseCloudBigDataApiLiveTest extends BaseApiLiveTest<CloudBigDataApi> {
+
+ /**
+ * Base Live Test
+ */
+ public BaseCloudBigDataApiLiveTest() {
+ provider = "rackspace-cloudbigdata";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE);
+ setIfTestSystemPropertyPresent(props, KeystoneProperties.SERVICE_TYPE);
+ return props;
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/internal/BaseCloudBigDataApiMockTest.java b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/internal/BaseCloudBigDataApiMockTest.java
new file mode 100644
index 0000000..2055256
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/java/org/jclouds/rackspace/cloudbigdata/v1/internal/BaseCloudBigDataApiMockTest.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.rackspace.cloudbigdata.v1.internal;
+
+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.util.Properties;
+
+import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
+import org.jclouds.openstack.v2_0.internal.BaseOpenStackMockTest;
+import org.jclouds.rackspace.cloudbigdata.v1.CloudBigDataApi;
+
+/**
+ * Base class for writing Cloud Big Data Expect tests
+ *
+ * @author Zack Shoylev
+ */
+public class BaseCloudBigDataApiMockTest extends BaseOpenStackMockTest<CloudBigDataApi> {
+ protected Properties overrides;
+ /**
+ * Base Mock Test
+ */
+ public BaseCloudBigDataApiMockTest() {
+ overrides = new Properties();
+ overrides.setProperty(SERVICE_TYPE, "rax:bigdata");
+ overrides.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/access.json b/rackspace-cloudbigdata/src/test/resources/access.json
new file mode 100644
index 0000000..fc24d20
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/access.json
@@ -0,0 +1,260 @@
+{
+ "access":{
+ "token":{
+ "id":"bb03a23aa8271291a7aaa9aaa2aaaaaa",
+ "expires":"2013-08-02T16:55:24.229-05:00",
+ "tenant":{
+ "id":"888888",
+ "name":"888888"
+ },
+ "RAX-AUTH:authenticatedBy":[
+ "PASSWORD"
+ ]
+ },
+ "serviceCatalog":[
+ {
+ "name":"cloudFilesCDN",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"SYD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ }
+ ],
+ "type":"rax:object-cdn"
+ },
+ {
+ "name":"cloudBigData",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:bigdata"
+ },
+ {
+ "name":"cloudFiles",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "internalURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "internalURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ },
+ {
+ "region":"SYD",
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "publicURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "internalURL":"URL/v1\/MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c"
+ }
+ ],
+ "type":"object-store"
+ },
+ {
+ "name":"cloudLoadBalancers",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:load-balancer"
+ },
+ {
+ "name":"cloudDatabases",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:database"
+ },
+ {
+ "name":"cloudBlockStorage",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1\/888888"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"URL/v1\/888888"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1\/888888"
+ }
+ ],
+ "type":"volume"
+ },
+ {
+ "name":"cloudServersOpenStack",
+ "endpoints":[
+ {
+ "region":"SYD",
+ "tenantId":"888888",
+ "publicURL":"URL/v2\/888888",
+ "versionInfo":"https:\/\/syd.servers.api.rackspacecloud.com\/v2",
+ "versionList":"https:\/\/syd.servers.api.rackspacecloud.com\/",
+ "versionId":"2"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"URL/v2\/888888",
+ "versionInfo":"https:\/\/dfw.servers.api.rackspacecloud.com\/v2",
+ "versionList":"https:\/\/dfw.servers.api.rackspacecloud.com\/",
+ "versionId":"2"
+ },
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v2\/888888",
+ "versionInfo":"https:\/\/ord.servers.api.rackspacecloud.com\/v2",
+ "versionList":"https:\/\/ord.servers.api.rackspacecloud.com\/",
+ "versionId":"2"
+ }
+ ],
+ "type":"compute"
+ },
+ {
+ "name":"autoscale",
+ "endpoints":[
+ {
+ "region":"ORD",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888",
+ "versionInfo":null,
+ "versionList":null,
+ "versionId":"1.0"
+ },
+ {
+ "region":"DFW",
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888",
+ "versionInfo":null,
+ "versionList":null,
+ "versionId":"1.0"
+ }
+ ],
+ "type":"rax:autoscale"
+ },
+ {
+ "name":"cloudMonitoring",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:monitor"
+ },
+ {
+ "name":"cloudBackup",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:backup"
+ },
+ {
+ "name":"cloudServers",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888",
+ "versionInfo":"https:\/\/servers.api.rackspacecloud.com\/v1.0",
+ "versionList":"https:\/\/servers.api.rackspacecloud.com\/",
+ "versionId":"1.0"
+ }
+ ],
+ "type":"compute"
+ },
+ {
+ "name":"cloudDNS",
+ "endpoints":[
+ {
+ "tenantId":"888888",
+ "publicURL":"URL/v1.0\/888888"
+ }
+ ],
+ "type":"rax:dns"
+ }
+ ],
+ "user":{
+ "id":"335853",
+ "roles":[
+ {
+ "id":"10000150",
+ "description":"Checkmate Access role",
+ "name":"checkmate"
+ },
+ {
+ "tenantId":"MossoCloudFS_0d629063-aa0f-4bf9-9e04-62e1fd6aaa2c",
+ "id":"5",
+ "description":"A Role that allows a user access to keystone Service methods",
+ "name":"object-store:default"
+ },
+ {
+ "tenantId":"888888",
+ "id":"6",
+ "description":"A Role that allows a user access to keystone Service methods",
+ "name":"compute:default"
+ },
+ {
+ "id":"3",
+ "description":"User Admin Role.",
+ "name":"identity:user-admin"
+ }
+ ],
+ "name":"test",
+ "RAX-AUTH:defaultRegion":"ORD"
+ }
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_create_request.json b/rackspace-cloudbigdata/src/test/resources/cluster_create_request.json
new file mode 100644
index 0000000..fe479d1
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_create_request.json
@@ -0,0 +1,8 @@
+{"cluster":
+ { "name": "slice",
+ "clusterType": "HADOOP_HDP1_1",
+ "flavorId": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 5,
+ "postInitScript" : "http://example.com/configure_cluster.sh"
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_create_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_create_response.json
new file mode 100644
index 0000000..db659e7
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_create_response.json
@@ -0,0 +1,21 @@
+{"cluster":
+ { "id": "db478fc1-2d86-4597-8010-cbe787bbbc41",
+ "created": "2012-12-27T10:10:10Z",
+ "updated": "2013-12-27T10:10:10Z",
+ "name": "slice",
+ "clusterType": "HADOOP_HDP1_1",
+ "flavorId": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 5,
+ "postInitScriptStatus": "PENDING",
+ "progress": 0.0,
+ "status": "BUILDING",
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_delete_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_delete_response.json
new file mode 100644
index 0000000..ccdb911
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_delete_response.json
@@ -0,0 +1,20 @@
+{"cluster":
+ { "id": "db478fc1-2d86-4597-8010-cbe787bbbc41",
+ "created": "2012-12-27T10:10:10Z",
+ "updated": "2013-12-27T10:10:10Z",
+ "name": "slice",
+ "clusterType": "HADOOP_HDP1_1",
+ "flavorId": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 5,
+ "postInitScriptStatus": null,
+ "status": "DELETING",
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_get_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_get_response.json
new file mode 100644
index 0000000..b92dd65
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_get_response.json
@@ -0,0 +1,21 @@
+{"cluster":
+ { "id": "db478fc1-2d86-4597-8010-cbe787bbbc41",
+ "created": "2012-12-27T10:10:10Z",
+ "updated": "2013-12-27T10:10:10Z",
+ "name": "slice",
+ "clusterType": "HADOOP_HDP1_1",
+ "flavorId": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 5,
+ "postInitScriptStatus": "PENDING",
+ "progress": 1.0,
+ "status": "ACTIVE",
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_list_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_list_response.json
new file mode 100644
index 0000000..e0472f8
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_list_response.json
@@ -0,0 +1,42 @@
+{"clusters":
+ [
+ { "id": "db478fc1-2d86-4597-8010-cbe787bbbc41",
+ "name": "slice",
+ "created": "2012-12-27T10:10:10Z",
+ "updated": "2013-12-27T10:10:10Z",
+ "clusterType": "HADOOP_HDP1_1",
+ "flavorId": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 5,
+ "postInitScriptStatus": "SUCCEEDED",
+ "progress": 1.0,
+ "status": "ACTIVE",
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ }
+ ]
+ },
+ { "id": "ac111111-2d86-4597-8010-cbe787bbbc41",
+ "name": "real",
+ "created": "2012-12-27T10:10:10Z",
+ "updated": "2012-12-27T10:15:10Z",
+ "clusterType": "HBASE_HDP1_1",
+ "flavorId": "518400b2-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 20,
+ "postInitScriptStatus": null,
+ "progress": 1.0,
+ "status": "ACTIVE",
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/ac111111-2d86-4597-8010-cbe787bbbc41"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/ac111111-2d86-4597-8010-cbe787bbbc41"
+ }
+ ]
+ }
+ ]
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_node_get_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_node_get_response.json
new file mode 100644
index 0000000..2421fb9
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_node_get_response.json
@@ -0,0 +1,28 @@
+{"node":
+ { "id": "000",
+ "created": "2012-12-27T10:10:10Z",
+ "role": "NAMENODE",
+ "name": "NAMENODE-1",
+ "postInitScriptStatus": null,
+ "status": "ACTIVE",
+ "addresses": {
+ "public": [{ "addr": "168.x.x.3", "version": 4 }],
+ "private": [{ "addr": "10.x.x.3", "version": 4}]
+ },
+ "services": [
+ { "name": "datanode" },
+ { "name": "tasktracker" },
+ { "name": "ssh",
+ "uri": "ssh://user@168.x.x.3"
+ }
+ ],
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/000"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/000"
+ }
+ ],
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_node_list_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_node_list_response.json
new file mode 100644
index 0000000..5be471a
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_node_list_response.json
@@ -0,0 +1,111 @@
+{"nodes":
+ [
+ { "id": "000",
+ "created": "2012-12-27T10:10:10Z",
+ "role": "NAMENODE",
+ "name": "NAMENODE-1",
+ "postInitScriptStatus": null,
+ "status": "ACTIVE",
+ "addresses": {
+ "public": [{ "addr": "168.x.x.3", "version": 4 }],
+ "private": [{ "addr": "10.x.x.3", "version": 4}]
+ },
+ "services": [
+ { "name": "namenode" },
+ { "name": "jobtracker" },
+ { "name": "ssh",
+ "uri": "ssh://user@168.x.x.3"
+ }
+ ],
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/000"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/000"
+ }
+ ],
+ },
+ { "id": "aaa",
+ "role": "GATEWAY",
+ "name": "GATEWAY-1",
+ "postInitScriptStatus": null,
+ "status": "ACTIVE",
+ "addresses": {
+ "public": [{ "addr": "168.x.x.4", "version": 4 }],
+ "private": [{ "addr": "10.x.x.4", "version": 4}]
+ },
+ "services": [
+ { "name": "pig" },
+ { "name": "hive" },
+ { "name": "ssh",
+ "uri": "ssh://user@168.x.x.4"
+ },
+ { "name": "status",
+ "uri": "http://10.x.x.4"
+ },
+ { "name": "hdfs-scp",
+ "uri": "scp://user@168.x.x.4:9022"
+ }
+ ],
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/aaa"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/aaa"
+ }
+ ],
+ },
+ { "id": "bbb",
+ "role": "DATANODE",
+ "name": "DATANODE-1",
+ "postInitScriptStatus": null,
+ "status": "ACTIVE",
+ "addresses": {
+ "public": [{ "addr": "168.x.x.5", "version": 4 }],
+ "private": [{ "addr": "10.x.x.5", "version": 4}]
+ },
+ "services": [
+ { "name": "datanode" },
+ { "name": "tasktracker" },
+ { "name": "ssh",
+ "uri": "ssh://user@168.x.x.5"
+ }
+ ],
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/bbb"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/bbb"
+ }
+ ],
+ },
+ { "id": "ccc",
+ "role": "DATANODE",
+ "name": "DATANODE-2",
+ "postInitScriptStatus": null,
+ "status": "ACTIVE",
+ "addresses": {
+ "public": [{ "addr": "168.x.x.6", "version": 4 }],
+ "private": [{ "addr": "10.x.x.6", "version": 4}]
+ },
+ "services": [
+ { "name": "datanode" },
+ { "name": "tasktracker" },
+ { "name": "ssh",
+ "uri": "ssh://user@168.x.x.6"
+ }
+ ],
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/ccc"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41/nodes/ccc"
+ }
+ ],
+ }
+ ]
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_resize_request.json b/rackspace-cloudbigdata/src/test/resources/cluster_resize_request.json
new file mode 100644
index 0000000..0a965b5
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_resize_request.json
@@ -0,0 +1,4 @@
+{"resize":
+ { "nodeCount": 10
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/cluster_resize_response.json b/rackspace-cloudbigdata/src/test/resources/cluster_resize_response.json
new file mode 100644
index 0000000..31292a2
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/cluster_resize_response.json
@@ -0,0 +1,21 @@
+{"cluster":
+ { "id": "db478fc1-2d86-4597-8010-cbe787bbbc41",
+ "created": "2012-12-27T10:10:10Z",
+ "updated": "2013-12-27T10:10:10Z",
+ "name": "slice",
+ "clusterType": "HADOOP_HDP1_1",
+ "flavorId": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "nodeCount": 10,
+ "postInitScriptStatus": "PENDING",
+ "progress": 0.5,
+ "status": "UPDATING",
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/1234/clusters/db478fc1-2d86-4597-8010-cbe787bbbc41"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/flavor_list_cluster_types_response.json b/rackspace-cloudbigdata/src/test/resources/flavor_list_cluster_types_response.json
new file mode 100644
index 0000000..81dfde6
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/flavor_list_cluster_types_response.json
@@ -0,0 +1,16 @@
+{ "types":
+ [
+ {
+ "id": "HADOOP_HDP1_1",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/types/HADOOP_HDP1_1",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/types/HADOOP_HDP1_1",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Hadoop (HDP 1.1)"
+ }
+ ]
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/flavor_list_details_response.json b/rackspace-cloudbigdata/src/test/resources/flavor_list_details_response.json
new file mode 100644
index 0000000..3aaaad8
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/flavor_list_details_response.json
@@ -0,0 +1,17 @@
+{ "flavor":
+ {
+ "disk": 256,
+ "id": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Tiny Hadoop Instance",
+ "ram": 5120,
+ "vcpus": 1
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/flavor_list_response.json b/rackspace-cloudbigdata/src/test/resources/flavor_list_response.json
new file mode 100644
index 0000000..e183d90
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/flavor_list_response.json
@@ -0,0 +1,62 @@
+{ "flavors": [
+ {
+ "disk": 256,
+ "id": "4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/4fba3bca-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Tiny Hadoop Instance",
+ "ram": 5120,
+ "vcpus": 1
+ },
+ {
+ "disk": 512,
+ "id": "518400b2-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/518400b2-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/518400b2-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Small Hadoop Instance",
+ "ram": 8192,
+ "vcpus": 2
+ },
+ {
+ "disk": 1024,
+ "id": "5413894c-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/5413894c-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/5413894c-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Medium Hadoop Instance",
+ "ram": 15360,
+ "vcpus": 4
+ },
+ {
+ "disk": 2000,
+ "id": "559dd2b8-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/559dd2b8-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/559dd2b8-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Large Hadoop Instance",
+ "ram": 27648,
+ "vcpus": 8
+ }
+] }
diff --git a/rackspace-cloudbigdata/src/test/resources/profile_create_request.json b/rackspace-cloudbigdata/src/test/resources/profile_create_request.json
new file mode 100644
index 0000000..b76a5c5
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/profile_create_request.json
@@ -0,0 +1,19 @@
+{ "profile": {
+ "username": "john.doe",
+ "password": "j0Hnd03",
+ "sshkeys": [
+ { "name": "t@test",
+ "publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtUFnkFrqDDCgEqW1akQkpMOX
+Owwvg73PLn5Z5QgvxjvJhRCg9ZTR/OWXpWcYqFVNagH4Zs8NOb9921TyQ+ydMnatOM
+haxMh1ZwTgaUcvndOF8fY+kcERiw1l0iT95w42F8IdUH42Z+8KihZM8gVsbMS6qYTi
+OM29WHX7y37wuJIzqf3N2TiVXrqfjwugvY/bZ+47EUn78uk6aPZYJGXdDgaFqnIXUV
+N+hRFYXgKnU0Ui0aQkuYwnAW8KmanLoNU2xodrb6/XqWnSAAmwl7aoGKFunQsT6xDW
+yQk+ncUHUcdofDUqgd3lXmHGrTmQW97vqexDEnhsJ+AwbLGD5dukr t@test"
+ }
+ ],
+ "cloudCredentials": {
+ "username": "jdoe",
+ "apikey": "df23gkh34h52gkdgfakgf"
+ }
+}
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/profile_create_response.json b/rackspace-cloudbigdata/src/test/resources/profile_create_response.json
new file mode 100644
index 0000000..7c2dfed
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/profile_create_response.json
@@ -0,0 +1,16 @@
+{"profile":
+ { "username": "john.doe",
+ "userId" : "12346",
+ "tenantId" : "123456",
+ "sshkeys": [{"name": "t@test", "publicKey" : "ssh-rsa ....."}],
+ "cloudCredentials": {"username": "jdoe"},
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/123456/profile"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/123456/profile"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/profile_get_response.json b/rackspace-cloudbigdata/src/test/resources/profile_get_response.json
new file mode 100644
index 0000000..7c2dfed
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/profile_get_response.json
@@ -0,0 +1,16 @@
+{"profile":
+ { "username": "john.doe",
+ "userId" : "12346",
+ "tenantId" : "123456",
+ "sshkeys": [{"name": "t@test", "publicKey" : "ssh-rsa ....."}],
+ "cloudCredentials": {"username": "jdoe"},
+ "links": [
+ { "rel": "self",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/v1.0/123456/profile"
+ },
+ { "rel": "bookmark",
+ "href": "https://dfw.bigdata.api.rackspacecloud.com/123456/profile"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/resource_limits_get_response.json b/rackspace-cloudbigdata/src/test/resources/resource_limits_get_response.json
new file mode 100644
index 0000000..8a65466
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/resource_limits_get_response.json
@@ -0,0 +1,30 @@
+{ "limits":
+ { "absolute":
+ {
+ "disk": {
+ "limit": 5120,
+ "remaining": 5120
+ },
+ "nodeCount": {
+ "limit": 5,
+ "remaining": 5
+ },
+ "ram": {
+ "limit": 40960,
+ "remaining": 40960
+ },
+ "vcpus": {
+ "limit": 10,
+ "remaining": 10
+ }
+ },
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/limits",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/limits",
+ "rel": "bookmark"
+ }
+ ]
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/type_list_details_response.json b/rackspace-cloudbigdata/src/test/resources/type_list_details_response.json
new file mode 100644
index 0000000..1884b92
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/type_list_details_response.json
@@ -0,0 +1,15 @@
+{ "type":
+ {
+ "id": "HADOOP_HDP1_1",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/types/HADOOP_HDP1_1",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/types/HADOOP_HDP1_1",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Hadoop (HDP 1.1)",
+ "services": []
+ }
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/type_list_response.json b/rackspace-cloudbigdata/src/test/resources/type_list_response.json
new file mode 100644
index 0000000..81dfde6
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/type_list_response.json
@@ -0,0 +1,16 @@
+{ "types":
+ [
+ {
+ "id": "HADOOP_HDP1_1",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/types/HADOOP_HDP1_1",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/types/HADOOP_HDP1_1",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Hadoop (HDP 1.1)"
+ }
+ ]
+}
diff --git a/rackspace-cloudbigdata/src/test/resources/type_list_supported_flavors_response.json b/rackspace-cloudbigdata/src/test/resources/type_list_supported_flavors_response.json
new file mode 100644
index 0000000..08ac826
--- /dev/null
+++ b/rackspace-cloudbigdata/src/test/resources/type_list_supported_flavors_response.json
@@ -0,0 +1,32 @@
+{ "flavors": [
+ {
+ "disk": 1024,
+ "id": "5413894c-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/5413894c-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/5413894c-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Medium Hadoop Instance",
+ "ram": 15360,
+ "vcpus": 4
+ },
+ {
+ "disk": 2000,
+ "id": "559dd2b8-7c76-11e2-b737-beeffa00040e",
+ "links": [
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/v1.0/1234/flavors/559dd2b8-7c76-11e2-b737-beeffa00040e",
+ "rel": "self"
+ },
+ { "href": "http://dfw.bigdata.api.rackspacecloud.com/1234/flavors/559dd2b8-7c76-11e2-b737-beeffa00040e",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Large Hadoop Instance",
+ "ram": 27648,
+ "vcpus": 8
+ }
+] }