Merge pull request #114 from fnordahl/issue/113
Fix race in `test_utils.config_change()`
This commit is contained in:
@@ -91,6 +91,8 @@ class TestModel(ut_utils.BaseTestCase):
|
||||
self.unit2.run_action.side_effect = _run_action
|
||||
self.unit1.is_leader_from_status.side_effect = _is_leader(False)
|
||||
self.unit2.is_leader_from_status.side_effect = _is_leader(True)
|
||||
self.unit1.data = {'agent-status': {'current': 'idle'}}
|
||||
self.unit2.data = {'agent-status': {'current': 'idle'}}
|
||||
self.units = [self.unit1, self.unit2]
|
||||
self.relation1 = mock.MagicMock()
|
||||
self.relation1.id = 42
|
||||
@@ -893,6 +895,29 @@ disk_formats = ami,ari,aki,vhd,vmdk,raw,qcow2,vdi,iso,root-tar
|
||||
'active',
|
||||
timeout=0.1)
|
||||
|
||||
def test_wait_for_agent_status(self):
|
||||
async def _block_until(f, timeout=None):
|
||||
if not f():
|
||||
raise asyncio.futures.TimeoutError
|
||||
self.patch_object(model, 'get_juju_model', return_value='mname')
|
||||
self.patch_object(model, 'Model')
|
||||
self.unit1.data = {'agent-status': {'current': 'idle'}}
|
||||
self.unit2.data = {'agent-status': {'current': 'executing'}}
|
||||
self.Model.return_value = self.Model_mock
|
||||
self.Model_mock.block_until.side_effect = _block_until
|
||||
model.wait_for_agent_status(timeout=0.1)
|
||||
|
||||
def test_wait_for_agent_status_timeout(self):
|
||||
async def _block_until(f, timeout=None):
|
||||
if not f():
|
||||
raise asyncio.futures.TimeoutError
|
||||
self.patch_object(model, 'get_juju_model', return_value='mname')
|
||||
self.patch_object(model, 'Model')
|
||||
self.Model.return_value = self.Model_mock
|
||||
self.Model_mock.block_until.side_effect = _block_until
|
||||
with self.assertRaises(asyncio.futures.TimeoutError):
|
||||
model.wait_for_agent_status(timeout=0.1)
|
||||
|
||||
|
||||
class AsyncModelTests(aiounittest.AsyncTestCase):
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ class OpenStackBaseTest(unittest.TestCase):
|
||||
alternate_config,
|
||||
model_name=self.model_name)
|
||||
|
||||
logging.debug(
|
||||
'Waiting for units to execute config-changed hook')
|
||||
model.wait_for_agent_status(model_name=self.model_name)
|
||||
|
||||
logging.debug(
|
||||
'Waiting for units to reach target states')
|
||||
model.wait_for_application_states(
|
||||
|
||||
@@ -606,6 +606,42 @@ def check_unit_workload_status_message(model, unit, message=None,
|
||||
raise ValueError("Must be called with message or prefixes")
|
||||
|
||||
|
||||
async def async_wait_for_agent_status(model_name=None, status='executing',
|
||||
timeout=60):
|
||||
"""Wait for at least one unit to enter a specific agent status.
|
||||
|
||||
This is useful for awaiting execution after mutating charm configuration.
|
||||
|
||||
:param model_name: Name of model to query.
|
||||
:type model_name: str
|
||||
:param status: The desired agent status we are looking for.
|
||||
:type status: str
|
||||
:param timeout: Time to wait for status to be achieved.
|
||||
:type timeout: int
|
||||
"""
|
||||
def one_agent_status(model, status):
|
||||
check_model_for_hard_errors(model)
|
||||
for app in model.applications:
|
||||
for unit in model.applications[app].units:
|
||||
agent_status = unit.data.get('agent-status', {})
|
||||
if agent_status.get('current', None) == status:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
break
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
async with run_in_model(model_name) as model:
|
||||
logging.info('Waiting for at least one unit with agent status "{}"'
|
||||
.format(status))
|
||||
await model.block_until(
|
||||
lambda: one_agent_status(model, status), timeout=timeout)
|
||||
|
||||
wait_for_agent_status = sync_wrapper(async_wait_for_agent_status)
|
||||
|
||||
|
||||
async def async_wait_for_application_states(model_name=None, states=None,
|
||||
timeout=2700):
|
||||
"""Wait for model to achieve the desired state.
|
||||
|
||||
Reference in New Issue
Block a user