65
51
args = parse_args(['foo', 'bar', 'baz', 'qux'])
66
52
self.assertEqual(args.temp_env_name, 'qux')
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')
72
def test_parse_args_series(self):
73
args = parse_args(['foo', 'bar', 'baz', '--series', 'qux'])
74
self.assertEqual(args.series, 'qux')
77
class TestMakeClientFromArgs(TestCase):
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')
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()
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()
107
class TestAssessRecovery(TestCase):
110
def assess_recovery_cxt(self, client):
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)
118
with patch('assess_recovery.terminate_instances',
119
side_effect=terminate):
120
with patch('deploy_stack.wait_for_port', autospec=True):
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')
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')
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')
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')
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')
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')
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,
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):
79
setup_test_logging(self)
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,
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)
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')
217
119
def test_destroy_on_boot_error(self, so_mock, cc_mock, co_mock,
218
dns_mock, ds_mock, dcm_mock, ns_mock,
120
dns_mock, ds_mock, di_mock, ws_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)
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):
235
def test_delete_controller_members(self, so_mock, ti_mock, wsss_mock):
236
client = make_mocked_client('foo')
239
'dns-name': '10.0.0.3',
240
'instance-id': 'juju-dddd-machine-3',
241
'controller-member-status': 'has-vote'}),
243
'dns-name': '10.0.0.0',
244
'instance-id': 'juju-aaaa-machine-0',
245
'controller-member-status': 'has-vote'}),
247
'dns-name': '10.0.0.2',
248
'instance-id': 'juju-cccc-machine-2',
249
'controller-member-status': 'has-vote'}),
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.
258
[call(client.env, ['juju-cccc-machine-2']),
259
call(client.env, ['juju-aaaa-machine-0']),
260
call(client.env, ['juju-dddd-machine-3'])],
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)
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()