From cd1b214d0d37ec277a48c750d3c065ea1275dff3 Mon Sep 17 00:00:00 2001 From: Aurelien Cedeyn Date: Tue, 19 Feb 2019 11:28:47 +0100 Subject: [PATCH] ActionTest.test_mix_errors_timeout: Fix timeout test ActionTest.test_mix_errors_timeout may fail depending on the local sshd version. The magic trick to trigger a sleep was a bit weak... To avoid this uncontroled behaviour, we add a temporary ssh configuration to trigger the timeout. We add globally this ssh configuration to be independent regarding the user configuration. Change-Id: I394e2087a58345b151d9ceb5eda5e7d7f517057e --- .../MilkCheckTests/EngineTests/ActionTest.py | 26 +++++++----- .../MilkCheckTests/EngineTests/ServiceTest.py | 8 ++++ tests/MilkCheckTests/UITests/CliTest.py | 10 +++++ tests/MilkCheckTests/__init__.py | 40 +++++++++++++++++++ 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/tests/MilkCheckTests/EngineTests/ActionTest.py b/tests/MilkCheckTests/EngineTests/ActionTest.py index 6a3e320..4e2a25b 100755 --- a/tests/MilkCheckTests/EngineTests/ActionTest.py +++ b/tests/MilkCheckTests/EngineTests/ActionTest.py @@ -17,12 +17,20 @@ DEP_ERROR, SKIPPED, WARNING from MilkCheck.Engine.Action import Action, ActionManager, action_manager_self from MilkCheck.Engine.Service import Service +from MilkCheckTests import setup_sshconfig, cleanup_sshconfig HOSTNAME = socket.gethostname().split('.')[0] + class ActionTest(TestCase): """Define the unit tests for the object action.""" + def setUp(self): + self.ssh_cfg = setup_sshconfig() + + def tearDown(self): + cleanup_sshconfig(self.ssh_cfg) + def test_desc(self): """Test action inherits 'desc'""" # No service description, no action description @@ -183,25 +191,25 @@ def test_nb_timeout_local(self): def test_mix_errors_timeout(self): """Test the result of mixed timeout and error actions.""" - cmd = 'echo "${SSH_CLIENT%% *}" | egrep "^(127.0.0.1|::1)$" || sleep 1' - action = Action(name='start', target='badname,%s,localhost' % HOSTNAME, - command=cmd, timeout=0.6) + + action = Action(name='start', target='badname,timeout,localhost', + command='/bin/true', timeout=0.9) action.errors = 1 service = Service('test_service') service.add_action(action) service.run('start') - self.assertEqual(action.nodes_error(), NodeSet("badname")) + self.assertEqual(action.nodes_error(), NodeSet('badname')) self.assertEqual(action.nb_errors(), 1) - self.assertEqual(action.nodes_timeout(), NodeSet(HOSTNAME)) + self.assertEqual(action.nodes_timeout(), NodeSet('timeout')) self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, ERROR) service.reset() action.errors = 2 service.run('start') - self.assertEqual(action.nodes_error(), NodeSet("badname")) + self.assertEqual(action.nodes_error(), NodeSet('badname')) self.assertEqual(action.nb_errors(), 1) - self.assertEqual(action.nodes_timeout(), NodeSet(HOSTNAME)) + self.assertEqual(action.nodes_timeout(), NodeSet('timeout')) self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, WARNING) @@ -209,9 +217,9 @@ def test_mix_errors_timeout(self): action.errors = 2 action.warnings = 2 service.run('start') - self.assertEqual(action.nodes_error(), NodeSet("badname")) + self.assertEqual(action.nodes_error(), NodeSet('badname')) self.assertEqual(action.nb_errors(), 1) - self.assertEqual(action.nodes_timeout(), NodeSet(HOSTNAME)) + self.assertEqual(action.nodes_timeout(), NodeSet('timeout')) self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, DONE) diff --git a/tests/MilkCheckTests/EngineTests/ServiceTest.py b/tests/MilkCheckTests/EngineTests/ServiceTest.py index 695cfe1..4b2b45f 100755 --- a/tests/MilkCheckTests/EngineTests/ServiceTest.py +++ b/tests/MilkCheckTests/EngineTests/ServiceTest.py @@ -22,12 +22,20 @@ from MilkCheck.Engine.BaseEntity import LOCKED, MISSING, CHECK, REQUIRE_WEAK, \ FILTER, REQUIRE +from MilkCheckTests import setup_sshconfig, cleanup_sshconfig + import socket HOSTNAME = socket.gethostname().split('.')[0] class ServiceTest(TestCase): """Define the unit tests for the object service.""" + def setUp(self): + self.ssh_cfg = setup_sshconfig() + + def tearDown(self): + cleanup_sshconfig(self.ssh_cfg) + def assert_near(self, target, delta, value): """Like self.assertTrue(target - delta < value < target + delta)""" low = target - delta diff --git a/tests/MilkCheckTests/UITests/CliTest.py b/tests/MilkCheckTests/UITests/CliTest.py index e25a70d..0477f0e 100755 --- a/tests/MilkCheckTests/UITests/CliTest.py +++ b/tests/MilkCheckTests/UITests/CliTest.py @@ -38,6 +38,9 @@ from MilkCheck.Engine.Service import ActionNotFoundError from MilkCheck.UI.OptionParser import InvalidOptionError +# SSH setup +from MilkCheckTests import setup_sshconfig, cleanup_sshconfig + HOSTNAME = socket.gethostname().split('.')[0] class MyOutput(StringIO): @@ -125,12 +128,18 @@ def setUp(self): sys.stdout = MyOutput() sys.stderr = MyOutput() + # Setup ssh configuration + self.ssh_cfg = setup_sshconfig() + def tearDown(self): '''Restore sys.stdout and sys.stderr''' sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ CallbackHandler._instance = None + # Cleanup ssh configuration + cleanup_sshconfig(self.ssh_cfg) + def _output_check(self, args, retcode, outexpected, errexpected=None, show_running=True, term_width=77): """ @@ -918,6 +927,7 @@ def test_custom_defines(self): class CLIConfigDirTests(CLICommon): def setUp(self): + CLICommon.setUp(self) self.manager = ServiceManager() ActionManager._instance = None diff --git a/tests/MilkCheckTests/__init__.py b/tests/MilkCheckTests/__init__.py index e69de29..c3c787c 100755 --- a/tests/MilkCheckTests/__init__.py +++ b/tests/MilkCheckTests/__init__.py @@ -0,0 +1,40 @@ +# Copyright CEA (2011-2019) +# Contributor: CEDEYN Aurelien +# +""" +Define common function for MilkCheck tests +""" + +import tempfile +import textwrap +from ClusterShell.Task import task_self + +def setup_sshconfig(): + """ Generate a custom ssh configuration for tests """ + ssh_cfg = tempfile.NamedTemporaryFile() + # Create a ssh_config file to manage timeout + # Get first default configuration + with (open('/etc/ssh/ssh_config', 'r')) as dflt_ssh_cfg: + ssh_cfg.write(dflt_ssh_cfg.read()) + dflt_ssh_cfg.close() + # Add custom configuration + ssh_cfg.write(textwrap.dedent(""" + Host * + UserKnownHostsFile /dev/null + StrictHostKeyChecking no + CheckHostIP no + LogLevel ERROR + Host timeout + proxycommand sleep 3 + """)) + ssh_cfg.flush() + task = task_self() + task.set_info('ssh_options', '-F {0}'.format(ssh_cfg.name)) + return ssh_cfg + + +def cleanup_sshconfig(ssh_cfg): + """ Remove ssh configuration file and restore task options """ + ssh_cfg.close() + task = task_self() + task.set_info('ssh_options', '')