diff --git a/.github/workflows/tox.yaml b/.github/workflows/tox.yaml index 9379c9f94..311c12015 100644 --- a/.github/workflows/tox.yaml +++ b/.github/workflows/tox.yaml @@ -5,11 +5,35 @@ on: - pull_request jobs: + build_old_versions: + runs-on: ubuntu-20.04 + strategy: + matrix: + python-version: ['3.6'] + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install codecov tox tox-gh-actions + - name: Lint with tox + run: tox -e pep8 + - name: Test with tox + run: tox -e py + - name: Codecov + run: | + set -euxo pipefail + codecov --verbose --gcov-glob unit_tests/* build: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.6', '3.7', '3.8', '3.9', '3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10'] steps: - uses: actions/checkout@v1 diff --git a/requirements.txt b/requirements.txt index faffe82cc..5a5371b03 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,7 @@ pyparsing<3.0.0 # pin for aodhclient which is held for py35 async_generator kubernetes<18.0.0; python_version < '3.6' # pined, as juju uses kubernetes -# pinned until 3.0 regressions are handled: https://github.com/openstack-charmers/zaza/issues/545 -juju<3.0 +juju juju_wait PyYAML>=3.0 pbr==5.6.0 diff --git a/setup.py b/setup.py index 87445e411..52a574275 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ 'hvac<0.7.0', 'jinja2', - 'juju<3.0', + 'juju', 'juju-wait', 'PyYAML', 'tenacity', diff --git a/unit_tests/test_zaza_model.py b/unit_tests/test_zaza_model.py index 0c8cf962e..8c75d95e7 100644 --- a/unit_tests/test_zaza_model.py +++ b/unit_tests/test_zaza_model.py @@ -142,6 +142,7 @@ async def _inner_is_leader(): self.run_action = mock.MagicMock() self.run_action.wait.side_effect = _wait self.action = mock.MagicMock() + self.action.wait.side_effect = _wait self.action.data = { 'model-uuid': '1a035018-71ff-473e-8aab-d1a8d6b6cda7', 'id': 'e26ffb69-6626-4e93-8840-07f7e041e99d', @@ -493,7 +494,9 @@ def test_block_until_auto_reconnect_model_disconnected_sync(self): with mock.patch.object(zaza, 'RUN_LIBJUJU_IN_THREAD', new=False): model.sync_wrapper(self._wrapper)() self.Model_mock.disconnect.assert_has_calls([mock.call()]) - self.Model_mock.connect_model.has_calls([mock.call('modelname')]) + self.Model_mock.connect_model.assert_has_calls( + [mock.call('testmodel')] + ) def test_block_until_auto_reconnect_model_disconnected_async(self): self._mocks_for_block_until_auto_reconnect_model( @@ -506,7 +509,9 @@ async def _async_true(): with mock.patch.object(zaza, 'RUN_LIBJUJU_IN_THREAD', new=False): model.sync_wrapper(self._wrapper)() self.Model_mock.disconnect.assert_has_calls([mock.call()]) - self.Model_mock.connect_model.has_calls([mock.call('modelname')]) + self.Model_mock.connect_model.assert_has_calls( + [mock.call('testmodel')] + ) def test_block_until_auto_reconnect_model_blocks_till_true(self): self._mocks_for_block_until_auto_reconnect_model(True, True) diff --git a/unit_tests/utilities/test_zaza_utilities_generic.py b/unit_tests/utilities/test_zaza_utilities_generic.py index 5d3fb7759..038d53e0b 100644 --- a/unit_tests/utilities/test_zaza_utilities_generic.py +++ b/unit_tests/utilities/test_zaza_utilities_generic.py @@ -254,7 +254,7 @@ def test_series_upgrade(self): _unit, _machine_num, origin=_origin, to_series=_to_series, from_series=_from_series, workaround_script=_workaround_script, files=_files) - self.block_until_all_units_idle.called_with() + self.block_until_all_units_idle.assert_called_with() self.prepare_series_upgrade.assert_called_once_with( _machine_num, to_series=_to_series) self.wrap_do_release_upgrade.assert_called_once_with( diff --git a/zaza/model.py b/zaza/model.py index e5539e15e..d05a1d7d6 100644 --- a/zaza/model.py +++ b/zaza/model.py @@ -545,6 +545,9 @@ def _normalise_action_results(results): results[old_key] = results[key] elif results.get(old_key) and not results.get(key): results[key] = results[old_key] + if 'return-code' in results: + results['Code'] = results.get('return-code') + del results['return-code'] return results else: return {} @@ -567,7 +570,10 @@ async def async_run_on_unit(unit_name, command, model_name=None, timeout=None): model = await get_model(model_name) unit = await async_get_unit_from_name(unit_name, model) action = await unit.run(command, timeout=timeout) + await action.wait() results = action.data.get('results') + if not results: + results = action.results return _normalise_action_results(results) run_on_unit = sync_wrapper(async_run_on_unit) @@ -593,7 +599,10 @@ async def async_run_on_leader(application_name, command, model_name=None, is_leader = await unit.is_leader_from_status() if is_leader: action = await unit.run(command, timeout=timeout) + await action.wait() results = action.data.get('results') + if not results: + results = action.results return _normalise_action_results(results) run_on_leader = sync_wrapper(async_run_on_leader) @@ -2049,7 +2058,13 @@ async def _check_file(): for unit in units: try: output = await unit.run('cat {}'.format(remote_file)) - contents = output.data.get('results').get('Stdout', '') + await output.wait() + results = output.data.get('results') + if not results: + results = output.results + contents = results.get('Stdout', '') + if not contents: + contents = results.get('stdout', '') if inspect.iscoroutinefunction(check_function): if not await check_function(contents): return False @@ -2184,7 +2199,13 @@ async def _check_for_file(model): for unit in units: try: output = await unit.run('test -e "{}"; echo $?'.format(path)) - contents = output.data.get('results')['Stdout'] + await output.wait() + output_result = output.data.get('results') + if not output_result: + output_result = output.results + contents = output_result.get('Stdout', '') + if not contents: + contents = output_result.get('stdout', '') results.append("1" in contents) # libjuju throws a generic error for connection failure. So we # cannot differentiate between a connectivity issue and a