Add functional test for SDG rolling_update

Adds functional test for SoftwareDeploymentGroup
rolling_update.

Change-Id: Id575765d52c84e3c29f443a18417b5f14d9331cc
diff --git a/common/test.py b/common/test.py
index ff1b93f..a7aec6c 100644
--- a/common/test.py
+++ b/common/test.py
@@ -308,7 +308,9 @@
 
     def _wait_for_stack_status(self, stack_identifier, status,
                                failure_pattern=None,
-                               success_on_not_found=False):
+                               success_on_not_found=False,
+                               signal_required=False,
+                               resources_to_signal=None):
         """Waits for a Stack to reach a given status.
 
         Note this compares the full $action_$status, e.g
@@ -340,7 +342,8 @@
                 if self._verify_status(stack, stack_identifier, status,
                                        fail_regexp):
                     return
-
+            if signal_required:
+                self.signal_resources(resources_to_signal)
             time.sleep(build_interval)
 
         message = ('Stack %s failed to reach %s status within '
@@ -493,6 +496,24 @@
         stack_link = [l for l in r.links if l.get('rel') == 'stack'][0]
         return stack_link['href'].split("/")[-1]
 
+    def check_input_values(self, group_resources, key, value):
+        # Check inputs for deployment and derived config
+        for r in group_resources:
+            d = self.client.software_deployments.get(
+                r.physical_resource_id)
+            self.assertEqual({key: value}, d.input_values)
+            c = self.client.software_configs.get(
+                d.config_id)
+            foo_input_c = [i for i in c.inputs if i.get('name') == key][0]
+            self.assertEqual(value, foo_input_c.get('value'))
+
+    def signal_resources(self, resources):
+        # Signal all IN_PROGRESS resources
+        for r in resources:
+            if 'IN_PROGRESS' in r.resource_status:
+                stack_id = self.get_resource_stack_id(r)
+                self.client.resources.signal(stack_id, r.resource_name)
+
     def stack_create(self, stack_name=None, template=None, files=None,
                      parameters=None, environment=None, tags=None,
                      expected_status='CREATE_COMPLETE',
diff --git a/functional/test_software_deployment_group.py b/functional/test_software_deployment_group.py
index 7817c2b..4e8b868 100644
--- a/functional/test_software_deployment_group.py
+++ b/functional/test_software_deployment_group.py
@@ -43,11 +43,43 @@
         '3': dummy3
 '''
 
+    sd_template_with_upd_policy = '''
+heat_template_version: 2016-10-14
+
+parameters:
+  input:
+    type: string
+    default: foo_input
+
+resources:
+  config:
+    type: OS::Heat::SoftwareConfig
+    properties:
+      group: script
+      inputs:
+      - name: foo
+
+  deployment:
+    type: OS::Heat::SoftwareDeploymentGroup
+    update_policy:
+      rolling_update:
+        max_batch_size: 2
+        pause_time: 1
+    properties:
+      config: {get_resource: config}
+      input_values:
+        foo: {get_param: input}
+      servers:
+        '0': dummy0
+        '1': dummy1
+        '2': dummy2
+        '3': dummy3
+'''
     enable_cleanup = True
 
-    def test_deployments_crud(self):
+    def deployment_crud(self, template):
         stack_identifier = self.stack_create(
-            template=self.sd_template,
+            template=template,
             enable_cleanup=self.enable_cleanup,
             expected_status='CREATE_IN_PROGRESS')
         self._wait_for_resource_status(
@@ -58,22 +90,24 @@
             stack_identifier, 'deployment', minimal=False)
 
         self.assertEqual(4, len(group_resources))
-        self.signal_deployments(group_resources)
-        self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
+        self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE',
+                                    signal_required=True,
+                                    resources_to_signal=group_resources)
 
-        self.check_input_values(group_resources, 'foo_input')
+        self.check_input_values(group_resources, 'foo', 'foo_input')
 
         self.update_stack(stack_identifier,
-                          template=self.sd_template,
+                          template=template,
                           environment={'parameters': {'input': 'input2'}},
                           expected_status='UPDATE_IN_PROGRESS')
         nested_identifier = self.assert_resource_is_a_stack(
             stack_identifier, 'deployment')
         self.assertEqual(4, len(group_resources))
-        self.signal_deployments(group_resources)
-        self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
+        self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE',
+                                    signal_required=True,
+                                    resources_to_signal=group_resources)
 
-        self.check_input_values(group_resources, 'input2')
+        self.check_input_values(group_resources, 'foo', 'input2')
 
         # We explicitly test delete here, vs just via cleanup and check
         # the nested stack is gone
@@ -82,6 +116,12 @@
             nested_identifier, 'DELETE_COMPLETE',
             success_on_not_found=True)
 
+    def test_deployment_crud(self):
+        self.deployment_crud(self.sd_template)
+
+    def test_deployment_crud_with_rolling_update(self):
+        self.deployment_crud(self.sd_template_with_upd_policy)
+
     def test_deployments_create_delete_in_progress(self):
         stack_identifier = self.stack_create(
             template=self.sd_template,
@@ -100,21 +140,3 @@
         self._wait_for_stack_status(
             nested_identifier, 'DELETE_COMPLETE',
             success_on_not_found=True)
-
-    def check_input_values(self, group_resources, value):
-        # Check inputs for deployment and derived config
-        for r in group_resources:
-            d = self.client.software_deployments.get(
-                r.physical_resource_id)
-            self.assertEqual({'foo': value}, d.input_values)
-            c = self.client.software_configs.get(
-                d.config_id)
-            foo_input_c = [i for i in c.inputs if i.get('name') == 'foo'][0]
-            self.assertEqual(value, foo_input_c.get('value'))
-
-    def signal_deployments(self, resources):
-        # Signal all IN_PROGRESS deployment resources
-        for r in resources:
-            if 'IN_PROGRESS' in r.resource_status:
-                stack_id = self.get_resource_stack_id(r)
-                self.client.resources.signal(stack_id, r.resource_name)