async def cli_deps( filled_graph_db: ArangoGraphDB, message_bus: MessageBus, event_sender: InMemoryEventSender, foo_model: Model, task_queue: WorkerTaskQueue, worker: Tuple[WorkerTaskDescription, WorkerTaskDescription, WorkerTaskDescription], expander: TemplateExpander, config_handler: ConfigHandler, cert_handler: CertificateHandler, ) -> AsyncIterator[CLIDependencies]: db_access = DbAccess(filled_graph_db.db.db, event_sender, NoAdjust(), empty_config()) model_handler = ModelHandlerStatic(foo_model) config = empty_config(["--graphdb-database", "test", "--graphdb-username", "test", "--graphdb-password", "test"]) deps = CLIDependencies( message_bus=message_bus, event_sender=event_sender, db_access=db_access, model_handler=model_handler, worker_task_queue=task_queue, config=config, template_expander=expander, forked_tasks=Queue(), config_handler=config_handler, cert_handler=cert_handler, ) yield deps await deps.stop()
async def __update_config(self) -> None: # in case the internal configuration holds new properties, we update the existing config always. try: existing = await self.config_handler.get_config(ResotoCoreConfigId) empty = empty_config().json() updated = deep_merge(empty, existing.config) if existing else empty updated = migrate_config(updated) if existing is None or updated != existing.config: await self.config_handler.put_config( ConfigEntity(ResotoCoreConfigId, updated), False) log.info("Default resoto config updated.") except Exception as ex: log.error(f"Could not update resoto default configuration: {ex}", exc_info=ex) # make sure there is a default command configuration # note: this configuration is only created one time and never updated try: existing_commands = await self.config_handler.get_config( ResotoCoreCommandsConfigId) if existing_commands is None: await self.config_handler.put_config( ConfigEntity(ResotoCoreCommandsConfigId, CustomCommandsConfig().json()), False) log.info("Default resoto commands config updated.") except Exception as ex: log.error(f"Could not update resoto command configuration: {ex}", exc_info=ex)
async def test_validation() -> None: validate = CoreConfigHandler.validate_config_entry # empty config is valid assert validate({"config": {ResotoCoreRoot: {}}}) is None # expected json object but got 23 assert validate({"config": {ResotoCoreRoot: 23}}) is not None # validation fails, since ui-path does not exist assert validate({"config": { ResotoCoreRoot: { "api": { "ui_path": "n/a" } } }}) is not None # default configuration is valid assert validate({"config": { ResotoCoreRoot: empty_config().json() }}) is None # empty command config is fine assert validate({"config": {ResotoCoreCommandsRoot: {}}}) is None # 23 can not be parsed as command list pytest.raises(DeserializationError, validate, {"config": { ResotoCoreCommandsRoot: { "commands": 23 } }}) # valid entry can be read assert validate( {"config": { ResotoCoreCommandsRoot: CustomCommandsConfig().json() }}) is None
def core_config_handler(message_bus: MessageBus, task_queue: WorkerTaskQueue, config_handler: ConfigHandler) -> CoreConfigHandler: def on_exit() -> None: config_handler_exits.append(True) config = empty_config() return CoreConfigHandler(config, message_bus, task_queue, config_handler, on_exit)
async def test_default_workflow_triggers() -> None: workflows = {wf.name: wf for wf in TaskHandlerService.known_workflows(empty_config())} assert workflows["collect"].triggers == [EventTrigger("start_collect_workflow")] assert workflows["cleanup"].triggers == [EventTrigger("start_cleanup_workflow")] assert workflows["metrics"].triggers == [EventTrigger("start_metrics_workflow")] assert workflows["collect_and_cleanup"].triggers == [ EventTrigger("start_collect_and_cleanup_workflow"), TimeTrigger("0 * * * *"), ]
async def test_merge_process(event_sender: AnalyticsEventSender, graph_db: ArangoGraphDB, foo_kinds: List[Kind]) -> None: # set explicitly (is done in main explicitly as well) set_start_method("spawn") # wipe any existing data await graph_db.wipe() # store the model in db, so it can be loaded by the sub process graph_db.db.collection("model").insert_many([to_js(a) for a in foo_kinds]) # define args to parse for the sub process config = empty_config([ "--graphdb-username", "test", "--graphdb-password", "test", "--graphdb-database", "test" ]) # create sample graph data to insert graph = create_graph("test") await outer_edge_db(graph_db.db, "deferred_outer_edges").create_update_schema() async def iterator() -> AsyncGenerator[bytes, None]: for node in graph.nodes(): yield bytes(json.dumps(graph.nodes[node]), "utf-8") for from_node, to_node, data in graph.edges(data=True): yield bytes( json.dumps({ "from": from_node, "to": to_node, "edge_type": data["edge_type"] }), "utf-8") yield bytes( json.dumps({ "from_selector": { "node_id": "id_123" }, "to_selector": { "node_id": "id_456" }, "edge_type": "delete" }), "utf-8", ) result = await merge_graph_process(graph_db, event_sender, config, iterator(), timedelta(seconds=30), None, TaskId("test_task_123")) assert result == GraphUpdate(112, 1, 0, 212, 0, 0) elem = graph_db.db.collection("deferred_outer_edges").all().next() assert elem["_key"] == "test_task_123" assert elem["task_id"] == "test_task_123" assert elem["edges"][0] == { "from_node": "id_123", "to_node": "id_456", "edge_type": "delete" }
def test_not_existing(system_db: StandardDatabase, test_db: StandardDatabase) -> None: access = DbAccess(test_db, NoEventSender(), NoAdjust(), empty_config()) # foo db and pass does not exist foodb = ["--graphdb-username", "foo", "--graphdb-password", "test", "--graphdb-database", "foo"] system_db.delete_user("foo", ignore_missing=True) system_db.delete_database("foo", ignore_missing=True) access.connect(parse_args(foodb), timedelta(seconds=5), sleep_time=0.1) assert system_db.has_user("foo") assert system_db.has_database("foo")
def handler() -> TaskHandlerService: th = TaskHandlerService( running_task_db, job_db, message_bus, event_sender, subscription_handler, Scheduler(), cli, empty_config(), ) th.task_descriptions = [test_workflow] return th
def test_not_existing_and_default_root_account( local_client: ArangoClient, system_db: StandardDatabase, test_db: StandardDatabase ) -> None: access = DbAccess(test_db, NoEventSender(), NoAdjust(), empty_config()) # foo db and pass does not exist foodb = ["--graphdb-username", "foo", "--graphdb-password", "bombproof", "--graphdb-database", "foo"] system_db.delete_user("foo", ignore_missing=True) system_db.delete_database("foo", ignore_missing=True) access.connect(parse_args(foodb), timedelta(seconds=5), sleep_time=0.1) # The default root account is used and a valid password is given -> also the root account uses this password changed_root = local_client.db(username="******", password="******") # Rest the password to the default one, to reset the state before the test changed_root.replace_user("root", "", True)
async def task_handler( running_task_db: RunningTaskDb, job_db: JobDb, message_bus: MessageBus, event_sender: AnalyticsEventSender, subscription_handler: SubscriptionHandler, cli: CLI, test_workflow: Workflow, ) -> AsyncGenerator[TaskHandlerService, None]: config = empty_config() task_handler = TaskHandlerService( running_task_db, job_db, message_bus, event_sender, subscription_handler, Scheduler(), cli, config ) task_handler.task_descriptions = [test_workflow] cli.dependencies.lookup["task_handler"] = task_handler async with task_handler: yield task_handler
def test_bootstrap(test_db: StandardDatabase) -> None: with TemporaryDirectory() as tmpdir: tmp = Path(tmpdir) sd = test_db.collection("system_data") config = empty_config() # Delete any existing entry, so a new certificate needs to be created sd.delete("ca", ignore_missing=True) handler = CertificateHandler.lookup(config, test_db, tmp) ca = sd.get("ca") assert ca is not None # ensure the certificate in the database is the same as exposed by the handler ca_bytes, fingerprint = handler.authority_certificate assert ca_bytes == ca["certificate"].encode("utf-8") # a new handler will use the existing certificate handler2 = CertificateHandler.lookup(config, test_db, tmp) assert handler.authority_certificate == handler2.authority_certificate # but the host certificate will be different assert handler.host_certificate != handler2.host_certificate
def cert_handler() -> Iterator[CertificateHandler]: config = empty_config() key, certificate = bootstrap_ca() temp = TemporaryDirectory() yield CertificateHandler(config, key, certificate, Path(temp.name)) temp.cleanup()
def test_already_existing(test_db: StandardDatabase) -> None: access = DbAccess(test_db, NoEventSender(), NoAdjust(), empty_config()) # test db and user already exist testdb = ["--graphdb-username", "test", "--graphdb-password", "test", "--graphdb-database", "test"] access.connect(parse_args(testdb), timedelta(seconds=0.01), sleep_time=0.01)