diff --git a/.zuul.yaml b/.zuul.yaml index 3ac4e20..60e1e2e 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -9,12 +9,14 @@ - openstack-tox-linters - stx-distcloud-client-tox-pep8 - stx-distcloud-client-tox-py27 + - stx-distcloud-client-tox-py36 - stx-distcloud-client-tox-pylint gate: jobs: - openstack-tox-linters - stx-distcloud-client-tox-pep8 - stx-distcloud-client-tox-py27 + - stx-distcloud-client-tox-py36 - stx-distcloud-client-tox-pylint post: jobs: @@ -28,6 +30,14 @@ tox_envlist: py27 tox_extra_args: -c distributedcloud-client/tox.ini +- job: + name: stx-distcloud-client-tox-py36 + parent: tox + description: Run py36 for distcloud-client + vars: + tox_envlist: py36 + tox_extra_args: -c distributedcloud-client/tox.ini + - job: name: stx-distcloud-client-tox-pylint parent: tox diff --git a/distributedcloud-client/dcmanagerclient/tests/base.py b/distributedcloud-client/dcmanagerclient/tests/base.py index 8fb0038..034c805 100644 --- a/distributedcloud-client/dcmanagerclient/tests/base.py +++ b/distributedcloud-client/dcmanagerclient/tests/base.py @@ -21,9 +21,8 @@ # import json - import mock -import unittest2 +import testtools class FakeResponse(object): @@ -39,9 +38,12 @@ class FakeResponse(object): return json.loads(self.content) -class BaseClientTest(unittest2.TestCase): +class BaseClientTest(testtools.TestCase): _client = None + def setUp(self): + super(BaseClientTest, self).setUp() + def mock_http_get(self, content, status_code=200): if isinstance(content, dict): content = json.dumps(content) @@ -76,8 +78,9 @@ class BaseClientTest(unittest2.TestCase): return self._client.http_client.delete -class BaseCommandTest(unittest2.TestCase): +class BaseCommandTest(testtools.TestCase): def setUp(self): + super(BaseCommandTest, self).setUp() self.app = mock.Mock() self.client = self.app.client_manager.subcloud_manager diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/mixins.py b/distributedcloud-client/dcmanagerclient/tests/v1/mixins.py new file mode 100644 index 0000000..1af418d --- /dev/null +++ b/distributedcloud-client/dcmanagerclient/tests/v1/mixins.py @@ -0,0 +1,72 @@ +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +from dcmanagerclient.tests.v1 import utils + + +class UpdateStrategyMixin(object): + """Mixin for testing the different types of dcmanager update strategies. + + Used by concrete testsuites of strategy types such as patch, upgrade, etc.. + Subclasses must: + - mix with BaseCommandTest + - provide: self.sw_update_manager + - provide: self.show_command + """ + def setUp(self): + super(UpdateStrategyMixin, self).setUp() + + def test_create_strategy(self): + """Test that if no strategy exists, one can be created.""" + # prepare mixin attributes + manager_to_test = self.sw_update_manager + expected_strategy_type = manager_to_test.update_type + + # mock the result of the API call + strategy = utils.make_strategy(strategy_type=expected_strategy_type) + + # mock that there is no pre-existing strategy + manager_to_test.create_sw_update_strategy.return_value = strategy + + # invoke the backend method for the CLI. + # Returns a tuple of field descriptions, and a second tuple of values + fields, results = self.call(self.create_command) + + # results is a tuple of expected length 7 + self.assertEqual(len(results), 7) + # result tuple values are + # - strategy_type + # - subcloud_apply_type + # - max_parallel_subclouds + # - stop_on_failure + # - state + # - created_at + # - updated_at + self.assertEqual(results[0], expected_strategy_type) + + def test_get_strategy(self): + # prepare mocked results + manager_to_test = self.sw_update_manager + expected_strategy_type = manager_to_test.update_type + expected_apply_type = 'parallel' + strategy = utils.make_strategy(strategy_type=expected_strategy_type, + subcloud_apply_type=expected_apply_type) + manager_to_test.update_sw_strategy_detail.return_value = strategy + + # invoke the backend method for the CLI. + # Returns a tuple of field descriptions, and a second tuple of values + fields, results = self.call(self.show_command) + # results is a tuple of expected length 7 + self.assertEqual(len(results), 7) + # result tuple values are + # - strategy_type + # - subcloud_apply_type + # - max_parallel_subclouds + # - stop_on_failure + # - state + # - created_at + # - updated_at + self.assertEqual(results[0], expected_strategy_type) + self.assertEqual(results[1], expected_apply_type) diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/test_fw_update_strategy.py b/distributedcloud-client/dcmanagerclient/tests/v1/test_fw_update_strategy.py new file mode 100644 index 0000000..e0130ec --- /dev/null +++ b/distributedcloud-client/dcmanagerclient/tests/v1/test_fw_update_strategy.py @@ -0,0 +1,19 @@ +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +from dcmanagerclient.commands.v1 import fw_update_manager as cli_cmd +from dcmanagerclient.tests import base +from dcmanagerclient.tests.v1.mixins import UpdateStrategyMixin + + +class TestFwUpdateStrategy(UpdateStrategyMixin, base.BaseCommandTest): + + def setUp(self): + super(TestFwUpdateStrategy, self).setUp() + self.sw_update_manager = \ + self.app.client_manager.fw_update_manager.fw_update_manager + self.create_command = cli_cmd.CreateFwUpdateStrategy + self.show_command = cli_cmd.ShowFwUpdateStrategy diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py b/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py index 7bc38aa..fb185ba 100644 --- a/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py +++ b/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py @@ -199,7 +199,7 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest): "external_oam_floating_address": EXTERNAL_OAM_FLOATING_ADDRESS, } - with tempfile.NamedTemporaryFile() as f: + with tempfile.NamedTemporaryFile(mode='w') as f: yaml.dump(values, f) file_path = os.path.abspath(f.name) actual_call = self.call( @@ -308,10 +308,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest): with tempfile.NamedTemporaryFile() as f: file_path = os.path.abspath(f.name) - # Python 2.7 onwards, context manager can be used to get the - # actual Exception object - with self.assertRaises(DCManagerClientException) as context: - self.call(subcloud_cmd.ReconfigSubcloud, - app_args=[ID, '--deploy-config', file_path]) + e = self.assertRaises(DCManagerClientException, + self.call, + subcloud_cmd.ReconfigSubcloud, + app_args=[ID, '--deploy-config', file_path]) self.assertTrue('deploy-config file does not exist' - in str(context.exception)) + in str(e)) diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/utils.py b/distributedcloud-client/dcmanagerclient/tests/v1/utils.py new file mode 100644 index 0000000..23c0c75 --- /dev/null +++ b/distributedcloud-client/dcmanagerclient/tests/v1/utils.py @@ -0,0 +1,35 @@ +# +# Copyright (c) 2020 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import mock + +from oslo_utils import timeutils + +from dcmanagerclient.api.v1.sw_update_manager import SwUpdateStrategy + +TIME_NOW = timeutils.utcnow().isoformat() +DEFAULT_APPLY_TYPE = 'serial' +DEFAULT_MAX_PARALLEL = 2 +DEFAULT_STATE = 'initial' +DEFAULT_STRATEGY_TYPE = 'patch' + + +def make_strategy(manager=mock.MagicMock(), + strategy_type=DEFAULT_STRATEGY_TYPE, + subcloud_apply_type=DEFAULT_APPLY_TYPE, + max_parallel_subclouds=DEFAULT_MAX_PARALLEL, + stop_on_failure=False, + state=DEFAULT_STATE, + created_at=TIME_NOW, + updated_at=None): + return SwUpdateStrategy(manager, + strategy_type, + subcloud_apply_type, + max_parallel_subclouds, + stop_on_failure, + state, + created_at, + updated_at) diff --git a/distributedcloud-client/test-requirements.txt b/distributedcloud-client/test-requirements.txt index ac7fe13..42a93bb 100644 --- a/distributedcloud-client/test-requirements.txt +++ b/distributedcloud-client/test-requirements.txt @@ -6,7 +6,6 @@ pylint==1.9.2;python_version<"3.0" # GPLv2 pylint==2.3.1;python_version>="3.0" # GPLv2 python-openstackclient>=3.3.0 # Apache-2.0 sphinx>=1.5.1 # BSD -unittest2 # BSD fixtures>=3.0.0 # Apache-2.0/BSD mock>=2.0 # BSD nose # LGPL diff --git a/distributedcloud-client/tox.ini b/distributedcloud-client/tox.ini index ea80fd9..1fcfb95 100644 --- a/distributedcloud-client/tox.ini +++ b/distributedcloud-client/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.3 -envlist = py27,pep8,pylint +envlist = py27,py36,pep8,pylint skipsdist = True toxworkdir = /tmp/{env:USER}_dc_client_tox @@ -32,6 +32,12 @@ commands = find {toxinidir} -not -path '{toxinidir}/.tox/*' -name '*.py[c|o]' -delete stestr --test-path={[dcclient]client_base_dir}/dcmanagerclient/tests run '{posargs}' +[testenv:py36] +basepython = python3.6 +commands = + find {toxinidir} -not -path '{toxinidir}/.tox/*' -name '*.py[c|o]' -delete + stestr --test-path={[dcclient]client_base_dir}/dcmanagerclient/tests run '{posargs}' + [testenv:pep8] basepython = python3 commands = flake8 {posargs}