Merge "Non-destructive upgrade for deprecated resources"
diff --git a/functional/test_conditions.py b/functional/test_conditions.py
index 577a645..ad1066d 100644
--- a/functional/test_conditions.py
+++ b/functional/test_conditions.py
@@ -20,8 +20,32 @@
     Default: test
     Type: String
     AllowedValues: [prod, test]
+  zone:
+    Type: String
+    Default: beijing
 Conditions:
   Prod: {"Fn::Equals" : [{Ref: env_type}, "prod"]}
+  Test:
+    Fn::Not:
+    - Fn::Equals:
+      - Ref: env_type
+      - prod
+  Beijing_Prod:
+    Fn::And:
+    - Fn::Equals:
+      - Ref: env_type
+      - prod
+    - Fn::Equals:
+      - Ref: zone
+      - beijing
+  Fujian_Zone:
+    Fn::Or:
+    - Fn::Equals:
+      - Ref: zone
+      - fuzhou
+    - Fn::Equals:
+      - Ref: zone
+      - xiamen
 Resources:
   test_res:
     Type: OS::Heat::TestResource
@@ -32,6 +56,21 @@
     Properties:
       value: prod_res
     Condition: Prod
+  test_res1:
+    Type: OS::Heat::TestResource
+    Properties:
+      value: just in test env
+    Condition: Test
+  beijing_prod_res:
+    Type: OS::Heat::TestResource
+    Properties:
+      value: beijing_prod_res
+    Condition: Beijing_Prod
+  fujian_res:
+    Type: OS::Heat::TestResource
+    Condition: Fujian_Zone
+    Properties:
+      value: fujian_res
 Outputs:
   res_value:
     Value: {"Fn::GetAtt": [prod_res, output]}
@@ -40,6 +79,11 @@
     Value: {"Fn::GetAtt": [test_res, output]}
   prod_resource:
     Value: {"Fn::If": [Prod, {Ref: prod_res}, 'no_prod_res']}
+  test_res1_value:
+    Value: {"Fn::If": [Test, {"Fn::GetAtt": [test_res1, output]},
+                       'no_test_res1']}
+  beijing_prod_res:
+    Value: {"Fn::If": [Beijing_Prod, {Ref: beijing_prod_res}, 'no_prod_res']}
 '''
 
 hot_template = '''
@@ -50,8 +94,32 @@
     type: string
     constraints:
       - allowed_values: [prod, test]
+  zone:
+    type: string
+    default: beijing
 conditions:
   prod: {equals : [{get_param: env_type}, "prod"]}
+  test:
+    not:
+      equals:
+      - get_param: env_type
+      - prod
+  beijing_prod:
+    and:
+    - equals:
+      - get_param: zone
+      - beijing
+    - equals:
+      - get_param: env_type
+      - prod
+  fujian_zone:
+    or:
+    - equals:
+      - get_param: zone
+      - fuzhou
+    - equals:
+      - get_param: zone
+      - xiamen
 resources:
   test_res:
     type: OS::Heat::TestResource
@@ -62,6 +130,21 @@
     properties:
       value: prod_res
     condition: prod
+  test_res1:
+    type: OS::Heat::TestResource
+    properties:
+      value: just in test env
+    condition: test
+  beijing_prod_res:
+    type: OS::Heat::TestResource
+    properties:
+      value: beijing_prod_res
+    condition: beijing_prod
+  fujian_res:
+    type: OS::Heat::TestResource
+    condition: fujian_zone
+    properties:
+      value: fujian_res
 outputs:
   res_value:
     value: {get_attr: [prod_res, output]}
@@ -70,6 +153,11 @@
     value: {get_attr: [test_res, output]}
   prod_resource:
     value: {if: [prod, {get_resource: prod_res}, 'no_prod_res']}
+  test_res1_value:
+    value: {if: [test, {get_attr: [test_res1, output]}, 'no_test_res1']}
+  beijing_prod_res:
+    value: {if: [beijing_prod, {get_resource: beijing_prod_res},
+                 'no_prod_res']}
 '''
 
 
@@ -78,19 +166,35 @@
     def setUp(self):
         super(CreateUpdateResConditionTest, self).setUp()
 
-    def res_assert_for_prod(self, resources):
-        self.assertEqual(2, len(resources))
+    def res_assert_for_prod(self, resources, bj_prod=True, fj_zone=False):
         res_names = [res.resource_name for res in resources]
+        if bj_prod:
+            self.assertEqual(3, len(resources))
+            self.assertIn('beijing_prod_res', res_names)
+        elif fj_zone:
+            self.assertEqual(3, len(resources))
+            self.assertIn('fujian_res', res_names)
+            self.assertNotIn('beijing_prod_res', res_names)
+        else:
+            self.assertEqual(2, len(resources))
         self.assertIn('prod_res', res_names)
         self.assertIn('test_res', res_names)
 
-    def res_assert_for_test(self, resources):
-        self.assertEqual(1, len(resources))
+    def res_assert_for_test(self, resources, fj_zone=False):
         res_names = [res.resource_name for res in resources]
+
+        if fj_zone:
+            self.assertEqual(3, len(resources))
+            self.assertIn('fujian_res', res_names)
+        else:
+            self.assertEqual(2, len(resources))
+            self.assertNotIn('fujian_res', res_names)
+
         self.assertIn('test_res', res_names)
+        self.assertIn('test_res1', res_names)
         self.assertNotIn('prod_res', res_names)
 
-    def output_assert_for_prod(self, stack_id):
+    def output_assert_for_prod(self, stack_id, bj_prod=True):
         output = self.client.stacks.output_show(stack_id,
                                                 'res_value')['output']
         self.assertEqual('prod_res', output['output_value'])
@@ -103,6 +207,18 @@
             stack_id, 'prod_resource')['output']
         self.assertNotEqual('no_prod_res', prod_resource['output_value'])
 
+        test_res_output = self.client.stacks.output_show(
+            stack_id, 'test_res1_value')['output']
+        self.assertEqual('no_test_res1', test_res_output['output_value'])
+
+        beijing_prod_res = self.client.stacks.output_show(
+            stack_id, 'beijing_prod_res')['output']
+        if bj_prod:
+            self.assertNotEqual('no_prod_res',
+                                beijing_prod_res['output_value'])
+        else:
+            self.assertEqual('no_prod_res', beijing_prod_res['output_value'])
+
     def output_assert_for_test(self, stack_id):
         output = self.client.stacks.output_show(stack_id,
                                                 'res_value')['output']
@@ -116,12 +232,30 @@
             stack_id, 'prod_resource')['output']
         self.assertEqual('no_prod_res', prod_resource['output_value'])
 
+        test_res_output = self.client.stacks.output_show(
+            stack_id, 'test_res1_value')['output']
+        self.assertEqual('just in test env',
+                         test_res_output['output_value'])
+
+        beijing_prod_res = self.client.stacks.output_show(
+            stack_id, 'beijing_prod_res')['output']
+        self.assertEqual('no_prod_res', beijing_prod_res['output_value'])
+
     def test_stack_create_update_cfn_template_test_to_prod(self):
         stack_identifier = self.stack_create(template=cfn_template)
         resources = self.client.resources.list(stack_identifier)
         self.res_assert_for_test(resources)
         self.output_assert_for_test(stack_identifier)
 
+        parms = {'zone': 'fuzhou'}
+        self.update_stack(stack_identifier,
+                          template=cfn_template,
+                          parameters=parms)
+
+        resources = self.client.resources.list(stack_identifier)
+        self.res_assert_for_test(resources, fj_zone=True)
+        self.output_assert_for_test(stack_identifier)
+
         parms = {'env_type': 'prod'}
         self.update_stack(stack_identifier,
                           template=cfn_template,
@@ -131,6 +265,26 @@
         self.res_assert_for_prod(resources)
         self.output_assert_for_prod(stack_identifier)
 
+        parms = {'env_type': 'prod',
+                 'zone': 'shanghai'}
+        self.update_stack(stack_identifier,
+                          template=cfn_template,
+                          parameters=parms)
+
+        resources = self.client.resources.list(stack_identifier)
+        self.res_assert_for_prod(resources, False)
+        self.output_assert_for_prod(stack_identifier, False)
+
+        parms = {'env_type': 'prod',
+                 'zone': 'xiamen'}
+        self.update_stack(stack_identifier,
+                          template=cfn_template,
+                          parameters=parms)
+
+        resources = self.client.resources.list(stack_identifier)
+        self.res_assert_for_prod(resources, bj_prod=False, fj_zone=True)
+        self.output_assert_for_prod(stack_identifier, False)
+
     def test_stack_create_update_cfn_template_prod_to_test(self):
         parms = {'env_type': 'prod'}
         stack_identifier = self.stack_create(template=cfn_template,
@@ -139,6 +293,16 @@
         self.res_assert_for_prod(resources)
         self.output_assert_for_prod(stack_identifier)
 
+        parms = {'zone': 'xiamen',
+                 'env_type': 'prod'}
+        self.update_stack(stack_identifier,
+                          template=cfn_template,
+                          parameters=parms)
+
+        resources = self.client.resources.list(stack_identifier)
+        self.res_assert_for_prod(resources, bj_prod=False, fj_zone=True)
+        self.output_assert_for_prod(stack_identifier, bj_prod=False)
+
         parms = {'env_type': 'test'}
         self.update_stack(stack_identifier,
                           template=cfn_template,
@@ -148,6 +312,16 @@
         self.res_assert_for_test(resources)
         self.output_assert_for_test(stack_identifier)
 
+        parms = {'env_type': 'test',
+                 'zone': 'fuzhou'}
+        self.update_stack(stack_identifier,
+                          template=cfn_template,
+                          parameters=parms)
+
+        resources = self.client.resources.list(stack_identifier)
+        self.res_assert_for_test(resources, fj_zone=True)
+        self.output_assert_for_test(stack_identifier)
+
     def test_stack_create_update_hot_template_test_to_prod(self):
         stack_identifier = self.stack_create(template=hot_template)
         resources = self.client.resources.list(stack_identifier)
@@ -163,6 +337,16 @@
         self.res_assert_for_prod(resources)
         self.output_assert_for_prod(stack_identifier)
 
+        parms = {'env_type': 'prod',
+                 'zone': 'shanghai'}
+        self.update_stack(stack_identifier,
+                          template=hot_template,
+                          parameters=parms)
+
+        resources = self.client.resources.list(stack_identifier)
+        self.res_assert_for_prod(resources, False)
+        self.output_assert_for_prod(stack_identifier, False)
+
     def test_stack_create_update_hot_template_prod_to_test(self):
         parms = {'env_type': 'prod'}
         stack_identifier = self.stack_create(template=hot_template,
diff --git a/functional/test_resource_group.py b/functional/test_resource_group.py
index f1ae923..c0c7de7 100644
--- a/functional/test_resource_group.py
+++ b/functional/test_resource_group.py
@@ -299,6 +299,7 @@
                                              files=files1)
         self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'},
                          self.list_resources(stack_identifier))
+        self.assertEqual(files1, self.client.stacks.files(stack_identifier))
 
         initial_nested_ident = self.group_nested_identifier(stack_identifier,
                                                             'random_group')
@@ -315,6 +316,7 @@
         updated_nested_ident = self.group_nested_identifier(stack_identifier,
                                                             'random_group')
         self.assertEqual(initial_nested_ident, updated_nested_ident)
+        self.assertEqual(files2, self.client.stacks.files(stack_identifier))
 
         # compare the output, we expect a change.
         stack1 = self.client.stacks.get(stack_identifier)