github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/jujupy/tests/test_wait_condition.py (about) 1 from datetime import ( 2 datetime, 3 timedelta, 4 ) 5 try: 6 from mock import ( 7 Mock, 8 patch, 9 ) 10 except ImportError: 11 from unittest.mock import ( 12 Mock, 13 patch, 14 ) 15 16 from jujupy import ( 17 fake_juju_client, 18 ) 19 from jujupy.status import ( 20 Status, 21 ) 22 from jujupy.wait_condition import ( 23 BaseCondition, 24 CommandComplete, 25 CommandTime, 26 ConditionList, 27 MachineDown, 28 NoopCondition, 29 WaitApplicationNotPresent, 30 WaitMachineNotPresent, 31 ) 32 33 from tests import ( 34 TestCase, 35 ) 36 37 38 class TestBaseCondition(TestCase): 39 40 def test_timeout(self): 41 condition = BaseCondition() 42 self.assertEqual(300, condition.timeout) 43 condition = BaseCondition(600) 44 self.assertEqual(600, condition.timeout) 45 46 47 class TestConditionList(TestCase): 48 49 def test_uses_max_timeout(self): 50 conditions = ConditionList([Mock(timeout=300), Mock(timeout=400)]) 51 self.assertEqual(400, conditions.timeout) 52 53 def test_empty_timeout(self): 54 conditions = ConditionList([]) 55 self.assertEqual(300, conditions.timeout) 56 57 def test_iter_blocking_state(self): 58 mock_ab = Mock(timeout=0) 59 mock_ab.iter_blocking_state.return_value = [('a', 'b')] 60 mock_cd = Mock(timeout=0) 61 mock_cd.iter_blocking_state.return_value = [('c', 'd')] 62 conditions = ConditionList([mock_ab, mock_cd]) 63 self.assertEqual([('a', 'b'), ('c', 'd')], 64 list(conditions.iter_blocking_state(None))) 65 66 67 class TestNoopCondition(TestCase): 68 69 def test_iter_blocking_state_is_noop(self): 70 condition = NoopCondition() 71 called = False 72 for _ in condition.iter_blocking_state({}): 73 called = True 74 self.assertFalse(called) 75 76 def test_do_raise_raises_Exception(self): 77 condition = NoopCondition() 78 with self.assertRaises(Exception): 79 condition.do_raise('model_name', {}) 80 81 82 class TestWaitMachineNotPresent(TestCase): 83 84 def test_iter_blocking_state(self): 85 not_present = WaitMachineNotPresent('0') 86 client = fake_juju_client() 87 client.bootstrap() 88 self.assertItemsEqual( 89 [], not_present.iter_blocking_state(client.get_status())) 90 client.juju('add-machine', ()) 91 self.assertItemsEqual( 92 [('0', 'still-present')], 93 not_present.iter_blocking_state(client.get_status())) 94 client.juju('remove-machine', ('0')) 95 self.assertItemsEqual( 96 [], not_present.iter_blocking_state(client.get_status())) 97 98 def test_do_raise(self): 99 not_present = WaitMachineNotPresent('0') 100 with self.assertRaisesRegexp( 101 Exception, 'Timed out waiting for machine removal 0'): 102 not_present.do_raise('', None) 103 104 105 class TestWaitApplicationNotPresent(TestCase): 106 107 def test_iter_blocking_state(self): 108 not_present = WaitApplicationNotPresent('foo') 109 client = fake_juju_client() 110 client.bootstrap() 111 self.assertItemsEqual( 112 [], not_present.iter_blocking_state(client.get_status())) 113 client.deploy('foo') 114 self.assertItemsEqual( 115 [('foo', 'still-present')], 116 not_present.iter_blocking_state(client.get_status())) 117 client.remove_service('foo') 118 self.assertItemsEqual( 119 [], not_present.iter_blocking_state(client.get_status())) 120 121 def test_do_raise(self): 122 not_present = WaitApplicationNotPresent('foo') 123 with self.assertRaisesRegexp( 124 Exception, 'Timed out waiting for application removal foo'): 125 not_present.do_raise('', None) 126 127 128 class TestMachineDown(TestCase): 129 130 def test_iter_blocking_state(self): 131 down = MachineDown('0') 132 client = fake_juju_client() 133 client.bootstrap() 134 client.juju('add-machine', ()) 135 self.assertItemsEqual( 136 [('0', 'idle')], 137 down.iter_blocking_state(client.get_status())) 138 status = Status({'machines': {'0': {'juju-status': { 139 'current': 'down', 140 }}}}, '') 141 self.assertItemsEqual( 142 [], down.iter_blocking_state(status)) 143 144 def test_do_raise(self): 145 down = MachineDown('0') 146 with self.assertRaisesRegexp( 147 Exception, 148 'Timed out waiting for juju to determine machine 0 down.'): 149 down.do_raise('', None) 150 151 152 class TestCommandTime(TestCase): 153 154 def test_default_values(self): 155 full_args = ['juju', '--showlog', 'bootstrap'] 156 utcnow = datetime(2017, 3, 22, 23, 36, 52, 530631) 157 with patch('jujupy.wait_condition.datetime', autospec=True) as m_dt: 158 m_dt.utcnow.return_value = utcnow 159 ct = CommandTime('bootstrap', full_args) 160 self.assertEqual(ct.cmd, 'bootstrap') 161 self.assertEqual(ct.full_args, full_args) 162 self.assertEqual(ct.envvars, None) 163 self.assertEqual(ct.start, utcnow) 164 self.assertEqual(ct.end, None) 165 166 def test_set_start_time(self): 167 ct = CommandTime('cmd', [], start='abc') 168 self.assertEqual(ct.start, 'abc') 169 170 def test_set_envvar(self): 171 details = {'abc': 123} 172 ct = CommandTime('cmd', [], envvars=details) 173 self.assertEqual(ct.envvars, details) 174 175 def test_actual_completion_sets_default(self): 176 utcnow = datetime(2017, 3, 22, 23, 36, 52, 530631) 177 ct = CommandTime('cmd', []) 178 with patch('jujupy.wait_condition.datetime', autospec=True) as m_dt: 179 m_dt.utcnow.return_value = utcnow 180 ct.actual_completion() 181 self.assertEqual(ct.end, utcnow) 182 183 def test_actual_completion_idempotent(self): 184 ct = CommandTime('cmd', []) 185 ct.actual_completion(end='a') 186 ct.actual_completion(end='b') 187 self.assertEqual(ct.end, 'a') 188 189 def test_actual_completion_set_value(self): 190 utcnow = datetime(2017, 3, 22, 23, 36, 52, 530631) 191 ct = CommandTime('cmd', []) 192 ct.actual_completion(end=utcnow) 193 self.assertEqual(ct.end, utcnow) 194 195 def test_total_seconds_returns_None_when_not_complete(self): 196 ct = CommandTime('cmd', []) 197 self.assertEqual(ct.total_seconds, None) 198 199 def test_total_seconds_returns_seconds_taken_to_complete(self): 200 utcstart = datetime(2017, 3, 22, 23, 36, 52, 530631) 201 utcend = utcstart + timedelta(seconds=1) 202 with patch('jujupy.wait_condition.datetime', autospec=True) as m_dt: 203 m_dt.utcnow.side_effect = [utcstart, utcend] 204 ct = CommandTime('cmd', []) 205 ct.actual_completion() 206 self.assertEqual(ct.total_seconds, 1) 207 208 209 class TestCommandComplete(TestCase): 210 211 def test_default_values(self): 212 ct = CommandTime('cmd', []) 213 base_condition = BaseCondition() 214 cc = CommandComplete(base_condition, ct) 215 216 self.assertEqual(cc.timeout, 300) 217 self.assertEqual(cc.already_satisfied, False) 218 self.assertEqual(cc._real_condition, base_condition) 219 self.assertEqual(cc.command_time, ct) 220 # actual_completion shouldn't be set as the condition is not already 221 # satisfied. 222 self.assertEqual(cc.command_time.end, None) 223 224 def test_sets_total_seconds_when_already_satisfied(self): 225 base_condition = BaseCondition(already_satisfied=True) 226 ct = CommandTime('cmd', []) 227 cc = CommandComplete(base_condition, ct) 228 229 self.assertIsNotNone(cc.command_time.total_seconds) 230 231 def test_calls_wrapper_condition_iter(self): 232 class TestCondition(BaseCondition): 233 def iter_blocking_state(self, status): 234 yield 'item', status 235 236 ct = CommandTime('cmd', []) 237 cc = CommandComplete(TestCondition(), ct) 238 239 k, v = next(cc.iter_blocking_state('status_obj')) 240 self.assertEqual(k, 'item') 241 self.assertEqual(v, 'status_obj') 242 243 def test_sets_actual_completion_when_complete(self): 244 """When the condition hits success must set actual_completion.""" 245 class TestCondition(BaseCondition): 246 def __init__(self): 247 super(TestCondition, self).__init__() 248 self._already_called = False 249 250 def iter_blocking_state(self, status): 251 if not self._already_called: 252 self._already_called = True 253 yield 'item', status 254 255 ct = CommandTime('cmd', []) 256 cc = CommandComplete(TestCondition(), ct) 257 258 next(cc.iter_blocking_state('status_obj')) 259 self.assertIsNone(cc.command_time.end) 260 next(cc.iter_blocking_state('status_obj'), None) 261 self.assertIsNotNone(cc.command_time.end) 262 263 def test_raises_exception_with_command_details(self): 264 ct = CommandTime('cmd', ['cmd', 'arg1', 'arg2']) 265 cc = CommandComplete(BaseCondition(), ct) 266 267 with self.assertRaises(RuntimeError) as ex: 268 cc.do_raise('status') 269 self.assertEqual( 270 str(ex.exception), 271 'Timed out waiting for "cmd" command to complete: "cmd arg1 arg2"')