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"')