177
89
args = parse_args(['rai', 'new-juju'])
178
90
self.assertRegexpMatches(
179
91
stderr.getvalue(), '.*error: too few arguments.*')
180
with parse_error(self) as stderr:
181
args = parse_args(['rai', 'new-juju', QUICK])
182
self.assertRegexpMatches(
183
stderr.getvalue(), '.*error: too few arguments.*')
184
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
92
args = parse_args(['rai', 'new-juju', QUICK])
185
93
self.assertEqual(args.env, 'rai')
186
94
self.assertEqual(args.new_juju_path, 'new-juju')
187
self.assertEqual(args.log_dir, 'log-dir')
188
self.assertEqual(args.suite, [QUICK])
189
self.assertIs(args.agent_stream, None)
95
self.assertEqual(args.suite, QUICK)
191
97
def test_parse_args_attempts(self):
192
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
98
args = parse_args(['rai', 'new-juju', QUICK])
193
99
self.assertEqual(args.attempts, 2)
194
args = parse_args(['rai', 'new-juju', '--attempts', '3', QUICK,
100
args = parse_args(['rai', 'new-juju', '--attempts', '3', QUICK])
196
101
self.assertEqual(args.attempts, 3)
198
103
def test_parse_args_json_file(self):
199
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
104
args = parse_args(['rai', 'new-juju', QUICK])
200
105
self.assertIs(args.json_file, None)
201
args = parse_args(['rai', 'new-juju', '--json-file', 'foobar', QUICK,
106
args = parse_args(['rai', 'new-juju', '--json-file', 'foobar', QUICK])
203
107
self.assertEqual(args.json_file, 'foobar')
205
109
def test_parse_args_suite(self):
206
args = parse_args(['rai', 'new-juju', 'full', 'log-dir'])
207
self.assertEqual(args.suite, [FULL])
208
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
209
self.assertEqual(args.suite, [QUICK])
210
args = parse_args(['rai', 'new-juju', DENSITY, 'log-dir'])
211
self.assertEqual(args.suite, [DENSITY])
212
args = parse_args(['rai', 'new-juju', BACKUP, 'log-dir'])
213
self.assertEqual(args.suite, [BACKUP])
214
with parse_error(self) as stderr:
215
args = parse_args(['rai', 'new-juju', 'foo', 'log-dir'])
216
self.assertRegexpMatches(
217
stderr.getvalue(), ".*argument suite: invalid choice: 'foo'.*")
219
def test_parse_args_multi_suite(self):
220
args = parse_args(['rai', 'new-juju', 'full,quick', 'log-dir'])
221
self.assertEqual(args.suite, [FULL, QUICK])
222
with parse_error(self) as stderr:
223
args = parse_args(['rai', 'new-juju', 'full,foo', 'log-dir'])
110
args = parse_args(['rai', 'new-juju', 'full'])
111
self.assertEqual(args.suite, FULL)
112
args = parse_args(['rai', 'new-juju', QUICK])
113
self.assertEqual(args.suite, QUICK)
114
args = parse_args(['rai', 'new-juju', DENSITY])
115
self.assertEqual(args.suite, DENSITY)
116
args = parse_args(['rai', 'new-juju', BACKUP])
117
self.assertEqual(args.suite, BACKUP)
118
with parse_error(self) as stderr:
119
args = parse_args(['rai', 'new-juju', 'foo'])
224
120
self.assertRegexpMatches(
225
121
stderr.getvalue(), ".*argument suite: invalid choice: 'foo'.*")
227
123
def test_parse_args_agent_url(self):
228
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
124
args = parse_args(['rai', 'new-juju', QUICK])
229
125
self.assertEqual(args.new_agent_url, None)
230
126
args = parse_args(['rai', 'new-juju', '--new-agent-url',
231
'http://example.org', QUICK, 'log-dir'])
127
'http://example.org', QUICK])
232
128
self.assertEqual(args.new_agent_url, 'http://example.org')
234
def test_parse_args_debug(self):
235
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
236
self.assertEqual(args.debug, False)
237
args = parse_args(['rai', 'new-juju', '--debug', QUICK, 'log-dir'])
238
self.assertEqual(args.debug, True)
240
def test_parse_args_old_stable(self):
241
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir',
242
'--old-stable', 'asdf'])
243
self.assertEqual(args.old_stable, 'asdf')
244
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
245
self.assertIs(args.old_stable, None)
247
def test_parse_args_agent_stream(self):
248
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir',
249
'--agent-stream', 'asdf'])
250
self.assertEqual(args.agent_stream, 'asdf')
251
args = parse_args(['rai', 'new-juju', QUICK, 'log-dir'])
252
self.assertIs(args.old_stable, None)
255
131
class FakeStepAttempt:
257
def __init__(self, result, new_path=None):
133
def __init__(self, result):
258
134
self.result = result
259
self.stage = StageInfo(result[0][0], '{} title'.format(result[0][0]))
260
self.new_path = new_path
263
def from_result(cls, old, new, test_id='foo-id', new_path=None):
264
"""Alternate constructor for backwards-compatibility.
266
Allows tests that used FakeAttempt to be adapted with minimal changes.
268
return cls([(test_id, old, new)], new_path)
270
def __eq__(self, other):
272
type(self) == type(other) and self.result == other.result)
274
def get_test_info(self):
275
return {self.result[0][0]: {'title': self.result[0][0]}}
277
def get_bootstrap_client(self, client):
280
136
def iter_test_results(self, old, new):
281
137
return iter(self.result)
283
def iter_steps(self, client):
284
yield self.stage.as_result()
285
if self.new_path is not None and client.full_path == self.new_path:
286
result_value = self.result[0][2]
288
result_value = self.result[0][1]
289
if isinstance(result_value, BaseException):
291
yield self.stage.as_result(result_value)
140
class FakeAttempt(FakeStepAttempt):
142
def __init__(self, old_result, new_result, test_id='foo-id'):
143
super(FakeAttempt, self).__init__([(test_id, old_result, new_result)])
145
def do_stage(self, old_client, new_client):
146
return self.result[0]
294
149
class FakeAttemptClass:
295
"""Instances of this class behave like classes, not instances.
297
Methods like factory, that would be classmethods on a normal class, are
298
normal methods on FakeAttemptClass.
301
def factory(self, upgrade_sequence, attempt_stream):
304
def __init__(self, title, *result, **kwargs):
151
def __init__(self, title, *result):
305
152
self.title = title
306
153
self.test_id = '{}-id'.format(title)
307
154
self.result = result
308
self.new_path = kwargs.get('new_path')
310
156
def get_test_info(self):
311
157
return {self.test_id: {'title': self.title}}
313
159
def __call__(self):
314
return FakeStepAttempt.from_result(*self.result, test_id=self.test_id,
315
new_path=self.new_path)
160
return FakeAttempt(*self.result, test_id=self.test_id)
163
class StubJujuClient:
165
def destroy_environment(self, delete_jenv=False):
327
def fake_bootstrap_manager(self, temp_env_name, client, *args, **kwargs):
328
return FakeBootstrapManager(client)
331
178
class TestMultiIndustrialTest(TestCase):
333
180
def test_from_args(self):
335
env='foo', new_juju_path='new-path', attempts=7, suite=[DENSITY],
336
log_dir='log-dir', new_agent_url=None, debug=False,
337
old_stable=None, agent_stream=None)
181
args = Namespace(env='foo', new_juju_path='new-path', attempts=7,
182
suite=QUICK, new_agent_url=None)
338
183
with temp_env('foo'):
339
mit = MultiIndustrialTest.from_args(args, QUICK)
184
mit = MultiIndustrialTest.from_args(args)
340
185
self.assertEqual(mit.env, 'foo')
341
186
self.assertEqual(mit.new_juju_path, 'new-path')
342
187
self.assertEqual(mit.attempt_count, 7)
343
188
self.assertEqual(mit.max_attempts, 14)
344
self.assertEqual(mit.log_parent_dir, 'log-dir')
345
self.assertIs(mit.agent_stream, None)
346
189
self.assertEqual(
347
mit.stages, AttemptSuiteFactory([]))
349
env='bar', new_juju_path='new-path2', attempts=6, suite=[FULL],
350
log_dir='log-dir2', new_agent_url=None, debug=False,
351
old_stable=None, agent_stream=None)
190
mit.stages, [BootstrapAttempt, DestroyEnvironmentAttempt])
191
args = Namespace(env='bar', new_juju_path='new-path2', attempts=6,
192
suite=FULL, new_agent_url=None)
352
193
with temp_env('bar'):
353
mit = MultiIndustrialTest.from_args(args, FULL)
194
mit = MultiIndustrialTest.from_args(args)
354
195
self.assertEqual(mit.env, 'bar')
355
196
self.assertEqual(mit.new_juju_path, 'new-path2')
356
197
self.assertEqual(mit.attempt_count, 6)
357
198
self.assertEqual(mit.max_attempts, 12)
358
self.assertEqual(mit.log_parent_dir, 'log-dir2')
359
self.assertIs(mit.agent_stream, None)
360
199
self.assertEqual(
361
mit.stages, AttemptSuiteFactory([
362
UpgradeCharmAttempt, DeployManyAttempt,
363
BackupRestoreAttempt, EnsureAvailabilityAttempt]))
201
BootstrapAttempt, DeployManyAttempt, BackupRestoreAttempt,
202
EnsureAvailabilityAttempt, DestroyEnvironmentAttempt])
365
204
def test_from_args_maas(self):
367
env='foo', new_juju_path='new-path', log_dir='log-dir',
368
attempts=7, new_agent_url=None, debug=False, old_stable=None,
370
with temp_env('foo', {'type': 'maas'}):
371
mit = MultiIndustrialTest.from_args(args, DENSITY)
373
mit.stages, AttemptSuiteFactory([DeployManyAttempt]))
375
def test_from_args_debug(self):
377
env='foo', new_juju_path='new-path', log_dir='log-dir',
378
attempts=7, new_agent_url=None, debug=False, old_stable=None,
380
with temp_env('foo', {'type': 'maas'}):
381
mit = MultiIndustrialTest.from_args(args, DENSITY)
382
self.assertEqual(mit.debug, False)
384
mit = MultiIndustrialTest.from_args(args, DENSITY)
385
self.assertEqual(mit.debug, True)
387
def test_from_args_really_old_path(self):
389
env='foo', new_juju_path='new-path', log_dir='log-dir',
390
attempts=7, new_agent_url=None, debug=False,
391
old_stable='really-old-path', agent_stream=None)
392
with temp_env('foo'):
393
mit = MultiIndustrialTest.from_args(args, FULL)
394
self.assertEqual(mit.really_old_path, 'really-old-path')
396
env='bar', new_juju_path='new-path2', log_dir='log-dir',
397
attempts=6, new_agent_url=None, debug=False, old_stable=None,
399
with temp_env('bar'):
400
mit = MultiIndustrialTest.from_args(args, FULL)
401
self.assertIs(mit.really_old_path, None)
403
def test_from_args_agent_stream(self):
405
env='foo', new_juju_path='new-path', log_dir='log-dir',
406
attempts=7, new_agent_url=None, debug=False, old_stable=None,
407
agent_stream='foo-stream')
408
with temp_env('foo', {'type': 'maas'}):
409
mit = MultiIndustrialTest.from_args(args, DENSITY)
410
self.assertEqual(mit.debug, False)
412
mit = MultiIndustrialTest.from_args(args, DENSITY)
413
self.assertEqual(mit.agent_stream, 'foo-stream')
205
args = Namespace(env='foo', new_juju_path='new-path', attempts=7,
206
suite=DENSITY, new_agent_url=None)
207
with temp_env('foo', {'type': 'maas'}):
208
mit = MultiIndustrialTest.from_args(args)
211
BootstrapAttempt, DeployManyFactory(2, 2),
212
DestroyEnvironmentAttempt])
214
def test_get_stages(self):
216
MultiIndustrialTest.get_stages(QUICK, {'type': 'foo'}),
217
[BootstrapAttempt, DestroyEnvironmentAttempt])
220
MultiIndustrialTest.get_stages(FULL, {'type': 'foo'}), [
221
BootstrapAttempt, DeployManyAttempt, BackupRestoreAttempt,
222
EnsureAvailabilityAttempt, DestroyEnvironmentAttempt])
224
MultiIndustrialTest.get_stages(DENSITY, {'type': 'foo'}), [
225
BootstrapAttempt, DeployManyAttempt,
226
DestroyEnvironmentAttempt])
228
MultiIndustrialTest.get_stages(BACKUP, {'type': 'foo'}), [
229
BootstrapAttempt, BackupRestoreAttempt,
230
DestroyEnvironmentAttempt])
232
def test_get_stages_maas(self):
234
MultiIndustrialTest.get_stages(QUICK, {'type': 'maas'}),
235
[BootstrapAttempt, DestroyEnvironmentAttempt])
237
MultiIndustrialTest.get_stages(FULL, {'type': 'maas'}), [
238
BootstrapAttempt, DeployManyFactory(2, 2),
239
BackupRestoreAttempt, EnsureAvailabilityAttempt,
240
DestroyEnvironmentAttempt])
242
MultiIndustrialTest.get_stages(DENSITY, {'type': 'maas'}), [
243
BootstrapAttempt, DeployManyFactory(2, 2),
244
DestroyEnvironmentAttempt])
415
246
def test_density_suite(self):
417
env='foo', new_juju_path='new-path', attempts=7,
418
log_dir='log-dir', new_agent_url=None, debug=False,
419
old_stable=None, agent_stream=None)
247
args = Namespace(env='foo', new_juju_path='new-path', attempts=7,
248
suite=DENSITY, new_agent_url=None)
420
249
with temp_env('foo'):
421
mit = MultiIndustrialTest.from_args(args, DENSITY)
250
mit = MultiIndustrialTest.from_args(args)
422
251
self.assertEqual(
423
mit.stages, AttemptSuiteFactory([DeployManyAttempt]))
252
mit.stages, [BootstrapAttempt, DeployManyAttempt,
253
DestroyEnvironmentAttempt])
425
255
def test_backup_suite(self):
427
env='foo', new_juju_path='new-path', attempts=7,
428
log_dir='log-dir', new_agent_url=None, debug=False,
429
old_stable=None, agent_stream=None)
256
args = Namespace(env='foo', new_juju_path='new-path', attempts=7,
257
suite=BACKUP, new_agent_url=None)
430
258
with temp_env('foo'):
431
mit = MultiIndustrialTest.from_args(args, BACKUP)
259
mit = MultiIndustrialTest.from_args(args)
432
260
self.assertEqual(
433
mit.stages, AttemptSuiteFactory([BackupRestoreAttempt]))
261
mit.stages, [BootstrapAttempt, BackupRestoreAttempt,
262
DestroyEnvironmentAttempt])
435
264
def test_from_args_new_agent_url(self):
437
env='foo', new_juju_path='new-path', attempts=7,
438
log_dir='log-dir', new_agent_url='http://example.net',
439
debug=False, old_stable=None, agent_stream=None)
265
args = Namespace(env='foo', new_juju_path='new-path', attempts=7,
266
suite=QUICK, new_agent_url='http://example.net')
440
267
with temp_env('foo'):
441
mit = MultiIndustrialTest.from_args(args, suite=QUICK)
268
mit = MultiIndustrialTest.from_args(args)
442
269
self.assertEqual(mit.new_agent_url, 'http://example.net')
444
271
def test_init(self):
445
272
mit = MultiIndustrialTest('foo-env', 'bar-path', [
446
DestroyEnvironmentAttempt, BootstrapAttempt], 'log-dir', 5)
273
DestroyEnvironmentAttempt, BootstrapAttempt], 5)
447
274
self.assertEqual(mit.env, 'foo-env')
448
275
self.assertEqual(mit.new_juju_path, 'bar-path')
449
276
self.assertEqual(mit.stages, [DestroyEnvironmentAttempt,
450
277
BootstrapAttempt])
451
278
self.assertEqual(mit.attempt_count, 5)
452
self.assertEqual(mit.log_parent_dir, 'log-dir')
454
280
def test_make_results(self):
455
mit = MultiIndustrialTest('foo-env', 'bar-path', AttemptSuiteFactory([
456
DestroyEnvironmentAttempt]), 5)
457
results = mit.make_results()
458
self.assertEqual(results, {'results': [
459
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
460
'title': 'bootstrap', 'test_id': 'bootstrap', 'report_on': True},
461
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
462
'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
464
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
465
'title': 'destroy environment', 'test_id': 'destroy-env',
467
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
468
'title': 'check substrate clean', 'test_id': 'substrate-clean',
472
def test_make_results_report_on(self):
477
return {'no-report': {
478
'title': 'No report', 'report_on': False}}
480
mit = MultiIndustrialTest('foo-env', 'bar-path', AttemptSuiteFactory([
482
results = mit.make_results()
483
self.assertEqual(results, {'results': [
485
'test_id': 'bootstrap',
486
'title': 'bootstrap',
493
'test_id': 'prepare-suite',
494
'title': 'Prepare suite tests',
501
'test_id': 'no-report',
502
'title': 'No report',
509
'test_id': 'destroy-env',
510
'title': 'destroy environment',
517
'test_id': 'substrate-clean',
518
'title': 'check substrate clean',
528
def patch_client(by_version):
529
with patch('industrial_test.client_from_config',
530
side_effect=by_version):
531
with patch('jujupy.SimpleEnvironment.from_config',
532
side_effect=lambda x: SimpleEnvironment(x, {})):
533
with patch.object(EnvJujuClient, 'get_full_path',
534
side_effect=lambda: 'juju'):
281
mit = MultiIndustrialTest('foo-env', 'bar-path', [
282
DestroyEnvironmentAttempt, BootstrapAttempt], 5)
283
results = mit.make_results()
284
self.assertEqual(results, {'results': [
285
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
286
'title': 'destroy environment', 'test_id': 'destroy-env'},
287
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
288
'title': 'check substrate clean', 'test_id': 'substrate-clean'},
289
{'attempts': 0, 'old_failures': 0, 'new_failures': 0,
290
'title': 'bootstrap', 'test_id': 'bootstrap'},
537
293
def test_make_industrial_test(self):
538
mit = MultiIndustrialTest('foo-env', 'bar-path', AttemptSuiteFactory([
539
DestroyEnvironmentAttempt]), 'log-dir', 5)
540
with self.patch_client(
541
lambda x, y=None, debug=False: fake_juju_client(
542
JujuData(x, {}, juju_home=''), full_path=y)):
543
industrial = mit.make_industrial_test()
544
old_client = industrial.old_client
545
self.assertEqual((old_client.env, old_client.full_path), (
546
JujuData('foo-env-old', {'name': 'foo-env-old'}, juju_home=''),
548
new_client = industrial.new_client
549
self.assertEqual((new_client.env, new_client.full_path), (
550
JujuData('foo-env-new', {'name': 'foo-env-new'}, juju_home=''),
552
self.assertEqual(len(industrial.stage_attempts), 1)
553
self.assertEqual([mit.stages], [sa.attempt_list for sa in
554
industrial.stage_attempts])
294
mit = MultiIndustrialTest('foo-env', 'bar-path', [
295
DestroyEnvironmentAttempt, BootstrapAttempt], 5)
296
side_effect = lambda x, y=None: (x, y)
297
with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
298
with patch('jujupy.SimpleEnvironment.from_config',
299
side_effect=lambda x: SimpleEnvironment(x, {})):
300
industrial = mit.make_industrial_test()
301
self.assertEqual(industrial.old_client,
302
(SimpleEnvironment('foo-env-old', {}), None))
303
self.assertEqual(industrial.new_client,
304
(SimpleEnvironment('foo-env-new', {}), 'bar-path'))
305
self.assertEqual(len(industrial.stage_attempts), 2)
306
for stage, attempt in zip(mit.stages, industrial.stage_attempts):
307
self.assertIs(type(attempt), stage)
556
309
def test_make_industrial_test_new_agent_url(self):
557
mit = MultiIndustrialTest('foo-env', 'bar-path',
558
AttemptSuiteFactory([]), 'log-dir',
310
mit = MultiIndustrialTest('foo-env', 'bar-path', [],
559
311
new_agent_url='http://example.com')
560
with self.patch_client(
561
lambda x, y=None, debug=False: fake_juju_client(full_path=y)):
562
industrial = mit.make_industrial_test()
312
side_effect = lambda x, y=None: (x, y)
313
with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
314
with patch('jujupy.SimpleEnvironment.from_config',
315
side_effect=lambda x: SimpleEnvironment(x, {})):
316
industrial = mit.make_industrial_test()
563
317
self.assertEqual(
564
(industrial.new_client.env, industrial.new_client.full_path), (
565
JujuData('foo-env-new', {
567
'default-series': 'angsty',
569
'name': 'foo-env-new',
570
'tools-metadata-url': 'http://example.com',
318
industrial.new_client, (
319
SimpleEnvironment('foo-env-new', {
320
'tools-metadata-url': 'http://example.com'}),
575
def test_make_industrial_test_debug(self):
576
mit = MultiIndustrialTest('foo-env', 'bar-path',
577
AttemptSuiteFactory([]), 'log-dir',
578
new_agent_url='http://example.com')
580
def side_effect(x, y=None, debug=False):
581
return fake_juju_client(env=JujuData(x, {}, juju_home='x'),
582
full_path=y, debug=debug)
584
with self.patch_client(side_effect):
585
industrial = mit.make_industrial_test()
586
self.assertEqual(industrial.new_client.debug, False)
587
self.assertEqual(industrial.old_client.debug, False)
589
with self.patch_client(side_effect):
590
industrial = mit.make_industrial_test()
591
self.assertEqual(industrial.new_client.debug, True)
592
self.assertEqual(industrial.old_client.debug, True)
594
324
def test_update_results(self):
595
mit = MultiIndustrialTest('foo-env', 'bar-path',
596
AttemptSuiteFactory([]), 2)
325
mit = MultiIndustrialTest('foo-env', 'bar-path', [
326
DestroyEnvironmentAttempt, BootstrapAttempt], 2)
597
327
results = mit.make_results()
598
mit.update_results([('bootstrap', True, False)], results)
328
mit.update_results([('destroy-env', True, False)], results)
599
329
expected = {'results': [
600
{'title': 'bootstrap', 'test_id': 'bootstrap',
601
'attempts': 1, 'new_failures': 1, 'old_failures': 0,
603
{'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
605
'new_failures': 0, 'old_failures': 0, 'report_on': False},
606
330
{'title': 'destroy environment', 'test_id': 'destroy-env',
608
'new_failures': 0, 'old_failures': 0, 'report_on': True},
331
'attempts': 1, 'new_failures': 1, 'old_failures': 0},
609
332
{'title': 'check substrate clean', 'test_id': 'substrate-clean',
610
'attempts': 0, 'new_failures': 0, 'old_failures': 0,
333
'attempts': 0, 'new_failures': 0, 'old_failures': 0},
334
{'title': 'bootstrap', 'test_id': 'bootstrap', 'attempts': 0,
335
'new_failures': 0, 'old_failures': 0},
613
337
self.assertEqual(results, expected)
615
('bootstrap', True, True), ('prepare-suite', True, True),
616
('destroy-env', False, True), ('substrate-clean', True, True)
339
[('destroy-env', True, True), ('substrate-clean', True, True),
340
('bootstrap', False, True)],
618
342
self.assertEqual(results, {'results': [
619
{'title': 'bootstrap', 'test_id': 'bootstrap',
620
'attempts': 2, 'new_failures': 1, 'old_failures': 0,
622
{'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
623
'attempts': 1, 'new_failures': 0, 'old_failures': 0,
625
343
{'title': 'destroy environment', 'test_id': 'destroy-env',
626
'attempts': 1, 'new_failures': 0, 'old_failures': 1, 'report_on':
344
'attempts': 2, 'new_failures': 1, 'old_failures': 0},
628
345
{'title': 'check substrate clean', 'test_id': 'substrate-clean',
629
'attempts': 1, 'new_failures': 0, 'old_failures': 0,
346
'attempts': 1, 'new_failures': 0, 'old_failures': 0},
347
{'title': 'bootstrap', 'test_id': 'bootstrap', 'attempts': 1,
348
'new_failures': 0, 'old_failures': 1},
632
350
mit.update_results(
633
[('bootstrap', False, False), ('prepare-suite', True, True),
634
('destroy-env', False, False), ('substrate-clean', True, True)],
351
[('destroy-env', False, False), ('substrate-clean', True, True),
352
('bootstrap', False, False)],
636
354
expected = {'results': [
637
{'title': 'bootstrap', 'test_id': 'bootstrap',
638
'attempts': 2, 'new_failures': 1, 'old_failures': 0,
640
{'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
641
'attempts': 2, 'new_failures': 0, 'old_failures': 0,
643
355
{'title': 'destroy environment', 'test_id': 'destroy-env',
644
'attempts': 2, 'new_failures': 1, 'old_failures': 2,
356
'attempts': 2, 'new_failures': 1, 'old_failures': 0},
646
357
{'title': 'check substrate clean', 'test_id': 'substrate-clean',
647
'attempts': 2, 'new_failures': 0, 'old_failures': 0,
358
'attempts': 2, 'new_failures': 0, 'old_failures': 0},
359
{'title': 'bootstrap', 'test_id': 'bootstrap', 'attempts': 2,
360
'new_failures': 1, 'old_failures': 2},
650
362
self.assertEqual(results, expected)
652
364
def test_run_tests(self):
653
log_dir = use_context(self, temp_dir())
654
mit = MultiIndustrialTest('foo-env', 'bar-path', AttemptSuiteFactory([
655
FakeAttemptClass('foo', True, True, new_path='bar-path'),
656
FakeAttemptClass('bar', True, False, new_path='bar-path'),
659
def side_effect(env, full_path=None, debug=False):
660
return fake_juju_client(None, full_path, debug)
662
with self.patch_client(side_effect):
663
with patch('industrial_test.BootstrapManager',
664
side_effect=fake_bootstrap_manager):
365
mit = MultiIndustrialTest('foo-env', 'bar-path', [
366
FakeAttemptClass('foo', True, True),
367
FakeAttemptClass('bar', True, False),
369
side_effect = lambda x, y=None: StubJujuClient()
370
with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
371
with patch('jujupy.SimpleEnvironment.from_config',
372
side_effect=lambda x: SimpleEnvironment(x, {})):
665
373
results = mit.run_tests()
666
374
self.assertEqual(results, {'results': [
667
{'title': 'bootstrap', 'test_id': 'bootstrap', 'attempts': 5,
668
'old_failures': 0, 'new_failures': 0, 'report_on': True},
669
{'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
670
'attempts': 5, 'old_failures': 0, 'new_failures': 0,
672
375
{'title': 'foo', 'test_id': 'foo-id', 'attempts': 5,
673
'old_failures': 0, 'new_failures': 0, 'report_on': True},
376
'old_failures': 0, 'new_failures': 0},
674
377
{'title': 'bar', 'test_id': 'bar-id', 'attempts': 5,
675
'old_failures': 0, 'new_failures': 5, 'report_on': True},
676
{'title': 'destroy environment', 'test_id': 'destroy-env',
677
'attempts': 0, 'old_failures': 0, 'new_failures': 0,
679
{'title': 'check substrate clean', 'test_id': 'substrate-clean',
680
'attempts': 0, 'old_failures': 0, 'new_failures': 0,
378
'old_failures': 0, 'new_failures': 5},
684
381
def test_run_tests_max_attempts(self):
685
log_dir = use_context(self, temp_dir())
686
mit = MultiIndustrialTest('foo-env', 'bar-path', AttemptSuiteFactory([
687
FakeAttemptClass('foo', True, False, new_path='bar-path'),
688
FakeAttemptClass('bar', True, False, new_path='bar-path'),
691
def side_effect(env, full_path=None, debug=False):
692
return fake_juju_client(None, full_path, debug)
694
with self.patch_client(side_effect):
695
with patch('industrial_test.BootstrapManager',
696
side_effect=fake_bootstrap_manager):
382
mit = MultiIndustrialTest('foo-env', 'bar-path', [
383
FakeAttemptClass('foo', True, False),
384
FakeAttemptClass('bar', True, False),
386
side_effect = lambda x, y=None: StubJujuClient()
387
with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
388
with patch('jujupy.SimpleEnvironment.from_config',
389
side_effect=lambda x: SimpleEnvironment(x, {})):
697
390
results = mit.run_tests()
698
391
self.assertEqual(results, {'results': [
699
{'title': 'bootstrap', 'test_id': 'bootstrap', 'attempts': 5,
700
'old_failures': 0, 'new_failures': 0, 'report_on': True},
701
{'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
702
'attempts': 5, 'old_failures': 0, 'new_failures': 0,
704
392
{'title': 'foo', 'test_id': 'foo-id', 'attempts': 5,
705
'old_failures': 0, 'new_failures': 5, 'report_on': True},
393
'old_failures': 0, 'new_failures': 5},
706
394
{'title': 'bar', 'test_id': 'bar-id', 'attempts': 0,
707
'old_failures': 0, 'new_failures': 0, 'report_on': True},
708
{'title': 'destroy environment', 'test_id': 'destroy-env',
709
'attempts': 0, 'old_failures': 0, 'new_failures': 0,
711
{'title': 'check substrate clean', 'test_id': 'substrate-clean',
712
'attempts': 0, 'old_failures': 0, 'new_failures': 0,
395
'old_failures': 0, 'new_failures': 0},
716
398
def test_run_tests_max_attempts_less_than_attempt_count(self):
717
log_dir = use_context(self, temp_dir())
718
mit = MultiIndustrialTest(
719
'foo-env', 'bar-path', AttemptSuiteFactory([
720
FakeAttemptClass('foo', True, False, new_path='bar-path'),
721
FakeAttemptClass('bar', True, False, new_path='bar-path')],
725
def side_effect(env, full_path=None, debug=False):
726
return fake_juju_client(None, full_path, debug)
728
with self.patch_client(side_effect):
729
with patch('industrial_test.BootstrapManager',
730
side_effect=fake_bootstrap_manager):
399
mit = MultiIndustrialTest('foo-env', 'bar-path', [
400
FakeAttemptClass('foo', True, False),
401
FakeAttemptClass('bar', True, False),
403
side_effect = lambda x, y=None: StubJujuClient()
404
with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
405
with patch('jujupy.SimpleEnvironment.from_config',
406
side_effect=lambda x: SimpleEnvironment(x, {})):
731
407
results = mit.run_tests()
733
{'title': 'bootstrap', 'test_id': 'bootstrap', 'attempts': 4,
734
'old_failures': 0, 'new_failures': 0, 'report_on': True},
735
{'title': 'Prepare suite tests', 'test_id': 'prepare-suite',
736
'attempts': 4, 'old_failures': 0, 'new_failures': 0,
408
self.assertEqual(results, {'results': [
738
409
{'title': 'foo', 'test_id': 'foo-id', 'attempts': 4,
739
'old_failures': 0, 'new_failures': 4, 'report_on': True},
410
'old_failures': 0, 'new_failures': 4},
740
411
{'title': 'bar', 'test_id': 'bar-id', 'attempts': 0,
741
'old_failures': 0, 'new_failures': 0, 'report_on': True},
742
{'title': 'destroy environment', 'test_id': 'destroy-env',
743
'attempts': 0, 'old_failures': 0, 'new_failures': 0,
745
{'title': 'check substrate clean', 'test_id': 'substrate-clean',
746
'attempts': 0, 'old_failures': 0, 'new_failures': 0,
749
self.assertEqual(results, {'results': expected})
755
{'title': 'foo', 'attempts': 5, 'old_failures': 1,
756
'new_failures': 2, 'test_id': 'foo-id'},
757
{'title': 'bar', 'attempts': 5, 'old_failures': 3,
758
'new_failures': 4, 'report_on': True, 'test_id': 'bar-id'},
759
{'title': 'baz', 'attempts': 5, 'old_failures': 3,
760
'new_failures': 4, 'report_on': False, 'test_id': 'baz-id'},
763
def test_combine_results_noop(self):
764
new_results = MultiIndustrialTest.combine_results([
765
self.get_results_1()])
766
self.assertEqual(new_results, self.get_results_1())
768
def test_combine_results_append(self):
769
results_2 = {'results': [
770
{'title': 'qux', 'test_id': 'quxx-id', 'attempts': 2,
771
'old_failures': 2, 'new_failures': 1}]}
772
new_results = MultiIndustrialTest.combine_results(
773
[self.get_results_1(), results_2])
774
self.assertEqual(new_results['results'][:3],
775
self.get_results_1()['results'])
776
self.assertEqual(new_results['results'][3:], results_2['results'])
778
def test_combine_results_add(self):
779
results_2 = {'results': [
780
{'test_id': 'foo-id', 'title': 'foo6', 'attempts': 3,
781
'old_failures': 2, 'new_failures': 1}]}
782
new_results = MultiIndustrialTest.combine_results(
783
[self.get_results_1(), results_2])
784
self.assertEqual(new_results, {'results': [
785
{'title': 'foo', 'attempts': 8, 'old_failures': 3,
786
'new_failures': 3, 'test_id': 'foo-id', 'report_on': True},
787
{'title': 'bar', 'attempts': 5, 'old_failures': 3,
788
'new_failures': 4, 'report_on': True, 'test_id': 'bar-id'},
789
{'title': 'baz', 'attempts': 5, 'old_failures': 3,
790
'new_failures': 4, 'report_on': False, 'test_id': 'baz-id'},
412
'old_failures': 0, 'new_failures': 0},
793
def test_combine_results_report_on(self):
794
results_1 = {'results': [
795
{'test_id': 'foo-id', 'title': 'foo6', 'attempts': 3,
796
'old_failures': 2, 'new_failures': 1},
797
{'test_id': 'bar-id', 'title': 'bar6', 'attempts': 3,
798
'old_failures': 2, 'new_failures': 1},
799
{'test_id': 'baz-id', 'title': 'baz', 'attempts': 3,
800
'old_failures': 2, 'new_failures': 1, 'report_on': False},
801
{'test_id': 'qux-id', 'title': 'qux', 'attempts': 3,
802
'old_failures': 2, 'new_failures': 1, 'report_on': False},
804
results_2 = {'results': [
805
{'test_id': 'foo-id', 'title': 'foo6', 'attempts': 3,
806
'old_failures': 2, 'new_failures': 1, 'report_on': True},
807
{'test_id': 'bar-id', 'title': 'foo6', 'attempts': 3,
808
'old_failures': 2, 'new_failures': 1, 'report_on': False},
809
{'test_id': 'baz-id', 'title': 'foo6', 'attempts': 3,
810
'old_failures': 2, 'new_failures': 1},
811
{'test_id': 'qux-id', 'title': 'qux6', 'attempts': 3,
812
'old_failures': 2, 'new_failures': 1, 'report_on': False},
814
new_results = MultiIndustrialTest.combine_results(
815
[results_1, results_2])
816
self.assertEqual(new_results['results'][0].get('report_on', True),
818
self.assertEqual(new_results['results'][1].get('report_on', True),
820
self.assertEqual(new_results['results'][2].get('report_on', True),
822
self.assertEqual(new_results['results'][3].get('report_on', False),
825
415
def test_results_table(self):
827
417
{'title': 'foo', 'attempts': 5, 'old_failures': 1,
828
418
'new_failures': 2},
829
419
{'title': 'bar', 'attempts': 5, 'old_failures': 3,
830
'new_failures': 4, 'report_on': True},
831
{'title': 'baz', 'attempts': 5, 'old_failures': 3,
832
'new_failures': 4, 'report_on': False},
834
422
self.assertEqual(
835
423
''.join(MultiIndustrialTest.results_table(results)),
897
466
self.assertEqual(len(cc_mock.mock_calls), 0)
899
468
def test_run_stages_old_fail(self):
900
old_client = fake_juju_client()
901
new_client = fake_juju_client(full_path='bar-path')
469
old_client = FakeEnvJujuClient('old')
470
new_client = FakeEnvJujuClient('new')
902
471
industrial = IndustrialTest(old_client, new_client, [
903
FakeStepAttempt.from_result(False, True),
904
FakeStepAttempt.from_result(True, True)])
905
suite_factory = AttemptSuiteFactory([
906
FakeAttemptClass('foo', False, True, new_path='bar-path'),
907
FakeAttemptClass('bar', True, True, new_path='bar-path')])
908
log_dir = use_context(self, temp_dir())
909
suite = suite_factory.factory([], log_dir, None)
910
industrial = IndustrialTest(old_client, new_client, [suite])
911
with patch('industrial_test.BootstrapManager',
912
fake_bootstrap_manager):
472
FakeAttempt(False, True), FakeAttempt(True, True)])
473
with patch('subprocess.call') as cc_mock:
913
474
result = industrial.run_stages()
914
self.assertItemsEqual(result, [
915
('bootstrap', True, True),
916
('prepare-suite', True, True),
917
('foo-id', False, True)])
918
self.assertEqual('controller-killed',
919
old_client._backend.controller_state.state)
920
self.assertEqual('controller-killed',
921
new_client._backend.controller_state.state)
475
self.assertItemsEqual(result, [('foo-id', False, True)])
476
assert_juju_call(self, cc_mock, old_client,
477
('timeout', '600.00s', 'juju', '--show-log',
478
'destroy-environment', 'old', '--force', '-y'), 0)
479
assert_juju_call(self, cc_mock, new_client,
480
('timeout', '600.00s', 'juju', '--show-log',
481
'destroy-environment', 'new', '--force', '-y'), 1)
923
483
def test_run_stages_new_fail(self):
924
old_client = fake_juju_client()
925
new_client = fake_juju_client(full_path='bar-path')
926
log_dir = use_context(self, temp_dir())
927
suite_factory = AttemptSuiteFactory([
928
FakeAttemptClass('foo', True, False, new_path='bar-path'),
929
FakeAttemptClass('bar', True, True, new_path='bar-path')])
930
suite = suite_factory.factory([], log_dir, None)
931
industrial = IndustrialTest(old_client, new_client, [suite])
932
with patch('industrial_test.BootstrapManager',
933
fake_bootstrap_manager):
484
old_client = FakeEnvJujuClient('old')
485
new_client = FakeEnvJujuClient('new')
486
industrial = IndustrialTest(old_client, new_client, [
487
FakeAttempt(True, False), FakeAttempt(True, True)])
488
with patch('subprocess.call') as cc_mock:
934
489
result = industrial.run_stages()
935
self.assertItemsEqual(result, [
936
('bootstrap', True, True),
937
('prepare-suite', True, True),
938
('foo-id', True, False)])
939
self.assertEqual('controller-killed',
940
old_client._backend.controller_state.state)
941
self.assertEqual('controller-killed',
942
new_client._backend.controller_state.state)
490
self.assertItemsEqual(result, [('foo-id', True, False)])
491
assert_juju_call(self, cc_mock, old_client,
492
('timeout', '600.00s', 'juju', '--show-log',
493
'destroy-environment', 'old', '--force', '-y'), 0)
494
assert_juju_call(self, cc_mock, new_client,
495
('timeout', '600.00s', 'juju', '--show-log',
496
'destroy-environment', 'new', '--force', '-y'), 1)
944
498
def test_run_stages_both_fail(self):
945
old_client = fake_juju_client()
946
new_client = fake_juju_client()
947
log_dir = use_context(self, temp_dir())
948
suite = AttemptSuiteFactory([
949
FakeAttemptClass('foo', False, False),
950
FakeAttemptClass('bar', True, True)]).factory([], log_dir,
952
industrial = IndustrialTest(old_client, new_client, [suite])
953
with patch('industrial_test.BootstrapManager',
954
fake_bootstrap_manager):
499
old_client = FakeEnvJujuClient('old')
500
new_client = FakeEnvJujuClient('new')
501
industrial = IndustrialTest(old_client, new_client, [
502
FakeAttempt(False, False), FakeAttempt(True, True)])
503
with patch('subprocess.call') as cc_mock:
955
504
result = industrial.run_stages()
956
self.assertItemsEqual(result, [
957
('bootstrap', True, True),
958
('prepare-suite', True, True),
959
('foo-id', False, False)])
960
self.assertEqual('controller-killed',
961
old_client._backend.controller_state.state)
962
self.assertEqual('controller-killed',
963
new_client._backend.controller_state.state)
505
self.assertItemsEqual(result, [('foo-id', False, False)])
506
assert_juju_call(self, cc_mock, old_client,
507
('timeout', '600.00s', 'juju', '--show-log',
508
'destroy-environment', 'old', '--force', '-y'), 0)
509
assert_juju_call(self, cc_mock, new_client,
510
('timeout', '600.00s', 'juju', '--show-log',
511
'destroy-environment', 'new', '--force', '-y'), 1)
965
513
def test_run_stages_recover_failure(self):
966
old_client = fake_juju_client()
967
new_client = fake_juju_client()
514
old_client = FakeEnvJujuClient('old')
515
new_client = FakeEnvJujuClient('new')
968
516
fsa = FakeStepAttempt([('foo', True, False), ('bar', True, True)])
969
517
industrial = IndustrialTest(old_client, new_client, [
970
fsa, FakeStepAttempt.from_result(True, True)])
518
fsa, FakeAttempt(True, True)])
971
519
self.assertEqual(list(industrial.run_stages()), [
972
520
('foo', True, False), ('bar', True, True), ('foo-id', True, True)])
1166
762
[('test-1', True, False), ('test-2', False, True)])
1167
763
le_mock.assert_called_once_with(error)
1169
def test_factory(self):
1171
class StubSA(SteppedStageAttempt):
1174
super(StubSA, self).__init__()
1176
self.assertIs(type(StubSA.factory(['a', 'b', 'c'], None)), StubSA)
1178
def test_get_test_info(self):
1180
class StubSA(SteppedStageAttempt):
1183
def get_stage_info():
1184
return [StageInfo('foo-id', 'Foo title'),
1185
StageInfo('bar-id', 'Bar title', report_on=False)]
1187
self.assertEqual(StubSA.get_test_info(), OrderedDict([
1188
('foo-id', {'title': 'Foo title', 'report_on': True}),
1189
('bar-id', {'title': 'Bar title', 'report_on': False})]))
1192
def FakeEnvJujuClient(name='steve', version='1.2', full_path='/jbin/juju'):
1193
juju_data = JujuData(name, {'type': 'fake', 'region': 'regionx'})
1194
juju_data.credentials = {'credentials': {'fake': {'creds': {}}}}
1195
return EnvJujuClient(
1196
juju_data, version, full_path)
1199
class FakeEnvJujuClient1X(EnvJujuClient1X):
1201
def __init__(self, name='steve', version='1.2', full_path='/jbin/juju'):
1202
super(FakeEnvJujuClient1X, self).__init__(
1203
SimpleEnvironment(name, {'type': 'fake'}), version, full_path)
1206
class TestBootstrapAttempt(JujuPyTestCase):
1208
def test_iter_steps(self):
1209
client = FakeEnvJujuClient()
1210
bootstrap = BootstrapAttempt()
1211
boot_iter = iter_steps_validate_info(self, bootstrap, client)
1212
self.assertEqual(boot_iter.next(), {'test_id': 'bootstrap'})
1213
with observable_temp_file() as config_file:
1214
with patch('subprocess.Popen') as popen_mock:
1215
self.assertEqual(boot_iter.next(), {'test_id': 'bootstrap'})
1216
assert_juju_call(self, popen_mock, client, (
1217
'juju', '--show-log', 'bootstrap', '--constraints', 'mem=2G',
1218
'steve', 'fake/regionx', '--config', config_file.name,
1219
'--default-model', 'steve', '--agent-version', '1.2'))
1221
{'machines': {'0': {'agent-state': 'pending'}},
1222
'applications': {}},
1223
{'machines': {'0': {'agent-state': 'started'}},
1226
popen_mock.return_value.wait.return_value = 0
1227
self.assertEqual(boot_iter.next(), {'test_id': 'bootstrap'})
1228
with patch_status(client, *statuses) as gs_mock:
1229
self.assertEqual(boot_iter.next(),
1230
{'test_id': 'bootstrap', 'result': True})
1231
self.assertEqual(2, gs_mock.call_count)
1234
class TestDestroyEnvironmentAttempt(JujuPyTestCase):
1236
def test_iter_steps(self):
1237
client = FakeEnvJujuClient()
1238
destroy_env = DestroyEnvironmentAttempt()
1239
iterator = iter_steps_validate_info(self, destroy_env, client)
1240
self.assertEqual({'test_id': 'destroy-env'}, iterator.next())
1241
with patch.object(client, 'get_jes_command',
1242
return_value='kill-controller'):
1243
with patch.object(destroy_env, 'get_security_groups') as gsg_mock:
1244
with patch('subprocess.call', return_value=0) as mock_cc:
1245
self.assertEqual(iterator.next(), {
1246
'test_id': 'destroy-env', 'result': True})
1247
gsg_mock.assert_called_once_with(client)
1248
assert_juju_call(self, mock_cc, client, get_timeout_prefix(600) + (
1249
'juju', '--show-log', 'kill-controller', 'steve', '-y'))
1250
self.assertEqual(iterator.next(), {'test_id': 'substrate-clean'})
1251
with patch.object(destroy_env, 'check_security_groups') as csg_mock:
1252
self.assertEqual(iterator.next(),
1253
{'test_id': 'substrate-clean', 'result': True})
1254
csg_mock.assert_called_once_with(client, gsg_mock.return_value)
1256
def test_iter_steps_non_jes(self):
1257
client = FakeEnvJujuClient1X()
1258
destroy_env = DestroyEnvironmentAttempt()
1259
iterator = iter_steps_validate_info(self, destroy_env, client)
1260
self.assertEqual({'test_id': 'destroy-env'}, iterator.next())
1261
with patch.object(client, 'is_jes_enabled', return_value=False):
1262
with patch.object(destroy_env, 'get_security_groups') as gsg_mock:
1263
with patch('subprocess.call', return_value=0) as mock_cc:
1264
self.assertEqual(iterator.next(), {
1265
'test_id': 'destroy-env', 'result': True})
1266
gsg_mock.assert_called_once_with(client)
1267
assert_juju_call(self, mock_cc, client, get_timeout_prefix(600) + (
1268
'juju', '--show-log', 'destroy-environment', 'steve', '-y'))
766
class FakeEnvJujuClient(EnvJujuClient):
768
def __init__(self, name='steve'):
769
super(FakeEnvJujuClient, self).__init__(
770
SimpleEnvironment(name, {'type': 'fake'}), '1.2', '/jbin/juju')
772
def wait_for_started(self, start=None):
773
with patch('sys.stdout'):
774
return super(FakeEnvJujuClient, self).wait_for_started(0.01,
777
def wait_for_ha(self):
778
with patch('sys.stdout'):
779
return super(FakeEnvJujuClient, self).wait_for_ha(0.01)
781
def juju(self, *args, **kwargs):
782
# Suppress stdout for juju commands.
783
with patch('sys.stdout'):
784
return super(FakeEnvJujuClient, self).juju(*args, **kwargs)
787
class TestBootstrapAttempt(TestCase):
789
def test_do_operation(self):
790
client = FakeEnvJujuClient()
791
bootstrap = BootstrapAttempt()
792
with patch('subprocess.check_call') as mock_cc:
793
bootstrap.do_operation(client)
794
assert_juju_call(self, mock_cc, client, (
795
'juju', '--show-log', 'bootstrap', '-e', 'steve',
796
'--constraints', 'mem=2G'))
798
def test_do_operation_exception(self):
799
client = FakeEnvJujuClient()
800
bootstrap = BootstrapAttempt()
801
with patch('subprocess.check_call', side_effect=Exception
803
with patch('logging.exception') as le_mock:
804
bootstrap.do_operation(client)
805
le_mock.assert_called_once()
806
assert_juju_call(self, mock_cc, client, (
807
'juju', '--show-log', 'bootstrap', '-e', 'steve',
808
'--constraints', 'mem=2G'))
809
output = yaml.safe_dump({
810
'machines': {'0': {'agent-state': 'started'}},
813
with patch('subprocess.check_output', return_value=output):
814
with patch('logging.exception') as le_mock:
815
self.assertFalse(bootstrap.get_result(client))
816
le_mock.assert_called_once()
818
def test_get_result_true(self):
819
bootstrap = BootstrapAttempt()
820
client = FakeEnvJujuClient()
821
output = yaml.safe_dump({
822
'machines': {'0': {'agent-state': 'started'}},
825
with patch('subprocess.check_output', return_value=output):
826
self.assertTrue(bootstrap.get_result(client))
828
@patch('logging.error')
829
def test_get_result_false(self, le_mock):
830
bootstrap = BootstrapAttempt()
831
client = FakeEnvJujuClient()
832
output = yaml.safe_dump({
833
'machines': {'0': {'agent-state': 'pending'}},
836
with patch('subprocess.check_output', return_value=output):
837
with patch('logging.exception') as le_mock:
838
self.assertFalse(bootstrap.get_result(client))
839
le_mock.assert_called_once()
842
class TestDestroyEnvironmentAttempt(TestCase):
844
def test_iter_steps(self):
845
client = FakeEnvJujuClient()
846
destroy_env = DestroyEnvironmentAttempt()
847
iterator = iter_steps_validate_info(self, destroy_env, client)
848
self.assertEqual({'test_id': 'destroy-env'}, iterator.next())
849
with patch('subprocess.call') as mock_cc:
850
with patch.object(destroy_env, 'get_security_groups') as gsg_mock:
851
self.assertEqual(iterator.next(), {
852
'test_id': 'destroy-env', 'result': True})
853
gsg_mock.assert_called_once_with(client)
854
assert_juju_call(self, mock_cc, client, (
855
'timeout', '600.00s', 'juju', '--show-log', 'destroy-environment',
1269
857
self.assertEqual(iterator.next(), {'test_id': 'substrate-clean'})
1270
858
with patch.object(destroy_env, 'check_security_groups') as csg_mock:
1271
859
self.assertEqual(iterator.next(),
1460
980
self.assertEqual(co_mock.call_count, 0)
1463
class TestEnsureAvailabilityAttempt(JujuPyTestCase):
1465
def test_iter_steps(self):
1466
client = FakeEnvJujuClient()
1467
controller_client = client.get_controller_client()
1468
ensure_av = EnsureAvailabilityAttempt()
1469
ensure_iter = iter_steps_validate_info(self, ensure_av, client)
1470
self.assertEqual(ensure_iter.next(), {
1471
'test_id': 'ensure-availability-n3'})
1472
with patch('subprocess.check_call') as cc_mock:
1473
with patch.object(client, 'get_controller_client',
1474
return_value=controller_client, autospec=True):
1475
self.assertEqual(ensure_iter.next(), {
1476
'test_id': 'ensure-availability-n3'})
1480
('juju', '--show-log', 'enable-ha', '-m',
1481
'steve:{}'.format(controller_client.env.environment), '-n', '3'))
1484
'0': {'controller-member-status': 'has-vote'},
1485
'1': {'controller-member-status': 'has-vote'},
1486
'2': {'controller-member-status': 'has-vote'},
1490
with patch_status(controller_client, status) as gs_mock:
1491
self.assertEqual(ensure_iter.next(), {
1492
'test_id': 'ensure-availability-n3', 'result': True})
1493
gs_mock.assert_called_once_with(controller=True)
1495
def test_iter_steps_failure(self):
1496
client = FakeEnvJujuClient()
1497
ensure_av = EnsureAvailabilityAttempt()
1498
ensure_iter = iter_steps_validate_info(self, ensure_av, client)
1500
with patch('subprocess.check_call'):
1501
controller_client = client.get_controller_client()
1502
with patch.object(client, 'get_controller_client',
1503
return_value=controller_client, autospec=True):
1507
'0': {'state-server-member-status': 'has-vote'},
1508
'1': {'state-server-member-status': 'has-vote'},
1512
with patch_status(controller_client, status) as gs_mock:
983
class TestEnsureAvailabilityAttempt(TestCase):
986
patcher = patch('jujupy.pause')
987
self.addCleanup(patcher.stop)
988
self.pause_mock = patcher.start()
990
def test__operation(self):
991
client = FakeEnvJujuClient()
992
ensure_av = EnsureAvailabilityAttempt()
993
with patch('subprocess.check_call') as mock_cc:
994
ensure_av._operation(client)
995
assert_juju_call(self, mock_cc, client, (
996
'juju', '--show-log', 'ensure-availability', '-e', 'steve', '-n',
999
def test__result_true(self):
1000
ensure_av = EnsureAvailabilityAttempt()
1001
client = FakeEnvJujuClient()
1002
output = yaml.safe_dump({
1004
'0': {'state-server-member-status': 'has-vote'},
1005
'1': {'state-server-member-status': 'has-vote'},
1006
'2': {'state-server-member-status': 'has-vote'},
1010
with patch('subprocess.check_output', return_value=output):
1011
self.assertTrue(ensure_av.get_result(client))
1013
def test__result_false(self):
1014
ensure_av = EnsureAvailabilityAttempt()
1015
client = FakeEnvJujuClient()
1016
output = yaml.safe_dump({
1018
'0': {'state-server-member-status': 'has-vote'},
1019
'1': {'state-server-member-status': 'has-vote'},
1023
with patch('subprocess.check_output', return_value=output):
1513
1024
with self.assertRaisesRegexp(
1514
1025
Exception, 'Timed out waiting for voting to be enabled.'):
1516
self.assertEqual(2, gs_mock.call_count)
1519
class TestDeployManyAttempt(JujuPyTestCase):
1521
def predict_add_machine_calls(self, deploy_many, machine_type):
1026
ensure_av._result(client)
1029
class TestDeployManyAttempt(TestCase):
1031
def predict_add_machine_calls(self, deploy_many):
1522
1032
for host in range(1, deploy_many.host_count + 1):
1523
1033
for container in range(deploy_many.container_count):
1524
target = '{}:{}'.format(machine_type, host)
1034
target = 'lxc:{}'.format(host)
1525
1035
service = 'ubuntu{}x{}'.format(host, container)
1526
yield ('juju', '--show-log', 'deploy', '-m', 'steve:steve',
1527
'ubuntu', service, '--to', target, '--series', 'angsty')
1529
def predict_remove_machine_calls(self, deploy_many):
1530
total_guests = deploy_many.host_count * deploy_many.container_count
1531
for guest in range(100, total_guests + 100):
1532
yield ('juju', '--show-log', 'remove-machine', '-m', 'steve:steve',
1533
'--force', str(guest))
1036
yield ('juju', '--show-log', 'deploy', '-e', 'steve', '--to',
1037
target, 'ubuntu', service)
1535
1039
def test_iter_steps(self):
1536
machine_started = {'juju-status': {'current': 'idle'}}
1537
unit_started = {'agent-status': {'current': 'idle'}}
1538
client = FakeEnvJujuClient()
1539
client.env.config['default-series'] = 'angsty'
1540
self.do_iter_steps(client, LXD_MACHINE, machine_started, unit_started)
1542
def test_iter_steps_1x(self):
1543
started_state = {'agent-state': 'started'}
1544
client = FakeEnvJujuClient()
1545
with patch.object(EnvJujuClient, 'supported_container_types',
1546
frozenset([KVM_MACHINE, LXC_MACHINE])):
1547
client.env.config['default-series'] = 'angsty'
1548
self.do_iter_steps(client, LXC_MACHINE, started_state,
1551
def do_iter_steps(self, client, machine_type, machine_started,
1040
client = FakeEnvJujuClient()
1553
1041
deploy_many = DeployManyAttempt(9, 11)
1554
1042
deploy_iter = iter_steps_validate_info(self, deploy_many, client)
1555
1043
self.assertEqual(deploy_iter.next(), {'test_id': 'add-machine-many'})
1557
'machines': {'0': dict(machine_started)},
1560
with patch_status(client, status):
1044
status = yaml.safe_dump({
1045
'machines': {'0': {'agent-state': 'started'}},
1048
with patch('subprocess.check_output', return_value=status):
1561
1049
with patch('subprocess.check_call') as mock_cc:
1562
1050
self.assertEqual(deploy_iter.next(),
1563
1051
{'test_id': 'add-machine-many'})
1564
1052
for index in range(deploy_many.host_count):
1565
1053
assert_juju_call(self, mock_cc, client, (
1566
'juju', '--show-log', 'add-machine',
1567
'-m', 'steve:steve'), index)
1054
'juju', '--show-log', 'add-machine', '-e', 'steve'), index)
1570
'machines': dict((str(x), dict(machine_started))
1056
status = yaml.safe_dump({
1057
'machines': dict((str(x), {'agent-state': 'started'})
1571
1058
for x in range(deploy_many.host_count + 1)),
1574
with patch_status(client, status):
1061
with patch('subprocess.check_output', return_value=status):
1575
1062
self.assertEqual(
1576
1063
deploy_iter.next(),
1577
1064
{'test_id': 'add-machine-many', 'result': True})
1810
1208
def test_iter_steps(self):
1811
1209
br_attempt = BackupRestoreAttempt()
1812
1210
client = FakeEnvJujuClient()
1813
aws_env = get_aws_env()
1814
client.env.environment = aws_env.environment
1815
client.env.config = aws_env.config
1816
client.env.juju_home = aws_env.juju_home
1817
client.env.credentials = {'credentials': {'aws': {'creds': {}}}}
1818
controller_client = client.get_controller_client()
1211
client.env = get_aws_env()
1819
1212
environ = dict(os.environ)
1820
1213
environ.update(get_euca_env(client.env.config))
1822
1215
def check_output(*args, **kwargs):
1824
'juju', '--show-log', 'create-backup', '-m',
1825
'steve:{}'.format(controller_client.env.environment),),):
1826
return FakePopen('juju-backup-24.tgz', '', 0)
1216
if args == (['juju', 'backup'],):
1217
return 'juju-backup-24.tgz'
1218
if args == (('juju', '--show-log', 'status', '-e', 'baz'),):
1219
return yaml.safe_dump({
1221
'instance-id': 'asdf',
1222
'dns-name': '128.100.100.128',
1827
1225
self.assertEqual([], args)
1830
'instance-id': 'asdf',
1831
'dns-name': '128.100.100.128',
1834
1226
iterator = iter_steps_validate_info(self, br_attempt, client)
1835
1227
self.assertEqual(iterator.next(), {'test_id': 'back-up-restore'})
1836
with patch_status(controller_client, initial_status) as gs_mock:
1837
with patch('subprocess.Popen',
1838
side_effect=check_output) as co_mock:
1839
with patch('subprocess.check_call') as cc_mock:
1840
with patch.object(client, 'get_controller_client',
1841
return_value=controller_client,
1843
with patch('sys.stdout'):
1846
{'test_id': 'back-up-restore'})
1851
('juju', '--show-log', 'create-backup',
1852
'-m', 'steve:{}'.format(controller_client.env.environment)),
1228
with patch('subprocess.check_output',
1229
side_effect=check_output) as co_mock:
1230
with patch('subprocess.check_call') as cc_mock:
1231
with patch('sys.stdout'):
1234
{'test_id': 'back-up-restore'})
1235
assert_juju_call(self, co_mock, client, ['juju', 'backup'], 0)
1854
1236
self.assertEqual(
1855
1237
cc_mock.mock_calls[0],
1856
1238
call(['euca-terminate-instances', 'asdf'], env=environ))
1857
with patch('deploy_stack.wait_for_port'):
1858
with patch('deploy_stack.print_now', autospec=True) as pn_mock:
1239
self.assertEqual(iterator.next(), {'test_id': 'back-up-restore'})
1240
with patch('subprocess.check_call') as cc_mock:
1241
with patch('sys.stdout'):
1859
1242
self.assertEqual(iterator.next(),
1860
1243
{'test_id': 'back-up-restore'})
1861
pn_mock.assert_called_with('Closed.')
1862
with patch.object(controller_client, 'restore_backup') as rb_mock:
1863
self.assertEqual(iterator.next(), {'test_id': 'back-up-restore'})
1864
rb_mock.assert_called_once_with(
1865
os.path.abspath('juju-backup-24.tgz'))
1866
with patch('os.unlink') as ul_mock:
1867
self.assertEqual(iterator.next(),
1868
{'test_id': 'back-up-restore'})
1869
ul_mock.assert_called_once_with(os.path.abspath('juju-backup-24.tgz'))
1245
self, cc_mock, client, (
1246
'juju', '--show-log', 'restore', '-e', 'baz',
1247
os.path.abspath('juju-backup-24.tgz')))
1248
output = yaml.safe_dump({
1872
1250
'0': {'agent-state': 'started'},
1876
with patch_status(controller_client, final_status) as gs_mock:
1254
with patch('subprocess.check_output', return_value=output) as co_mock:
1877
1255
self.assertEqual(iterator.next(),
1878
1256
{'test_id': 'back-up-restore', 'result': True})
1879
gs_mock.assert_called_once_with()
1881
def test_iter_steps_azure(self):
1882
test_id = {'test_id': 'back-up-restore'}
1883
br_attempt = BackupRestoreAttempt()
1884
azure_env = SimpleEnvironment('steve', get_azure_config())
1885
client = FakeEnvJujuClient()
1886
client.env.environment = azure_env.environment
1887
client.env.config = azure_env.config
1888
client.env.credentials = {'credentials': {'azure': {'creds': {}}}}
1889
controller_client = client.get_controller_client()
1891
iterator = iter_steps_validate_info(self, br_attempt, client)
1892
self.assertEqual(iterator.next(), test_id)
1896
'instance-id': 'not-id',
1897
'dns-name': '128.100.100.128',
1900
# The azure-provider does does not provide sane ids, so the instance-id
1901
# is used to search for the actual azure instance.
1902
substrate = AzureARMAccount(None)
1904
'industrial_test.make_substrate_manager'
1906
msm_mock.return_value.__enter__.return_value = substrate
1907
with patch.object(substrate, 'convert_to_azure_ids',
1908
autospec=True, return_value=['id']) as ca_mock:
1909
with patch.object(client, 'get_controller_client',
1911
return_value=controller_client):
1912
with patch.object(controller_client, 'backup',
1914
return_value='juju-backup.tgz'
1916
with patch('industrial_test.terminate_instances',
1918
with patch_status(controller_client,
1920
self.assertEqual(iterator.next(), test_id)
1921
b_mock.assert_called_once_with()
1922
ca_mock.assert_called_once_with(controller_client, ['not-id'])
1925
class TestPrepareUpgradeJujuAttempt(JujuPyTestCase):
1927
def test_factory(self):
1928
uj_attempt = PrepareUpgradeJujuAttempt.factory(
1929
['a', 'b', 'c'], None)
1930
self.assertIs(type(uj_attempt), PrepareUpgradeJujuAttempt)
1931
self.assertEqual(uj_attempt.bootstrap_paths, {'b': 'a', 'c': 'b'})
1933
def test_factory_empty(self):
1934
with self.assertRaisesRegexp(
1935
ValueError, 'Not enough paths for upgrade.'):
1936
PrepareUpgradeJujuAttempt.factory(['a'], None)
1937
with self.assertRaisesRegexp(
1938
ValueError, 'Not enough paths for upgrade.'):
1939
PrepareUpgradeJujuAttempt.factory([], None)
1941
def test_get_bootstrap_client(self):
1942
client = fake_juju_client(full_path='c', debug=True)
1943
puj_attempt = PrepareUpgradeJujuAttempt.factory(['a', 'b', 'c'], None)
1945
def by_version(path):
1946
return fake_juju_client(client.env, path, client.debug)
1948
with patch.object(client, 'clone_path_cls', by_version):
1949
bootstrap_client = puj_attempt.get_bootstrap_client(client)
1951
self.assertIsNot(bootstrap_client, client)
1952
self.assertIs(client.debug, bootstrap_client.debug)
1953
self.assertIs(client.env, bootstrap_client.env)
1954
self.assertEqual('b', bootstrap_client.full_path)
1956
def test_iter_steps(self):
1957
future_client = FakeEnvJujuClient(full_path='/future/juju')
1958
present_client = FakeEnvJujuClient(full_path='/present/juju')
1959
puj_attempt = PrepareUpgradeJujuAttempt(
1960
{future_client.full_path: present_client.full_path})
1961
puj_iterator = iter_steps_validate_info(self, puj_attempt,
1963
with patch('subprocess.check_output', return_value='2.0-alpha3-a-b'):
1964
with patch('industrial_test.client_from_config',
1965
return_value=future_client):
1966
self.assertEqual({'test_id': 'prepare-upgrade-juju'},
1967
puj_iterator.next())
1968
with observable_temp_file() as config_file:
1969
with patch('subprocess.Popen') as po_mock:
1970
self.assertEqual({'test_id': 'prepare-upgrade-juju'},
1971
puj_iterator.next())
1972
assert_juju_call(self, po_mock, future_client, (
1973
'juju', '--show-log', 'bootstrap', '--constraints', 'mem=2G',
1974
'steve', 'fake/regionx', '--config', config_file.name,
1975
'--agent-version', '2.0-alpha3'))
1976
po_mock.return_value.wait.return_value = 0
1977
self.assertEqual(puj_iterator.next(),
1978
{'test_id': 'prepare-upgrade-juju'})
1980
'machines': {'0': {'agent-state': 'started'}},
1983
with patch_status(None, b_status):
1985
puj_iterator.next(),
1986
{'test_id': 'prepare-upgrade-juju', 'result': True})
1988
def test_iter_steps_no_previous_client(self):
1989
uj_attempt = PrepareUpgradeJujuAttempt({})
1990
client = FakeEnvJujuClient(full_path='/present/juju')
1991
uj_iterator = uj_attempt.iter_steps(client)
1992
with self.assertRaises(CannotUpgradeToClient) as exc_context:
1994
self.assertIs(exc_context.exception.client, client)
1997
class TestUpgradeJujuAttempt(JujuPyTestCase):
1999
def test_iter_steps(self):
2000
future_client = FakeEnvJujuClient(full_path='/future/juju')
2001
uj_attempt = UpgradeJujuAttempt()
2002
uj_iterator = iter_steps_validate_info(self, uj_attempt, future_client)
2003
self.assertEqual(uj_iterator.next(), {'test_id': 'upgrade-juju'})
2004
with patch('subprocess.check_call') as cc_mock:
2005
self.assertEqual({'test_id': 'upgrade-juju'}, uj_iterator.next())
2010
('juju', '--show-log', 'upgrade-juju',
2011
'-m', 'steve:steve', '--agent-version',
2012
future_client.get_matching_agent_version()))
2015
'agent-version': future_client.get_matching_agent_version()}},
2018
with patch_status(None, version_status):
2019
self.assertEqual({'test_id': 'upgrade-juju', 'result': True},
2023
class TestUpgradeCharmAttempt(JujuPyTestCase):
2025
def assert_hook(self, hook_path, content):
2026
with open(hook_path) as hook_file:
2027
self.assertEqual(hook_file.read(), content)
2028
mode = os.fstat(hook_file.fileno()).st_mode
2029
self.assertEqual(0o755, mode & 0o777)
2031
def test_iter_steps(self):
2032
client = FakeEnvJujuClient(version='2.0.0', full_path='/future/juju')
2033
self._iter_steps(client)
2035
def test_iter_steps_juju_1x(self):
2036
client = FakeEnvJujuClient1X(version='1.25.0',
2037
full_path='/future/juju')
2038
self._iter_steps(client)
2040
def _iter_steps(self, client):
2041
self.assertEqual(client.full_path, '/future/juju')
2042
uc_attempt = UpgradeCharmAttempt()
2043
uc_iterator = iter_steps_validate_info(self, uc_attempt, client)
2044
self.assertEqual(uc_iterator.next(),
2045
{'test_id': 'prepare-upgrade-charm'})
2046
temp_repository = mkdtemp()
2047
with patch('utility.mkdtemp', return_value=temp_repository):
2048
with patch('subprocess.check_call') as cc_mock:
2049
self.assertEqual(uc_iterator.next(),
2050
{'test_id': 'prepare-upgrade-charm'})
2051
metadata_path = os.path.join(
2052
temp_repository, 'trusty', 'mycharm', 'metadata.yaml')
2053
with open(metadata_path) as metadata_file:
2054
metadata = yaml.safe_load(metadata_file)
2055
self.assertEqual(metadata['name'], 'mycharm')
2056
self.assertIn('summary', metadata)
2057
self.assertIn('description', metadata)
2058
self.assertEqual(['trusty'], metadata['series'])
2059
if client.version.startswith('1.'):
2060
charm_path = os.path.join('local:trusty', 'mycharm')
2061
assert_juju_call(self, cc_mock, client, (
2062
'juju', '--show-log', 'deploy', '-e', 'steve', charm_path,
2063
'--repository', temp_repository))
2066
charm_path = os.path.join(temp_repository, 'trusty', 'mycharm')
2067
assert_juju_call(self, cc_mock, client, (
2068
'juju', '--show-log', 'deploy',
2069
'-m', 'steve:steve', charm_path))
2071
self.assertNotIn('min-juju-version', metadata)
2073
'machines': {'0': {'agent-state': 'started'}},
2076
with patch_status(client, status):
2077
self.assertEqual(uc_iterator.next(),
2078
{'test_id': 'prepare-upgrade-charm'})
2079
hooks_path = os.path.join(temp_repository, 'trusty', 'mycharm',
2081
upgrade_path = os.path.join(hooks_path, 'upgrade-charm')
2082
config_changed = os.path.join(hooks_path, 'config-changed')
2083
self.assertFalse(os.path.exists(config_changed))
2084
self.assertFalse(os.path.exists(upgrade_path))
2087
{'test_id': 'prepare-upgrade-charm', 'result': True})
2088
self.assert_hook(upgrade_path, dedent("""\
2092
self.assert_hook(config_changed, dedent("""\
2096
self.assertEqual(uc_iterator.next(), {'test_id': 'upgrade-charm'})
2097
with patch('subprocess.check_call') as cc_mock:
2098
self.assertEqual(uc_iterator.next(), {'test_id': 'upgrade-charm'})
2099
if client.version.startswith('1.'):
2100
assert_juju_call(self, cc_mock, client, (
2101
'juju', '--show-log', 'upgrade-charm', option, 'steve',
2102
'mycharm', '--repository', temp_repository))
2104
assert_juju_call(self, cc_mock, client, (
2105
'juju', '--show-log', 'upgrade-charm', option, 'steve:steve',
2106
'mycharm', '--path', os.path.join(temp_repository, 'trusty',
2109
'machines': {'0': {'agent-state': 'started'}},
2110
'applications': {'mycharm': {'units': {'mycharm/0': {
2111
'open-ports': ['42/tcp', '34/tcp'],
2114
with patch_status(client, status):
2117
{'test_id': 'upgrade-charm', 'result': True})
1257
assert_juju_call(self, co_mock, client, (
1258
'juju', '--show-log', 'status', '-e', 'baz'), assign_stderr=True)
2120
1261
class TestMaybeWriteJson(TestCase):
2140
1281
self.assertEqual(temp_file.read(), expected)
2143
class TestMakeSubstrate(JujuPyTestCase):
1284
class TestMakeSubstrate(TestCase):
2145
def test_make_substrate_manager_no_support(self):
2146
client = EnvJujuClient(JujuData('foo', {'type': 'foo'}),
1286
def test_make_substrate_no_support(self):
1287
client = EnvJujuClient(SimpleEnvironment('foo', {'type': 'foo'}),
2148
client.env.credentials = {'credentials': {'foo': {'creds': {}}}}
2149
with make_substrate_manager(client, []) as substrate:
2150
self.assertIs(substrate, None)
1289
self.assertIs(make_substrate(client, []), None)
2152
1291
def test_make_substrate_no_requirements(self):
2153
client = EnvJujuClient(get_aws_juju_data(), '', '')
2154
client.env.credentials = {'credentials': {'aws': {'creds': {}}}}
2155
with make_substrate_manager(client, []) as substrate:
2156
self.assertIs(type(substrate), AWSAccount)
1292
client = EnvJujuClient(get_aws_env(), '', '')
1293
self.assertIs(type(make_substrate(client, [])), AWSAccount)
2158
def test_make_substrate_manager_unsatisifed_requirements(self):
2159
client = EnvJujuClient(get_aws_juju_data(), '', '')
2160
client.env.credentials = {'credentials': {'aws': {'creds': {}}}}
2161
with make_substrate_manager(client, ['foo']) as substrate:
2162
self.assertIs(substrate, None)
2163
with make_substrate_manager(
2164
client, ['iter_security_groups', 'foo']) as substrate:
2165
self.assertIs(substrate, None)
1295
def test_make_substrate_unsatisifed_requirements(self):
1296
client = EnvJujuClient(get_aws_env(), '', '')
1297
self.assertIs(make_substrate(client, ['foo']), None)
1298
self.assertIs(make_substrate(client, ['iter_security_groups', 'foo']),
2167
1301
def test_make_substrate_satisfied_requirements(self):
2168
client = EnvJujuClient(get_aws_juju_data(), '', '')
2169
client.env.credentials = {'credentials': {'aws': {'creds': {}}}}
2170
with make_substrate_manager(
2171
client, ['iter_security_groups']) as substrate:
2172
self.assertIs(type(substrate), AWSAccount)
2173
with make_substrate_manager(
2174
client, ['iter_security_groups',
2175
'iter_instance_security_groups']
2177
self.assertIs(type(substrate), AWSAccount)
2180
class TestStageInfo(TestCase):
2182
def test_ctor(self):
2183
si = StageInfo('foo-id', 'Foo title')
2184
self.assertEqual(si.stage_id, 'foo-id')
2185
self.assertEqual(si.title, 'Foo title')
2186
self.assertEqual(si.report_on, True)
2188
si = StageInfo('foo-id', 'Foo title', False)
2189
self.assertEqual(si.report_on, False)
2191
def test_as_tuple(self):
2192
si = StageInfo('foo-id', 'Foo title')
2195
('foo-id', {'title': 'Foo title', 'report_on': True}))
2196
si = StageInfo('bar-id', 'Bar title', False)
2199
('bar-id', {'title': 'Bar title', 'report_on': False}))
2201
def test_as_result(self):
2202
si = StageInfo('foo-id', 'Foo title')
2203
self.assertEqual(si.as_result(), {'test_id': 'foo-id'})
2204
self.assertEqual(si.as_result(True),
2205
{'test_id': 'foo-id', 'result': True})
2206
self.assertEqual(si.as_result(False),
2207
{'test_id': 'foo-id', 'result': False})
2210
class TestAttemptSuiteFactory(TestCase):
2212
def test_factory(self):
2213
fake_bootstrap = FakeAttemptClass('bootstrap')
2214
factory = AttemptSuiteFactory([],
2215
bootstrap_attempt=fake_bootstrap)
2216
attempt_suite = factory.factory(['1', '2'], 'log-1', 'foo-stream')
2217
self.assertEqual(factory, attempt_suite.attempt_list)
2218
self.assertEqual(['1', '2'], attempt_suite.upgrade_sequence)
2219
self.assertEqual('log-1', attempt_suite.log_dir)
2220
self.assertEqual('foo-stream', attempt_suite.agent_stream)
2222
def test_get_test_info(self):
2223
fake_bootstrap = FakeAttemptClass('fake-bootstrap')
2224
fake_1 = FakeAttemptClass('fake-1')
2225
fake_2 = FakeAttemptClass('fake-2')
2226
factory = AttemptSuiteFactory([fake_1, fake_2],
2227
bootstrap_attempt=fake_bootstrap)
2228
self.assertEqual(OrderedDict([
2229
('fake-bootstrap-id', {'title': 'fake-bootstrap'}),
2230
('prepare-suite', {'title': 'Prepare suite tests',
2231
'report_on': False}),
2232
('fake-1-id', {'title': 'fake-1'}),
2233
('fake-2-id', {'title': 'fake-2'}),
2234
('destroy-env', {'title': 'destroy environment',
2235
'report_on': True}),
2236
('substrate-clean', {'title': 'check substrate clean',
2237
'report_on': True}),
2238
]), factory.get_test_info())
2241
class TestAttemptSuite(TestCase):
2243
def test_get_test_info(self):
2244
fake_bootstrap = FakeAttemptClass('fake-bootstrap')
2245
fake_1 = FakeAttemptClass('fake-1')
2246
fake_2 = FakeAttemptClass('fake-2')
2247
factory = AttemptSuiteFactory([fake_1, fake_2],
2248
bootstrap_attempt=fake_bootstrap)
2249
attempt_suite = AttemptSuite(factory, None, None, None)
2250
self.assertEqual(OrderedDict([
2251
('fake-bootstrap-id', {'title': 'fake-bootstrap'}),
2252
('prepare-suite', {'title': 'Prepare suite tests',
2253
'report_on': False}),
2254
('fake-1-id', {'title': 'fake-1'}),
2255
('fake-2-id', {'title': 'fake-2'}),
2256
('destroy-env', {'title': 'destroy environment',
2257
'report_on': True}),
2258
('substrate-clean', {'title': 'check substrate clean',
2259
'report_on': True}),
2260
]), attempt_suite.get_test_info())
2263
def iter_steps_cxt(self, attempt_suite):
2264
with patch('industrial_test.BootstrapManager') as mock_bm:
2265
with patch.object(attempt_suite,
2266
'_iter_bs_manager_steps') as mock_ibms:
2267
with patch('industrial_test.make_log_dir',
2268
return_value='qux-1'):
2269
yield (mock_ibms, mock_bm)
2271
def test_iter_steps(self):
2272
fake_bootstrap = FakeAttemptClass('fake-bootstrap', '1', '2')
2273
factory = AttemptSuiteFactory([], bootstrap_attempt=fake_bootstrap)
2274
attempt_suite = AttemptSuite(factory, None, 'asdf', None)
2275
with self.iter_steps_cxt(attempt_suite) as (mock_ibms, mock_bm):
2276
client = fake_juju_client()
2277
attempt_suite.iter_steps(client)
2278
mock_bm.assert_called_once_with(
2279
'name', client, client, agent_stream=None, agent_url=None,
2280
bootstrap_host=None, jes_enabled=True, keep_env=True,
2281
log_dir='qux-1', machines=[], permanent=True,
2282
region=None, series=None)
2284
def test_iter_steps_agent_stream(self):
2285
fake_bootstrap = FakeAttemptClass('fake-bootstrap', '1', '2')
2286
factory = AttemptSuiteFactory([], bootstrap_attempt=fake_bootstrap)
2287
attempt_suite = AttemptSuite(factory, None, 'asdf', 'bar-stream')
2288
with self.iter_steps_cxt(attempt_suite) as (mock_ibms, mock_bm):
2289
client = fake_juju_client()
2290
iterator = attempt_suite.iter_steps(client)
2291
self.assertEqual(iterator, mock_ibms.return_value)
2292
mock_bm.assert_called_once_with(
2293
'name', client, client, agent_stream='bar-stream', agent_url=None,
2294
bootstrap_host=None, jes_enabled=True, keep_env=True,
2295
log_dir='qux-1', machines=[], permanent=True,
2296
region=None, series=None)
2298
def test__iter_bs_manager_steps(self):
2299
fake_bootstrap = FakeAttemptClass('fake-bootstrap', '1', '2')
2300
fake_1 = FakeAttemptClass('fake-1', '1', '2')
2301
fake_2 = FakeAttemptClass('fake-2', '1', '2')
2302
factory = AttemptSuiteFactory([fake_1, fake_2],
2303
bootstrap_attempt=fake_bootstrap)
2304
attempt_suite = AttemptSuite(factory, None, None, None)
2305
client = fake_juju_client()
2306
bs_manager = FakeBootstrapManager(client)
2307
steps = list(attempt_suite._iter_bs_manager_steps(
2308
bs_manager, client, fake_bootstrap(), True))
2310
{'test_id': 'fake-bootstrap-id'},
2311
{'test_id': 'fake-bootstrap-id', 'result': '1'},
2312
{'test_id': 'prepare-suite'},
2313
{'test_id': 'prepare-suite', 'result': True},
2314
{'test_id': 'fake-1-id'},
2315
{'test_id': 'fake-1-id', 'result': '1'},
2316
{'test_id': 'fake-2-id'},
2317
{'test_id': 'fake-2-id', 'result': '1'},
2318
{'test_id': 'destroy-env'},
2319
{'test_id': 'destroy-env', 'result': True},
2320
{'test_id': 'substrate-clean'},
2321
{'test_id': 'substrate-clean', 'result': True},
2324
def test__iter_bs_manager_steps_teardown_in_runtime(self):
2325
fake_bootstrap = FakeAttemptClass('fake-bootstrap', '1', '2')
2326
fake_1 = FakeAttemptClass('fake-1', Exception('fake exception'), '2')
2327
factory = AttemptSuiteFactory([fake_1],
2328
bootstrap_attempt=fake_bootstrap)
2329
attempt_suite = AttemptSuite(factory, None, None, None)
2330
client = fake_juju_client()
2331
bs_manager = FakeBootstrapManager(client, keep_env=True)
2332
with self.assertRaisesRegexp(Exception, 'fake exception'):
2333
list(attempt_suite._iter_bs_manager_steps(
2334
bs_manager, client, fake_bootstrap(), True))
2335
self.assertIs(True, bs_manager.torn_down)
1302
client = EnvJujuClient(get_aws_env(), '', '')
1303
self.assertIs(type(make_substrate(client, ['iter_security_groups'])),
1305
self.assertIs(type(make_substrate(client, [
1306
'iter_security_groups', 'iter_instance_security_groups'])),