I am new to Ansible and trying to run a playbook from my Ansible Controller (Linux box ) against Windows 10 (target machine). The playbook copies a PowerShell script (sample.ps1) from the controller to the target and runs it afterward. The PS script tries to modify an INI file in the target machine. The PS script runs fine if I RDP the target machine and run it from the Powershell window. But when I run it through Ansible Playbook, it does show that the file is changed but actually nothing changed. Here are the scripts and playbook.
Ansible Playbook: sample.yml
'''
name: "Ansible"
tasks:
- name: Copy Powershell script
win_copy:
src: /root/templates/sample.ps1
dest: "C:\\Temp\\"
force: yes
- name: Ensure the file is present on Remote Host
win_stat:
path: "C:\\Temp\\sample.ps1"
become: yes
become_method: runas
become_user: "{{host_name}}\\<<userId>>"
vars:
ansible_become_password: "<<password>>"
ansible_become_user: <<user>>
ansible_become: yes
- name: Run Powershell script
win_command: powershell.exe -
args:
stdin: '.\sample.ps1 -iniFile c:\temp\sample.ini'
chdir: "C:\\Temp\\"
become_method: runas
become_flags: logon_type=new_credentials logon_flags=netcredentials_only
become_user: "{{host_name}}\\<<userId>>"
vars:
ansible_become_password: <<password>>
ansible_become_user: <<user>>
ansible_become: yes
'''
Powershell script: sample.ps1
param ($iniFile)
$prop = Get-Content ($iniFile)
$prop = $prop -replace "xyz", "abc"
Set-Content -Path $iniFile -Value $prop
Run playbook like this:
ansible-playbook sample.yml --extra-vars "host_name=<<machineName>>" -vvvv
And here is the playbook output:
When I RDP the machine and see the content of the sample.ini file, it is unchanged.
Your help is appreciated.
I have a relatively simple requirement in my playbook (small example below). I have a Windows executable which sometimes will connect to a remote server first time, but sometimes doesn't. So I want to loop around the launch of the executable file and verify the tcp connection to the remote server has been established before moving on.
Below is a Windows play so far:
Download an executable (windows) or binary (linux) file from a url
Async launch of downloaded file on target
---
- hosts: target-1
vars:
remote_server_ip = '192.168.100.10'
remote_server_port = '9000'
tasks:
- name: Download executable from remote host
win_shell: |
Invoke-WebRequest -Uri "http://{{ software_repo }}/{{ filename }}" -OutFile "C:\\{{ file_name }}"
# Probably not needed, but this gives a tiny delay to ensure the file download is complete before execution.
- name: "Check file_name exists: C:\\{{ file_name }}"
win_stat:
path: "C:\\{{ file_name }}"
register: file_name_exists
- name: "Launch executable: {{ file_name }}"
win_shell: |
Start-Process -FilePath "C:\\{{ file_name }}" -PassThru
async: 10
poll: 0
register: result_launch_executable
become: true
when:
- file_name_exists.stat.exists
I want be able do the following (ideally for both Windows & Linux):
Confirm the executable has established a tcp connection to the remote_server_ip based on a specific IP and Port.
Loop around the process until the connection is 'established', time-out after x loops.
The following Windows PowerShell command gives me the confirmation I need showing the connection has been established, but not sure how to get this into the playbook.
Get-NetTCPConnection | where-object {$_.remoteaddress -eq '192.168.100.10'}
Caption :
...
...
RemoteAddress : 192.168.100.10
RemotePort : 8080
State : Established
can anyone assist with interrupting this code?
i need to pull out the variable output and test this
-can i pull out the var to a debug/msg?
also- im not sure if the with items is pulling the name of a host
that passed the check for the installation of application1
- name: check if application1 is installed if yes continue
win_shell: |
$application1 = ("","Wow6432Node: |ForEach-Object {Get-ChildItem HKLM:/SOFTWARE\$_\Microsoft\hostname }}"Windows\CurrentVersion\Uninstall\}
select#(n=Name;e={$.getvalue("displayname")}} Where {$. -like "*application1*"}).name.length -gt 0
with_items:"{{ hostname }}"
changed_when: false
ignore_errors: true
register: output
win_shell: echo output.stdout```
How to turn off IE enhanced security using ansible
Is there any way I can configure user account in Windows server by using ansible YAML
You can do this with powershell:
myscript.ps1:
$AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}"
$UserKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}"
Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0
Set-ItemProperty -Path $UserKey -Name "IsInstalled" -Value 0
Stop-Process -Name Explorer
Ansible playbook:
- name: example copying file with owner and permissions
copy:
src: myscript.ps1
dest: myscript.ps1
- name: Run ps1 script in privileged mode
hosts: "{{ my_hosts }}"
become_method: runas
vars:
ansible_become_password: passwordhere
tasks:
- win_shell: '.\myscript.ps1'
become: yes
become_user: Administrator
- name: Create new user
win_user:
name: someuser
password: somepassword
state: present
groups:
- Users
I'm trying to automate some tasks on Windows guests using Ansible, and I'm running into some issues mapping a network drive.
What I'm trying to do is map the drive, do something to it (in my example here, I just try to list the files), and then unmap it.
When I run Ansible, the output suggests that the shared drive was mapped successfully, but listing the files and unmapping both result in errors that state that the drive doesn't exist. ("A drive with the name 'K' does not exist.")
When I login to the Windows guest after running Ansible, the drive is mapped.
If I run Ansible while I am logged in the guest, the drive only becomes visible after I logout and log back in again. The script I use to mount the drive also creates a file on the guest for debugging purposes, and the file does appear even when I'm logged in. I don't need to logout and back in again for it to become visible. So it seems only the network drive mapping requires a logout and login to take effect.
I also tried "net use" to map the drive, and the results were the same.
My Ansible playbook looks like this. (I have left out some sensitive parts.)
tasks:
- name: Mount share
script: scripts/mount.ps1 {{ share }}
- name: Test
script: scripts/test.ps1
register: test
- name: Test stdout
debug: msg="{{ test.stdout }}"
- name: Test stderr
debug: msg="{{ test.stderr }}"
- name: Umount share
script: scripts/umount.ps1
mount.ps1.
param([string]$share)
$share | Out-File c:\ansible-test\debug.txt
New-PSDrive -Name "K" -PSProvider FileSystem -Root "$share" -Persist
test.ps1
Get-ChildItem K:\
umount.ps1
Remove-PSDrive "K"
Unfortunately this is down the way Ansible communicates with windows. I've had similar issues where commands and package installation didn't work as expected.
When Ansible communicates over WinRM to the windows box it initiates a batch connection, not a full session. Mapping drives is one of those tasks that requires a full session, but each task that Ansible runs creates it's own batch connection so when you map a drive as soon as it disconnects, you loose that mapping because there is no actual user to register it too.
The only work around you have here is to create a .ps1 to map the drive then use Invoke-Command.
Here is my work around :
- name: map drive and run a task
script: files/mapdrive.ps1 -network_password "{{ network_password }" -command_to_run "{ Copy-Item Y:\file_to_copy.txt C:\Some\Were }"
and my ps1 looks like this :
param(
$network_password,
$command_to_run
)
$PWord = ConvertTo-SecureString $network_password -AsPlainText -Force
$myCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "domain\user",$PWord
New-PSDrive -Name "Y" -PSProvider "FileSystem" -Root "\\remoteserver\share" -Credential $myCreds
Invoke-Command -ScriptBlock $command_to_run
Apparently future releases of Ansible will employ a form of "become" which will allow these persistent sessions making this type of task a lot easier, but that could be a couple of years away and at least 2 or 3 releases ahead.
After reading so many articles, stackoverflow links, I was unable to map network drive on windows because of multiple failure.
Finally, I wrote a custom ansible playbook which is a very very raw workaround -
---
- hosts: "{{hostname}}"
name: "MOUNT SMB SHARE"
gather_facts: no
vars:
already_mounted: false
drive_matched: false
drive_letter: "{{drive}}:"
share_path: '\\{{fs}}\{{share}}'
tasks:
- name: Delete status file if exists
file:
path: c:\\__run_status
state: absent
ignore_errors: yes
- name: Delete map_drive.ps1 if exists
file:
path: c:\\map_drive.ps1
state: absent
ignore_errors: yes
- name: Delete run.bat if exists
file:
path: c:\\run.bat
state: absent
ignore_errors: yes
- name: Delete task if exists
win_shell: schtasks.exe /DELETE /TN MAPDRIVE /F
register: command_output
ignore_errors: yes
- name: smb-mapping command
set_fact:
cmd1: New-SmbMapping -LocalPath {{drive_letter}} -Persistent 1
cmd2: -RemotePath {{share_path}} -UserName {{username}} -Password {{password}}
- name: Write powershell script
local_action:
module: copy
content: |
Enable-PSRemoting
if (Get-PSDrive {{drive}} -ErrorAction SilentlyContinue) {
Write-Host "Delete drive {{drive_letter}} which is already in use."
net use {{drive_letter}} /delete
}
{{cmd1}} {{cmd2}}
dest: /tmp/map_drive.ps1
- name: write wrapper batch
local_action:
module: copy
content: |
powershell.exe c:\\map_drive.ps1 >> c:\\__run_status
echo "FINISH" >> c:\\__run_status
dest: /tmp/run.bat
- name: Powershell script to map network drive
win_copy: src=/tmp/map_drive.ps1 dest=c:\\map_drive.ps1
register: result
until: result is success
retries: 3
delay: 30
- name: Batch script to run map network drive
win_copy: src=/tmp/run.bat dest=c:\\run.bat
register: result
until: result is success
retries: 3
delay: 30
- name: Register scheduled task commad args
set_fact:
cmd1: "Register-ScheduledTask 'MAPDRIVE' -InputObject"
cmd2: $(New-ScheduledTask -Action $(New-ScheduledTaskAction -Execute c:\run.bat)
cmd3: -Trigger $(New-ScheduledTaskTrigger -AtStartup))
cmd4: "-User {{win_user}} -Password {{win_pass}}"
- name: Register scheduled task commad
set_fact:
cmd: "powershell.exe {{cmd1}} {{cmd2}} {{cmd3}} {{cmd4}}"
- name: create batch script
local_action:
module: copy
content: "{{ cmd }}"
dest: /tmp/register_task.bat
- name: Wait for the windows server is able to connect
wait_for_connection:
connect_timeout: 120
delay: 2
- name: Copying batch to windows guest
win_copy: src=/tmp/register_task.bat dest=c:\\register_task.bat
register: result
until: result is success
retries: 3
delay: 30
- name: Pring command output
debug:
msg: "{{command_output.stdout}}"
- name: Register scheduled task
win_shell: C:\register_task.bat
register: command_output
- name: Debug
debug:
msg: "{{command_output}}"
- name: Start freesshd scheduled task
win_shell: powershell.exe "& Start-ScheduledTask -TaskName 'MAPDRIVE'"
register: command_output
- name: Query task
win_shell: "schtasks.exe /QUERY /TN MAPDRIVE"
register: command_output
- name: Pring command output
debug:
msg: "{{command_output.stdout}}"
- name: Check if map_drive.ps1 execution completed
win_shell: type C:\\__run_status
register: result
until: result.stdout.find('FINISH') != -1
retries: 10
delay: 30
- name: Delete task
win_shell: schtasks.exe /DELETE /TN MAPDRIVE /F
register: command_output
- name: Pring command output
debug:
msg: "{{command_output.stdout}}"