From 89e7afbf74ffbbb54dd892bf2c4245aedee2a832 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 9 Dec 2014 11:10:24 -0600 Subject: Remove blanket excepts from plugins and lint This removes most blanket except: clauses from all plugins, including the base plugin libraries, and bcfg2-lint. The few that remain should all be necessary. Most of the changes were quite minor, but this did require some restructuring of the CfgPrivateKeyCreator; as a result, the tests for that module were rewritten. --- .../TestPlugins/TestCfg/TestCfgGenshiGenerator.py | 2 +- .../TestCfg/TestCfgPrivateKeyCreator.py | 94 ++++++++++++---------- .../TestServer/TestPlugins/TestCfg/Test_init.py | 2 +- .../Testlib/TestServer/TestPlugins/TestMetadata.py | 7 -- .../TestServer/TestPlugins/TestProperties.py | 2 +- testsuite/Testsrc/test_code_checks.py | 5 +- testsuite/common.py | 27 +++++++ testsuite/install.sh | 2 +- 8 files changed, 88 insertions(+), 53 deletions(-) (limited to 'testsuite') diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgGenshiGenerator.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgGenshiGenerator.py index b667d417a..e2636908e 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgGenshiGenerator.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgGenshiGenerator.py @@ -129,7 +129,7 @@ class TestCfgGenshiGenerator(TestCfgGenerator): encoding=Bcfg2.Options.setup.encoding) cgg.loader.reset_mock() - cgg.loader.load.side_effect = OSError + cgg.loader.load.side_effect = TemplateError("test") self.assertRaises(PluginExecutionError, cgg.handle_event, event) cgg.loader.load.assert_called_with( diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgPrivateKeyCreator.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgPrivateKeyCreator.py index d64bbaabf..45945911f 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgPrivateKeyCreator.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/TestCfgPrivateKeyCreator.py @@ -2,6 +2,7 @@ import os import sys import lxml.etree from mock import Mock, MagicMock, patch +from Bcfg2.Compat import StringIO from Bcfg2.Server.Plugins.Cfg import CfgCreationError from Bcfg2.Server.Plugins.Cfg.CfgPrivateKeyCreator import * from Bcfg2.Server.Plugin import PluginExecutionError @@ -29,24 +30,25 @@ class TestCfgPrivateKeyCreator(TestXMLCfgCreator): test_obj = CfgPrivateKeyCreator should_monitor = False + def setUp(self): + TestXMLCfgCreator.setUp(self) + set_setup_default("cfg_category", "category") + @patch("Bcfg2.Server.Plugins.Cfg.CfgPublicKeyCreator.get_cfg", Mock()) def get_obj(self, name=None, fam=None): return TestXMLCfgCreator.get_obj(self, name=name) @patch("shutil.rmtree") - @patch("tempfile.mkdtemp") - def test__gen_keypair(self, mock_mkdtemp, mock_rmtree): + def _gen_keypair(self, mock_mkdtemp, mock_rmtree): pkc = self.get_obj() pkc.cmd = Mock() pkc.XMLMatch = Mock() - mock_mkdtemp.return_value = datastore metadata = Mock() exc = Mock() exc.success = True pkc.cmd.run.return_value = exc - spec = lxml.etree.Element("PrivateKey") pkc.XMLMatch.return_value = spec def reset(): @@ -82,52 +84,62 @@ class TestCfgPrivateKeyCreator(TestXMLCfgCreator): mock_rmtree.assert_called_with(datastore) @patch("shutil.rmtree") + @patch("tempfile.mkdtemp") @patch("%s.open" % builtins) - def test_create_data(self, mock_open, mock_rmtree): - pkc = self.get_obj() - pkc.XMLMatch = Mock() - pkc.get_specificity = Mock() - # in order to make ** magic work in older versions of python, - # get_specificity() must return an actual dict, not just a - # Mock object that works like a dict. in order to test that - # the get_specificity() return value is being used - # appropriately, we put some dummy data in it and test for - # that data - pkc.get_specificity.side_effect = lambda m: dict(group="foo") - pkc._gen_keypair = Mock() - privkey = os.path.join(datastore, "privkey") - pkc._gen_keypair.return_value = privkey - pkc.pubkey_creator = Mock() - pkc.pubkey_creator.get_filename.return_value = "pubkey.filename" + def _create_private_key(self, expected, mock_open, mock_mkdtemp, + mock_rmtree, spec=None): + pkc = self.get_obj(name="/home/foo/.ssh/id_rsa/privkey.xml") + pkc.cmd = MockExecutor() + pkc.pubkey_creator.write_data = Mock() pkc.write_data = Mock() + mock_mkdtemp.return_value = datastore + + if spec is None: + pkc.xdata = lxml.etree.Element("PrivateKey") + else: + pkc.xdata = spec + + privkey_filename = os.path.join(datastore, "privkey") + pubkey_filename = os.path.join(datastore, "privkey.pub") entry = lxml.etree.Element("Path", name="/home/foo/.ssh/id_rsa") metadata = Mock() + metadata.group_in_category.return_value = "foo" - def open_read_rv(): - mock_open.return_value.read.side_effect = lambda: "privatekey" - return "ssh-rsa publickey foo@bar.com" + def open_key(fname): + if fname == privkey_filename: + return StringIO("privatekey") + elif fname == pubkey_filename: + return StringIO("ssh-rsa publickey foo@bar.com") + else: + self.fail("Unexpected open call: %s" % fname) - def reset(): - mock_open.reset_mock() - mock_rmtree.reset_mock() - pkc.XMLMatch.reset_mock() - pkc.get_specificity.reset_mock() - pkc._gen_keypair.reset_mock() - pkc.pubkey_creator.reset_mock() - pkc.write_data.reset_mock() - mock_open.return_value.read.side_effect = open_read_rv + mock_open.side_effect = open_key - reset() self.assertEqual(pkc.create_data(entry, metadata), "privatekey") - pkc.XMLMatch.assert_called_with(metadata) - pkc.get_specificity.assert_called_with(metadata) - pkc._gen_keypair.assert_called_with(metadata, - pkc.XMLMatch.return_value) self.assertItemsEqual(mock_open.call_args_list, - [call(privkey + ".pub"), call(privkey)]) - pkc.pubkey_creator.get_filename.assert_called_with(group="foo") + [call(pubkey_filename), call(privkey_filename)]) + self.assertItemsEqual( + pkc.cmd.calls[0]['command'], + ['ssh-keygen', '-f', privkey_filename] + expected) + metadata.group_in_category.assert_called_with("category") pkc.pubkey_creator.write_data.assert_called_with( - "ssh-rsa publickey pubkey.filename\n", group="foo") - pkc.write_data.assert_called_with("privatekey", group="foo") + "ssh-rsa publickey /home/foo/.ssh/id_rsa.pub/id_rsa.pub.G50_foo\n", + group="foo", prio=50) + pkc.write_data.assert_called_with("privatekey", group="foo", prio=50) mock_rmtree.assert_called_with(datastore) + + def test_create_data(self): + pass + + def test_create_private_key_defaults(self): + self._create_private_key(['-t', 'rsa', '-N', '']) + + def test_create_private_key_spec(self): + spec = lxml.etree.Element("PrivateKey") + lxml.etree.SubElement(spec, "Params", bits="768", type="dsa") + passphrase = lxml.etree.SubElement(spec, "Passphrase") + passphrase.text = "foo" + + self._create_private_key(['-t', 'dsa', '-b', '768', '-N', 'foo'], + spec=spec) diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/Test_init.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/Test_init.py index 1b55beded..507f0c9c2 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/Test_init.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestCfg/Test_init.py @@ -726,7 +726,7 @@ class TestCfgEntrySet(TestEntrySet): # test failure to create data reset() - creator.create_data.side_effect = OSError + creator.create_data.side_effect = CfgCreationError self.assertRaises(PluginExecutionError, eset._create_data, entry, metadata) diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py index d3fa15236..f2721c9ea 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestMetadata.py @@ -519,13 +519,6 @@ class TestMetadata(_TestMetadata, TestClientRunHooks, TestDatabaseBacked): os.path.join(metadata.data, "clients.xml"), metadata) - mock_get_fam.reset_mock() - fam = Mock() - fam.AddMonitor = Mock(side_effect=IOError) - mock_get_fam.return_value = fam - self.assertRaises(Bcfg2.Server.Plugin.PluginInitError, - self.get_obj, core=core) - @patch('os.makedirs', Mock()) @patch('%s.open' % builtins) def test_init_repo(self, mock_open): diff --git a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py index 159dc6e66..36baee899 100644 --- a/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py +++ b/testsuite/Testsrc/Testlib/TestServer/TestPlugins/TestProperties.py @@ -124,7 +124,7 @@ class TestJSONPropertyFile(TestFileBacked, TestPropertyFile): mock_dumps.assert_called_with(pf.json) mock_dumps.reset_mock() - mock_dumps.side_effect = ValueError + mock_dumps.side_effect = TypeError self.assertRaises(PluginExecutionError, pf.validate_data) mock_dumps.assert_called_with(pf.json) diff --git a/testsuite/Testsrc/test_code_checks.py b/testsuite/Testsrc/test_code_checks.py index 79eff7959..ba4b19d1c 100644 --- a/testsuite/Testsrc/test_code_checks.py +++ b/testsuite/Testsrc/test_code_checks.py @@ -49,7 +49,10 @@ contingent_checks = { ["CfgEncryptedCheetahGenerator.py"]}, ("M2Crypto", "jinja2"): {"lib/Bcfg2/Server/Plugins/Cfg": ["CfgEncryptedJinja2Generator.py"]}, - } + ("mercurial",): {"lib/Bcfg2/Server/Plugins": ["Hg.py"]}, + ("guppy",): {"lib/Bcfg2/Server/Plugins": ["Guppy.py"]}, + ("boto",): {"lib/Bcfg2/Server/Plugins": ["AWSTags.py"]}, +} # perform only error checking on the listed files error_checks = { diff --git a/testsuite/common.py b/testsuite/common.py index fc2397560..4c7337e0d 100644 --- a/testsuite/common.py +++ b/testsuite/common.py @@ -14,6 +14,7 @@ import sys import codecs import lxml.etree import Bcfg2.Options +import Bcfg2.Utils from mock import patch, MagicMock, _patch, DEFAULT try: from unittest2 import skip, skipIf, skipUnless, TestCase @@ -119,6 +120,29 @@ else: return codecs.unicode_escape_decode(s)[0] +class MockExecutor(object): + """mock object for :class:`Bcfg2.Utils.Executor` objects.""" + def __init__(self, timeout=None): + self.timeout = timeout + + # variables that can be set to control the result returned + self.stdout = '' + self.stderr = '' + self.retval = 0 + + # variables that record how run() was called + self.calls = [] + + def run(self, command, inputdata=None, timeout=None, **kwargs): + self.calls.append({"command": command, + "inputdata": inputdata, + "timeout": timeout or self.timeout, + "kwargs": kwargs}) + + return Bcfg2.Utils.ExecutorResult(self.stdout, self.stderr, + self.retval) + + class Bcfg2TestCase(TestCase): """ Base TestCase class that inherits from :class:`unittest.TestCase`. This class adds @@ -138,6 +162,9 @@ class Bcfg2TestCase(TestCase): if cls.capture_stderr: sys.stderr = cls._stderr + if hasattr(TestCase, "assertCountEqual"): + assertItemsEqual = assertCountEqual + def assertXMLEqual(self, el1, el2, msg=None): """ Test that the two XML trees given are equal. """ if msg is None: diff --git a/testsuite/install.sh b/testsuite/install.sh index bbbd9ae76..42d5bbadb 100755 --- a/testsuite/install.sh +++ b/testsuite/install.sh @@ -17,7 +17,7 @@ if [[ "$WITH_OPTIONAL_DEPS" == "yes" ]]; then sudo apt-get install -y yum libaugeas0 augeas-lenses libacl1-dev libssl-dev pip install --use-mirrors PyYAML pyinotify boto pylibacl 'django<1.5' \ - Jinja2 + Jinja2 mercurial guppy easy_install https://fedorahosted.org/released/python-augeas/python-augeas-0.4.1.tar.gz if [[ ${PYVER:0:1} == "2" ]]; then # django supports py3k, but South doesn't, and the django bits -- cgit v1.2.3-1-g7c22