def run(self, args: dict = None): args = setup_args(args, self.DEFAULTS, self.get_args) # After this setup we assume args dictionary has all keys # defined in self.DEFAULTS self.log.set_loglevel(args['loglevel']) try: MongoAccess.set_config_file(args['mongo_config']) self.inv = InventoryMgr() self.inv.log.set_loglevel(args['loglevel']) self.inv.set_collections(args['inventory']) self.conf = Configuration() except FileNotFoundError as e: return False, 'Mongo configuration file not found: {}'\ .format(str(e)) scan_plan = self.get_scan_plan(args) if scan_plan.clear or scan_plan.clear_all: self.inv.clear(scan_plan) self.conf.log.set_loglevel(scan_plan.loglevel) env_name = scan_plan.env self.conf.use_env(env_name) # generate ScanObject Class and instance. scanner = Scanner() scanner.log.set_loglevel(args['loglevel']) scanner.set_env(env_name) scanner.found_errors[env_name] = False # decide what scanning operations to do inventory_only = scan_plan.inventory_only links_only = scan_plan.links_only cliques_only = scan_plan.cliques_only monitoring_setup_only = scan_plan.monitoring_setup_only run_all = False if inventory_only or links_only or cliques_only \ or monitoring_setup_only else True # setup monitoring server monitoring = \ self.inv.is_feature_supported(env_name, EnvironmentFeatures.MONITORING) if monitoring: self.inv.monitoring_setup_manager = \ MonitoringSetupManager(env_name) self.inv.monitoring_setup_manager.server_setup() # do the actual scanning try: if inventory_only or run_all: scanner.run_scan(scan_plan.scanner_type, scan_plan.obj, scan_plan.id_field, scan_plan.child_id, scan_plan.child_type) if links_only or run_all: scanner.scan_links() if cliques_only or run_all: scanner.scan_cliques() if monitoring: if monitoring_setup_only: self.inv.monitoring_setup_manager.simulate_track_changes() if not (inventory_only or links_only or cliques_only): scanner.deploy_monitoring_setup() except ScanError as e: return False, "scan error: " + str(e) SshConnection.disconnect_all() status = 'ok' if not scanner.found_errors.get(env_name, False) \ else 'errors detected' if status == 'ok' and scan_plan.object_type == "environment": self.mark_env_scanned(scan_plan.env) self.log.info('Scan completed, status: {}'.format(status)) return True, status
class TestScanner(TestScan): def setUp(self): super().setUp() ScanMetadataParser.parse_metadata_file = \ MagicMock(return_value=METADATA) FindLinksMetadataParser.parse_metadata_file = \ MagicMock(return_value=LINK_FINDERS_METADATA) self.scanner = Scanner() self.scanner.set_env(self.env) MonitoringSetupManager.create_setup = MagicMock() self.scanner.inv.monitoring_setup_manager = \ MonitoringSetupManager(self.env) def test_check_type_env_without_environment_condition(self): result = self.scanner.check_type_env(TYPE_TO_FETCH_WITHOUT_ENV_CON) self.assertEqual( result, True, "Can't get true when the type_to_fetch " + "doesn't contain environment condition") def test_check_type_with_error_value(self): # store original method original_get_env_config = self.scanner.config.get_env_config # mock get_env_config method self.scanner.config.get_env_config =\ MagicMock(return_value=CONFIGURATIONS) result = self.scanner.check_type_env(TYPE_TO_FETCH_WITH_ERROR_VALUE) # reset get_env_config method self.scanner.config.get_env_config = original_get_env_config self.assertEqual( result, False, "Can't get false when the type_to_fetch " + "contain error value") def test_check_type_env_without_mechanism_drivers_in_env_config(self): # store original method original_get_env_config = self.scanner.config.get_env_config # mock get_env_config_method self.scanner.config.get_env_config =\ MagicMock(return_value=CONFIGURATIONS_WITHOUT_MECHANISM_DRIVERS) result = self.scanner.check_type_env(TYPE_TO_FETCH) # reset get_env_config method self.scanner.check_type_env = original_get_env_config self.assertEqual( result, False, "Can't get false when configuration " + "doesn't contain mechanism drivers") def test_check_type_env_with_wrong_mech_drivers_in_env_condition(self): # store original method original_get_env_config = self.scanner.config.get_env_config # mock get_env_config_method self.scanner.config.get_env_config =\ MagicMock(return_value=CONFIGURATIONS) result = self.scanner.\ check_type_env(TYPE_TO_FETCH_WITH_WRONG_ENVIRONMENT_CONDITION) # reset get_env_config method self.scanner.check_type_env = original_get_env_config self.assertEqual( result, False, "Can't get false when the mechanism " + "drivers in type_to_fetch " + "don't exist in configurations") def test_check_type_env(self): # store original method original_get_env_config = self.scanner.config.get_env_config # mock method self.scanner.config.get_env_config =\ MagicMock(return_value=CONFIGURATIONS) result = self.scanner.check_type_env(TYPE_TO_FETCH) # reset method self.scanner.config.get_env_config = original_get_env_config self.assertEqual(result, True, "Can't get True when the type_to_fetch is correct") def test_scan_error_type(self): # store original method original_check_type_env = self.scanner.check_type_env # mock method self.scanner.check_type_env = MagicMock(return_value=False) result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) # reset method self.scanner.check_type_env = original_check_type_env self.assertEqual(result, [], "Can't get [], when the type_to_fetch is wrong") def test_scan_type_without_parent_id(self): try: self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT_WITHOUT_ID, ID_FIELD) self.fail("Can't get error when the parent " + "doesn't contain id attribute") except: pass @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_with_get_exception(self, fetcher_get): fetcher_get.side_effect = Exception("get exception") try: self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.fail( "Can't get exception when fetcher.get throws an exception") except: pass @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_without_master_parent(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITHOUT_MASTER_PARENT_IN_DB # store original get_by_id original_get_by_id = self.scanner.inv.get_by_id original_set = self.scanner.inv.set # mock methods self.scanner.inv.get_by_id = MagicMock(return_value=[]) result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) # reset methods self.scanner.inv.get_by_id = original_get_by_id self.scanner.inv.set = original_set self.assertEqual( result, [], "Can't get [], when the master parent " + "doesn't exist in database") @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_with_master_parent(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITH_MASTER_PARENT_IN_DB # store original methods original_get_by_id = self.scanner.inv.get_by_id original_set = self.scanner.inv.set # mock methods self.scanner.inv.get_by_id = MagicMock(return_value=MASTER_PARENT) self.scanner.inv.set = MagicMock() self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.assertEqual(self.scanner.inv.set.call_count, 2, "Can't create additional folder") self.assertNotIn("master_parent_type", DB_RESULTS_WITH_MASTER_PARENT_IN_DB, "Can't delete the master_parent_type") self.assertNotIn("master_parent_id", DB_RESULTS_WITH_MASTER_PARENT_IN_DB, "Can't delete the master_parent_id") # reset methods self.scanner.inv.get_by_id = original_get_by_id self.scanner.inv.set = original_set @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_with_in_project(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITH_PROJECT # store original method original_set = self.scanner.inv.set original_get_by_id = self.scanner.inv.get_by_id # mock method self.scanner.inv.set = MagicMock() self.scanner.inv.get_by_id = MagicMock(return_value=PARENT) self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.assertIn("projects", DB_RESULTS_WITH_PROJECT[0], "Can't get the projects from DB result") self.assertNotIn(PROJECT_KEY, DB_RESULTS_WITH_PROJECT[0], "Can't delete the project key in the object") self.scanner.inv.set = original_set self.scanner.inv.get_by_id = original_get_by_id @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_without_create_object(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITHOUT_CREATE_OBJECT original_set = self.scanner.inv.set original_get_by_id = self.scanner.inv.get_by_id self.scanner.inv.set = MagicMock() self.scanner.inv.get_by_id = MagicMock(return_value=PARENT) self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.assertEqual(self.scanner.inv.set.call_count, 0, "Set the object when the create object is false") self.scanner.inv.set = original_set self.scanner.inv.get_by_id = original_get_by_id @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_with_create_object(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT original_set = self.scanner.inv.set original_get_by_id = self.scanner.inv.get_by_id self.scanner.inv.set = MagicMock() self.scanner.inv.get_by_id = MagicMock(return_value=PARENT) self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.assertEqual(self.scanner.inv.set.call_count, 1, "Set the object when the create object is false") self.scanner.inv.set = original_set self.scanner.inv.get_by_id = original_get_by_id @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_with_children_scanner(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT original_set = self.scanner.inv.set original_get_by_id = self.scanner.inv.get_by_id original_queue_for_scan = self.scanner.queue_for_scan self.scanner.inv.set = MagicMock() self.scanner.inv.get_by_id = MagicMock(return_value=PARENT) self.scanner.queue_for_scan = MagicMock() self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.assertEqual(self.scanner.queue_for_scan.call_count, 1, "Can't put children scanner in the queue") self.scanner.inv.set = original_set self.scanner.inv.get_by_id = original_get_by_id self.scanner.queue_for_scan = original_queue_for_scan @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type_without_children_scanner(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT original_set = self.scanner.inv.set original_get_by_id = self.scanner.inv.get_by_id original_queue_for_scan = self.scanner.queue_for_scan self.scanner.inv.set = MagicMock() self.scanner.inv.get_by_id = MagicMock(return_value=PARENT) self.scanner.queue_for_scan = MagicMock() self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENV_WITHOUT_CHILDREN_FETCHER, PARENT, ID_FIELD) self.assertEqual(self.scanner.queue_for_scan.call_count, 0, "Can't put children scanner in the queue") self.scanner.inv.set = original_set self.scanner.inv.get_by_id = original_get_by_id self.scanner.queue_for_scan = original_queue_for_scan @patch("discover.fetchers.folder_fetcher.FolderFetcher.get") def test_scan_type(self, fetcher_get): fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT original_set = self.scanner.inv.set original_get_by_id = self.scanner.inv.get_by_id original_queue_for_scan = self.scanner.queue_for_scan self.scanner.inv.set = MagicMock() self.scanner.inv.get_by_id = MagicMock(return_value=PARENT) self.scanner.queue_for_scan = MagicMock() result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD) self.assertNotEqual(result, [], "Can't get children form scan_type") self.scanner.inv.set = original_set self.scanner.inv.get_by_id = original_get_by_id self.scanner.queue_for_scan = original_queue_for_scan def test_scan_with_limit_to_child_type(self): original_scan_type = self.scanner.scan_type original_get_scanner = self.scanner.get_scanner self.scanner.scan_type = MagicMock(return_value=[]) self.scanner.get_scanner = MagicMock(return_value=TYPES_TO_FETCH) limit_to_child_type = TYPES_TO_FETCH[0]['type'] self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT, limit_to_child_type=limit_to_child_type) # only scan the limit child type self.scanner.scan_type.assert_called_with(TYPES_TO_FETCH[0], PARENT, ID_FIELD) self.scanner.scan_type = original_scan_type self.scanner.get_scanner = original_get_scanner def test_scan_with_limit_to_child_id(self): original_scan_type = self.scanner.scan_type original_get_scanner = self.scanner.get_scanner self.scanner.get_scanner = MagicMock(return_value=TYPES_TO_FETCH) limit_to_child_id = SCAN_TYPE_RESULTS[0][ID_FIELD] self.scanner.scan_type = MagicMock(return_value=SCAN_TYPE_RESULTS) children = self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT, id_field=ID_FIELD, limit_to_child_id=limit_to_child_id) # only get the limit child self.assertEqual(children, SCAN_TYPE_RESULTS[0]) self.scanner.scan_type = original_scan_type self.scanner.get_scanner = original_get_scanner def test_scan(self): original_scan_type = self.scanner.scan_type original_get_scanner = self.scanner.get_scanner self.scanner.get_scanner = MagicMock(return_values=TYPES_TO_FETCH) result = self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT) self.assertEqual(PARENT, result, "Can't get the original parent after the scan") self.scanner.get_scanner = original_get_scanner self.scanner.scan_type = original_scan_type def test_run_scan(self): original_scan = self.scanner.scan original_scan_from_queue = self.scanner.scan_from_queue self.scanner.scan = MagicMock() self.scanner.scan_from_queue = MagicMock() self.scanner.run_scan(SCANNER_TYPE_FOR_ENV, PARENT, ID_FIELD, LIMIT_TO_CHILD_ID, LIMIT_TO_CHILD_TYPE) self.scanner.scan.assert_called_with(SCANNER_TYPE_FOR_ENV, PARENT, ID_FIELD, LIMIT_TO_CHILD_ID, LIMIT_TO_CHILD_TYPE) self.scanner.scan_from_queue.assert_any_call() self.scanner.scan = original_scan self.scanner.scan_from_queue = original_scan_from_queue @patch("discover.scanner.Scanner.scan") def test_scan_from_queue(self, scan): scan.return_value = [] Scanner.scan_queue = SCAN_QUEUE self.scanner.scan_from_queue() self.assertEqual(self.scanner.scan.call_count, QUEUE_SIZE, "Can't scan all the objects in the queue")