#!/usr/bin/env python """This tool verifies that all clients known to the server build without failures""" import os import sys import signal import fnmatch import logging import Bcfg2.Logger import Bcfg2.Server.Core from nose.core import TestProgram from nose.suite import LazySuite from unittest import TestCase class ClientTest(TestCase): """ A test case representing the build of all of the configuration for a single host. Checks that none of the build config entities has had a failure when it is building. Optionally ignores some config files that we know will cause errors (because they are private files we don't have access to, for instance) """ __test__ = False # Do not collect def __init__(self, bcfg2_core, client, ignore=None): TestCase.__init__(self) self.bcfg2_core = bcfg2_core self.client = client if ignore is None: self.ignore = dict() else: self.ignore = ignore def ignore_entry(self, tag, name): """ return True if an error on a given entry should be ignored """ if tag in self.ignore: if name in self.ignore[tag]: return True else: # try wildcard matching for pattern in self.ignore[tag]: if fnmatch.fnmatch(name, pattern): return True return False def shortDescription(self): return "Building configuration for %s" % self.client def runTest(self): """ run this individual test """ config = self.bcfg2_core.BuildConfiguration(self.client) failures = [] msg = ["Failures:"] for failure in config.xpath('//*[@failure]'): if not self.ignore_entry(failure.tag, failure.get('name')): failures.append(failure) msg.append("%s:%s: %s" % (failure.tag, failure.get("name"), failure.get("failure"))) assert len(failures) == 0, "\n".join(msg) def __str__(self): return "ClientTest(%s)" % self.client id = __str__ def get_sigint_handler(core): def hdlr(sig, frame): core.shutdown() os._exit(1) return hdlr def main(): optinfo = dict(noseopts=Bcfg2.Options.TEST_NOSEOPTS, test_ignore=Bcfg2.Options.TEST_IGNORE, validate=Bcfg2.Options.CFG_VALIDATION) optinfo.update(Bcfg2.Options.CLI_COMMON_OPTIONS) optinfo.update(Bcfg2.Options.SERVER_COMMON_OPTIONS) setup = Bcfg2.Options.OptionParser(optinfo) setup.hm = \ "bcfg2-test [options] [client] [client] [...]\nOptions:\n %s" % \ setup.buildHelpMessage() setup.parse(sys.argv[1:]) if setup['debug']: level = logging.DEBUG elif setup['verbose']: level = logging.INFO else: level = logging.WARNING Bcfg2.Logger.setup_logging("bcfg2-test", to_console=setup['verbose'] or setup['debug'], to_syslog=False, to_file=setup['logging'], level=level) if (setup['debug'] or setup['verbose']) and "-v" not in setup['noseopts']: setup['noseopts'].append("-v") core = Bcfg2.Server.Core.BaseCore(setup) signal.signal(signal.SIGINT, get_sigint_handler(core)) ignore = dict() for entry in setup['test_ignore']: tag, name = entry.split(":") try: ignore[tag].append(name) except KeyError: ignore[tag] = [name] core.fam.handle_events_in_interval(0.1) if setup['args']: clients = setup['args'] else: clients = core.metadata.clients def run_tests(): """ Run the test suite """ for client in clients: yield ClientTest(core, client, ignore) TestProgram(argv=sys.argv[0:1] + setup['noseopts'], suite=LazySuite(run_tests)) core.shutdown() os._exit(0) # pylint: disable=W0212 if __name__ == "__main__": sys.exit(main())