ansible/v2/bin/ansible-playbook
James Cammarata 2aeb79f45f Starting work on getting integration tests working on v2
This is incomplete work, and requires some minor tweeks to the integration
tests which are not included in this commit.
2015-01-12 16:07:01 -06:00

162 lines
7.2 KiB
Python
Executable file

#!/usr/bin/env python
import os
import stat
import sys
from ansible import constants as C
from ansible.errors import AnsibleError
from ansible.executor.playbook_executor import PlaybookExecutor
from ansible.inventory import Inventory
from ansible.parsing import DataLoader
from ansible.parsing.splitter import parse_kv
from ansible.playbook import Playbook
from ansible.playbook.task import Task
from ansible.utils.cli import base_parser
from ansible.utils.vars import combine_vars
from ansible.vars import VariableManager
#---------------------------------------------------------------------------------------------------
def main(args):
''' run ansible-playbook operations '''
# create parser for CLI options
parser = base_parser(
usage = "%prog playbook.yml",
connect_opts=True,
runas_opts=True,
subset_opts=True,
check_opts=True,
diff_opts=True
)
#parser.add_option('--vault-password', dest="vault_password",
# help="password for vault encrypted files")
parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append",
help="set additional variables as key=value or YAML/JSON", default=[])
parser.add_option('-t', '--tags', dest='tags', default='all',
help="only run plays and tasks tagged with these values")
parser.add_option('--skip-tags', dest='skip_tags',
help="only run plays and tasks whose tags do not match these values")
parser.add_option('--syntax-check', dest='syntax', action='store_true',
help="perform a syntax check on the playbook, but do not execute it")
parser.add_option('--list-tasks', dest='listtasks', action='store_true',
help="list all tasks that would be executed")
parser.add_option('--step', dest='step', action='store_true',
help="one-step-at-a-time: confirm each task before running")
parser.add_option('--start-at-task', dest='start_at',
help="start the playbook at the task matching this name")
parser.add_option('--force-handlers', dest='force_handlers', action='store_true',
help="run handlers even if a task fails")
parser.add_option('--flush-cache', dest='flush_cache', action='store_true',
help="clear the fact cache")
options, args = parser.parse_args(args)
if len(args) == 0:
parser.print_help(file=sys.stderr)
return 1
#---------------------------------------------------------------------------------------------------
# FIXME: su/sudo stuff needs to be generalized
# su and sudo command line arguments need to be mutually exclusive
#if (options.su or options.su_user or options.ask_su_pass) and \
# (options.sudo or options.sudo_user or options.ask_sudo_pass):
# parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') "
# "and su arguments ('-su', '--su-user', and '--ask-su-pass') are "
# "mutually exclusive")
#
#if (options.ask_vault_pass and options.vault_password_file):
# parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
#
#sshpass = None
#sudopass = None
#su_pass = None
#vault_pass = None
#
#options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
#
#if options.listhosts or options.syntax or options.listtasks:
# (_, _, _, vault_pass) = utils.ask_passwords(ask_vault_pass=options.ask_vault_pass)
#else:
# options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS
# # Never ask for an SSH password when we run with local connection
# if options.connection == "local":
# options.ask_pass = False
# options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS
# options.ask_su_pass = options.ask_su_pass or C.DEFAULT_ASK_SU_PASS
# (sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
# options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
# options.su_user = options.su_user or C.DEFAULT_SU_USER
#
## read vault_pass from a file
#if not options.ask_vault_pass and options.vault_password_file:
# vault_pass = utils.read_vault_file(options.vault_password_file)
# END FIXME
#---------------------------------------------------------------------------------------------------
# FIXME: this hard-coded value will be removed after fixing the removed block
# above, which dealt wtih asking for passwords during runtime
vault_pass = 'testing'
loader = DataLoader(vault_password=vault_pass)
extra_vars = {}
for extra_vars_opt in options.extra_vars:
if extra_vars_opt.startswith("@"):
# Argument is a YAML file (JSON is a subset of YAML)
data = loader.load_from_file(extra_vars_opt[1:])
extra_vars = combine_vars(extra_vars, data)
elif extra_vars_opt and extra_vars_opt[0] in '[{':
# Arguments as YAML
data = loader.load(extra_vars)
extra_vars = combine_vars(extra_vars, data)
else:
# Arguments as Key-value
data = parse_kv(extra_vars_opt)
extra_vars = combine_vars(extra_vars, data)
# FIXME: this should be moved inside the playbook executor code
only_tags = options.tags.split(",")
skip_tags = options.skip_tags
if options.skip_tags is not None:
skip_tags = options.skip_tags.split(",")
# initial error check, to make sure all specified playbooks are accessible
# before we start running anything through the playbook executor
for playbook in args:
if not os.path.exists(playbook):
raise AnsibleError("the playbook: %s could not be found" % playbook)
if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)):
raise AnsibleError("the playbook: %s does not appear to be a file" % playbook)
# create the variable manager, which will be shared throughout
# the code, ensuring a consistent view of global variables
variable_manager = VariableManager()
variable_manager.set_extra_vars(extra_vars)
# create the inventory, and filter it based on the subset specified (if any)
inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=options.inventory)
inventory.subset(options.subset)
if len(inventory.list_hosts()) == 0:
raise AnsibleError("provided hosts list is empty")
# create the playbook executor, which manages running the plays
# via a task queue manager
pbex = PlaybookExecutor(playbooks=args, inventory=inventory, variable_manager=variable_manager, loader=loader, options=options)
return pbex.run()
if __name__ == "__main__":
#display(" ", log_only=True)
#display(" ".join(sys.argv), log_only=True)
#display(" ", log_only=True)
try:
sys.exit(main(sys.argv[1:]))
except AnsibleError, e:
#display("ERROR: %s" % e, color='red', stderr=True)
print e
sys.exit(1)
except KeyboardInterrupt, ke:
#display("ERROR: interrupted", color='red', stderr=True)
print "keyboard interrupt"
sys.exit(1)