Bring partially https://github.com/gophercloud/gophercloud/pull/1221

Change-Id: I185e1991b68a22b387d043bc32bef79cd4c3dc4e
Related-To: PRODX-8893
diff --git a/openstack/orchestration/v1/stacks/testing/fixtures.go b/openstack/orchestration/v1/stacks/testing/fixtures.go
index 11e9e70..c22b93e 100644
--- a/openstack/orchestration/v1/stacks/testing/fixtures.go
+++ b/openstack/orchestration/v1/stacks/testing/fixtures.go
@@ -12,6 +12,9 @@
 	fake "gerrit.mcp.mirantis.net/debian/gophercloud.git/testhelper/client"
 )
 
+var Create_time, _ = time.Parse(time.RFC3339, "2018-06-26T07:58:17Z")
+var Updated_time, _ = time.Parse(time.RFC3339, "2018-06-26T07:59:17Z")
+
 // CreateExpected represents the expected object from a Create request.
 var CreateExpected = &stacks.CreatedStack{
 	ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -61,7 +64,7 @@
 		},
 		StatusReason: "Stack CREATE completed successfully",
 		Name:         "postman_stack",
-		CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+		CreationTime: Create_time,
 		Status:       "CREATE_COMPLETE",
 		ID:           "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
 		Tags:         []string{"rackspace", "atx"},
@@ -76,8 +79,8 @@
 		},
 		StatusReason: "Stack successfully updated",
 		Name:         "gophercloud-test-stack-2",
-		CreationTime: time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC),
-		UpdatedTime:  time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC),
+		CreationTime: Create_time,
+		UpdatedTime:  Updated_time,
 		Status:       "UPDATE_COMPLETE",
 		ID:           "db6977b2-27aa-4775-9ae7-6213212d4ada",
 		Tags:         []string{"sfo", "satx"},
@@ -98,7 +101,7 @@
     ],
     "stack_status_reason": "Stack CREATE completed successfully",
     "stack_name": "postman_stack",
-    "creation_time": "2015-02-03T20:07:39",
+    "creation_time": "2018-06-26T07:58:17Z",
     "updated_time": null,
     "stack_status": "CREATE_COMPLETE",
     "id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -114,8 +117,8 @@
     ],
     "stack_status_reason": "Stack successfully updated",
     "stack_name": "gophercloud-test-stack-2",
-    "creation_time": "2014-12-11T17:39:16",
-    "updated_time": "2014-12-11T17:40:37",
+    "creation_time": "2018-06-26T07:58:17Z",
+    "updated_time": "2018-06-26T07:59:17Z",
     "stack_status": "UPDATE_COMPLETE",
     "id": "db6977b2-27aa-4775-9ae7-6213212d4ada",
 	"tags": ["sfo", "satx"]
@@ -158,7 +161,7 @@
 	StatusReason: "Stack CREATE completed successfully",
 	Name:         "postman_stack",
 	Outputs:      []map[string]interface{}{},
-	CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+	CreationTime: Create_time,
 	Links: []gophercloud.Link{
 		{
 			Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -187,7 +190,7 @@
     "stack_status_reason": "Stack CREATE completed successfully",
     "stack_name": "postman_stack",
     "outputs": [],
-    "creation_time": "2015-02-03T20:07:39",
+    "creation_time": "2018-06-26T07:58:17Z",
     "links": [
     {
       "href": "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -233,6 +236,19 @@
 	})
 }
 
+// HandleUpdatePatchSuccessfully 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 HandleUpdatePatchSuccessfully(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, "PATCH")
+		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)
+	})
+}
+
 // HandleDeleteSuccessfully creates an HTTP handler at `/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87`
 // on the test handler mux that responds with a `Delete` response.
 func HandleDeleteSuccessfully(t *testing.T) {
@@ -256,7 +272,7 @@
 		"OS::stack_id":   "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
 	},
 	Name:         "postman_stack",
-	CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+	CreationTime: Create_time,
 	Links: []gophercloud.Link{
 		{
 			Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
diff --git a/openstack/orchestration/v1/stacks/testing/requests_test.go b/openstack/orchestration/v1/stacks/testing/requests_test.go
index 2846811..de5f9ec 100644
--- a/openstack/orchestration/v1/stacks/testing/requests_test.go
+++ b/openstack/orchestration/v1/stacks/testing/requests_test.go
@@ -39,6 +39,29 @@
 	th.AssertDeepEquals(t, expected, actual)
 }
 
+func TestCreateStackMissingRequiredInOpts(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	HandleCreateSuccessfully(t, CreateOutput)
+	template := new(stacks.Template)
+	template.Bin = []byte(`
+		{
+			"heat_template_version": "2013-05-23",
+			"description": "Simple template to test heat commands",
+			"parameters": {
+				"flavor": {
+					"default": "m1.tiny",
+					"type": "string"
+				}
+			}
+		}`)
+	createOpts := stacks.CreateOpts{
+		DisableRollback: gophercloud.Disabled,
+	}
+	r := stacks.Create(fake.ServiceClient(), createOpts)
+	th.AssertEquals(t, "Missing input for argument [Name]", r.Err.Error())
+}
+
 func TestAdoptStack(t *testing.T) {
 	th.SetupHTTP()
 	defer th.TeardownHTTP()
@@ -133,13 +156,45 @@
 				}
 			}
 		}`)
-	updateOpts := stacks.UpdateOpts{
+	updateOpts := &stacks.UpdateOpts{
 		TemplateOpts: template,
 	}
 	err := stacks.Update(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
 	th.AssertNoErr(t, err)
 }
 
+func TestUpdateStackNoTemplate(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	HandleUpdateSuccessfully(t)
+
+	parameters := make(map[string]interface{})
+	parameters["flavor"] = "m1.tiny"
+
+	updateOpts := &stacks.UpdateOpts{
+		Parameters: parameters,
+	}
+	expected := stacks.ErrTemplateRequired{}
+
+	err := stacks.Update(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
+	th.AssertEquals(t, expected, err)
+}
+
+func TestUpdatePatchStack(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	HandleUpdatePatchSuccessfully(t)
+
+	parameters := make(map[string]interface{})
+	parameters["flavor"] = "m1.tiny"
+
+	updateOpts := &stacks.UpdateOpts{
+		Parameters: parameters,
+	}
+	err := stacks.UpdatePatch(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
+	th.AssertNoErr(t, err)
+}
+
 func TestDeleteStack(t *testing.T) {
 	th.SetupHTTP()
 	defer th.TeardownHTTP()