Merge "Add functional test for immutable parameters"
diff --git a/functional/test_immutable_parameters.py b/functional/test_immutable_parameters.py
new file mode 100644
index 0000000..b8c498d
--- /dev/null
+++ b/functional/test_immutable_parameters.py
@@ -0,0 +1,141 @@
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from heat_integrationtests.functional import functional_base
+from heatclient import exc as heat_exceptions
+
+
+class ImmutableParametersTest(functional_base.FunctionalTestsBase):
+
+    template_param_has_no_immutable_field = '''
+heat_template_version: 2014-10-16
+parameters:
+  param1:
+    type: string
+    default: default_value
+outputs:
+  param1_output:
+    description: 'parameter 1 details'
+    value: { get_param: param1 }
+'''
+
+    template_param_has_immutable_field = '''
+heat_template_version: 2014-10-16
+parameters:
+  param1:
+    type: string
+    default: default_value
+    immutable: false
+outputs:
+  param1_output:
+    description: 'parameter 1 details'
+    value: { get_param: param1 }
+'''
+
+    def test_no_immutable_param_field(self):
+        param1_create_value = 'value1'
+        create_parameters = {"param1": param1_create_value}
+
+        stack_identifier = self.stack_create(
+            template=self.template_param_has_no_immutable_field,
+            parameters=create_parameters
+        )
+        stack = self.client.stacks.get(stack_identifier)
+
+        # Verify the value of the parameter
+        self.assertEqual(param1_create_value,
+                         self._stack_output(stack, 'param1_output'))
+
+        param1_update_value = 'value2'
+        update_parameters = {"param1": param1_update_value}
+
+        self.update_stack(
+            stack_identifier,
+            template=self.template_param_has_no_immutable_field,
+            parameters=update_parameters)
+
+        stack = self.client.stacks.get(stack_identifier)
+
+        # Verify the value of the updated parameter
+        self.assertEqual(param1_update_value,
+                         self._stack_output(stack, 'param1_output'))
+
+    def test_immutable_param_field_allowed(self):
+        param1_create_value = 'value1'
+        create_parameters = {"param1": param1_create_value}
+
+        stack_identifier = self.stack_create(
+            template=self.template_param_has_immutable_field,
+            parameters=create_parameters
+        )
+        stack = self.client.stacks.get(stack_identifier)
+
+        # Verify the value of the parameter
+        self.assertEqual(param1_create_value,
+                         self._stack_output(stack, 'param1_output'))
+
+        param1_update_value = 'value2'
+        update_parameters = {"param1": param1_update_value}
+
+        self.update_stack(
+            stack_identifier,
+            template=self.template_param_has_immutable_field,
+            parameters=update_parameters)
+        stack = self.client.stacks.get(stack_identifier)
+
+        # Verify the value of the updated parameter
+        self.assertEqual(param1_update_value,
+                         self._stack_output(stack, 'param1_output'))
+
+        # Ensure stack is not in a failed state
+        self.assertEqual('UPDATE_COMPLETE', stack.stack_status)
+
+    def test_immutable_param_field_error(self):
+        param1_create_value = 'value1'
+        create_parameters = {"param1": param1_create_value}
+
+        # Toggle the immutable field to preclude updating
+        immutable_true = self.template_param_has_immutable_field.replace(
+            'immutable: false', 'immutable: true')
+
+        stack_identifier = self.stack_create(
+            template=immutable_true,
+            parameters=create_parameters
+        )
+        stack = self.client.stacks.get(stack_identifier)
+
+        param1_update_value = 'value2'
+        update_parameters = {"param1": param1_update_value}
+
+        # Verify the value of the parameter
+        self.assertEqual(param1_create_value,
+                         self._stack_output(stack, 'param1_output'))
+
+        # Attempt to update the stack with a new parameter value
+        try:
+            self.update_stack(
+                stack_identifier,
+                template=immutable_true,
+                parameters=update_parameters)
+        except heat_exceptions.HTTPInternalServerError as exc:
+            exp = ('The following parameters are immutable and may not be '
+                   'updated: param1')
+            self.assertIn(exp, str(exc))
+
+        stack = self.client.stacks.get(stack_identifier)
+
+        # Ensure stack is not in a failed state
+        self.assertEqual('CREATE_COMPLETE', stack.stack_status)
+
+        # Ensure immutable parameter has not changed
+        self.assertEqual(param1_create_value,
+                         self._stack_output(stack, 'param1_output'))