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:56 UTC
[2/3] Adds Otter (Rackspace Autoscale) to labs
https://issues.apache.org/jira/browse/JCLOUDS-215
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;
+ }
+}