mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
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:
parent
bdd838f876
commit
d732c94ac2
9 changed files with 72 additions and 35 deletions
|
@ -38,34 +38,40 @@ class ConnectionInformation:
|
||||||
connection/authentication information.
|
connection/authentication information.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, play=None, options=None):
|
def __init__(self, play=None, options=None, passwords=None):
|
||||||
# FIXME: implement the new methodology here for supporting
|
|
||||||
# various different auth escalation methods (becomes, etc.)
|
|
||||||
|
|
||||||
self.connection = C.DEFAULT_TRANSPORT
|
if passwords is None:
|
||||||
|
passwords = {}
|
||||||
|
|
||||||
|
# connection
|
||||||
|
self.connection = None
|
||||||
self.remote_addr = None
|
self.remote_addr = None
|
||||||
self.remote_user = 'root'
|
self.remote_user = None
|
||||||
self.password = ''
|
self.password = passwords.get('conn_pass','')
|
||||||
self.port = 22
|
self.port = None
|
||||||
self.private_key_file = 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.verbosity = 0
|
||||||
self.only_tags = set()
|
self.only_tags = set()
|
||||||
self.skip_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.no_log = False
|
||||||
self.check_mode = 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:
|
if play:
|
||||||
self.set_play(play)
|
self.set_play(play)
|
||||||
|
|
||||||
if options:
|
|
||||||
self.set_options(options)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
value = "CONNECTION INFO:\n"
|
value = "CONNECTION INFO:\n"
|
||||||
|
@ -84,12 +90,18 @@ class ConnectionInformation:
|
||||||
if play.connection:
|
if play.connection:
|
||||||
self.connection = play.connection
|
self.connection = play.connection
|
||||||
|
|
||||||
self.remote_user = play.remote_user
|
if play.remote_user:
|
||||||
self.password = ''
|
self.remote_user = play.remote_user
|
||||||
self.port = int(play.port) if play.port else 22
|
|
||||||
self.become = play.become
|
if play.port:
|
||||||
self.become_method = play.become_method
|
self.port = int(play.port)
|
||||||
self.become_user = play.become_user
|
|
||||||
|
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
|
self.become_pass = play.become_pass
|
||||||
|
|
||||||
# non connection related
|
# non connection related
|
||||||
|
@ -103,15 +115,30 @@ class ConnectionInformation:
|
||||||
higher precedence than those set on the play or host.
|
higher precedence than those set on the play or host.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# FIXME: set other values from options here?
|
|
||||||
|
|
||||||
self.verbosity = options.verbosity
|
|
||||||
if options.connection:
|
if options.connection:
|
||||||
self.connection = 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:
|
if options.check:
|
||||||
self.check_mode = boolean(options.check)
|
self.check_mode = boolean(options.check)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# get the tag info from options, converting a comma-separated list
|
# 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
|
# 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
|
# options have the attribute, as it is not always added via the CLI
|
||||||
|
|
|
@ -36,18 +36,19 @@ class PlaybookExecutor:
|
||||||
basis for bin/ansible-playbook operation.
|
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._playbooks = playbooks
|
||||||
self._inventory = inventory
|
self._inventory = inventory
|
||||||
self._variable_manager = variable_manager
|
self._variable_manager = variable_manager
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
self._display = display
|
self._display = display
|
||||||
self._options = options
|
self._options = options
|
||||||
|
self.passwords = {'conn_pass': conn_pass, 'become_pass': become_pass}
|
||||||
|
|
||||||
if options.listhosts or options.listtasks or options.listtags:
|
if options.listhosts or options.listtasks or options.listtags:
|
||||||
self._tqm = None
|
self._tqm = None
|
||||||
else:
|
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):
|
def run(self):
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ class TaskQueueManager:
|
||||||
which dispatches the Play's tasks to hosts.
|
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._inventory = inventory
|
||||||
self._variable_manager = variable_manager
|
self._variable_manager = variable_manager
|
||||||
|
@ -56,6 +56,7 @@ class TaskQueueManager:
|
||||||
self._display = display
|
self._display = display
|
||||||
self._options = options
|
self._options = options
|
||||||
self._stats = AggregateStats()
|
self._stats = AggregateStats()
|
||||||
|
self.passwords = passwords
|
||||||
|
|
||||||
# a special flag to help us exit cleanly
|
# a special flag to help us exit cleanly
|
||||||
self._terminated = False
|
self._terminated = False
|
||||||
|
@ -144,7 +145,7 @@ class TaskQueueManager:
|
||||||
new_play = play.copy()
|
new_play = play.copy()
|
||||||
new_play.post_validate(all_vars, fail_on_undefined=False)
|
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:
|
for callback_plugin in self._callback_plugins:
|
||||||
if hasattr(callback_plugin, 'set_connection_info'):
|
if hasattr(callback_plugin, 'set_connection_info'):
|
||||||
callback_plugin.set_connection_info(connection_info)
|
callback_plugin.set_connection_info(connection_info)
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Play(Base, Taggable, Become):
|
||||||
_hosts = FieldAttribute(isa='list', default=[], required=True)
|
_hosts = FieldAttribute(isa='list', default=[], required=True)
|
||||||
_name = FieldAttribute(isa='string', default='<no name specified>')
|
_name = FieldAttribute(isa='string', default='<no name specified>')
|
||||||
_port = FieldAttribute(isa='int', default=22)
|
_port = FieldAttribute(isa='int', default=22)
|
||||||
_remote_user = FieldAttribute(isa='string', default='root')
|
_remote_user = FieldAttribute(isa='string')
|
||||||
|
|
||||||
# Variable Attributes
|
# Variable Attributes
|
||||||
_vars = FieldAttribute(isa='dict', default=dict())
|
_vars = FieldAttribute(isa='dict', default=dict())
|
||||||
|
|
|
@ -415,7 +415,11 @@ class ActionBase:
|
||||||
# FIXME: in error situations, the stdout may not contain valid data, so we
|
# FIXME: in error situations, the stdout may not contain valid data, so we
|
||||||
# should check for bad rc codes better to catch this here
|
# should check for bad rc codes better to catch this here
|
||||||
if 'stdout' in res and res['stdout'].strip():
|
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:
|
if 'parsed' in data and data['parsed'] == False:
|
||||||
data['msg'] += res['stderr']
|
data['msg'] += res['stderr']
|
||||||
# pre-split stdout into lines, if stdout is in the data and there
|
# pre-split stdout into lines, if stdout is in the data and there
|
||||||
|
|
|
@ -37,6 +37,9 @@ class Connection(ConnectionBase):
|
||||||
|
|
||||||
def connect(self, port=None):
|
def connect(self, port=None):
|
||||||
''' connect to the local host; nothing to do here '''
|
''' 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
|
return self
|
||||||
|
|
||||||
def exec_command(self, cmd, tmp_path, executable='/bin/sh', in_data=None):
|
def exec_command(self, cmd, tmp_path, executable='/bin/sh', in_data=None):
|
||||||
|
|
|
@ -57,7 +57,7 @@ class Connection(ConnectionBase):
|
||||||
def connect(self):
|
def connect(self):
|
||||||
''' connect to the remote host '''
|
''' 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 = []
|
self._common_args = []
|
||||||
extra_args = C.ANSIBLE_SSH_ARGS
|
extra_args = C.ANSIBLE_SSH_ARGS
|
||||||
|
@ -99,7 +99,7 @@ class Connection(ConnectionBase):
|
||||||
self._common_args += ["-o", "KbdInteractiveAuthentication=no",
|
self._common_args += ["-o", "KbdInteractiveAuthentication=no",
|
||||||
"-o", "PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey",
|
"-o", "PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey",
|
||||||
"-o", "PasswordAuthentication=no"]
|
"-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]
|
self._common_args += ["-o", "User="+self._connection_info.remote_user]
|
||||||
# FIXME: figure out where this goes
|
# FIXME: figure out where this goes
|
||||||
#self._common_args += ["-o", "ConnectTimeout=%d" % self.runner.timeout]
|
#self._common_args += ["-o", "ConnectTimeout=%d" % self.runner.timeout]
|
||||||
|
|
|
@ -93,6 +93,7 @@ class Cli(object):
|
||||||
|
|
||||||
normalize_become_options(options)
|
normalize_become_options(options)
|
||||||
(sshpass, becomepass, vault_pass) = ask_passwords(options)
|
(sshpass, becomepass, vault_pass) = ask_passwords(options)
|
||||||
|
passwords = { 'conn_pass': sshpass, 'become_pass': becomepass }
|
||||||
|
|
||||||
if options.vault_password_file:
|
if options.vault_password_file:
|
||||||
# read vault_pass from a file
|
# read vault_pass from a file
|
||||||
|
@ -138,7 +139,7 @@ class Cli(object):
|
||||||
# now create a task queue manager to execute the play
|
# now create a task queue manager to execute the play
|
||||||
try:
|
try:
|
||||||
display = Display()
|
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)
|
result = tqm.run(play)
|
||||||
tqm.cleanup()
|
tqm.cleanup()
|
||||||
except AnsibleError:
|
except AnsibleError:
|
||||||
|
|
|
@ -127,7 +127,7 @@ def main(display, args):
|
||||||
raise errors.AnsibleError("Specified --limit does not match any hosts")
|
raise errors.AnsibleError("Specified --limit does not match any hosts")
|
||||||
|
|
||||||
# create the playbook executor, which manages running the plays via a task queue manager
|
# 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()
|
results = pbex.run()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue