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

« back to all changes in this revision

Viewing changes to test_assess_recovery.py

  • Committer: Aaron Bentley
  • Date: 2015-09-02 17:46:47 UTC
  • mto: This revision was merged to the branch mainline in revision 1082.
  • Revision ID: aaron.bentley@canonical.com-20150902174647-06vmnsooo6yzd46t
Stop supplying env to subprocess calls.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from argparse import Namespace
2
 
from contextlib import contextmanager
3
 
from mock import (
4
 
    call,
5
 
    patch,
6
 
    Mock,
7
 
)
 
1
from mock import patch
 
2
from unittest import TestCase
8
3
 
9
4
from assess_recovery import (
10
 
    assess_recovery,
11
 
    delete_controller_members,
12
5
    main,
13
 
    make_client_from_args,
14
6
    parse_args,
15
7
)
16
8
from jujupy import (
17
9
    EnvJujuClient,
18
 
    JujuData,
19
 
    Machine,
20
 
    _temp_env as temp_env,
21
 
)
22
 
from tests import (
23
 
    FakeHomeTestCase,
24
 
    TestCase,
25
 
)
26
 
from tests.test_jujupy import FakeJujuClient
 
10
    SimpleEnvironment,
 
11
)
 
12
from utility import (
 
13
    setup_test_logging,
 
14
)
27
15
 
28
16
 
29
17
class TestParseArgs(TestCase):
33
21
        self.assertEqual(args.juju_path, 'foo')
34
22
        self.assertEqual(args.env_name, 'bar')
35
23
        self.assertEqual(args.logs, 'baz')
36
 
        self.assertEqual(args.charm_series, '')
 
24
        self.assertEqual(args.charm_prefix, '')
37
25
        self.assertEqual(args.strategy, 'backup')
38
26
        self.assertEqual(args.debug, False)
39
 
        self.assertIs(args.agent_stream, None)
40
 
        self.assertIs(args.series, None)
41
27
 
42
28
    def test_parse_args_ha(self):
43
29
        args = parse_args(['foo', 'bar', 'baz', '--ha'])
51
37
        args = parse_args(['foo', 'bar', 'baz', '--ha', '--backup'])
52
38
        self.assertEqual(args.strategy, 'backup')
53
39
 
54
 
    def test_parse_args_charm_series(self):
55
 
        args = parse_args(['foo', 'bar', 'baz', '--charm-series', 'qux'])
56
 
        self.assertEqual(args.charm_series, 'qux')
 
40
    def test_parse_args_charm_prefix(self):
 
41
        args = parse_args(['foo', 'bar', 'baz', '--charm-prefix', 'qux'])
 
42
        self.assertEqual(args.charm_prefix, 'qux')
57
43
 
58
44
    def test_parse_args_debug(self):
59
45
        args = parse_args(['foo', 'bar', 'baz', '--debug'])
65
51
        args = parse_args(['foo', 'bar', 'baz', 'qux'])
66
52
        self.assertEqual(args.temp_env_name, 'qux')
67
53
 
68
 
    def test_parse_args_agent_stream(self):
69
 
        args = parse_args(['foo', 'bar', 'baz', '--agent-stream', 'qux'])
70
 
        self.assertEqual(args.agent_stream, 'qux')
71
 
 
72
 
    def test_parse_args_series(self):
73
 
        args = parse_args(['foo', 'bar', 'baz', '--series', 'qux'])
74
 
        self.assertEqual(args.series, 'qux')
75
 
 
76
 
 
77
 
class TestMakeClientFromArgs(TestCase):
78
 
 
79
 
    def test_make_client_from_args(self):
80
 
        with temp_env({'environments': {'foo': {}}}):
81
 
            with patch.object(EnvJujuClient, 'get_version', return_value=''):
82
 
                with patch.object(JujuData, 'load_yaml'):
83
 
                    client = make_client_from_args(
84
 
                        Namespace(env_name='foo', juju_path='bar',
85
 
                                  temp_env_name='temp-foo', debug=False,
86
 
                                  agent_stream=None, series=None))
87
 
        self.assertEqual(client.env.config, {'name': 'temp-foo'})
88
 
        self.assertEqual(client.env.environment, 'temp-foo')
89
 
 
90
54
 
91
55
def make_mocked_client(name, status_error=None):
92
 
    client = EnvJujuClient(JujuData(
93
 
        name, {'type': 'paas', 'region': 'region-foo'}), '1.23', 'path')
 
56
    client = EnvJujuClient(SimpleEnvironment(
 
57
        name, {'type': 'paas'}), '1.23', 'path')
94
58
    patch.object(client, 'wait_for_ha', autospec=True).start()
95
59
    patch.object(
96
60
        client, 'get_status', autospec=True, side_effect=status_error).start()
97
 
    patch.object(client, 'kill_controller', autospec=True).start()
98
 
    patch.object(client, 'is_jes_enabled', autospec=True,
99
 
                 return_value=True).start()
100
 
    patch.object(client, 'get_admin_client', autospec=True,
101
 
                 return_value=client).start()
102
 
    patch.object(client, 'iter_model_clients', autospec=True,
103
 
                 return_value=[client]).start()
 
61
    patch.object(client, 'destroy_environment', autospec=True).start()
104
62
    return client
105
63
 
106
64
 
107
 
class TestAssessRecovery(TestCase):
108
 
 
109
 
    @contextmanager
110
 
    def assess_recovery_cxt(self, client):
111
 
        client.bootstrap()
112
 
 
113
 
        def terminate(env, instance_ids):
114
 
            for instance_id in instance_ids:
115
 
                admin_model = client._backing_state.controller.admin_model
116
 
                admin_model.remove_state_server(instance_id)
117
 
 
118
 
        with patch('assess_recovery.terminate_instances',
119
 
                   side_effect=terminate):
120
 
            with patch('deploy_stack.wait_for_port', autospec=True):
121
 
                yield
122
 
 
123
 
    def test_backup(self):
124
 
        client = FakeJujuClient()
125
 
        bs_manager = Mock(client=client, known_hosts={})
126
 
        with self.assess_recovery_cxt(client):
127
 
            assess_recovery(bs_manager, 'backup', 'trusty')
128
 
 
129
 
    def test_ha(self):
130
 
        client = FakeJujuClient()
131
 
        bs_manager = Mock(client=client, known_hosts={})
132
 
        with self.assess_recovery_cxt(client):
133
 
            assess_recovery(bs_manager, 'ha', 'trusty')
134
 
 
135
 
    def test_ha_backup(self):
136
 
        client = FakeJujuClient()
137
 
        bs_manager = Mock(client=client, known_hosts={})
138
 
        with self.assess_recovery_cxt(client):
139
 
            assess_recovery(bs_manager, 'ha-backup', 'trusty')
140
 
 
141
 
    def test_admin_model_backup(self):
142
 
        client = FakeJujuClient(jes_enabled=True)
143
 
        bs_manager = Mock(client=client, known_hosts={})
144
 
        with self.assess_recovery_cxt(client):
145
 
            assess_recovery(bs_manager, 'backup', 'trusty')
146
 
 
147
 
    def test_admin_model_ha(self):
148
 
        client = FakeJujuClient(jes_enabled=True)
149
 
        bs_manager = Mock(client=client, known_hosts={})
150
 
        with self.assess_recovery_cxt(client):
151
 
            assess_recovery(bs_manager, 'ha', 'trusty')
152
 
 
153
 
    def test_admin_model_ha_backup(self):
154
 
        client = FakeJujuClient(jes_enabled=True)
155
 
        bs_manager = Mock(client=client, known_hosts={})
156
 
        with self.assess_recovery_cxt(client):
157
 
            assess_recovery(bs_manager, 'ha-backup', 'trusty')
158
 
 
159
 
 
160
 
@patch('assess_recovery.BootstrapManager.dump_all_logs', autospec=True)
 
65
@patch('assess_recovery.dump_env_logs', autospec=True)
161
66
@patch('assess_recovery.parse_new_state_server_from_error', autospec=True,
162
67
       return_value='new_host')
163
 
@patch('assess_recovery.delete_controller_members', autospec=True,
164
 
       return_value=['0'])
165
 
@patch('assess_recovery.deploy_stack', autospec=True)
166
 
@patch('deploy_stack.get_machine_dns_name', autospec=True,
 
68
@patch('assess_recovery.wait_for_state_server_to_shutdown', autospec=True)
 
69
@patch('assess_recovery.delete_instance', autospec=True)
 
70
@patch('assess_recovery.deploy_stack', autospec=True, return_value='i_id')
 
71
@patch('assess_recovery.get_machine_dns_name', autospec=True,
167
72
       return_value='host')
168
73
@patch('subprocess.check_output', autospec=True)
169
74
@patch('subprocess.check_call', autospec=True)
170
 
@patch('sys.stderr', autospec=True)
171
 
class TestMain(FakeHomeTestCase):
 
75
@patch('sys.stdout', autospec=True)
 
76
class TestMain(TestCase):
 
77
 
 
78
    def setUp(self):
 
79
        setup_test_logging(self)
172
80
 
173
81
    def test_ha(self, so_mock, cc_mock, co_mock,
174
 
                dns_mock, ds_mock, dcm_mock, ns_mock, dal_mock):
 
82
                dns_mock, ds_mock, di_mock, ws_mock, ns_mock, dl_mock):
175
83
        client = make_mocked_client('foo')
176
 
        with patch('assess_recovery.make_client_from_args', autospec=True,
 
84
        with patch('assess_recovery.make_client', autospec=True,
177
85
                   return_value=client) as mc_mock:
178
86
            main(['./', 'foo', 'log_dir',
179
 
                  '--ha', '--charm-series', 'charm-series'])
180
 
        mc_mock.assert_called_once_with(Namespace(
181
 
            agent_stream=None, charm_series='charm-series', debug=False,
182
 
            env_name='foo', juju_path='./', logs='log_dir', strategy='ha',
183
 
            temp_env_name=None, series=None))
 
87
                  '--ha', '--charm-prefix', 'prefix'])
 
88
        mc_mock.assert_called_once_with('./', False, 'foo', None)
184
89
        client.wait_for_ha.assert_called_once_with()
185
90
        client.get_status.assert_called_once_with(600)
186
 
        self.assertEqual(2, client.kill_controller.call_count)
187
 
        dns_mock.assert_called_once_with(client.get_admin_client.return_value,
188
 
                                         '0')
189
 
        ds_mock.assert_called_once_with(client, 'charm-series')
190
 
        dcm_mock.assert_called_once_with(client, leader_only=True)
191
 
        self.assertTrue(dal_mock.called)
 
91
        client.destroy_environment.assert_called_once_with()
 
92
        dns_mock.assert_called_once_with(client, 0)
 
93
        ds_mock.assert_called_once_with(client, 'prefix')
 
94
        di_mock.assert_called_once_with(client, 'i_id')
 
95
        ws_mock.assert_called_once_with('host', client, 'i_id')
 
96
        dl_mock.assert_called_once_with(client, None, 'log_dir')
192
97
        self.assertEqual(0, ns_mock.call_count)
193
98
 
194
99
    def test_ha_error(self, so_mock, cc_mock, co_mock,
195
 
                      dns_mock, ds_mock, dcm_mock, ns_mock, dal_mock):
 
100
                      dns_mock, ds_mock, di_mock, ws_mock, ns_mock, dl_mock):
196
101
        error = Exception()
197
102
        client = make_mocked_client('foo', status_error=error)
198
 
        with patch('assess_recovery.make_client_from_args', autospec=True,
 
103
        with patch('assess_recovery.make_client', autospec=True,
199
104
                   return_value=client) as mc_mock:
200
105
            with self.assertRaises(SystemExit):
201
 
                    main(['./', 'foo', 'log_dir',
202
 
                          '--ha', '--charm-series', 'prefix'])
203
 
        mc_mock.assert_called_once_with(Namespace(
204
 
            agent_stream=None, charm_series='prefix', debug=False,
205
 
            env_name='foo', juju_path='./', logs='log_dir', strategy='ha',
206
 
            temp_env_name=None, series=None))
 
106
                main(['./', 'foo', 'log_dir',
 
107
                      '--ha', '--charm-prefix', 'prefix'])
 
108
        mc_mock.assert_called_once_with('./', False, 'foo', None)
207
109
        client.wait_for_ha.assert_called_once_with()
208
110
        client.get_status.assert_called_once_with(600)
209
 
        self.assertEqual(2, client.kill_controller.call_count)
210
 
        dns_mock.assert_called_once_with(
211
 
            client.get_admin_client.return_value, '0')
 
111
        client.destroy_environment.assert_called_once_with()
 
112
        dns_mock.assert_called_once_with(client, 0)
212
113
        ds_mock.assert_called_once_with(client, 'prefix')
213
 
        dcm_mock.assert_called_once_with(client, leader_only=True)
 
114
        di_mock.assert_called_once_with(client, 'i_id')
 
115
        ws_mock.assert_called_once_with('host', client, 'i_id')
214
116
        ns_mock.assert_called_once_with(error)
215
 
        self.assertTrue(dal_mock.called)
 
117
        dl_mock.assert_called_once_with(client, 'new_host', 'log_dir')
216
118
 
217
119
    def test_destroy_on_boot_error(self, so_mock, cc_mock, co_mock,
218
 
                                   dns_mock, ds_mock, dcm_mock, ns_mock,
219
 
                                   dl_mock):
 
120
                                   dns_mock, ds_mock, di_mock, ws_mock,
 
121
                                   ns_mock, dl_mock):
220
122
        client = make_mocked_client('foo')
221
123
        with patch('assess_recovery.make_client', autospec=True,
222
124
                   return_value=client):
223
125
            with patch.object(client, 'bootstrap', side_effect=Exception):
224
126
                with self.assertRaises(SystemExit):
225
127
                    main(['./', 'foo', 'log_dir',
226
 
                          '--ha', '--charm-series', 'prefix'])
227
 
        self.assertEqual(2, client.kill_controller.call_count)
228
 
 
229
 
 
230
 
@patch('assess_recovery.wait_for_state_server_to_shutdown', autospec=True)
231
 
@patch('assess_recovery.terminate_instances', autospec=True)
232
 
@patch('sys.stderr', autospec=True)
233
 
class TestDeleteControllerMembers(FakeHomeTestCase):
234
 
 
235
 
    def test_delete_controller_members(self, so_mock, ti_mock, wsss_mock):
236
 
        client = make_mocked_client('foo')
237
 
        members = [
238
 
            Machine('3', {
239
 
                'dns-name': '10.0.0.3',
240
 
                'instance-id': 'juju-dddd-machine-3',
241
 
                'controller-member-status': 'has-vote'}),
242
 
            Machine('0', {
243
 
                'dns-name': '10.0.0.0',
244
 
                'instance-id': 'juju-aaaa-machine-0',
245
 
                'controller-member-status': 'has-vote'}),
246
 
            Machine('2', {
247
 
                'dns-name': '10.0.0.2',
248
 
                'instance-id': 'juju-cccc-machine-2',
249
 
                'controller-member-status': 'has-vote'}),
250
 
        ]
251
 
        with patch.object(client, 'get_controller_members',
252
 
                          autospec=True, return_value=members) as gcm_mock:
253
 
            deleted = delete_controller_members(client)
254
 
        self.assertEqual(['2', '0', '3'], deleted)
255
 
        gcm_mock.assert_called_once_with()
256
 
        # terminate_instance was call in the reverse order of members.
257
 
        self.assertEqual(
258
 
            [call(client.env, ['juju-cccc-machine-2']),
259
 
             call(client.env, ['juju-aaaa-machine-0']),
260
 
             call(client.env, ['juju-dddd-machine-3'])],
261
 
            ti_mock.mock_calls)
262
 
        self.assertEqual(
263
 
            [call('10.0.0.2', client, 'juju-cccc-machine-2'),
264
 
             call('10.0.0.0', client, 'juju-aaaa-machine-0'),
265
 
             call('10.0.0.3', client, 'juju-dddd-machine-3')],
266
 
            wsss_mock.mock_calls)
267
 
 
268
 
    def test_delete_controller_members_leader_only(
269
 
            self, so_mock, ti_mock, wsss_mock):
270
 
        client = make_mocked_client('foo')
271
 
        leader = Machine('3', {
272
 
            'dns-name': '10.0.0.3',
273
 
            'instance-id': 'juju-dddd-machine-3',
274
 
            'controller-member-status': 'has-vote'})
275
 
        with patch.object(client, 'get_controller_leader',
276
 
                          autospec=True, return_value=leader) as gcl_mock:
277
 
            deleted = delete_controller_members(client, leader_only=True)
278
 
        self.assertEqual(['3'], deleted)
279
 
        gcl_mock.assert_called_once_with()
280
 
        ti_mock.assert_called_once_with(client.env, ['juju-dddd-machine-3'])
281
 
        wsss_mock.assert_called_once_with(
282
 
            '10.0.0.3', client, 'juju-dddd-machine-3')
 
128
                          '--ha', '--charm-prefix', 'prefix'])
 
129
        client.destroy_environment.assert_called_once_with()