|
25 | 25 | ############################################################################### |
26 | 26 | import argparse |
27 | 27 | import datetime |
28 | | -import json |
29 | 28 | import logging |
30 | 29 | import os |
31 | 30 | import platform |
|
35 | 34 |
|
36 | 35 | from nodescraper.cli.constants import DEFAULT_CONFIG, META_VAR_MAP |
37 | 36 | from nodescraper.cli.dynamicparserbuilder import DynamicParserBuilder |
| 37 | +from nodescraper.cli.helper import ( |
| 38 | + generate_reference_config, |
| 39 | + get_plugin_configs, |
| 40 | + get_system_info, |
| 41 | + log_system_info, |
| 42 | + parse_describe, |
| 43 | + parse_gen_plugin_config, |
| 44 | +) |
38 | 45 | from nodescraper.cli.inputargtypes import ModelArgHandler, json_arg, log_path_arg |
39 | | -from nodescraper.configbuilder import ConfigBuilder |
40 | 46 | from nodescraper.configregistry import ConfigRegistry |
41 | 47 | from nodescraper.constants import DEFAULT_LOGGER |
42 | 48 | from nodescraper.enums import ExecutionStatus, SystemInteractionLevel, SystemLocation |
43 | | -from nodescraper.models import PluginConfig, SystemInfo |
| 49 | +from nodescraper.models import SystemInfo |
44 | 50 | from nodescraper.pluginexecutor import PluginExecutor |
45 | 51 | from nodescraper.pluginregistry import PluginRegistry |
46 | | -from nodescraper.resultcollators.tablesummary import TableSummary |
47 | 52 |
|
48 | 53 |
|
49 | 54 | def build_parser( |
@@ -257,111 +262,6 @@ def setup_logger(log_level: str = "INFO", log_path: str | None = None) -> loggin |
257 | 262 | return logger |
258 | 263 |
|
259 | 264 |
|
260 | | -def get_system_info(args: argparse.Namespace) -> SystemInfo: |
261 | | - """build system info object using args |
262 | | -
|
263 | | - Args: |
264 | | - args (argparse.Namespace): parsed args |
265 | | -
|
266 | | - Raises: |
267 | | - argparse.ArgumentTypeError: if system location arg is invalid |
268 | | -
|
269 | | - Returns: |
270 | | - SystemInfo: system info instance |
271 | | - """ |
272 | | - |
273 | | - if args.system_config: |
274 | | - system_info = args.system_config |
275 | | - else: |
276 | | - system_info = SystemInfo() |
277 | | - |
278 | | - if args.sys_name: |
279 | | - system_info.name = args.sys_name |
280 | | - |
281 | | - if args.sys_sku: |
282 | | - system_info.sku = args.sys_sku |
283 | | - |
284 | | - if args.sys_platform: |
285 | | - system_info.platform = args.sys_platform |
286 | | - |
287 | | - if args.sys_location: |
288 | | - try: |
289 | | - location = getattr(SystemLocation, args.sys_location) |
290 | | - except Exception as e: |
291 | | - raise argparse.ArgumentTypeError("Invalid input for system location") from e |
292 | | - |
293 | | - system_info.location = location |
294 | | - |
295 | | - return system_info |
296 | | - |
297 | | - |
298 | | -def get_plugin_configs( |
299 | | - plugin_config_input: list[str], |
300 | | - system_interaction_level: SystemInteractionLevel, |
301 | | - built_in_configs: dict[str, PluginConfig], |
302 | | - parsed_plugin_args: dict[str, argparse.Namespace], |
303 | | - plugin_subparser_map: dict[str, tuple[argparse.ArgumentParser, dict]], |
304 | | -) -> list[PluginConfig]: |
305 | | - """Build list of plugin configs based on input args |
306 | | -
|
307 | | - Args: |
308 | | - plugin_config_input (list[str]): list of plugin config inputs, can be paths to JSON files or built-in config names |
309 | | - system_interaction_level (SystemInteractionLevel): system interaction level, used to determine the type of actions that plugins can perform |
310 | | - built_in_configs (dict[str, PluginConfig]): built-in plugin configs, mapping from config name to PluginConfig instance |
311 | | - parsed_plugin_args (dict[str, argparse.Namespace]): parsed plugin arguments, mapping from plugin name to parsed args |
312 | | - plugin_subparser_map (dict[str, tuple[argparse.ArgumentParser, dict]]): plugin subparser map, mapping from plugin name to tuple of parser and model type map |
313 | | -
|
314 | | - Raises: |
315 | | - argparse.ArgumentTypeError: if system interaction level is invalid |
316 | | - argparse.ArgumentTypeError: if no plugin config found for a given input |
317 | | -
|
318 | | - Returns: |
319 | | - list[PluginConfig]: list of PluginConfig instances based on input args |
320 | | - """ |
321 | | - try: |
322 | | - system_interaction_level = getattr(SystemInteractionLevel, system_interaction_level) |
323 | | - except Exception as e: |
324 | | - raise argparse.ArgumentTypeError("Invalid input for system interaction level") from e |
325 | | - |
326 | | - base_config = PluginConfig(result_collators={str(TableSummary.__name__): {}}) |
327 | | - |
328 | | - base_config.global_args["system_interaction_level"] = system_interaction_level |
329 | | - |
330 | | - plugin_configs = [base_config] |
331 | | - |
332 | | - if plugin_config_input: |
333 | | - for config in plugin_config_input: |
334 | | - if os.path.exists(config): |
335 | | - plugin_configs.append(ModelArgHandler(PluginConfig).process_file_arg(config)) |
336 | | - elif config in built_in_configs: |
337 | | - plugin_configs.append(built_in_configs[config]) |
338 | | - else: |
339 | | - raise argparse.ArgumentTypeError(f"No plugin config found for: {config}") |
340 | | - |
341 | | - if parsed_plugin_args: |
342 | | - plugin_input_config = PluginConfig() |
343 | | - |
344 | | - for plugin, plugin_args in parsed_plugin_args.items(): |
345 | | - config = {} |
346 | | - model_type_map = plugin_subparser_map[plugin][1] |
347 | | - for arg, val in vars(plugin_args).items(): |
348 | | - if val is None: |
349 | | - continue |
350 | | - if arg in model_type_map: |
351 | | - model = model_type_map[arg] |
352 | | - if model in config: |
353 | | - config[model][arg] = val |
354 | | - else: |
355 | | - config[model] = {arg: val} |
356 | | - else: |
357 | | - config[arg] = val |
358 | | - plugin_input_config.plugins[plugin] = config |
359 | | - |
360 | | - plugin_configs.append(plugin_input_config) |
361 | | - |
362 | | - return plugin_configs |
363 | | - |
364 | | - |
365 | 265 | def process_args( |
366 | 266 | raw_arg_input: list[str], plugin_names: list[str] |
367 | 267 | ) -> tuple[list[str], dict[str, list[str]]]: |
@@ -401,183 +301,6 @@ def process_args( |
401 | 301 | return (top_level_args, plugin_arg_map) |
402 | 302 |
|
403 | 303 |
|
404 | | -def build_config( |
405 | | - config_reg: ConfigRegistry, |
406 | | - plugin_reg: PluginRegistry, |
407 | | - logger: logging.Logger, |
408 | | - plugins: Optional[list[str]] = None, |
409 | | - built_in_configs: Optional[list[str]] = None, |
410 | | -) -> PluginConfig: |
411 | | - """build a plugin config |
412 | | -
|
413 | | - Args: |
414 | | - config_reg (ConfigRegistry): config registry instance |
415 | | - plugin_reg (PluginRegistry): plugin registry instance |
416 | | - logger (logging.Logger): logger instance |
417 | | - plugins (Optional[list[str]], optional): list of plugin names to include. Defaults to None. |
418 | | - built_in_configs (Optional[list[str]], optional): list of built in config names to include. Defaults to None. |
419 | | -
|
420 | | - Returns: |
421 | | - PluginConfig: plugin config obf |
422 | | - """ |
423 | | - configs = [] |
424 | | - if plugins: |
425 | | - logger.info("Building config for plugins: %s", plugins) |
426 | | - config_builder = ConfigBuilder(plugin_registry=plugin_reg) |
427 | | - configs.append(config_builder.gen_config(plugins)) |
428 | | - |
429 | | - if built_in_configs: |
430 | | - logger.info("Retrieving built in configs: %s", built_in_configs) |
431 | | - for config in built_in_configs: |
432 | | - if config not in config_reg.configs: |
433 | | - logger.warning("No built in config found for name: %s", config) |
434 | | - else: |
435 | | - configs.append(config_reg.configs[config]) |
436 | | - |
437 | | - config = PluginExecutor.merge_configs(configs) |
438 | | - return config |
439 | | - |
440 | | - |
441 | | -def parse_describe( |
442 | | - parsed_args: argparse.Namespace, |
443 | | - plugin_reg: PluginRegistry, |
444 | | - config_reg: ConfigRegistry, |
445 | | - logger: logging.Logger, |
446 | | -): |
447 | | - """parse 'describe' cmd line argument |
448 | | -
|
449 | | - Args: |
450 | | - parsed_args (argparse.Namespace): parsed cmd line arguments |
451 | | - plugin_reg (PluginRegistry): plugin registry instance |
452 | | - config_reg (ConfigRegistry): config registry instance |
453 | | - logger (logging.Logger): logger instance |
454 | | - """ |
455 | | - if not parsed_args.name: |
456 | | - if parsed_args.type == "config": |
457 | | - print("Available built-in configs:") # noqa: T201 |
458 | | - for name in config_reg.configs: |
459 | | - print(f" {name}") # noqa: T201 |
460 | | - elif parsed_args.type == "plugin": |
461 | | - print("Available plugins:") # noqa: T201 |
462 | | - for name in plugin_reg.plugins: |
463 | | - print(f" {name}") # noqa: T201 |
464 | | - print(f"\nUsage: describe {parsed_args.type} <name>") # noqa: T201 |
465 | | - sys.exit(0) |
466 | | - |
467 | | - if parsed_args.type == "config": |
468 | | - if parsed_args.name not in config_reg.configs: |
469 | | - logger.error("No config found for name: %s", parsed_args.name) |
470 | | - sys.exit(1) |
471 | | - config_model = config_reg.configs[parsed_args.name] |
472 | | - print(f"Config Name: {parsed_args.name}") # noqa: T201 |
473 | | - print(f"Description: {getattr(config_model, 'desc', '')}") # noqa: T201 |
474 | | - print("Plugins:") # noqa: T201 |
475 | | - for plugin in getattr(config_model, "plugins", []): |
476 | | - print(f"\t{plugin}") # noqa: T201 |
477 | | - |
478 | | - elif parsed_args.type == "plugin": |
479 | | - if parsed_args.name not in plugin_reg.plugins: |
480 | | - logger.error("No plugin found for name: %s", parsed_args.name) |
481 | | - sys.exit(1) |
482 | | - plugin_class = plugin_reg.plugins[parsed_args.name] |
483 | | - print(f"Plugin Name: {parsed_args.name}") # noqa: T201 |
484 | | - print(f"Description: {getattr(plugin_class, '__doc__', '')}") # noqa: T201 |
485 | | - |
486 | | - sys.exit(0) |
487 | | - |
488 | | - |
489 | | -def parse_gen_plugin_config( |
490 | | - parsed_args: argparse.Namespace, |
491 | | - plugin_reg: PluginRegistry, |
492 | | - config_reg: ConfigRegistry, |
493 | | - logger: logging.Logger, |
494 | | -): |
495 | | - """parse 'gen_plugin_config' cmd line argument |
496 | | -
|
497 | | - Args: |
498 | | - parsed_args (argparse.Namespace): parsed cmd line arguments |
499 | | - plugin_reg (PluginRegistry): plugin registry instance |
500 | | - config_reg (ConfigRegistry): config registry instance |
501 | | - logger (logging.Logger): logger instance |
502 | | - """ |
503 | | - try: |
504 | | - config = build_config( |
505 | | - config_reg, plugin_reg, logger, parsed_args.plugins, parsed_args.built_in_configs |
506 | | - ) |
507 | | - |
508 | | - config.name = parsed_args.config_name.split(".")[0] |
509 | | - config.desc = "Auto generated config" |
510 | | - output_path = os.path.join(parsed_args.output_path, parsed_args.config_name) |
511 | | - with open(output_path, "w", encoding="utf-8") as out_file: |
512 | | - out_file.write(config.model_dump_json(indent=2)) |
513 | | - |
514 | | - logger.info("Config saved to: %s", output_path) |
515 | | - sys.exit(0) |
516 | | - except Exception: |
517 | | - logger.exception("Exception when building config") |
518 | | - sys.exit(1) |
519 | | - |
520 | | - |
521 | | -def log_system_info(log_path: str | None, system_info: SystemInfo, logger: logging.Logger): |
522 | | - """dump system info object to json log |
523 | | -
|
524 | | - Args: |
525 | | - log_path (str): path to log folder |
526 | | - system_info (SystemInfo): system object instance |
527 | | - """ |
528 | | - if log_path: |
529 | | - try: |
530 | | - with open( |
531 | | - os.path.join(log_path, "system_info.json"), "w", encoding="utf-8" |
532 | | - ) as log_file: |
533 | | - json.dump( |
534 | | - system_info.model_dump(mode="json", exclude_none=True), |
535 | | - log_file, |
536 | | - indent=2, |
537 | | - ) |
538 | | - except Exception as exp: |
539 | | - logger.error(exp) |
540 | | - |
541 | | - |
542 | | -def generate_reference_config(results, plugin_reg, logger, path): |
543 | | - plugin_config = PluginConfig() |
544 | | - plugins = {} |
545 | | - for obj in results: |
546 | | - data_model = obj.result_data.system_data |
547 | | - |
548 | | - plugin = plugin_reg.plugins.get(obj.result_data.collection_result.parent) |
549 | | - if not plugin.ANALYZER_ARGS: |
550 | | - logger.warning( |
551 | | - "Plugin: %s does not support reference config creation. No analyzer args defined.", |
552 | | - obj.source, |
553 | | - ) |
554 | | - continue |
555 | | - |
556 | | - args = None |
557 | | - try: |
558 | | - args = plugin.ANALYZER_ARGS.build_from_model(data_model) |
559 | | - except NotImplementedError as nperr: |
560 | | - logger.info(nperr) |
561 | | - continue |
562 | | - args.build_from_model(data_model) |
563 | | - plugins[obj.source] = {"analysis_args": {}} |
564 | | - plugins[obj.source]["analysis_args"] = args.model_dump(exclude_none=True) |
565 | | - plugin_config.plugins = plugins |
566 | | - |
567 | | - if not path: |
568 | | - path = os.path.join(os.getcwd(), "reference_config.json") |
569 | | - try: |
570 | | - with open(path, "w") as f: |
571 | | - json.dump( |
572 | | - plugin_config.model_dump(mode="json", exclude_none=True), |
573 | | - f, |
574 | | - indent=2, |
575 | | - ) |
576 | | - logger.info("Reference config written to: %s", path) |
577 | | - except Exception as exp: |
578 | | - logger.error(exp) |
579 | | - |
580 | | - |
581 | 304 | def main(arg_input: Optional[list[str]] = None): |
582 | 305 | """Main entry point for the CLI |
583 | 306 |
|
|
0 commit comments