ansible 2.9.4 - task with delegate_to: <windows_host> works, subsequent tasks fail

Hi All, hope this question makes sense. Here goes:

Context: I have several automated patching playbooks that rely on stopping/starting services on windows before patching a database on Linux. We are using a python script to generate a dynamic inventory. We are leveraging a powershell script on a windows host to remotely start/stop services on various other windows hosts, so we only need to delegate to the one single windows host that houses the powershell scripts. We are NOT naming the windows host in the python script for dynamic inventory, and instead delegating to the FQDN of the windows host, backed by a host_vars/<windows_server>.yml for connection info for ansible to use. Oh and we are using psexec because I can’t get win_shell to work to save my life.

Tasks:

- name: Pre-patching - Copy powershell script to stop service (windows)
run_once: true
become: false
win_copy:
src: …/supporting_tools/scripts/serviceshutdown{{ vmenv_result.stdout }}
dest: C:\temp\serviceshutdown{{ vmenv_result.stdout }}.ps1
force: no
delegate_to: windows_server

- name: Pre-patching - Copy psexec to stop service (windows)
run_once: true
become: false
win_copy:
src: …/supporting_tools/scripts/PsExec.exe
dest: C:\temp\PsExec.exe
force: no

delegate_to: windows_server

- name: Pre-patching - Stop service (windows)
become: false
run_once: true
win_psexec:
command: powershell.exe -executionpolicy bypass -noninteractive -nologo -file “C:\temp\serviceshutdown{{ vmenv_result.stdout }}.ps1”
executable: C:\temp\PsExec.exe
elevated: yes
nobanner: yes
username: “{{ansible_user}}”
password: “{{ansible_password}}”
interactive: no
vars:
ansible_become_method: runas

delegate_to: windows_server

host_vars/windows_server.yml:
ansible_user: ad_user
ansible_password: password
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore

ansible_port: 5986

Hi All, hope this question makes sense. Here goes:

Context: I have several automated patching playbooks that rely on stopping/starting services on windows before patching
a database on Linux. We are using a python script to generate a dynamic inventory. We are leveraging a powershell script
on a windows host to remotely start/stop services on various other windows hosts, so we only need to delegate to the one
single windows host that houses the powershell scripts. We are NOT naming the windows host in the python script for
dynamic inventory, and instead delegating to the FQDN of the windows host, backed by a host_vars/<windows_server>.yml
for connection info for ansible to use. Oh and we are using psexec because I can't get win_shell to work to save my life.

Tasks:
*- name: Pre-patching - Copy powershell script to stop service (windows)*
* run_once: true*
* become: false*
* win_copy:*
* src: ../supporting_tools/scripts/serviceshutdown{{ vmenv_result.stdout }}*
* dest: C:\temp\serviceshutdown{{ vmenv_result.stdout }}.ps1*
* force: no*
* delegate_to: windows_server*
*
*
*- name: Pre-patching - Copy psexec to stop service (windows)*
* run_once: true*
* become: false*
* win_copy:*
* src: ../supporting_tools/scripts/PsExec.exe*
* dest: C:\temp\PsExec.exe*
* force: no*
* delegate_to: windows_server*
*
*
*- name: Pre-patching - Stop service (windows)*
* become: false*
* run_once: true*
* win_psexec:*
* command: powershell.exe -executionpolicy bypass -noninteractive -nologo -file "C:\temp\serviceshutdown{{
vmenv_result.stdout }}.ps1"*
* executable: C:\temp\PsExec.exe*
* elevated: yes*
* nobanner: yes*
* username: "{{ansible_user}}"*
* password: "{{ansible_password}}"*
* interactive: no*
* vars:*
* ansible_become_method: runas*
* delegate_to: windows_server*

host_vars/windows_server.yml:
*ansible_user: ad_user
ansible_password: password
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
*
*ansible_port: 5986*

--------------------
The above role tasks run fine. Services get stopped as expected and the playbook moves on. However the next role is to
gather the current repo information from the linux server that is to be patched and is a block that is a mix of
delegate_to: 127.0.0.1 tasks and non delegated tasks (i.e.: they run on the target linux server). This is where the
playbook falls down and goes boom. The first non-delegated task after delegating to the windows server above fails with
the following error:

fatal: [linux_server]: FAILED! => msg: The powershell shell family is incompatible with the sudo become plugin

The role in question is:

- name: Pre-patching - Update sw.repo block: - name: Pre-patching - gather minor OS target version shell: curl -sk -u
user:pass "https://server.fqdn.com/cgi-bin/patchmm?major=\{{ ansible_distribution_major_version }}&os={{ os_shorthand }}"
args: warn: false register: minor_version changed_when: false become: false delegate_to: 127.0.0.1 - name: Pre-patching
- gather local errata repo name shell: yum repolist | grep ERRATA_ | awk '{print $1}' register: current_errata_repo
args: warn: false changed_when: false

when: ansible_distribution != 'Debian' and ansible_distribution != 'Ubuntu' and not (facter_os.family == "RedHat" and
ansible_distribution_major_version == "8")

The task in red is what is failing. I'm not sure why I'm getting this failure message since I'm not trying to use any
powershell commands or even target a windows server. I've tried putting ansible_become_method in the host_vars file with
no difference in results. Using win_shell to run a command to turn on or off a service seems to work, but I do not want
to have to target 8 or 9 windows servers individually (for this one application alone. there are others with more
servers behind them). Has anyone run across this before? What is the resolution here? Is it because I am not targeting
the windows host in inventory? I'd like to not do that because the entire playbook and all 50 or so included roles are
geared to linux only and I do not want to have to add when clauses everywhere.

Hello Andrew,

what are your connection settings for the linux_server host?

Regards
        Racke

@Racke,

These are my ansible.cfg settings. The playbook is called with ‘become: true’ since most tasks require elevated rights:

[defaults]
forks = 60
poll_interval = 15
become_user = root
remote_port = 22
host_key_checking = False
become_exe = sudo
timeout = 60
callback_whitelist = timer, profile_tasks
display_skipped_hosts = no
force_color = True
stdout_callback = yaml
bin_ansible_callbacks = True
gather_subset=!all,min,facter,!hardware,!network,!virtual,!ohai

[paramiko_connection]
record_host_keys = False
host_key_checking = False

[ssh_connection]
ssh_args = -o ControlMaster=no -o ControlPersist=60s -o ControlPath=/tmp/ssh-%h -o StrictHostKeyChecking=no
scp_if_ssh = True
retries = 2
pipelining = True

In hindsight this is pretty obvious – I did not realize I was stepping on some ansible built-ins like become_method and whatnot. adding a set_fact task after the windows execution solved this issue…