From c04177442c7d96f743949fe0be2045742f7bdc03 Mon Sep 17 00:00:00 2001 From: Sebastian Wagner Date: Mon, 6 Sep 2021 12:21:58 +0200 Subject: [PATCH] pybind/mgr: tox.ini add nooptional testenv To verify cephadm properly works as expected without asyncssh installed Signed-off-by: Sebastian Wagner --- src/pybind/mgr/CMakeLists.txt | 2 +- src/pybind/mgr/cephadm/tests/test_cephadm.py | 35 ------------- src/pybind/mgr/cephadm/tests/test_ssh.py | 55 ++++++++++++++++++++ src/pybind/mgr/requirements-required.txt | 14 +++++ src/pybind/mgr/requirements.txt | 18 +------ src/pybind/mgr/tox.ini | 12 +++++ 6 files changed, 84 insertions(+), 52 deletions(-) create mode 100644 src/pybind/mgr/cephadm/tests/test_ssh.py create mode 100644 src/pybind/mgr/requirements-required.txt diff --git a/src/pybind/mgr/CMakeLists.txt b/src/pybind/mgr/CMakeLists.txt index 5193f05f43d..8fcb62a8a83 100644 --- a/src/pybind/mgr/CMakeLists.txt +++ b/src/pybind/mgr/CMakeLists.txt @@ -13,7 +13,7 @@ if(WITH_MGR_ROOK_CLIENT) endif() if(WITH_TESTS) include(AddCephTest) - add_tox_test(mgr ${CMAKE_CURRENT_SOURCE_DIR} TOX_ENVS py3 mypy flake8 jinjalint) + add_tox_test(mgr ${CMAKE_CURRENT_SOURCE_DIR} TOX_ENVS py3 mypy flake8 jinjalint nooptional) endif() # Location needs to match default setting for mgr_module_path, currently: diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index c2e84535148..2cde6ce1415 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -1,11 +1,4 @@ import json -try: - # AsyncMock was not added until python 3.8 - from unittest.mock import AsyncMock -except ImportError: - from asyncmock import AsyncMock -except ImportError: - AsyncMock = None from contextlib import contextmanager @@ -22,8 +15,6 @@ try: except ImportError: pass -from asyncssh.misc import ConnectionLost - from ceph.deployment.service_spec import ServiceSpec, PlacementSpec, RGWSpec, \ NFSServiceSpec, IscsiServiceSpec, HostPlacementSpec, CustomContainerSpec from ceph.deployment.drive_selection.selector import DriveSelection @@ -1084,32 +1075,6 @@ spec: assert_rm_daemon(cephadm_module, spec.service_name(), 'host1') # verifies ok-to-stop assert_rm_daemon(cephadm_module, spec.service_name(), 'host2') - @mock.patch("cephadm.ssh.SSHManager.execute_command") - @mock.patch("cephadm.ssh.SSHManager.check_execute_command") - def test_offline(self, check_execute_command, execute_command, cephadm_module): - check_execute_command.return_value = '' - execute_command.return_value = '', '', 0 - - if not AsyncMock: - # can't run this test if we could not import AsyncMock - return - mock_connect = AsyncMock(return_value='') - with mock.patch("asyncssh.connect", new=mock_connect) as asyncssh_connect: - with with_host(cephadm_module, 'test'): - asyncssh_connect.side_effect = ConnectionLost('reason') - code, out, err = cephadm_module.check_host('test') - assert out == '' - assert "Host 'test' not found" in err - - out = wait(cephadm_module, cephadm_module.get_hosts())[0].to_json() - assert out == HostSpec('test', '1.2.3.4', status='Offline').to_json() - - asyncssh_connect.return_value = mock.MagicMock() - asyncssh_connect.side_effect = None - assert CephadmServe(cephadm_module)._check_host('test') is None - out = wait(cephadm_module, cephadm_module.get_hosts())[0].to_json() - assert out == HostSpec('test', '1.2.3.4').to_json() - @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) def test_dont_touch_offline_or_maintenance_host_daemons(self, cephadm_module): # test daemons on offline/maint hosts not removed when applying specs diff --git a/src/pybind/mgr/cephadm/tests/test_ssh.py b/src/pybind/mgr/cephadm/tests/test_ssh.py new file mode 100644 index 00000000000..288217b7aea --- /dev/null +++ b/src/pybind/mgr/cephadm/tests/test_ssh.py @@ -0,0 +1,55 @@ +from unittest import mock +try: + # AsyncMock was not added until python 3.8 + from unittest.mock import AsyncMock +except ImportError: + from asyncmock import AsyncMock +except ImportError: + AsyncMock = None +import pytest + +try: + from asyncssh.misc import ConnectionLost +except ImportError: + ConnectionLost = None + +from ceph.deployment.hostspec import HostSpec + +from cephadm import CephadmOrchestrator +from cephadm.serve import CephadmServe +from cephadm.tests.fixtures import with_host, wait + + +@pytest.mark.skipif(ConnectionLost is None, reason='no asyncssh') +class TestWithSSH: + @mock.patch("cephadm.ssh.SSHManager.execute_command") + @mock.patch("cephadm.ssh.SSHManager.check_execute_command") + def test_offline(self, check_execute_command, execute_command, cephadm_module): + check_execute_command.return_value = '' + execute_command.return_value = '', '', 0 + + if not AsyncMock: + # can't run this test if we could not import AsyncMock + return + mock_connect = AsyncMock(return_value='') + with mock.patch("asyncssh.connect", new=mock_connect) as asyncssh_connect: + with with_host(cephadm_module, 'test'): + asyncssh_connect.side_effect = ConnectionLost('reason') + code, out, err = cephadm_module.check_host('test') + assert out == '' + assert "Host 'test' not found" in err + + out = wait(cephadm_module, cephadm_module.get_hosts())[0].to_json() + assert out == HostSpec('test', '1.2.3.4', status='Offline').to_json() + + asyncssh_connect.return_value = mock.MagicMock() + asyncssh_connect.side_effect = None + assert CephadmServe(cephadm_module)._check_host('test') is None + out = wait(cephadm_module, cephadm_module.get_hosts())[0].to_json() + assert out == HostSpec('test', '1.2.3.4').to_json() + + +@pytest.mark.skipif(ConnectionLost is not None, reason='asyncssh') +class TestWithoutSSH: + def test_can_run(self, cephadm_module: CephadmOrchestrator): + assert cephadm_module.can_run() == (False, "loading asyncssh library:No module named 'asyncssh'") diff --git a/src/pybind/mgr/requirements-required.txt b/src/pybind/mgr/requirements-required.txt new file mode 100644 index 00000000000..49ea088e12c --- /dev/null +++ b/src/pybind/mgr/requirements-required.txt @@ -0,0 +1,14 @@ +-e../../python-common +asyncmock +cherrypy +jsonpatch +Jinja2 +pecan +prettytable +pyfakefs +pyOpenSSL +pytest-cov==2.7.1 +pyyaml +requests-mock +scipy +werkzeug diff --git a/src/pybind/mgr/requirements.txt b/src/pybind/mgr/requirements.txt index 9b315e4562a..617b6dee2d3 100644 --- a/src/pybind/mgr/requirements.txt +++ b/src/pybind/mgr/requirements.txt @@ -1,17 +1,3 @@ -pytest-cov==2.7.1 --e../../python-common -kubernetes -requests-mock -pyyaml -prettytable -pyOpenSSL -Jinja2 -pyfakefs +-rrequirements-required.txt asyncssh -asyncmock - -jsonpatch -pecan -scipy -cherrypy -werkzeug +kubernetes diff --git a/src/pybind/mgr/tox.ini b/src/pybind/mgr/tox.ini index 0165f77ddbe..2256d996bfc 100644 --- a/src/pybind/mgr/tox.ini +++ b/src/pybind/mgr/tox.ini @@ -6,6 +6,7 @@ envlist = fix flake8 jinjalint + nooptional skipsdist = true requires = cython @@ -45,6 +46,17 @@ deps = commands = pytest --doctest-modules {posargs:} +[testenv:nooptional] +setenv = + UNITTEST = true + PYTHONPATH = $PYTHONPATH:.. +deps = + cython + -rrequirements-required.txt +commands = + pytest {posargs:cephadm/tests/test_ssh.py} + + [testenv:mypy] setenv = MYPYPATH = {toxinidir}/.. -- 2.39.5