blob: d406b53e99886cc60d4cfdf4d83c44a1599faf60 [file] [log] [blame]
Rabi Mishra87be9b42016-02-15 14:15:50 +05301# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
Zane Bitter6df3d3d2016-06-14 15:09:19 +020013import time
14
Rabi Mishra87be9b42016-02-15 14:15:50 +053015from heat_integrationtests.functional import functional_base
16
17test_template = {
18 'heat_template_version': '2013-05-23',
19 'description': 'Test template to create one instance.',
20 'resources': {
21 'bar': {
22 'type': 'OS::Heat::TestResource',
23 'properties': {
24 'value': '1234',
25 'update_replace': False,
26 }
27 }
28 }
29}
30
31env_both_restrict = {u'resource_registry': {
32 u'resources': {
33 'bar': {'restricted_actions': ['update', 'replace']}
34 }
35}
36}
37
38env_replace_restrict = {u'resource_registry': {
39 u'resources': {
40 '*ar': {'restricted_actions': 'replace'}
41 }
42}
43}
44
45reason_update_restrict = 'update is restricted for resource.'
46reason_replace_restrict = 'replace is restricted for resource.'
47
48
49class UpdateRestrictedStackTest(functional_base.FunctionalTestsBase):
50
51 def _check_for_restriction_reason(self, events,
52 reason, num_expected=1):
53 matched = [e for e in events
54 if e.resource_status_reason == reason]
55 return len(matched) == num_expected
56
57 def test_update(self):
58 stack_identifier = self.stack_create(template=test_template)
59
60 update_template = test_template.copy()
61 props = update_template['resources']['bar']['properties']
62 props['value'] = '4567'
63
64 # check update fails - with 'both' restricted
65 self.update_stack(stack_identifier, update_template,
66 env_both_restrict,
67 expected_status='UPDATE_FAILED')
68
69 self.assertTrue(self.verify_resource_status(stack_identifier, 'bar',
70 'CREATE_COMPLETE'))
71 resource_events = self.client.events.list(stack_identifier, 'bar')
72 self.assertTrue(
73 self._check_for_restriction_reason(resource_events,
74 reason_update_restrict))
75
76 # check update succeeds - with only 'replace' restricted
77 self.update_stack(stack_identifier, update_template,
78 env_replace_restrict,
79 expected_status='UPDATE_COMPLETE')
80
81 self.assertTrue(self.verify_resource_status(stack_identifier, 'bar',
82 'UPDATE_COMPLETE'))
83 resource_events = self.client.events.list(stack_identifier, 'bar')
84 self.assertFalse(
85 self._check_for_restriction_reason(resource_events,
86 reason_update_restrict, 2))
87 self.assertTrue(
88 self._check_for_restriction_reason(resource_events,
89 reason_replace_restrict, 0))
90
91 def test_replace(self):
92 stack_identifier = self.stack_create(template=test_template)
93
94 update_template = test_template.copy()
95 props = update_template['resources']['bar']['properties']
96 props['update_replace'] = True
97
98 # check replace fails - with 'both' restricted
99 self.update_stack(stack_identifier, update_template,
rabi1305de92016-06-13 12:04:10 +0530100 env_both_restrict,
Rabi Mishra87be9b42016-02-15 14:15:50 +0530101 expected_status='UPDATE_FAILED')
102
103 self.assertTrue(self.verify_resource_status(stack_identifier, 'bar',
104 'CREATE_COMPLETE'))
105 resource_events = self.client.events.list(stack_identifier, 'bar')
106 self.assertTrue(
107 self._check_for_restriction_reason(resource_events,
108 reason_replace_restrict))
109
Zane Bitter6df3d3d2016-06-14 15:09:19 +0200110 # Ensure the timestamp changes, since this will be very quick
111 time.sleep(1)
112
Rabi Mishra87be9b42016-02-15 14:15:50 +0530113 # check replace fails - with only 'replace' restricted
114 self.update_stack(stack_identifier, update_template,
115 env_replace_restrict,
116 expected_status='UPDATE_FAILED')
117
118 self.assertTrue(self.verify_resource_status(stack_identifier, 'bar',
119 'CREATE_COMPLETE'))
120 resource_events = self.client.events.list(stack_identifier, 'bar')
121 self.assertTrue(
122 self._check_for_restriction_reason(resource_events,
123 reason_replace_restrict, 2))
124 self.assertTrue(
125 self._check_for_restriction_reason(resource_events,
126 reason_update_restrict, 0))
127
128 def test_update_type_changed(self):
129 stack_identifier = self.stack_create(template=test_template)
130
131 update_template = test_template.copy()
132 rsrc = update_template['resources']['bar']
133 rsrc['type'] = 'OS::Heat::None'
134
135 # check replace fails - with 'both' restricted
136 self.update_stack(stack_identifier, update_template,
137 env_both_restrict,
138 expected_status='UPDATE_FAILED')
139
140 self.assertTrue(self.verify_resource_status(stack_identifier, 'bar',
141 'CREATE_COMPLETE'))
142 resource_events = self.client.events.list(stack_identifier, 'bar')
143 self.assertTrue(
144 self._check_for_restriction_reason(resource_events,
145 reason_replace_restrict))
146
Zane Bitter6df3d3d2016-06-14 15:09:19 +0200147 # Ensure the timestamp changes, since this will be very quick
148 time.sleep(1)
149
Rabi Mishra87be9b42016-02-15 14:15:50 +0530150 # check replace fails - with only 'replace' restricted
151 self.update_stack(stack_identifier, update_template,
152 env_replace_restrict,
153 expected_status='UPDATE_FAILED')
154
155 self.assertTrue(self.verify_resource_status(stack_identifier, 'bar',
156 'CREATE_COMPLETE'))
157 resource_events = self.client.events.list(stack_identifier, 'bar')
158 self.assertTrue(
159 self._check_for_restriction_reason(resource_events,
160 reason_replace_restrict, 2))
161 self.assertTrue(
162 self._check_for_restriction_reason(resource_events,
163 reason_update_restrict, 0))