Browse Source

Add cli.py

Bertrand Chenal 6 năm trước cách đây
mục cha
commit
ab6c919384
4 tập tin đã thay đổi với 138 bổ sung131 xóa
  1. 128 0
      byrd/cli.py
  2. 1 2
      byrd/config.py
  3. 3 129
      byrd/main.py
  4. 6 0
      byrd/utils.py

+ 128 - 0
byrd/cli.py

@@ -0,0 +1,128 @@
+import argparse
+import os
+
+from config import yaml_load,ConfigRoot
+from main import get_hosts_and_tasks, run_batch, info
+from utils import (enable_logging_color, log_handler, logger, ByrdException,
+                    ObjectDict, Env, abort)
+
+basedir, _ = os.path.split(__file__)
+PKG_DIR = os.path.join(basedir, 'pkg')
+
+
+
+def load_cfg(path, prefix=None):
+    load_sections = ('networks', 'tasks', 'auth', 'env')
+
+    if os.path.isfile(path):
+        logger.debug('Load config %s' % os.path.relpath(path))
+        cfg = yaml_load(open(path))
+        cfg = ConfigRoot.parse(cfg)
+    else:
+        raise ByrdException('Config file "%s" not found' % path)
+
+    # Define useful defaults
+    cfg.networks = cfg.networks or ObjectDict()
+    cfg.tasks = cfg.tasks or ObjectDict()
+
+    # Create backrefs between tasks to the local config
+    if cfg.get('tasks'):
+        cfg_cp = cfg.copy()
+        for k, v in cfg['tasks'].items():
+            v._cfg = cfg_cp
+
+
+    # Recursive load
+    if cfg.load:
+        cfg_path = os.path.dirname(path)
+        for item in cfg.load:
+            if item.get('file'):
+                rel_path = item.file
+                child_path = os.path.join(cfg_path, item.file)
+            elif item.get('pkg'):
+                rel_path = item.pkg
+                child_path = os.path.join(PKG_DIR, item.pkg)
+
+            if item.get('as'):
+                child_prefix = item['as']
+            else:
+                child_prefix, _ = os.path.splitext(rel_path)
+
+            child_cfg = load_cfg(child_path, child_prefix)
+            key_fn = lambda x: '/'.join([child_prefix, x])
+            for section in load_sections:
+                if not section in child_cfg:
+                    continue
+                items = {key_fn(k): v for k, v in child_cfg[section].items()}
+                cfg[section].update(items)
+    return cfg
+
+
+def load_cli(args=None):
+    parser = argparse.ArgumentParser()
+    parser.add_argument('names',  nargs='*',
+                        help='Hosts and commands to run them on')
+    parser.add_argument('-c', '--config', default='bd.yaml',
+                        help='Config file')
+    parser.add_argument('-R', '--run', nargs='*', default=[],
+                        help='Run remote task')
+    parser.add_argument('-L', '--run-local', nargs='*', default=[],
+                        help='Run local task')
+    parser.add_argument('-P', '--run-python', nargs='*', default=[],
+                        help='Run python task')
+    parser.add_argument('-d', '--dry-run', action='store_true',
+                        help='Do not run actual tasks, just print them')
+    parser.add_argument('-e', '--env', nargs='*', default=[],
+                        help='Add value to execution environment '
+                        '(ex: -e foo=bar "name=John Doe")')
+    parser.add_argument('-s', '--sudo', default='auto',
+                        help='Enable sudo (auto|yes|no')
+    parser.add_argument('-v', '--verbose', action='count',
+                        default=0, help='Increase verbosity')
+    parser.add_argument('-q', '--quiet', action='count',
+                        default=0, help='Decrease verbosity')
+    parser.add_argument('-n', '--no-color', action='store_true',
+                        help='Disable colored logs')
+    parser.add_argument('-i', '--info', action='store_true',
+                        help='Print info')
+    cli = parser.parse_args(args=args)
+    cli = ObjectDict(vars(cli))
+
+    # Load config
+    cfg = load_cfg(cli.config)
+    cli.cfg = cfg
+    cli.update(get_hosts_and_tasks(cli, cfg))
+
+    # Transformt env string into dict
+    cli.env = dict(e.split('=') for e in cli.env)
+    return cli
+
+def run():
+    cli = None
+    try:
+        cli = load_cli()
+        if not cli.no_color:
+            enable_logging_color()
+        cli.verbose = max(0, 1 + cli.verbose - cli.quiet)
+        level = ['WARNING', 'INFO', 'DEBUG'][min(cli.verbose, 2)]
+        logger.setLevel(level)
+        log_handler.setLevel(level)
+
+        if cli.info:
+            info(cli)
+            return
+
+        base_env = Env(
+            cli.env, # Highest-priority
+            cli.cfg.get('env'),
+            os.environ, # Lowest
+        )
+        for task in cli.tasks:
+            run_batch(task, cli.hosts, cli, base_env)
+    except ByrdException as e:
+        if cli and cli.verbose > 2:
+            raise
+        abort(str(e))
+
+if __name__ == '__main__':
+    run()

+ 1 - 2
byrd/config.py

@@ -1,7 +1,6 @@
 from collections import OrderedDict
 
-from .utils import (ByrdException, ObjectDict, spell,
-                    gen_candidates)
+from utils import (ByrdException, ObjectDict, spell, gen_candidates)
 
 
 try:

+ 3 - 129
byrd/main.py

@@ -3,18 +3,15 @@ from hashlib import md5
 from itertools import chain
 from itertools import islice
 from string import Formatter
-import argparse
 import io
 import os
 import posixpath
 import subprocess
-import sys
 import threading
 
-from .config import Task, yaml_load, ConfigRoot
-from .utils import (ByrdException, LocalException, ObjectDict, RemoteException,
-                   DummyClient, Env, spellcheck, spell, enable_logging_color,
-                   logger, log_handler)
+from config import Task, yaml_load
+from utils import (ByrdException, LocalException, ObjectDict, RemoteException,
+                   DummyClient, Env, spellcheck, spell, logger)
 
 try:
     # This file is imported by setup.py at install time
@@ -24,8 +21,6 @@ except ImportError:
     pass
 
 __version__ = '0.0.2'
-basedir, _ = os.path.split(__file__)
-PKG_DIR = os.path.join(basedir, 'pkg')
 TAB = '\n    '
 
 
@@ -394,97 +389,8 @@ def extract_host(host_string):
     return host_string and host_string.split('@')[-1] or ''
 
 
-def abort(msg):
-    logger.error(msg)
-    sys.exit(1)
 
 
-def load_cfg(path, prefix=None):
-    load_sections = ('networks', 'tasks', 'auth', 'env')
-
-    if os.path.isfile(path):
-        logger.debug('Load config %s' % os.path.relpath(path))
-        cfg = yaml_load(open(path))
-        cfg = ConfigRoot.parse(cfg)
-    else:
-        raise ByrdException('Config file "%s" not found' % path)
-
-    # Define useful defaults
-    cfg.networks = cfg.networks or ObjectDict()
-    cfg.tasks = cfg.tasks or ObjectDict()
-
-    # Create backrefs between tasks to the local config
-    if cfg.get('tasks'):
-        cfg_cp = cfg.copy()
-        for k, v in cfg['tasks'].items():
-            v._cfg = cfg_cp
-
-
-    # Recursive load
-    if cfg.load:
-        cfg_path = os.path.dirname(path)
-        for item in cfg.load:
-            if item.get('file'):
-                rel_path = item.file
-                child_path = os.path.join(cfg_path, item.file)
-            elif item.get('pkg'):
-                rel_path = item.pkg
-                child_path = os.path.join(PKG_DIR, item.pkg)
-
-            if item.get('as'):
-                child_prefix = item['as']
-            else:
-                child_prefix, _ = os.path.splitext(rel_path)
-
-            child_cfg = load_cfg(child_path, child_prefix)
-            key_fn = lambda x: '/'.join([child_prefix, x])
-            for section in load_sections:
-                if not section in child_cfg:
-                    continue
-                items = {key_fn(k): v for k, v in child_cfg[section].items()}
-                cfg[section].update(items)
-    return cfg
-
-
-def load_cli(args=None):
-    parser = argparse.ArgumentParser()
-    parser.add_argument('names',  nargs='*',
-                        help='Hosts and commands to run them on')
-    parser.add_argument('-c', '--config', default='bd.yaml',
-                        help='Config file')
-    parser.add_argument('-R', '--run', nargs='*', default=[],
-                        help='Run remote task')
-    parser.add_argument('-L', '--run-local', nargs='*', default=[],
-                        help='Run local task')
-    parser.add_argument('-P', '--run-python', nargs='*', default=[],
-                        help='Run python task')
-    parser.add_argument('-d', '--dry-run', action='store_true',
-                        help='Do not run actual tasks, just print them')
-    parser.add_argument('-e', '--env', nargs='*', default=[],
-                        help='Add value to execution environment '
-                        '(ex: -e foo=bar "name=John Doe")')
-    parser.add_argument('-s', '--sudo', default='auto',
-                        help='Enable sudo (auto|yes|no')
-    parser.add_argument('-v', '--verbose', action='count',
-                        default=0, help='Increase verbosity')
-    parser.add_argument('-q', '--quiet', action='count',
-                        default=0, help='Decrease verbosity')
-    parser.add_argument('-n', '--no-color', action='store_true',
-                        help='Disable colored logs')
-    parser.add_argument('-i', '--info', action='store_true',
-                        help='Print info')
-    cli = parser.parse_args(args=args)
-    cli = ObjectDict(vars(cli))
-
-    # Load config
-    cfg = load_cfg(cli.config)
-    cli.cfg = cfg
-    cli.update(get_hosts_and_tasks(cli, cfg))
-
-    # Transformt env string into dict
-    cli.env = dict(e.split('=') for e in cli.env)
-    return cli
-
 def get_hosts_and_tasks(cli, cfg):
     # Make sure we don't have overlap between hosts and tasks
     items = list(cfg.networks) + list(cfg.tasks)
@@ -555,35 +461,3 @@ def info(cli):
 
         if variables:
             print(f'\tVariables: {variables}')
-
-
-def main():
-    cli = None
-    try:
-        cli = load_cli()
-        if not cli.no_color:
-            enable_logging_color()
-        cli.verbose = max(0, 1 + cli.verbose - cli.quiet)
-        level = ['WARNING', 'INFO', 'DEBUG'][min(cli.verbose, 2)]
-        logger.setLevel(level)
-        log_handler.setLevel(level)
-
-        if cli.info:
-            info(cli)
-            return
-
-        base_env = Env(
-            cli.env, # Highest-priority
-            cli.cfg.get('env'),
-            os.environ, # Lowest
-        )
-        for task in cli.tasks:
-            run_batch(task, cli.hosts, cli, base_env)
-    except ByrdException as e:
-        if cli and cli.verbose > 2:
-            raise
-        abort(str(e))
-
-
-if __name__ == '__main__':
-    main()

+ 6 - 0
byrd/utils.py

@@ -1,3 +1,4 @@
+import sys
 from itertools import chain
 from collections import defaultdict, ChainMap
 from contextlib import contextmanager
@@ -96,6 +97,11 @@ def spellcheck(objdict, word):
     raise ByrdException(msg)
 
 
+def abort(msg):
+    logger.error(msg)
+    sys.exit(1)
+
+
 class ObjectDict(dict):
     """
     Simple objet sub-class that allows to transform a dict into an