openstack update stack op and unit test
diff --git a/openstack/orchestration/v1/stacks/fixtures.go b/openstack/orchestration/v1/stacks/fixtures.go
index 092f60e..6b00d9b 100644
--- a/openstack/orchestration/v1/stacks/fixtures.go
+++ b/openstack/orchestration/v1/stacks/fixtures.go
@@ -140,3 +140,88 @@
}
})
}
+
+// GetExpected represents the expected object from a Get request.
+var GetExpected = &RetrievedStack{
+ DisableRollback: true,
+ Description: "Simple template to test heat commands",
+ Parameters: map[string]string{
+ "flavor": "m1.tiny",
+ "OS::stack_name": "postman_stack",
+ "OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
+ },
+ StatusReason: "Stack CREATE completed successfully",
+ Name: "postman_stack",
+ Outputs: []map[string]interface{}{},
+ CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+ Links: []gophercloud.Link{
+ gophercloud.Link{
+ Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
+ Rel: "self",
+ },
+ },
+ Capabilities: []interface{}{},
+ NotificationTopics: []interface{}{},
+ Status: "CREATE_COMPLETE",
+ ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
+ TemplateDescription: "Simple template to test heat commands",
+}
+
+// GetOutput represents the response body from a Get request.
+const GetOutput = `
+{
+ "stack": {
+ "disable_rollback": true,
+ "description": "Simple template to test heat commands",
+ "parameters": {
+ "flavor": "m1.tiny",
+ "OS::stack_name": "postman_stack",
+ "OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87"
+ },
+ "stack_status_reason": "Stack CREATE completed successfully",
+ "stack_name": "postman_stack",
+ "outputs": [],
+ "creation_time": "2015-02-03T20:07:39Z",
+ "links": [
+ {
+ "href": "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
+ "rel": "self"
+ }
+ ],
+ "capabilities": [],
+ "notification_topics": [],
+ "timeout_mins": null,
+ "stack_status": "CREATE_COMPLETE",
+ "updated_time": null,
+ "id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
+ "template_description": "Simple template to test heat commands"
+ }
+}
+`
+
+// HandleGetSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87`
+// on the test handler mux that responds with a `Get` response.
+func HandleGetSuccessfully(t *testing.T, output string) {
+ th.Mux.HandleFunc("/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+ th.TestHeader(t, r, "Accept", "application/json")
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ fmt.Fprintf(w, output)
+ })
+}
+
+// HandleUpdateSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87`
+// on the test handler mux that responds with an `Update` response.
+func HandleUpdateSuccessfully(t *testing.T) {
+ th.Mux.HandleFunc("/stacks/gophercloud-test-stack-2/db6977b2-27aa-4775-9ae7-6213212d4ada", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "PUT")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+ th.TestHeader(t, r, "Accept", "application/json")
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusAccepted)
+ })
+}
diff --git a/openstack/orchestration/v1/stacks/requests_test.go b/openstack/orchestration/v1/stacks/requests_test.go
index 0bf1101..8316caa 100644
--- a/openstack/orchestration/v1/stacks/requests_test.go
+++ b/openstack/orchestration/v1/stacks/requests_test.go
@@ -115,3 +115,50 @@
th.AssertNoErr(t, err)
th.CheckEquals(t, count, 1)
}
+
+func TestGetStack(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleGetSuccessfully(t, GetOutput)
+
+ actual, err := Get(fake.ServiceClient(), "postman_stack", "16ef0584-4458-41eb-87c8-0dc8d5f66c87").Extract()
+ th.AssertNoErr(t, err)
+
+ expected := GetExpected
+ th.AssertDeepEquals(t, expected, actual)
+}
+
+func TestUpdateStack(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleUpdateSuccessfully(t)
+
+ updateOpts := UpdateOpts{
+ Template: `
+ {
+ "heat_template_version": "2013-05-23",
+ "description": "Simple template to test heat commands",
+ "parameters": {
+ "flavor": {
+ "default": "m1.tiny",
+ "type": "string"
+ }
+ },
+ "resources": {
+ "hello_world": {
+ "type":"OS::Nova::Server",
+ "properties": {
+ "key_name": "heat_key",
+ "flavor": {
+ "get_param": "flavor"
+ },
+ "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
+ "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
+ }
+ }
+ }
+ }`,
+ }
+ err := Update(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
+ th.AssertNoErr(t, err)
+}
diff --git a/openstack/orchestration/v1/stacks/results.go b/openstack/orchestration/v1/stacks/results.go
index 8866425..d69031c 100644
--- a/openstack/orchestration/v1/stacks/results.go
+++ b/openstack/orchestration/v1/stacks/results.go
@@ -8,15 +8,19 @@
"github.com/rackspace/gophercloud/pagination"
)
+// CreatedStack represents the object extracted from a Create operation.
type CreatedStack struct {
ID string `mapstructure:"id"`
Links []gophercloud.Link `mapstructure:"links"`
}
+// CreateResult represents the result of a Create operation.
type CreateResult struct {
gophercloud.Result
}
+// Extract returns a pointer to a CreatedStack object and is called after a
+// Create operation.
func (r CreateResult) Extract() (*CreatedStack, error) {
if r.Err != nil {
return nil, r.Err
@@ -33,6 +37,8 @@
return res.Stack, nil
}
+// AdoptResult represents the result of an Adopt operation. AdoptResult has the
+// same form as CreateResult.
type AdoptResult struct {
CreateResult
}
@@ -51,6 +57,7 @@
return len(stacks) == 0, nil
}
+// ListedStack represents an element in the slice extracted from a List operation.
type ListedStack struct {
CreationTime time.Time `mapstructure:"-"`
Description string `mapstructure:"description"`
@@ -62,7 +69,7 @@
UpdatedTime time.Time `mapstructure:"-"`
}
-// ExtractStacks extracts and returns a slice of Stacks. It is used while iterating
+// ExtractStacks extracts and returns a slice of ListedStack. It is used while iterating
// over a stacks.List call.
func ExtractStacks(page pagination.Page) ([]ListedStack, error) {
var res struct {
@@ -98,28 +105,32 @@
return res.Stacks, nil
}
+// RetrievedStack represents the object extracted from a Get operation.
type RetrievedStack struct {
- Capabilities []interface{} `mapstructure:"capabilities"`
- CreationTime time.Time `mapstructure:"-"`
- Description string `mapstructure:"description"`
- DisableRollback bool `mapstructure:"disable_rollback"`
- ID string `mapstructure:"id"`
- Links []gophercloud.Link `mapstructure:"links"`
- NotificationTopics []interface{} `mapstructure:"notification_topics"`
- Outputs []map[string]string `mapstructure:"outputs"`
- Parameters map[string]string `mapstructure:"parameters"`
- Name string `mapstructure:"stack_name"`
- Status string `mapstructure:"stack_status"`
- StausReason string `mapstructure:"stack_status_reason"`
- TemplateDescription string `mapstructure:"template_description"`
- Timeout int `mapstructure:"timeout_mins"`
- UpdatedTime time.Time `mapstructure:"-"`
+ Capabilities []interface{} `mapstructure:"capabilities"`
+ CreationTime time.Time `mapstructure:"-"`
+ Description string `mapstructure:"description"`
+ DisableRollback bool `mapstructure:"disable_rollback"`
+ ID string `mapstructure:"id"`
+ Links []gophercloud.Link `mapstructure:"links"`
+ NotificationTopics []interface{} `mapstructure:"notification_topics"`
+ Outputs []map[string]interface{} `mapstructure:"outputs"`
+ Parameters map[string]string `mapstructure:"parameters"`
+ Name string `mapstructure:"stack_name"`
+ Status string `mapstructure:"stack_status"`
+ StatusReason string `mapstructure:"stack_status_reason"`
+ TemplateDescription string `mapstructure:"template_description"`
+ Timeout int `mapstructure:"timeout_mins"`
+ UpdatedTime time.Time `mapstructure:"-"`
}
+// GetResult represents the result of a Get operation.
type GetResult struct {
gophercloud.Result
}
+// Extract returns a pointer to a RetrievedStack object and is called after a
+// Get operation.
func (r GetResult) Extract() (*RetrievedStack, error) {
if r.Err != nil {
return nil, r.Err
@@ -163,10 +174,12 @@
return res.Stack, err
}
+// UpdateResult represents the result of a Update operation.
type UpdateResult struct {
gophercloud.ErrResult
}
+// DeleteResult represents the result of a Delete operation.
type DeleteResult struct {
gophercloud.ErrResult
}