|
| 1 | +""" |
| 2 | +The snowsaw CLI. |
| 3 | +
|
| 4 | +This is the main entry point of the public API. |
| 5 | +""" |
| 6 | +from argparse import ArgumentParser |
| 7 | +import glob |
| 8 | +import os |
| 9 | + |
| 10 | +from .config import ConfigReader, ReadingError |
| 11 | +from .dispatcher import Dispatcher, DispatchError |
| 12 | +from .logging import Level |
| 13 | +from .logging import Logger |
| 14 | +from .util import module |
| 15 | + |
| 16 | + |
| 17 | +def add_options(parser): |
| 18 | + """ |
| 19 | + Adds all options to the specified parser. |
| 20 | +
|
| 21 | + :param parser: The parser to add all options to |
| 22 | + :return: None |
| 23 | + """ |
| 24 | + parser.add_argument('-Q', '--super-quiet', dest='super_quiet', action='store_true', help='suppress almost all output') |
| 25 | + parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help='suppress most output') |
| 26 | + parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='enable verbose output') |
| 27 | + parser.add_argument('-s', '--snowblocks-directory', nargs=1, dest='snowblocks_directory', |
| 28 | + help='base snowblock directory to run all tasks of', metavar='SNOWBLOCKSDIR', required=True) |
| 29 | + parser.add_argument('-c', '--config-file', nargs=1, dest='config_file', help='run tasks for the specified snowblock', metavar='CONFIGFILE') |
| 30 | + parser.add_argument('-p', '--plugin', action='append', dest='plugins', default=[], help='load PLUGIN as a plugin', metavar='PLUGIN') |
| 31 | + parser.add_argument('--disable-core-plugins', dest='disable_core_plugins', action='store_true', help='disable all core plugins') |
| 32 | + parser.add_argument('--plugin-dir', action='append', dest='plugin_dirs', default=[], metavar='PLUGIN_DIR', help='load all plugins in PLUGIN_DIR') |
| 33 | + |
| 34 | + |
| 35 | +def read_config(config_file): |
| 36 | + """ |
| 37 | + Reads the specified configuration file. |
| 38 | +
|
| 39 | + :param config_file: The configuration file to read |
| 40 | + :return: The read configuration data |
| 41 | + """ |
| 42 | + reader = ConfigReader(config_file) |
| 43 | + return reader.get_config() |
| 44 | + |
| 45 | + |
| 46 | +def main(): |
| 47 | + """ |
| 48 | + Processes all parsed options and hands it over to the dispatcher for each snowblock. |
| 49 | +
|
| 50 | + :return: True if all tasks have been executed successfully, False otherwise |
| 51 | + """ |
| 52 | + log = Logger() |
| 53 | + try: |
| 54 | + parser = ArgumentParser() |
| 55 | + snowblock_config_filename = "snowblock.json" |
| 56 | + add_options(parser) |
| 57 | + options = parser.parse_args() |
| 58 | + |
| 59 | + if options.super_quiet: |
| 60 | + log.set_level(Level.WARNING) |
| 61 | + if options.quiet: |
| 62 | + log.set_level(Level.INFO) |
| 63 | + if options.verbose: |
| 64 | + log.set_level(Level.DEBUG) |
| 65 | + |
| 66 | + plugin_directories = list(options.plugin_dirs) |
| 67 | + if not options.disable_core_plugins: |
| 68 | + plugin_directories.append(os.path.join(os.path.dirname(__file__), "plugins")) |
| 69 | + plugin_paths = [] |
| 70 | + for directory in plugin_directories: |
| 71 | + for plugin_path in glob.glob(os.path.join(directory, "*.py")): |
| 72 | + plugin_paths.append(plugin_path) |
| 73 | + for plugin_path in options.plugins: |
| 74 | + plugin_paths.append(plugin_path) |
| 75 | + for plugin_path in plugin_paths: |
| 76 | + abspath = os.path.abspath(plugin_path) |
| 77 | + module.load(abspath) |
| 78 | + |
| 79 | + if options.config_file: |
| 80 | + snowblocks = [os.path.basename(os.path.dirname(options.config_file[0]))] |
| 81 | + else: |
| 82 | + snowblocks = [snowblock for snowblock in os.listdir(options.snowblocks_directory[0]) |
| 83 | + if os.path.isdir(os.path.join(options.snowblocks_directory[0], snowblock))] |
| 84 | + |
| 85 | + for snowblock in snowblocks: |
| 86 | + if os.path.isfile(os.path.join(snowblock, snowblock_config_filename)): |
| 87 | + log.info("❄ {}".format(snowblock)) |
| 88 | + tasks = read_config(os.path.join(snowblock, snowblock_config_filename)) |
| 89 | + |
| 90 | + if not isinstance(tasks, list): |
| 91 | + raise ReadingError("Configuration file must be a list of tasks") |
| 92 | + |
| 93 | + dispatcher = Dispatcher(snowblock) |
| 94 | + success = dispatcher.dispatch(tasks) |
| 95 | + if success: |
| 96 | + log.info("==> All tasks executed successfully\n") |
| 97 | + else: |
| 98 | + raise DispatchError("\n==> Some tasks were not executed successfully") |
| 99 | + else: |
| 100 | + log.lowinfo("Skipped snowblock \"{}\": No configuration file found".format(snowblock)) |
| 101 | + except (ReadingError, DispatchError) as e: |
| 102 | + log.error("{}".format(e)) |
| 103 | + exit(1) |
| 104 | + except KeyboardInterrupt: |
| 105 | + log.error("\n==> Operation aborted") |
| 106 | + exit(1) |
0 commit comments