You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by za...@apache.org on 2013/08/30 19:19:55 UTC
[1/3] Adds Otter (Rackspace Autoscale) to labs
https://issues.apache.org/jira/browse/JCLOUDS-215
Updated Branches:
refs/heads/master 9f440d6bc -> 46f493ac8
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.java
new file mode 100644
index 0000000..4e5668d
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleExpectTest.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.autoscale.v1.internal;
+
+import javax.ws.rs.core.MediaType;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+
+/**
+ * Base class for writing Autoscale Expect tests
+ *
+ * @author Adrian Cole
+ * @author Zack Shoylev
+ */
+public class BaseAutoscaleExpectTest<T> extends BaseRestApiExpectTest<T> {
+ protected HttpRequest keystoneAuthWithUsernameAndPassword;
+ protected HttpRequest keystoneAuthWithUsernameAndPasswordAndTenantName;
+ protected HttpRequest keystoneAuthWithAccessKeyAndSecretKeyAndTenantName;
+ protected String authToken;
+ protected HttpResponse responseWithKeystoneAccess;
+ protected HttpRequest extensionsOfNovaRequest;
+ protected HttpResponse extensionsOfNovaResponse;
+ protected HttpResponse unmatchedExtensionsOfNovaResponse;
+ protected HttpRequest keystoneAuthWithAccessKeyAndSecretKeyAndTenantId;
+ protected String identityWithTenantId;
+
+ public BaseAutoscaleExpectTest() {
+ provider = "rackspace-autoscale";
+ keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
+ credential);
+ keystoneAuthWithUsernameAndPasswordAndTenantName = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPasswordAndTenantName(identity,
+ credential);
+ keystoneAuthWithAccessKeyAndSecretKeyAndTenantName = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKeyAndTenantName(identity,
+ credential);
+ keystoneAuthWithAccessKeyAndSecretKeyAndTenantId = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKeyAndTenantId(identity,
+ credential);
+
+ authToken = "bb03a23aa8271291a7aaa9aaa2aaaaaa";
+ responseWithKeystoneAccess = HttpResponse.builder()
+ .statusCode(200)
+ .payload(payloadFromResourceWithContentType("/access_rax.json", "application/json"))
+ .build();
+ // now, createContext arg will need tenant prefix
+ identityWithTenantId = KeystoneFixture.INSTANCE.getTenantId() + ":" + identity;
+ identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity;
+ }
+
+ @Override
+ protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) {
+ return HttpRequestComparisonType.JSON;
+ }
+
+ protected HttpRequest.Builder<?> authenticatedGET() {
+ return HttpRequest.builder()
+ .method("GET")
+ .addHeader("Accept", MediaType.APPLICATION_JSON)
+ .addHeader("X-Auth-Token", authToken);
+ }
+
+ protected HttpRequest.Builder<?> authenticatedPOST() {
+ return HttpRequest.builder()
+ .method("POST")
+ .addHeader("Accept", MediaType.APPLICATION_JSON)
+ .addHeader("X-Auth-Token", authToken);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/access_rax.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/access_rax.json b/rackspace-autoscale/src/test/resources/access_rax.json
new file mode 100644
index 0000000..2fba05d
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/access_rax.json
@@ -0,0 +1,249 @@
+{
+ "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":"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"
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json b/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json
new file mode 100644
index 0000000..4480ff0
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_create_request.json
@@ -0,0 +1,56 @@
+{
+ "launchConfiguration": {
+ "args": {
+ "loadBalancers": [
+ {
+ "port": 8080,
+ "loadBalancerId": 9099
+ }
+ ],
+ "server": {
+ "name": "autoscale_server",
+ "imageRef": "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
+ "flavorRef": "2",
+ "OS-DCF:diskConfig": "AUTO",
+ "metadata": {
+ "build_config": "core",
+ "meta_key_1": "meta_value_1",
+ "meta_key_2": "meta_value_2"
+ },
+ "networks": [
+ {
+ "uuid": "11111111-1111-1111-1111-111111111111"
+ },
+ {
+ "uuid": "00000000-0000-0000-0000-000000000000"
+ }
+ ],
+ "personality": [
+ {
+ "path": "/root/.csivh",
+ "contents": "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
+ }
+ ]
+ }
+ },
+ "type": "launch_server"
+ },
+ "groupConfiguration": {
+ "maxEntities": 10,
+ "cooldown": 360,
+ "name": "testscalinggroup198547",
+ "minEntities": 0,
+ "metadata": {
+ "gc_meta_key_2": "gc_meta_value_2",
+ "gc_meta_key_1": "gc_meta_value_1"
+ }
+ },
+ "scalingPolicies": [
+ {
+ "cooldown": 0,
+ "type": "webhook",
+ "name": "scale up by 1",
+ "change": 1
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json
new file mode 100644
index 0000000..21622f9
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_create_response.json
@@ -0,0 +1,72 @@
+{
+ "group": {
+ "launchConfiguration": {
+ "args": {
+ "loadBalancers": [
+ {
+ "port": 8080,
+ "loadBalancerId": 9099
+ }
+ ],
+ "server": {
+ "name": "autoscale_server",
+ "imageRef": "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
+ "flavorRef": "2",
+ "OS-DCF:diskConfig": "AUTO",
+ "personality": [
+ {
+ "path": "/root/.csivh",
+ "contents": "VGhpcyBpcyBhIHRlc3QgZmlsZS4="
+ }
+ ],
+ "networks": [
+ {
+ "uuid": "11111111-1111-1111-1111-111111111111"
+ },
+ {
+ "uuid": "00000000-0000-0000-0000-000000000000"
+ }
+ ],
+ "metadata": {
+ "build_config": "core",
+ "meta_key_1": "meta_value_1",
+ "meta_key_2": "meta_value_2"
+ }
+ }
+ },
+ "type": "launch_server"
+ },
+ "groupConfiguration": {
+ "maxEntities": 10,
+ "cooldown": 360,
+ "name": "testscalinggroup198547",
+ "minEntities": 0,
+ "metadata": {
+ "gc_meta_key_2": "gc_meta_value_2",
+ "gc_meta_key_1": "gc_meta_value_1"
+ }
+ },
+ "scalingPolicies": [
+ {
+ "name": "scale up by 1",
+ "links": [
+ {
+ "href": "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/policies/dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1/",
+ "rel": "self"
+ }
+ ],
+ "cooldown": 0,
+ "type": "webhook",
+ "id": "dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1",
+ "change": 1
+ }
+ ],
+ "links": [
+ {
+ "href": "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/",
+ "rel": "self"
+ }
+ ],
+ "id": "6791761b-821a-4d07-820d-0b2afc7dd7f6"
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json
new file mode 100644
index 0000000..ccf1ec0
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_get_response.json
@@ -0,0 +1,93 @@
+{
+ "group": {
+ "id": "1234567890",
+ "links": [
+ {
+ "href": "https://rackspace/v1.0/010101/groups/1234567890",
+ "rel": "self"
+ }
+ ],
+ "groupConfiguration": {
+ "name": "workers",
+ "cooldown": 60,
+ "minEntities": 5,
+ "maxEntities": 100,
+ "metadata": {
+ "firstkey": "this is a string",
+ "secondkey": "1"
+ }
+ },
+ "launchConfiguration": {
+ "type": "launch_server",
+ "args": {
+ "server": {
+ "flavorRef": "3",
+ "name": "webhead",
+ "imageRef": "0d589460-f177-4b0f-81c1-8ab8903ac7d8",
+ "OS-DCF:diskConfig": "AUTO",
+ "metadata": {
+ "mykey": "myvalue"
+ },
+ "personality": [
+ {
+ "path": "/root/.ssh/authorized_keys",
+ "contents": "ssh-rsa AAAAB3Nza...LiPk== user@example.net"
+ }
+ ],
+ "networks": [
+ {
+ "uuid": "11111111-1111-1111-1111-111111111111"
+ }
+ ]
+ },
+ "loadBalancers": [
+ {
+ "loadBalancerId": 2200,
+ "port": 8081
+ }
+ ]
+ }
+ },
+ "scalingPolicies": [
+ {
+ "id": "policyId1",
+ "links": [
+ {
+ "href": "https://rackspace/v1.0/010101/groups/1234567890/policies/policyId1",
+ "rel": "self"
+ }
+ ],
+ "name": "scale up by 10",
+ "change": 10,
+ "cooldown": 5,
+ "type": "webhook"
+ },
+ {
+ "id": "policyId2",
+ "links": [
+ {
+ "href": "https://rackspace/v1.0/010101/groups/1234567890/policies/policyId2",
+ "rel": "self"
+ }
+ ],
+ "name": "scale down by 5.5 percent",
+ "changePercent": -5.5,
+ "cooldown": 6,
+ "type": "webhook"
+ },
+ {
+ "id": "policyId3",
+ "links": [
+ {
+ "href": "https://rackspace/v1.0/010101/groups/groupId/policies/policyId3",
+ "rel": "self"
+ }
+ ],
+ "name": "set number of servers to 10",
+ "desiredCapacity": 10,
+ "cooldown": 3,
+ "type": "webhook"
+ }
+ ]
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json
new file mode 100644
index 0000000..82aa4dc
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_list_response.json
@@ -0,0 +1,33 @@
+{
+ "groups": [
+ {
+ "active": [],
+ "activeCapacity": 0,
+ "desiredCapacity": 0,
+ "id": "e41380ae-173c-4b40-848a-25c16d7fa83d",
+ "links": [
+ {
+ "href": "https://dfw.autoscale.api.rackspacecloud.com/v1.0/676873/groups/e41380ae-173c-4b40-848a-25c16d7fa83d/",
+ "rel": "self"
+ }
+ ],
+ "paused": false,
+ "pendingCapacity": 0
+ },
+ {
+ "active": [],
+ "activeCapacity": 0,
+ "desiredCapacity": 0,
+ "id": "f82bb000-f451-40c8-9dc3-6919097d2f7e",
+ "links": [
+ {
+ "href": "https://dfw.autoscale.api.rackspacecloud.com/v1.0/676873/groups/f82bb000-f451-40c8-9dc3-6919097d2f7e/",
+ "rel": "self"
+ }
+ ],
+ "paused": false,
+ "pendingCapacity": 0
+ }
+ ],
+ "groups_links": []
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json b/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json
new file mode 100644
index 0000000..f55d08a
--- /dev/null
+++ b/rackspace-autoscale/src/test/resources/autoscale_groups_state_response.json
@@ -0,0 +1,35 @@
+{
+ "group": {
+ "id": "1234567890",
+ "links": [
+ {
+ "href": "https://dfw.servers.api.rackspacecloud.com/v1.0/010101/groups/1234567890",
+ "rel": "self"
+ }
+ ],
+ "active": [
+ {
+ "id": "444444",
+ "links": [
+ {
+ "href": "https://dfw.servers.api.rackspacecloud.com/v2/010101/servers/444444",
+ "rel": "self"
+ }
+ ]
+ },
+ {
+ "id": "555555555",
+ "links": [
+ {
+ "href": "https://dfw.servers.api.rackspacecloud.com/v2/010101/servers/555555555",
+ "rel": "self"
+ }
+ ]
+ }
+ ],
+ "activeCapacity": 2,
+ "pendingCapacity": 2,
+ "desiredCapacity": 4,
+ "paused": false
+ }
+}
[2/3] Adds Otter (Rackspace Autoscale) to labs
https://issues.apache.org/jira/browse/JCLOUDS-215
Posted by za...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java
new file mode 100644
index 0000000..a6690ef
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LaunchConfiguration.java
@@ -0,0 +1,341 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import java.beans.ConstructorProperties;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Autoscale LaunchConfiguration.
+ *
+ * @see GroupApi#create(GroupConfiguration, LaunchConfiguration, List)
+ * @author Zack Shoylev
+ */
+public class LaunchConfiguration implements Comparable<LaunchConfiguration>{
+ private final ImmutableList<LoadBalancer> loadBalancers;
+ private final LaunchConfigurationType type;
+ private final ImmutableList<String> networks;
+ private final ImmutableList<Personality> personalities;
+
+ private final String serverName;
+ private final String serverImageRef;
+ private final String serverFlavorRef;
+ private final String serverDiskConfig;
+ private final ImmutableMap<String, String> serverMetadata;
+
+ @ConstructorProperties({
+ "loadBalancers", "type", "networks", "personalities", "serverName", "serverImageRef", "serverFlavorRef", "serverDiskConfig", "serverMetadata"
+ })
+ protected LaunchConfiguration(List<LoadBalancer> loadBalancers, LaunchConfigurationType type, List<String> networks, List<Personality> personalities, String serverName, String serverImageRef, String serverFlavorRef, String serverDiskConfig, Map<String, String> serverMetadata) {
+ this.loadBalancers = ImmutableList.copyOf(loadBalancers);
+ this.type = type;
+ this.networks = ImmutableList.copyOf(networks);
+ this.personalities = ImmutableList.copyOf(personalities);
+ this.serverName = serverName;
+ this.serverImageRef = serverImageRef;
+ this.serverFlavorRef = serverFlavorRef;
+ this.serverDiskConfig = serverDiskConfig;
+ this.serverMetadata = ImmutableMap.copyOf(serverMetadata);
+ }
+
+ /**
+ * @return the list of load balancers of this LaunchConfiguration.
+ * @see LaunchConfiguration.Builder#loadBalancers(List)
+ */
+ public List<LoadBalancer> getLoadBalancers() {
+ return this.loadBalancers;
+ }
+
+ /**
+ * @return the type for this LaunchConfiguration.
+ * @see LaunchConfigurationType
+ * @see LaunchConfiguration.Builder#type(LaunchConfigurationType)
+ */
+ public LaunchConfigurationType getType() {
+ return this.type;
+ }
+
+ /**
+ * @return the networks for this LaunchConfiguration.
+ * @see LaunchConfiguration#getNetworks()
+ * @see LaunchConfiguration.Builder#networks(List)
+ */
+ public List<String> getNetworks() {
+ return this.networks;
+ }
+
+ /**
+ * @return the personalities for this LaunchConfiguration.
+ * @see Personality
+ * @see LaunchConfiguration.Builder#personalities(List)
+ */
+ public List<Personality> getPersonalities() {
+ return this.personalities;
+ }
+
+ /**
+ * @return the server name for this LaunchConfiguration.
+ * @see LaunchConfiguration.Builder#serverName(String)
+ */
+ public String getServerName() {
+ return this.serverName;
+ }
+
+ /**
+ * @return the server image ref for this LaunchConfiguration.
+ * @see LaunchConfiguration.Builder#serverImageRef(String)
+ */
+ public String getServerImageRef() {
+ return this.serverImageRef;
+ }
+
+ /**
+ * @return the server flavor ref for this LaunchConfiguration.
+ * @see LaunchConfiguration.Builder#serverFlavorRef(String)
+ */
+ public String getServerFlavorRef() {
+ return this.serverFlavorRef;
+ }
+
+ /**
+ * @return the server disk config for this LaunchConfiguration, ex. "AUTO"
+ * @see LaunchConfiguration.Builder#serverDiskConfig(String)
+ */
+ public String getServerDiskConfig() {
+ return this.serverDiskConfig;
+ }
+
+ /**
+ * @return the server metadata for this LaunchConfiguration.
+ * @see LaunchConfiguration.Builder#serverMetadata(ImmutableMap)
+ */
+ public ImmutableMap<String, String> getServerMetadata() {
+ return this.serverMetadata;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(loadBalancers, type, networks, personalities, serverName, serverImageRef, serverFlavorRef, serverDiskConfig, serverMetadata);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ LaunchConfiguration that = LaunchConfiguration.class.cast(obj);
+ return Objects.equal(this.loadBalancers, that.loadBalancers) &&
+ Objects.equal(this.type, that.type) &&
+ Objects.equal(this.networks, that.networks) &&
+ Objects.equal(this.personalities, that.personalities) &&
+ Objects.equal(this.serverName, that.serverName) &&
+ Objects.equal(this.serverImageRef, that.serverImageRef) &&
+ Objects.equal(this.serverFlavorRef, that.serverFlavorRef) &&
+ Objects.equal(this.serverDiskConfig, that.serverDiskConfig) &&
+ Objects.equal(this.serverMetadata, that.serverMetadata);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("loadBalancers", loadBalancers)
+ .add("type", type)
+ .add("networks", networks)
+ .add("personalities", personalities)
+ .add("serverName", serverName)
+ .add("serverImageRef", serverImageRef)
+ .add("serverFlavorRef", serverFlavorRef)
+ .add("serverDiskConfig", serverDiskConfig)
+ .add("serverMetadata", serverMetadata);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromLaunchConfiguration(this);
+ }
+
+ public static class Builder {
+ protected List<LoadBalancer> loadBalancers;
+ protected LaunchConfigurationType type;
+ protected List<String> networks;
+ protected List<Personality> personalities;
+
+ protected String serverName;
+ protected String serverImageRef;
+ protected String serverFlavorRef;
+ protected String serverDiskConfig;
+ protected ImmutableMap<String, String> serverMetadata;
+
+ /**
+ * @param loadBalancers The load balancers of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getLoadBalancers()
+ */
+ public Builder loadBalancers(List<LoadBalancer> loadBalancers) {
+ this.loadBalancers = loadBalancers;
+ return this;
+ }
+
+ /**
+ * @param type The type for this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getType()
+ */
+ public Builder type(LaunchConfigurationType type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * @param networks The networks of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getNetworks()
+ */
+ public Builder networks(List<String> networks) {
+ this.networks = networks;
+ return this;
+ }
+
+ /**
+ * @param personalities The personalities of this LaunchConfiguration.
+ * @return The builder object.
+ * @see Personality
+ * @see LaunchConfiguration#getPersonalities()
+ */
+ public Builder personalities(List<Personality> personalities) {
+ this.personalities = personalities;
+ return this;
+ }
+
+ /**
+ * @param serverName The serverName of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getServerName()
+ */
+ public Builder serverName(String serverName) {
+ this.serverName = serverName;
+ return this;
+ }
+
+ /**
+ * @param serverImageRef The serverImageRef of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getServerImageRef()
+ */
+ public Builder serverImageRef(String serverImageRef) {
+ this.serverImageRef = serverImageRef;
+ return this;
+ }
+
+ /**
+ * @param serverFlavorRef The serverFlavorRef of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getServerFlavorRef()
+ */
+ public Builder serverFlavorRef(String serverFlavorRef) {
+ this.serverFlavorRef = serverFlavorRef;
+ return this;
+ }
+
+ /**
+ * @param serverDiskConfig The serverDiskConfig of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getServerDiskConfig()
+ */
+ public Builder serverDiskConfig(String serverDiskConfig) {
+ this.serverDiskConfig = serverDiskConfig;
+ return this;
+ }
+
+ /**
+ * @param serverMetadata The serverMetadata of this LaunchConfiguration.
+ * @return The builder object.
+ * @see LaunchConfiguration#getServerMetadata()
+ */
+ public Builder serverMetadata(Map<String, String> serverMetadata) {
+ this.serverMetadata = ImmutableMap.copyOf(serverMetadata);
+ return this;
+ }
+
+ /**
+ * @return A new LaunchConfiguration object.
+ */
+ public LaunchConfiguration build() {
+ return new LaunchConfiguration(loadBalancers, type, networks, personalities, serverName, serverImageRef, serverFlavorRef, serverDiskConfig, serverMetadata);
+ }
+
+ public Builder fromLaunchConfiguration(LaunchConfiguration in) {
+ return this
+ .loadBalancers(in.getLoadBalancers())
+ .type(in.getType())
+ .networks(in.getNetworks())
+ .personalities(in.getPersonalities())
+ .serverName(in.getServerName())
+ .serverImageRef(in.getServerImageRef())
+ .serverFlavorRef(in.getServerFlavorRef())
+ .serverDiskConfig(in.getServerDiskConfig())
+ .serverMetadata(in.getServerMetadata());
+ }
+ }
+
+ @Override
+ public int compareTo(LaunchConfiguration that) {
+ return this.getServerName().compareTo(that.getServerName());
+ }
+
+ /**
+ * Enumerates launch configuration types
+ */
+ public static enum LaunchConfigurationType {
+ LAUNCH_SERVER("launch_server");
+
+ private final String name;
+
+ private LaunchConfigurationType(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public static Optional<LaunchConfigurationType> getByValue(String value){
+ for (final LaunchConfigurationType element : EnumSet.allOf(LaunchConfigurationType.class)) {
+ if (element.toString().equals(value)) {
+ return Optional.of(element);
+ }
+ }
+ return Optional.absent();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java
new file mode 100644
index 0000000..004bb97
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/LoadBalancer.java
@@ -0,0 +1,129 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.beans.ConstructorProperties;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Autoscale LoadBalancer. Part of the launch configuration.
+ *
+ * @see LaunchConfiguration#getLoadBalancers()
+ * @author Zack Shoylev
+ */
+public class LoadBalancer {
+ private final int port;
+ @SerializedName("loadBalancerId")
+ private final int id;
+
+ @ConstructorProperties({ "port", "loadBalancerId" })
+ protected LoadBalancer(int port, int id) {
+ checkArgument(port >= 0, "port should be non-negative");
+ this.port = port;
+ checkArgument(id >= 0, "id should be non-negative");
+ this.id = id;
+ }
+
+ /**
+ * @return the socket port number of this LoadBalancer.
+ * @see LoadBalancer.Builder#port(int)
+ */
+ public int getPort() {
+ return this.port;
+ }
+
+ /**
+ * @return the id for this LoadBalancer.
+ * @see LoadBalancer.Builder#id(int)
+ */
+ public int getId() {
+ return this.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(port, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ LoadBalancer that = LoadBalancer.class.cast(obj);
+ return Objects.equal(this.port, that.port) && Objects.equal(this.id, that.id);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).add("port", port).add("id", id);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromLoadBalancer(this);
+ }
+
+ public static class Builder {
+ protected int port;
+ protected int id;
+
+ /**
+ * @param port The port of this LoadBalancer.
+ * @return The builder object.
+ * @see LoadBalancer#getPort()
+ */
+ public Builder port(int port) {
+ this.port = port;
+ return this;
+ }
+
+ /**
+ * @param id The id of this LoadBalancer.
+ * @return The builder object.
+ * @see LoadBalancer#getId()
+ */
+ public Builder id(int id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * @return A new LoadBalancer object.
+ */
+ public LoadBalancer build() {
+ return new LoadBalancer(port, id);
+ }
+
+ public Builder fromLoadBalancer(LoadBalancer in) {
+ return this.port(in.getPort()).id(in.getId());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java
new file mode 100644
index 0000000..4b2400f
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Personality.java
@@ -0,0 +1,125 @@
+/*
+ * 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.autoscale.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;
+
+/**
+ * Autoscale Personality. Part of the launch configuration.
+ *
+ * @see LaunchConfiguration#getPersonalities()
+ * @author Zack Shoylev
+ */
+public class Personality {
+ private final String path;
+ private final String contents;
+
+ @ConstructorProperties({ "path", "contents" })
+ protected Personality(String path, String contents) {
+ this.path = checkNotNull(path, "path should not be null");
+ this.contents = checkNotNull(contents, "contents should not be null");
+ }
+
+ /**
+ * @return the path of this Personality.
+ * @see Personality.Builder#path(String)
+ */
+ public String getPath() {
+ return this.path;
+ }
+
+ /**
+ * @return the contents for this Personality.
+ * @see Personality.Builder#contents(String)
+ */
+ public String getContents() {
+ return this.contents;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(path, contents);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ Personality that = Personality.class.cast(obj);
+ return Objects.equal(this.path, that.path) && Objects.equal(this.contents, that.contents);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).add("path", path).add("contents", contents);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromPersonality(this);
+ }
+
+ public static class Builder {
+ protected String path;
+ protected String contents;
+
+ /**
+ * @param path The path of this Personality.
+ * @return The builder object.
+ * @see Personality#getPath()
+ */
+ public Builder path(String path) {
+ this.path = path;
+ return this;
+ }
+
+ /**
+ * @param contents The contents of this Personality.
+ * @return The builder object.
+ * @see Personality#getContents()
+ */
+ public Builder contents(String contents) {
+ this.contents = contents;
+ return this;
+ }
+
+ /**
+ * @return A new Personality object.
+ */
+ public Personality build() {
+ return new Personality(path, contents);
+ }
+
+ public Builder fromPersonality(Personality in) {
+ return this.path(in.getPath()).contents(in.getContents());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java
new file mode 100644
index 0000000..0cefb05
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicy.java
@@ -0,0 +1,275 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.EnumSet;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * Autoscale ScalingPolicy. This class is used for requests.
+ *
+ * @see GroupApi#create(GroupConfiguration, LaunchConfiguration, java.util.List)
+ * @see Group#getScalingPolicies()
+ * @see ScalingPolicyResponse
+ * @author Zack Shoylev
+ */
+public class ScalingPolicy implements Comparable<ScalingPolicy>{
+ private final String name;
+ private final ScalingPolicyType type;
+ private final int cooldown;
+ private final int target;
+ private final ScalingPolicyTargetType targetType;
+
+ @ConstructorProperties({
+ "name", "type", "cooldown", "target", "targetType"
+ })
+ protected ScalingPolicy(String name, ScalingPolicyType type, int cooldown, int target, ScalingPolicyTargetType targetType) {
+
+ this.name = checkNotNull(name, "name required");
+ this.type = type;
+ checkArgument(cooldown >= 0, "cooldown should be non-negative");
+ this.cooldown = cooldown;
+ this.target = target;
+ this.targetType = targetType;
+ }
+
+ /**
+ * @return the name of this ScalingPolicy.
+ * @see ScalingPolicy.Builder#name(String)
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @return the type for this ScalingPolicy.
+ * @see ScalingPolicyType
+ * @see ScalingPolicy.Builder#type(String)
+ */
+ public ScalingPolicyType getType() {
+ return this.type;
+ }
+
+ /**
+ * @return the cooldown for this ScalingPolicy.
+ * @see ScalingPolicy.Builder#cooldown(int)
+ */
+ public int getCooldown() {
+ return this.cooldown;
+ }
+
+ /**
+ * @return the target for this ScalingPolicy. This is a numeric value, but could represent a 0-100% for some target types. Scale-down policies might have negative values.
+ *
+ * @see ScalingPolicy.Builder#target(int)
+ */
+ public int getTarget() {
+ return this.target;
+ }
+
+ /**
+ * @return the target type for this ScalingPolicy.
+ * @see ScalingPolicyTargetType
+ * @see ScalingPolicy.Builder#targetType(int)
+ */
+ public ScalingPolicyTargetType getTargetType() {
+ return this.targetType;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, type, cooldown, target, targetType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ ScalingPolicy that = ScalingPolicy.class.cast(obj);
+ return Objects.equal(this.name, that.name) &&
+ Objects.equal(this.type, that.type) &&
+ Objects.equal(this.cooldown, that.cooldown) &&
+ Objects.equal(this.target, that.target) &&
+ Objects.equal(this.targetType, that.targetType);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("name", name)
+ .add("type", type)
+ .add("cooldown", cooldown)
+ .add("target", target)
+ .add("targetType", "targetType");
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromScalingPolicy(this);
+ }
+
+ public static class Builder {
+ protected String name;
+ protected ScalingPolicyType type;
+ protected int cooldown;
+ protected int target;
+ protected ScalingPolicyTargetType targetType;
+
+ /**
+ * @param name The name of this ScalingPolicy.
+ * @return The builder object.
+ * @see ScalingPolicy#getName()
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param name The type for this ScalingPolicy.
+ * @return The builder object.
+ * @see ScalingPolicyType
+ * @see ScalingPolicy#getType()
+ */
+ public Builder type(ScalingPolicyType type) {
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * @param cooldown The cooldown of this ScalingPolicy.
+ * @return The builder object.
+ * @see ScalingPolicy#getCooldown()
+ */
+ public Builder cooldown(int cooldown) {
+ this.cooldown = cooldown;
+ return this;
+ }
+
+ /**
+ * @param target The target of this ScalingPolicy.
+ * @return The builder object.
+ * @see ScalingPolicy#getTarget()
+ */
+ public Builder target(int target) {
+ this.target = target;
+ return this;
+ }
+
+ /**
+ * @param target type The target type of this ScalingPolicy.
+ * @return The builder object.
+ * @see ScalingPolicyTargetType
+ * @see ScalingPolicy#getTargetType()
+ */
+ public Builder targetType(ScalingPolicyTargetType targetType) {
+ this.targetType = targetType;
+ return this;
+ }
+
+ /**
+ * @return A new ScalingPolicy object.
+ */
+ public ScalingPolicy build() {
+ return new ScalingPolicy(name, type, cooldown, target, targetType);
+ }
+
+ public Builder fromScalingPolicy(ScalingPolicy in) {
+ return this
+ .name(in.getName())
+ .type(in.getType())
+ .cooldown(in.getCooldown())
+ .target(in.getTarget())
+ .targetType(in.getTargetType());
+ }
+ }
+
+ @Override
+ public int compareTo(ScalingPolicy that) {
+ return this.getName().compareTo(that.getName());
+ }
+
+ /**
+ * Enumerates different types of scaling policies
+ */
+ public static enum ScalingPolicyType {
+ WEBHOOK("webhook");
+
+ private final String name;
+
+ private ScalingPolicyType(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public static Optional<ScalingPolicyType> getByValue(String value){
+ for (final ScalingPolicyType element : EnumSet.allOf(ScalingPolicyType.class)) {
+ if (element.toString().equals(value)) {
+ return Optional.of(element);
+ }
+ }
+ return Optional.absent();
+ }
+ }
+
+ /**
+ * Enumerates different types of targets a policy might have
+ */
+ public static enum ScalingPolicyTargetType {
+ INCREMENTAL("change"),
+ DESIRED_CAPACITY("desiredCapacity"),
+ PERCENT_CHANGE("changePercent");
+
+ private final String name;
+
+ private ScalingPolicyTargetType(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public static Optional<ScalingPolicyTargetType> getByValue(String value){
+ for (final ScalingPolicyTargetType element : EnumSet.allOf(ScalingPolicyTargetType.class)) {
+ if (element.toString().equals(value)) {
+ return Optional.of(element);
+ }
+ }
+ return Optional.absent();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java
new file mode 100644
index 0000000..c469719
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/ScalingPolicyResponse.java
@@ -0,0 +1,90 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.List;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Autoscale ScalingPolicyResponse. Extends ScalingPolicy with id and links.
+ *
+ * @see Group#getScalingPolicies()
+ * @author Zack Shoylev
+ */
+public class ScalingPolicyResponse extends ScalingPolicy{
+ private final ImmutableList<Link> links;
+ private final String id;
+
+ @ConstructorProperties({
+ "name", "type", "cooldown", "target", "targetType", "links", "id"
+ })
+ public ScalingPolicyResponse(String name, ScalingPolicyType type, int cooldown, int target, ScalingPolicyTargetType targetType, List<Link> links, String id) {
+ super(name, type, cooldown, target, targetType);
+ this.id = checkNotNull(id, "id required");
+ this.links = ImmutableList.copyOf(checkNotNull(links, "links required"));
+ }
+
+ /**
+ * @return the unique id of this ScalingPolicy.
+ * @see ScalingPolicyResponse.Builder#id(String)
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the links to this ScalingPolicy.
+ * @see ScalingPolicyResponse.Builder#links(String)
+ */
+ public ImmutableList<Link> getLinks() {
+ return this.links;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), links, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ ScalingPolicyResponse that = ScalingPolicyResponse.class.cast(obj);
+ return Objects.equal(this.id, that.id) &&
+ Objects.equal(this.links, that.links) &&
+ super.equals(obj);
+ }
+
+ protected ToStringHelper string() {
+ return super.string()
+ .add("links", links)
+ .add("id", id);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java
new file mode 100644
index 0000000..f12b690
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/features/GroupApi.java
@@ -0,0 +1,159 @@
+/*
+ * 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.autoscale.v1.features;
+
+
+import java.util.List;
+
+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.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.autoscale.v1.binders.BindCreateGroupToJson;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupState;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rackspace.autoscale.v1.functions.ParseGroupResponse;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.common.collect.FluentIterable;
+
+/**
+ * The API for controlling scaling groups.
+ * A scaling group is a high-level autoscaling concept that encompasses a group configuration, a launch configuration, and a set of scaling policies.
+ * @author Zack Shoylev
+ */
+@RequestFilters(AuthenticateRequest.class)
+public interface GroupApi {
+
+ /**
+ * Create a scaling group.
+ * @param groupConfiguration The group configuration.
+ * @param launchConfiguration The launch configuration.
+ * @param scalingPolicies The list of scaling policies.
+ * @return Group The group created by this call.
+ * @see GroupConfiguration
+ * @see LaunchConfiguration
+ * @see ScalingPolicy
+ * @see Group
+ */
+ @Named("Group:create")
+ @POST
+ @Path("/groups")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(NullOnNotFoundOr404.class)
+ @MapBinder(BindCreateGroupToJson.class)
+ @ResponseParser(ParseGroupResponse.class)
+ Group create(@PayloadParam("groupConfiguration") GroupConfiguration groupConfiguration,
+ @PayloadParam("launchConfiguration") LaunchConfiguration launchConfiguration,
+ @PayloadParam("scalingPolicies") List<ScalingPolicy> scalingPolicies);
+
+ /**
+ * This operation pauses the specified Autoscaling Group
+ *
+ * @param groupId The id for the specified Group.
+ * @return true if successful.
+ * @see GroupApi#resume(String)
+ */
+ @Named("Groups:pause/{groupId}")
+ @POST
+ @Path("/groups/{groupId}/pause")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(FalseOnNotFoundOr404.class)
+ boolean pause(@PathParam("groupId") String groupId);
+
+ /**
+ * This operation resumes the specified Autoscaling Group.
+ *
+ * @param groupId The id for the specified Group.
+ * @return true if successful.
+ * @see GroupApi#pause(String)
+ */
+ @Named("Groups:pause/{groupId}")
+ @POST
+ @Path("/groups/{groupId}/resume")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(FalseOnNotFoundOr404.class)
+ boolean resume(@PathParam("groupId") String groupId);
+
+ /**
+ * This operation deletes the specified Autoscaling Group
+ *
+ * @param groupId The id for the specified Group.
+ * @return true if successful.
+ */
+ @Named("Groups:delete/{id}")
+ @DELETE
+ @Path("/groups/{id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(FalseOnNotFoundOr404.class)
+ boolean delete(@PathParam("id") String groupId);
+
+ /**
+ * This operation gets group details for a group
+ * @param id The unique identifier of the scaling group.
+ * @return Group Full details for the scaling group.
+ */
+ @Named("Group:get/{id}")
+ @GET
+ @Path("/groups/{id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ResponseParser(ParseGroupResponse.class)
+ @Fallback(NullOnNotFoundOr404.class)
+ Group get(@PathParam("id") String id);
+
+ /**
+ * This operation gets the state of the Autoscaling Group. This is a slightly different set of information than the full details for a group.
+ * @param id The unique identifier of the scaling group.
+ * @return The state of the Group.
+ * @see GroupState
+ */
+ @Named("Group:state")
+ @GET
+ @Path("/groups/{id}/state")
+ @SelectJson("group")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Fallback(NullOnNotFoundOr404.class)
+ GroupState getState(@PathParam("id") String id);
+
+ /**
+ * This operation lists all autoscaling groups.
+ * @return A list of group states for all scaling groups.
+ * @see GroupState
+ */
+ @Named("Group:states")
+ @GET
+ @Path("/groups")
+ @SelectJson("groups")
+ @Consumes(MediaType.APPLICATION_JSON)
+ FluentIterable<GroupState> listGroupStates();
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java
new file mode 100644
index 0000000..5673a2c
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/functions/ParseGroupResponse.java
@@ -0,0 +1,151 @@
+/*
+ * 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.autoscale.v1.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.Link.Relation;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration.LaunchConfigurationType;
+import org.jclouds.rackspace.autoscale.v1.domain.LoadBalancer;
+import org.jclouds.rackspace.autoscale.v1.domain.Personality;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyTargetType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicyResponse;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+
+/**
+ * This parses the group response and decouples domain objects from the json object returned by the service.
+ * @author Zack Shoylev
+ */
+public class ParseGroupResponse implements Function<HttpResponse, Group> {
+
+ private final ParseJson<Map<String, Object>> json;
+
+ @Inject
+ ParseGroupResponse(ParseJson<Map<String, Object>> json) {
+ this.json = checkNotNull(json, "json");
+ }
+
+ /**
+ * Extracts the user password from the json response
+ */
+ @SuppressWarnings("unchecked")
+ public Group apply(HttpResponse from) {
+ Map<String, Object> result = json.apply(from);
+
+ Map<String, Object> group = (Map<String, Object>) result.get("group");
+ Map<String, Object> groupConfigurationMap = (Map<String, Object>) group.get("groupConfiguration");
+ Map<String, Object> launchConfigurationMap = (Map<String, Object>) group.get("launchConfiguration");
+ List<ScalingPolicyResponse> scalingPoliciesList = Lists.newArrayList();
+ Map<String, Object> args = (Map<String, Object>) launchConfigurationMap.get("args");
+ Map<String, Object> server = (Map<String, Object>) args.get("server");
+
+ List<Personality> personalities = Lists.newArrayList();
+ List<String> networks = Lists.newArrayList();
+ for(Map<String,String> jsonPersonality : (List<Map<String,String>>) server.get("personality")) {
+ personalities.add(Personality.builder().path(jsonPersonality.get("path")).contents(jsonPersonality.get("contents")).build());
+ }
+
+ for(Map<String,String> jsonNetwork : (List<Map<String,String>>) server.get("networks")) {
+ networks.add(jsonNetwork.get("uuid"));
+ }
+
+ List<LoadBalancer> loadBalancers = Lists.newArrayList();
+ for(Map<String,Double> jsonLoadBalancer : (List<Map<String,Double>>) args.get("loadBalancers")) {
+ loadBalancers.add(
+ LoadBalancer.builder().id( ((Double)jsonLoadBalancer.get("loadBalancerId")).intValue() ).port( ((Double)jsonLoadBalancer.get("port")).intValue() ).build()
+ );
+ }
+
+ LaunchConfiguration launchConfiguration = LaunchConfiguration.builder()
+ .loadBalancers(loadBalancers)
+ .serverName((String) server.get("name"))
+ .serverImageRef((String) server.get("imageRef"))
+ .serverFlavorRef((String) server.get("flavorRef"))
+ .serverDiskConfig((String) server.get("OS-DCF:diskConfig"))
+ .serverMetadata((Map<String, String>) server.get("metadata"))
+ .personalities(personalities)
+ .networks(networks)
+ .type(LaunchConfigurationType.getByValue((String) launchConfigurationMap.get("type")).get())
+ .build();
+
+ GroupConfiguration groupConfiguration = GroupConfiguration.builder()
+ .cooldown(((Double) groupConfigurationMap.get("cooldown")).intValue())
+ .minEntities(((Double) groupConfigurationMap.get("minEntities")).intValue())
+ .maxEntities(((Double) groupConfigurationMap.get("maxEntities")).intValue())
+ .name((String) groupConfigurationMap.get("name"))
+ .metadata((Map<String, String>) groupConfigurationMap.get("metadata"))
+ .build();
+
+ for(Map<String, Object> scalingPolicyMap : (List<Map<String, Object>>) group.get("scalingPolicies")) {
+ ScalingPolicyTargetType targetType = null;
+ for(String key : scalingPolicyMap.keySet()) {
+ if(ScalingPolicyTargetType.getByValue(key).isPresent()) {
+ targetType = ScalingPolicyTargetType.getByValue(key).get();
+ break;
+ }
+ }
+
+ List<Link> links = Lists.newArrayList();
+ for(Map<String, String> linkMap : (List<Map<String, String>>) scalingPolicyMap.get("links")) {
+ Link link = Link.builder().href(URI.create(linkMap.get("href"))).relation(Relation.fromValue(linkMap.get("rel"))).build();
+ links.add(link);
+ }
+
+ ScalingPolicyResponse scalingPolicyResponse =
+ new ScalingPolicyResponse(
+ (String)scalingPolicyMap.get("name"),
+ ScalingPolicyType.getByValue((String)scalingPolicyMap.get("type")).get(),
+ ((Double)scalingPolicyMap.get("cooldown")).intValue(),
+ ((Double)scalingPolicyMap.get(targetType.toString())).intValue(),
+ targetType,
+ ImmutableList.copyOf(links),
+ (String) scalingPolicyMap.get("id")
+ );
+ scalingPoliciesList.add(scalingPolicyResponse);
+ }
+
+ List<Link> links = Lists.newArrayList();
+ for(Map<String, String> linkMap : (List<Map<String, String>>) group.get("links")) {
+ Link link = Link.builder().href(URI.create(linkMap.get("href"))).relation(Relation.fromValue(linkMap.get("rel"))).build();
+ links.add(link);
+ }
+
+ String groupId = (String) group.get("id");
+ return Group.builder()
+ .id(groupId)
+ .scalingPolicy(scalingPoliciesList)
+ .groupConfiguration(groupConfiguration)
+ .launchConfiguration(launchConfiguration)
+ .links(links)
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.java
new file mode 100644
index 0000000..202b5de
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/handlers/AutoscaleErrorHandler.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.autoscale.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 AutoscaleErrorHandler 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/rackspace-autoscale/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
new file mode 100644
index 0000000..4ee5597
--- /dev/null
+++ b/rackspace-autoscale/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.autoscale.v1.AutoscaleApiMetadata
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java
new file mode 100644
index 0000000..b6f4e87
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiExpectTest.java
@@ -0,0 +1,357 @@
+/*
+ * 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.autoscale.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.assertFalse;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupState;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration.LaunchConfigurationType;
+import org.jclouds.rackspace.autoscale.v1.domain.LoadBalancer;
+import org.jclouds.rackspace.autoscale.v1.domain.Personality;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyTargetType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyType;
+import org.jclouds.rackspace.autoscale.v1.internal.BaseAutoscaleApiExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+/**
+ * Tests GroupApi Guice wiring and parsing
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "GroupApiExpectTest")
+public class GroupApiExpectTest extends BaseAutoscaleApiExpectTest {
+
+ public void testCreateGroup() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().method("POST").endpoint(endpoint).payload(payloadFromResourceWithContentType("/autoscale_groups_create_request.json", MediaType.APPLICATION_JSON)).build(),
+ HttpResponse.builder().statusCode(201).payload(payloadFromResource("/autoscale_groups_create_response.json")).build()
+ ).getGroupApiForZone("DFW");
+
+ GroupConfiguration groupConfiguration = GroupConfiguration.builder()
+ .maxEntities(10)
+ .cooldown(360)
+ .name("testscalinggroup198547")
+ .minEntities(0)
+ .metadata(ImmutableMap.of("gc_meta_key_2","gc_meta_value_2","gc_meta_key_1","gc_meta_value_1"))
+ .build();
+
+ LaunchConfiguration launchConfiguration = LaunchConfiguration.builder()
+ .loadBalancers(ImmutableList.of(LoadBalancer.builder().port(8080).id(9099).build()))
+ .serverName("autoscale_server")
+ .serverImageRef("0d589460-f177-4b0f-81c1-8ab8903ac7d8")
+ .serverFlavorRef("2")
+ .serverDiskConfig("AUTO")
+ .serverMetadata(ImmutableMap.of("build_config","core","meta_key_1","meta_value_1","meta_key_2","meta_value_2"))
+ .networks(ImmutableList.of("11111111-1111-1111-1111-111111111111","00000000-0000-0000-0000-000000000000"))
+ .personalities(ImmutableList.of(Personality.builder().path("/root/.csivh").contents("VGhpcyBpcyBhIHRlc3QgZmlsZS4=").build()))
+ .type(LaunchConfigurationType.LAUNCH_SERVER)
+ .build();
+
+ List<ScalingPolicy> scalingPolicies = Lists.newArrayList();
+
+ ScalingPolicy scalingPolicy = ScalingPolicy.builder()
+ .cooldown(0)
+ .type(ScalingPolicyType.WEBHOOK)
+ .name("scale up by 1")
+ .targetType(ScalingPolicyTargetType.INCREMENTAL)
+ .target(1)
+ .build();
+ scalingPolicies.add(scalingPolicy);
+
+ Group g = api.create(groupConfiguration, launchConfiguration, scalingPolicies);
+
+ assertNotNull(g);
+ assertEquals(g.getId(),"6791761b-821a-4d07-820d-0b2afc7dd7f6");
+ assertEquals(g.getLinks().size(), 1);
+ assertEquals(g.getLinks().get(0).getHref().toString(), "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/");
+ assertEquals(g.getLinks().get(0).getRelation(), Link.Relation.SELF);
+
+ assertEquals(g.getScalingPolicies().get(0).getId(), "dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1");
+ assertEquals(g.getScalingPolicies().get(0).getLinks().size(), 1);
+ assertEquals(g.getScalingPolicies().get(0).getLinks().get(0).getHref().toString(), "https://ord.autoscale.api.rackspacecloud.com/v1.0/829409/groups/6791761b-821a-4d07-820d-0b2afc7dd7f6/policies/dceb14ac-b2b3-4f06-aac9-a5b6cd5d40e1/");
+ assertEquals(g.getScalingPolicies().get(0).getLinks().get(0).getRelation(), Link.Relation.SELF);
+ assertEquals(g.getScalingPolicies().get(0).getCooldown(), 0);
+ assertEquals(g.getScalingPolicies().get(0).getTarget(), 1);
+ assertEquals(g.getScalingPolicies().get(0).getTargetType(), ScalingPolicyTargetType.INCREMENTAL);
+ assertEquals(g.getScalingPolicies().get(0).getType(), ScalingPolicyType.WEBHOOK);
+ assertEquals(g.getScalingPolicies().get(0).getName(), "scale up by 1");
+
+ assertEquals(g.getLaunchConfiguration().getLoadBalancers().size(), 1);
+ assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getId(), 9099);
+ assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getPort(), 8080);
+ assertEquals(g.getLaunchConfiguration().getServerName(), "autoscale_server");
+ assertEquals(g.getLaunchConfiguration().getServerImageRef(), "0d589460-f177-4b0f-81c1-8ab8903ac7d8");
+ assertEquals(g.getLaunchConfiguration().getServerFlavorRef(), "2");
+ assertEquals(g.getLaunchConfiguration().getServerDiskConfig(), "AUTO");
+ assertEquals(g.getLaunchConfiguration().getPersonalities().size(), 1);
+ assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getPath(), "/root/.csivh");
+ assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getContents(), "VGhpcyBpcyBhIHRlc3QgZmlsZS4=");
+ assertEquals(g.getLaunchConfiguration().getNetworks().size(), 2);
+ assertEquals(g.getLaunchConfiguration().getNetworks().get(0), "11111111-1111-1111-1111-111111111111");
+ assertEquals(g.getLaunchConfiguration().getNetworks().get(1), "00000000-0000-0000-0000-000000000000");
+ assertEquals(g.getLaunchConfiguration().getServerMetadata().size(), 3);
+ assertTrue(g.getLaunchConfiguration().getServerMetadata().containsKey("build_config"));
+ assertTrue(g.getLaunchConfiguration().getServerMetadata().containsValue("core"));
+ assertEquals(g.getLaunchConfiguration().getType(), LaunchConfigurationType.LAUNCH_SERVER);
+
+ assertEquals(g.getGroupConfiguration().getMaxEntities(), 10);
+ assertEquals(g.getGroupConfiguration().getCooldown(), 360);
+ assertEquals(g.getGroupConfiguration().getName(), "testscalinggroup198547");
+ assertEquals(g.getGroupConfiguration().getMinEntities(), 0);
+ assertEquals(g.getGroupConfiguration().getMetadata().size(), 2);
+ assertTrue(g.getGroupConfiguration().getMetadata().containsKey("gc_meta_key_2"));
+ assertTrue(g.getGroupConfiguration().getMetadata().containsValue("gc_meta_value_2"));
+ }
+
+ public void testCreateGroupFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().method("POST").endpoint(endpoint).payload(payloadFromResourceWithContentType("/autoscale_groups_create_request.json", MediaType.APPLICATION_JSON)).build(),
+ HttpResponse.builder().statusCode(404).payload(payloadFromResource("/autoscale_groups_create_response.json")).build()
+ ).getGroupApiForZone("DFW");
+
+ GroupConfiguration groupConfiguration = GroupConfiguration.builder()
+ .maxEntities(10)
+ .cooldown(360)
+ .name("testscalinggroup198547")
+ .minEntities(0)
+ .metadata(ImmutableMap.of("gc_meta_key_2","gc_meta_value_2","gc_meta_key_1","gc_meta_value_1"))
+ .build();
+
+ LaunchConfiguration launchConfiguration = LaunchConfiguration.builder()
+ .loadBalancers(ImmutableList.of(LoadBalancer.builder().port(8080).id(9099).build()))
+ .serverName("autoscale_server")
+ .serverImageRef("0d589460-f177-4b0f-81c1-8ab8903ac7d8")
+ .serverFlavorRef("2")
+ .serverDiskConfig("AUTO")
+ .serverMetadata(ImmutableMap.of("build_config","core","meta_key_1","meta_value_1","meta_key_2","meta_value_2"))
+ .networks(ImmutableList.of("11111111-1111-1111-1111-111111111111","00000000-0000-0000-0000-000000000000"))
+ .personalities(ImmutableList.of(Personality.builder().path("/root/.csivh").contents("VGhpcyBpcyBhIHRlc3QgZmlsZS4=").build()))
+ .type(LaunchConfigurationType.LAUNCH_SERVER)
+ .build();
+
+ List<ScalingPolicy> scalingPolicies = Lists.newArrayList();
+
+ ScalingPolicy scalingPolicy = ScalingPolicy.builder()
+ .cooldown(0)
+ .type(ScalingPolicyType.WEBHOOK)
+ .name("scale up by 1")
+ .targetType(ScalingPolicyTargetType.INCREMENTAL)
+ .target(1)
+ .build();
+ scalingPolicies.add(scalingPolicy);
+
+ Group g = api.create(groupConfiguration, launchConfiguration, scalingPolicies);
+
+ assertNull(g);
+ }
+
+ public void testListGroups() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(200).payload(payloadFromResource("/autoscale_groups_list_response.json")).build()
+ ).getGroupApiForZone("DFW");
+
+ FluentIterable<GroupState> groupStates = api.listGroupStates();
+ assertEquals(groupStates.size(),2);
+
+ assertEquals(groupStates.get(0).getGroupInstances().size(), 0);
+ assertEquals(groupStates.get(0).getActiveCapacity(), 0);
+ assertEquals(groupStates.get(0).getDesiredCapacity(), 0);
+ assertEquals(groupStates.get(0).getId(), "e41380ae-173c-4b40-848a-25c16d7fa83d");
+ assertEquals(groupStates.get(0).getLinks().size(), 1);
+ assertEquals(groupStates.get(0).getLinks().get(0).getHref().toString(), "https://dfw.autoscale.api.rackspacecloud.com/v1.0/676873/groups/e41380ae-173c-4b40-848a-25c16d7fa83d/");
+ assertEquals(groupStates.get(0).getLinks().get(0).getRelation(), Link.Relation.SELF);
+ assertEquals(groupStates.get(0).getPaused(), false);
+ assertEquals(groupStates.get(0).getPendingCapacity(), 0);
+ }
+
+ @Test(expectedExceptions = org.jclouds.rest.ResourceNotFoundException.class)
+ public void testListGroupsFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(404).build()
+ ).getGroupApiForZone("DFW");
+
+ FluentIterable<GroupState> groupStates = api.listGroupStates();
+ assertEquals(groupStates.size(), 0);
+ }
+
+ public void testGetGroup() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(200).payload(payloadFromResource("/autoscale_groups_get_response.json")).build()
+ ).getGroupApiForZone("DFW");
+
+ Group g = api.get("1234567890");
+ assertEquals(g.getId(), "1234567890");
+ assertEquals(g.getScalingPolicies().size(), 3);
+ }
+
+ public void testGetGroupFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(404).build()
+ ).getGroupApiForZone("DFW");
+
+ Group g = api.get("1234567890");
+ assertNull(g);
+ }
+
+ public void testDeleteGroup() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).method("DELETE").build(),
+ HttpResponse.builder().statusCode(204).build()
+ ).getGroupApiForZone("DFW");
+
+ boolean success = api.delete("1234567890");
+ assertTrue(success);
+ }
+
+ public void testDeleteGroupFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).method("DELETE").build(),
+ HttpResponse.builder().statusCode(404).build()
+ ).getGroupApiForZone("DFW");
+
+ boolean success = api.delete("1234567890");
+ assertFalse(success);
+ }
+
+ public void testGetGroupState() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/state");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(200).payload(payloadFromResource("/autoscale_groups_state_response.json")).build()
+ ).getGroupApiForZone("DFW");
+
+ GroupState gs = api.getState("1234567890");
+ assertEquals(gs.getId(), "1234567890");
+ assertEquals(gs.getGroupInstances().size(), 2);
+ assertEquals(gs.getGroupInstances().get(0).getId(), "444444");
+ }
+
+ public void testGetGroupStateFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/state");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).build(),
+ HttpResponse.builder().statusCode(404).payload(payloadFromResource("/autoscale_groups_state_response.json")).build()
+ ).getGroupApiForZone("DFW");
+
+ GroupState gs = api.getState("1234567890");
+ assertNull(gs);
+ }
+
+ public void testPause() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/pause");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).method("POST").build(),
+ HttpResponse.builder().statusCode(204).build()
+ ).getGroupApiForZone("DFW");
+
+ boolean success = api.pause("1234567890");
+ assertTrue(success);
+ }
+
+ public void testPauseFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/pause");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).method("POST").build(),
+ HttpResponse.builder().statusCode(404).build()
+ ).getGroupApiForZone("DFW");
+
+ boolean success = api.pause("1234567890");
+ assertFalse(success);
+ }
+
+ public void testResume() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/resume");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).method("POST").build(),
+ HttpResponse.builder().statusCode(204).build()
+ ).getGroupApiForZone("DFW");
+
+ boolean success = api.resume("1234567890");
+ assertTrue(success);
+ }
+
+ public void testResumeFail() {
+ URI endpoint = URI.create("https://dfw.autoscale.api.rackspacecloud.com/v1.0/888888/groups/1234567890/resume");
+ GroupApi api = requestsSendResponses(
+ keystoneAuthWithUsernameAndPasswordAndTenantName,
+ responseWithKeystoneAccess,
+ authenticatedGET().endpoint(endpoint).method("POST").build(),
+ HttpResponse.builder().statusCode(404).build()
+ ).getGroupApiForZone("DFW");
+
+ boolean success = api.resume("1234567890");
+ assertFalse(success);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java
new file mode 100644
index 0000000..da6370b
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/features/GroupApiLiveTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.autoscale.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.autoscale.v1.domain.Group;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupState;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration.LaunchConfigurationType;
+import org.jclouds.rackspace.autoscale.v1.domain.LoadBalancer;
+import org.jclouds.rackspace.autoscale.v1.domain.Personality;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyTargetType;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy.ScalingPolicyType;
+import org.jclouds.rackspace.autoscale.v1.internal.BaseAutoscaleApiLiveTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Tests GroupApi Guice live test
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "GroupApiLiveTest")
+public class GroupApiLiveTest extends BaseAutoscaleApiLiveTest {
+
+ private static Map<String, List<Group>> created = Maps.newHashMap();
+
+ @Override
+ @BeforeClass(groups = { "integration", "live" })
+ public void setup() {
+ super.setup();
+ for (String zone : api.getConfiguredZones()) {
+ List<Group> createdGroupList = Lists.newArrayList();
+ created.put(zone, createdGroupList);
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+
+ GroupConfiguration groupConfiguration = GroupConfiguration.builder().maxEntities(10).cooldown(360)
+ .name("testscalinggroup198547").minEntities(0)
+ .metadata(ImmutableMap.of("gc_meta_key_2", "gc_meta_value_2", "gc_meta_key_1", "gc_meta_value_1"))
+ .build();
+
+ LaunchConfiguration launchConfiguration = LaunchConfiguration
+ .builder()
+ .loadBalancers(ImmutableList.of(LoadBalancer.builder().port(8080).id(9099).build()))
+ .serverName("autoscale_server")
+ .serverImageRef("0d589460-f177-4b0f-81c1-8ab8903ac7d8")
+ .serverFlavorRef("1")
+ .serverDiskConfig("AUTO")
+ .serverMetadata(
+ ImmutableMap
+ .of("build_config", "core", "meta_key_1", "meta_value_1", "meta_key_2", "meta_value_2"))
+ .networks(
+ ImmutableList.of("11111111-1111-1111-1111-111111111111", "00000000-0000-0000-0000-000000000000"))
+ .personalities(
+ ImmutableList.of(Personality.builder().path("/root/.csivh")
+ .contents("VGhpcyBpcyBhIHRlc3QgZmlsZS4=").build()))
+ .type(LaunchConfigurationType.LAUNCH_SERVER).build();
+
+ List<ScalingPolicy> scalingPolicies = Lists.newArrayList();
+
+ ScalingPolicy scalingPolicy = ScalingPolicy.builder().cooldown(0).type(ScalingPolicyType.WEBHOOK)
+ .name("scale up by 1").targetType(ScalingPolicyTargetType.INCREMENTAL).target(1).build();
+ scalingPolicies.add(scalingPolicy);
+
+ Group g = groupApi.create(groupConfiguration, launchConfiguration, scalingPolicies);
+ createdGroupList.add(g);
+
+ assertNotNull(g);
+ assertNotNull(g.getId());
+ assertEquals(g.getLinks().size(), 1);
+ assertEquals(g.getLinks().get(0).getHref().toString(),
+ "https://" + zone.toLowerCase() + ".autoscale.api.rackspacecloud.com/v1.0/" + api.getCurrentTenantId().get().getId() + "/groups/" + g.getId() + "/");
+ assertEquals(g.getLinks().get(0).getRelation(), Link.Relation.SELF);
+
+ assertNotNull(g.getScalingPolicies().get(0).getId());
+ assertEquals(g.getScalingPolicies().get(0).getLinks().size(), 1);
+ assertEquals(
+ g.getScalingPolicies().get(0).getLinks().get(0).getHref().toString(),
+ "https://" + zone.toLowerCase() + ".autoscale.api.rackspacecloud.com/v1.0/" + api.getCurrentTenantId().get().getId() + "/groups/" + g.getId() + "/policies/" + g.getScalingPolicies().get(0).getId() +"/");
+ assertEquals(g.getScalingPolicies().get(0).getLinks().get(0).getRelation(), Link.Relation.SELF);
+ assertEquals(g.getScalingPolicies().get(0).getCooldown(), 0);
+ assertEquals(g.getScalingPolicies().get(0).getTarget(), 1);
+ assertEquals(g.getScalingPolicies().get(0).getTargetType(), ScalingPolicyTargetType.INCREMENTAL);
+ assertEquals(g.getScalingPolicies().get(0).getType(), ScalingPolicyType.WEBHOOK);
+ assertEquals(g.getScalingPolicies().get(0).getName(), "scale up by 1");
+
+ assertEquals(g.getLaunchConfiguration().getLoadBalancers().size(), 1);
+ assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getId(), 9099);
+ assertEquals(g.getLaunchConfiguration().getLoadBalancers().get(0).getPort(), 8080);
+ assertEquals(g.getLaunchConfiguration().getServerName(), "autoscale_server");
+ assertNotNull(g.getLaunchConfiguration().getServerImageRef());
+ assertEquals(g.getLaunchConfiguration().getServerFlavorRef(), "1");
+ assertEquals(g.getLaunchConfiguration().getServerDiskConfig(), "AUTO");
+ assertEquals(g.getLaunchConfiguration().getPersonalities().size(), 1);
+ assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getPath(), "/root/.csivh");
+ assertEquals(g.getLaunchConfiguration().getPersonalities().get(0).getContents(),
+ "VGhpcyBpcyBhIHRlc3QgZmlsZS4=");
+ assertEquals(g.getLaunchConfiguration().getNetworks().size(), 2);
+ assertEquals(g.getLaunchConfiguration().getNetworks().get(0), "11111111-1111-1111-1111-111111111111");
+ assertEquals(g.getLaunchConfiguration().getNetworks().get(1), "00000000-0000-0000-0000-000000000000");
+ assertEquals(g.getLaunchConfiguration().getServerMetadata().size(), 3);
+ assertTrue(g.getLaunchConfiguration().getServerMetadata().containsKey("build_config"));
+ assertTrue(g.getLaunchConfiguration().getServerMetadata().containsValue("core"));
+ assertEquals(g.getLaunchConfiguration().getType(), LaunchConfigurationType.LAUNCH_SERVER);
+
+ assertEquals(g.getGroupConfiguration().getMaxEntities(), 10);
+ assertEquals(g.getGroupConfiguration().getCooldown(), 360);
+ assertEquals(g.getGroupConfiguration().getName(), "testscalinggroup198547");
+ assertEquals(g.getGroupConfiguration().getMinEntities(), 0);
+ assertEquals(g.getGroupConfiguration().getMetadata().size(), 2);
+ assertTrue(g.getGroupConfiguration().getMetadata().containsKey("gc_meta_key_2"));
+ assertTrue(g.getGroupConfiguration().getMetadata().containsValue("gc_meta_value_2"));
+ }
+ }
+
+ @Test
+ public void testGetGroup() {
+ for (String zone : api.getConfiguredZones()) {
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+ String groupId = created.get(zone).get(0).getId();
+ Group testGroup = groupApi.get(groupId);
+ assertEquals(testGroup.getId(), groupId);
+ assertEquals(testGroup.getGroupConfiguration().getCooldown(), 360);
+ assertEquals(testGroup.getLaunchConfiguration().getServerName(), "autoscale_server");
+ assertEquals(testGroup.getScalingPolicies().get(0).getName(), "scale up by 1");
+ }
+ }
+
+ @Test
+ public void testGetState() {
+ for (String zone : api.getConfiguredZones()) {
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+ String groupId = created.get(zone).get(0).getId();
+ GroupState testGroup = groupApi.getState(groupId);
+ assertEquals(testGroup.getId(), groupId);
+ }
+ }
+
+ @Test
+ public void testListGroups() {
+ for (String zone : api.getConfiguredZones()) {
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+ FluentIterable<GroupState> groupsList = groupApi.listGroupStates();
+ String groupId = created.get(zone).get(0).getId();
+ for( GroupState groupState : groupsList) {
+ if( groupId.equals(groupState.getId()) ) {
+ return;
+ }
+ }
+ fail("Could not find known groupID " + groupId);
+ }
+ }
+
+ /* TODO: uncomment when implemented
+ @Test
+ public void testPause() {
+ for (String zone : api.getConfiguredZones()) {
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+ String groupId = created.get(zone).get(0).getId();
+ assertTrue(groupApi.pause(groupId));
+ }
+ }
+
+ @Test
+ public void testResume() {
+ for (String zone : api.getConfiguredZones()) {
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+ String groupId = created.get(zone).get(0).getId();
+ assertTrue(groupApi.resume(groupId));
+ }
+ }
+ */
+
+ @Override
+ @AfterClass(groups = { "integration", "live" })
+ public void tearDown() {
+ for (String zone : api.getConfiguredZones()) {
+ GroupApi groupApi = api.getGroupApiForZone(zone);
+ for (Group group : created.get(zone)) {
+ if (!groupApi.delete(group.getId()))
+ throw new RuntimeException("Could not delete an autoscale group after tests!");
+ }
+ }
+ super.tearDown();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java
new file mode 100644
index 0000000..4cf1527
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiExpectTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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.autoscale.v1.internal;
+
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+
+/**
+ * Base class for writing Autoscale Expect tests
+ *
+ * @author Zack Shoylev
+ */
+public class BaseAutoscaleApiExpectTest extends BaseAutoscaleExpectTest<AutoscaleApi> {
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.java
new file mode 100644
index 0000000..56f4ffa
--- /dev/null
+++ b/rackspace-autoscale/src/test/java/org/jclouds/rackspace/autoscale/v1/internal/BaseAutoscaleApiLiveTest.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.autoscale.v1.internal;
+
+import java.util.Properties;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+
+/**
+ * Tests behavior of AutoscaleApi
+ *
+ * @author Zack Shoylev
+ */
+public class BaseAutoscaleApiLiveTest extends BaseApiLiveTest<AutoscaleApi> {
+
+ public BaseAutoscaleApiLiveTest() {
+ provider = "rackspace-autoscale";
+ }
+
+ @Override
+ protected Properties setupProperties() {
+ Properties props = super.setupProperties();
+ setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE);
+ setIfTestSystemPropertyPresent(props, KeystoneProperties.SERVICE_TYPE);
+ return props;
+ }
+}
[3/3] git commit: Adds Otter (Rackspace Autoscale) to labs
https://issues.apache.org/jira/browse/JCLOUDS-215
Posted by za...@apache.org.
Adds Otter (Rackspace Autoscale) to labs https://issues.apache.org/jira/browse/JCLOUDS-215
Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/commit/46f493ac
Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/tree/46f493ac
Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/diff/46f493ac
Branch: refs/heads/master
Commit: 46f493ac869890fef4085af3de6c1801736a4c23
Parents: 9f440d6
Author: Zack Shoylev <za...@rackspace.com>
Authored: Fri Aug 2 01:34:17 2013 -0500
Committer: Zack Shoylev <za...@rackspace.com>
Committed: Fri Aug 30 12:15:02 2013 -0500
----------------------------------------------------------------------
pom.xml | 2 +
rackspace-autoscale-us/pom.xml | 145 ++++++++
.../us/v1/AutoscaleUSProviderMetadata.java | 114 ++++++
.../org.jclouds.providers.ProviderMetadata | 18 +
.../AutoscaleUSProviderMetadataExpectTest.java | 64 ++++
.../us/v1/AutoscaleUSProviderTest.java | 32 ++
.../features/AutoscaleUSGroupApiLiveTest.java | 32 ++
.../src/test/resources/access_rax_us.json | 249 +++++++++++++
.../src/test/resources/logback.xml | 69 ++++
rackspace-autoscale/pom.xml | 134 +++++++
.../rackspace/autoscale/v1/AutoscaleApi.java | 61 ++++
.../autoscale/v1/AutoscaleApiMetadata.java | 96 +++++
.../v1/binders/BindCreateGroupToJson.java | 97 +++++
.../v1/config/AutoscaleHttpApiModule.java | 79 ++++
.../v1/config/AutoscaleParserModule.java | 32 ++
.../rackspace/autoscale/v1/domain/Group.java | 206 +++++++++++
.../autoscale/v1/domain/GroupConfiguration.java | 221 ++++++++++++
.../autoscale/v1/domain/GroupInstance.java | 82 +++++
.../autoscale/v1/domain/GroupState.java | 145 ++++++++
.../v1/domain/LaunchConfiguration.java | 341 ++++++++++++++++++
.../autoscale/v1/domain/LoadBalancer.java | 129 +++++++
.../autoscale/v1/domain/Personality.java | 125 +++++++
.../autoscale/v1/domain/ScalingPolicy.java | 275 ++++++++++++++
.../v1/domain/ScalingPolicyResponse.java | 90 +++++
.../autoscale/v1/features/GroupApi.java | 159 +++++++++
.../v1/functions/ParseGroupResponse.java | 151 ++++++++
.../v1/handlers/AutoscaleErrorHandler.java | 67 ++++
.../services/org.jclouds.apis.ApiMetadata | 18 +
.../v1/features/GroupApiExpectTest.java | 357 +++++++++++++++++++
.../autoscale/v1/features/GroupApiLiveTest.java | 217 +++++++++++
.../v1/internal/BaseAutoscaleApiExpectTest.java | 27 ++
.../v1/internal/BaseAutoscaleApiLiveTest.java | 43 +++
.../v1/internal/BaseAutoscaleExpectTest.java | 82 +++++
.../src/test/resources/access_rax.json | 249 +++++++++++++
.../autoscale_groups_create_request.json | 56 +++
.../autoscale_groups_create_response.json | 72 ++++
.../autoscale_groups_get_response.json | 93 +++++
.../autoscale_groups_list_response.json | 33 ++
.../autoscale_groups_state_response.json | 35 ++
39 files changed, 4497 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 814b44e..85e8642 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,8 @@
<module>openstack-swift</module>
<module>rackspace-clouddatabases-us</module>
<module>rackspace-clouddatabases-uk</module>
+ <module>rackspace-autoscale</module>
+ <module>rackspace-autoscale-us</module>
</modules>
<build>
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/pom.xml
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/pom.xml b/rackspace-autoscale-us/pom.xml
new file mode 100644
index 0000000..e2f19a9
--- /dev/null
+++ b/rackspace-autoscale-us/pom.xml
@@ -0,0 +1,145 @@
+<?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.7.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- TODO: when out of labs, switch to org.jclouds.api -->
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-autoscale-us</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <name>jclouds rackspace-autoscale api provider</name>
+ <description>jclouds components to access Rackspace Autoscale</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- keystone endpoint -->
+ <test.rackspace-autoscale.endpoint>http://localhost:5000/v2.0/</test.rackspace-autoscale.endpoint>
+ <!-- keystone version -->
+ <test.rackspace-autoscale.api-version>2.0</test.rackspace-autoscale.api-version>
+ <test.rackspace-autoscale.build-version />
+ <test.rackspace-autoscale.identity>FIXME_IDENTITY</test.rackspace-autoscale.identity>
+ <test.rackspace-autoscale.credential>FIXME_CREDENTIALS</test.rackspace-autoscale.credential>
+ <test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+
+ <jclouds.osgi.export>org.jclouds.rackspace.autoscale.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>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-autoscale</artifactId>
+ <version>${project.parent.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-autoscale</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>
+ </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-autoscale.endpoint>${test.rackspace-autoscale-us.endpoint}</test.rackspace-autoscale.endpoint>
+ <test.rackspace-autoscale.api-version>${test.rackspace-autoscale-us.api-version}</test.rackspace-autoscale.api-version>
+ <test.rackspace-autoscale.build-version>${test.rackspace-autoscale-us.build-version}</test.rackspace-autoscale.build-version>
+ <test.rackspace-autoscale.identity>${test.rackspace-autoscale-us.identity}</test.rackspace-autoscale.identity>
+ <test.rackspace-autoscale.credential>${test.rackspace-autoscale-us.credential}</test.rackspace-autoscale.credential>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java b/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java
new file mode 100644
index 0000000..f680c25
--- /dev/null
+++ b/rackspace-autoscale-us/src/main/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadata.java
@@ -0,0 +1,114 @@
+/*
+ * 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.autoscale.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.apis.ApiMetadata;
+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.autoscale.v1.AutoscaleApiMetadata;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleHttpApiModule;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleParserModule;
+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 Autoscale API
+ *
+ * @author Zack Shoylev
+ */
+public class AutoscaleUSProviderMetadata extends BaseProviderMetadata {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return builder().fromProviderMetadata(this);
+ }
+
+ public AutoscaleUSProviderMetadata() {
+ super(builder());
+ }
+
+ public AutoscaleUSProviderMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = new Properties();
+ properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
+ properties.setProperty(SERVICE_TYPE, "rax:autoscale");
+ properties.setProperty(PROPERTY_ZONES, "ORD,DFW,SYD");
+ 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;
+ }
+
+ public static class Builder extends BaseProviderMetadata.Builder {
+
+ protected Builder(){
+ id("rackspace-autoscale-us")
+ .name("Rackspace autoscale US")
+ .apiMetadata(new AutoscaleApiMetadata().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(AutoscaleParserModule.class)
+ .add(AutoscaleHttpApiModule.class).build())
+ .build())
+ .homepage(URI.create("http://www.rackspace.com/cloud/public/autoscale/"))
+ .console(URI.create("https://mycloud.rackspace.com"))
+ .linkedServices("rackspace-cloudservers-us", "cloudfiles-us")
+ .iso3166Codes("US-IL", "US-TX", "AU-NSW")
+ .endpoint("https://identity.api.rackspacecloud.com/v2.0/")
+ .defaultProperties(AutoscaleUSProviderMetadata.defaultProperties());
+ }
+
+ @Override
+ public AutoscaleUSProviderMetadata build() {
+ return new AutoscaleUSProviderMetadata(this);
+ }
+
+ @Override
+ public Builder fromProviderMetadata(ProviderMetadata in) {
+ super.fromProviderMetadata(in);
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/rackspace-autoscale-us/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..1717af9
--- /dev/null
+++ b/rackspace-autoscale-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.autoscale.us.v1.AutoscaleUSProviderMetadata
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java
new file mode 100644
index 0000000..f119e99
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderMetadataExpectTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.autoscale.us.v1;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApi;
+import org.jclouds.rackspace.autoscale.v1.internal.BaseAutoscaleApiExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This test ensures that the wiring in {@link AutoscaleUSProviderMetadata} is correct.
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSProviderMetadataExpectTest")
+public class AutoscaleUSProviderMetadataExpectTest extends BaseAutoscaleApiExpectTest {
+
+ public AutoscaleUSProviderMetadataExpectTest() {
+ this.provider = "rackspace-autoscale-us";
+ this.identity = "myUsername";
+ this.credential = "myApiKey";
+ }
+
+ public void testCanGetConfiguredZones() {
+
+ HttpRequest authenticate = HttpRequest.builder().method("POST")
+ .endpoint("https://identity.api.rackspacecloud.com/v2.0/tokens")
+ .addHeader("Accept", "application/json")
+ .payload(payloadFromStringWithContentType(
+ "{\"auth\":{\"RAX-KSKEY:apiKeyCredentials\":{\"username\":\"myUsername\",\"apiKey\":\"myApiKey\"}}}"
+ , "application/json")).build();
+
+
+ HttpResponse authenticationResponse = HttpResponse.builder()
+ .statusCode(200)
+ .payload(payloadFromResourceWithContentType("/access_rax_us.json", "application/json"))
+ .build();
+
+ AutoscaleApi whenNovaRegionExists = requestSendsResponse(authenticate, authenticationResponse);
+
+ assertEquals(whenNovaRegionExists.getConfiguredZones(), ImmutableSet.of("ORD", "DFW"));
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.java
new file mode 100644
index 0000000..2d2ca2c
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/AutoscaleUSProviderTest.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.autoscale.us.v1;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.jclouds.rackspace.autoscale.v1.AutoscaleApiMetadata;
+import org.testng.annotations.Test;
+
+/**
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSProviderTest")
+public class AutoscaleUSProviderTest extends BaseProviderMetadataTest {
+
+ public AutoscaleUSProviderTest() {
+ super(new AutoscaleUSProviderMetadata(), new AutoscaleApiMetadata());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.java
new file mode 100644
index 0000000..08ac5fb
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/java/org/jclouds/rackspace/autoscale/us/v1/features/AutoscaleUSGroupApiLiveTest.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.autoscale.us.v1.features;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Tests GroupApi Guice wiring and parsing
+ *
+ * @author Zack Shoylev
+ */
+@Test(groups = "unit", testName = "AutoscaleUSGroupApiLiveTest")
+public class AutoscaleUSGroupApiLiveTest extends GroupApiLiveTest {
+ public AutoscaleUSGroupApiLiveTest() {
+ provider = "rackspace-autoscale-us";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/resources/access_rax_us.json
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/resources/access_rax_us.json b/rackspace-autoscale-us/src/test/resources/access_rax_us.json
new file mode 100644
index 0000000..2fba05d
--- /dev/null
+++ b/rackspace-autoscale-us/src/test/resources/access_rax_us.json
@@ -0,0 +1,249 @@
+{
+ "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":"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"
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale-us/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/rackspace-autoscale-us/src/test/resources/logback.xml b/rackspace-autoscale-us/src/test/resources/logback.xml
new file mode 100644
index 0000000..6559c23
--- /dev/null
+++ b/rackspace-autoscale-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>
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/pom.xml
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/pom.xml b/rackspace-autoscale/pom.xml
new file mode 100644
index 0000000..58fffe9
--- /dev/null
+++ b/rackspace-autoscale/pom.xml
@@ -0,0 +1,134 @@
+<?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.7.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- TODO: when out of labs, switch to org.jclouds.api -->
+ <groupId>org.apache.jclouds.labs</groupId>
+ <artifactId>rackspace-autoscale</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <name>jclouds rackspace-autoscale api</name>
+ <description>jclouds components to access Rackspace Autoscale</description>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- keystone endpoint -->
+ <test.rackspace-autoscale.endpoint>http://localhost:5000/v2.0/</test.rackspace-autoscale.endpoint>
+ <!-- keystone version -->
+ <test.rackspace-autoscale.api-version>2.0</test.rackspace-autoscale.api-version>
+ <test.rackspace-autoscale.build-version />
+ <test.rackspace-autoscale.identity>FIXME_IDENTITY</test.rackspace-autoscale.identity>
+ <test.rackspace-autoscale.credential>FIXME_CREDENTIALS</test.rackspace-autoscale.credential>
+ <test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
+
+ <jclouds.osgi.export>org.jclouds.rackspace.autoscale.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>
+
+ <dependencies>
+ <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>
+ </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-autoscale.endpoint>${test.rackspace-autoscale.endpoint}</test.rackspace-autoscale.endpoint>
+ <test.rackspace-autoscale.api-version>${test.rackspace-autoscale.api-version}</test.rackspace-autoscale.api-version>
+ <test.rackspace-autoscale.build-version>${test.rackspace-autoscale.build-version}</test.rackspace-autoscale.build-version>
+ <test.rackspace-autoscale.identity>${test.rackspace-autoscale.identity}</test.rackspace-autoscale.identity>
+ <test.rackspace-autoscale.credential>${test.rackspace-autoscale.credential}</test.rackspace-autoscale.credential>
+ <test.jclouds.keystone.credential-type>${test.jclouds.keystone.credential-type}</test.jclouds.keystone.credential-type>
+ </systemPropertyVariables>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java
new file mode 100644
index 0000000..4563a3f
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApi.java
@@ -0,0 +1,61 @@
+/*
+ * 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.autoscale.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.openstack.keystone.v2_0.domain.Tenant;
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.common.base.Optional;
+import com.google.inject.Provides;
+
+/**
+ * Provides access to Rackspace Autoscale.
+ *
+ * @see <a href="https://rackspace-autoscale.readthedocs.org">API Doc</a>
+ * @see <a href="http://docs.autoscale.apiary.io/">Apiary API Doc</a>
+ * @author Zack Shoylev
+ */
+public interface AutoscaleApi extends Closeable{
+ /**
+ * Provides a set of all zones available.
+ *
+ * @return the Zone codes configured
+ */
+ @Provides
+ @Zone
+ Set<String> getConfiguredZones();
+
+ /**
+ * Provides access to all scaling Group features.
+ */
+ @Delegate
+ GroupApi getGroupApiForZone(@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
+
+ /**
+ * Provides the Tenant.
+ */
+ @Provides
+ Optional<Tenant> getCurrentTenantId();
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java
new file mode 100644
index 0000000..0d36410
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/AutoscaleApiMetadata.java
@@ -0,0 +1,96 @@
+/*
+ * 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.autoscale.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.autoscale.v1.config.AutoscaleHttpApiModule;
+import org.jclouds.rackspace.autoscale.v1.config.AutoscaleParserModule;
+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 Autoscale API
+ *
+ * @see AutoscaleApi
+ * @author Zack Shoylev
+ */
+public class AutoscaleApiMetadata extends BaseHttpApiMetadata<AutoscaleApi> {
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder().fromApiMetadata(this);
+ }
+
+ public AutoscaleApiMetadata() {
+ this(new Builder());
+ }
+
+ protected AutoscaleApiMetadata(Builder builder) {
+ super(builder);
+ }
+
+ public static Properties defaultProperties() {
+ Properties properties = BaseHttpApiMetadata.defaultProperties();
+ properties.setProperty(SERVICE_TYPE, "rax:autoscale");
+ properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
+ return properties;
+ }
+
+ public static class Builder extends BaseHttpApiMetadata.Builder<AutoscaleApi, Builder> {
+
+ protected Builder() {
+ id("rackspace-autoscale")
+ .name("Rackspace Autoscale 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(AutoscaleApiMetadata.defaultProperties())
+ .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+ .add(CloudIdentityAuthenticationApiModule.class)
+ .add(CloudIdentityAuthenticationModule.class)
+ .add(ZoneModule.class)
+ .add(AutoscaleParserModule.class)
+ .add(AutoscaleHttpApiModule.class)
+ .build());
+ }
+
+ @Override
+ public AutoscaleApiMetadata build() {
+ return new AutoscaleApiMetadata(this);
+ }
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java
new file mode 100644
index 0000000..8e06f95
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/binders/BindCreateGroupToJson.java
@@ -0,0 +1,97 @@
+/*
+ * 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.autoscale.v1.binders;
+
+import java.util.List;
+import java.util.Map;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rackspace.autoscale.v1.domain.GroupConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.LaunchConfiguration;
+import org.jclouds.rackspace.autoscale.v1.domain.ScalingPolicy;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.inject.Inject;
+
+/**
+ * Decouple building the json object from the domain objects structure by using the binder
+ * @author Zack Shoylev
+ */
+public class BindCreateGroupToJson implements MapBinder {
+
+ private final BindToJsonPayload jsonBinder;
+
+ @Inject
+ private BindCreateGroupToJson(BindToJsonPayload jsonBinder) {
+ this.jsonBinder = jsonBinder;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+ List<ScalingPolicy> scalingPoliciesRequest = (List<ScalingPolicy>) postParams.get("scalingPolicies");
+ LaunchConfiguration launchConfigurationRequest = (LaunchConfiguration) postParams.get("launchConfiguration");
+
+ GroupConfiguration groupConfiguration = (GroupConfiguration) postParams.get("groupConfiguration");
+
+ Map<String, Object> launchConfigurationMap = Maps.newHashMap();
+ List<Map<String, Object>> scalingPoliciesList = Lists.newArrayList();
+ Map<String, Object> args = Maps.newHashMap();
+ launchConfigurationMap.put("args", args);
+ launchConfigurationMap.put("type", launchConfigurationRequest.getType().toString());
+
+ args.put("loadBalancers", launchConfigurationRequest.getLoadBalancers());
+ Map<String, Object> server = Maps.newHashMap();
+ args.put("server", server);
+ server.put("name", launchConfigurationRequest.getServerName());
+ server.put("imageRef", launchConfigurationRequest.getServerImageRef());
+ server.put("flavorRef", launchConfigurationRequest.getServerFlavorRef());
+ server.put("OS-DCF:diskConfig", launchConfigurationRequest.getServerDiskConfig());
+ server.put("metadata", launchConfigurationRequest.getServerMetadata());
+ List<Map<String, String>> networks = Lists.newArrayList();
+ server.put("networks", networks);
+ for(String networkId : launchConfigurationRequest.getNetworks()) {
+ Map<String, String> network = Maps.newHashMap();
+ network.put("uuid", networkId);
+ networks.add(network);
+ }
+ server.put("personality", launchConfigurationRequest.getPersonalities());
+
+ for(ScalingPolicy scalingPolicy : scalingPoliciesRequest) {
+ Map<String,Object> scalingPolicyMap = Maps.newHashMap();
+ scalingPoliciesList.add(scalingPolicyMap);
+ scalingPolicyMap.put("cooldown", scalingPolicy.getCooldown());
+ scalingPolicyMap.put("type", scalingPolicy.getType().toString());
+ scalingPolicyMap.put("name", scalingPolicy.getName());
+ // A couple of different scaling policies are supported, such as percent or number based, or targeting specific numbers of instances
+ scalingPolicyMap.put(scalingPolicy.getTargetType().toString(), scalingPolicy.getTarget());
+ }
+
+ return jsonBinder.bindToRequest(request, ImmutableMap.of(
+ "launchConfiguration", launchConfigurationMap,
+ "groupConfiguration", groupConfiguration,
+ "scalingPolicies", scalingPoliciesList));
+ }
+
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
+ throw new IllegalStateException("CreateInstance is a POST operation");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.java
new file mode 100644
index 0000000..9311287
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleHttpApiModule.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.autoscale.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.autoscale.v1.AutoscaleApi;
+import org.jclouds.rackspace.autoscale.v1.handlers.AutoscaleErrorHandler;
+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 Autoscale connection.
+ *
+ * @author Zack Shoylev
+ */
+@ConfiguresHttpApi
+public class AutoscaleHttpApiModule extends HttpApiModule<AutoscaleApi> {
+
+ @Override
+ protected void configure() {
+ super.configure();
+ }
+
+ @Provides
+ @Singleton
+ public Multimap<URI, URI> aliases() {
+ return ImmutableMultimap.<URI, URI>builder().build();
+ }
+
+ @Override
+ protected void bindErrorHandlers() {
+ bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(AutoscaleErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(AutoscaleErrorHandler.class);
+ bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(AutoscaleErrorHandler.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();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.java
new file mode 100644
index 0000000..580ff2a
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/config/AutoscaleParserModule.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.autoscale.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 AutoscaleParserModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java
new file mode 100644
index 0000000..091143c
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/Group.java
@@ -0,0 +1,206 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import java.util.List;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Autoscale Group.
+ * This domain object contains information about an autoscaling group.
+ *
+ * @author Zack Shoylev
+ */
+
+public class Group {
+ private final String id;
+ private final ImmutableList<Link> links;
+ private final ImmutableList<ScalingPolicyResponse> scalingPolicy;
+ private final GroupConfiguration groupConfiguration;
+ private final LaunchConfiguration launchConfiguration;
+
+ protected Group(String id, ImmutableList<Link> links, ImmutableList<ScalingPolicyResponse> scalingPolicy, GroupConfiguration groupConfiguration, LaunchConfiguration launchConfiguration) {
+ this.id = id;
+ this.links = links;
+ this.scalingPolicy = scalingPolicy;
+ this.groupConfiguration = groupConfiguration;
+ this.launchConfiguration = launchConfiguration;
+ }
+
+ /**
+ * Unique group identifier, usually UUID
+ * @return the id of this Group.
+ * @see Group.Builder#id(String)
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the links of this Group.
+ * @see Link
+ * @see Group.Builder#links(List)
+ */
+ public ImmutableList<Link> getLinks() {
+ return this.links;
+ }
+
+ /**
+ * @return A list of scaling policies for this Group.
+ * @see ScalingPolicy
+ * @see Group.Builder#scalingPolicy(List)
+ */
+ public ImmutableList<ScalingPolicyResponse> getScalingPolicies() {
+ return this.scalingPolicy;
+ }
+
+ /**
+ * @return the group configuration of this Group.
+ * @see GroupConfiguration
+ * @see Group.Builder#groupConfiguration(GroupConfiguration)
+ */
+ public GroupConfiguration getGroupConfiguration() {
+ return this.groupConfiguration;
+ }
+
+ /**
+ * @return the launch configuration of this Group.
+ * @see LaunchConfiguration
+ * @see Group.Builder#launchConfiguration(LaunchConfiguration)
+ */
+ public LaunchConfiguration getLaunchConfiguration() {
+ return this.launchConfiguration;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, links, scalingPolicy, groupConfiguration, launchConfiguration);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ Group that = Group.class.cast(obj);
+ return Objects.equal(this.id, that.id) &&
+ Objects.equal(this.links, that.links) &&
+ Objects.equal(this.scalingPolicy, that.scalingPolicy) &&
+ Objects.equal(this.groupConfiguration, that.groupConfiguration) &&
+ Objects.equal(this.launchConfiguration, that.launchConfiguration);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("id", id)
+ .add("links", links)
+ .add("scalingPolicy", scalingPolicy)
+ .add("groupConfiguration", groupConfiguration)
+ .add("launchConfiguration", "launchConfiguration");
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromGroup(this);
+ }
+
+ public static class Builder {
+ protected String id;
+ protected ImmutableList<Link> links;
+ protected ImmutableList<ScalingPolicyResponse> scalingPolicy;
+ protected GroupConfiguration groupConfiguration;
+ protected LaunchConfiguration launchConfiguration;
+
+ /**
+ * @param id The id of this Group.
+ * @return The builder object.
+ * @see Group#getId()
+ */
+ public Builder id(String id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * @param links The links of this Group.
+ * @return The builder object.
+ * @see Group#getLinks()
+ */
+ public Builder links(List<Link> links) {
+ this.links = ImmutableList.copyOf(links);
+ return this;
+ }
+
+ /**
+ * @param scalingPolicy The scaling policies list of this Group.
+ * @return The builder object.
+ * @see Group#getScalingPolicy()
+ */
+ public Builder scalingPolicy(List<ScalingPolicyResponse> scalingPolicy) {
+ this.scalingPolicy = ImmutableList.copyOf(scalingPolicy);
+ return this;
+ }
+
+ /**
+ * @param groupConfiguration The groupConfiguration of this Group.
+ * @return The builder object.
+ * @see Group#getGroupConfiguration()
+ */
+ public Builder groupConfiguration(GroupConfiguration groupConfiguration) {
+ this.groupConfiguration = groupConfiguration;
+ return this;
+ }
+
+ /**
+ * @param launchConfiguration The launchConfiguration of this Group.
+ * @return The builder object.
+ * @see Group#getLaunchConfiguration()
+ */
+ public Builder launchConfiguration(LaunchConfiguration launchConfiguration) {
+ this.launchConfiguration = launchConfiguration;
+ return this;
+ }
+
+ /**
+ * @return A new ScalingPolicy object.
+ */
+ public Group build() {
+ return new Group(id, links, scalingPolicy, groupConfiguration, launchConfiguration);
+ }
+
+ public Builder fromGroup(Group in) {
+ return this
+ .id(in.getId())
+ .links(in.getLinks())
+ .scalingPolicy(in.getScalingPolicies())
+ .groupConfiguration(in.getGroupConfiguration())
+ .launchConfiguration(in.getLaunchConfiguration());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java
new file mode 100644
index 0000000..b2673d0
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupConfiguration.java
@@ -0,0 +1,221 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.Map;
+
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Autoscale GroupConfiguration.
+ *
+ * @see GroupApi#create(GroupConfiguration, LaunchConfiguration, java.util.List)
+ * @author Zack Shoylev
+ */
+public class GroupConfiguration implements Comparable<GroupConfiguration>{
+ private final String name;
+ private final int cooldown;
+ private final int minEntities;
+ private final int maxEntities;
+ private final ImmutableMap<String,String> metadata;
+
+ @ConstructorProperties({
+ "name", "cooldown", "minEntities", "maxEntities", "metadata"
+ })
+ protected GroupConfiguration(String name, int cooldown, int minEntities, int maxEntities, Map<String,String> metadata) {
+
+ this.name = checkNotNull(name, "name required");
+ checkArgument(cooldown >= 0, "cooldown should be non-negative");
+ checkArgument(minEntities >= 0, "minEntities should be non-negative");
+ checkArgument(maxEntities >= 0, "maxEntities should be non-negative");
+ this.cooldown = cooldown;
+ this.minEntities = minEntities;
+ this.maxEntities = maxEntities;
+ if(metadata == null) {
+ this.metadata = ImmutableMap.of();
+ } else {
+ this.metadata = ImmutableMap.copyOf(metadata);
+ }
+ }
+
+ /**
+ * @return the name of this GroupConfiguration. The name is not a unique or even sufficient identifier in some cases.
+ * @see GroupConfiguration.Builder#name(String)
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @return the cooldown for this GroupConfiguration.
+ * @see GroupConfiguration.Builder#cooldown(int)
+ */
+ public int getCooldown() {
+ return this.cooldown;
+ }
+
+ /**
+ * @return the minimum number of entities for this GroupConfiguration.
+ * @see GroupConfiguration.Builder#minEntities(int)
+ */
+ public int getMinEntities() {
+ return this.minEntities;
+ }
+
+ /**
+ * @return the maximum number of entities for this GroupConfiguration.
+ * @see GroupConfiguration.Builder#maxEntities(int)
+ */
+ public int getMaxEntities() {
+ return this.maxEntities;
+ }
+
+ /**
+ * @return the metadata map for this GroupConfiguration.
+ * @see GroupConfiguration.Builder#metadata(Map<String,String>)
+ */
+ public ImmutableMap<String, String> getMetadata() {
+ return metadata;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, cooldown, minEntities, maxEntities, metadata);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ GroupConfiguration that = GroupConfiguration.class.cast(obj);
+ return Objects.equal(this.name, that.name) &&
+ Objects.equal(this.cooldown, that.cooldown) &&
+ Objects.equal(this.minEntities, that.minEntities) &&
+ Objects.equal(this.maxEntities, that.maxEntities) &&
+ Objects.equal(this.metadata, that.metadata);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this)
+ .add("name", name)
+ .add("cooldown", cooldown)
+ .add("minEntities", minEntities)
+ .add("maxEntities", maxEntities)
+ .add("metadata", metadata);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromGroupConfiguration(this);
+ }
+
+ public static class Builder {
+ protected String name;
+ protected int cooldown;
+ protected int minEntities;
+ protected int maxEntities;
+ protected Map<String, String> metadata;
+
+ /**
+ * @param name The name of this GroupConfiguration.
+ * @return The builder object.
+ * @see GroupConfiguration#getName()
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param name The cooldown for this GroupConfiguration.
+ * @return The builder object.
+ * @see GroupConfiguration#getCooldown()
+ */
+ public Builder cooldown(int cooldown) {
+ this.cooldown = cooldown;
+ return this;
+ }
+
+ /**
+ * @param name The cooldown for this GroupConfiguration.
+ * @return The builder object.
+ * @see GroupConfiguration#getCooldown()
+ */
+ public Builder minEntities(int minEntities) {
+ this.minEntities = minEntities;
+ return this;
+ }
+
+ /**
+ * @param name The maxEntities for this GroupConfiguration.
+ * @return The builder object.
+ * @see GroupConfiguration#getCooldown()
+ */
+ public Builder maxEntities(int maxEntities) {
+ this.maxEntities = maxEntities;
+ return this;
+ }
+
+ /**
+ * @param name The metadata for this GroupConfiguration.
+ * @return The builder object.
+ * @see GroupConfiguration#getDatabases()
+ */
+ public Builder metadata(Map<String, String> metadata) {
+ this.metadata = metadata;
+ return this;
+ }
+
+ /**
+ *
+ * @return A new GroupConfiguration object.
+ */
+ public GroupConfiguration build() {
+ return new GroupConfiguration(name, cooldown, minEntities, maxEntities, metadata);
+ }
+
+ public Builder fromGroupConfiguration(GroupConfiguration in) {
+ return this
+ .name(in.getName())
+ .cooldown(in.getCooldown())
+ .minEntities(in.getMinEntities())
+ .maxEntities(in.getMaxEntities())
+ .metadata(in.getMetadata());
+ }
+ }
+
+ @Override
+ public int compareTo(GroupConfiguration that) {
+ return this.getName().compareTo(that.getName());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.java
new file mode 100644
index 0000000..70d265a
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupInstance.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.autoscale.v1.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Autoscale Group Instance (as in hardware instance). Part of the group state.
+ *
+ * @see GroupState#getGroupInstances()
+ * @author Zack Shoylev
+ */
+public class GroupInstance {
+ private final String id;
+ private final ImmutableList<Link> links;
+
+ @ConstructorProperties({ "id", "links" })
+ protected GroupInstance(String id, ImmutableList<Link> links) {
+ this.id = checkNotNull(id, "id should not be null");
+ this.links = checkNotNull(links, "links should not be null");
+ }
+
+ /**
+ * @return the id of this GroupInstance.
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the links for this GroupInstance.
+ */
+ public ImmutableList<Link> getLinks() {
+ return this.links;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(links, id);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ GroupInstance that = GroupInstance.class.cast(obj);
+ return Objects.equal(this.id, that.id) && Objects.equal(this.links, that.links);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).add("id", id).add("links", links);
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/46f493ac/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java
----------------------------------------------------------------------
diff --git a/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java
new file mode 100644
index 0000000..5b26e34
--- /dev/null
+++ b/rackspace-autoscale/src/main/java/org/jclouds/rackspace/autoscale/v1/domain/GroupState.java
@@ -0,0 +1,145 @@
+/*
+ * 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.autoscale.v1.domain;
+
+import java.beans.ConstructorProperties;
+import java.util.List;
+
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.rackspace.autoscale.v1.features.GroupApi;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableList;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Autoscale Group State. Contains information about a scaling group.
+ *
+ * @see Group
+ * @see GroupApi#listGroupStates()
+ * @see GroupApi#getState(String)
+ * @author Zack Shoylev
+ */
+public class GroupState implements Comparable<GroupState> {
+ private final String id;
+ private final ImmutableList<Link> links;
+ private final int activeCapacity;
+ private final int pendingCapacity;
+ private final int desiredCapacity;
+ private final boolean paused;
+ @SerializedName("active")
+ private final ImmutableList<GroupInstance> groupInstances;
+
+ @ConstructorProperties({ "id", "links", "activeCapacity", "pendingCapacity", "desiredCapacity", "paused",
+ "active" })
+ protected GroupState(String id, List<Link> links, int activeCapacity, int pendingCapacity,
+ int desiredCapacity, boolean paused, List<GroupInstance> groupInstances) {
+ this.id = id;
+ this.links = ImmutableList.copyOf(links);
+ this.activeCapacity = activeCapacity;
+ this.pendingCapacity = pendingCapacity;
+ this.desiredCapacity = desiredCapacity;
+ this.paused = paused;
+ this.groupInstances = ImmutableList.copyOf(groupInstances);
+ }
+
+ /**
+ * @return the id of this GroupState.
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @return the links for this GroupState.
+ */
+ public List<Link> getLinks() {
+ return this.links;
+ }
+
+ /**
+ * @return the active capacity for this GroupState.
+ */
+ public int getActiveCapacity() {
+ return this.activeCapacity;
+ }
+
+ /**
+ * @return the pending capacity for this GroupState.
+ */
+ public int getPendingCapacity() {
+ return this.pendingCapacity;
+ }
+
+ /**
+ * @return the desired capacity for this GroupState.
+ */
+ public int getDesiredCapacity() {
+ return this.desiredCapacity;
+ }
+
+ /**
+ * @return the paused status for this GroupState.
+ */
+ public boolean getPaused() {
+ return this.paused;
+ }
+
+ /**
+ * @return the group instances for this GroupState.
+ * @see GroupInstance
+ */
+ public List<GroupInstance> getGroupInstances() {
+ return this.groupInstances;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, links, activeCapacity, pendingCapacity, desiredCapacity, paused, groupInstances);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+ GroupState that = GroupState.class.cast(obj);
+ return Objects.equal(this.id, that.id) && Objects.equal(this.links, that.links)
+ && Objects.equal(this.activeCapacity, that.activeCapacity)
+ && Objects.equal(this.pendingCapacity, that.pendingCapacity)
+ && Objects.equal(this.desiredCapacity, that.desiredCapacity) && Objects.equal(this.paused, that.paused)
+ && Objects.equal(this.groupInstances, that.groupInstances);
+ }
+
+ protected ToStringHelper string() {
+ return Objects.toStringHelper(this).add("id", id).add("links", links).add("activeCapacity", activeCapacity)
+ .add("pendingCapacity", pendingCapacity).add("desiredCapacity", "desiredCapacity").add("paused", "paused")
+ .add("groupInstances", "groupInstances");
+ }
+
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ @Override
+ public int compareTo(GroupState that) {
+ return this.getId().compareTo(that.getId());
+ }
+}