become - stop using play context in more places (#62373)
* become - stop using play context in more places - ci_complete * Fix up review points
This commit is contained in:
parent
a385ad321b
commit
480b106d65
13 changed files with 116 additions and 84 deletions
3
changelogs/fragments/become-pass-precedence.yaml
Normal file
3
changelogs/fragments/become-pass-precedence.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
bugfixes:
|
||||||
|
- become - Fix various plugins that still used play_context to get the become password instead of through the plugin - https://github.com/ansible/ansible/issues/62367
|
||||||
|
- runas - Fix the ``runas`` ``become_pass`` variable fallback from ``ansible_runas_runas`` to ``ansible_runas_pass``
|
|
@ -175,6 +175,17 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
final_environment = dict()
|
final_environment = dict()
|
||||||
self._compute_environment_string(final_environment)
|
self._compute_environment_string(final_environment)
|
||||||
|
|
||||||
|
become_kwargs = {}
|
||||||
|
if self._connection.become:
|
||||||
|
become_kwargs['become'] = True
|
||||||
|
become_kwargs['become_method'] = self._connection.become.name
|
||||||
|
become_kwargs['become_user'] = self._connection.become.get_option('become_user',
|
||||||
|
playcontext=self._play_context)
|
||||||
|
become_kwargs['become_password'] = self._connection.become.get_option('become_pass',
|
||||||
|
playcontext=self._play_context)
|
||||||
|
become_kwargs['become_flags'] = self._connection.become.get_option('become_flags',
|
||||||
|
playcontext=self._play_context)
|
||||||
|
|
||||||
# modify_module will exit early if interpreter discovery is required; re-run after if necessary
|
# modify_module will exit early if interpreter discovery is required; re-run after if necessary
|
||||||
for dummy in (1, 2):
|
for dummy in (1, 2):
|
||||||
try:
|
try:
|
||||||
|
@ -182,12 +193,8 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
task_vars=task_vars,
|
task_vars=task_vars,
|
||||||
module_compression=self._play_context.module_compression,
|
module_compression=self._play_context.module_compression,
|
||||||
async_timeout=self._task.async_val,
|
async_timeout=self._task.async_val,
|
||||||
become=self._play_context.become,
|
environment=final_environment,
|
||||||
become_method=self._play_context.become_method,
|
**become_kwargs)
|
||||||
become_user=self._play_context.become_user,
|
|
||||||
become_password=self._play_context.become_pass,
|
|
||||||
become_flags=self._play_context.become_flags,
|
|
||||||
environment=final_environment)
|
|
||||||
break
|
break
|
||||||
except InterpreterDiscoveryRequiredError as idre:
|
except InterpreterDiscoveryRequiredError as idre:
|
||||||
self._discovered_interpreter = AnsibleUnsafeText(discover_interpreter(
|
self._discovered_interpreter = AnsibleUnsafeText(discover_interpreter(
|
||||||
|
@ -260,7 +267,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
module_style == "new", # old style modules do not support pipelining
|
module_style == "new", # old style modules do not support pipelining
|
||||||
not C.DEFAULT_KEEP_REMOTE_FILES, # user wants remote files
|
not C.DEFAULT_KEEP_REMOTE_FILES, # user wants remote files
|
||||||
not wrap_async or self._connection.always_pipeline_modules, # async does not normally support pipelining unless it does (eg winrm)
|
not wrap_async or self._connection.always_pipeline_modules, # async does not normally support pipelining unless it does (eg winrm)
|
||||||
self._play_context.become_method != 'su', # su does not work with pipelining,
|
(self._connection.become.name if self._connection.become else '') != 'su', # su does not work with pipelining,
|
||||||
# FIXME: we might need to make become_method exclusion a configurable list
|
# FIXME: we might need to make become_method exclusion a configurable list
|
||||||
]:
|
]:
|
||||||
if not condition:
|
if not condition:
|
||||||
|
@ -298,7 +305,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
'''
|
'''
|
||||||
# if we don't use become then we know we aren't switching to a
|
# if we don't use become then we know we aren't switching to a
|
||||||
# different unprivileged user
|
# different unprivileged user
|
||||||
if not self._play_context.become:
|
if not self._connection.become:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# if we use become and the user is not an admin (or same user) then
|
# if we use become and the user is not an admin (or same user) then
|
||||||
|
@ -634,7 +641,7 @@ class ActionBase(with_metaclass(ABCMeta, object)):
|
||||||
become_user = self.get_become_option('become_user')
|
become_user = self.get_become_option('become_user')
|
||||||
if getattr(self._connection, '_remote_is_local', False):
|
if getattr(self._connection, '_remote_is_local', False):
|
||||||
pass
|
pass
|
||||||
elif sudoable and self._play_context.become and become_user:
|
elif sudoable and self._connection.become and become_user:
|
||||||
expand_path = '~%s' % become_user
|
expand_path = '~%s' % become_user
|
||||||
else:
|
else:
|
||||||
# use remote user instead, if none set default to current user
|
# use remote user instead, if none set default to current user
|
||||||
|
|
|
@ -72,7 +72,7 @@ class ActionModule(ActionBase):
|
||||||
source = self._remote_expand_user(source)
|
source = self._remote_expand_user(source)
|
||||||
|
|
||||||
remote_checksum = None
|
remote_checksum = None
|
||||||
if not self._play_context.become:
|
if not self._connection.become:
|
||||||
# calculate checksum for the remote file, don't bother if using become as slurp will be used
|
# calculate checksum for the remote file, don't bother if using become as slurp will be used
|
||||||
# Force remote_checksum to follow symlinks because fetch always follows symlinks
|
# Force remote_checksum to follow symlinks because fetch always follows symlinks
|
||||||
remote_checksum = self._remote_checksum(source, all_vars=task_vars, follow=True)
|
remote_checksum = self._remote_checksum(source, all_vars=task_vars, follow=True)
|
||||||
|
|
|
@ -8,6 +8,7 @@ from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
from ansible.parsing.yaml.objects import AnsibleUnicode
|
from ansible.parsing.yaml.objects import AnsibleUnicode
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
|
from ansible.plugins.loader import become_loader
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
@ -103,27 +104,19 @@ class ActionModule(ActionBase):
|
||||||
|
|
||||||
def _execute_module_with_become(self, module_name, module_args, task_vars,
|
def _execute_module_with_become(self, module_name, module_args, task_vars,
|
||||||
wrap_async, use_task):
|
wrap_async, use_task):
|
||||||
orig_become = self._play_context.become
|
orig_become = self._connection.become
|
||||||
orig_become_method = self._play_context.become_method
|
|
||||||
orig_become_user = self._play_context.become_user
|
|
||||||
|
|
||||||
if not use_task:
|
|
||||||
if orig_become is None or orig_become is False:
|
|
||||||
self._play_context.become = True
|
|
||||||
if orig_become_method != 'runas':
|
|
||||||
self._play_context.become_method = 'runas'
|
|
||||||
if orig_become_user is None or orig_become_user == 'root':
|
|
||||||
self._play_context.become_user = 'SYSTEM'
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if not use_task and orig_become is None:
|
||||||
|
become = become_loader.get('runas')
|
||||||
|
become.set_options(direct={'become_user': 'SYSTEM', 'become_pass': None})
|
||||||
|
self._connection.set_become_plugin(become)
|
||||||
|
|
||||||
module_res = self._execute_module(module_name=module_name,
|
module_res = self._execute_module(module_name=module_name,
|
||||||
module_args=module_args,
|
module_args=module_args,
|
||||||
task_vars=task_vars,
|
task_vars=task_vars,
|
||||||
wrap_async=wrap_async)
|
wrap_async=wrap_async)
|
||||||
finally:
|
finally:
|
||||||
self._play_context.become = orig_become
|
self._connection.set_become_plugin(orig_become)
|
||||||
self._play_context.become_method = orig_become_method
|
|
||||||
self._play_context.become_user = orig_become_user
|
|
||||||
|
|
||||||
return module_res
|
return module_res
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,19 @@ class BecomeBase(AnsiblePlugin):
|
||||||
self._id = ''
|
self._id = ''
|
||||||
self.success = ''
|
self.success = ''
|
||||||
|
|
||||||
|
def get_option(self, option, hostvars=None, playcontext=None):
|
||||||
|
""" Overrides the base get_option to provide a fallback to playcontext vars in case a 3rd party plugin did not
|
||||||
|
implement the base become options required in Ansible. """
|
||||||
|
# TODO: add deprecation warning for ValueError in devel that removes the playcontext fallback
|
||||||
|
try:
|
||||||
|
return super(BecomeBase, self).get_option(option, hostvars=hostvars)
|
||||||
|
except KeyError:
|
||||||
|
pc_fallback = ['become_user', 'become_pass', 'become_flags', 'become_exe']
|
||||||
|
if option not in pc_fallback:
|
||||||
|
raise
|
||||||
|
|
||||||
|
return getattr(playcontext, option, None)
|
||||||
|
|
||||||
def expect_prompt(self):
|
def expect_prompt(self):
|
||||||
"""This function assists connection plugins in determining if they need to wait for
|
"""This function assists connection plugins in determining if they need to wait for
|
||||||
a prompt. Both a prompt and a password are required.
|
a prompt. Both a prompt and a password are required.
|
||||||
|
|
|
@ -48,7 +48,7 @@ DOCUMENTATION = """
|
||||||
vars:
|
vars:
|
||||||
- name: ansible_become_password
|
- name: ansible_become_password
|
||||||
- name: ansible_become_pass
|
- name: ansible_become_pass
|
||||||
- name: ansible_runas_runas
|
- name: ansible_runas_pass
|
||||||
env:
|
env:
|
||||||
- name: ANSIBLE_BECOME_PASS
|
- name: ANSIBLE_BECOME_PASS
|
||||||
- name: ANSIBLE_RUNAS_PASS
|
- name: ANSIBLE_RUNAS_PASS
|
||||||
|
|
|
@ -249,7 +249,8 @@ class Connection(ConnectionBase):
|
||||||
selector.close()
|
selector.close()
|
||||||
|
|
||||||
if not self.become.check_success(become_output):
|
if not self.become.check_success(become_output):
|
||||||
p.stdin.write(to_bytes(self._play_context.become_pass, errors='surrogate_or_strict') + b'\n')
|
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
|
||||||
|
p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,8 @@ class Connection(ConnectionBase):
|
||||||
selector.close()
|
selector.close()
|
||||||
|
|
||||||
if not self.become.check_success(become_output):
|
if not self.become.check_success(become_output):
|
||||||
p.stdin.write(to_bytes(self._play_context.become_pass, errors='surrogate_or_strict') + b'\n')
|
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
|
||||||
|
p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -415,7 +415,9 @@ class Connection(ConnectionBase):
|
||||||
display.debug("chunk is: %s" % chunk)
|
display.debug("chunk is: %s" % chunk)
|
||||||
if not chunk:
|
if not chunk:
|
||||||
if b'unknown user' in become_output:
|
if b'unknown user' in become_output:
|
||||||
raise AnsibleError('user %s does not exist' % self._play_context.become_user)
|
n_become_user = to_native(self.become.get_option('become_user',
|
||||||
|
playcontext=self._play_context))
|
||||||
|
raise AnsibleError('user %s does not exist' % n_become_user)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
# raise AnsibleError('ssh connection closed waiting for password prompt')
|
# raise AnsibleError('ssh connection closed waiting for password prompt')
|
||||||
|
@ -432,8 +434,9 @@ class Connection(ConnectionBase):
|
||||||
break
|
break
|
||||||
|
|
||||||
if passprompt:
|
if passprompt:
|
||||||
if self._play_context.become and self._play_context.become_pass:
|
if self.become:
|
||||||
chan.sendall(to_bytes(self._play_context.become_pass) + b'\n')
|
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
|
||||||
|
chan.sendall(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
||||||
else:
|
else:
|
||||||
raise AnsibleError("A password is required but none was supplied")
|
raise AnsibleError("A password is required but none was supplied")
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -577,10 +577,6 @@ if ($bytes_read -gt 0) {
|
||||||
self._connected = False
|
self._connected = False
|
||||||
|
|
||||||
def _build_kwargs(self):
|
def _build_kwargs(self):
|
||||||
self._become_method = self._play_context.become_method
|
|
||||||
self._become_user = self._play_context.become_user
|
|
||||||
self._become_pass = self._play_context.become_pass
|
|
||||||
|
|
||||||
self._psrp_host = self.get_option('remote_addr')
|
self._psrp_host = self.get_option('remote_addr')
|
||||||
self._psrp_user = self.get_option('remote_user')
|
self._psrp_user = self.get_option('remote_user')
|
||||||
self._psrp_pass = self._play_context.password
|
self._psrp_pass = self._play_context.password
|
||||||
|
|
|
@ -837,7 +837,7 @@ class Connection(ConnectionBase):
|
||||||
# wait for a password prompt.
|
# wait for a password prompt.
|
||||||
state = states.index('awaiting_prompt')
|
state = states.index('awaiting_prompt')
|
||||||
display.debug(u'Initial state: %s: %s' % (states[state], to_text(prompt)))
|
display.debug(u'Initial state: %s: %s' % (states[state], to_text(prompt)))
|
||||||
elif self._play_context.become and self.become.success:
|
elif self.become and self.become.success:
|
||||||
# We're requesting escalation without a password, so we have to
|
# We're requesting escalation without a password, so we have to
|
||||||
# detect success/failure before sending any initial data.
|
# detect success/failure before sending any initial data.
|
||||||
state = states.index('awaiting_escalation')
|
state = states.index('awaiting_escalation')
|
||||||
|
@ -947,7 +947,8 @@ class Connection(ConnectionBase):
|
||||||
if states[state] == 'awaiting_prompt':
|
if states[state] == 'awaiting_prompt':
|
||||||
if self._flags['become_prompt']:
|
if self._flags['become_prompt']:
|
||||||
display.debug(u'Sending become_password in response to prompt')
|
display.debug(u'Sending become_password in response to prompt')
|
||||||
stdin.write(to_bytes(self._play_context.become_pass) + b'\n')
|
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
|
||||||
|
stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
||||||
# On python3 stdin is a BufferedWriter, and we don't have a guarantee
|
# On python3 stdin is a BufferedWriter, and we don't have a guarantee
|
||||||
# that the write will happen without a flush
|
# that the write will happen without a flush
|
||||||
stdin.flush()
|
stdin.flush()
|
||||||
|
@ -968,19 +969,19 @@ class Connection(ConnectionBase):
|
||||||
display.vvv(u'Escalation failed')
|
display.vvv(u'Escalation failed')
|
||||||
self._terminate_process(p)
|
self._terminate_process(p)
|
||||||
self._flags['become_error'] = False
|
self._flags['become_error'] = False
|
||||||
raise AnsibleError('Incorrect %s password' % self._play_context.become_method)
|
raise AnsibleError('Incorrect %s password' % self.become.name)
|
||||||
elif self._flags['become_nopasswd_error']:
|
elif self._flags['become_nopasswd_error']:
|
||||||
display.vvv(u'Escalation requires password')
|
display.vvv(u'Escalation requires password')
|
||||||
self._terminate_process(p)
|
self._terminate_process(p)
|
||||||
self._flags['become_nopasswd_error'] = False
|
self._flags['become_nopasswd_error'] = False
|
||||||
raise AnsibleError('Missing %s password' % self._play_context.become_method)
|
raise AnsibleError('Missing %s password' % self.become.name)
|
||||||
elif self._flags['become_prompt']:
|
elif self._flags['become_prompt']:
|
||||||
# This shouldn't happen, because we should see the "Sorry,
|
# This shouldn't happen, because we should see the "Sorry,
|
||||||
# try again" message first.
|
# try again" message first.
|
||||||
display.vvv(u'Escalation prompt repeated')
|
display.vvv(u'Escalation prompt repeated')
|
||||||
self._terminate_process(p)
|
self._terminate_process(p)
|
||||||
self._flags['become_prompt'] = False
|
self._flags['become_prompt'] = False
|
||||||
raise AnsibleError('Incorrect %s password' % self._play_context.become_method)
|
raise AnsibleError('Incorrect %s password' % self.become.name)
|
||||||
|
|
||||||
# Once we're sure that the privilege escalation prompt, if any, has
|
# Once we're sure that the privilege escalation prompt, if any, has
|
||||||
# been dealt with, we can send any initial data and start waiting
|
# been dealt with, we can send any initial data and start waiting
|
||||||
|
|
|
@ -143,6 +143,15 @@
|
||||||
- '"LogonUser failed" not in become_invalid_pass.msg'
|
- '"LogonUser failed" not in become_invalid_pass.msg'
|
||||||
- '"Win32ErrorCode 1326 - 0x0000052E)" not in become_invalid_pass.msg'
|
- '"Win32ErrorCode 1326 - 0x0000052E)" not in become_invalid_pass.msg'
|
||||||
|
|
||||||
|
- name: test become password precedence
|
||||||
|
win_whoami:
|
||||||
|
become: yes
|
||||||
|
become_method: runas
|
||||||
|
become_user: '{{ become_test_username }}'
|
||||||
|
vars:
|
||||||
|
ansible_become_pass: broken
|
||||||
|
ansible_runas_pass: '{{ gen_pw }}' # should have a higher precedence than ansible_become_pass
|
||||||
|
|
||||||
- name: test become + async
|
- name: test become + async
|
||||||
vars: *become_vars
|
vars: *become_vars
|
||||||
win_command: whoami
|
win_command: whoami
|
||||||
|
|
|
@ -6,13 +6,30 @@
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from units.compat.mock import patch, MagicMock
|
from units.compat.mock import patch, MagicMock
|
||||||
from ansible.plugins.action.win_updates import ActionModule
|
from ansible.plugins.action.win_updates import ActionModule
|
||||||
|
from ansible.plugins.become.runas import BecomeModule
|
||||||
from ansible.playbook.task import Task
|
from ansible.playbook.task import Task
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def test_win_updates():
|
||||||
|
task = MagicMock(Task)
|
||||||
|
task.args = {}
|
||||||
|
|
||||||
|
connection = MagicMock()
|
||||||
|
connection.module_implementation_preferences = ('.ps1', '.exe', '')
|
||||||
|
|
||||||
|
play_context = MagicMock()
|
||||||
|
play_context.check_mode = False
|
||||||
|
|
||||||
|
plugin = ActionModule(task, connection, play_context, loader=None, templar=None, shared_loader_obj=None)
|
||||||
|
return plugin
|
||||||
|
|
||||||
|
|
||||||
class TestWinUpdatesActionPlugin(object):
|
class TestWinUpdatesActionPlugin(object):
|
||||||
|
|
||||||
INVALID_OPTIONS = (
|
INVALID_OPTIONS = (
|
||||||
|
@ -58,58 +75,46 @@ class TestWinUpdatesActionPlugin(object):
|
||||||
assert res['failed']
|
assert res['failed']
|
||||||
assert expected in res['msg']
|
assert expected in res['msg']
|
||||||
|
|
||||||
BECOME_OPTIONS = (
|
def test_exec_with_become(self, test_win_updates):
|
||||||
(False, False, "sudo", "root", True, "runas", "SYSTEM"),
|
test_become = os.urandom(8)
|
||||||
(False, True, "sudo", "root", True, "runas", "SYSTEM"),
|
|
||||||
(False, False, "runas", "root", True, "runas", "SYSTEM"),
|
|
||||||
(False, False, "sudo", "user", True, "runas", "user"),
|
|
||||||
(False, None, "sudo", None, True, "runas", "SYSTEM"),
|
|
||||||
|
|
||||||
# use scheduled task, we shouldn't change anything
|
set_become_mock = MagicMock()
|
||||||
(True, False, "sudo", None, False, "sudo", None),
|
test_win_updates._connection.become = test_become
|
||||||
(True, True, "runas", "SYSTEM", True, "runas", "SYSTEM"),
|
test_win_updates._connection.set_become_plugin = set_become_mock
|
||||||
)
|
|
||||||
|
|
||||||
# pylint bug: https://github.com/PyCQA/pylint/issues/511
|
with patch('ansible.plugins.action.ActionBase._execute_module', new=MagicMock()):
|
||||||
# pylint: disable=undefined-variable
|
test_win_updates._execute_module_with_become('win_updates', {}, {}, True, False)
|
||||||
@pytest.mark.parametrize('use_task, o_b, o_bmethod, o_buser, e_b, e_bmethod, e_buser',
|
|
||||||
((u, ob, obm, obu, eb, ebm, ebu)
|
|
||||||
for u, ob, obm, obu, eb, ebm, ebu in BECOME_OPTIONS))
|
|
||||||
def test_module_exec_with_become(self, use_task, o_b, o_bmethod, o_buser,
|
|
||||||
e_b, e_bmethod, e_buser):
|
|
||||||
def mock_execute_module(self, **kwargs):
|
|
||||||
pc = self._play_context
|
|
||||||
return {"become": pc.become, "become_method": pc.become_method,
|
|
||||||
"become_user": pc.become_user}
|
|
||||||
|
|
||||||
task = MagicMock(Task)
|
# Asserts we don't override the become plugin.
|
||||||
task.args = {}
|
assert set_become_mock.call_count == 1
|
||||||
|
assert set_become_mock.mock_calls[0][1][0] == test_become
|
||||||
|
|
||||||
connection = MagicMock()
|
def test_exec_with_become_no_plugin_set(self, test_win_updates):
|
||||||
connection.module_implementation_preferences = ('.ps1', '.exe', '')
|
set_become_mock = MagicMock()
|
||||||
|
test_win_updates._connection.become = None
|
||||||
|
test_win_updates._connection.set_become_plugin = set_become_mock
|
||||||
|
|
||||||
play_context = MagicMock()
|
with patch('ansible.plugins.action.ActionBase._execute_module', new=MagicMock()):
|
||||||
play_context.check_mode = False
|
test_win_updates._execute_module_with_become('win_updates', {}, {}, True, False)
|
||||||
play_context.become = o_b
|
|
||||||
play_context.become_method = o_bmethod
|
|
||||||
play_context.become_user = o_buser
|
|
||||||
|
|
||||||
plugin = ActionModule(task, connection, play_context, loader=None,
|
assert set_become_mock.call_count == 2
|
||||||
templar=None, shared_loader_obj=None)
|
assert isinstance(set_become_mock.mock_calls[0][1][0], BecomeModule)
|
||||||
with patch('ansible.plugins.action.ActionBase._execute_module',
|
assert set_become_mock.mock_calls[0][1][0].name == 'runas'
|
||||||
new=mock_execute_module):
|
assert set_become_mock.mock_calls[0][1][0].get_option('become_user') == 'SYSTEM'
|
||||||
actual = plugin._execute_module_with_become('win_updates', {}, {},
|
assert set_become_mock.mock_calls[0][1][0].get_option('become_flags') == ''
|
||||||
True, use_task)
|
assert set_become_mock.mock_calls[0][1][0].get_option('become_pass') is None
|
||||||
|
assert set_become_mock.mock_calls[1][1] == (None,)
|
||||||
|
|
||||||
# always make sure we reset back to the defaults
|
def test_exec_with_become_no_plugin_set_use_task(self, test_win_updates):
|
||||||
assert play_context.become == o_b
|
set_become_mock = MagicMock()
|
||||||
assert play_context.become_method == o_bmethod
|
test_win_updates._connection.become = None
|
||||||
assert play_context.become_user == o_buser
|
test_win_updates._connection.set_become_plugin = set_become_mock
|
||||||
|
|
||||||
# verify what was set when _execute_module was called
|
with patch('ansible.plugins.action.ActionBase._execute_module', new=MagicMock()):
|
||||||
assert actual['become'] == e_b
|
test_win_updates._execute_module_with_become('win_updates', {}, {}, True, True)
|
||||||
assert actual['become_method'] == e_bmethod
|
|
||||||
assert actual['become_user'] == e_buser
|
assert set_become_mock.call_count == 1
|
||||||
|
assert set_become_mock.mock_calls[0][1][0] is None
|
||||||
|
|
||||||
def test_module_exec_async_result(self, monkeypatch):
|
def test_module_exec_async_result(self, monkeypatch):
|
||||||
return_val = {
|
return_val = {
|
||||||
|
|
Loading…
Reference in a new issue