openstack preview stack op and unit test
diff --git a/openstack/orchestration/v1/stacks/fixtures.go b/openstack/orchestration/v1/stacks/fixtures.go
index 3809583..31814cc 100644
--- a/openstack/orchestration/v1/stacks/fixtures.go
+++ b/openstack/orchestration/v1/stacks/fixtures.go
@@ -238,3 +238,42 @@
 		w.WriteHeader(http.StatusNoContent)
 	})
 }
+
+// GetExpected represents the expected object from a Get request.
+var PreviewExpected = &PreviewedStack{
+	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",
+	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",
+}
+
+// HandlePreviewSuccessfully creates an HTTP handler at `/stacks/preview`
+// on the test handler mux that responds with an `Preview` response.
+func HandlePreviewSuccessfully(t *testing.T, output string) {
+	th.Mux.HandleFunc("/stacks/preview", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		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)
+	})
+}
diff --git a/openstack/orchestration/v1/stacks/requests.go b/openstack/orchestration/v1/stacks/requests.go
index 8d27e7b..81b4ea0 100644
--- a/openstack/orchestration/v1/stacks/requests.go
+++ b/openstack/orchestration/v1/stacks/requests.go
@@ -49,7 +49,7 @@
 	// (OPTIONAL) Enables or disables deletion of all stack resources when a stack
 	// creation fails. Default is true, meaning all resources are not deleted when
 	// stack creation fails.
-	DisableRollback *bool
+	DisableRollback Rollback
 	// (OPTIONAL) A stringified JSON environment for the stack.
 	Environment string
 	// (OPTIONAL) A map that maps file names to file contents. It can also be used
@@ -155,7 +155,7 @@
 	// (OPTIONAL) Enables or disables deletion of all stack resources when a stack
 	// creation fails. Default is true, meaning all resources are not deleted when
 	// stack creation fails.
-	DisableRollback *bool
+	DisableRollback Rollback
 	// (OPTIONAL) A stringified JSON environment for the stack.
 	Environment string
 	// (OPTIONAL) A map that maps file names to file contents. It can also be used
@@ -322,12 +322,30 @@
 // UpdateOpts contains the common options struct used in this package's Update
 // operation.
 type UpdateOpts struct {
-	Environment string
-	Files       map[string]interface{}
-	Parameters  map[string]string
-	Template    string
+	// (REQUIRED) The timeout for stack creation in minutes.
+	Timeout int
+	// (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
+	// This value is ignored if Template is supplied inline.
 	TemplateURL string
-	Timeout     int
+	// (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
+	// is a stringified version of the JSON/YAML template. Since the template will likely
+	// be located in a file, one way to set this variable is by using ioutil.ReadFile:
+	// import "io/ioutil"
+	// var opts stacks.CreateOpts
+	// b, err := ioutil.ReadFile("path/to/you/template/file.json")
+	// if err != nil {
+	//   // handle error...
+	// }
+	// opts.Template = string(b)
+	Template string
+	// (OPTIONAL) A stringified JSON environment for the stack.
+	Environment string
+	// (OPTIONAL) A map that maps file names to file contents. It can also be used
+	// to pass provider template contents. Example:
+	// Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
+	Files map[string]interface{}
+	// (OPTIONAL) User-defined parameters to pass to the template.
+	Parameters map[string]string
 }
 
 // ToStackUpdateMap casts a CreateOpts struct to a map.
@@ -402,14 +420,36 @@
 // PreviewOpts contains the common options struct used in this package's Preview
 // operation.
 type PreviewOpts struct {
-	DisableRollback *bool
-	Environment     string
-	Files           map[string]interface{}
-	Name            string
-	Parameters      map[string]string
-	Template        string
-	TemplateURL     string
-	Timeout         int
+	// (REQUIRED) The name of the stack. It must start with an alphabetic character.
+	Name string
+	// (REQUIRED) The timeout for stack creation in minutes.
+	Timeout int
+	// (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
+	// This value is ignored if Template is supplied inline.
+	TemplateURL string
+	// (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
+	// is a stringified version of the JSON/YAML template. Since the template will likely
+	// be located in a file, one way to set this variable is by using ioutil.ReadFile:
+	// import "io/ioutil"
+	// var opts stacks.CreateOpts
+	// b, err := ioutil.ReadFile("path/to/you/template/file.json")
+	// if err != nil {
+	//   // handle error...
+	// }
+	// opts.Template = string(b)
+	Template string
+	// (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+	// creation fails. Default is true, meaning all resources are not deleted when
+	// stack creation fails.
+	DisableRollback Rollback
+	// (OPTIONAL) A stringified JSON environment for the stack.
+	Environment string
+	// (OPTIONAL) A map that maps file names to file contents. It can also be used
+	// to pass provider template contents. Example:
+	// Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
+	Files map[string]interface{}
+	// (OPTIONAL) User-defined parameters to pass to the template.
+	Parameters map[string]string
 }
 
 // ToStackPreviewMap casts a PreviewOpts struct to a map.
diff --git a/openstack/orchestration/v1/stacks/requests_test.go b/openstack/orchestration/v1/stacks/requests_test.go
index cbaa1e0..1e32ca2 100644
--- a/openstack/orchestration/v1/stacks/requests_test.go
+++ b/openstack/orchestration/v1/stacks/requests_test.go
@@ -171,3 +171,47 @@
 	err := Delete(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada").ExtractErr()
 	th.AssertNoErr(t, err)
 }
+
+func TestPreviewStack(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	HandlePreviewSuccessfully(t, GetOutput)
+
+	previewOpts := PreviewOpts{
+		Name:    "stackcreated",
+		Timeout: 60,
+		Template: `
+    {
+      "stack_name": "postman_stack",
+      "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"
+            }
+          }
+        }
+      }
+    }`,
+		DisableRollback: Disable,
+	}
+	actual, err := Preview(fake.ServiceClient(), previewOpts).Extract()
+	th.AssertNoErr(t, err)
+
+	expected := PreviewExpected
+	th.AssertDeepEquals(t, expected, actual)
+}
diff --git a/openstack/orchestration/v1/stacks/results.go b/openstack/orchestration/v1/stacks/results.go
index d69031c..b648fb2 100644
--- a/openstack/orchestration/v1/stacks/results.go
+++ b/openstack/orchestration/v1/stacks/results.go
@@ -184,28 +184,32 @@
 	gophercloud.ErrResult
 }
 
+// PreviewedStack represents the result of a Preview operation.
 type PreviewedStack 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:"-"`
+	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]interface{} `mapstructure:"resources"`
+	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:"-"`
 }
 
+// PreviewResult represents the result of a Preview operation.
 type PreviewResult struct {
 	gophercloud.Result
 }
 
+// Extract returns a pointer to a PreviewedStack object and is called after a
+// Preview operation.
 func (r PreviewResult) Extract() (*PreviewedStack, error) {
 	if r.Err != nil {
 		return nil, r.Err