mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Rearranging some become stuff in relation to action/connection plugins
Moving the make_sudo_cmd() calls back up to the action level so that connection plugins don't have to know about it at all, and moving some of the become data (prompt and success_key) into the ConnectionInformation object so they don't need to be passed around needlessly.
This commit is contained in:
parent
7a9b5b6fe8
commit
1c185b68be
6 changed files with 25 additions and 20 deletions
|
@ -161,6 +161,8 @@ class ConnectionInformation:
|
||||||
self.become_pass = passwords.get('become_pass','')
|
self.become_pass = passwords.get('become_pass','')
|
||||||
self.become_exe = None
|
self.become_exe = None
|
||||||
self.become_flags = None
|
self.become_flags = None
|
||||||
|
self.prompt = None
|
||||||
|
self.success_key = None
|
||||||
|
|
||||||
# backwards compat
|
# backwards compat
|
||||||
self.sudo_exe = None
|
self.sudo_exe = None
|
||||||
|
@ -317,18 +319,22 @@ class ConnectionInformation:
|
||||||
|
|
||||||
return new_info
|
return new_info
|
||||||
|
|
||||||
def make_become_cmd(self, cmd, executable=C.DEFAULT_EXECUTABLE):
|
def make_become_cmd(self, cmd, executable=None):
|
||||||
""" helper function to create privilege escalation commands """
|
""" helper function to create privilege escalation commands """
|
||||||
|
|
||||||
prompt = None
|
prompt = None
|
||||||
success_key = None
|
success_key = None
|
||||||
|
|
||||||
|
print("in make_become_cmd, executable is: %s" % executable)
|
||||||
|
if executable is None:
|
||||||
|
executable = C.DEFAULT_EXECUTABLE
|
||||||
|
|
||||||
if self.become:
|
if self.become:
|
||||||
|
|
||||||
becomecmd = None
|
becomecmd = None
|
||||||
randbits = ''.join(chr(random.randint(ord('a'), ord('z'))) for x in xrange(32))
|
randbits = ''.join(chr(random.randint(ord('a'), ord('z'))) for x in xrange(32))
|
||||||
success_key = 'BECOME-SUCCESS-%s' % randbits
|
success_key = 'BECOME-SUCCESS-%s' % randbits
|
||||||
executable = executable or '$SHELL'
|
#executable = executable or '$SHELL'
|
||||||
success_cmd = pipes.quote('echo %s; %s' % (success_key, cmd))
|
success_cmd = pipes.quote('echo %s; %s' % (success_key, cmd))
|
||||||
|
|
||||||
if self.become_method == 'sudo':
|
if self.become_method == 'sudo':
|
||||||
|
@ -371,9 +377,11 @@ class ConnectionInformation:
|
||||||
else:
|
else:
|
||||||
raise AnsibleError("Privilege escalation method not found: %s" % self.become_method)
|
raise AnsibleError("Privilege escalation method not found: %s" % self.become_method)
|
||||||
|
|
||||||
return (('%s -c ' % executable) + pipes.quote(becomecmd), prompt, success_key)
|
self.prompt = prompt
|
||||||
|
self.success_key = success_key
|
||||||
|
return ('%s -c ' % executable) + pipes.quote(becomecmd)
|
||||||
|
|
||||||
return (cmd, prompt, success_key)
|
return ('%s -c ' % executable) + pipes.quote(cmd)
|
||||||
|
|
||||||
def _get_fields(self):
|
def _get_fields(self):
|
||||||
return [i for i in self.__dict__.keys() if i[:1] != '_']
|
return [i for i in self.__dict__.keys() if i[:1] != '_']
|
||||||
|
|
|
@ -429,6 +429,10 @@ class ActionBase:
|
||||||
debug("no command, exiting _low_level_execute_command()")
|
debug("no command, exiting _low_level_execute_command()")
|
||||||
return dict(stdout='', stderr='')
|
return dict(stdout='', stderr='')
|
||||||
|
|
||||||
|
print("in _low_level_execute_command, executable is: %s" % executable)
|
||||||
|
if sudoable:
|
||||||
|
cmd = self._connection_info.make_become_cmd(cmd, executable=executable)
|
||||||
|
|
||||||
debug("executing the command %s through the connection" % cmd)
|
debug("executing the command %s through the connection" % cmd)
|
||||||
rc, stdin, stdout, stderr = self._connection.exec_command(cmd, tmp, in_data=in_data, sudoable=sudoable)
|
rc, stdin, stdout, stderr = self._connection.exec_command(cmd, tmp, in_data=in_data, sudoable=sudoable)
|
||||||
debug("command execution done")
|
debug("command execution done")
|
||||||
|
|
|
@ -118,7 +118,7 @@ class ConnectionBase(with_metaclass(ABCMeta, object)):
|
||||||
|
|
||||||
@ensure_connect
|
@ensure_connect
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def exec_command(self, cmd, tmp_path, in_data=None, sudoable=True):
|
def exec_command(self, cmd, tmp_path, in_data=None, executable=None, sudoable=True):
|
||||||
"""Run a command on the remote host"""
|
"""Run a command on the remote host"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -140,15 +140,15 @@ class ConnectionBase(with_metaclass(ABCMeta, object)):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def check_become_success(self, output):
|
def check_become_success(self, output):
|
||||||
return self.success_key in output
|
return self._connection_info.success_key in output
|
||||||
|
|
||||||
def check_password_prompt(self, output):
|
def check_password_prompt(self, output):
|
||||||
if self.prompt is None:
|
if self._connection_info.prompt is None:
|
||||||
return False
|
return False
|
||||||
elif isinstance(self.prompt, basestring):
|
elif isinstance(self._connection_info.prompt, basestring):
|
||||||
return output.endswith(self.prompt)
|
return output.endswith(self._connection_info.prompt)
|
||||||
else:
|
else:
|
||||||
return self.prompt(output)
|
return self._connection_info.prompt(output)
|
||||||
|
|
||||||
def check_incorrect_password(self, output):
|
def check_incorrect_password(self, output):
|
||||||
incorrect_password = gettext.dgettext(self._connection_info.become_method, C.BECOME_ERROR_STRINGS[self._connection_info.become_method])
|
incorrect_password = gettext.dgettext(self._connection_info.become_method, C.BECOME_ERROR_STRINGS[self._connection_info.become_method])
|
||||||
|
|
|
@ -59,9 +59,6 @@ class Connection(ConnectionBase):
|
||||||
raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
|
raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
|
||||||
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else None
|
executable = C.DEFAULT_EXECUTABLE.split()[0] if C.DEFAULT_EXECUTABLE else None
|
||||||
|
|
||||||
if sudoable:
|
|
||||||
cmd, self.prompt, self.success_key = self._connection_info.make_become_cmd(cmd)
|
|
||||||
|
|
||||||
self._display.vvv("{0} EXEC {1}".format(self._connection_info.remote_addr, cmd))
|
self._display.vvv("{0} EXEC {1}".format(self._connection_info.remote_addr, cmd))
|
||||||
# FIXME: cwd= needs to be set to the basedir of the playbook
|
# FIXME: cwd= needs to be set to the basedir of the playbook
|
||||||
debug("opening command with Popen()")
|
debug("opening command with Popen()")
|
||||||
|
@ -75,7 +72,7 @@ class Connection(ConnectionBase):
|
||||||
)
|
)
|
||||||
debug("done running command with Popen()")
|
debug("done running command with Popen()")
|
||||||
|
|
||||||
if self.prompt and self._connection_info.become_pass:
|
if self._connection_info.prompt and self._connection_info.become_pass:
|
||||||
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
|
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||||
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
|
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||||
become_output = ''
|
become_output = ''
|
||||||
|
|
|
@ -223,7 +223,7 @@ class Connection(ConnectionBase):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
chan.exec_command(cmd)
|
chan.exec_command(cmd)
|
||||||
if self.prompt:
|
if self._connection_info.prompt:
|
||||||
while True:
|
while True:
|
||||||
debug('Waiting for Privilege Escalation input')
|
debug('Waiting for Privilege Escalation input')
|
||||||
if self.check_become_success(become_output) or self.check_password_prompt(become_output):
|
if self.check_become_success(become_output) or self.check_password_prompt(become_output):
|
||||||
|
|
|
@ -345,13 +345,9 @@ class Connection(ConnectionBase):
|
||||||
ssh_cmd += ['-6']
|
ssh_cmd += ['-6']
|
||||||
ssh_cmd.append(self.host)
|
ssh_cmd.append(self.host)
|
||||||
|
|
||||||
if sudoable:
|
|
||||||
cmd, self.prompt, self.success_key = self._connection_info.make_become_cmd(cmd)
|
|
||||||
|
|
||||||
ssh_cmd.append(cmd)
|
ssh_cmd.append(cmd)
|
||||||
self._display.vvv("EXEC {0}".format(' '.join(ssh_cmd)), host=self.host)
|
self._display.vvv("EXEC {0}".format(' '.join(ssh_cmd)), host=self.host)
|
||||||
|
|
||||||
|
|
||||||
self.lock_host_keys(True)
|
self.lock_host_keys(True)
|
||||||
|
|
||||||
# create process
|
# create process
|
||||||
|
@ -362,7 +358,7 @@ class Connection(ConnectionBase):
|
||||||
no_prompt_out = ''
|
no_prompt_out = ''
|
||||||
no_prompt_err = ''
|
no_prompt_err = ''
|
||||||
|
|
||||||
if self.prompt:
|
if self._connection_info.prompt:
|
||||||
'''
|
'''
|
||||||
Several cases are handled for privileges with password
|
Several cases are handled for privileges with password
|
||||||
* NOPASSWD (tty & no-tty): detect success_key on stdout
|
* NOPASSWD (tty & no-tty): detect success_key on stdout
|
||||||
|
|
Loading…
Add table
Reference in a new issue