31
30
Returns: string of testdata.
33
32
base_dir = os.path.dirname(os.path.abspath(__file__))
34
with open(os.path.join(base_dir, 'testdata', filename), 'r') as test_file:
33
with open(os.path.join(base_dir, "testdata", filename), "r") as test_file:
35
34
return test_file.read()
38
with mock.patch('mojo.juju.status.major_version', new=2):
37
with mock.patch("mojo.juju.status.major_version", new=2):
39
38
self.status = mojo.juju.status.Juju2Status()
40
self.status._raw_status = self._testdata_from_file('juju2-idle.yaml')
39
self.status._raw_status = self._testdata_from_file("juju2-idle.yaml")
42
41
def test_machine_ids_list(self):
43
42
"""Test getting all machine IDs"""
44
self.assertEqual(self.status.machine_ids_list(), ['2', '3'])
43
self.assertEqual(self.status.machine_ids_list(), ["2", "3"])
46
@mock.patch('mojo.juju.status.Juju2Status.status')
45
@mock.patch("mojo.juju.status.Juju2Status.status")
47
46
def test_machine_and_container_ids_list(self, status_mock):
48
47
"""Test getting all machine and container IDs"""
49
48
# First test on a status that doesn't have containers
50
with mock.patch('mojo.juju.status.major_version', new=2):
49
with mock.patch("mojo.juju.status.major_version", new=2):
51
50
self.status = mojo.juju.status.Juju2Status()
52
status_mock.return_value = self._testdata_from_file('juju2-idle.yaml')
53
self.assertEqual(self.status.machine_ids_list(), ['2', '3'])
54
self.assertEqual(self.status.machine_and_container_ids_list(), ['2', '3'])
51
status_mock.return_value = self._testdata_from_file("juju2-idle.yaml")
52
self.assertEqual(self.status.machine_ids_list(), ["2", "3"])
53
self.assertEqual(self.status.machine_and_container_ids_list(), ["2", "3"])
55
54
# And now test on a status that does have containers
56
with mock.patch('mojo.juju.status.major_version', new=2):
55
with mock.patch("mojo.juju.status.major_version", new=2):
57
56
self.status = mojo.juju.status.Juju2Status()
58
status_mock.return_value = self._testdata_from_file('juju2-openstack-with-containers.yaml')
59
self.assertEqual(self.status.machine_ids_list(), ['0', '1', '2', '3', '4', '5', '6', '7', '8'])
60
self.assertEqual(self.status.machine_and_container_ids_list(),
61
['0', '0/lxd/0', '0/lxd/1', '0/lxd/2', '0/lxd/3', '0/lxd/4', '0/lxd/5', '0/lxd/6', '0/lxd/7',
62
'1', '1/lxd/0', '1/lxd/1', '1/lxd/2', '1/lxd/3', '1/lxd/4', '1/lxd/5', '1/lxd/6', '1/lxd/7',
63
'2', '3', '4', '5', '6', '7', '8'])
57
status_mock.return_value = self._testdata_from_file("juju2-openstack-with-containers.yaml")
58
self.assertEqual(self.status.machine_ids_list(), ["0", "1", "2", "3", "4", "5", "6", "7", "8"])
60
self.status.machine_and_container_ids_list(),
65
90
def test_applications_ips(self):
66
91
""""Test getting services_list"""
67
self.assertEqual(self.status.application_ips('apache2'), ['fd28:938b:9119:802d:216:3eff:fe96:aa2d'])
68
self.assertEqual(self.status.application_ips('prometheus'), ['10.47.34.203'])
92
self.assertEqual(self.status.application_ips("apache2"), ["fd28:938b:9119:802d:216:3eff:fe96:aa2d"])
93
self.assertEqual(self.status.application_ips("prometheus"), ["10.47.34.203"])
70
95
def test_applications_list(self):
71
96
""""Test getting services_list"""
72
self.assertEqual(self.status.applications_list(), ['apache2', 'prometheus'])
73
self.assertEqual(self.status.applications_list(exclude_subordinates=False), ['apache2', 'prometheus', 'telegraf'])
97
self.assertEqual(self.status.applications_list(), ["apache2", "prometheus"])
99
self.status.applications_list(exclude_subordinates=False), ["apache2", "prometheus", "telegraf"]
75
102
def test_application_machine_numbers(self):
76
self.assertEqual(self.status.application_machine_numbers('apache2'), ['3'])
103
self.assertEqual(self.status.application_machine_numbers("apache2"), ["3"])
78
105
def test_application_units(self):
79
self.assertEqual(self.status.application_units('apache2'), ['apache2/1'])
106
self.assertEqual(self.status.application_units("apache2"), ["apache2/1"])
81
@mock.patch('logging.info')
82
@mock.patch('mojo.juju.status.wait')
83
@mock.patch('mojo.juju.status.Juju2Status.status')
84
@mock.patch('subprocess.check_output')
85
@mock.patch('time.sleep')
108
@mock.patch("logging.info")
109
@mock.patch("mojo.juju.status.wait")
110
@mock.patch("mojo.juju.status.Juju2Status.status")
111
@mock.patch("subprocess.check_output")
112
@mock.patch("time.sleep")
86
113
def test_check_and_wait_juju_wait(self, _sleep, _check_output, status_mock, _wait, _logging_info):
87
_wait.return_value = ''
114
_wait.return_value = ""
88
115
# Confirm we don't raise a JujuStatusError
89
with mock.patch('mojo.juju.status.major_version', new=2):
116
with mock.patch("mojo.juju.status.major_version", new=2):
90
117
self.status = mojo.juju.status.Juju2Status()
91
status_mock.return_value = self._testdata_from_file('juju2-idle.yaml')
118
status_mock.return_value = self._testdata_from_file("juju2-idle.yaml")
92
119
# First of all call with default (wait_for_steady=False) and confirm
93
120
# wait not called (because juju status is okay).
94
121
self.status.check_and_wait()
101
128
expected_logging_args_list = [
102
129
"Waiting for environment to reach steady state",
103
130
"Environment has reached steady state",
105
132
self.assertEquals(len(_logging_info.call_args_list), len(expected_logging_args_list))
106
133
for i, call in enumerate(_logging_info.call_args_list):
107
134
self.assertEquals(call, mock.call(expected_logging_args_list[i]))
109
@mock.patch('mojo.juju.status.Juju2Status.status')
110
@mock.patch('subprocess.check_output')
111
@mock.patch('time.sleep')
136
@mock.patch("mojo.juju.status.Juju2Status.status")
137
@mock.patch("subprocess.check_output")
138
@mock.patch("time.sleep")
112
139
def test_check_and_wait(self, _sleep, _check_output, status_mock):
113
140
# Wait for steady state timeouts
114
with mock.patch('mojo.juju.status.major_version', new=2):
115
self.status = mojo.juju.status.Juju2Status()
116
status_mock.return_value = self._testdata_from_file('juju2-busy.yaml')
117
with self.assertRaises(mojo.juju.JujuWaitException):
118
self.status.check_and_wait(wait_for_steady=True, timeout=1)
119
with mock.patch('mojo.juju.status.major_version', new=2):
120
self.status = mojo.juju.status.Juju2Status()
121
status_mock.return_value = self._testdata_from_file('juju2-busy2.yaml')
122
with self.assertRaises(mojo.juju.JujuWaitException):
123
self.status.check_and_wait(wait_for_steady=True, timeout=1)
124
with mock.patch('mojo.juju.status.major_version', new=2):
125
self.status = mojo.juju.status.Juju2Status()
126
status_mock.return_value = self._testdata_from_file('juju2-subordinate-busy.yaml')
127
with self.assertRaises(mojo.juju.JujuWaitException):
128
self.status.check_and_wait(wait_for_steady=True, timeout=1)
129
status_mock.return_value = self._testdata_from_file('juju2-subordinate-busy2.yaml')
141
with mock.patch("mojo.juju.status.major_version", new=2):
142
self.status = mojo.juju.status.Juju2Status()
143
status_mock.return_value = self._testdata_from_file("juju2-busy.yaml")
144
with self.assertRaises(mojo.juju.JujuWaitException):
145
self.status.check_and_wait(wait_for_steady=True, timeout=1)
146
with mock.patch("mojo.juju.status.major_version", new=2):
147
self.status = mojo.juju.status.Juju2Status()
148
status_mock.return_value = self._testdata_from_file("juju2-busy2.yaml")
149
with self.assertRaises(mojo.juju.JujuWaitException):
150
self.status.check_and_wait(wait_for_steady=True, timeout=1)
151
with mock.patch("mojo.juju.status.major_version", new=2):
152
self.status = mojo.juju.status.Juju2Status()
153
status_mock.return_value = self._testdata_from_file("juju2-subordinate-busy.yaml")
154
with self.assertRaises(mojo.juju.JujuWaitException):
155
self.status.check_and_wait(wait_for_steady=True, timeout=1)
156
status_mock.return_value = self._testdata_from_file("juju2-subordinate-busy2.yaml")
130
157
with self.assertRaises(mojo.juju.JujuWaitException):
131
158
self.status.check_and_wait(wait_for_steady=True, timeout=1)
134
with mock.patch('mojo.juju.status.major_version', new=2):
161
with mock.patch("mojo.juju.status.major_version", new=2):
135
162
self.status = mojo.juju.status.Juju2Status()
136
status_mock.return_value = self._testdata_from_file('juju2-fail.yaml')
163
status_mock.return_value = self._testdata_from_file("juju2-fail.yaml")
137
164
with self.assertRaises(mojo.juju.JujuStatusError):
138
165
self.status.check_and_wait()
139
with mock.patch('mojo.juju.status.major_version', new=2):
166
with mock.patch("mojo.juju.status.major_version", new=2):
140
167
self.status = mojo.juju.status.Juju2Status()
141
status_mock.return_value = self._testdata_from_file('juju2-subordinate-fail.yaml')
168
status_mock.return_value = self._testdata_from_file("juju2-subordinate-fail.yaml")
142
169
with self.assertRaises(mojo.juju.JujuStatusError):
143
170
self.status.check_and_wait()
145
172
# And now confirm we don't raise an error on an environment in error
146
173
# state if we pass the right additional_error_states
147
with mock.patch('mojo.juju.status.major_version', new=2):
148
self.status = mojo.juju.status.Juju2Status(additional_ready_states=['maintenance', 'executing'])
149
with mock.patch('mojo.juju.status.major_version', new=2):
150
self.status = mojo.juju.status.Juju2Status()
151
self.status._raw_status = self._testdata_from_file('juju2-busy.yaml')
152
with mock.patch('mojo.juju.status.major_version', new=2):
153
self.status = mojo.juju.status.Juju2Status()
154
status_mock.return_value = self._testdata_from_file('juju2-busy.yaml')
155
with mock.patch('mojo.juju.status.wait', new=lambda max_wait: None):
174
with mock.patch("mojo.juju.status.major_version", new=2):
175
self.status = mojo.juju.status.Juju2Status(additional_ready_states=["maintenance", "executing"])
176
with mock.patch("mojo.juju.status.major_version", new=2):
177
self.status = mojo.juju.status.Juju2Status()
178
self.status._raw_status = self._testdata_from_file("juju2-busy.yaml")
179
with mock.patch("mojo.juju.status.major_version", new=2):
180
self.status = mojo.juju.status.Juju2Status()
181
status_mock.return_value = self._testdata_from_file("juju2-busy.yaml")
182
with mock.patch("mojo.juju.status.wait", new=lambda max_wait: None):
156
183
self.status.check_and_wait(wait_for_steady=True, timeout=1)
158
@mock.patch('subprocess.check_output')
185
@mock.patch("subprocess.check_output")
159
186
def test_controller_version(self, mock_check_output):
160
with mock.patch('mojo.juju.status.major_version', new=2):
187
with mock.patch("mojo.juju.status.major_version", new=2):
161
188
self.status = mojo.juju.status.Juju2Status()
162
mock_check_output.return_value = self._testdata_from_file('juju2-controllers.yaml')
163
self.assertEqual('2.0-rc1', self.status.controller_version())
189
mock_check_output.return_value = self._testdata_from_file("juju2-controllers.yaml")
190
self.assertEqual("2.0-rc1", self.status.controller_version())
165
192
def test_machine_instance_id(self):
166
self.assertEqual(self.status.machine_instance_id('2'), 'juju-fdef5d-2')
193
self.assertEqual(self.status.machine_instance_id("2"), "juju-fdef5d-2")
168
195
def test_model_version(self):
169
self.assertEqual(self.status.model_version(), '2.0-beta18')
196
self.assertEqual(self.status.model_version(), "2.0-beta18")
171
198
def test_status(self):
172
199
"""Test the status function"""
173
200
self.assertEqual(self.status.status(), self.status._raw_status)
175
with mock.patch('subprocess.check_output') as mock_check_output:
202
with mock.patch("subprocess.check_output") as mock_check_output:
176
203
# First check with no environment set
177
204
no_env_status = mojo.juju.status.Juju2Status(command_timeout=None)
178
205
no_env_status.status()
179
mock_check_output.assert_called_with(
180
[JUJU_PATH, 'status', '--format=yaml'], universal_newlines=True)
206
mock_check_output.assert_called_with([JUJU_PATH, "status", "--format=yaml"], universal_newlines=True)
181
207
# Second test with an environment set
182
208
env_status = mojo.juju.status.Juju2Status(environment="test-env")
183
209
env_status.status()
184
210
mock_check_output.assert_called_with(
185
['/usr/bin/timeout', '--kill-after', '5', '600',
186
JUJU_PATH, 'status', '--format=yaml', '-m', 'test-env'], universal_newlines=True)
222
universal_newlines=True,
188
with mock.patch('subprocess.check_output') as mock_check_output:
225
with mock.patch("subprocess.check_output") as mock_check_output:
189
226
# Check that if we're calling status() where _raw_status is
190
227
# set, it doesn't query juju status
191
228
self.assertTrue(self.status._raw_status)
196
233
self.status.status(force_update=True)
197
234
mock_check_output.assert_called_with(
198
['/usr/bin/timeout', '--kill-after', '5', '600',
199
JUJU_PATH, 'status', '--format=yaml'], universal_newlines=True)
235
["/usr/bin/timeout", "--kill-after", "5", "600", JUJU_PATH, "status", "--format=yaml"],
236
universal_newlines=True,
201
@mock.patch('mojo.juju.status.check_output_with_timeout')
239
@mock.patch("mojo.juju.status.check_output_with_timeout")
202
240
def test_yaml_status(self, _check_output_with_timeout):
203
241
"""Test the yaml_status function"""
204
_check_output_with_timeout.return_value = self._testdata_from_file('juju2-idle.yaml')
242
_check_output_with_timeout.return_value = self._testdata_from_file("juju2-idle.yaml")
205
243
self.maxDiff = None
207
'model': {'name': 'mojo-test', 'controller': 'laptop', 'cloud': 'lxd',
208
'region': 'localhost', 'version': '2.0-beta18'},
209
'machines': {'2': {'juju-status': {'current': 'started', 'since': '16 Sep 2016 14:56:46Z',
210
'version': '2.0-beta18'},
211
'dns-name': '10.47.34.203',
212
'instance-id': 'juju-fdef5d-2',
213
'machine-status': {'current': 'running', 'message': 'Running',
214
'since': '16 Sep 2016 14:55:58Z'},
216
'hardware': 'arch=amd64 cpu-cores=0 mem=0M'},
217
'3': {'juju-status': {'current': 'started', 'since': '16 Sep 2016 14:57:11Z',
218
'version': '2.0-beta18'},
219
'dns-name': 'fd28:938b:9119:802d:216:3eff:fe96:aa2d',
220
'instance-id': 'juju-fdef5d-3',
221
'machine-status': {'current': 'running', 'message': 'Running',
222
'since': '16 Sep 2016 14:56:19Z'},
224
'hardware': 'arch=amd64 cpu-cores=0 mem=0M'}},
225
'applications': {'apache2': {'charm': 'cs:trusty/apache2-20', 'series': 'xenial',
226
'os': 'ubuntu', 'charm-origin': 'jujucharms',
227
'charm-name': 'apache2', 'charm-rev': 20, 'exposed': False,
228
'application-status': {'current': 'unknown',
229
'since': '16 Sep 2016 14:57:53Z'},
230
'relations': {'juju-info': ['telegraf']},
231
'units': {'apache2/1': {'workload-status': {'current': 'unknown',
232
'since': '16 Sep 2016 14:57:53Z'},
233
'juju-status': {'current': 'idle',
234
'since': '16 Sep 2016 15:20:34Z',
235
'version': '2.0-beta18'},
237
'public-address': 'fd28:938b:9119:802d:216:3eff:fe96:aa2d',
238
'subordinates': {'telegraf/0': {
241
'message': 'Monitoring apache2/1',
242
'since': '16 Sep 2016 15:23:55Z'},
245
'since': '16 Sep 2016 15:23:55Z',
246
'version': '2.0-beta18'},
247
'upgrading-from': 'cs:~telegraf-charmers/telegraf-6',
248
'open-ports': ['9103/tcp'],
249
'public-address': 'fd28:938b:9119:802d:216:3eff:fe96:aa2d'
251
'prometheus': {'charm': 'cs:~prometheus-charmers/prometheus-2', 'series': 'xenial',
252
'os': 'ubuntu', 'charm-origin': 'jujucharms',
253
'charm-name': 'prometheus', 'charm-rev': 2, 'exposed': False,
254
'application-status': {'current': 'active', 'message': 'Ready',
255
'since': '16 Sep 2016 14:59:53Z'},
256
'relations': {'juju-info': ['telegraf']},
257
'units': {'prometheus/1': {'workload-status': {'current': 'active',
259
'since': '16 Sep 2016 14:59:53Z'},
260
'juju-status': {'current': 'idle',
261
'since': '16 Sep 2016 15:20:39Z',
262
'version': '2.0-beta18'},
264
'open-ports': ['9090/tcp'],
265
'public-address': '10.47.34.203',
266
'subordinates': {'telegraf/1': {
269
'message': 'Monitoring prometheus/1',
270
'since': '16 Sep 2016 15:23:55Z'},
271
'juju-status': {'current': 'idle',
272
'since': '16 Sep 2016 15:23:55Z',
273
'version': '2.0-beta18'},
274
'upgrading-from': 'cs:~telegraf-charmers/telegraf-6',
275
'open-ports': ['9103/tcp'],
276
'public-address': '10.47.34.203'}}}}},
277
'telegraf': {'charm': 'cs:~telegraf-charmers/telegraf-6',
278
'series': 'xenial', 'os': 'ubuntu', 'charm-origin': 'jujucharms',
279
'charm-name': 'telegraf', 'charm-rev': 6, 'exposed': False,
280
'application-status': {'current': 'active',
281
'message': 'Monitoring apache2/1',
282
'since': '16 Sep 2016 15:23:55Z'},
283
'relations': {'juju-info': ['apache2', 'prometheus']},
284
'subordinate-to': ['apache2', 'prometheus']}}}
247
"controller": "laptop",
249
"region": "localhost",
250
"version": "2.0-beta18",
254
"juju-status": {"current": "started", "since": "16 Sep 2016 14:56:46Z", "version": "2.0-beta18"},
255
"dns-name": "10.47.34.203",
256
"instance-id": "juju-fdef5d-2",
257
"machine-status": {"current": "running", "message": "Running", "since": "16 Sep 2016 14:55:58Z"},
259
"hardware": "arch=amd64 cpu-cores=0 mem=0M",
262
"juju-status": {"current": "started", "since": "16 Sep 2016 14:57:11Z", "version": "2.0-beta18"},
263
"dns-name": "fd28:938b:9119:802d:216:3eff:fe96:aa2d",
264
"instance-id": "juju-fdef5d-3",
265
"machine-status": {"current": "running", "message": "Running", "since": "16 Sep 2016 14:56:19Z"},
267
"hardware": "arch=amd64 cpu-cores=0 mem=0M",
272
"charm": "cs:trusty/apache2-20",
275
"charm-origin": "jujucharms",
276
"charm-name": "apache2",
279
"application-status": {"current": "unknown", "since": "16 Sep 2016 14:57:53Z"},
280
"relations": {"juju-info": ["telegraf"]},
283
"workload-status": {"current": "unknown", "since": "16 Sep 2016 14:57:53Z"},
286
"since": "16 Sep 2016 15:20:34Z",
287
"version": "2.0-beta18",
290
"public-address": "fd28:938b:9119:802d:216:3eff:fe96:aa2d",
295
"message": "Monitoring apache2/1",
296
"since": "16 Sep 2016 15:23:55Z",
300
"since": "16 Sep 2016 15:23:55Z",
301
"version": "2.0-beta18",
303
"upgrading-from": "cs:~telegraf-charmers/telegraf-6",
304
"open-ports": ["9103/tcp"],
305
"public-address": "fd28:938b:9119:802d:216:3eff:fe96:aa2d",
312
"charm": "cs:~prometheus-charmers/prometheus-2",
315
"charm-origin": "jujucharms",
316
"charm-name": "prometheus",
319
"application-status": {"current": "active", "message": "Ready", "since": "16 Sep 2016 14:59:53Z"},
320
"relations": {"juju-info": ["telegraf"]},
326
"since": "16 Sep 2016 14:59:53Z",
330
"since": "16 Sep 2016 15:20:39Z",
331
"version": "2.0-beta18",
334
"open-ports": ["9090/tcp"],
335
"public-address": "10.47.34.203",
340
"message": "Monitoring prometheus/1",
341
"since": "16 Sep 2016 15:23:55Z",
345
"since": "16 Sep 2016 15:23:55Z",
346
"version": "2.0-beta18",
348
"upgrading-from": "cs:~telegraf-charmers/telegraf-6",
349
"open-ports": ["9103/tcp"],
350
"public-address": "10.47.34.203",
357
"charm": "cs:~telegraf-charmers/telegraf-6",
360
"charm-origin": "jujucharms",
361
"charm-name": "telegraf",
364
"application-status": {
366
"message": "Monitoring apache2/1",
367
"since": "16 Sep 2016 15:23:55Z",
369
"relations": {"juju-info": ["apache2", "prometheus"]},
370
"subordinate-to": ["apache2", "prometheus"],
285
374
self.assertEqual(self.status.yaml_status(force_update=True), expected)
300
389
to use the KILL (9) signal, since this signal cannot be caught, in which
301
390
case the exit status is 128+9 rather than 124."""
303
@mock.patch('subprocess.check_output')
392
@mock.patch("subprocess.check_output")
304
393
def test_command_succeeds(self, check_output_mock):
305
394
"""command succeeds within timeout -> returns output, no exception"""
307
command = ['/bin/echo', 'blorp']
308
check_output_mock.return_value = 'blorp'
396
command = ["/bin/echo", "blorp"]
397
check_output_mock.return_value = "blorp"
310
399
self.assertEqual(
311
400
mojo.juju.status.check_output_with_timeout(
314
timeout_exception=Juju2CheckOutputWithTimeoutTestException),
401
command, command_timeout=5, timeout_exception=Juju2CheckOutputWithTimeoutTestException
317
@mock.patch('subprocess.check_output')
406
@mock.patch("subprocess.check_output")
318
407
def test_command_fails_within_timeout(self, check_output_mock):
319
408
"""command fails within timeout -> CalledProcessError thrown"""
321
410
import subprocess
323
command = ['/bin/echo', 'blorp']
412
command = ["/bin/echo", "blorp"]
324
413
check_output_mock.side_effect = subprocess.CalledProcessError(returncode=1, cmd=command)
326
415
with self.assertRaises(subprocess.CalledProcessError) as arcm:
327
416
mojo.juju.status.check_output_with_timeout(
330
timeout_exception=Juju2CheckOutputWithTimeoutTestException)
417
command, command_timeout=5, timeout_exception=Juju2CheckOutputWithTimeoutTestException
332
420
self.assertEqual(arcm.exception.returncode, 1)
334
@mock.patch('subprocess.check_output')
422
@mock.patch("subprocess.check_output")
335
423
def test_command_times_out_and_is_terminated(self, check_output_mock):
336
424
"""command times out, SIGTERM exits -> CalledProcessError.returncode==124 -> timeout_exception('...')"""
338
426
import subprocess
340
command = ['/bin/echo', 'blorp']
428
command = ["/bin/echo", "blorp"]
341
429
check_output_mock.side_effect = subprocess.CalledProcessError(returncode=124, cmd=command)
343
431
with self.assertRaises(Juju2CheckOutputWithTimeoutTestException) as arcm:
344
432
mojo.juju.status.check_output_with_timeout(
347
timeout_exception=Juju2CheckOutputWithTimeoutTestException)
350
str(arcm.exception).endswith(' timed out after 5 seconds'))
352
@mock.patch('subprocess.check_output')
433
command, command_timeout=5, timeout_exception=Juju2CheckOutputWithTimeoutTestException
436
self.assertTrue(str(arcm.exception).endswith(" timed out after 5 seconds"))
438
@mock.patch("subprocess.check_output")
353
439
def test_command_times_out_and_is_killed(self, check_output_mock):
354
"""command times out, SIGKILL exits -> CalledProcessError.returncode==128+9 -> timeout_exception('... (killed)')"""
442
SIGKILL exits -> CalledProcessError.returncode==128+9 -> timeout_exception('... (killed)')"""
356
444
import subprocess
358
command = ['/bin/echo', 'blorp']
359
check_output_mock.side_effect = subprocess.CalledProcessError(returncode=128+9, cmd=command)
446
command = ["/bin/echo", "blorp"]
447
check_output_mock.side_effect = subprocess.CalledProcessError(returncode=128 + 9, cmd=command)
361
449
with self.assertRaises(Juju2CheckOutputWithTimeoutTestException) as arcm:
362
450
mojo.juju.status.check_output_with_timeout(
365
timeout_exception=Juju2CheckOutputWithTimeoutTestException)
451
command, command_timeout=5, timeout_exception=Juju2CheckOutputWithTimeoutTestException
368
str(arcm.exception).endswith(' timed out after 5 seconds (killed)'))
454
self.assertTrue(str(arcm.exception).endswith(" timed out after 5 seconds (killed)"))
371
457
class Juju2ChecksTest(TestCase):
373
self.testdata = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testdata')
374
self.status_path = os.path.join(self.testdata, 'juju2-idle2.yaml')
459
self.testdata = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testdata")
460
self.status_path = os.path.join(self.testdata, "juju2-idle2.yaml")
376
@mock.patch('sys.stdout', new_callable=StringIO)
462
@mock.patch("sys.stdout", new_callable=StringIO)
377
463
def test_Errors_success(self, mock_stdout):
378
sys.argv = ['self', '-f', self.status_path, 'errors']
464
sys.argv = ["self", "-f", self.status_path, "errors"]
379
465
return_code = check()
380
466
self.assertEqual(0, return_code)
381
self.assertEqual(mock_stdout.getvalue(), 'OK: No Juju status errors found.\n')
467
self.assertEqual(mock_stdout.getvalue(), "OK: No Juju status errors found.\n")
383
@mock.patch('sys.stdout', new_callable=StringIO)
469
@mock.patch("sys.stdout", new_callable=StringIO)
384
470
def test_Errors_failure(self, mock_stdout):
385
error_status = os.path.join(self.testdata, 'juju2-fail.yaml')
386
sys.argv = ['self', '-f', error_status, 'errors']
471
error_status = os.path.join(self.testdata, "juju2-fail.yaml")
472
sys.argv = ["self", "-f", error_status, "errors"]
387
473
return_code = check()
388
474
self.assertEqual(2, return_code)
389
self.assertEqual(mock_stdout.getvalue(), 'CRITICAL: apache2 is in status error\n')
475
self.assertEqual(mock_stdout.getvalue(), "CRITICAL: apache2 is in status error\n")
391
@mock.patch('sys.stdout', new_callable=StringIO)
477
@mock.patch("sys.stdout", new_callable=StringIO)
392
478
def test_Unused_success(self, mock_stdout):
393
sys.argv = ['self', '-f', self.status_path, 'unused_machines']
479
sys.argv = ["self", "-f", self.status_path, "unused_machines"]
394
480
return_code = check()
395
481
self.assertEqual(0, return_code)
396
self.assertEqual(mock_stdout.getvalue(), 'OK: All machines are being used.\n')
482
self.assertEqual(mock_stdout.getvalue(), "OK: All machines are being used.\n")
398
@mock.patch('sys.stdout', new_callable=StringIO)
484
@mock.patch("sys.stdout", new_callable=StringIO)
399
485
def test_Unused_failure(self, mock_stdout):
400
unused_status = os.path.join(self.testdata, 'juju2-unused-machines.yaml')
401
sys.argv = ['self', '-f', unused_status, 'unused_machines']
486
unused_status = os.path.join(self.testdata, "juju2-unused-machines.yaml")
487
sys.argv = ["self", "-f", unused_status, "unused_machines"]
402
488
return_code = check()
403
489
self.assertEqual(2, return_code)
404
490
self.assertEqual(mock_stdout.getvalue(), "CRITICAL: Unused machines found: ['3']\n")
406
@mock.patch('sys.stdout', new_callable=StringIO)
492
@mock.patch("sys.stdout", new_callable=StringIO)
407
493
def test_UpgradeAvailable_success(self, mock_stdout):
408
sys.argv = ['self', '-f', self.status_path, 'upgrade_available', '--check_version', '2.0-rc1']
494
sys.argv = ["self", "-f", self.status_path, "upgrade_available", "--check_version", "2.0-rc1"]
409
495
return_code = check()
410
496
self.assertEqual(0, return_code)
411
self.assertEqual(mock_stdout.getvalue(), 'OK: The Juju controller and model are running the same version (2.0-rc1).\n')
498
mock_stdout.getvalue(), "OK: The Juju controller and model are running the same version (2.0-rc1).\n"
413
@mock.patch('sys.stdout', new_callable=StringIO)
501
@mock.patch("sys.stdout", new_callable=StringIO)
414
502
def test_UpgradeAvailable_failure(self, mock_stdout):
415
sys.argv = ['self', '-f', self.status_path, 'upgrade_available', '--check_version', '2.0-rc2']
503
sys.argv = ["self", "-f", self.status_path, "upgrade_available", "--check_version", "2.0-rc2"]
416
504
return_code = check()
417
505
self.assertEqual(2, return_code)
418
self.assertEqual(mock_stdout.getvalue(), 'CRITICAL: controller version 2.0-rc2 != model version 2.0-rc1\n')
506
self.assertEqual(mock_stdout.getvalue(), "CRITICAL: controller version 2.0-rc2 != model version 2.0-rc1\n")
421
509
class Juju2ParseStatusTest(TestCase):
423
self.testdata = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testdata')
424
self.status_path = os.path.join(self.testdata, 'juju2-idle3.yaml')
511
self.testdata = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testdata")
512
self.status_path = os.path.join(self.testdata, "juju2-idle3.yaml")
426
@mock.patch('sys.stdout', new_callable=StringIO)
514
@mock.patch("sys.stdout", new_callable=StringIO)
427
515
def test_GetIPs_all(self, mock_stdout):
428
sys.argv = ['self', '-f', self.status_path, 'get_ips', 'all']
429
ips = list(sorted('10.25.2.111\n10.242.242.242\n10.25.2.109\n10.25.2.112\n10.25.2.110\n'.strip().split("\n")))
516
sys.argv = ["self", "-f", self.status_path, "get_ips", "all"]
517
ips = list(sorted("10.25.2.111\n10.242.242.242\n10.25.2.109\n10.25.2.112\n10.25.2.110\n".strip().split("\n")))
430
518
rc = parse_status()
431
519
self.assertEqual(rc, 0)
432
520
self.assertEqual(list(sorted(mock_stdout.getvalue().strip().split("\n"))), ips)
434
@mock.patch('sys.stdout', new_callable=StringIO)
522
@mock.patch("sys.stdout", new_callable=StringIO)
435
523
def test_GetIPs_app(self, mock_stdout):
436
sys.argv = ['self', '-f', self.status_path, 'get_ips', 'ubuntu']
437
ips = list(sorted('10.25.2.109\n10.25.2.111\n10.25.2.110\n'.strip().split("\n")))
524
sys.argv = ["self", "-f", self.status_path, "get_ips", "ubuntu"]
525
ips = list(sorted("10.25.2.109\n10.25.2.111\n10.25.2.110\n".strip().split("\n")))
438
526
rc = parse_status()
439
527
self.assertEqual(rc, 0)
440
528
self.assertEqual(list(sorted(mock_stdout.getvalue().strip().split("\n"))), ips)