def run_plugins(plugins, available, source, check): """Execute plugins without the base class of ServiceCheck These are the remaining, non-service checking checks that do validation for various parts of a system. """ results = Results() for plugin in plugins: if isinstance(plugin, ServiceCheck): continue if not source_or_check_matches(plugin, source, check): continue logger.debug('Calling check %s' % plugin) if not set(plugin.requires).issubset(available): logger.debug('Skipping %s:%s because %s service(s) not running', plugin.__class__.__module__, plugin.__class__.__name__, ', '.join(set(plugin.requires) - available)) # Not providing a Result in this case because if a required # service isn't available then this could generate a lot of # false positives. else: for result in run_plugin(plugin, available): results.add(result) return results
def test_incorrect_output_type_cfg_file(mock_parse, mock_run, mock_service): """ Test the error message is user-friendly if the incorrect output type is provided in cfg file Related: https://bugzilla.redhat.com/show_bug.cgi?id=2079698 """ mock_service.return_value = (Results(), []) mock_run.return_value = Results() mock_parse.return_value = options fd, config_path = tempfile.mkstemp() os.close(fd) with open(config_path, "w") as fd: fd.write('[default]\n') fd.write('output_type=42\n') try: run = RunChecks([], config_path) f = io.StringIO() with redirect_stdout(f): run.run_healthcheck() assert "Unknown output-type" in f.getvalue() finally: os.remove(config_path)
def test_incorrect_delimiter_cfg_file(mock_parse, mock_run, mock_service, caplog): """ Test the error message is user-friendly if the incorrect delimiter is used in cfg file Related: https://bugzilla.redhat.com/show_bug.cgi?id=2079739 """ mock_service.return_value = (Results(), []) mock_run.return_value = Results() mock_parse.return_value = options fd, config_path = tempfile.mkstemp() os.close(fd) with open(config_path, "w") as fd: fd.write('[default]\n') fd.write('output_type;human\n') try: run = RunChecks([], config_path) with caplog.at_level(logging.ERROR): run.run_healthcheck() assert "contains parsing errors" in caplog.text finally: os.remove(config_path)
def limit_results(results, source, check): """Return ony those results which match source and/or check""" new_results = Results() for result in results.results: if result.source == source: if check is None or result.check == check: new_results.add(result) return new_results
def get_results(results, type): """Pull out the type of results I want to look at: owner, group or mode""" my_results = Results() for r in results.results: kw = r.kw if kw.get('type') != type: continue my_results.add(r) return my_results
def capture_results(f): """ Loop over check() and collect the results. """ results = Results() for result in f.check(): if result is not None: results.add(result) return results
def test_suppress_source(mock_find, mock_parse, mock_service): """ Test suppressing plugins """ global outputdata mock_service.return_value = (Results(), []) mock_parse.return_value = options mock_find.return_value = {'test': registry} outputdata = None fd, config_path = tempfile.mkstemp() os.close(fd) with open(config_path, "w") as fd: fd.write('[default]\n') fd.write('[excludes]\n') fd.write('source=test_suppress\n') try: run = RunChecks(['test'], config_path) run.run_healthcheck() assert len(outputdata) == 0 finally: os.remove(config_path)
def run_service_plugins(plugins, source, check): """Execute plugins with the base class of ServiceCheck This is a specialized check to use systemd to determine if a service is running or not. """ results = Results() available = [] for plugin in plugins: if not isinstance(plugin, ServiceCheck): continue # Try to save some time to not check dependent services if the # parent is down. if not set(plugin.requires).issubset(available): # A required service is not available. Either it hasn't been # checked yet or it isn't running. If not running break. running = True for result in results.results: if result.check in plugin.requires: # if not in available but in results the service failed running = False break if not running: logger.debug( 'Skipping %s:%s because %s service(s) not running', plugin.__class__.__module__, plugin.__class__.__name__, ', '.join(set(plugin.requires) - set(available))) continue logger.debug('Calling check %s', plugin) for result in plugin.check(): # always run the service checks so dependencies work if result is not None and result.result == constants.SUCCESS: available.append(plugin.service.service_name) if not source_or_check_matches(plugin, source, check): continue if result is not None: results.add(result) return results, set(available)
def test_cfg_file_debug_option(mock_parse, mock_run, mock_service): """ Test if the debug option is respected in the configuration file Related: https://bugzilla.redhat.com/show_bug.cgi?id=2079861 """ mock_service.return_value = (Results(), []) mock_run.return_value = Results() mock_parse.return_value = options fd, config_path = tempfile.mkstemp() os.close(fd) with open(config_path, "w") as fd: fd.write('[default]\n') fd.write('debug=True\n') try: run = RunChecks([], config_path) run.run_healthcheck() assert run.options.debug finally: os.remove(config_path)
def run_service_plugins(plugins, source, check): """Execute plugins with the base class of ServiceCheck This is a specialized check to use systemd to determine if a service is running or not. """ results = Results() available = [] for plugin in plugins: if not isinstance(plugin, ServiceCheck): continue logger.debug('Calling check %s', plugin) for result in plugin.check(): # always run the service checks so dependencies work if result is not None and result.result == constants.SUCCESS: available.append(plugin.service.service_name) if not source_or_check_matches(plugin, source, check): continue if result is not None: results.add(result) return results, set(available)
def test_options_merge(mock_parse, mock_run, mock_service): """ Test merging file-based and CLI options """ mock_service.return_value = (Results(), []) mock_run.return_value = Results() mock_parse.return_value = options fd, config_path = tempfile.mkstemp() os.close(fd) with open(config_path, "w") as fd: fd.write('[default]\n') fd.write('output_type=human\n') fd.write('indent=5\n') try: run = RunChecks(['ipahealthcheck.registry'], config_path) run.run_healthcheck() # verify two valus that have defaults with our overriden values assert run.options.output_type == 'human' assert run.options.indent == 5 finally: os.remove(config_path)
def limit_results(results, source, check): """Return ony those results which match source and/or check""" new_results = Results() for result in results.results: if check is None: # treat 'source' as prefix if _is_prefix_of_source(source, result.source): new_results.add(result) else: # when 'check' is given, match source fully if result.source == source and result.check == check: new_results.add(result) return new_results
def test_Result(): """ Test the `ipahealthcheck.plugin.Result` class """ registry = Registry() p = Plugin(registry) # Standard case of passing plugin to Result r = Result(p, constants.SUCCESS) kw = dict(key='value') r = Result(p, constants.SUCCESS, **kw) e = raises(TypeError, Result) assert str(e) == "__init__() missing 2 required positional arguments: " \ "'plugin' and 'result'" # Test passing source and check to Result. This is used for loading # a previous output. try: r = Result(None, constants.SUCCESS) except TypeError as e: assert str(e) == "source and check or plugin must be provided" try: r = Result(None, constants.SUCCESS, source='test') except TypeError as e: assert str(e) == "source and check or plugin must be provided" try: r = Result(None, constants.SUCCESS, check='test') except TypeError as e: assert str(e) == "source and check or plugin must be provided" r = Result(None, constants.SUCCESS, source='test', check='test') # Test results r = Result(p, constants.SUCCESS) results = Results() results.add(r) assert len(results) == 1 r = Result(p, constants.CRITICAL) results2 = Results() results2.add(r) assert len(results2) == 1 results.extend(results2) assert len(results) == 2 output = [x for x in results.output()] assert len(output) == 2 for x in output: assert x['source'] == 'ipahealthcheck.core.plugin' assert x['check'] == 'Plugin' assert x['result'] in (constants.getLevelName(constants.SUCCESS), constants.getLevelName(constants.CRITICAL)) assert len(x['kw']) == 0