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 2015/04/29 19:12:43 UTC
[1/2] jclouds-labs-openstack git commit: adding: StackApi Stack and
StackResource
Repository: jclouds-labs-openstack
Updated Branches:
refs/heads/master ea1e72905 -> ce4d93f82
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/stack_list_response.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/stack_list_response.json b/openstack-heat/src/test/resources/stack_list_response.json
new file mode 100644
index 0000000..66d2532
--- /dev/null
+++ b/openstack-heat/src/test/resources/stack_list_response.json
@@ -0,0 +1,19 @@
+{
+ "stacks": [
+ {
+ "creation_time": "2014-06-03T20:59:46Z",
+ "description": "sample stack",
+ "id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "links": [
+ {
+ "href": "http://192.168.123.200:8004/v1/eb1c63a4f77141548385f113a28f0f52/stacks/simple_stack/3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "rel": "self"
+ }
+ ],
+ "stack_name": "simple_stack",
+ "stack_status": "CREATE_COMPLETE",
+ "stack_status_reason": "Stack CREATE completed successfully",
+ "updated_time": "2014-06-03T20:59:46Z"
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/stack_resources_get_response.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/stack_resources_get_response.json b/openstack-heat/src/test/resources/stack_resources_get_response.json
new file mode 100644
index 0000000..0286dbd
--- /dev/null
+++ b/openstack-heat/src/test/resources/stack_resources_get_response.json
@@ -0,0 +1,23 @@
+{
+ "resource": {
+ "resource_name": "cinder_volume",
+ "description": "",
+ "links": [
+ {
+ "href": "http://10.20.20.11:8004/v1/ed902e7377e340a7a0d78e1dfeb15c62/stacks/StackIT_1424281004155/c749952a-dde7-4aba-83d1-f360217a93e0/resources/cinder_volume",
+ "rel": "self"
+ },
+ {
+ "href": "http://10.20.20.11:8004/v1/ed902e7377e340a7a0d78e1dfeb15c62/stacks/StackIT_1424281004155/c749952a-dde7-4aba-83d1-f360217a93e0",
+ "rel": "stack"
+ }
+ ],
+ "logical_resource_id": "cinder_volume",
+ "resource_status": "CREATE_COMPLETE",
+ "updated_time": "2015-02-18T17:36:45Z",
+ "required_by": [ ],
+ "resource_status_reason": "state changed",
+ "physical_resource_id": "f59b7a86-aee0-4f62-b190-606c4e08da7c",
+ "resource_type": "OS::Cinder::Volume"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/stack_resources_list_response.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/stack_resources_list_response.json b/openstack-heat/src/test/resources/stack_resources_list_response.json
new file mode 100644
index 0000000..32b842c
--- /dev/null
+++ b/openstack-heat/src/test/resources/stack_resources_list_response.json
@@ -0,0 +1,24 @@
+{
+ "resources": [
+ {
+ "resource_name": "cinder_volume",
+ "links": [
+ {
+ "href": "http://10.20.20.11:8004/v1/ed902e7377e340a7a0d78e1dfeb15c62/stacks/StackIT_1424281004155/c749952a-dde7-4aba-83d1-f360217a93e0/resources/cinder_volume",
+ "rel": "self"
+ },
+ {
+ "href": "http://10.20.20.11:8004/v1/ed902e7377e340a7a0d78e1dfeb15c62/stacks/StackIT_1424281004155/c749952a-dde7-4aba-83d1-f360217a93e0",
+ "rel": "stack"
+ }
+ ],
+ "logical_resource_id": "cinder_volume",
+ "resource_status_reason": "state changed",
+ "updated_time": "2015-02-18T17:36:45Z",
+ "required_by": [ ],
+ "resource_status": "CREATE_COMPLETE",
+ "physical_resource_id": "f59b7a86-aee0-4f62-b190-606c4e08da7c",
+ "resource_type": "OS::Cinder::Volume"
+ }
+ ]
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/stack_with_environment_and_files.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/stack_with_environment_and_files.json b/openstack-heat/src/test/resources/stack_with_environment_and_files.json
new file mode 100644
index 0000000..50934f8
--- /dev/null
+++ b/openstack-heat/src/test/resources/stack_with_environment_and_files.json
@@ -0,0 +1,21 @@
+{
+ "environment": {
+ "resource_registry": {
+ "ALU::LCP::VolumeB": "VolumeB.template.yaml"
+ }
+ },
+
+ "template": {
+
+ "heat_template_version": "2013-05-23",
+
+ "resources": {
+ "ALU-LCP-OAMB": {
+ "properties": {
+ "storage_size": 4
+ },
+ "type": "ALU::LCP::VolumeB"
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/stack_with_parameters.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/stack_with_parameters.json b/openstack-heat/src/test/resources/stack_with_parameters.json
new file mode 100644
index 0000000..6ace6b5
--- /dev/null
+++ b/openstack-heat/src/test/resources/stack_with_parameters.json
@@ -0,0 +1,25 @@
+{
+ "template": {
+ "heat_template_version": "2013-05-23",
+
+ "description": "Simple template to deploy a single compute instance",
+
+ "parameters": {
+ "key_name": {
+ "type": "string",
+ "label": "Key Name",
+ "description": "Name of key-pair to be used for compute instance"
+ }
+ },
+
+ "resources": {
+ "my_instance": {
+ "type": "OS::Nova::KeyPair",
+ "properties": {
+ "name": { "get_param": "key_name" }
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
[2/2] jclouds-labs-openstack git commit: adding: StackApi Stack and
StackResource
Posted by za...@apache.org.
adding: StackApi Stack and StackResource
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/commit/ce4d93f8
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/tree/ce4d93f8
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/diff/ce4d93f8
Branch: refs/heads/master
Commit: ce4d93f82c0210a5a58789cee8a7ff8fd8f9817d
Parents: ea1e729
Author: lbortman <li...@alcatel-lucent.com>
Authored: Wed Apr 8 11:05:19 2015 +0300
Committer: Zack Shoylev <za...@rackspace.com>
Committed: Wed Apr 29 12:09:08 2015 -0500
----------------------------------------------------------------------
openstack-heat/pom.xml | 13 +-
.../org/jclouds/openstack/heat/v1/HeatApi.java | 8 +
.../jclouds/openstack/heat/v1/domain/Stack.java | 150 +++++
.../openstack/heat/v1/domain/StackResource.java | 95 ++++
.../heat/v1/domain/StackResourceStatus.java | 57 ++
.../openstack/heat/v1/domain/StackStatus.java | 57 ++
.../openstack/heat/v1/features/StackApi.java | 123 +++++
.../openstack/heat/v1/options/CreateStack.java | 185 +++++++
.../heat/v1/options/ListStackOptions.java | 243 +++++++++
.../openstack/heat/v1/options/UpdateStack.java | 116 ++++
.../heat/v1/features/StackApiLiveTest.java | 321 +++++++++++
.../heat/v1/features/StackApiMockTest.java | 542 +++++++++++++++++++
.../heat/v1/options/ListStackOptionsTest.java | 109 ++++
.../src/test/resources/create_stack.json | 11 +
.../test/resources/files_for_atck_template.json | 33 ++
.../src/test/resources/resources_metadata.json | 6 +
.../src/test/resources/simple_stack.json | 21 +
.../src/test/resources/stack_get_response.json | 27 +
.../src/test/resources/stack_list_response.json | 19 +
.../resources/stack_resources_get_response.json | 23 +
.../stack_resources_list_response.json | 24 +
.../stack_with_environment_and_files.json | 21 +
.../test/resources/stack_with_parameters.json | 25 +
23 files changed, 2226 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/pom.xml
----------------------------------------------------------------------
diff --git a/openstack-heat/pom.xml b/openstack-heat/pom.xml
index 5d995f4..afe7870 100644
--- a/openstack-heat/pom.xml
+++ b/openstack-heat/pom.xml
@@ -96,14 +96,21 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>com.google.auto.service</groupId>
+ <artifactId>auto-service</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
+ <version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>com.google.auto.service</groupId>
- <artifactId>auto-service</artifactId>
- <scope>provided</scope>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1</version>
+ <scope>test</scope>
</dependency>
</dependencies>
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/HeatApi.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/HeatApi.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/HeatApi.java
index e1f9e25..9197b5a 100644
--- a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/HeatApi.java
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/HeatApi.java
@@ -22,6 +22,7 @@ import java.util.Set;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpoint;
import org.jclouds.openstack.heat.v1.features.ResourceApi;
+import org.jclouds.openstack.heat.v1.features.StackApi;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
@@ -42,4 +43,11 @@ public interface HeatApi extends Closeable {
*/
@Delegate
ResourceApi getResourceApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
+
+ /**
+ * Provides access to Stack features.
+ */
+ @Delegate
+ StackApi getStackApi(@EndpointParam(parser = RegionToEndpoint.class) String region);
}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/Stack.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/Stack.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/Stack.java
new file mode 100644
index 0000000..9b43eb8
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/Stack.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.domain;
+
+import autovalue.shaded.com.google.common.common.collect.ImmutableMap;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Representation of an OpenStack Heat Stack.
+ */
+@AutoValue
+public abstract class Stack {
+
+ /**
+ * @return Specifies the Stack ID . The value is a UUID, such as 96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0.
+ */
+ public abstract String getId();
+
+ /**
+ * @return Specifies the name of the stack
+ */
+ @Nullable public abstract String getName();
+
+ /**
+ * @return the template description of this Stack.
+ */
+ @Nullable public abstract String getTemplateDescription();
+
+ /**
+ * @return the description of this Stack.
+ */
+ @Nullable public abstract String getDescription();
+
+ /**
+ * @return the owner of this Stack.
+ */
+ @Nullable public abstract String getOwner();
+
+ /**
+ * @return the project ID of the stack
+ */
+ @Nullable public abstract String getProject();
+
+ /**
+ * @return the parameters of this Stack.
+ */
+ @Nullable public abstract Map<String, String> getParameters();
+
+ /**
+ * @return the capabilities of this Stack.
+ */
+ @Nullable public abstract Set<String> getCapabilities();
+
+ /**
+ * @return the outputs of this Stack.
+ */
+ @Nullable public abstract List<String> getOutputs();
+
+ /**
+ * @return the notification topics of this Stack.
+ */
+ @Nullable public abstract List<String> getNotificationTopics();
+
+ /**
+ * @return the status of this Stack.
+ */
+ @Nullable public abstract StackStatus getStatus();
+
+ /**
+ * @return the status reason of this Stack.
+ */
+ @Nullable public abstract String getSatusReason();
+
+ /**
+ * @return the date this Stack was created.
+ */
+ @Nullable public abstract Date getCreated();
+
+ /**
+ * @return the date this Stack was last updated.
+ */
+ @Nullable public abstract Date getUpdated();
+
+ /**
+ * @return the timeout of this Stack (in minutes).
+ */
+ public abstract int getTimeoutMins();
+
+ /**
+ * @return true is disableRollback is true
+ */
+ public abstract boolean isDisableRollback();
+
+ /**
+ * @return Specifies the self-navigating JSON document paths.
+ */
+ public abstract Set<Link> getLinks();
+
+ @SerializedNames({"id", "stack_name", "description", "owner", "capabilities", "parameters", "outputs",
+ "notification_topics", "template_description", "stack_status", "stack_status_reason", "creation_time",
+ "updated_time", "timeout_mins", "disable_rollback", "project", "links"})
+ private static Stack create(String id, String name, String description, String owner, Set<String> capabilities,
+ Map<String, String> parameters, List<String> outputs, List<String> notificationTopics,
+ String templateDescription, StackStatus status, String statusReason, Date created, Date updated, int timeoutMins,
+ boolean disableRollback, String project, Set<Link> links) {
+ return new AutoValue_Stack(
+ id,
+ name,
+ templateDescription,
+ description,
+ owner,
+ project,
+ parameters != null ? ImmutableMap.copyOf(parameters) : null,
+ capabilities != null ? ImmutableSet.copyOf(capabilities) : null,
+ outputs != null ? ImmutableList.copyOf(outputs) : null,
+ notificationTopics != null ? ImmutableList.copyOf(notificationTopics) : null,
+ status,
+ statusReason,
+ created,
+ updated,
+ timeoutMins,
+ disableRollback,
+ ImmutableSet.copyOf(links));
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResource.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResource.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResource.java
new file mode 100644
index 0000000..5d17764
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResource.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+import org.jclouds.openstack.v2_0.domain.Link;
+
+import java.util.Date;
+import java.util.Set;
+
+/**
+ * Representation of an OpenStack Heat Stack Resources.
+ */
+@AutoValue
+public abstract class StackResource {
+
+ /**
+ * @return Specifies the name of the stack
+ */
+ public abstract String getName();
+
+ /**
+ * @return logical resource ID.
+ */
+ public abstract String getLogicalResourceId();
+
+ /**
+ * @return physical resource ID.
+ */
+ public abstract String getPhysicalResourceId();
+
+ /**
+ * @return the status
+ */
+ public abstract StackResourceStatus getStatus();
+
+ /**
+ * @return Status reason
+ */
+ public abstract String getStatusReason();
+
+ /**
+ * @return the field required_by
+ */
+ @Nullable public abstract Set<String> getRequiredBy();
+
+ /**
+ * @return the resource type
+ */
+ public abstract String getResourceType();
+
+ /**
+ * @return the update time
+ */
+ public abstract Date getUpdated();
+
+ /**
+ * @return Specifies the self-navigating JSON document paths.
+ */
+ public abstract Set<Link> getLinks();
+
+ @SerializedNames({"resource_name", "logical_resource_id", "resource_status_reason", "updated_time", "required_by", "resource_status", "physical_resource_id", "resource_type", "links"})
+ private static StackResource create(String name, String logicalResourceId, String statusReason, Date updated, @Nullable Set<String> requiredBy,
+ StackResourceStatus status, String physicalResourceId, String resourceType, Set<Link> links) {
+ return new AutoValue_StackResource(
+ name,
+ logicalResourceId,
+ physicalResourceId,
+ status,
+ statusReason,
+ requiredBy != null ? ImmutableSet.copyOf(requiredBy) : null,
+ resourceType,
+ updated,
+ ImmutableSet.copyOf(links));
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResourceStatus.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResourceStatus.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResourceStatus.java
new file mode 100644
index 0000000..5f06a3c
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackResourceStatus.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.domain;
+
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public enum StackResourceStatus {
+ INIT_COMPLETE, CREATE_IN_PROGRESS, CREATE_COMPLETE, CREATE_FAILED,
+ UPDATE_IN_PROGRESS, UPDATE_COMPLETE, UPDATE_FAILED,
+ DELETE_IN_PROGRESS, DELETE_COMPLETE, DELETE_FAILED,
+ ROLLBACK_IN_PROGRESS, ROLLBACK_COMPLETE, ROLLBACK_FAILED,
+ SUSPEND_IN_PROGRESS, SUSPEND_COMPLETE, SUSPEND_FAILED,
+ RESUME_IN_PROGRESS, RESUME_COMPLETE, RESUME_FAILED,
+ UNRECOGNIZED;
+
+ public String value() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
+ }
+
+ @Override
+ public String toString() {
+ return value();
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ *
+ * @param name The string representation of this enum value.
+ * @return The corresponding enum value.
+ */
+
+ public static StackResourceStatus fromValue(String status) {
+ try {
+ return valueOf(checkNotNull(status, "status"));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackStatus.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackStatus.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackStatus.java
new file mode 100644
index 0000000..8d318e6
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/domain/StackStatus.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.domain;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public enum StackStatus {
+ CREATE_IN_PROGRESS, CREATE_COMPLETE, CREATE_FAILED,
+ UPDATE_IN_PROGRESS, UPDATE_COMPLETE, UPDATE_FAILED,
+ DELETE_IN_PROGRESS, DELETE_COMPLETE, DELETE_FAILED,
+ ROLLBACK_IN_PROGRESS, ROLLBACK_COMPLETE, ROLLBACK_FAILED,
+ SUSPEND_IN_PROGRESS, SUSPEND_COMPLETE, SUSPEND_FAILED,
+ RESUME_IN_PROGRESS, RESUME_COMPLETE, RESUME_FAILED,
+ UNRECOGNIZED;
+
+ public String value() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name());
+ }
+
+ @Override
+ public String toString() {
+ return value();
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ *
+ * @param name The string representation of this enum value.
+ * @return The corresponding enum value.
+ */
+
+ public static StackStatus fromValue(String status) {
+ try {
+ return valueOf(checkNotNull(status, "status"));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ } catch (NullPointerException e){
+ return UNRECOGNIZED;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/features/StackApi.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/features/StackApi.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/features/StackApi.java
new file mode 100644
index 0000000..271d9a4
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/features/StackApi.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.features;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.heat.v1.domain.Stack;
+import org.jclouds.openstack.heat.v1.domain.StackResource;
+import org.jclouds.openstack.heat.v1.options.CreateStack;
+import org.jclouds.openstack.heat.v1.options.ListStackOptions;
+import org.jclouds.openstack.heat.v1.options.UpdateStack;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+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.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Provides access to the OpenStack Orchestration (Heat) Stack API features.
+ */
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+@Path("/stacks")
+public interface StackApi {
+
+ @Named("stack:list")
+ @GET
+ @SelectJson("stacks")
+ @Fallback(EmptyListOnNotFoundOr404.class)
+ List<Stack> list();
+
+ @Named("stack:list")
+ @GET
+ @SelectJson("stacks")
+ @Fallback(EmptyListOnNotFoundOr404.class)
+ List<Stack> list(ListStackOptions options);
+
+ @Named("stack:get")
+ @GET
+ @SelectJson("stack")
+ @Path("/{stack_name}/{stack_id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ @Nullable
+ Stack get(@PathParam("stack_name") String name, @PathParam("stack_id") String id);
+
+ @Named("stack:get")
+ @GET
+ @SelectJson("stack")
+ @Path("/{id}")
+ @Fallback(NullOnNotFoundOr404.class)
+ Stack get(@PathParam("id") String stackId);
+
+ @Named("stack:create")
+ @POST
+ @SelectJson("stack")
+ Stack create(@BinderParam(BindToJsonPayload.class) CreateStack options);
+
+ @Named("stack:delete")
+ @DELETE
+ @Path("/{stack_name}/{stack_id}")
+ @Fallback(FalseOnNotFoundOr404.class)
+ boolean delete(@PathParam("stack_name") String name, @PathParam("stack_id") String id);
+
+ @Named("stack:update")
+ @PUT
+ @Path("/{stack_name}/{stack_id}")
+ @Nullable
+ boolean update(@PathParam("stack_name") String name, @PathParam("stack_id") String id, @BinderParam(BindToJsonPayload.class) UpdateStack options);
+
+
+ @Named("stack:list_resources")
+ @GET
+ @SelectJson("resources")
+ @Path("/{stack_name}/{stack_id}/resources")
+ @Fallback(EmptyListOnNotFoundOr404.class)
+ List<StackResource> listStackResources(@PathParam("stack_name") String stackName, @PathParam("stack_id") String stackId);
+
+ @Named("stack:get_resources")
+ @GET
+ @SelectJson("resource")
+ @Path("/{stack_name}/{stack_id}/resources/{resource_name}")
+ @Fallback(NullOnNotFoundOr404.class)
+ StackResource getStackResource(@PathParam("stack_name") String stackName, @PathParam("stack_id") String stackId, @PathParam("resource_name") String name);
+
+ @Named("stack:get_resources_metadata")
+ @GET
+ @SelectJson("metadata")
+ @Path("/{stack_name}/{stack_id}/resources/{resource_name}/metadata")
+ @Fallback(EmptyMapOnNotFoundOr404.class)
+ Map<String, Object> getStackResourceMetadata(@PathParam("stack_name") String stackName, @PathParam("stack_id") String stackId, @PathParam("resource_name") String name);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/CreateStack.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/CreateStack.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/CreateStack.java
new file mode 100644
index 0000000..864d090
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/CreateStack.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.options;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Map;
+
+/**
+ * Representation of create stack options.
+ */
+@AutoValue
+public abstract class CreateStack {
+
+ /**
+ * @see Builder#name(String)
+ */
+ public abstract String getName();
+
+ /**
+ * @see Builder#template(String)
+ */
+ @Nullable public abstract String getTemplate();
+
+ /**
+ * @see Builder#templateUrl(String)
+ */
+ @Nullable public abstract String getTemplateUrl();
+
+ /**
+ * @see Builder#parameters(Map<String, Object>)
+ */
+ @Nullable public abstract Map<String, Object> getParameters();
+
+ /**
+ * @see Builder#disableRollback(boolean)
+ */
+ public abstract boolean isDisableRollback();
+
+ /**
+ * @see Builder#files(Map<String, String>)
+ */
+ @Nullable public abstract Map<String, String> getFiles();
+
+ /**
+ * @see Builder#environment(String)
+ */
+ @Nullable public abstract String getEnvironment();
+
+ public static Builder builder() {
+ return new AutoValue_CreateStack.Builder().disableRollback(true).files(null).environment(null);
+ }
+
+ public Builder toBuilder() {
+ return builder()
+ .name(getName())
+ .template(getTemplate())
+ .templateUrl(getTemplateUrl())
+ .parameters(getParameters())
+ .disableRollback(isDisableRollback())
+ .files(getFiles())
+ .environment(getEnvironment());
+ }
+
+ @SerializedNames({"stack_name", "template", "template_url", "parameters", "disable_rollback", "files", "environment" })
+ private static CreateStack create(String name, @Nullable String template, @Nullable String templateUrl, @Nullable Map<String, Object> parameters, boolean disableRollback, @Nullable Map<String, String> files, @Nullable String environment) {
+ return builder()
+ .name(name)
+ .template(template)
+ .templateUrl(templateUrl)
+ .parameters(parameters)
+ .disableRollback(disableRollback)
+ .files(files)
+ .environment(environment).build();
+ }
+
+ public static final class Builder {
+
+ private String name;
+ private String template;
+ private String templateUrl;
+ private Map<String, Object> parameters;
+ private boolean disableRollback = true;
+ private Map<String, String> files;
+ private String environment;
+
+ Builder() {
+ }
+
+ Builder(CreateStack source) {
+ name(source.getName());
+ template(source.getTemplate());
+ templateUrl(source.getTemplateUrl());
+ parameters(source.getParameters());
+ disableRollback(source.isDisableRollback());
+ files(source.getFiles());
+ environment(source.getEnvironment());
+ }
+
+ /**
+ * @param name - The name of the stack
+ */
+ public Builder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param template - The stack template to instantiate.
+ */
+ public Builder template(String template) {
+ this.template = template;
+ return this;
+ }
+
+ /**
+ * @param templateUrl - A URI to the location containing the stack template to instantiate.
+ */
+ public Builder templateUrl(String templateUrl) {
+ this.templateUrl = templateUrl;
+ return this;
+ }
+
+ /**
+ * @param parameters - The properties for the template
+ */
+ public Builder parameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ return this;
+ }
+
+ /**
+ * @param disableRollback - Controls whether a failure during stack creation causes deletion of all previously-created resources in that stack. The default is True
+ */
+ public Builder disableRollback(boolean disableRollback) {
+ this.disableRollback = disableRollback;
+ return this;
+ }
+
+ /**
+ * @param files - The properties for the template
+ */
+ public Builder files(Map<String, String> files) {
+ this.files = files;
+ return this;
+ }
+
+ /**
+ * @param environment - used to affect the runtime behaviour of the template
+ */
+ public Builder environment(String environment) {
+ this.environment = environment;
+ return this;
+ }
+
+ public CreateStack build() {
+ CreateStack result = new AutoValue_CreateStack(
+ this.name,
+ this.template,
+ this.templateUrl,
+ this.parameters != null ? ImmutableMap.copyOf(this.parameters) : null,
+ this.disableRollback,
+ this.files != null ? ImmutableMap.copyOf(this.files) : null,
+ this.environment);
+ return result;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/ListStackOptions.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/ListStackOptions.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/ListStackOptions.java
new file mode 100644
index 0000000..9f85b08
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/ListStackOptions.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.options;
+
+import com.google.common.base.CaseFormat;
+import org.jclouds.openstack.heat.v1.domain.StackStatus;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Options used to control the amount of detail in the request.
+ *
+ * @see PaginationOptions
+ */
+public class ListStackOptions extends PaginationOptions {
+
+ public static final ListStackOptions NONE = new ListStackOptions();
+
+ public enum SortDirection {
+ ASCENDING("asc"),
+ DESCENDING("desc"),
+ UNRECOGNIZED("unrecognized");
+
+ private String name;
+
+ private SortDirection(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ *
+ * @param name The string representation of this enum value.
+ * @return The corresponding enum value.
+ */
+ public static SortDirection fromValue(String direction) {
+ if (direction != null) {
+ for (SortDirection value : SortDirection.values()) {
+ if (direction.equalsIgnoreCase(value.name)) {
+ return value;
+ }
+ }
+ }
+ return UNRECOGNIZED;
+ }
+
+ public static boolean contains(SortDirection direction) {
+ for (SortDirection dir : SortDirection.values()) {
+ if (dir.equals(direction)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public enum SortKey {
+ NAME, STATUS, CREATED_AT, UPDATED_AT,
+ UNRECOGNIZED;
+
+ public String value() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_UNDERSCORE, name());
+ }
+
+ @Override
+ public String toString() {
+ return value();
+ }
+
+ /**
+ * This provides GSON enum support in jclouds.
+ *
+ * @param name The string representation of this enum value.
+ * @return The corresponding enum value.
+ */
+
+ public static SortKey fromValue(String sortKey) {
+ try {
+ return valueOf(checkNotNull(sortKey, "sortKey"));
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+
+ public static boolean contains(String sortKey) {
+ for (SortKey key : SortKey.values()) {
+ if (key.value().equals(sortKey)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean contains(SortKey sortKey) {
+ for (SortKey key : SortKey.values()) {
+ if (key.equals(sortKey)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ListStackOptions limit(int limit) {
+ super.limit(limit);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ListStackOptions marker(String marker) {
+ super.marker(marker);
+ return this;
+ }
+
+ /**
+ * Filters the stack list by the specified status. You can use this filter multiple
+ * times to filter by multiple statuses.
+ */
+ public ListStackOptions status(StackStatus status) {
+ this.queryParameters.put("status", checkNotNull(status.toString(), "status"));
+ return this;
+ }
+
+ /**
+ * Filters the stack list by the specified name.
+ */
+ public ListStackOptions name(String name) {
+ this.queryParameters.put("name", checkNotNull(name, "name"));
+ return this;
+ }
+
+ /**
+ * Return all the stack of all the tenant
+ */
+ public ListStackOptions globalTenant(Boolean globalTenant) {
+ this.queryParameters.put("global_tenant", globalTenant != null ? Boolean.toString(globalTenant) : "false");
+ return this;
+ }
+
+ /**
+ * Sorts the stack list by one of these attributes:
+ * name, status, created_at, or updated_at
+ */
+ public ListStackOptions sortKey(SortKey key) {
+ checkState(SortKey.contains(key), "invalid sort key");
+ this.queryParameters.put("sort_keys", checkNotNull(key.toString(), "key"));
+ return this;
+ }
+
+ /**
+ * The sort direction of the stack list. Either asc (ascending) or desc (descending).
+ */
+ public ListStackOptions sortDirection(SortDirection direction) {
+ checkState(SortDirection.contains(direction), "direction is either asc or desc");
+ this.queryParameters.put("sort_dir", checkNotNull(direction.toString(), "direction"));
+ return this;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ /**
+ * @see PaginationOptions#limit(int)
+ */
+ public static ListStackOptions limit(int limit) {
+ return new ListStackOptions().limit(limit);
+ }
+
+ /**
+ * @see PaginationOptions#marker(String)
+ */
+ public static ListStackOptions marker(String marker) {
+ return new ListStackOptions().marker(marker);
+ }
+
+ /**
+ * @see ListStackOptions#status(String)
+ */
+ public static ListStackOptions status(StackStatus status) {
+ return new ListStackOptions().status(status);
+ }
+
+ /**
+ * @see ListStackOptions#name(String)
+ */
+ public static ListStackOptions name(String name) {
+ return new ListStackOptions().name(name);
+ }
+
+ /**
+ * @see ListStackOptions#sortKey(String)
+ */
+ public static ListStackOptions sortKey(SortKey key) {
+ return new ListStackOptions().sortKey(key);
+ }
+
+ /**
+ * @see ListStackOptions#sortDirection(String)
+ */
+ public static ListStackOptions sortDirection(SortDirection direction) {
+ return new ListStackOptions().sortDirection(direction);
+ }
+
+ /**
+ * @see ListStackOptions#globalTenant(Boolean
+ */
+ public static ListStackOptions globalTenant(Boolean globalTenant) {
+ return new ListStackOptions().globalTenant(globalTenant);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/UpdateStack.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/UpdateStack.java b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/UpdateStack.java
new file mode 100644
index 0000000..b1f7640
--- /dev/null
+++ b/openstack-heat/src/main/java/org/jclouds/openstack/heat/v1/options/UpdateStack.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.options;
+
+
+import autovalue.shaded.com.google.common.common.collect.ImmutableMap;
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Map;
+
+/**
+ * Representation of updatable options
+ */
+@AutoValue
+public abstract class UpdateStack {
+
+ /**
+ * @see Builder#template(String)
+ */
+ @Nullable public abstract String getTemplate();
+
+ /**
+ * @see Builder#templateUrl(String)
+ */
+ @Nullable public abstract String getTemplateUrl();
+
+ /**
+ * @see Builder#parameters(java.util.Map)
+ */
+ @Nullable public abstract Map<String, Object> getParameters();
+
+ public static Builder builder() {
+ return new AutoValue_UpdateStack.Builder().parameters(null);
+ }
+
+ public Builder toBuilder() {
+ return builder()
+ .template(getTemplate())
+ .templateUrl(getTemplateUrl())
+ .parameters(getParameters());
+ }
+
+ @SerializedNames({"template", "template_url", "parameters"})
+ private static UpdateStack create(@Nullable String template, @Nullable String templateUrl, @Nullable Map<String, Object> parameters) {
+ return builder()
+ .template(template)
+ .templateUrl(templateUrl)
+ .parameters(parameters).build();
+ }
+
+
+ public static final class Builder {
+
+ private String template;
+ private String templateUrl;
+ private Map<String, Object> parameters;
+
+ Builder() {
+ }
+
+ Builder(CreateStack source) {
+ template(source.getTemplate());
+ templateUrl(source.getTemplateUrl());
+ parameters(source.getParameters());
+ }
+
+ /**
+ * @see UpdateStack#getTemplate()
+ */
+ public Builder template(String template) {
+ this.template = template;
+ return this;
+ }
+
+ /**
+ * @see UpdateStack#getTemplateUrl()
+ */
+ public Builder templateUrl(String templateUrl) {
+ this.templateUrl = templateUrl;
+ return this;
+ }
+
+ /**
+ * @see UpdateStack#getParameters()
+ */
+ public Builder parameters(Map<String, Object> parameters) {
+ this.parameters = parameters;
+ return this;
+ }
+
+ public UpdateStack build() {
+ UpdateStack result = new AutoValue_UpdateStack(
+ this.template,
+ this.templateUrl,
+ parameters != null ? ImmutableMap.copyOf(this.parameters) : null);
+ return result;
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiLiveTest.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiLiveTest.java b/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiLiveTest.java
new file mode 100644
index 0000000..f9e30a0
--- /dev/null
+++ b/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiLiveTest.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.features;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Throwables;
+import org.jclouds.openstack.heat.v1.domain.Stack;
+import org.jclouds.openstack.heat.v1.domain.StackResource;
+import org.jclouds.openstack.heat.v1.domain.StackResourceStatus;
+import org.jclouds.openstack.heat.v1.domain.StackStatus;
+import org.jclouds.openstack.heat.v1.internal.BaseHeatApiLiveTest;
+import org.jclouds.openstack.heat.v1.options.CreateStack;
+import org.jclouds.openstack.heat.v1.options.UpdateStack;
+import org.jclouds.util.Strings2;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.util.Predicates2.retry;
+
+/**
+ * Tests parsing and Guice wiring of StackApi
+ */
+@Test(groups = "live", testName = "StackApiLiveTest")
+public class StackApiLiveTest extends BaseHeatApiLiveTest {
+
+ public static final String TEMPLATE_URL = "http://10.5.5.121/Installs/cPaaS/YAML/simple_stack.yaml";
+ protected String stackName = System.getProperty("user.name").replace('.', '-').toLowerCase();
+
+ public void testList() {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+
+ List<Stack> stacks = stackApi.list();
+
+ assertThat(stacks).isNotEmpty();
+
+ int oldStackSize = stacks.size();
+ CreateStack createStack = CreateStack.builder().name(getName()).templateUrl(TEMPLATE_URL).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ stacks = stackApi.list();
+ assertThat(stacks.size()).isEqualTo(oldStackSize + 1);
+ }
+ }
+
+
+ public void testGetStackWitnNameAndID() {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+
+ List<Stack> stacks = stackApi.list();
+ assertThat(stacks).isNotNull();
+
+ Stack stack = stackApi.get(stacks.get(0).getName(), stacks.get(0).getId());
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isEqualTo(stacks.get(0).getId());
+ }
+ }
+
+ public void testGetStack() {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+
+ List<Stack> stacks = stackApi.list();
+ assertThat(stacks).isNotNull();
+
+ Stack stack = stackApi.get(stacks.get(0).getId());
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isEqualTo(stacks.get(0).getId());
+ }
+ }
+
+ public void testCreateWithTempletUrl() {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ CreateStack createStack = CreateStack.builder().name(getName()).templateUrl(TEMPLATE_URL).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+
+ }
+ }
+
+ public void testDeleteStack() {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ String stackName = getName();
+ CreateStack createStack = CreateStack.builder().name(stackName).templateUrl(TEMPLATE_URL).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+ assertThat(stackApi.delete(stackName, stack.getId())).isTrue();
+ Stack stackAfterDelete = stackApi.get(stackName, stack.getId());
+ assertThat(stackAfterDelete).isNotNull();
+ }
+ }
+
+ public void testCreateWithDisableRollback() {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ CreateStack createStack = CreateStack.builder().name(getName()).templateUrl(TEMPLATE_URL).disableRollback(false).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+ assertThat(stack.isDisableRollback()).isFalse();
+
+ }
+ }
+
+ public void testCreateWithTemplate() throws ParseException {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ JSONParser parser = new JSONParser();
+ Object obj = parser.parse(stringFromResource("/simple_stack.json"));
+
+ JSONObject jsonObject = (JSONObject) obj;
+
+ CreateStack createStack = CreateStack.builder().name(getName()).template(String.valueOf(jsonObject.get("template"))).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+ }
+ }
+
+ public void testUpdateStack() throws ParseException {
+ for (String region : api.getConfiguredRegions()) {
+ final StackApi stackApi = api.getStackApi(region);
+ JSONParser parser = new JSONParser();
+ Object obj = parser.parse(stringFromResource("/simple_stack.json"));
+
+ JSONObject jsonObject = (JSONObject) obj;
+
+ String stackName = getName();
+ CreateStack createStack = CreateStack.builder().name(stackName).template(String.valueOf(jsonObject.get("template"))).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ String stackId = stack.getId();
+ assertThat(stackId).isNotEmpty();
+
+ boolean success = retry(new Predicate<String>() {
+ public boolean apply(String stackId) {
+ return stackApi.get(stackId).getStatus() == StackStatus.CREATE_COMPLETE;
+ }
+
+ }, 60, 1, SECONDS).apply(stackId);
+
+ if (!success) {
+ Assert.fail("Stack didn't get to status CREATE_COMPLETE in 20m.");
+ }
+
+ UpdateStack updateOptions = UpdateStack.builder().templateUrl(TEMPLATE_URL).build();
+ assertThat(stackApi.update(stackName, stack.getId(), updateOptions)).isTrue();
+ Stack stackAfterUpdate = stackApi.get(stackName, stack.getId());
+ assertThat(stackAfterUpdate.getStatus()).isEqualTo(StackStatus.UPDATE_IN_PROGRESS);
+
+ }
+ }
+
+ public void testCreateWithParameters() throws ParseException {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ Map<String, Object> parameters = new HashMap<String, Object>();
+ parameters.put("key_name", "myKey");
+
+ JSONParser parser = new JSONParser();
+ Object obj = parser.parse(stringFromResource("/stack_with_parameters.json"));
+
+ JSONObject jsonObject = (JSONObject) obj;
+
+ CreateStack createStack = CreateStack.builder().name(getName()).template(String.valueOf(jsonObject.get("template")))
+ .parameters(parameters).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+
+ Stack stackFromList = stackApi.get(stack.getId());
+ assertThat(stackFromList).isNotNull();
+ assertThat(stackFromList.getId()).isEqualTo(stack.getId());
+ for (String parmName : parameters.keySet()) {
+ assertThat(stackFromList.getParameters().containsKey(parmName)).isTrue();
+ }
+
+ }
+ }
+
+ public void testCreateWithFilesAndEnvironment() throws IOException, ParseException {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ JSONParser parser = new JSONParser();
+ Object obj = parser.parse(stringFromResource("/stack_with_environment_and_files.json"));
+ JSONObject jsonObject = (JSONObject) obj;
+
+ Object objFilesJsone = parser.parse(stringFromResource("/files_for_atck_template.json"));
+ JSONObject filesAsJason = (JSONObject) objFilesJsone;
+ Map<String, String> files = new HashMap<String, String>();
+ files.put("VolumeB.template.yaml", String.valueOf(filesAsJason.get("VolumeB.template.yaml")));
+
+ CreateStack createStack = CreateStack.builder().name(getName())
+ .template(String.valueOf(jsonObject.get("template")))
+ .environment(String.valueOf(jsonObject.get("environment")))
+ .files(files).build();
+
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+ }
+ }
+
+ public void testListAndGetStackResources() throws ParseException {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ JSONParser parser = new JSONParser();
+ Object obj = parser.parse(stringFromResource("/stack_with_parameters.json"));
+
+ JSONObject jsonObject = (JSONObject) obj;
+ Map<String, Object> parameters = new HashMap<String, Object>();
+ parameters.put("key_name", "myKey");
+
+ String stackName = getName();
+ CreateStack createStack = CreateStack.builder().name(stackName).template(String.valueOf(jsonObject.get("template"))).parameters(parameters).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+ List<StackResource> resources = stackApi.listStackResources(stackName, stack.getId());
+ assertThat(resources).isNotNull();
+ assertThat(resources).isNotEmpty();
+ for (StackResource stackResource : resources) {
+ assertThat(stackResource).isNotNull();
+ String stackResourceName = stackResource.getName();
+ assertThat(stackResourceName).isNotNull();
+ assertThat(stackResourceName).isNotEmpty();
+ assertThat(stackResource.getStatus()).isNotEqualTo(StackResourceStatus.UNRECOGNIZED);
+ StackResource resourceFromGet = stackApi.getStackResource(stackName, stack.getId(), stackResourceName);
+ assertThat(resourceFromGet).isNotNull();
+ assertThat(resourceFromGet.getName()).isEqualTo(stackResourceName);
+ }
+ }
+ }
+
+ public void testGetStackResourceMetadata() throws ParseException {
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ JSONParser parser = new JSONParser();
+ Object obj = parser.parse(stringFromResource("/simple_stack.json"));
+
+ JSONObject jsonObject = (JSONObject) obj;
+
+ String stackName = getName();
+ CreateStack createStack = CreateStack.builder().name(stackName).template(String.valueOf(jsonObject.get("template"))).build();
+ Stack stack = stackApi.create(createStack);
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isNotEmpty();
+ List<StackResource> resources = stackApi.listStackResources(stackName, stack.getId());
+ assertThat(resources).isNotNull();
+ assertThat(resources).isNotEmpty();
+ for (StackResource stackResource : resources) {
+ assertThat(stackResource).isNotNull();
+ String stackResourceName = stackResource.getName();
+ assertThat(stackResourceName).isNotNull();
+ assertThat(stackResourceName).isNotEmpty();
+ assertThat(stackResource.getStatus()).isNotEqualTo(StackResourceStatus.UNRECOGNIZED);
+ Map metadata = stackApi.getStackResourceMetadata(stackName, stack.getId(), stackResourceName);
+ assertThat(metadata).isNotNull();
+ assertThat(metadata).isNotEmpty();
+ }
+ }
+ }
+
+ @AfterClass
+ public void cleanup(){
+
+ for (String region : api.getConfiguredRegions()) {
+ StackApi stackApi = api.getStackApi(region);
+ List<Stack> stacks = stackApi.list();
+ for (Stack stack : stacks){
+ if (stack.getName().startsWith(stackName)){
+ stackApi.delete(stack.getName(), stack.getId());
+ }
+ }
+ }
+
+ }
+
+ private String getName() {
+ return stackName + "_" + System.currentTimeMillis();
+ }
+
+ private String stringFromResource(String resourceName) {
+ try {
+ return Strings2.toStringAndClose(getClass().getResourceAsStream(resourceName));
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiMockTest.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiMockTest.java b/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiMockTest.java
new file mode 100644
index 0000000..54ce022
--- /dev/null
+++ b/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/features/StackApiMockTest.java
@@ -0,0 +1,542 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.features;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+import org.jclouds.openstack.heat.v1.HeatApi;
+import org.jclouds.openstack.heat.v1.domain.Stack;
+import org.jclouds.openstack.heat.v1.domain.StackResource;
+import org.jclouds.openstack.heat.v1.internal.BaseHeatApiMockTest;
+import org.jclouds.openstack.heat.v1.options.CreateStack;
+import org.jclouds.openstack.heat.v1.options.ListStackOptions;
+import org.jclouds.openstack.heat.v1.options.UpdateStack;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests annotation parsing of {@code StackApi}
+ */
+@Test(groups = "unit", testName = "StackApiMockTest")
+public class StackApiMockTest extends BaseHeatApiMockTest {
+
+ public static final String TEST_STACK_NAME = "testStack";
+ public static final String TEST_STACK_ID = "testStack";
+ public static final String RESOURCES_TEST_NAME = "testResources";
+ public static final String TEST_STACK_RESOURCE_NAME = "cinder_volume";
+
+
+ public void testGetAutoStack() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(200).setBody(stringFromResource("/stack_get_response.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Stack stack = api.get("simple_stack", "3095aefc-09fb-4bc7-b1f0-f21a304e864c");
+
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/simple_stack/3095aefc-09fb-4bc7-b1f0-f21a304e864c");
+
+
+ assertThat(stack).isNotNull();
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetStackFail() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Stack stack = api.get("Non_Existing_Stack", "Non-Existing-Stack");
+
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/Non_Existing_Stack/Non-Existing-Stack");
+
+ assertNull(stack);
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGeStackWithIDOnly() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(200).setBody(stringFromResource("/stack_get_response.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Stack stack = api.get("3095aefc-09fb-4bc7-b1f0-f21a304e864c");
+
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/3095aefc-09fb-4bc7-b1f0-f21a304e864c");
+
+
+ assertThat(stack).isNotNull();
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetStackWithIDOnlyFail() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Stack stack = api.get("Non-Existing-Stack");
+
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/Non-Existing-Stack");
+
+ assertNull(stack);
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetStackResourceFail() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ StackResource stackResource = api.getStackResource(TEST_STACK_NAME, TEST_STACK_ID, "Non_Existing_Stack_resource");
+
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID + "/resources/Non_Existing_Stack_resource");
+
+ assertNull(stackResource);
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+
+ public void testList() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(200).setBody(stringFromResource("/stack_list_response.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ List<Stack> stacks = api.list();
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks");
+
+ /*
+ * Check response
+ */
+ assertThat(stacks).isNotEmpty();
+ assertThat(stacks.size()).isEqualTo(1);
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListWithOptions() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(200).setBody(stringFromResource("/stack_list_response.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ ListStackOptions options = ListStackOptions.Builder.name("simple_stack");
+
+ List<Stack> stacks = api.list(options);
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks?name=simple_stack");
+
+ /*
+ * Check response
+ */
+ assertThat(stacks).isNotEmpty();
+ assertThat(stacks.size()).isEqualTo(1);
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListResource() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(200).setBody(stringFromResource("/stack_resources_list_response.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ List<StackResource> stackResources = api.listStackResources(TEST_STACK_NAME, TEST_STACK_ID);
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID + "/resources");
+
+ /*
+ * Check response
+ */
+ assertThat(stackResources).isNotEmpty();
+ assertThat(stackResources.size()).isEqualTo(1);
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetResource() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(200).setBody(stringFromResource("/stack_resources_get_response.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ StackResource stackResource = api.getStackResource(TEST_STACK_NAME, TEST_STACK_ID, TEST_STACK_RESOURCE_NAME);
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID + "/resources/" + TEST_STACK_RESOURCE_NAME);
+
+ /*
+ * Check response
+ */
+ assertThat(stackResource).isNotNull();
+ assertThat(stackResource.getName()).isNotNull();
+ assertThat(stackResource.getName()).isNotEmpty();
+ assertThat(stackResource.getLogicalResourceId()).isNotNull();
+ assertThat(stackResource.getLogicalResourceId()).isNotEmpty();
+ assertThat(stackResource.getPhysicalResourceId()).isNotNull();
+ assertThat(stackResource.getPhysicalResourceId()).isNotEmpty();
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListIsEmpty() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ List<Stack> stacks = api.list();
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks");
+
+ /*
+ * Check response
+ */
+ assertThat(stacks).isEmpty();
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListWithOptionsIsEmpty() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ ListStackOptions options = ListStackOptions.Builder.name("Stack_dont_exist");
+ List<Stack> stacks = api.list(options);
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks?name=Stack_dont_exist");
+
+ /*
+ * Check response
+ */
+ assertThat(stacks).isEmpty();
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListStackResourceIsEmpty() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ List<StackResource> stackResources = api.listStackResources("empty_stack", "empty_stack_id");
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/empty_stack/empty_stack_id/resources");
+
+ /*
+ * Check response
+ */
+ assertThat(stackResources).isEmpty();
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testCreateWithTemplateUrl() throws Exception {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/create_stack.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("key_name", "myKey");
+ parameters.put("image_id", "3b7be1fa-d381-4067-bb81-e835df630564");
+ parameters.put("instance_type", "SMALL_1");
+ CreateStack createStack = CreateStack.builder().name(TEST_STACK_NAME).templateUrl("http://10.5.5.121/Installs/cPaaS/YAML/simple_stack.yaml").build();
+ Stack stack = api.create(createStack);
+
+ /*
+ * Check request
+ */
+ assertThat(server.getRequestCount()).isEqualTo(2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", BASE_URI + "/stacks");
+
+ /*
+ * Check response
+ */
+ assertThat(stack).isNotNull();
+ assertThat(stack.getId()).isEqualTo("3095aefc-09fb-4bc7-b1f0-f21a304e864c");
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testDeleteStack() throws IOException, InterruptedException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ boolean result = api.delete(TEST_STACK_NAME, TEST_STACK_ID);
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "DELETE", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID);
+
+ /*
+ * Check response
+ */
+ assertTrue(result);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testDeleteReturnFalseOn404Stack() throws IOException, InterruptedException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ boolean result = api.delete("Non-Existing-Stack-Name", "Non-Existing-Stack-ID");
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "DELETE", BASE_URI + "/stacks/Non-Existing-Stack-Name/Non-Existing-Stack-ID");
+
+ /*
+ * Check response
+ */
+ assertFalse(result);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testUpdateStack() throws IOException, InterruptedException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(202)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ UpdateStack updateOptions = UpdateStack.builder().templateUrl("http://10.5.5.121/Installs/cPaaS/YAML/simple_stack.yaml").build();
+
+ boolean result = api.update(TEST_STACK_NAME, TEST_STACK_ID, updateOptions);
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "PUT", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID);
+
+ /*
+ * Check response
+ */
+ assertTrue(result);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testResourcesMetadata() throws IOException, InterruptedException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/resources_metadata.json"))));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Map<String, Object> metadata = api.getStackResourceMetadata(TEST_STACK_NAME, TEST_STACK_ID, RESOURCES_TEST_NAME);
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID + "/resources/" + RESOURCES_TEST_NAME + "/metadata");
+ assertThat(metadata).isNotEmpty();
+
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testResourcesMetadataReturnNullOn404() throws IOException, InterruptedException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(404)));
+
+ try {
+ HeatApi heatApi = api(server.getUrl("/").toString(), "openstack-heat", overrides);
+ StackApi api = heatApi.getStackApi("RegionOne");
+
+ Map<String, Object> metadata = api.getStackResourceMetadata(TEST_STACK_NAME, TEST_STACK_ID, "Stack_Resource_dont_exist");
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", BASE_URI + "/stacks/" + TEST_STACK_NAME + "/" + TEST_STACK_ID + "/resources/Stack_Resource_dont_exist/metadata");
+ assertThat(metadata).isEmpty();
+
+
+ } finally {
+ server.shutdown();
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/options/ListStackOptionsTest.java
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/options/ListStackOptionsTest.java b/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/options/ListStackOptionsTest.java
new file mode 100644
index 0000000..066f95e
--- /dev/null
+++ b/openstack-heat/src/test/java/org/jclouds/openstack/heat/v1/options/ListStackOptionsTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.heat.v1.options;
+
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.openstack.heat.v1.domain.StackStatus;
+import org.jclouds.openstack.heat.v1.options.ListStackOptions.SortDirection;
+import org.jclouds.openstack.heat.v1.options.ListStackOptions.SortKey;
+import org.testng.annotations.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.globalTenant;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.limit;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.marker;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.name;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.sortDirection;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.sortKey;
+import static org.jclouds.openstack.heat.v1.options.ListStackOptions.Builder.status;
+
+/**
+ * Tests behavior of {@code ListVirtualMachinesOptions}
+ */
+@Test(groups = "unit")
+public class ListStackOptionsTest {
+
+ public void testLimit() {
+ ListStackOptions options = new ListStackOptions().limit(42);
+ assertThat(options.buildQueryParameters().get("limit")).isEqualTo(ImmutableSet.of("42"));
+ }
+
+ public void testLimitStatic() {
+ ListStackOptions options = limit(42);
+ assertThat(options.buildQueryParameters().get("limit")).isEqualTo(ImmutableSet.of("42"));
+ }
+
+ public void testMarker() {
+ ListStackOptions options = new ListStackOptions().marker("deploy");
+ assertThat(options.buildQueryParameters().get("marker")).isEqualTo(ImmutableSet.of("deploy"));
+ }
+
+ public void testMarkerStatic() {
+ ListStackOptions options = marker("deploy");
+ assertThat(options.buildQueryParameters().get("marker")).isEqualTo(ImmutableSet.of("deploy"));
+ }
+
+ public void testStatus() {
+ ListStackOptions options = new ListStackOptions().status(StackStatus.CREATE_COMPLETE);
+ assertThat(options.buildQueryParameters().get("status"))
+ .isEqualTo(ImmutableSet.of(StackStatus.CREATE_COMPLETE.toString()));
+ }
+
+ public void testStatusStatic() {
+ ListStackOptions options = status(StackStatus.CREATE_COMPLETE);
+ assertThat(options.buildQueryParameters().get("status"))
+ .isEqualTo(ImmutableSet.of(StackStatus.CREATE_COMPLETE.toString()));
+ }
+
+ public void testName() {
+ ListStackOptions options = new ListStackOptions().name("deployment");
+ assertThat(options.buildQueryParameters().get("name")).isEqualTo(ImmutableSet.of("deployment"));
+ }
+
+ public void testNameStatic() {
+ ListStackOptions options = name("deployment");
+ assertThat(options.buildQueryParameters().get("name")).isEqualTo(ImmutableSet.of("deployment"));
+ }
+
+ public void testSortKey() {
+ ListStackOptions options = new ListStackOptions().sortKey(SortKey.NAME);
+ assertThat(options.buildQueryParameters().get("sort_keys")).isEqualTo(ImmutableSet.of(SortKey.NAME.toString()));
+ }
+
+ public void testSortKeyStatic() {
+ ListStackOptions options = sortKey(SortKey.NAME);
+ assertThat(options.buildQueryParameters().get("sort_keys")).isEqualTo(ImmutableSet.of(SortKey.NAME.toString()));
+ }
+
+ public void testSortDirection() {
+ ListStackOptions options = new ListStackOptions().sortDirection(SortDirection.ASCENDING);
+ assertThat(options.buildQueryParameters().get("sort_dir"))
+ .isEqualTo(ImmutableSet.of(SortDirection.ASCENDING.toString()));
+ }
+
+ public void testSortDirectionStatic() {
+ ListStackOptions options = sortDirection(SortDirection.DESCENDING);
+ assertThat(options.buildQueryParameters().get("sort_dir"))
+ .isEqualTo(ImmutableSet.of(SortDirection.DESCENDING.toString()));
+ }
+
+ public void testGlobalTenant() {
+ ListStackOptions options = globalTenant(true);
+ assertThat(options.buildQueryParameters().get("global_tenant"))
+ .isEqualTo(ImmutableSet.of("true"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/create_stack.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/create_stack.json b/openstack-heat/src/test/resources/create_stack.json
new file mode 100644
index 0000000..18a03ed
--- /dev/null
+++ b/openstack-heat/src/test/resources/create_stack.json
@@ -0,0 +1,11 @@
+{
+ "stack": {
+ "id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "links": [
+ {
+ "href": "http://192.168.123.200:8004/v1/eb1c63a4f77141548385f113a28f0f52/stacks/simple_stack/3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "rel": "self"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/files_for_atck_template.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/files_for_atck_template.json b/openstack-heat/src/test/resources/files_for_atck_template.json
new file mode 100644
index 0000000..c0b20de
--- /dev/null
+++ b/openstack-heat/src/test/resources/files_for_atck_template.json
@@ -0,0 +1,33 @@
+{
+ "VolumeB.template.yaml": {
+ "resources": {
+ "Block-StorageB": {
+ "properties": {
+ "description": "Used for VM \\/storage partition.",
+ "name": "voldB",
+ "size": {
+ "get_param": "storage_size"
+ }
+ },
+ "type": "OS::Cinder::Volume"
+ }
+ },
+ "heat_template_version": "2013-05-23",
+ "description": "Template to set up volumes for the initial deployment",
+ "parameters": {
+ "storage_size": {
+ "default": "4",
+ "description": "GBs for block storage",
+ "type": "number"
+ }
+ },
+ "outputs": {
+ "volumeId": {
+ "description": "VolumeId",
+ "value": {
+ "get_resource": "Block-StorageB"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/resources_metadata.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/resources_metadata.json b/openstack-heat/src/test/resources/resources_metadata.json
new file mode 100644
index 0000000..b43b6b6
--- /dev/null
+++ b/openstack-heat/src/test/resources/resources_metadata.json
@@ -0,0 +1,6 @@
+{
+ "metadata": {
+ "some_other_key": "some_other_value",
+ "some_key": "some_value"
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/simple_stack.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/simple_stack.json b/openstack-heat/src/test/resources/simple_stack.json
new file mode 100644
index 0000000..22fd8bb
--- /dev/null
+++ b/openstack-heat/src/test/resources/simple_stack.json
@@ -0,0 +1,21 @@
+{
+ "template": {
+ "heat_template_version": "2013-05-23",
+
+ "description": "HOT template to deploy volume",
+
+ "resources": {
+ "cinder_volume": {
+ "type": "OS::Cinder::Volume",
+ "properties": {
+ "size": "1"
+ },
+ "metadata": {
+ "some_key": "some_value",
+ "some_other_key": 5,
+ "more_key": null
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs-openstack/blob/ce4d93f8/openstack-heat/src/test/resources/stack_get_response.json
----------------------------------------------------------------------
diff --git a/openstack-heat/src/test/resources/stack_get_response.json b/openstack-heat/src/test/resources/stack_get_response.json
new file mode 100644
index 0000000..cce3ff3
--- /dev/null
+++ b/openstack-heat/src/test/resources/stack_get_response.json
@@ -0,0 +1,27 @@
+{
+ "stack": {
+ "capabilities": [],
+ "creation_time": "2014-06-03T20:59:46Z",
+ "description": "sample stack",
+ "disable_rollback": true,
+ "id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "links": [
+ {
+ "href": "http://192.168.123.200:8004/v1/eb1c63a4f77141548385f113a28f0f52/stacks/simple_stack/3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "rel": "self"
+ }
+ ],
+ "notification_topics": [],
+ "outputs": [],
+ "parameters": {
+ "OS::stack_id": "3095aefc-09fb-4bc7-b1f0-f21a304e864c",
+ "OS::stack_name": "simple_stack"
+ },
+ "stack_name": "simple_stack",
+ "stack_status": "CREATE_COMPLETE",
+ "stack_status_reason": "Stack CREATE completed successfully",
+ "template_description": "sample stack",
+ "timeout_mins": 15,
+ "updated_time": "2014-06-12T20:59:46Z"
+ }
+}
\ No newline at end of file