def run(self): """Runs ansible CLI. Runs ansible CLI using PlaybookCLI and command line arguments stored in the self.cli_args list. Raises: CommandError: If there was error while running the command. Returns: int or list: return from the ansible PlaybookExecutor run() """ # Set the ansible.cfg that will be used by octario octario_ansible_config = self._get_ansible_config_file() if octario_ansible_config: os.environ['ANSIBLE_CONFIG'] = octario_ansible_config # Import must happen after setting ANSIBLE_CONFIG, otherwise # environment variable will not be used. from ansible.cli.playbook import PlaybookCLI ansible_cli = PlaybookCLI(self.cli_args) ansible_cli.parse() results = ansible_cli.run() if results: raise exceptions.CommandError("Failed to run tester: %s" % self.tester.get_playbook_path()) return results
def _run_playbook(playbook, service, node): # Unfortunately, there's no good way to get the options instance # with proper defaults since it's generated by argparse inside # PlaybookCLI. Due to the fact that the options can't be empty # and must contain proper values we have not choice but extract # them from PlaybookCLI instance. playbook_cli = PlaybookCLI(['to-be-stripped', playbook]) playbook_cli.parse() options = playbook_cli.options # Get others required options. loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader, variable_manager) variable_manager.set_inventory(inventory) variable_manager.extra_vars = _get_user_settings(loader) # OpenStack Ansible deploys control plane services in LXC containers, # and use those as native hosts in its inventory. However, from # Kostyor's POV we are interested in baremetal node-by-node upgrade, # so we need to limit playbook execution only to baremetal node under # upgrade and its service's containers. inventory.subset([ host.get_vars()['inventory_hostname'] for host in _get_component_hosts_on_node(inventory, service, node) ]) # Finally, we can create a playbook executor and run the playbook. executor = PlaybookExecutor(playbooks=[playbook], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords={}) executor.run()
def cell(create, destroy, playbook, inventory, key_file, aws_config, with_freeipa): """Manage treadmill cell on AWS""" playbook_args = [ 'ansible-playbook', '-i', inventory, '-e', 'aws_config={}'.format(aws_config) + ' freeipa={}'.format(with_freeipa), ] if create: playbook_args.extend([ playbook or deploy_path_join('cell.yml'), '--key-file', key_file, ]) elif destroy: playbook_args.append(playbook or deploy_path_join('destroy-cell.yml')) else: return playbook_cli = PlaybookCLI(playbook_args) playbook_cli.parse() playbook_cli.run()
def executor(tmpdir_factory, request): playbooks = request.node.callspec.params.get('playbook') playbook_files = [] for name, playbook in playbooks.items(): filename = str(tmpdir_factory.mktemp('data').join(name)) with open(filename, 'w') as f: f.write(playbook) playbook_files.append(filename) cli = PlaybookCLI(['', 'playbook.yml']) cli.parse() options = cli.parser.parse_args(['-v'])[0] loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=['localhost']) variable_manager.set_inventory(inventory) return PlaybookExecutor(playbooks=playbook_files, inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords={})
def _run_playbook(cli_args, vars_dict): """Runs ansible cli with vars dict :param vars_dict: dict, Will be passed as Ansible extra-vars :param cli_args: the list of command line arguments :return: ansible results """ # TODO(yfried): use ansible vars object instead of tmpfile # NOTE(oanufrii): !!!this import should be exactly here!!! # Ansible uses 'display' singleton from '__main__' and # gets it on module level. While we monkeypatching our # '__main__' in 'ansible_playbook' function import of # PlaybookCLI shoul be after that, to get patched # '__main__'. Otherwise ansible gets unpatched '__main__' # and creates new 'display' object with default (0) # verbosity. from ansible.cli.playbook import PlaybookCLI with tempfile.NamedTemporaryFile( prefix="ir-settings-", delete=True) as tmp: tmp.write(yaml.safe_dump(vars_dict, default_flow_style=False)) # make sure created file is readable. tmp.flush() cli_args.extend(['--extra-vars', "@" + tmp.name]) cli = PlaybookCLI(cli_args) LOG.debug('Starting ansible cli with args: {}'.format(cli_args[1:])) cli.parse() return cli.run()
def _run_playbook(cli_args, vars_dict): """Runs ansible cli with vars dict :param vars_dict: dict, Will be passed as Ansible extra-vars :param cli_args: the list of command line arguments :return: ansible results """ # TODO(yfried): use ansible vars object instead of tmpfile # NOTE(oanufrii): !!!this import should be exactly here!!! # Ansible uses 'display' singleton from '__main__' and # gets it on module level. While we monkeypatching our # '__main__' in 'ansible_playbook' function import of # PlaybookCLI shoul be after that, to get patched # '__main__'. Otherwise ansible gets unpatched '__main__' # and creates new 'display' object with default (0) # verbosity. from ansible.cli.playbook import PlaybookCLI with tempfile.NamedTemporaryFile(prefix="ir-settings-", delete=True) as tmp: tmp.write(yaml.safe_dump(vars_dict, default_flow_style=False)) # make sure created file is readable. tmp.flush() cli_args.extend(['--extra-vars', "@" + tmp.name]) cli = PlaybookCLI(cli_args) LOG.debug('Starting ansible cli with args: {}'.format(cli_args[1:])) cli.parse() return cli.run()
def execute_playbooks(playbook_dir, host_file, extra_vars, host, logger=None, limit_playbooks=[]): # Import PlaybookCLI here because if it is imported before reading ansible.cfg, # ansible will try to create a tempdir that it does not have permission for. from ansible.cli.playbook import PlaybookCLI # Force requirement of a logger for 2.0 playbook runs if not logger: logger = deploy_logger inventory_dir = "%s/ansible" % settings.ANSIBLE_ROOT # Run playbooks results = [] for pb in limit_playbooks: logger.info("Executing playbook %s/%s" % (playbook_dir, pb)) args = [ "--inventory=%s" % inventory_dir, "--limit=%s" % host, "--extra-vars=%s" % json.dumps(extra_vars), "%s/%s" % (playbook_dir, pb) ] pb_runner = PlaybookCLI(args) pb_runner.parse() results.append(pb_runner.run()) if results[-1] != 0: break return results
def runPlaybook(state, pbook): try: playbookCLI = PlaybookCLI( ["ansible-playbook", "-l", state.limit, pbook]) playbookCLI.parse() playbookCLI.run() except AnsibleError as e: click.echo(e)
def run_pbook(self): """Run playbook in check mode with console-stdout suppressed""" for flag in ('--check',): if flag not in self.ansible_pbook_args: self.ansible_pbook_args.append(flag) obj = PlaybookCLI(self.ansible_pbook_args) obj.parse() obj.run()
def main(): """Run playbook""" for flag in ('--check',): if flag not in sys.argv: sys.argv.append(flag) obj = PlaybookCLI(sys.argv) obj.parse() obj.run()
def read_playbook(playbook): cli_args = [os.path.realpath(playbook), testinfra_hosts] cli = PlaybookCLI(cli_args) cli.parse() loader, inventory, variable_manager = cli._play_prereqs() pb = Playbook.load(cli.args[0], variable_manager, loader) for play in pb.get_plays(): yield variable_manager.get_vars(play)
def run_playbook(module, extra_vars=None, extra_args=None): # Assemble parameters for playbook call path = 'test/test_playbooks/{}.yml'.format(module) playbook_opts = ['ansible-playbook', path] if extra_vars: playbook_opts.extend(['--extra-vars', extra_vars]) if extra_args: playbook_opts.extend(extra_args) cli = PlaybookCLI(playbook_opts) cli.parse() return cli.run()
def __run_playbook(inventory_path, playbook_path, key_path, tags, ansibleopts): vault_password_file = vault.VAULT_PASSWORD_FILENAME if os.path.exists(vault.VAULT_PLAIN_PASSWORD_FILENAME): vault_password_file = vault.VAULT_PLAIN_PASSWORD_FILENAME cmd = ['ansible-playbook', '-i', inventory_path, '--private-key', key_path, '--vault-password-file={}'.format(vault_password_file), playbook_path] if len(tags) > 0: cmd += ['--tags', ','.join(tags)] if ansibleopts is not None: cmd += ansibleopts.strip().split() cli = PlaybookCLI(cmd) cli.parse() return cli.run()
def test_flush_cache(self): cli = PlaybookCLI(args=["ansible-playbook", "--flush-cache", "foobar.yml"]) cli.parse() self.assertTrue(cli.options.flush_cache) variable_manager = VariableManager() fake_loader = DictDataLoader({'foobar.yml': ""}) inventory = InventoryManager(loader=fake_loader, sources='testhost,') variable_manager.set_host_facts(inventory.get_host('testhost'), {'canary': True}) self.assertTrue('testhost' in variable_manager._fact_cache) cli._flush_cache(inventory, variable_manager) self.assertFalse('testhost' in variable_manager._fact_cache)
def test_flush_cache(self): cli = PlaybookCLI( args=["ansible-playbook", "--flush-cache", "foobar.yml"]) cli.parse() self.assertTrue(context.CLIARGS['flush_cache']) variable_manager = VariableManager() fake_loader = DictDataLoader({'foobar.yml': ""}) inventory = InventoryManager(loader=fake_loader, sources='testhost,') variable_manager.set_host_facts('testhost', {'canary': True}) self.assertTrue('testhost' in variable_manager._fact_cache) cli._flush_cache(inventory, variable_manager) self.assertFalse('testhost' in variable_manager._fact_cache)
def node(create, playbook, inventory, key_file, aws_config): """Manage treadmill node""" if create: playbook_cli = PlaybookCLI([ 'ansible-playbook', '-i', inventory, playbook, '--key-file', key_file, '-e', 'aws_config={}'.format(aws_config), ]) playbook_cli.parse() playbook_cli.run()
def deploy(self): os.chdir(self.wd) # need to chdir before importing! from ansible.cli.playbook import PlaybookCLI cli = PlaybookCLI( [ sys.argv[0], '-i', 'inventory', '-f', '10', self.playbook ] ) cli.parse() exit = cli.run() os.chdir(self.pwd) return exit
def _run_playbook(cli_args, settings): """ Runs ansible cli. :param cli_args: the list of command line arguments :param settings: the settings dictionary :return: ansible results """ with tempfile.NamedTemporaryFile( prefix="ir-settings-", delete=True) as tmp: tmp.write(yaml.safe_dump(settings, default_flow_style=False)) # make sure ansible can read that file. tmp.flush() cli_args.extend(['--extra-vars', "@" + tmp.name]) cli = PlaybookCLI(cli_args) LOG.debug('Starting ansible cli with args: {}'.format(cli_args[1:])) cli.parse() return cli.run()
def _run_playbook(cli_args, settings): """ Runs ansible cli. :param cli_args: the list of command line arguments :param settings: the settings dictionary :return: ansible results """ with tempfile.NamedTemporaryFile(prefix="ir-settings-", delete=True) as tmp: tmp.write(yaml.safe_dump(settings, default_flow_style=False)) # make sure ansible can read that file. tmp.flush() cli_args.extend(['--extra-vars', "@" + tmp.name]) cli = PlaybookCLI(cli_args) LOG.debug('Starting ansible cli with args: {}'.format(cli_args[1:])) cli.parse() return cli.run()
def _run_playbook_impl(playbook, hosts_fn=None, cwd=None, ignore_errors=False): # Unfortunately, there's no good way to get the options instance # with proper defaults since it's generated by argparse inside # PlaybookCLI. Due to the fact that the options can't be empty # and must contain proper values we have not choice but extract # them from PlaybookCLI instance. playbook_cli = PlaybookCLI(['to-be-stripped', playbook]) playbook_cli.parse() options = playbook_cli.options # Get others required options. loader = DataLoader() variable_manager = VariableManager() inventory = Inventory(loader, variable_manager) variable_manager.set_inventory(inventory) variable_manager.extra_vars = _get_user_settings(loader) # Limit playbook execution to hosts returned by 'hosts_fn'. if hosts_fn is not None: inventory.subset([ host.get_vars()['inventory_hostname'] for host in hosts_fn(inventory) ]) # Finally, we can create a playbook executor and run the playbook. executor = PlaybookExecutor(playbooks=[playbook], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords={}) # Some playbooks may rely on current working directory, so better allow # to change it before execution. with _setcwd(cwd): exitcode = executor.run() # Celery treats exceptions from task as way to mark it failed. So let's # throw one to do so in case return code is not zero. if all([not ignore_errors, exitcode is not None, exitcode != 0]): raise Exception('Playbook "%s" has been finished with errors. ' 'Exit code is "%d".' % (playbook, exitcode)) return exitcode
def main(cliargs=None): data_path = resource_filename(__name__, 'data') packaging_playbooks_path = os.path.join(data_path, 'playbooks') cfg_path = os.path.join(data_path, 'ansible.cfg') if os.path.exists(cfg_path): os.environ["ANSIBLE_CONFIG"] = cfg_path # this needs to be global, as otherwise PlaybookCLI fails # to set the verbosity correctly from ansible.utils.display import Display global display display = Display() inventory_path = os.path.join(os.getcwd(), 'package_manifest.yaml') package_choices = find_packages(inventory_path) playbooks = find_playbooks(packaging_playbooks_path) parser = obal_argument_parser(playbooks.keys(), package_choices) args = parser.parse_args(cliargs) playbook_path = playbooks[args.action] if not os.path.exists(inventory_path): print("Could not find your package_manifest.yaml") exit(1) if not os.path.exists(playbook_path): print("Could not find the packaging playbooks") exit(1) from ansible.cli.playbook import PlaybookCLI ansible_args = generate_ansible_args(inventory_path, playbook_path, args) ansible_playbook = (["ansible-playbook"] + ansible_args) if args.verbose: print(ansible_playbook) cli = PlaybookCLI(ansible_playbook) cli.parse() exit_code = cli.run() sys.exit(exit_code)
def runPlaybooks(playbooks, _inventory, params=None, args=None, vault_secrets=None): inventoryArgs = ["-i", _inventory] if _inventory else [] args = ["ansible-playbook"] + inventoryArgs + (args or []) + playbooks logger.info("running " + " ".join(args)) cli = PlaybookCLI(args) context._init_global_context = _init_global_context cli.parse() # replace C.DEFAULT_STDOUT_CALLBACK with our own so we have control over logging # config/base.yml sets C.DEFAULT_STDOUT_CALLBACK == 'default' (ansible/plugins/callback/default.py) # (cli/console.py and cli/adhoc.py sets it to 'minimal' but PlaybookCLI.run() in cli/playbook.py uses the default) # see also https://github.com/projectatomic/atomic-host-tests/blob/master/callback_plugins/default.py resultsCB = ResultCallback() resultsCB.set_options() C.DEFAULT_STDOUT_CALLBACK = resultsCB _play_prereqs = cli._play_prereqs def hook_play_prereqs(): loader, inventory, variable_manager = _play_prereqs() if vault_secrets: loader.set_vault_secrets(vault_secrets) if params: variable_manager._extra_vars.update(params) resultsCB.inventoryManager = inventory resultsCB.variableManager = variable_manager return loader, inventory, variable_manager cli._play_prereqs = hook_play_prereqs oldVerbosity = display.verbosity if logging.getLogger("unfurl.ansible").getEffectiveLevel() <= 10: # debug display.verbosity = 2 try: resultsCB.exit_code = cli.run() finally: display.verbosity = oldVerbosity return resultsCB
def _run_playbook(cli_args, vars_dict): """Runs ansible cli with vars dict :param vars_dict: dict, Will be passed as Ansible extra-vars :param cli_args: the list of command line arguments :return: ansible results """ # TODO(yfried): use ansible vars object instead of tmpfile with tempfile.NamedTemporaryFile( prefix="ir-settings-", delete=True) as tmp: tmp.write(yaml.safe_dump(vars_dict, default_flow_style=False)) # make sure created file is readable. tmp.flush() cli_args.extend(['--extra-vars', "@" + tmp.name]) cli = PlaybookCLI(cli_args) LOG.debug('Starting ansible cli with args: {}'.format(cli_args[1:])) cli.parse() return cli.run()
def main(cliargs=None, application_config=ApplicationConfig): # pylint: disable=R0914 """ Main command """ cfg_path = application_config.ansible_config_path() if os.path.exists(cfg_path): os.environ["ANSIBLE_CONFIG"] = cfg_path # this needs to be global, as otherwise PlaybookCLI fails # to set the verbosity correctly from ansible.utils.display import Display # pylint: disable=all global display # pylint: disable=C0103,W0603 display = Display() inventory_path = application_config.inventory_path() targets = find_targets(inventory_path) parser = obsah_argument_parser(application_config, targets=targets) args = parser.parse_args(cliargs) if args.playbook.takes_target_parameter and not os.path.exists( inventory_path): print("Could not find your inventory at {}".format(inventory_path)) sys.exit(1) from ansible.cli.playbook import PlaybookCLI # pylint: disable=all ansible_args = generate_ansible_args(inventory_path, args, parser.obsah_arguments) ansible_playbook = (["ansible-playbook"] + ansible_args) if args.verbose: print("ANSIBLE_CONFIG={}".format(os.environ["ANSIBLE_CONFIG"]), ' '.join(ansible_playbook)) cli = PlaybookCLI(ansible_playbook) cli.parse() exit_code = cli.run() sys.exit(exit_code)
def main(cliargs=None): # pylint: disable=R0914 """ Main command """ cfg_path = get_ansible_config_path() if os.path.exists(cfg_path): os.environ["ANSIBLE_CONFIG"] = cfg_path # this needs to be global, as otherwise PlaybookCLI fails # to set the verbosity correctly from ansible.utils.display import Display global display # pylint: disable=C0103,W0603 display = Display() inventory_path = os.path.join(os.getcwd(), 'package_manifest.yaml') package_choices = find_packages(inventory_path) playbooks = find_playbooks(get_playbooks_path()) parser = obal_argument_parser(playbooks, package_choices) args = parser.parse_args(cliargs) if args.playbook.takes_package_parameter and not os.path.exists(inventory_path): print("Could not find your package_manifest.yaml") exit(1) from ansible.cli.playbook import PlaybookCLI ansible_args = generate_ansible_args(inventory_path, args) ansible_playbook = (["ansible-playbook"] + ansible_args) if args.verbose: print(ansible_playbook) cli = PlaybookCLI(ansible_playbook) cli.parse() exit_code = cli.run() sys.exit(exit_code)
class General(object): def __init__(self): self.cli = PlaybookCLI(sys.argv, callback=CallbackModule) self.cli.parse() def run(self): sshpass = None becomepass = None passwords = {} if not self.cli.options.listhosts and not self.cli.options.listtasks and not self.cli.options.listtags and not self.cli.options.syntax: self.cli.normalize_become_options() (sshpass, becomepass) = self.cli.ask_passwords() passwords = {'conn_pass': sshpass, 'become_pass': becomepass} loader, inventory, variable_manager = self.cli._play_prereqs( self.cli.options) for playbook_path in self.cli.args: pb = Playbook.load(playbook_path, variable_manager=variable_manager, loader=loader) plays = pb.get_plays() for play in plays: tqm = None try: tqm = TaskQueueManager( inventory=inventory, variable_manager=variable_manager, loader=loader, options=self.cli.options, passwords=passwords, stdout_callback=CallbackModule(), ) tqm.run(play) finally: if tqm is not None: tqm.cleanup()
def generate_playbook_options(self, playbook): """ Use the Ansible CLI code to generate a set of options for the Playbook API. We do not know or care about the fields that may or may not be needed from the options, so we let the Ansible code parse them out and set other defaults as necessary. :return: namedtuple-esque playbook options object """ playbook_args = [ 'ansible-playbook', '-{}'.format('v' * self.verbosity), playbook ] if self.check: playbook_args.append('--check') playbook_cli = PlaybookCLI(args=playbook_args) playbook_cli.parse() playbook_cli.options.module_path = self.custom_module_path return playbook_cli.options
print("[+] launching ansible-galaxy") default_opts = ["ansible-galaxy"] default_opts += ["install"] default_opts += ["-r", "ansible-requirements.yml"] default_opts += ["--force"] galaxy_cli = GalaxyCLI(default_opts) galaxy_cli.parse() exit_code = galaxy_cli.run() if exit_code: clean_and_exit(tmpdir, exit_code) if not options.no_ansible: print("[+] launching ansible-playbook") default_opts = ["ansible-playbook"] default_opts += ["-i", "default_groups"] default_opts += ["-i", inventory_file] default_opts += ["-e", "@{}".format(vars_file)] if '-u' not in options.ansible_args: default_opts += ["-u", "vagrant"] if options.offline: default_opts += [ "--module-path", "ansible_plugins/modules:offline/ansible_modules/offline" ] ansible_args = default_opts + options.ansible_args play_cli = PlaybookCLI(ansible_args) play_cli.parse() exit_code = play_cli.run() clean_and_exit(tmpdir, exit_code)
if not options.no_ansible_galaxy: print("[+] launching ansible-galaxy") default_opts = ["ansible-galaxy"] default_opts += ["install"] default_opts += ["-r", "ansible-requirements.yml"] default_opts += ["--force"] galaxy_cli = GalaxyCLI(default_opts) galaxy_cli.parse() exit_code = galaxy_cli.run() if exit_code: clean_and_exit(tmpdir, exit_code) if not options.no_ansible: print("[+] launching ansible-playbook") default_opts = ["ansible-playbook"] default_opts += ["-i", "default_groups"] default_opts += ["-i", inventory_file] default_opts += ["-e", "@{}".format(vars_file)] if '-u' not in options.ansible_args: default_opts += ["-u", "vagrant"] if options.offline: default_opts += [ "--module-path", "ansible_plugins/modules:offline/ansible_modules/offline"] ansible_args = default_opts + options.ansible_args play_cli = PlaybookCLI(ansible_args) play_cli.parse() exit_code = play_cli.run() clean_and_exit(tmpdir, exit_code)
self.package_info[h]["failed"] = True super(CallbackModule, self).v2_runner_item_on_failed(result) # Initialise our custom callback results_callback = CallbackModule() # Read all the arguments from the cli args = [to_text(a, errors='surrogate_or_strict') for a in sys.argv] # Ensure dry-run option is specified if '--check' not in args: args.append('--check') pb_cli = PlaybookCLI(args) pb_cli.parse() ##################################################################### ### Execute a playbook # This section is copied directly from: https://github.com/ansible/ansible/blob/stable-2.9/lib/ansible/cli/playbook.py#L71 # manages passwords sshpass = None becomepass = None passwords = {} b_playbook_dirs = [] for playbook in context.CLIARGS['args']: if not os.path.exists(playbook): raise AnsibleError("the playbook: %s could not be found" % playbook) if not (os.path.isfile(playbook)
def main(): inventory_path = os.path.join(os.getcwd(), 'package_manifest.yaml') package_choices = find_packages(inventory_path) parser = argparse.ArgumentParser() parser.add_argument('-e', '--extra-vars', dest="extra_vars", action="append", default=[], help="""set additional variables as key=value or YAML/JSON, if filename prepend with @""") parser.add_argument("-v", "--verbose", action="count", dest="verbose", help="verbose output") parser.add_argument("--start-at-task", action="store", dest="start_at_task", help="Start at a specific task") parser.add_argument("--step", action="store_true", dest="step", default=False, help="interactive: confirm each task before running") parser.add_argument("--list-tasks", action="store_true", dest="list_tasks", default=False, help="list tasks that will be run in the playbook") parser.add_argument("action", choices=_PLAYBOOKS.keys(), help="""which action to execute""") parser.add_argument('package', metavar='package', choices=package_choices, help="the package to build") if argcomplete: argcomplete.autocomplete(parser) args = parser.parse_args() packaging_playbooks_path = resource_filename(__name__, 'data') playbook = _PLAYBOOKS[args.action] playbook_path = os.path.join(packaging_playbooks_path, playbook) cfg_path = os.path.join(packaging_playbooks_path, 'ansible.cfg') if os.path.exists(cfg_path): os.environ["ANSIBLE_CONFIG"] = cfg_path if not os.path.exists(inventory_path): print("Could not find your package_manifest.yaml") exit(1) if not os.path.exists(playbook_path): print("Could not find the packaging playbooks") exit(1) from ansible.cli.playbook import PlaybookCLI ansible_args = [ playbook_path, '--inventory', inventory_path, '--limit', args.package ] for extra_var in args.extra_vars: ansible_args.extend(["-e", extra_var]) if args.verbose: ansible_args.append("-%s" % str("v" * args.verbose)) if args.start_at_task: ansible_args.append("--start-at-task") ansible_args.append(args.start_at_task) if args.step: ansible_args.append("--step") if args.list_tasks: ansible_args = ["--list-tasks"] ansible_playbook = (["ansible-playbook"] + ansible_args) if args.verbose: print(ansible_playbook) cli = PlaybookCLI(ansible_playbook) cli.parse() cli.run()
def run_playbook(args): pb_cli = PlaybookCLI(args) pb_cli.parse() return pb_cli.run()
def _run_playbook(cli_args, vars_dict, ir_workspace, ir_plugin): """Runs ansible cli with vars dict :param vars_dict: dict, Will be passed as Ansible extra-vars :param cli_args: the list of command line arguments :param ir_workspace: An Infrared Workspace object represents the active workspace :param ir_plugin: An InfraredPlugin object of the current plugin :return: ansible results """ # TODO(yfried): use ansible vars object instead of tmpfile # NOTE(oanufrii): !!!this import should be exactly here!!! # Ansible uses 'display' singleton from '__main__' and # gets it on module level. While we monkeypatching our # '__main__' in 'ansible_playbook' function import of # PlaybookCLI shoul be after that, to get patched # '__main__'. Otherwise ansible gets unpatched '__main__' # and creates new 'display' object with default (0) # verbosity. from ansible.cli.playbook import PlaybookCLI from ansible.errors import AnsibleOptionsError from ansible.errors import AnsibleParserError with tempfile.NamedTemporaryFile(mode='w+', prefix="ir-settings-", delete=True) as tmp: tmp.write(yaml.safe_dump(vars_dict, default_flow_style=False)) # make sure created file is readable. tmp.flush() cli_args.extend(['--extra-vars', "@" + tmp.name]) cli = PlaybookCLI(cli_args) LOG.debug('Starting ansible cli with args: {}'.format(cli_args[1:])) try: cli.parse() stdout = not bool( strtobool(os.environ.get('IR_ANSIBLE_NO_STDOUT', 'no'))) stderr = not bool( strtobool(os.environ.get('IR_ANSIBLE_NO_STDERR', 'no'))) ansible_outputs_dir = \ os.path.join(ir_workspace.path, 'ansible_outputs') ansible_vars_dir = \ os.path.join(ir_workspace.path, 'ansible_vars') timestamp = datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%S.%f") filename_template = \ "ir_{timestamp}_{plugin_name}{postfix}.{file_ext}" for _dir in (ansible_outputs_dir, ansible_vars_dir): try: os.makedirs(_dir) except OSError as e: if e.errno != errno.EEXIST: raise if bool(strtobool(os.environ.get('IR_GEN_VARS_JSON', 'no'))): filename = filename_template.format(timestamp=timestamp, plugin_name=ir_plugin.name, postfix='', file_ext='json') vars_file = os.path.join(ansible_vars_dir, filename) with open(vars_file, 'w') as fp: json.dump(vars_dict, fp, indent=4, sort_keys=True) with IRSTDFDManager(stdout=stdout, stderr=stderr) as fd_manager: if bool( strtobool(os.environ.get('IR_ANSIBLE_LOG_OUTPUT', 'no'))): filename = filename_template.format( timestamp=timestamp, plugin_name=ir_plugin.name, postfix='', file_ext='log') log_file = os.path.join(ansible_outputs_dir, filename) fd_manager.add(open(log_file, 'w')) if bool( strtobool( os.environ.get('IR_ANSIBLE_LOG_OUTPUT_NO_ANSI', 'no'))): filename = filename_template.format( timestamp=timestamp, plugin_name=ir_plugin.name, postfix='_no_ansi', file_ext='log') log_file = os.path.join(ansible_outputs_dir, filename) fd_manager.add(NoAnsiFile(open(log_file, 'w'))) # Return the result: # 0: Success # 1: "Error" # 2: Host failed # 3: Unreachable # 4: Parser Error # 5: Options error return cli.run() except (AnsibleParserError, AnsibleOptionsError) as error: LOG.error('{}: {}'.format(type(error), error)) raise error
def run_playbook(path, extra_vars=""): cli = PlaybookCLI(['ansible-playbook', path, "--extra-vars", extra_vars]) cli.parse() return cli.run()
def default(self): verbose = self.app.pargs.verbose init(autoreset=True) if len(self.app.pargs.extra_arguments) == 0: self.app.args.print_help() print(Fore.RED + 'Error! You must specify a playbook file to run') sys.exit(1) if str(self.app.pargs.become_method).upper() not in [ 'SUDO', 'SU', 'PBRUN', 'PFEXEC', 'DOAS', 'DZDO', 'KSU', 'RUNAS' ]: print( Fore.RED + 'Error! Become method must be one of sudo, su, pbrun, pfexec, doas, dzdo, ksu or runas.' ) sys.exit(1) #if len(self.app.pargs.extra_arguments) > 0: playbook_path = self.app.pargs.extra_arguments[0] if len( self.app.pargs.extra_arguments) > 0 else "site.yml" if not os.path.isfile(playbook_path): print(Fore.RED + 'Error! The playbook file does not exist') sys.exit(1) inventory_path = self.app.pargs.inventory if not os.path.isfile(inventory_path): print(Fore.RED + 'Error! The inventory file does not exist.') sys.exit(1) # Most of the code from here down is straight copy & paste from ansible source code, # with a few tweaks/hacks to clean up variables that we don't want to emit in the generated # YAML. loader = DataLoader() pb_cli = PlaybookCLI(sys.argv[1:]) pb_cli.parse() # !!!!! WARNING: THESE WILL BE INCLUDED IN THE GENERATED YAML FILE !!!!! (ssh_pass, become_pass) = pb_cli.ask_passwords() passwords = {'conn_pass': ssh_pass, 'become_pass': become_pass} vault_pass = None if self.app.pargs.ask_vault_pass: vault_pass = pb_cli.ask_vault_passwords() else: vault_pass = pb_cli.read_vault_password_file( self.app.pargs.vault_password_file, loader) if vault_pass is not None: loader.set_vault_password(vault_pass) # create the inventory, and filter it based on the subset specified (if any) host_list = self.app.pargs.inventory if self.app.pargs.inventory else constants.DEFAULT_HOST_LIST # FIXME: This should parse any arguments provided via -e or --extra-vars. Currently it seems # to parse the argument value wrongly and returns # '_raw_params': '<last character in variable>'. This prevents the ability to use # --extra-vars when executing plays. variable_manager = VariableManager() options = Options( verbosity=self.app.pargs.verbose, inventory=self.app.pargs.inventory, subset=self.app.pargs.limit, extra_vars=[self.app.pargs.extra_vars], forks=self.app.pargs.forks, ask_vault_pass=self.app.pargs.ask_vault_pass, vault_password_files=self.app.pargs.vault_password_file, tags=self.app.pargs.tags, skip_tags=self.app.pargs.skip_tags, become=self.app.pargs.become, become_method=self.app.pargs.become_method, become_user=self.app.pargs.become_user, become_ask_pass=self.app.pargs.ask_become_pass, ask_pass=self.app.pargs.ask_pass, private_key_file=self.app.pargs.private_key, remote_user=self.app.pargs.user, connection=self.app.pargs.connection, timeout=self.app.pargs.timeout, ssh_common_args=self.app.pargs.ssh_common_args, sftp_extra_args=self.app.pargs.sftp_extra_args, ssh_extra_args=self.app.pargs.ssh_extra_args, scp_extra_args=self.app.pargs.scp_extra_args, flush_cache=self.app.pargs.flush_cache, module_path=self.app.pargs.module_path) inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=host_list) variable_manager.extra_vars = load_extra_vars(loader=loader, options=options) #variable_manager.options_vars = load_options_vars(options) if self.app.pargs.flush_cache: inventory.refresh_inventory() no_hosts = False if len(inventory.list_hosts()) == 0: print( Fore.YELLOW + "Warning! Provided hosts list is empty, only localhost is available." ) no_hosts = True # FIXME: Limit is currently ignored. inventory.subset(self.app.pargs.limit) if len(inventory.list_hosts()) == 0 and no_hosts is False: # Invalid limit print(Fore.RED + "Error! Specified --limit does not match any hosts.") sys.exit(1) play_data = loader.load_from_file(playbook_path) host_list = inventory.get_hosts( pattern=self.app.pargs.limit ) if self.app.pargs.limit else inventory.get_hosts() playbook = Playbook(loader=loader).load( playbook_path, variable_manager=variable_manager, loader=loader) pbex = PlaybookExecutor(playbooks=playbook.get_plays(), inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords) # Ansible variables matching these strings will be excluded from the generated yaml content. ignored_elements = [ 'ansible_playbook_python', 'ansible_version', 'group_names', 'inventory_hostname', 'inventory_hostname_short', 'omit', 'playbook_dir', 'role_names' ] json_data = {} for host in host_list: host_vars = host.get_vars() host_name = host_vars[ 'ansible_host'] if 'ansible_host' in host_vars.keys( ) else host.get_name() for play in playbook.get_plays(): loader.set_vault_password(vault_pass) all_vars = variable_manager.get_vars(loader=loader, play=play, host=host) json_data[host_name] = all_vars['vars'] json_data[host_name]['ansible_groups'] = all_vars[ 'group_names'] json_data[host_name]['ansible_roles'] = all_vars['role_names'] for elem in ignored_elements: del json_data['{}'.format(host)][elem] json_data[host_name][ 'ansible_become_user'] = self.app.pargs.become_user if passwords['become_pass'] is not None: json_data[host_name]['ansible_become_pass'] = passwords[ 'become_pass'] json_data[host_name]['ansible_become'] = self.app.pargs.become json_data[host_name][ 'ansible_become_method'] = self.app.pargs.become_method if self.app.pargs.ssh_extra_args: json_data[host_name][ 'ansible_ssh_extra_args'] = self.app.pargs.ssh_extra_args if self.app.pargs.scp_extra_args: json_data[host_name][ 'ansible_scp_extra_args'] = self.app.pargs.scp_extra_args if self.app.pargs.sftp_extra_args: json_data[host_name][ 'ansible_sftp_extra_args'] = self.app.pargs.sftp_extra_args if self.app.pargs.ssh_common_args: json_data[host_name][ 'ansible_ssh_common_args'] = self.app.pargs.ssh_common_args json_data[host_name][ 'ansible_connection_timeout'] = self.app.pargs.timeout json_data[host_name][ 'ansible_connection_method'] = self.app.pargs.connection if self.app.pargs.private_key: json_data[host_name][ 'ansible_private_key'] = self.app.pargs.private_key json_data[host_name][ 'ansible_ask_pass'] = self.app.pargs.ask_pass if self.app.pargs.limit: json_data[host_name][ 'ansible_limit'] = self.app.pargs.limit # FIXME: Extra vars needs to be processed by Ansible instead of dumping them # here as a "dumb" string. if self.app.pargs.extra_vars: json_data[host_name][ 'ansible_extra_vars'] = self.app.pargs.extra_vars for key, value in json_data[host_name].iteritems(): if type(value) is AnsibleVaultEncryptedUnicode: json_data[host_name][key] = str(value) # Convert the processed python dictionary to a valid json string json_obj = json.dumps(json_data) # Take the json string, and convert it to a valid yaml string yml = YAML(typ="safe", pure=True) yml.default_flow_style = False yml_obj = yml.load(json_obj) if self.app.pargs.output is None: yml.dump(yml_obj, sys.stdout) else: with open(self.app.pargs.output, 'w') as outfile: yml.dump(yml_obj, outfile) print(Fore.GREEN + "Ansible variable dictionary written to {}".format( self.app.pargs.output)) sys.exit(1)