diff --git a/GENERATE.md b/GENERATE.md new file mode 100644 index 0000000..c237e51 --- /dev/null +++ b/GENERATE.md @@ -0,0 +1,29 @@ +# ansible-dk generate + +An ansible-dk cli subcommand for generating skeleton Ansible code layouts + +### Usage: +>$ ansible-dk generate repo foo + +Would generate a skeleton ansible repo named foo by running a generator playbook +located at /opt/ansible-dk/generators/default/repo.yml + +Note: The default generators are still in development and in most cases don't do anything yet. + +### Custom Generators +You can supply custom generator playbooks. This can be done with a cli arg: +>$ ansible-dk generate repo -g /path/to/my/generators foo + +This would generate an ansible repo named foo using a playbook at /path/to/my/generators/repo.yml + +You can also set this in a config file so you won't have to pass it to the cli every time. +Add something like this to ~/.ansible-dk/config.yml: +``` +--- +generator: /path/to/my/generators +``` + +### Variables +By default all generator playbooks are passed a variable of [thing]_name. Example: repo_name +You can add custom variables to run with your playbooks in the same format you'd pass them to `ansible-playbooks`: +>$ ansible-dk generate repo foo -e foo=bar -e bar=foo diff --git a/ansible-dk-cli/ansible-dk b/ansible-dk-cli/ansible-dk index b9cae83..c95a9ab 100755 --- a/ansible-dk-cli/ansible-dk +++ b/ansible-dk-cli/ansible-dk @@ -6,6 +6,13 @@ import click import os import sys import json +import yaml +from tempfile import NamedTemporaryFile +from ansible.executor import playbook_executor +from ansible.inventory import Inventory +from ansible.parsing.dataloader import DataLoader +from ansible.vars import VariableManager +from collections import namedtuple ################################################### # Defaults @@ -13,6 +20,26 @@ RUBY_ABI = "2.1.0" PYTHON_ABI = "2.7" HOME = os.getenv("HOME") +def get_config(debug=False): + config_path=os.path.expanduser('~/.ansible-dk/config.yml') + config = { + 'generator': '/opt/ansible-dk/generators/default' + } + if os.path.isfile(config_path): + try: + config.update(yaml.load(open(config_path, 'r'))) + if debug: + click.echo("Loaded config from %s:\n%s" % (config_path, config)) + return config + except: + if debug: + click.echo("Error loading config file %s" % config_path) + return config + else: + if debug: + click.echo("No config file found at %s" % config_path) + return config + # pull version from version-manifest file left by package install def check_version(): file='/opt/ansible-dk/version-manifest.json' @@ -101,19 +128,61 @@ def verify(): ################################################### # generate command -@cli.group() +@cli.group(help='A tool for generating skeleton Ansible code layouts. More info: https://github.com/omniti-labs/ansible-dk/blob/master/GENERATE.md') def generate(): pass -@generate.command(name='playbook') -@click.option('--name', required=True, help='Name of playbook to generate') -def generate_playbook(name): - print("Generating playbook: ", name) +def parse_extra_vars(context, param, e): + extra_vars = {} + for var in e: + try: + key, value = var.split('=') + except ValueError: + raise click.BadParameter('must be in the format var=value') + extra_vars[key] = value + return extra_vars + +# dynamically create generate subcommands +def generate_method(thing): + @generate.command(name=thing, help='Generate ansible %s' % thing) + @click.option('--debug', is_flag=True, help="Enable debug mode") + @click.option('--generator', '-g', default=False, metavar='/opt/ansible-dk/generators/default', help='Path to custom generator repo') + @click.option('-e', 'extra_vars', multiple=True, callback=parse_extra_vars, metavar='var=value', help='extra vars to pass to ansible, multiple ok') + @click.argument('name') + def generated_method(debug, generator, name, extra_vars): + if not generator: + generator = get_config(debug)['generator'] + extra_vars[thing+'_name'] = name + playbook_path = "%s/%s.yml" % (generator, thing) + if debug: + click.echo('generating %s named %s using %s' % (thing, name, playbook_path)) + run_ansible(playbook_path, extra_vars) + generated_method.__name__ = 'generate_%s' % thing + +generate_things = ['repo', 'role', 'filter', 'inventory', 'config', 'playbook'] +for thing in generate_things: + generate_method(thing) -@generate.command(name='role') -@click.option('--name', required=True, help='Name of role to generate') -def generate_role(name): - print("Generating role: ", name) +def run_ansible(playbook, vars=None): + if not os.path.exists(playbook): + print 'Error - specified role generator playbook does not exist' + sys.exit() + Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'listhosts', 'listtasks', 'listtags', 'syntax', 'remote_user', 'private_key_file', 'ssh_common_args', 'sftp_extra_args', 'scp_extra_args', 'ssh_extra_args', 'verbosity']) + options = Options(connection='local', module_path=None, forks=100, become=None, become_method=None, become_user=None, check=False, listhosts=False, listtasks=False, listtags=False, syntax=False, remote_user=None, private_key_file=None, ssh_common_args=None, sftp_extra_args=None, scp_extra_args=None, ssh_extra_args=None, verbosity=None) + loader = DataLoader() + variable_manager = VariableManager() + inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list='localhost') + variable_manager.set_inventory(inventory) + if vars: + variable_manager.extra_vars = vars + playbook_executor.PlaybookExecutor( + playbooks=[playbook], + inventory=inventory, + options=options, + loader=loader, + variable_manager=variable_manager, + passwords=dict() + ).run() ################################################### # Call main CLI diff --git a/config/software/ansible-dk-cli.rb b/config/software/ansible-dk-cli.rb index 92e9537..c55c4ca 100644 --- a/config/software/ansible-dk-cli.rb +++ b/config/software/ansible-dk-cli.rb @@ -1,9 +1,9 @@ name "ansible-dk-cli" default_version "0.1.0" # This is just to silence a warning -description "One day this might be a generic CLI tool; today it is a hack to make shell-init work" +description "generic CLI tool for ansible-dk" -# This isn't used yet (as we're a shell script, derp) but will be soon! dependency 'click' +dependency 'ansible-dk-generators' build do copy Dir.pwd + "/ansible-dk-cli/ansible-dk", "#{install_dir}/embedded/bin" diff --git a/config/software/ansible-dk-generators.rb b/config/software/ansible-dk-generators.rb new file mode 100644 index 0000000..405805b --- /dev/null +++ b/config/software/ansible-dk-generators.rb @@ -0,0 +1,7 @@ +name "ansible-dk-generators" +default_version "0.1.0" # This is just to silence a warning +description "a set of generic playbooks for the ansible-dk generator" + +build do + copy Dir.pwd + "/generators", "#{install_dir}/" +end diff --git a/generators/default/config.yml b/generators/default/config.yml new file mode 100644 index 0000000..34db7ba --- /dev/null +++ b/generators/default/config.yml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + connection: local + tasks: + - debug: msg="running dummy config generator playbook" + diff --git a/generators/default/filter.yml b/generators/default/filter.yml new file mode 100644 index 0000000..763fa43 --- /dev/null +++ b/generators/default/filter.yml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + connection: local + tasks: + - debug: msg="running dummy filter generator playbook" + diff --git a/generators/default/inventory.yml b/generators/default/inventory.yml new file mode 100644 index 0000000..d8444aa --- /dev/null +++ b/generators/default/inventory.yml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + connection: local + tasks: + - debug: msg="running dummy inventory generator playbook" + diff --git a/generators/default/playbook.yml b/generators/default/playbook.yml new file mode 100644 index 0000000..70e6b22 --- /dev/null +++ b/generators/default/playbook.yml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + connection: local + tasks: + - debug: msg="running dummy playbook generator playbook" + diff --git a/generators/default/repo.yml b/generators/default/repo.yml new file mode 100644 index 0000000..5dc5880 --- /dev/null +++ b/generators/default/repo.yml @@ -0,0 +1,6 @@ +--- +- hosts: localhost + connection: local + tasks: + - debug: msg="running dummy repo generator playbook" + diff --git a/generators/default/role.yml b/generators/default/role.yml new file mode 100644 index 0000000..7f5e08c --- /dev/null +++ b/generators/default/role.yml @@ -0,0 +1,23 @@ +--- +- hosts: localhost + connection: local + vars: + role_subdirectories: + - tasks + - handlers + - templates + - files + - vars + - meta + tasks: + + - name: create top level role directory + file: state=directory path="{{ role_name }}" recurse=yes + + - name: create subdirectories + file: state=directory path="{{ role_name }}/{{ item }}" + with_items: "{{ role_subdirectories }}" + + - name: create main.yml files + copy: content="---\n" dest="{{ role_name }}/{{ item }}/main.yml" + with_items: "{{ role_subdirectories }}"