~andrewjbeach/juju-ci-tools/make-local-patcher

« back to all changes in this revision

Viewing changes to tests/test_industrial_test.py

  • Committer: Curtis Hovey
  • Date: 2016-09-20 01:59:47 UTC
  • mto: This revision was merged to the branch mainline in revision 1602.
  • Revision ID: curtis@canonical.com-20160920015947-ko27xkj3a4i774h6
Convert juju instance=ids to true azuzre ids.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
    closing,
6
6
    contextmanager,
7
7
    )
 
8
import json
8
9
import os
9
10
from tempfile import (
10
11
    mkdtemp,
20
21
    )
21
22
import yaml
22
23
 
 
24
from fakejuju import (
 
25
    fake_juju_client,
 
26
    )
23
27
from industrial_test import (
24
28
    AttemptSuite,
25
29
    AttemptSuiteFactory,
51
55
    EnvJujuClient1X,
52
56
    get_timeout_prefix,
53
57
    JujuData,
 
58
    KVM_MACHINE,
 
59
    LXC_MACHINE,
 
60
    LXD_MACHINE,
54
61
    SimpleEnvironment,
55
62
    Status,
56
63
    _temp_env,
63
70
    use_context,
64
71
)
65
72
from tests.test_deploy_stack import FakeBootstrapManager
66
 
from test_jujupy import (
 
73
from tests.test_jujupy import (
67
74
    assert_juju_call,
68
 
    FakeJujuClient,
 
75
    FakePopen,
69
76
    observable_temp_file,
70
77
    )
71
 
from test_substrate import (
 
78
from tests.test_substrate import (
72
79
    get_aws_env,
 
80
    get_azure_config,
73
81
    get_os_config,
74
82
    make_os_security_group_instance,
75
83
    make_os_security_groups,
142
150
    """
143
151
    kwargs = {}
144
152
    if len(statuses) > 1:
145
 
        kwargs['side_effect'] = (Status.from_text(yaml.safe_dump(s))
 
153
        kwargs['side_effect'] = (Status.from_text(json.dumps(s))
146
154
                                 for s in statuses).next
147
155
    else:
148
 
        kwargs['return_value'] = Status.from_text(yaml.safe_dump(statuses[0]))
 
156
        kwargs['return_value'] = Status.from_text(json.dumps(statuses[0]))
149
157
    if client is not None:
150
158
        return patch.object(client, 'get_status', autospec=True, **kwargs)
151
159
    return patch('jujupy.EnvJujuClient.get_status', autospec=True, **kwargs)
272
280
    def iter_steps(self, client):
273
281
        yield self.stage.as_result()
274
282
        if self.new_path is not None and client.full_path == self.new_path:
275
 
            yield self.stage.as_result(self.result[0][2])
 
283
            result_value = self.result[0][2]
276
284
        else:
277
 
            yield self.stage.as_result(self.result[0][1])
 
285
            result_value = self.result[0][1]
 
286
        if isinstance(result_value, BaseException):
 
287
            raise result_value
 
288
        yield self.stage.as_result(result_value)
278
289
 
279
290
 
280
291
class FakeAttemptClass:
512
523
    @staticmethod
513
524
    @contextmanager
514
525
    def patch_client(by_version):
515
 
        with patch('jujupy.EnvJujuClient.by_version', side_effect=by_version):
 
526
        with patch('industrial_test.client_from_config',
 
527
                   side_effect=by_version):
516
528
            with patch('jujupy.SimpleEnvironment.from_config',
517
529
                       side_effect=lambda x: SimpleEnvironment(x, {})):
518
530
                with patch.object(EnvJujuClient, 'get_full_path',
522
534
    def test_make_industrial_test(self):
523
535
        mit = MultiIndustrialTest('foo-env', 'bar-path', AttemptSuiteFactory([
524
536
            DestroyEnvironmentAttempt]), 'log-dir', 5)
525
 
        with self.patch_client(lambda x, y=None, debug=False: (x, y)):
 
537
        with self.patch_client(
 
538
            lambda x, y=None, debug=False: fake_juju_client(
 
539
                JujuData(x, {}, juju_home=''), full_path=y)):
526
540
            industrial = mit.make_industrial_test()
527
 
        self.assertEqual(industrial.old_client, (
528
 
            SimpleEnvironment('foo-env-old', {'name': 'foo-env-old'}), None))
529
 
        self.assertEqual(industrial.new_client, (
530
 
            SimpleEnvironment('foo-env-new', {'name': 'foo-env-new'}),
 
541
        old_client = industrial.old_client
 
542
        self.assertEqual((old_client.env, old_client.full_path), (
 
543
            JujuData('foo-env-old', {'name': 'foo-env-old'}, juju_home=''),
 
544
            None))
 
545
        new_client = industrial.new_client
 
546
        self.assertEqual((new_client.env, new_client.full_path), (
 
547
            JujuData('foo-env-new', {'name': 'foo-env-new'}, juju_home=''),
531
548
            'bar-path'))
532
549
        self.assertEqual(len(industrial.stage_attempts), 1)
533
550
        self.assertEqual([mit.stages], [sa.attempt_list for sa in
537
554
        mit = MultiIndustrialTest('foo-env', 'bar-path',
538
555
                                  AttemptSuiteFactory([]), 'log-dir',
539
556
                                  new_agent_url='http://example.com')
540
 
        with self.patch_client(lambda x, y=None, debug=False: (x, y)):
 
557
        with self.patch_client(
 
558
                lambda x, y=None, debug=False: fake_juju_client(full_path=y)):
541
559
            industrial = mit.make_industrial_test()
542
560
        self.assertEqual(
543
 
            industrial.new_client, (
544
 
                SimpleEnvironment('foo-env-new', {
 
561
            (industrial.new_client.env, industrial.new_client.full_path), (
 
562
                JujuData('foo-env-new', {
 
563
                    'type': 'foo',
 
564
                    'default-series': 'angsty',
 
565
                    'region': 'bar',
545
566
                    'name': 'foo-env-new',
546
567
                    'tools-metadata-url': 'http://example.com',
547
 
                    }),
 
568
                    }, 'foo'),
548
569
                'bar-path')
549
570
            )
550
571
 
554
575
                                  new_agent_url='http://example.com')
555
576
 
556
577
        def side_effect(x, y=None, debug=False):
557
 
            return debug
 
578
            return fake_juju_client(env=JujuData(x, {}, juju_home='x'),
 
579
                                    full_path=y, debug=debug)
558
580
 
559
581
        with self.patch_client(side_effect):
560
582
            industrial = mit.make_industrial_test()
561
 
        self.assertEqual(industrial.new_client, False)
562
 
        self.assertEqual(industrial.old_client, False)
 
583
        self.assertEqual(industrial.new_client.debug, False)
 
584
        self.assertEqual(industrial.old_client.debug, False)
563
585
        mit.debug = True
564
586
        with self.patch_client(side_effect):
565
587
            industrial = mit.make_industrial_test()
566
 
        self.assertEqual(industrial.new_client, True)
567
 
        self.assertEqual(industrial.old_client, True)
 
588
        self.assertEqual(industrial.new_client.debug, True)
 
589
        self.assertEqual(industrial.old_client.debug, True)
568
590
 
569
591
    def test_update_results(self):
570
592
        mit = MultiIndustrialTest('foo-env', 'bar-path',
632
654
            ]), log_dir, 5, 10)
633
655
 
634
656
        def side_effect(env, full_path=None, debug=False):
635
 
            return FakeJujuClient(None, full_path, debug)
 
657
            return fake_juju_client(None, full_path, debug)
636
658
 
637
659
        with self.patch_client(side_effect):
638
660
            with patch('industrial_test.BootstrapManager',
664
686
            ]), log_dir, 5, 6)
665
687
 
666
688
        def side_effect(env, full_path=None, debug=False):
667
 
            return FakeJujuClient(None, full_path, debug)
 
689
            return fake_juju_client(None, full_path, debug)
668
690
 
669
691
        with self.patch_client(side_effect):
670
692
            with patch('industrial_test.BootstrapManager',
698
720
            log_dir, 5, 4)
699
721
 
700
722
        def side_effect(env, full_path=None, debug=False):
701
 
            return FakeJujuClient(None, full_path, debug)
 
723
            return fake_juju_client(None, full_path, debug)
702
724
 
703
725
        with self.patch_client(side_effect):
704
726
            with patch('industrial_test.BootstrapManager',
828
850
 
829
851
    def test_from_args(self):
830
852
        def side_effect(x, y=None, debug=False):
831
 
            return (x, y)
832
 
        with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
833
 
            with patch('jujupy.SimpleEnvironment.from_config',
834
 
                       side_effect=lambda x: SimpleEnvironment(x, {})):
835
 
                industrial = IndustrialTest.from_args(
836
 
                    'foo', 'new-juju-path', [])
 
853
            return fake_juju_client(env=JujuData(x, {}), full_path=y)
 
854
        with patch('industrial_test.client_from_config',
 
855
                   side_effect=side_effect):
 
856
            industrial = IndustrialTest.from_args(
 
857
                'foo', 'new-juju-path', [])
837
858
        self.assertIsInstance(industrial, IndustrialTest)
838
 
        self.assertEqual(industrial.old_client, (
839
 
            SimpleEnvironment('foo-old', {'name': 'foo-old'}), None))
840
 
        self.assertEqual(industrial.new_client, (
841
 
            SimpleEnvironment('foo-new', {'name': 'foo-new'}),
 
859
        old_client = industrial.old_client
 
860
        self.assertEqual((old_client.env, old_client.full_path), (
 
861
            JujuData('foo-old', {'name': 'foo-old'}), None))
 
862
        new_client = industrial.new_client
 
863
        self.assertEqual((new_client.env, new_client.full_path), (
 
864
            JujuData('foo-new', {'name': 'foo-new'}),
842
865
            'new-juju-path'))
843
 
        self.assertNotEqual(industrial.old_client[0].environment,
844
 
                            industrial.new_client[0].environment)
 
866
        self.assertNotEqual(old_client.env.environment,
 
867
                            new_client.env.environment)
845
868
 
846
869
    def test_from_args_debug(self):
847
870
        def side_effect(x, y=None, debug=False):
848
 
            return debug
849
 
        with patch('jujupy.EnvJujuClient.by_version', side_effect=side_effect):
 
871
            return fake_juju_client(full_path=y, debug=debug)
 
872
        with patch('industrial_test.client_from_config',
 
873
                   side_effect=side_effect):
850
874
            with patch('jujupy.SimpleEnvironment.from_config'):
851
875
                industrial = IndustrialTest.from_args(
852
876
                    'foo', 'new-juju-path', [], debug=False)
853
 
                self.assertEqual(industrial.old_client, False)
854
 
                self.assertEqual(industrial.new_client, False)
 
877
                self.assertEqual(industrial.old_client.debug, False)
 
878
                self.assertEqual(industrial.new_client.debug, False)
855
879
                industrial = IndustrialTest.from_args(
856
880
                    'foo', 'new-juju-path', [], debug=True)
857
 
                self.assertEqual(industrial.old_client, True)
858
 
                self.assertEqual(industrial.new_client, True)
 
881
                self.assertEqual(industrial.old_client.debug, True)
 
882
                self.assertEqual(industrial.new_client.debug, True)
859
883
 
860
884
    def test_run_stages(self):
861
885
        old_client = FakeEnvJujuClient('old')
870
894
        self.assertEqual(len(cc_mock.mock_calls), 0)
871
895
 
872
896
    def test_run_stages_old_fail(self):
873
 
        old_client = FakeJujuClient()
874
 
        new_client = FakeJujuClient(full_path='bar-path')
 
897
        old_client = fake_juju_client()
 
898
        new_client = fake_juju_client(full_path='bar-path')
875
899
        industrial = IndustrialTest(old_client, new_client, [
876
900
            FakeStepAttempt.from_result(False, True),
877
901
            FakeStepAttempt.from_result(True, True)])
888
912
                ('bootstrap', True, True),
889
913
                ('prepare-suite', True, True),
890
914
                ('foo-id', False, True)])
891
 
        self.assertEqual('destroyed', old_client._backing_state.state)
892
 
        self.assertEqual('destroyed', new_client._backing_state.state)
 
915
        self.assertEqual('controller-killed',
 
916
                         old_client._backend.controller_state.state)
 
917
        self.assertEqual('controller-killed',
 
918
                         new_client._backend.controller_state.state)
893
919
 
894
920
    def test_run_stages_new_fail(self):
895
 
        old_client = FakeJujuClient()
896
 
        new_client = FakeJujuClient(full_path='bar-path')
 
921
        old_client = fake_juju_client()
 
922
        new_client = fake_juju_client(full_path='bar-path')
897
923
        log_dir = use_context(self, temp_dir())
898
924
        suite_factory = AttemptSuiteFactory([
899
925
            FakeAttemptClass('foo', True, False, new_path='bar-path'),
907
933
                ('bootstrap', True, True),
908
934
                ('prepare-suite', True, True),
909
935
                ('foo-id', True, False)])
910
 
        self.assertEqual('destroyed', old_client._backing_state.state)
911
 
        self.assertEqual('destroyed', new_client._backing_state.state)
 
936
        self.assertEqual('controller-killed',
 
937
                         old_client._backend.controller_state.state)
 
938
        self.assertEqual('controller-killed',
 
939
                         new_client._backend.controller_state.state)
912
940
 
913
941
    def test_run_stages_both_fail(self):
914
 
        old_client = FakeJujuClient()
915
 
        new_client = FakeJujuClient()
 
942
        old_client = fake_juju_client()
 
943
        new_client = fake_juju_client()
916
944
        log_dir = use_context(self, temp_dir())
917
945
        suite = AttemptSuiteFactory([
918
946
            FakeAttemptClass('foo', False, False),
926
954
                ('bootstrap', True, True),
927
955
                ('prepare-suite', True, True),
928
956
                ('foo-id', False, False)])
929
 
        self.assertEqual('destroyed', old_client._backing_state.state)
930
 
        self.assertEqual('destroyed', new_client._backing_state.state)
 
957
        self.assertEqual('controller-killed',
 
958
                         old_client._backend.controller_state.state)
 
959
        self.assertEqual('controller-killed',
 
960
                         new_client._backend.controller_state.state)
931
961
 
932
962
    def test_run_stages_recover_failure(self):
933
 
        old_client = FakeJujuClient()
934
 
        new_client = FakeJujuClient()
 
963
        old_client = fake_juju_client()
 
964
        new_client = fake_juju_client()
935
965
        fsa = FakeStepAttempt([('foo', True, False), ('bar', True, True)])
936
966
        industrial = IndustrialTest(old_client, new_client, [
937
967
            fsa, FakeStepAttempt.from_result(True, True)])
957
987
            list(industrial.run_stages())
958
988
 
959
989
    def test_run_attempt(self):
960
 
        old_client = FakeJujuClient()
961
 
        new_client = FakeJujuClient()
 
990
        old_client = fake_juju_client()
 
991
        new_client = fake_juju_client()
962
992
        attempt = FakeStepAttempt.from_result(True, True)
963
993
        log_dir = use_context(self, temp_dir())
964
994
        suite = AttemptSuiteFactory([attempt]).factory([], log_dir, None)
976
1006
                           fake_bootstrap_manager):
977
1007
                    industrial.run_attempt()
978
1008
        self.assertEqual(2, le_mock.call_count)
979
 
        self.assertEqual('destroyed', old_client._backing_state.state)
980
 
        self.assertEqual('destroyed', new_client._backing_state.state)
 
1009
        self.assertEqual('controller-killed',
 
1010
                         old_client._backend.controller_state.state)
 
1011
        self.assertEqual('controller-killed',
 
1012
                         new_client._backend.controller_state.state)
981
1013
 
982
1014
 
983
1015
class TestSteppedStageAttempt(JujuPyTestCase):
1154
1186
            ('bar-id', {'title': 'Bar title', 'report_on': False})]))
1155
1187
 
1156
1188
 
1157
 
class FakeEnvJujuClient(EnvJujuClient):
1158
 
 
1159
 
    def __init__(self, name='steve'):
1160
 
        super(FakeEnvJujuClient, self).__init__(
1161
 
            JujuData(name, {'type': 'fake', 'region': 'regionx'}),
1162
 
            '1.2', '/jbin/juju')
 
1189
def FakeEnvJujuClient(name='steve', version='1.2', full_path='/jbin/juju'):
 
1190
    return EnvJujuClient(
 
1191
        JujuData(name, {'type': 'fake', 'region': 'regionx'}),
 
1192
        version, full_path)
1163
1193
 
1164
1194
 
1165
1195
class FakeEnvJujuClient1X(EnvJujuClient1X):
1166
1196
 
1167
 
    def __init__(self, name='steve'):
 
1197
    def __init__(self, name='steve', version='1.2', full_path='/jbin/juju'):
1168
1198
        super(FakeEnvJujuClient1X, self).__init__(
1169
 
            SimpleEnvironment(name, {'type': 'fake'}), '1.2', '/jbin/juju')
 
1199
            SimpleEnvironment(name, {'type': 'fake'}), version, full_path)
1170
1200
 
1171
1201
 
1172
1202
class TestBootstrapAttempt(JujuPyTestCase):
1185
1215
                '--default-model', 'steve', '--agent-version', '1.2'))
1186
1216
            statuses = [
1187
1217
                {'machines': {'0': {'agent-state': 'pending'}},
1188
 
                 'services': {}},
 
1218
                 'applications': {}},
1189
1219
                {'machines': {'0': {'agent-state': 'started'}},
1190
 
                 'services': {}},
 
1220
                 'applicaions': {}},
1191
1221
            ]
1192
1222
            popen_mock.return_value.wait.return_value = 0
1193
1223
            self.assertEqual(boot_iter.next(), {'test_id': 'bootstrap'})
1286
1316
            iterator.next()
1287
1317
 
1288
1318
    def test_iter_steps_kill_controller(self):
1289
 
        client = FakeJujuClient(jes_enabled=True)
 
1319
        client = fake_juju_client()
 
1320
        client.bootstrap()
1290
1321
        destroy_env = DestroyEnvironmentAttempt()
1291
1322
        iterator = iter_steps_validate_info(self, destroy_env, client)
1292
1323
        with closing(iterator):
1293
1324
            self.assertEqual({'test_id': 'destroy-env'}, iterator.next())
1294
1325
            self.assertEqual(iterator.next(), {
1295
1326
                'test_id': 'destroy-env', 'result': True})
1296
 
        self.assertEqual('controller-killed', client._backing_state.state)
 
1327
        self.assertEqual('controller-killed',
 
1328
                         client._backend.controller_state.state)
1297
1329
 
1298
1330
    @staticmethod
1299
1331
    def get_aws_client():
1423
1455
 
1424
1456
    def test_iter_steps(self):
1425
1457
        client = FakeEnvJujuClient()
 
1458
        controller_client = client.get_controller_client()
1426
1459
        ensure_av = EnsureAvailabilityAttempt()
1427
1460
        ensure_iter = iter_steps_validate_info(self, ensure_av, client)
1428
1461
        self.assertEqual(ensure_iter.next(), {
1429
1462
            'test_id': 'ensure-availability-n3'})
1430
1463
        with patch('subprocess.check_call') as cc_mock:
1431
 
            self.assertEqual(ensure_iter.next(), {
1432
 
                'test_id': 'ensure-availability-n3'})
1433
 
        assert_juju_call(self, cc_mock, client, (
1434
 
            'juju', '--show-log', 'enable-ha', '-m', 'steve', '-n', '3'))
 
1464
            with patch.object(client, 'get_controller_client',
 
1465
                              return_value=controller_client, autospec=True):
 
1466
                self.assertEqual(ensure_iter.next(), {
 
1467
                    'test_id': 'ensure-availability-n3'})
 
1468
        assert_juju_call(
 
1469
            self,
 
1470
            cc_mock, client,
 
1471
            ('juju', '--show-log', 'enable-ha', '-m',
 
1472
             'steve:{}'.format(controller_client.env.environment), '-n', '3'))
1435
1473
        status = {
1436
1474
            'machines': {
1437
1475
                '0': {'controller-member-status': 'has-vote'},
1438
1476
                '1': {'controller-member-status': 'has-vote'},
1439
1477
                '2': {'controller-member-status': 'has-vote'},
1440
1478
                },
1441
 
            'services': {},
 
1479
            'applications': {},
1442
1480
        }
1443
 
        with patch_status(client, status) as gs_mock:
 
1481
        with patch_status(controller_client, status) as gs_mock:
1444
1482
            self.assertEqual(ensure_iter.next(), {
1445
1483
                'test_id': 'ensure-availability-n3', 'result': True})
1446
 
        gs_mock.assert_called_once_with(admin=True)
 
1484
        gs_mock.assert_called_once_with(controller=True)
1447
1485
 
1448
1486
    def test_iter_steps_failure(self):
1449
1487
        client = FakeEnvJujuClient()
1451
1489
        ensure_iter = iter_steps_validate_info(self, ensure_av, client)
1452
1490
        ensure_iter.next()
1453
1491
        with patch('subprocess.check_call'):
1454
 
            ensure_iter.next()
 
1492
            controller_client = client.get_controller_client()
 
1493
            with patch.object(client, 'get_controller_client',
 
1494
                              return_value=controller_client, autospec=True):
 
1495
                ensure_iter.next()
1455
1496
        status = {
1456
1497
            'machines': {
1457
1498
                '0': {'state-server-member-status': 'has-vote'},
1458
1499
                '1': {'state-server-member-status': 'has-vote'},
1459
1500
                },
1460
 
            'services': {},
 
1501
            'applications': {},
1461
1502
        }
1462
 
        with patch_status(client, status) as gs_mock:
 
1503
        with patch_status(controller_client, status) as gs_mock:
1463
1504
            with self.assertRaisesRegexp(
1464
1505
                    Exception, 'Timed out waiting for voting to be enabled.'):
1465
1506
                ensure_iter.next()
1468
1509
 
1469
1510
class TestDeployManyAttempt(JujuPyTestCase):
1470
1511
 
1471
 
    def predict_add_machine_calls(self, deploy_many):
 
1512
    def predict_add_machine_calls(self, deploy_many, machine_type):
1472
1513
        for host in range(1, deploy_many.host_count + 1):
1473
1514
            for container in range(deploy_many.container_count):
1474
 
                target = 'lxc:{}'.format(host)
 
1515
                target = '{}:{}'.format(machine_type, host)
1475
1516
                service = 'ubuntu{}x{}'.format(host, container)
1476
 
                yield ('juju', '--show-log', 'deploy', '-m', 'steve', '--to',
1477
 
                       target, 'ubuntu', service)
 
1517
                yield ('juju', '--show-log', 'deploy', '-m', 'steve:steve',
 
1518
                       'ubuntu', service, '--to', target, '--series', 'angsty')
1478
1519
 
1479
1520
    def predict_remove_machine_calls(self, deploy_many):
1480
1521
        total_guests = deploy_many.host_count * deploy_many.container_count
1481
1522
        for guest in range(100, total_guests + 100):
1482
 
            yield ('juju', '--show-log', 'remove-machine', '-m', 'steve',
 
1523
            yield ('juju', '--show-log', 'remove-machine', '-m', 'steve:steve',
1483
1524
                   '--force', str(guest))
1484
1525
 
1485
1526
    def test_iter_steps(self):
1486
 
        client = FakeEnvJujuClient()
 
1527
        machine_started = {'juju-status': {'current': 'idle'}}
 
1528
        unit_started = {'agent-status': {'current': 'idle'}}
 
1529
        client = FakeEnvJujuClient()
 
1530
        client.env.config['default-series'] = 'angsty'
 
1531
        self.do_iter_steps(client, LXD_MACHINE, machine_started, unit_started)
 
1532
 
 
1533
    def test_iter_steps_1x(self):
 
1534
        started_state = {'agent-state': 'started'}
 
1535
        client = FakeEnvJujuClient()
 
1536
        with patch.object(EnvJujuClient, 'supported_container_types',
 
1537
                          frozenset([KVM_MACHINE, LXC_MACHINE])):
 
1538
            client.env.config['default-series'] = 'angsty'
 
1539
            self.do_iter_steps(client, LXC_MACHINE, started_state,
 
1540
                               started_state)
 
1541
 
 
1542
    def do_iter_steps(self, client, machine_type, machine_started,
 
1543
                      unit_started):
1487
1544
        deploy_many = DeployManyAttempt(9, 11)
1488
1545
        deploy_iter = iter_steps_validate_info(self, deploy_many, client)
1489
1546
        self.assertEqual(deploy_iter.next(), {'test_id': 'add-machine-many'})
1490
1547
        status = {
1491
 
            'machines': {'0': {'agent-state': 'started'}},
1492
 
            'services': {},
 
1548
            'machines': {'0': dict(machine_started)},
 
1549
            'applications': {},
1493
1550
        }
1494
1551
        with patch_status(client, status):
1495
1552
            with patch('subprocess.check_call') as mock_cc:
1497
1554
                                 {'test_id': 'add-machine-many'})
1498
1555
        for index in range(deploy_many.host_count):
1499
1556
            assert_juju_call(self, mock_cc, client, (
1500
 
                'juju', '--show-log', 'add-machine', '-m', 'steve'), index)
 
1557
                'juju', '--show-log', 'add-machine',
 
1558
                '-m', 'steve:steve'), index)
1501
1559
 
1502
1560
        status = {
1503
 
            'machines': dict((str(x), {'agent-state': 'started'})
 
1561
            'machines': dict((str(x), dict(machine_started))
1504
1562
                             for x in range(deploy_many.host_count + 1)),
1505
 
            'services': {},
 
1563
            'applications': {},
1506
1564
        }
1507
1565
        with patch_status(client, status):
1508
1566
                self.assertEqual(
1521
1579
            self.assertEqual(deploy_iter.next(),
1522
1580
                             {'test_id': 'deploy-many'})
1523
1581
 
1524
 
        calls = self.predict_add_machine_calls(deploy_many)
 
1582
        calls = self.predict_add_machine_calls(deploy_many, machine_type)
1525
1583
        for num, args in enumerate(calls):
1526
1584
            assert_juju_call(self, mock_cc, client, args, num)
1527
1585
        service_names = []
1528
1586
        for host in range(1, deploy_many.host_count + 1):
1529
1587
            for container in range(deploy_many.container_count):
1530
1588
                service_names.append('ubuntu{}x{}'.format(host, container))
1531
 
        services = dict((service_name, {
1532
 
            'units': {
1533
 
                'foo': {'machine': str(num + 100), 'agent-state': 'started'}
1534
 
                }})
1535
 
            for num, service_name in enumerate(service_names))
 
1589
        applications = {}
 
1590
        for num, service_name in enumerate(service_names):
 
1591
            foo = {'machine': str(num + 100)}
 
1592
            foo.update(unit_started)
 
1593
            units = {
 
1594
                'foo': foo,
 
1595
                }
 
1596
            applications[service_name] = {'units': units}
1536
1597
        status = {
1537
 
            'machines': {'0': {'agent-state': 'started'}},
1538
 
            'services': services,
 
1598
            'machines': {'0': dict(machine_started)},
 
1599
            'applications': applications,
1539
1600
        }
1540
1601
        with patch_status(client, status):
1541
1602
            self.assertEqual(deploy_iter.next(),
1542
1603
                             {'test_id': 'deploy-many', 'result': True})
1543
1604
 
1544
1605
        self.assertEqual(deploy_iter.next(),
1545
 
                         {'test_id': 'remove-machine-many-lxc'})
 
1606
                         {'test_id': 'remove-machine-many-container'})
1546
1607
        with patch_status(client, status):
1547
1608
            with patch('subprocess.check_call') as mock_cc:
1548
1609
                self.assertEqual(
1549
1610
                    deploy_iter.next(),
1550
 
                    {'test_id': 'remove-machine-many-lxc'})
 
1611
                    {'test_id': 'remove-machine-many-container'})
1551
1612
        calls = self.predict_remove_machine_calls(deploy_many)
1552
1613
        for num, args in enumerate(calls):
1553
1614
            assert_juju_call(self, mock_cc, client, args, num)
1554
1615
        statuses = [
1555
 
            {'machines': {'100': {'agent-state': 'started'}}, 'services': {}},
1556
 
            {'machines': {}, 'services': {}},
 
1616
            {'machines': {'100': dict(machine_started)}, 'applications': {}},
 
1617
            {'machines': {}, 'applications': {}},
1557
1618
        ]
1558
1619
        with patch_status(client, *statuses) as status_mock:
1559
1620
            self.assertEqual(
1560
1621
                deploy_iter.next(),
1561
 
                {'test_id': 'remove-machine-many-lxc', 'result': True})
 
1622
                {'test_id': 'remove-machine-many-container', 'result': True})
1562
1623
        self.assertEqual(2, status_mock.call_count)
1563
1624
        self.assertEqual(deploy_iter.next(), {
1564
1625
            'test_id': 'remove-machine-many-instance'})
1568
1629
                {'test_id': 'remove-machine-many-instance'})
1569
1630
        for num in range(deploy_many.host_count):
1570
1631
            assert_juju_call(self, mock_cc, client, (
1571
 
                'juju', '--show-log', 'remove-machine', '-m', 'steve',
 
1632
                'juju', '--show-log', 'remove-machine', '-m', 'steve:steve',
1572
1633
                str(num + 1)), num)
1573
1634
 
1574
1635
        statuses = [
1575
 
            {'machines': {'1': {'agent-state': 'started'}}, 'services': {}},
1576
 
            {'machines': {}, 'services': {}},
 
1636
            {'machines': {'1': dict(machine_started)}, 'applications': {}},
 
1637
            {'machines': {}, 'applications': {}},
1577
1638
        ]
1578
1639
        with patch_status(client, *statuses) as status_mock:
1579
1640
            self.assertEqual(
1584
1645
    def test_iter_step_failure(self):
1585
1646
        deploy_many = DeployManyAttempt()
1586
1647
        client = FakeEnvJujuClient()
 
1648
        client.env.config['default-series'] = 'angsty'
1587
1649
        deploy_iter = iter_steps_validate_info(self, deploy_many, client)
1588
1650
        self.assertEqual(deploy_iter.next(), {'test_id': 'add-machine-many'})
1589
1651
        status = {
1590
1652
            'machines': {'0': {'agent-state': 'started'}},
1591
 
            'services': {},
 
1653
            'applications': {},
1592
1654
        }
1593
1655
        with patch_status(client, status):
1594
1656
            with patch('subprocess.check_call') as mock_cc:
1596
1658
                                 {'test_id': 'add-machine-many'})
1597
1659
        for index in range(deploy_many.host_count):
1598
1660
            assert_juju_call(self, mock_cc, client, (
1599
 
                'juju', '--show-log', 'add-machine', '-m', 'steve'), index)
 
1661
                'juju', '--show-log', 'add-machine',
 
1662
                '-m', 'steve:steve'), index)
1600
1663
 
1601
1664
        status = {
1602
1665
            'machines': dict((str(x), {'agent-state': 'started'})
1603
1666
                             for x in range(deploy_many.host_count + 1)),
1604
 
            'services': {},
 
1667
            'applications': {},
1605
1668
        }
1606
1669
        with patch_status(client, status):
1607
1670
                self.assertEqual(
1623
1686
            'machines': {
1624
1687
                '0': {'agent-state': 'pending'},
1625
1688
                },
1626
 
            'services': {},
 
1689
            'applications': {},
1627
1690
        }
1628
1691
        with patch_status(client, status):
1629
1692
            with self.assertRaisesRegexp(
1634
1697
    def test_iter_step_add_machine_failure(self):
1635
1698
        deploy_many = DeployManyAttempt()
1636
1699
        client = FakeEnvJujuClient()
 
1700
        client.env.config['default-series'] = 'angsty'
1637
1701
        deploy_iter = iter_steps_validate_info(self, deploy_many, client)
1638
1702
        self.assertEqual(deploy_iter.next(), {'test_id': 'add-machine-many'})
1639
1703
        status = {
1640
1704
            'machines': {'0': {'agent-state': 'started'}},
1641
 
            'services': {},
 
1705
            'applications': {},
1642
1706
        }
1643
1707
        with patch_status(client, status) as gs_mock:
1644
1708
            with patch('subprocess.check_call') as mock_cc:
1646
1710
                                 {'test_id': 'add-machine-many'})
1647
1711
        for index in range(deploy_many.host_count):
1648
1712
            assert_juju_call(self, mock_cc, client, (
1649
 
                'juju', '--show-log', 'add-machine', '-m', 'steve'), index)
 
1713
                'juju', '--show-log', 'add-machine',
 
1714
                '-m', 'steve:steve'), index)
1650
1715
        gs_mock.assert_called_once_with()
1651
1716
 
1652
1717
        status = {
1653
1718
            'machines': dict((str(x), {'agent-state': 'pending'})
1654
1719
                             for x in range(deploy_many.host_count + 1)),
1655
 
            'services': {},
 
1720
            'applications': {},
1656
1721
        }
1657
1722
        with patch_status(client, status) as gs_mock:
1658
1723
            self.assertEqual(deploy_iter.next(),
1664
1729
                             deploy_iter.next())
1665
1730
        for x in range(deploy_many.host_count):
1666
1731
            assert_juju_call(self, mock_cc, client, (
1667
 
                'juju', '--show-log', 'remove-machine', '-m', 'steve',
 
1732
                'juju', '--show-log', 'remove-machine', '-m', 'steve:steve',
1668
1733
                '--force', str((x + 1))), x * 2)
1669
1734
            assert_juju_call(self, mock_cc, client, (
1670
 
                'juju', '--show-log', 'add-machine', '-m', 'steve'), x * 2 + 1)
 
1735
                'juju', '--show-log', 'add-machine',
 
1736
                '-m', 'steve:steve'), x * 2 + 1)
1671
1737
 
1672
1738
        status = {
1673
1739
            'machines': dict((str(x), {'agent-state': 'started'})
1674
1740
                             for x in range(deploy_many.host_count + 1)),
1675
 
            'services': {},
 
1741
            'applications': {},
1676
1742
        }
1677
1743
        with patch_status(client, status) as gs_mock:
1678
1744
            self.assertEqual({'test_id': 'ensure-machines', 'result': True},
1680
1746
        self.assertEqual({'test_id': 'deploy-many'}, deploy_iter.next())
1681
1747
        with patch('subprocess.check_call') as mock_cc:
1682
1748
            self.assertEqual({'test_id': 'deploy-many'}, deploy_iter.next())
1683
 
        calls = self.predict_add_machine_calls(deploy_many)
 
1749
        calls = self.predict_add_machine_calls(deploy_many, LXD_MACHINE)
1684
1750
        for num, args in enumerate(calls):
1685
1751
            assert_juju_call(self, mock_cc, client, args, num)
1686
1752
 
 
1753
    def get_wait_until_removed_timeout(self, container_type):
 
1754
        deploy_many = DeployManyAttempt()
 
1755
        client = fake_juju_client()
 
1756
        client.bootstrap()
 
1757
        deploy_iter = iter_steps_validate_info(self, deploy_many, client)
 
1758
        with patch('industrial_test.wait_until_removed') as wur_mock:
 
1759
            with patch.object(client, 'preferred_container',
 
1760
                              return_value=container_type):
 
1761
                list(deploy_iter)
 
1762
        return wur_mock.mock_calls[0][2]['timeout']
 
1763
 
 
1764
    def test_wait_until_removed_timeout_lxd(self):
 
1765
        self.assertEqual(900, self.get_wait_until_removed_timeout(LXD_MACHINE))
 
1766
 
 
1767
    def test_wait_until_removed_timeout_lxc(self):
 
1768
        self.assertEqual(30, self.get_wait_until_removed_timeout(LXC_MACHINE))
 
1769
 
 
1770
    def test_wait_until_removed_timeout_azure(self):
 
1771
        deploy_many = DeployManyAttempt(host_count=4, container_count=0)
 
1772
        client = fake_juju_client()
 
1773
        client.env.config['type'] = 'azure'
 
1774
        client.env.config['location'] = 'us-west-1'
 
1775
        client.bootstrap()
 
1776
        deploy_iter = iter_steps_validate_info(self, deploy_many, client)
 
1777
        with patch('industrial_test.wait_until_removed') as wur_mock:
 
1778
            list(deploy_iter)
 
1779
        remove_timeout = wur_mock.mock_calls[3][2]['timeout']
 
1780
        self.assertEqual(2400, remove_timeout)
 
1781
 
 
1782
    def test_wait_until_removed_timeout_not_azure(self):
 
1783
        deploy_many = DeployManyAttempt(host_count=4, container_count=0)
 
1784
        client = fake_juju_client()
 
1785
        client.env.config['type'] = 'aws'
 
1786
        client.bootstrap()
 
1787
        deploy_iter = iter_steps_validate_info(self, deploy_many, client)
 
1788
        with patch('industrial_test.wait_until_removed') as wur_mock:
 
1789
            list(deploy_iter)
 
1790
        remove_timeout = wur_mock.mock_calls[3][2]['timeout']
 
1791
        self.assertEqual(300, remove_timeout)
 
1792
 
1687
1793
 
1688
1794
class TestBackupRestoreAttempt(JujuPyTestCase):
1689
1795
 
1695
1801
    def test_iter_steps(self):
1696
1802
        br_attempt = BackupRestoreAttempt()
1697
1803
        client = FakeEnvJujuClient()
1698
 
        client.env = get_aws_env()
 
1804
        aws_env = get_aws_env()
 
1805
        client.env.environment = aws_env.environment
 
1806
        client.env.config = aws_env.config
 
1807
        client.env.juju_home = aws_env.juju_home
 
1808
        controller_client = client.get_controller_client()
1699
1809
        environ = dict(os.environ)
1700
1810
        environ.update(get_euca_env(client.env.config))
1701
1811
 
1702
1812
        def check_output(*args, **kwargs):
1703
 
            if args == (('juju', '--show-log', 'create-backup', '-m',
1704
 
                         'baz',),):
1705
 
                return 'juju-backup-24.tgz'
 
1813
            if args == ((
 
1814
                    'juju', '--show-log', 'create-backup', '-m',
 
1815
                    'steve:{}'.format(controller_client.env.environment),),):
 
1816
                return FakePopen('juju-backup-24.tgz', '', 0)
1706
1817
            self.assertEqual([], args)
1707
1818
        initial_status = {
1708
1819
            'machines': {'0': {
1712
1823
        }
1713
1824
        iterator = iter_steps_validate_info(self, br_attempt, client)
1714
1825
        self.assertEqual(iterator.next(), {'test_id': 'back-up-restore'})
1715
 
        with patch_status(client, initial_status) as gs_mock:
1716
 
            with patch('subprocess.check_output',
 
1826
        with patch_status(controller_client, initial_status) as gs_mock:
 
1827
            with patch('subprocess.Popen',
1717
1828
                       side_effect=check_output) as co_mock:
1718
1829
                with patch('subprocess.check_call') as cc_mock:
1719
 
                    with patch('sys.stdout'):
1720
 
                        self.assertEqual(
1721
 
                            iterator.next(),
1722
 
                            {'test_id': 'back-up-restore'})
1723
 
        assert_juju_call(self, co_mock, client, (
1724
 
            'juju', '--show-log', 'create-backup', '-m', 'baz'), 0)
 
1830
                    with patch.object(client, 'get_controller_client',
 
1831
                                      return_value=controller_client,
 
1832
                                      autospec=True):
 
1833
                        with patch('sys.stdout'):
 
1834
                            self.assertEqual(
 
1835
                                iterator.next(),
 
1836
                                {'test_id': 'back-up-restore'})
 
1837
        assert_juju_call(
 
1838
            self,
 
1839
            co_mock,
 
1840
            client,
 
1841
            ('juju', '--show-log', 'create-backup',
 
1842
             '-m', 'steve:{}'.format(controller_client.env.environment)),
 
1843
            0)
1725
1844
        self.assertEqual(
1726
1845
            cc_mock.mock_calls[0],
1727
1846
            call(['euca-terminate-instances', 'asdf'], env=environ))
1730
1849
                self.assertEqual(iterator.next(),
1731
1850
                                 {'test_id': 'back-up-restore'})
1732
1851
        pn_mock.assert_called_with('Closed.')
1733
 
        with patch('subprocess.Popen') as po_mock:
 
1852
        with patch.object(controller_client, 'restore_backup') as rb_mock:
1734
1853
            self.assertEqual(iterator.next(), {'test_id': 'back-up-restore'})
1735
 
        assert_juju_call(
1736
 
            self, po_mock, client, (
1737
 
                'juju', '--show-log', 'restore', '-m', 'baz',
1738
 
                os.path.abspath('juju-backup-24.tgz')))
1739
 
        po_mock.return_value.wait.return_value = 0
 
1854
        rb_mock.assert_called_once_with(
 
1855
            os.path.abspath('juju-backup-24.tgz'))
1740
1856
        with patch('os.unlink') as ul_mock:
1741
1857
            self.assertEqual(iterator.next(),
1742
1858
                             {'test_id': 'back-up-restore'})
1745
1861
            'machines': {
1746
1862
                '0': {'agent-state': 'started'},
1747
1863
                },
1748
 
            'services': {},
 
1864
            'applications': {},
1749
1865
        }
1750
 
        with patch_status(client, final_status) as gs_mock:
 
1866
        with patch_status(controller_client, final_status) as gs_mock:
1751
1867
            self.assertEqual(iterator.next(),
1752
1868
                             {'test_id': 'back-up-restore', 'result': True})
1753
1869
        gs_mock.assert_called_once_with()
1754
1870
 
 
1871
    def test_iter_steps_azure(self):
 
1872
        test_id = {'test_id': 'back-up-restore'}
 
1873
        br_attempt = BackupRestoreAttempt()
 
1874
        azure_env = SimpleEnvironment('steve', get_azure_config())
 
1875
        client = FakeEnvJujuClient()
 
1876
        client.env.environment = azure_env.environment
 
1877
        client.env.config = azure_env.config
 
1878
        controller_client = client.get_controller_client()
 
1879
        # First yield.
 
1880
        iterator = iter_steps_validate_info(self, br_attempt, client)
 
1881
        self.assertEqual(iterator.next(), test_id)
 
1882
        # Second yield.
 
1883
        initial_status = {
 
1884
            'machines': {'0': {
 
1885
                'instance-id': 'not-id',
 
1886
                'dns-name': '128.100.100.128',
 
1887
                }}
 
1888
        }
 
1889
        # The azure-provider does does not provide sane ids, so the instance-id
 
1890
        # is used to search for the actual azure instance.
 
1891
        with patch_status(controller_client, initial_status):
 
1892
            with patch.object(client, 'get_controller_client', autospec=True,
 
1893
                              return_value=controller_client):
 
1894
                with patch.object(controller_client, 'backup', autospec=True,
 
1895
                                  return_value='juju-backup.tgz') as b_mock:
 
1896
                    with patch('industrial_test.convert_to_azure_ids',
 
1897
                               autospec=True, return_value=['id']) as ca_mock:
 
1898
                        with patch('industrial_test.terminate_instances',
 
1899
                                   autospec=True):
 
1900
                            self.assertEqual(iterator.next(), test_id)
 
1901
        b_mock.assert_called_once_with()
 
1902
        ca_mock.assert_called_once_with(controller_client, ['not-id'])
 
1903
 
1755
1904
 
1756
1905
class TestPrepareUpgradeJujuAttempt(JujuPyTestCase):
1757
1906
 
1770
1919
            PrepareUpgradeJujuAttempt.factory([], None)
1771
1920
 
1772
1921
    def test_get_bootstrap_client(self):
1773
 
        client = FakeJujuClient(full_path='c', debug=True)
 
1922
        client = fake_juju_client(full_path='c', debug=True)
1774
1923
        puj_attempt = PrepareUpgradeJujuAttempt.factory(['a', 'b', 'c'], None)
1775
 
        bootstrap_client = puj_attempt.get_bootstrap_client(client)
 
1924
 
 
1925
        def by_version(path):
 
1926
            return fake_juju_client(client.env, path, client.debug)
 
1927
 
 
1928
        with patch.object(client, 'clone_path_cls', by_version):
 
1929
            bootstrap_client = puj_attempt.get_bootstrap_client(client)
 
1930
 
1776
1931
        self.assertIsNot(bootstrap_client, client)
1777
1932
        self.assertIs(client.debug, bootstrap_client.debug)
1778
1933
        self.assertIs(client.env, bootstrap_client.env)
1779
1934
        self.assertEqual('b', bootstrap_client.full_path)
1780
1935
 
1781
1936
    def test_iter_steps(self):
1782
 
        future_client = FakeEnvJujuClient()
1783
 
        future_client.full_path = '/future/juju'
1784
 
        present_client = FakeEnvJujuClient()
1785
 
        present_client.full_path = '/present/juju'
 
1937
        future_client = FakeEnvJujuClient(full_path='/future/juju')
 
1938
        present_client = FakeEnvJujuClient(full_path='/present/juju')
1786
1939
        puj_attempt = PrepareUpgradeJujuAttempt(
1787
1940
            {future_client.full_path: present_client.full_path})
1788
1941
        puj_iterator = iter_steps_validate_info(self, puj_attempt,
1789
1942
                                                future_client)
1790
1943
        with patch('subprocess.check_output', return_value='2.0-alpha3-a-b'):
1791
 
            self.assertEqual({'test_id': 'prepare-upgrade-juju'},
1792
 
                             puj_iterator.next())
 
1944
            with patch('industrial_test.client_from_config',
 
1945
                       return_value=future_client):
 
1946
                self.assertEqual({'test_id': 'prepare-upgrade-juju'},
 
1947
                                 puj_iterator.next())
1793
1948
        with observable_temp_file() as config_file:
1794
1949
            with patch('subprocess.Popen') as po_mock:
1795
1950
                self.assertEqual({'test_id': 'prepare-upgrade-juju'},
1796
1951
                                 puj_iterator.next())
1797
 
            assert_juju_call(self, po_mock, present_client, (
 
1952
            assert_juju_call(self, po_mock, future_client, (
1798
1953
                'juju', '--show-log', 'bootstrap', '--constraints', 'mem=2G',
1799
1954
                'steve', 'fake/regionx', '--config', config_file.name,
1800
1955
                '--agent-version', '2.0-alpha3'))
1803
1958
                             {'test_id': 'prepare-upgrade-juju'})
1804
1959
        b_status = {
1805
1960
            'machines': {'0': {'agent-state': 'started'}},
1806
 
            'services': {},
 
1961
            'applications': {},
1807
1962
        }
1808
1963
        with patch_status(None, b_status):
1809
1964
            self.assertEqual(
1812
1967
 
1813
1968
    def test_iter_steps_no_previous_client(self):
1814
1969
        uj_attempt = PrepareUpgradeJujuAttempt({})
1815
 
        client = FakeEnvJujuClient()
1816
 
        client.full_path = '/present/juju'
 
1970
        client = FakeEnvJujuClient(full_path='/present/juju')
1817
1971
        uj_iterator = uj_attempt.iter_steps(client)
1818
1972
        with self.assertRaises(CannotUpgradeToClient) as exc_context:
1819
1973
            uj_iterator.next()
1823
1977
class TestUpgradeJujuAttempt(JujuPyTestCase):
1824
1978
 
1825
1979
    def test_iter_steps(self):
1826
 
        future_client = FakeEnvJujuClient()
1827
 
        future_client.full_path = '/future/juju'
 
1980
        future_client = FakeEnvJujuClient(full_path='/future/juju')
1828
1981
        uj_attempt = UpgradeJujuAttempt()
1829
1982
        uj_iterator = iter_steps_validate_info(self, uj_attempt, future_client)
1830
1983
        self.assertEqual(uj_iterator.next(), {'test_id': 'upgrade-juju'})
1831
1984
        with patch('subprocess.check_call') as cc_mock:
1832
1985
            self.assertEqual({'test_id': 'upgrade-juju'}, uj_iterator.next())
1833
 
        assert_juju_call(self, cc_mock, future_client, (
1834
 
            'juju', '--show-log', 'upgrade-juju', '-m', 'steve', '--version',
1835
 
            future_client.get_matching_agent_version()))
 
1986
        assert_juju_call(
 
1987
            self,
 
1988
            cc_mock,
 
1989
            future_client,
 
1990
            ('juju', '--show-log', 'upgrade-juju',
 
1991
             '-m', 'steve:steve', '--version',
 
1992
             future_client.get_matching_agent_version()))
1836
1993
        version_status = {
1837
1994
            'machines': {'0': {
1838
1995
                'agent-version': future_client.get_matching_agent_version()}},
1839
 
            'services': {},
 
1996
            'applications': {},
1840
1997
        }
1841
1998
        with patch_status(None, version_status):
1842
1999
            self.assertEqual({'test_id': 'upgrade-juju', 'result': True},
1852
2009
        self.assertEqual(0o755, mode & 0o777)
1853
2010
 
1854
2011
    def test_iter_steps(self):
1855
 
        client = FakeEnvJujuClient()
1856
 
        client.version = '2.0.0'
1857
 
        client.full_path = '/future/juju'
 
2012
        client = FakeEnvJujuClient(version='2.0.0', full_path='/future/juju')
 
2013
        self._iter_steps(client)
 
2014
 
 
2015
    def test_iter_steps_juju_1x(self):
 
2016
        client = FakeEnvJujuClient1X(version='1.25.0',
 
2017
                                     full_path='/future/juju')
 
2018
        self._iter_steps(client)
 
2019
 
 
2020
    def _iter_steps(self, client):
 
2021
        self.assertEqual(client.full_path, '/future/juju')
1858
2022
        uc_attempt = UpgradeCharmAttempt()
1859
2023
        uc_iterator = iter_steps_validate_info(self, uc_attempt, client)
1860
2024
        self.assertEqual(uc_iterator.next(),
1871
2035
        self.assertEqual(metadata['name'], 'mycharm')
1872
2036
        self.assertIn('summary', metadata)
1873
2037
        self.assertIn('description', metadata)
1874
 
        assert_juju_call(self, cc_mock, client, (
1875
 
            'juju', '--show-log', 'deploy', '-m', 'steve',
1876
 
            os.path.join(temp_repository, 'trusty', 'mycharm')))
 
2038
        self.assertEqual(['trusty'], metadata['series'])
 
2039
        if client.version.startswith('1.'):
 
2040
            charm_path = os.path.join('local:trusty', 'mycharm')
 
2041
            assert_juju_call(self, cc_mock, client, (
 
2042
                'juju', '--show-log', 'deploy', '-e', 'steve', charm_path,
 
2043
                '--repository', temp_repository))
 
2044
            option = '-e'
 
2045
        else:
 
2046
            charm_path = os.path.join(temp_repository, 'trusty', 'mycharm')
 
2047
            assert_juju_call(self, cc_mock, client, (
 
2048
                'juju', '--show-log', 'deploy',
 
2049
                '-m', 'steve:steve', charm_path))
 
2050
            option = '-m'
 
2051
        self.assertNotIn('min-juju-version', metadata)
1877
2052
        status = {
1878
2053
            'machines': {'0': {'agent-state': 'started'}},
1879
 
            'services': {},
 
2054
            'applications': {},
1880
2055
        }
1881
2056
        with patch_status(client, status):
1882
2057
            self.assertEqual(uc_iterator.next(),
1901
2076
        self.assertEqual(uc_iterator.next(), {'test_id': 'upgrade-charm'})
1902
2077
        with patch('subprocess.check_call') as cc_mock:
1903
2078
            self.assertEqual(uc_iterator.next(), {'test_id': 'upgrade-charm'})
1904
 
        assert_juju_call(self, cc_mock, client, (
1905
 
            'juju', '--show-log', 'upgrade-charm', '-m', 'steve',
1906
 
            'mycharm', '--repository', temp_repository))
 
2079
        if client.version.startswith('1.'):
 
2080
            assert_juju_call(self, cc_mock, client, (
 
2081
                'juju', '--show-log', 'upgrade-charm', option, 'steve',
 
2082
                'mycharm', '--repository', temp_repository))
 
2083
        else:
 
2084
            assert_juju_call(self, cc_mock, client, (
 
2085
                'juju', '--show-log', 'upgrade-charm', option, 'steve:steve',
 
2086
                'mycharm', '--path', os.path.join(temp_repository, 'trusty',
 
2087
                                                  'mycharm')))
1907
2088
        status = {
1908
2089
            'machines': {'0': {'agent-state': 'started'}},
1909
 
            'services': {'mycharm': {'units': {'mycharm/0': {
 
2090
            'applications': {'mycharm': {'units': {'mycharm/0': {
1910
2091
                'open-ports': ['42/tcp', '34/tcp'],
1911
2092
                }}}},
1912
2093
        }
2068
2249
        factory = AttemptSuiteFactory([], bootstrap_attempt=fake_bootstrap)
2069
2250
        attempt_suite = AttemptSuite(factory, None, 'asdf', None)
2070
2251
        with self.iter_steps_cxt(attempt_suite) as (mock_ibms, mock_bm):
2071
 
            client = FakeJujuClient()
 
2252
            client = fake_juju_client()
2072
2253
            attempt_suite.iter_steps(client)
2073
2254
        mock_bm.assert_called_once_with(
2074
2255
            'name', client, client, agent_stream=None, agent_url=None,
2075
 
            bootstrap_host=None, jes_enabled=False, keep_env=True,
2076
 
            log_dir='qux-1', machines=[], permanent=False,
 
2256
            bootstrap_host=None, jes_enabled=True, keep_env=True,
 
2257
            log_dir='qux-1', machines=[], permanent=True,
2077
2258
            region=None, series=None)
2078
2259
 
2079
2260
    def test_iter_steps_agent_stream(self):
2081
2262
        factory = AttemptSuiteFactory([], bootstrap_attempt=fake_bootstrap)
2082
2263
        attempt_suite = AttemptSuite(factory, None, 'asdf', 'bar-stream')
2083
2264
        with self.iter_steps_cxt(attempt_suite) as (mock_ibms, mock_bm):
2084
 
            client = FakeJujuClient()
 
2265
            client = fake_juju_client()
2085
2266
            iterator = attempt_suite.iter_steps(client)
2086
2267
        self.assertEqual(iterator, mock_ibms.return_value)
2087
2268
        mock_bm.assert_called_once_with(
2088
2269
            'name', client, client, agent_stream='bar-stream', agent_url=None,
2089
 
            bootstrap_host=None, jes_enabled=False, keep_env=True,
2090
 
            log_dir='qux-1', machines=[], permanent=False,
 
2270
            bootstrap_host=None, jes_enabled=True, keep_env=True,
 
2271
            log_dir='qux-1', machines=[], permanent=True,
2091
2272
            region=None, series=None)
2092
2273
 
2093
2274
    def test__iter_bs_manager_steps(self):
2097
2278
        factory = AttemptSuiteFactory([fake_1, fake_2],
2098
2279
                                      bootstrap_attempt=fake_bootstrap)
2099
2280
        attempt_suite = AttemptSuite(factory, None, None, None)
2100
 
        client = FakeJujuClient()
 
2281
        client = fake_juju_client()
2101
2282
        bs_manager = FakeBootstrapManager(client)
2102
2283
        steps = list(attempt_suite._iter_bs_manager_steps(
2103
2284
            bs_manager, client, fake_bootstrap(), True))
2115
2296
            {'test_id': 'substrate-clean'},
2116
2297
            {'test_id': 'substrate-clean', 'result': True},
2117
2298
            ], steps)
 
2299
 
 
2300
    def test__iter_bs_manager_steps_teardown_in_runtime(self):
 
2301
        fake_bootstrap = FakeAttemptClass('fake-bootstrap', '1', '2')
 
2302
        fake_1 = FakeAttemptClass('fake-1', Exception('fake exception'), '2')
 
2303
        factory = AttemptSuiteFactory([fake_1],
 
2304
                                      bootstrap_attempt=fake_bootstrap)
 
2305
        attempt_suite = AttemptSuite(factory, None, None, None)
 
2306
        client = fake_juju_client()
 
2307
        bs_manager = FakeBootstrapManager(client, keep_env=True)
 
2308
        with self.assertRaisesRegexp(Exception, 'fake exception'):
 
2309
            list(attempt_suite._iter_bs_manager_steps(
 
2310
                bs_manager, client, fake_bootstrap(), True))
 
2311
        self.assertIs(True, bs_manager.torn_down)