a bunch of updates to connection info and related, to pass down passwords

also now options populate required fields in required order allowing play to override
added capture of debug in action plugins when stdout is not json
This commit is contained in:
Brian Coca 2015-04-06 22:31:55 -04:00
parent bdd838f876
commit d732c94ac2
9 changed files with 72 additions and 35 deletions

View file

@ -38,34 +38,40 @@ class ConnectionInformation:
connection/authentication information.
'''
def __init__(self, play=None, options=None):
# FIXME: implement the new methodology here for supporting
# various different auth escalation methods (becomes, etc.)
def __init__(self, play=None, options=None, passwords=None):
self.connection = C.DEFAULT_TRANSPORT
if passwords is None:
passwords = {}
# connection
self.connection = None
self.remote_addr = None
self.remote_user = 'root'
self.password = ''
self.port = 22
self.remote_user = None
self.password = passwords.get('conn_pass','')
self.port = None
self.private_key_file = None
# privilege escalation
self.become = None
self.become_method = None
self.become_user = None
self.become_pass = passwords.get('become_pass','')
# general flags (should we move out?)
self.verbosity = 0
self.only_tags = set()
self.skip_tags = set()
# privilege escalation
self.become = False
self.become_method = C.DEFAULT_BECOME_METHOD
self.become_user = ''
self.become_pass = ''
self.no_log = False
self.check_mode = False
#TODO: just pull options setup to above?
# set options before play to allow play to override them
if options:
self.set_options(options)
if play:
self.set_play(play)
if options:
self.set_options(options)
def __repr__(self):
value = "CONNECTION INFO:\n"
@ -84,12 +90,18 @@ class ConnectionInformation:
if play.connection:
self.connection = play.connection
self.remote_user = play.remote_user
self.password = ''
self.port = int(play.port) if play.port else 22
self.become = play.become
self.become_method = play.become_method
self.become_user = play.become_user
if play.remote_user:
self.remote_user = play.remote_user
if play.port:
self.port = int(play.port)
if play.become is not None:
self.become = play.become
if play.become_method:
self.become_method = play.become_method
if play.become_user:
self.become_user = play.become_user
self.become_pass = play.become_pass
# non connection related
@ -103,15 +115,30 @@ class ConnectionInformation:
higher precedence than those set on the play or host.
'''
# FIXME: set other values from options here?
self.verbosity = options.verbosity
if options.connection:
self.connection = options.connection
self.remote_user = options.remote_user
#if 'port' in options and options.port is not None:
# self.port = options.port
self.private_key_file = None
# privilege escalation
self.become = options.become
self.become_method = options.become_method
self.become_user = options.become_user
self.become_pass = ''
# general flags (should we move out?)
if options.verbosity:
self.verbosity = options.verbosity
#if options.no_log:
# self.no_log = boolean(options.no_log)
if options.check:
self.check_mode = boolean(options.check)
# get the tag info from options, converting a comma-separated list
# of values into a proper list if need be. We check to see if the
# options have the attribute, as it is not always added via the CLI

View file

@ -36,18 +36,19 @@ class PlaybookExecutor:
basis for bin/ansible-playbook operation.
'''
def __init__(self, playbooks, inventory, variable_manager, loader, display, options):
def __init__(self, playbooks, inventory, variable_manager, loader, display, options, conn_pass, become_pass):
self._playbooks = playbooks
self._inventory = inventory
self._variable_manager = variable_manager
self._loader = loader
self._display = display
self._options = options
self.passwords = {'conn_pass': conn_pass, 'become_pass': become_pass}
if options.listhosts or options.listtasks or options.listtags:
self._tqm = None
else:
self._tqm = TaskQueueManager(inventory=inventory, callback='default', variable_manager=variable_manager, loader=loader, display=display, options=options)
self._tqm = TaskQueueManager(inventory=inventory, callback='default', variable_manager=variable_manager, loader=loader, display=display, options=options, passwords=self.passwords)
def run(self):

View file

@ -48,7 +48,7 @@ class TaskQueueManager:
which dispatches the Play's tasks to hosts.
'''
def __init__(self, inventory, callback, variable_manager, loader, display, options):
def __init__(self, inventory, callback, variable_manager, loader, display, options, passwords):
self._inventory = inventory
self._variable_manager = variable_manager
@ -56,6 +56,7 @@ class TaskQueueManager:
self._display = display
self._options = options
self._stats = AggregateStats()
self.passwords = passwords
# a special flag to help us exit cleanly
self._terminated = False
@ -144,7 +145,7 @@ class TaskQueueManager:
new_play = play.copy()
new_play.post_validate(all_vars, fail_on_undefined=False)
connection_info = ConnectionInformation(new_play, self._options)
connection_info = ConnectionInformation(new_play, self._options, self.passwords)
for callback_plugin in self._callback_plugins:
if hasattr(callback_plugin, 'set_connection_info'):
callback_plugin.set_connection_info(connection_info)

View file

@ -61,7 +61,7 @@ class Play(Base, Taggable, Become):
_hosts = FieldAttribute(isa='list', default=[], required=True)
_name = FieldAttribute(isa='string', default='<no name specified>')
_port = FieldAttribute(isa='int', default=22)
_remote_user = FieldAttribute(isa='string', default='root')
_remote_user = FieldAttribute(isa='string')
# Variable Attributes
_vars = FieldAttribute(isa='dict', default=dict())

View file

@ -415,7 +415,11 @@ class ActionBase:
# FIXME: in error situations, the stdout may not contain valid data, so we
# should check for bad rc codes better to catch this here
if 'stdout' in res and res['stdout'].strip():
data = json.loads(self._filter_leading_non_json_lines(res['stdout']))
try:
data = json.loads(self._filter_leading_non_json_lines(res['stdout']))
except ValueError:
# not valid json, lets try to capture error
data = {'traceback': res['stdout']}
if 'parsed' in data and data['parsed'] == False:
data['msg'] += res['stderr']
# pre-split stdout into lines, if stdout is in the data and there

View file

@ -37,6 +37,9 @@ class Connection(ConnectionBase):
def connect(self, port=None):
''' connect to the local host; nothing to do here '''
self._display.vvv("ESTABLISH LOCAL CONNECTION FOR USER: %s" % self._connection_info.remote_user, host=self._connection_info.remote_addr)
return self
def exec_command(self, cmd, tmp_path, executable='/bin/sh', in_data=None):

View file

@ -57,7 +57,7 @@ class Connection(ConnectionBase):
def connect(self):
''' connect to the remote host '''
self._display.vvv("ESTABLISH CONNECTION FOR USER: %s" % self._connection_info.remote_user, host=self._connection_info.remote_addr)
self._display.vvv("ESTABLISH SSH CONNECTION FOR USER: %s" % self._connection_info.remote_user, host=self._connection_info.remote_addr)
self._common_args = []
extra_args = C.ANSIBLE_SSH_ARGS
@ -99,7 +99,7 @@ class Connection(ConnectionBase):
self._common_args += ["-o", "KbdInteractiveAuthentication=no",
"-o", "PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey",
"-o", "PasswordAuthentication=no"]
if self._connection_info.remote_user != pwd.getpwuid(os.geteuid())[0]:
if self._connection_info.remote_user is not None and self._connection_info.remote_user != pwd.getpwuid(os.geteuid())[0]:
self._common_args += ["-o", "User="+self._connection_info.remote_user]
# FIXME: figure out where this goes
#self._common_args += ["-o", "ConnectTimeout=%d" % self.runner.timeout]

View file

@ -93,6 +93,7 @@ class Cli(object):
normalize_become_options(options)
(sshpass, becomepass, vault_pass) = ask_passwords(options)
passwords = { 'conn_pass': sshpass, 'become_pass': becomepass }
if options.vault_password_file:
# read vault_pass from a file
@ -138,7 +139,7 @@ class Cli(object):
# now create a task queue manager to execute the play
try:
display = Display()
tqm = TaskQueueManager(inventory=inventory, callback='minimal', variable_manager=variable_manager, loader=loader, display=display, options=options)
tqm = TaskQueueManager(inventory=inventory, callback='minimal', variable_manager=variable_manager, loader=loader, display=display, options=options, passwords=passwords)
result = tqm.run(play)
tqm.cleanup()
except AnsibleError:

View file

@ -127,7 +127,7 @@ def main(display, args):
raise errors.AnsibleError("Specified --limit does not match any hosts")
# 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, display=display, options=options)
pbex = PlaybookExecutor(playbooks=args, inventory=inventory, variable_manager=variable_manager, loader=loader, display=display, options=options, conn_pass=sshpass, become_pass=becomepass)
results = pbex.run()