def test_io_output_processing_is_raising_exception_when_invalid_type_returned_in_debug_mode( self): """ Error handling - when level is "debug", then we should be raising exceptions Variant: returned invalid type (not a STR - returned INT) """ mocked_output = [] io = IO() io.set_log_level('debug') io._stderr = io._stdout = lambda txt: mocked_output.append(txt) def processor_that_raises_exceptions(txt, origin): return 123456 # noinspection PyTypeChecker io.add_output_processor(processor_that_raises_exceptions) with self.assertRaises(Exception): io.info( 'Face the facts, no thanks, "Your passport lacks stamps Please go back for war, ' + 'torture and the death camps" Join the ranks, labeled as illegal people, Cursed by those who ' + 'suck blood from golden calf’s nipple')
def test_io_output_processing_does_not_break_on_exception_in_processing_method_when_error_level_is_not_debug( self): """ Verify error handling - when level is not "debug", then no any error should be present from processors because we cannot mess with the I/O that is written to the console """ mocked_output = [] io = IO() io.set_log_level('info') io._stderr = io._stdout = lambda txt: mocked_output.append(txt) def processor_that_raises_exceptions(txt, origin): raise Exception('Hello') io.add_output_processor(processor_that_raises_exceptions) io.info( '26 Jan 1932 4000 mainly Jewish tenants in New York attacked police reserve forces who were trying ' + 'to evict 17 tenants. The mob was led by women on rooftops who directed the action with megaphones ' + 'and hurled missiles at police.') self.assertIn('were trying to evict 17 tenants', str(mocked_output))
def test_is_log_level_at_least_info(self): """Test error level comparison Covers: IO.set_log_level() and IO.is_log_level_at_least() """ io = IO() io.set_log_level('info') self.assertFalse(io.is_log_level_at_least('debug')) self.assertTrue(io.is_log_level_at_least('info')) self.assertTrue(io.is_log_level_at_least('warning')) self.assertTrue(io.is_log_level_at_least('fatal'))
def main(): io = IO() try: args = WaitForOutputApp.parse_args() io.set_log_level(args['log_level']) WaitForOutputApp(container=args['container'], command=args['command'], pattern=args['pattern'], timeout=int(args['timeout']), io=io) \ .main() except ResultSignal as signal: io.info(signal.message) if signal.exit_code == 0 else io.error( signal.message) sys.exit(signal.exit_code)
def test_io_output_processing_is_raising_exception_in_debug_mode(self): """ Error handling - when level is "debug", then we should be raising exceptions """ mocked_output = [] io = IO() io.set_log_level('debug') io._stderr = io._stdout = lambda txt: mocked_output.append(txt) def processor_that_raises_exceptions(txt, origin): raise Exception('Hello') io.add_output_processor(processor_that_raises_exceptions) with self.assertRaises(Exception): io.info('There will be no shelter here')
def test_io_output_processing_changes_output(self): """ Tests adding "[stdout]" and "[stderr]" prefixes to the output """ mocked_output = [] io = IO() io.set_log_level('info') io._stderr = io._stdout = lambda txt: mocked_output.append(txt) # add a processor that will append origin - "stdout" or "stderr" io.add_output_processor( lambda txt, origin: '[{}]: {}'.format(origin, txt)) io.info('Hello from stdout') io.error('Hello from stderr') mocked_output_as_str = " ".join(mocked_output) self.assertIn('[stdout]: \x1b', mocked_output_as_str) self.assertIn('[stderr]: \x1b', mocked_output_as_str)
def test_set_log_level_cannot_set_invalid_log_level(self): """Checks validation in IO.set_log_level()""" io = IO() self.assertRaises(Exception, lambda: io.set_log_level('strikebreaker'))
class Controller(object): """ Constructs application context and passes actions to given services that are taking care about the processing """ project_dirs: list runner: Runner repository: Repository config_loader: ConfigLoader io: IO def __init__(self, project_dir: str, server_port: int, server_path_prefix: str, db_path: str, wait_time: int, timeout: int, log_level: str): self.io = IO() self.io.set_log_level(log_level) self.project_dirs = self._combine_project_dirs(project_dir) self.config_loader = ConfigLoader(self.project_dirs, self.io) self.repository = Repository(self.project_dirs, db_path) self.runner = Runner(dirs=self.project_dirs, config_loader=self.config_loader, repository=self.repository, timeout=timeout, wait_time=wait_time, io=self.io) self.scheduler = Scheduler(self.runner, self.repository, self.io) def list_enabled_configs(self) -> List[str]: return self.repository.get_configured_checks(with_disabled=False) def list_available_checks(self) -> List[str]: return self.repository.get_available_checks() def list_all_configs(self) -> List[str]: return self.repository.get_configured_checks(with_disabled=True) def spawn_threaded_application(self, refresh_time: int) -> None: """ Spawns a background worker """ self.scheduler.schedule_jobs_in_background(every_seconds=refresh_time) @staticmethod def get_version() -> dict: """ Gets Infracheck version """ return {"version": get_version(), "python": sys.version} def retrieve_checks(self) -> ExecutedChecksResultList: """ Only retrieves results of last checking """ return self.runner.get_checks_results(self.list_enabled_configs()) def perform_checks(self) -> ExecutedChecksResultList: """ Runs and returns results synchronously """ configs = self.list_enabled_configs() self.runner.run_checks(configs) return self.runner.get_checks_results(configs) @staticmethod def _combine_project_dirs(project_dir: str) -> list: paths = [ # directory specified by eg. the "--directory" commandline parameter project_dir, # standalone application running from cloned repository os.path.dirname(os.path.realpath(__file__)) + '/../', # official docker container '/app', '/data', # current directory os.getcwd(), ] return list( filter(lambda path: os.path.isdir(path + '/configured'), paths))