~ubuntu-branches/ubuntu/wily/heat/wily-proposed

« back to all changes in this revision

Viewing changes to heat/tests/test_autoscaling_update_policy.py

  • Committer: Package Import Robot
  • Author(s): James Page, Corey Bryant, James Page
  • Date: 2015-03-30 11:11:18 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20150330111118-2qpycylx6swu4yhj
Tags: 2015.1~b3-0ubuntu1
[ Corey Bryant ]
* New upstream milestone release for OpenStack kilo:
  - d/control: Align with upstream dependencies.
  - d/p/sudoers_patch.patch: Rebased.
  - d/p/fix-requirements.patch: Rebased.

[ James Page ]
* d/p/fixup-assert-regex.patch: Tweak test to use assertRegexpMatches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
3
 
#    not use this file except in compliance with the License. You may obtain
4
 
#    a copy of the License at
5
 
#
6
 
#         http://www.apache.org/licenses/LICENSE-2.0
7
 
#
8
 
#    Unless required by applicable law or agreed to in writing, software
9
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
 
#    License for the specific language governing permissions and limitations
12
 
#    under the License.
13
 
 
14
 
import json
15
 
 
16
 
import mock
17
 
from oslo.config import cfg
18
 
import six
19
 
 
20
 
from heat.common import exception
21
 
from heat.common import template_format
22
 
from heat.engine import function
23
 
from heat.engine import rsrc_defn
24
 
from heat.tests import common
25
 
from heat.tests import utils
26
 
from heat.tests.v1_1 import fakes as fakes_v1_1
27
 
 
28
 
 
29
 
asg_tmpl_without_updt_policy = '''
30
 
{
31
 
  "AWSTemplateFormatVersion" : "2010-09-09",
32
 
  "Description" : "Template to create autoscaling group.",
33
 
  "Parameters" : {},
34
 
  "Resources" : {
35
 
    "WebServerGroup" : {
36
 
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
37
 
      "Properties" : {
38
 
        "AvailabilityZones" : ["nova"],
39
 
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
40
 
        "MinSize" : "10",
41
 
        "MaxSize" : "20",
42
 
        "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ]
43
 
      }
44
 
    },
45
 
    "ElasticLoadBalancer" : {
46
 
        "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
47
 
        "Properties" : {
48
 
            "AvailabilityZones" : ["nova"],
49
 
            "Listeners" : [ {
50
 
                "LoadBalancerPort" : "80",
51
 
                "InstancePort" : "80",
52
 
                "Protocol" : "HTTP"
53
 
            }]
54
 
        }
55
 
    },
56
 
    "LaunchConfig" : {
57
 
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
58
 
      "Properties": {
59
 
        "ImageId"           : "F20-x86_64-cfntools",
60
 
        "InstanceType"      : "m1.medium",
61
 
        "KeyName"           : "test",
62
 
        "SecurityGroups"    : [ "sg-1" ],
63
 
        "UserData"          : "jsconfig data"
64
 
      }
65
 
    }
66
 
  }
67
 
}
68
 
'''
69
 
 
70
 
asg_tmpl_with_bad_updt_policy = '''
71
 
{
72
 
  "AWSTemplateFormatVersion" : "2010-09-09",
73
 
  "Description" : "Template to create autoscaling group.",
74
 
  "Parameters" : {},
75
 
  "Resources" : {
76
 
    "WebServerGroup" : {
77
 
      "UpdatePolicy": {
78
 
        "foo": {
79
 
        }
80
 
      },
81
 
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
82
 
      "Properties" : {
83
 
        "AvailabilityZones" : ["nova"],
84
 
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
85
 
        "MinSize" : "10",
86
 
        "MaxSize" : "20"
87
 
      }
88
 
    },
89
 
    "LaunchConfig" : {
90
 
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
91
 
      "Properties": {
92
 
        "ImageId"           : "F20-x86_64-cfntools",
93
 
        "InstanceType"      : "m1.medium",
94
 
        "KeyName"           : "test",
95
 
        "SecurityGroups"    : [ "sg-1" ],
96
 
        "UserData"          : "jsconfig data"
97
 
      }
98
 
    }
99
 
  }
100
 
}
101
 
'''
102
 
 
103
 
asg_tmpl_with_default_updt_policy = '''
104
 
{
105
 
  "AWSTemplateFormatVersion" : "2010-09-09",
106
 
  "Description" : "Template to create autoscaling group.",
107
 
  "Parameters" : {},
108
 
  "Resources" : {
109
 
    "WebServerGroup" : {
110
 
      "UpdatePolicy" : {
111
 
        "AutoScalingRollingUpdate" : {
112
 
        }
113
 
      },
114
 
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
115
 
      "Properties" : {
116
 
        "AvailabilityZones" : ["nova"],
117
 
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
118
 
        "MinSize" : "10",
119
 
        "MaxSize" : "20",
120
 
        "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ]
121
 
      }
122
 
    },
123
 
    "ElasticLoadBalancer" : {
124
 
        "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
125
 
        "Properties" : {
126
 
            "AvailabilityZones" : ["nova"],
127
 
            "Listeners" : [ {
128
 
                "LoadBalancerPort" : "80",
129
 
                "InstancePort" : "80",
130
 
                "Protocol" : "HTTP"
131
 
            }]
132
 
        }
133
 
    },
134
 
    "LaunchConfig" : {
135
 
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
136
 
      "Properties": {
137
 
        "ImageId"           : "F20-x86_64-cfntools",
138
 
        "InstanceType"      : "m1.medium",
139
 
        "KeyName"           : "test",
140
 
        "SecurityGroups"    : [ "sg-1" ],
141
 
        "UserData"          : "jsconfig data"
142
 
      }
143
 
    }
144
 
  }
145
 
}
146
 
'''
147
 
 
148
 
asg_tmpl_with_updt_policy = '''
149
 
{
150
 
  "AWSTemplateFormatVersion" : "2010-09-09",
151
 
  "Description" : "Template to create autoscaling group.",
152
 
  "Parameters" : {},
153
 
  "Resources" : {
154
 
    "WebServerGroup" : {
155
 
      "UpdatePolicy" : {
156
 
        "AutoScalingRollingUpdate" : {
157
 
          "MinInstancesInService" : "1",
158
 
          "MaxBatchSize" : "2",
159
 
          "PauseTime" : "PT1S"
160
 
        }
161
 
      },
162
 
      "Type" : "AWS::AutoScaling::AutoScalingGroup",
163
 
      "Properties" : {
164
 
        "AvailabilityZones" : ["nova"],
165
 
        "LaunchConfigurationName" : { "Ref" : "LaunchConfig" },
166
 
        "MinSize" : "10",
167
 
        "MaxSize" : "20",
168
 
        "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ]
169
 
      }
170
 
    },
171
 
    "ElasticLoadBalancer" : {
172
 
        "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
173
 
        "Properties" : {
174
 
            "AvailabilityZones" : ["nova"],
175
 
            "Listeners" : [ {
176
 
                "LoadBalancerPort" : "80",
177
 
                "InstancePort" : "80",
178
 
                "Protocol" : "HTTP"
179
 
            }]
180
 
        }
181
 
    },
182
 
    "LaunchConfig" : {
183
 
      "Type" : "AWS::AutoScaling::LaunchConfiguration",
184
 
      "Properties": {
185
 
        "ImageId"           : "F20-x86_64-cfntools",
186
 
        "InstanceType"      : "m1.medium",
187
 
        "KeyName"           : "test",
188
 
        "SecurityGroups"    : [ "sg-1" ],
189
 
        "UserData"          : "jsconfig data"
190
 
      }
191
 
    }
192
 
  }
193
 
}
194
 
'''
195
 
 
196
 
 
197
 
class AutoScalingGroupTest(common.HeatTestCase):
198
 
 
199
 
    def setUp(self):
200
 
        super(AutoScalingGroupTest, self).setUp()
201
 
        self.fc = fakes_v1_1.FakeClient()
202
 
        self.stub_keystoneclient(username='test_stack.CfnLBUser')
203
 
        cfg.CONF.set_default('heat_waitcondition_server_url',
204
 
                             'http://127.0.0.1:8000/v1/waitcondition')
205
 
 
206
 
    def get_launch_conf_name(self, stack, ig_name):
207
 
        return stack[ig_name].properties['LaunchConfigurationName']
208
 
 
209
 
    def test_parse_without_update_policy(self):
210
 
        tmpl = template_format.parse(asg_tmpl_without_updt_policy)
211
 
        stack = utils.parse_stack(tmpl)
212
 
        self.stub_ImageConstraint_validate()
213
 
        self.stub_KeypairConstraint_validate()
214
 
        self.stub_FlavorConstraint_validate()
215
 
        self.m.ReplayAll()
216
 
 
217
 
        stack.validate()
218
 
        grp = stack['WebServerGroup']
219
 
        self.assertFalse(grp.update_policy['AutoScalingRollingUpdate'])
220
 
        self.m.VerifyAll()
221
 
 
222
 
    def test_parse_with_update_policy(self):
223
 
        tmpl = template_format.parse(asg_tmpl_with_updt_policy)
224
 
        stack = utils.parse_stack(tmpl)
225
 
        self.stub_ImageConstraint_validate()
226
 
        self.stub_KeypairConstraint_validate()
227
 
        self.stub_FlavorConstraint_validate()
228
 
        self.m.ReplayAll()
229
 
 
230
 
        stack.validate()
231
 
        tmpl_grp = tmpl['Resources']['WebServerGroup']
232
 
        tmpl_policy = tmpl_grp['UpdatePolicy']['AutoScalingRollingUpdate']
233
 
        tmpl_batch_sz = int(tmpl_policy['MaxBatchSize'])
234
 
        grp = stack['WebServerGroup']
235
 
        self.assertTrue(grp.update_policy)
236
 
        self.assertEqual(1, len(grp.update_policy))
237
 
        self.assertIn('AutoScalingRollingUpdate', grp.update_policy)
238
 
        policy = grp.update_policy['AutoScalingRollingUpdate']
239
 
        self.assertTrue(policy and len(policy) > 0)
240
 
        self.assertEqual(1, int(policy['MinInstancesInService']))
241
 
        self.assertEqual(tmpl_batch_sz, int(policy['MaxBatchSize']))
242
 
        self.assertEqual('PT1S', policy['PauseTime'])
243
 
        self.m.VerifyAll()
244
 
 
245
 
    def test_parse_with_default_update_policy(self):
246
 
        tmpl = template_format.parse(asg_tmpl_with_default_updt_policy)
247
 
        stack = utils.parse_stack(tmpl)
248
 
        self.stub_ImageConstraint_validate()
249
 
        self.stub_KeypairConstraint_validate()
250
 
        self.stub_FlavorConstraint_validate()
251
 
        self.m.ReplayAll()
252
 
 
253
 
        stack.validate()
254
 
        grp = stack['WebServerGroup']
255
 
        self.assertTrue(grp.update_policy)
256
 
        self.assertEqual(1, len(grp.update_policy))
257
 
        self.assertIn('AutoScalingRollingUpdate', grp.update_policy)
258
 
        policy = grp.update_policy['AutoScalingRollingUpdate']
259
 
        self.assertTrue(policy and len(policy) > 0)
260
 
        self.assertEqual(0, int(policy['MinInstancesInService']))
261
 
        self.assertEqual(1, int(policy['MaxBatchSize']))
262
 
        self.assertEqual('PT0S', policy['PauseTime'])
263
 
        self.m.VerifyAll()
264
 
 
265
 
    def test_parse_with_bad_update_policy(self):
266
 
        self.stub_ImageConstraint_validate()
267
 
        self.stub_KeypairConstraint_validate()
268
 
        self.stub_FlavorConstraint_validate()
269
 
        self.m.ReplayAll()
270
 
        tmpl = template_format.parse(asg_tmpl_with_bad_updt_policy)
271
 
        stack = utils.parse_stack(tmpl)
272
 
        error = self.assertRaises(
273
 
            exception.StackValidationFailed, stack.validate)
274
 
        self.assertIn("foo", six.text_type(error))
275
 
 
276
 
    def test_parse_with_bad_pausetime_in_update_policy(self):
277
 
        self.stub_ImageConstraint_validate()
278
 
        self.stub_KeypairConstraint_validate()
279
 
        self.stub_FlavorConstraint_validate()
280
 
        self.m.ReplayAll()
281
 
        tmpl = template_format.parse(asg_tmpl_with_default_updt_policy)
282
 
        group = tmpl['Resources']['WebServerGroup']
283
 
        policy = group['UpdatePolicy']['AutoScalingRollingUpdate']
284
 
        policy['PauseTime'] = 'P1YT1H'
285
 
        stack = utils.parse_stack(tmpl)
286
 
        error = self.assertRaises(
287
 
            exception.StackValidationFailed, stack.validate)
288
 
        self.assertIn("Only ISO 8601 duration format", six.text_type(error))
289
 
 
290
 
    def validate_update_policy_diff(self, current, updated):
291
 
 
292
 
        # load current stack
293
 
        current_tmpl = template_format.parse(current)
294
 
        current_stack = utils.parse_stack(current_tmpl)
295
 
 
296
 
        # get the json snippet for the current InstanceGroup resource
297
 
        current_grp = current_stack['WebServerGroup']
298
 
        current_snippets = dict((n, r.parsed_template())
299
 
                                for n, r in current_stack.items())
300
 
        current_grp_json = current_snippets[current_grp.name]
301
 
 
302
 
        # load the updated stack
303
 
        updated_tmpl = template_format.parse(updated)
304
 
        updated_stack = utils.parse_stack(updated_tmpl)
305
 
 
306
 
        # get the updated json snippet for the InstanceGroup resource in the
307
 
        # context of the current stack
308
 
        updated_grp = updated_stack['WebServerGroup']
309
 
        updated_grp_json = function.resolve(updated_grp.t)
310
 
 
311
 
        # identify the template difference
312
 
        tmpl_diff = updated_grp.update_template_diff(
313
 
            updated_grp_json, current_grp_json)
314
 
        updated_policy = (updated_grp.t['UpdatePolicy']
315
 
                          if 'UpdatePolicy' in updated_grp.t else None)
316
 
        expected = {u'UpdatePolicy': updated_policy}
317
 
        self.assertEqual(expected, tmpl_diff)
318
 
 
319
 
        # test application of the new update policy in handle_update
320
 
        update_snippet = rsrc_defn.ResourceDefinition(
321
 
            current_grp.name,
322
 
            current_grp.type(),
323
 
            properties=updated_grp.t['Properties'],
324
 
            update_policy=updated_policy)
325
 
        current_grp._try_rolling_update = mock.MagicMock()
326
 
        current_grp.adjust = mock.MagicMock()
327
 
        current_grp.handle_update(update_snippet, tmpl_diff, None)
328
 
        if updated_policy is None:
329
 
            self.assertEqual({}, current_grp.update_policy.data)
330
 
        else:
331
 
            self.assertEqual(updated_policy, current_grp.update_policy.data)
332
 
 
333
 
    def test_update_policy_added(self):
334
 
        self.validate_update_policy_diff(asg_tmpl_without_updt_policy,
335
 
                                         asg_tmpl_with_updt_policy)
336
 
 
337
 
    def test_update_policy_updated(self):
338
 
        updt_template = json.loads(asg_tmpl_with_updt_policy)
339
 
        grp = updt_template['Resources']['WebServerGroup']
340
 
        policy = grp['UpdatePolicy']['AutoScalingRollingUpdate']
341
 
        policy['MinInstancesInService'] = '2'
342
 
        policy['MaxBatchSize'] = '4'
343
 
        policy['PauseTime'] = 'PT1M30S'
344
 
        self.validate_update_policy_diff(asg_tmpl_with_updt_policy,
345
 
                                         json.dumps(updt_template))
346
 
 
347
 
    def test_update_policy_removed(self):
348
 
        self.validate_update_policy_diff(asg_tmpl_with_updt_policy,
349
 
                                         asg_tmpl_without_updt_policy)