diff --git a/.github/workflows/tox.yaml b/.github/workflows/tox.yaml index 0f8b395d3..3bdd5dba2 100644 --- a/.github/workflows/tox.yaml +++ b/.github/workflows/tox.yaml @@ -31,6 +31,27 @@ jobs: codecov --verbose --gcov-glob unit_tests/* func: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + juju_channel: + - latest/stable + - 2.9/stable + - 2.8/stable + bundle: + - first + - second + - third + exclude: + # disable 'first' and 'second' bundles for juju 2.8 since 'magpie' + # is not a promulgated charm in the charmstore, only on charmhub + # which 2.8 can't talk to. + - juju_channel: 2.8/stable + bundle: first + - juju_channel: 2.8/stable + bundle: second + env: + TEST_ZAZA_BUG_LP1987332: "on" # http://pad.lv/1987332 needs: build steps: - uses: actions/checkout@v1 @@ -39,7 +60,7 @@ jobs: set -euxo pipefail python -m pip install --upgrade pip pip install tox tox-gh-actions - sudo snap install --classic juju + sudo snap install --channel ${{ matrix.juju_channel }} --classic juju sudo snap install --classic juju-crashdump sudo lxd init --auto # This is a throw-away CI environment, do not do this at home @@ -56,13 +77,15 @@ jobs: run: | set -euxo pipefail mkdir logs - tox -e func | tee logs/tox-output.txt - juju status -m $(juju models --format yaml|grep "^- name:.*zaza"|cut -f2 -d/) | tee logs/juju-status.txt + tox -e func-target -- ${{ matrix.bundle }} | tee logs/tox-output.txt - name: crashdump on failure if: failure() run: | - set -euxo pipefail - juju crashdump -o logs/ + set -eux + juju models + model=$(juju models --format yaml|grep "^- name:.*zaza"|cut -f2 -d/) + juju status -m $model | tee logs/juju-status.txt + juju crashdump -m $model -o logs/ - name: upload logs on failure if: failure() uses: actions/upload-artifact@v2 diff --git a/pip.sh b/pip.sh new file mode 100755 index 000000000..1085da286 --- /dev/null +++ b/pip.sh @@ -0,0 +1,3 @@ +#!/bin/bash +pip install pip==20.2.3 +pip install "$@" diff --git a/tests/bundles/first.yaml b/tests/bundles/first.yaml index 7595b3464..ef473c3cd 100644 --- a/tests/bundles/first.yaml +++ b/tests/bundles/first.yaml @@ -13,3 +13,9 @@ applications: ubuntu: charm: ch:ubuntu num_units: 3 + ntp: + charm: ch:ntp + num_units: 0 +relations: + - - ubuntu + - ntp diff --git a/tests/bundles/second.yaml b/tests/bundles/second.yaml index b4ead7f8f..362a15b02 100644 --- a/tests/bundles/second.yaml +++ b/tests/bundles/second.yaml @@ -8,3 +8,9 @@ applications: ubuntu: charm: ch:ubuntu num_units: 3 + ntp: + charm: ch:ntp + num_units: 0 +relations: + - - ubuntu + - ntp diff --git a/tests/bundles/third.yaml b/tests/bundles/third.yaml index c6294bbc7..1b2235d4a 100644 --- a/tests/bundles/third.yaml +++ b/tests/bundles/third.yaml @@ -1,6 +1,11 @@ series: focal applications: ubuntu: - charm: ch:ubuntu + charm: ubuntu num_units: 10 - + ntp: + charm: ntp + num_units: 0 +relations: + - - ubuntu + - ntp diff --git a/tox.ini b/tox.ini index 62df7615c..44328e376 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ whitelist_external = juju passenv = HOME TERM CS_* OS_* TEST_* deps = -r{toxinidir}/requirements.txt install_command = - pip install {opts} {packages} + {toxinidir}/pip.sh install {opts} {packages} commands = nosetests --with-coverage --cover-package=zaza {posargs} {toxinidir}/unit_tests [testenv:py3] @@ -56,7 +56,14 @@ basepython = python3 deps = -r{toxinidir}/requirements.txt commands = {envdir}/bin/python3 setup.py install - functest-run-suite --keep-model + functest-run-suite --keep-faulty-model + +[testenv:func-target] +basepython = python3 +deps = -r{toxinidir}/requirements.txt +commands = + {envdir}/bin/python3 setup.py install + functest-run-suite --keep-model --bundle {posargs} [testenv:remove-placement] basepython = python3 diff --git a/unit_tests/utilities/test_zaza_utilities_juju.py b/unit_tests/utilities/test_zaza_utilities_juju.py index f15b3e4f5..7fa5e2187 100644 --- a/unit_tests/utilities/test_zaza_utilities_juju.py +++ b/unit_tests/utilities/test_zaza_utilities_juju.py @@ -13,6 +13,7 @@ # limitations under the License. import mock +import os import unit_tests.utils as ut_utils from zaza.utilities import juju as juju_utils @@ -411,6 +412,51 @@ def test_get_subordinate_units(self): status=juju_status), ['cinder-ceph/3']) + def test_get_subordinate_units_lp1987332(self): + juju_status = mock.MagicMock() + juju_status.applications = { + 'nova-compute': { + 'charm': 'ch:amd64/focal/nova-compute-1', + 'units': { + 'nova-compute/0': { + 'subordinates': { + 'neutron-openvswitch/2': { + 'charm': ''}}}}}, + 'cinder': { + 'charm': 'ch:amd64/focal/cinder-2', + 'units': { + 'cinder/1': { + 'subordinates': { + 'cinder-hacluster/0': { + 'charm': ''}, + 'cinder-ceph/3': { + 'charm': ''}}}}}, + 'cinder-hacluster': { + 'charm': 'ch:amd64/focal/hacluster-3', + }, + 'cinder-ceph': { + 'charm': 'ch:amd64/focal/cinder-ceph-4', + }, + 'neutron-openvswitch': { + 'charm': 'ch:amd64/focal/neutron-openvswitch-5', + }, + } + self.model.get_status.return_Value = juju_status + with mock.patch.dict(os.environ, + {'TEST_ZAZA_BUG_LP1987332': '1'}): + self.assertEqual( + sorted(juju_utils.get_subordinate_units( + ['nova-compute/0', 'cinder/1'], + status=juju_status)), + sorted(['neutron-openvswitch/2', 'cinder-hacluster/0', + 'cinder-ceph/3'])) + self.assertEqual( + juju_utils.get_subordinate_units( + ['nova-compute/0', 'cinder/1'], + charm_name='ceph', + status=juju_status), + ['cinder-ceph/3']) + def test_get_application_ip(self): self.model.get_application_config.return_value = { 'vip': {'value': '10.0.0.10'}} diff --git a/zaza/charm_tests/libjuju/tests.py b/zaza/charm_tests/libjuju/tests.py index ca266a127..67b66cf59 100644 --- a/zaza/charm_tests/libjuju/tests.py +++ b/zaza/charm_tests/libjuju/tests.py @@ -20,6 +20,7 @@ import unittest import zaza.model +import zaza.utilities.juju as juju_utils class RegressionTest(unittest.TestCase): @@ -50,3 +51,14 @@ def test_02_get_unit_public_address(self): for ip in ips: logging.info("Ip found %s", ip) self.assertIsNotNone(ip) + + def test_03_get_subordinates(self): + """Get the subordinates associated to a principal.""" + logging.info('Get the list of subordinates.') + units = [u.entity_id for u in zaza.model.get_units('ubuntu')] + logging.info('principal units found: %s', units) + subordinate = juju_utils.get_subordinate_units([units[0]], + charm_name='ntp') + logging.info('subordinate(s) found %s for principal %s', + subordinate, units[0]) + self.assertEqual(len(subordinate), 1) diff --git a/zaza/utilities/juju.py b/zaza/utilities/juju.py index 95dd94671..de9b942e9 100644 --- a/zaza/utilities/juju.py +++ b/zaza/utilities/juju.py @@ -480,9 +480,14 @@ def get_subordinate_units(unit_list, charm_name=None, status=None, subs = status.applications[app_name]['units'][unit_name].get( 'subordinates') or {} if charm_name: - for unit_name, unit_data in subs.items(): - if charm_name in unit_data['charm']: - sub_units.append(unit_name) + for subordinate_name, unit_data in subs.items(): + if os.environ.get('TEST_ZAZA_BUG_LP1987332'): + sub_app = subordinate_name.split('/')[0] + charm = status.applications[sub_app]['charm'] + else: + charm = unit_data['charm'] + if charm_name in charm: + sub_units.append(subordinate_name) else: sub_units.extend([n for n in subs.keys()]) return sub_units