|
@@ -172,6 +172,8 @@ class Command(Node):
|
|
|
def setup(cls, values, path):
|
|
def setup(cls, values, path):
|
|
|
if path:
|
|
if path:
|
|
|
values['name'] = path[-1]
|
|
values['name'] = path[-1]
|
|
|
|
|
+ if 'desc' not in values:
|
|
|
|
|
+ values['desc'] = values['name']
|
|
|
return values
|
|
return values
|
|
|
|
|
|
|
|
class Task(Node):
|
|
class Task(Node):
|
|
@@ -179,13 +181,22 @@ class Task(Node):
|
|
|
'*': Command,
|
|
'*': Command,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+class LoadNode(Node):
|
|
|
|
|
+ _children = {
|
|
|
|
|
+ 'file': Atom,
|
|
|
|
|
+ 'as': Atom,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+class LoadList(Node):
|
|
|
|
|
+ _children = [LoadNode]
|
|
|
|
|
+
|
|
|
class ConfigRoot(Node):
|
|
class ConfigRoot(Node):
|
|
|
_children = {
|
|
_children = {
|
|
|
'networks': Network,
|
|
'networks': Network,
|
|
|
'tasks': Task,
|
|
'tasks': Task,
|
|
|
'auth': Auth,
|
|
'auth': Auth,
|
|
|
'env': EnvNode,
|
|
'env': EnvNode,
|
|
|
- # 'load': ? -> todo allows to load other files and merge them
|
|
|
|
|
|
|
+ 'load': LoadList,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -206,7 +217,6 @@ class Env(ChainMap):
|
|
|
logger.error(msg)
|
|
logger.error(msg)
|
|
|
sys.exit()
|
|
sys.exit()
|
|
|
|
|
|
|
|
-
|
|
|
|
|
def get_passphrase(key_path):
|
|
def get_passphrase(key_path):
|
|
|
service = 'SSH private key'
|
|
service = 'SSH private key'
|
|
|
csum = md5(open(key_path, 'rb').read()).digest().hex()
|
|
csum = md5(open(key_path, 'rb').read()).digest().hex()
|
|
@@ -335,6 +345,7 @@ def run_task(task, host, cli, parent_env=None):
|
|
|
env.update({
|
|
env.update({
|
|
|
'task_desc': env.fmt(task.desc),
|
|
'task_desc': env.fmt(task.desc),
|
|
|
'task_name': task.name,
|
|
'task_name': task.name,
|
|
|
|
|
+ 'host': host,
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
if task.local:
|
|
if task.local:
|
|
@@ -413,6 +424,43 @@ def base_cli(args=None):
|
|
|
return ObjectDict(vars(cli))
|
|
return ObjectDict(vars(cli))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def load(path, prefix=None):
|
|
|
|
|
+ load_sections = ('networks', 'tasks', 'auth', 'env')
|
|
|
|
|
+
|
|
|
|
|
+ logger.info('Load config %s' % path)
|
|
|
|
|
+ cfg = yaml_load(open(path))
|
|
|
|
|
+ cfg = ConfigRoot.parse(cfg)
|
|
|
|
|
+
|
|
|
|
|
+ # Define useful defaults
|
|
|
|
|
+ cfg.networks = cfg.networks or {}
|
|
|
|
|
+ cfg.tasks = cfg.tasks or {}
|
|
|
|
|
+
|
|
|
|
|
+ if prefix:
|
|
|
|
|
+ fn = lambda x: '/'.join(prefix + [x])
|
|
|
|
|
+ # Apply prefix
|
|
|
|
|
+ for section in load_sections:
|
|
|
|
|
+ if not cfg.get(section):
|
|
|
|
|
+ continue
|
|
|
|
|
+ items = cfg[section].items()
|
|
|
|
|
+ cfg[section] = {fn(k): v for k, v in items}
|
|
|
|
|
+
|
|
|
|
|
+ # Recursive load
|
|
|
|
|
+ if cfg.load:
|
|
|
|
|
+ cfg_path = os.path.dirname(path)
|
|
|
|
|
+ for item in cfg.load:
|
|
|
|
|
+ if item.get('as'):
|
|
|
|
|
+ child_prefix = item['as']
|
|
|
|
|
+ else:
|
|
|
|
|
+ child_prefix, _ = os.path.splitext(item.file)
|
|
|
|
|
+ child_path = os.path.join(cfg_path, item.file)
|
|
|
|
|
+ child_cfg = load(child_path, child_prefix.split('/'))
|
|
|
|
|
+
|
|
|
|
|
+ for section in load_sections:
|
|
|
|
|
+ if not cfg.get(section):
|
|
|
|
|
+ cfg[section] = {}
|
|
|
|
|
+ cfg[section].update(child_cfg.get(section, {}))
|
|
|
|
|
+ return cfg
|
|
|
|
|
+
|
|
|
def main():
|
|
def main():
|
|
|
cli = base_cli()
|
|
cli = base_cli()
|
|
|
if cli.verbose:
|
|
if cli.verbose:
|
|
@@ -421,15 +469,9 @@ def main():
|
|
|
logger.info('Log level set to: %s' % level)
|
|
logger.info('Log level set to: %s' % level)
|
|
|
|
|
|
|
|
# Load config
|
|
# Load config
|
|
|
- logger.info('Load config %s' % cli.config)
|
|
|
|
|
- cfg = yaml_load(open(cli.config))
|
|
|
|
|
- cfg = ConfigRoot.parse(cfg)
|
|
|
|
|
|
|
+ cfg = load(cli.config)
|
|
|
cli.cfg = cfg
|
|
cli.cfg = cfg
|
|
|
|
|
|
|
|
- # Define useful defaults
|
|
|
|
|
- cfg.networks = cfg.networks or {}
|
|
|
|
|
- cfg.tasks = cfg.tasks or {}
|
|
|
|
|
-
|
|
|
|
|
# Make sure we don't have overlap between hosts and tasks
|
|
# Make sure we don't have overlap between hosts and tasks
|
|
|
items = list(cfg.networks) + list(cfg.tasks)
|
|
items = list(cfg.networks) + list(cfg.tasks)
|
|
|
msg = 'Name collision between tasks and networks'
|
|
msg = 'Name collision between tasks and networks'
|