23
23
from oslo.config import cfg
25
from heat.common import config
26
from heat.common import context
27
25
from heat.engine import environment
28
26
from heat.common import exception
29
27
from heat.tests.v1_1 import fakes
35
33
from heat.engine import service
36
34
from heat.engine.properties import Properties
37
35
from heat.engine.resources import instance as instances
36
from heat.engine import resource as rsrs
38
37
from heat.engine import watchrule
39
38
from heat.openstack.common import threadgroup
40
39
from heat.tests.common import HeatTestCase
41
40
from heat.tests import utils
41
from heat.tests.utils import dummy_context
42
42
from heat.tests.utils import setup_dummy_db
72
"AWSTemplateFormatVersion" : "2010-09-09",
73
"Description" : "alarming",
76
"Type": "AWS::CloudWatch::Alarm",
78
"EvaluationPeriods": "1",
80
"AlarmDescription": "do the thing",
81
"Namespace": "dev/null",
83
"ComparisonOperator": "GreaterThanThreshold",
84
"Statistic": "SampleCount",
86
"MetricName": "ServiceFailure"
95
"AWSTemplateFormatVersion" : "2010-09-09",
96
"Description" : "alarming",
98
"WebServerScaleDownPolicy" : {
99
"Type" : "AWS::AutoScaling::ScalingPolicy",
101
"AdjustmentType" : "ChangeInCapacity",
102
"AutoScalingGroupName" : "",
104
"ScalingAdjustment" : "-1"
71
112
def create_context(mocks, user='stacks_test_user',
72
tenant='test_admin', password='stacks_test_password'):
73
ctx = context.get_admin_context()
113
tenant_id='test_admin', password='stacks_test_password'):
114
ctx = dummy_context()
74
115
mocks.StubOutWithMock(ctx, 'username')
75
116
mocks.StubOutWithMock(ctx, 'tenant_id')
76
117
mocks.StubOutWithMock(ctx, 'password')
77
118
ctx.username = user
78
ctx.tenant_id = tenant
119
ctx.tenant_id = tenant_id
79
120
ctx.password = password
132
def get_stack(stack_name, ctx, template):
133
t = template_format.parse(template)
134
template = parser.Template(t)
135
stack = parser.Stack(ctx, stack_name, template)
91
139
def setup_mocks(mocks, stack):
92
140
fc = fakes.FakeClient()
93
141
mocks.StubOutWithMock(instances.Instance, 'nova')
174
222
def add_timer(self, interval, callback, initial_delay=None,
175
223
*args, **kwargs):
224
self.threads.append(callback)
178
226
def add_thread(self, callback, *args, **kwargs):
179
227
self.threads.append(callback)
189
class stackCreateTest(HeatTestCase):
236
class StackCreateTest(HeatTestCase):
191
super(stackCreateTest, self).setUp()
238
super(StackCreateTest, self).setUp()
194
241
def test_wordpress_single_instance_stack_create(self):
203
250
self.assertNotEqual(stack.resources['WebServer'].ipaddress, '0.0.0.0')
205
252
def test_wordpress_single_instance_stack_delete(self):
206
ctx = create_context(self.m, tenant='test_delete_tenant')
253
ctx = create_context(self.m)
207
254
stack = get_wordpress_stack('test_stack', ctx)
208
255
fc = setup_mocks(self.m, stack)
209
256
self.m.ReplayAll()
230
277
self.assertEqual('COMPLETE', db_s.status, )
233
class stackServiceCreateUpdateDeleteTest(HeatTestCase):
280
class StackServiceCreateUpdateDeleteTest(HeatTestCase):
236
super(stackServiceCreateUpdateDeleteTest, self).setUp()
237
self.username = 'stack_service_create_test_user'
238
self.tenant = 'stack_service_create_test_tenant'
283
super(StackServiceCreateUpdateDeleteTest, self).setUp()
240
self.ctx = create_context(self.m, self.username, self.tenant)
285
self.ctx = create_context(self.m)
242
287
self.man = service.EngineService('a-host', 'a-topic')
368
413
def test_stack_delete(self):
369
414
stack_name = 'service_delete_test_stack'
370
415
stack = get_wordpress_stack(stack_name, self.ctx)
373
s = db_api.stack_get(self.ctx, sid)
374
self.m.StubOutWithMock(parser.Stack, 'load')
376
parser.Stack.load(self.ctx, stack=s).AndReturn(stack)
416
stack.status = "COMPLETE"
378
419
self.man.tg = DummyThreadGroup()
383
424
self.man.delete_stack(self.ctx, stack.identifier()))
384
425
self.m.VerifyAll()
427
def test_stack_delete_action_in_progress_err(self):
429
Test that deleting a stack with an action in progress results in
430
an ActionInProgress exception.
433
stack_name = 'service_delete_action_in_progress_err'
434
stack = get_wordpress_stack(stack_name, self.ctx)
435
stack.status = "IN_PROGRESS"
438
self.assertRaises(exception.ActionInProgress,
439
self.man.delete_stack,
386
443
def test_stack_delete_nonexist(self):
387
444
stack_name = 'service_delete_nonexist_test_stack'
388
445
stack = get_wordpress_stack(stack_name, self.ctx)
392
447
self.assertRaises(exception.StackNotFound,
393
448
self.man.delete_stack,
394
449
self.ctx, stack.identifier())
397
451
def test_stack_update(self):
398
452
stack_name = 'service_update_test_stack'
400
454
template = '{ "Template": "data" }'
402
456
old_stack = get_wordpress_stack(stack_name, self.ctx)
457
old_stack.status = 'COMPLETE'
403
458
sid = old_stack.store()
404
459
s = db_api.stack_get(self.ctx, sid)
432
487
self.assertTrue(result['stack_id'])
433
488
self.m.VerifyAll()
490
def test_stack_update_action_in_progress_err(self):
492
Test that updating a stack with an action in progress results
493
in an ActionInProgress exception.
496
stack_name = 'service_update_action_in_progress_err_test_stack'
497
params = {'foo': 'bar'}
498
template = '{ "Template": "data" }'
500
old_stack = get_wordpress_stack(stack_name, self.ctx)
501
old_stack.status = 'IN_PROGRESS'
505
exception.ActionInProgress,
506
self.man.update_stack,
507
self.ctx, old_stack.identifier(),
508
template, params, None, {})
435
510
def test_stack_update_verify_err(self):
436
511
stack_name = 'service_update_verify_err_test_stack'
437
512
params = {'foo': 'bar'}
438
513
template = '{ "Template": "data" }'
440
515
old_stack = get_wordpress_stack(stack_name, self.ctx)
516
old_stack.status = 'COMPLETE'
441
517
old_stack.store()
442
518
sid = old_stack.store()
443
519
s = db_api.stack_get(self.ctx, sid)
506
class stackServiceSuspendResumeTest(HeatTestCase):
582
class StackServiceSuspendResumeTest(HeatTestCase):
509
super(stackServiceSuspendResumeTest, self).setUp()
510
self.username = 'stack_service_suspend_test_user'
511
self.tenant = 'stack_service_suspend_test_tenant'
585
super(StackServiceSuspendResumeTest, self).setUp()
513
self.ctx = create_context(self.m, self.username, self.tenant)
587
self.ctx = create_context(self.m)
515
589
self.man = service.EngineService('a-host', 'a-topic')
571
645
self.m.VerifyAll()
574
class stackServiceTest(HeatTestCase):
648
class StackServiceTest(HeatTestCase):
577
super(stackServiceTest, self).setUp()
579
config.register_engine_opts()
580
self.username = 'stack_service_test_user'
581
self.tenant = 'stack_service_test_tenant'
583
self.ctx = create_context(self.m, self.username, self.tenant)
651
super(StackServiceTest, self).setUp()
653
self.ctx = create_context(self.m,
654
tenant_id='stack_service_test_tenant')
584
655
self.eng = service.EngineService('a-host', 'a-topic')
585
656
cfg.CONF.set_default('heat_stack_user_role', 'stack_user_role')
625
696
self.assertEqual(self.stack.id,
626
697
db_api.stack_get_by_name(self.ctx,
627
698
self.stack.name).id)
628
ctx2 = create_context(self.m, self.username,
629
'stack_service_test_tenant2')
699
ctx2 = create_context(self.m, tenant_id='stack_service_test_tenant2')
630
700
self.assertEqual(None, db_api.stack_get_by_name(ctx2, self.stack.name))
632
702
@stack_context('service_event_list_test_stack')
1053
1123
self.m.VerifyAll()
1125
def test_signal_reception(self):
1126
stack = get_stack('signal_reception',
1133
test_data = {'food': 'yum'}
1135
self.m.StubOutWithMock(service.EngineService, '_get_stack')
1136
s = db_api.stack_get(self.ctx, self.stack.id)
1137
service.EngineService._get_stack(self.ctx,
1138
self.stack.identifier()).AndReturn(s)
1140
self.m.StubOutWithMock(db_api, 'user_creds_get')
1141
db_api.user_creds_get(mox.IgnoreArg()).MultipleTimes().AndReturn(
1144
self.m.StubOutWithMock(rsrs.Resource, 'signal')
1145
rsrs.Resource.signal(mox.IgnoreArg()).AndReturn(None)
1148
result = self.eng.resource_signal(self.ctx,
1149
dict(self.stack.identifier()),
1150
'WebServerScaleDownPolicy',
1155
def test_signal_reception_no_resource(self):
1156
stack = get_stack('signal_reception_no_resource',
1163
test_data = {'food': 'yum'}
1165
self.m.StubOutWithMock(service.EngineService, '_get_stack')
1166
s = db_api.stack_get(self.ctx, self.stack.id)
1167
service.EngineService._get_stack(self.ctx,
1168
self.stack.identifier()).AndReturn(s)
1170
self.m.StubOutWithMock(db_api, 'user_creds_get')
1171
db_api.user_creds_get(mox.IgnoreArg()).MultipleTimes().AndReturn(
1175
self.assertRaises(exception.ResourceNotFound,
1176
self.eng.resource_signal, self.ctx,
1177
dict(self.stack.identifier()),
1178
'resource_does_not_exist',
1055
1183
@stack_context('service_metadata_test_stack')
1056
1184
def test_metadata(self):
1057
1185
test_metadata = {'foo': 'bar', 'baz': 'quux', 'blarg': 'wibble'}
1062
1190
service.EngineService._get_stack(self.ctx,
1063
1191
self.stack.identifier()).AndReturn(s)
1064
1192
self.m.StubOutWithMock(instances.Instance, 'metadata_update')
1193
self.m.StubOutWithMock(db_api, 'user_creds_get')
1065
1194
instances.Instance.metadata_update(new_metadata=test_metadata)
1195
db_api.user_creds_get(mox.IgnoreArg()).MultipleTimes().AndReturn(
1066
1197
self.m.ReplayAll()
1068
1199
result = self.eng.metadata_update(self.ctx,
1107
1238
self.m.VerifyAll()
1240
@stack_context('periodic_watch_task_not_created')
1241
def test_periodic_watch_task_not_created(self):
1242
self.eng.stg[self.stack.id] = DummyThreadGroup()
1243
self.eng._start_watch_task(self.stack.id, self.ctx)
1244
self.assertEqual([], self.eng.stg[self.stack.id].threads)
1246
def test_periodic_watch_task_created(self):
1247
stack = get_stack('period_watch_task_created',
1248
create_context(self.m),
1254
self.eng.stg[stack.id] = DummyThreadGroup()
1255
self.eng._start_watch_task(stack.id, self.ctx)
1256
self.assertEqual([self.eng._periodic_watcher_task],
1257
self.eng.stg[stack.id].threads)
1109
1260
@stack_context('service_show_watch_test_stack', False)
1110
1261
@utils.wr_delete_after
1111
1262
def test_show_watch(self):
1253
1404
watch_name="OverrideAlarm",
1255
1406
self.assertEqual(state, result[engine_api.WATCH_STATE_VALUE])
1256
self.assertEqual([DummyAction.alarm],
1407
self.assertEqual([DummyAction.signal],
1257
1408
self.eng.stg[self.stack.id].threads)
1259
1410
self.m.VerifyAll()