stacks
diff --git a/openstack/orchestration/v1/stacks/results.go b/openstack/orchestration/v1/stacks/results.go
new file mode 100644
index 0000000..9e11f82
--- /dev/null
+++ b/openstack/orchestration/v1/stacks/results.go
@@ -0,0 +1,219 @@
+package stacks
+
+import (
+ "time"
+
+ "github.com/mitchellh/mapstructure"
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/pagination"
+)
+
+type CreateStack struct {
+ ID string `mapstructure:"id"`
+ Links []gophercloud.Link `mapstructure:"links"`
+}
+
+type CreateResult struct {
+ gophercloud.Result
+}
+
+func (r CreateResult) Extract() (*CreateStack, error) {
+ if r.Err != nil {
+ return nil, r.Err
+ }
+
+ var res struct {
+ Stack *CreateStack `json:"stack"`
+ }
+
+ if err := mapstructure.Decode(r.Body, &res); err != nil {
+ return nil, err
+ }
+
+ return res.Stack, nil
+}
+
+type AdoptResult struct {
+ gophercloud.Result
+}
+
+// StackPage is a pagination.Pager that is returned from a call to the List function.
+type StackPage struct {
+ pagination.SinglePageBase
+}
+
+// IsEmpty returns true if a ListResult contains no Stacks.
+func (r StackPage) IsEmpty() (bool, error) {
+ stacks, err := ExtractStacks(r)
+ if err != nil {
+ return true, err
+ }
+ return len(stacks) == 0, nil
+}
+
+type ListStack struct {
+ CreationTime time.Time `mapstructure:"-"`
+ Description string `mapstructure:"description"`
+ ID string `mapstructure:"id"`
+ Links []gophercloud.Link `mapstructure:"links"`
+ Name string `mapstructure:"stack_name"`
+ Status string `mapstructure:"stack_status"`
+ StausReason string `mapstructure:"stack_status_reason"`
+ UpdatedTime time.Time `mapstructure:"-"`
+}
+
+// ExtractStacks extracts and returns a slice of Stacks. It is used while iterating
+// over a stacks.List call.
+func ExtractStacks(page pagination.Page) ([]ListStack, error) {
+ var res struct {
+ Stacks []ListStack `json:"stacks"`
+ }
+
+ err := mapstructure.Decode(page.(StackPage).Body, &res)
+ return res.Stacks, err
+}
+
+type GetStack 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:"-"`
+}
+
+type GetResult struct {
+ gophercloud.Result
+}
+
+func (r GetResult) Extract() (*GetStack, error) {
+ if r.Err != nil {
+ return nil, r.Err
+ }
+
+ var res struct {
+ Stack *GetStack `json:"stack"`
+ }
+
+ config := &mapstructure.DecoderConfig{
+ Result: &res,
+ WeaklyTypedInput: true,
+ }
+ decoder, err := mapstructure.NewDecoder(config)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := decoder.Decode(r.Body); err != nil {
+ return nil, err
+ }
+
+ b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
+
+ if date, ok := b["creation_time"]; ok && date != nil {
+ t, err := time.Parse(time.RFC3339, date.(string))
+ if err != nil {
+ return nil, err
+ }
+ res.Stack.CreationTime = t
+ }
+
+ if date, ok := b["updated_time"]; ok && date != nil {
+ t, err := time.Parse(time.RFC3339, date.(string))
+ if err != nil {
+ return nil, err
+ }
+ res.Stack.UpdatedTime = t
+ }
+
+ return res.Stack, err
+}
+
+type UpdateResult struct {
+ gophercloud.ErrResult
+}
+
+type DeleteResult struct {
+ gophercloud.ErrResult
+}
+
+type PreviewStack 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"`
+ Name string `mapstructure:"stack_name"`
+ NotificationTopics []interface{} `mapstructure:"notification_topics"`
+ Parameters map[string]string `mapstructure:"parameters"`
+ Resources []map[string]string `mapstructure:"resources"`
+ 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:"-"`
+}
+
+type PreviewResult struct {
+ gophercloud.Result
+}
+
+func (r PreviewResult) Extract() (*PreviewStack, error) {
+ if r.Err != nil {
+ return nil, r.Err
+ }
+
+ var res struct {
+ Stack *PreviewStack `json:"stack"`
+ }
+
+ config := &mapstructure.DecoderConfig{
+ Result: &res,
+ WeaklyTypedInput: true,
+ }
+ decoder, err := mapstructure.NewDecoder(config)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := decoder.Decode(r.Body); err != nil {
+ return nil, err
+ }
+
+ b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
+
+ if date, ok := b["creation_time"]; ok && date != nil {
+ t, err := time.Parse(time.RFC3339, date.(string))
+ if err != nil {
+ return nil, err
+ }
+ res.Stack.CreationTime = t
+ }
+
+ if date, ok := b["updated_time"]; ok && date != nil {
+ t, err := time.Parse(time.RFC3339, date.(string))
+ if err != nil {
+ return nil, err
+ }
+ res.Stack.UpdatedTime = t
+ }
+
+ return res.Stack, err
+}
+
+type AbandonStack struct {
+}
+
+type AbandonResult struct {
+ gophercloud.Result
+}