This works nice, until a name contains an accent. Then I get the following error:
{
"msg": "An unhandled exception occurred while running the lookup plugin 'windhcp_getranges'. Error was a <class 'UnicodeDecodeError'>, original message: 'utf-8' codec can't decode byte 0x89 in position 5268: invalid start byte. 'utf-8' codec can't decode byte 0x89 in position 5268: invalid start byte",
"_ansible_no_log": false
}
So there’s an encoding problem somewhere.
Does anyone know what codec winrm returns? I’ve tried decoding std_out with several options (ascii, latin1, cp1250/1252), but none convert \x89 to ë (the name is ‘Wieën’, std_out contains ‘Wie\x89n’).
You could use the 65001 codepage which is UTF-8 to be able to support more than just what cp437 does.
But in reality you should look at using an actual module with the winrm connection plugin. Target the actual Windows host with the module and have Ansible deal with all the connection bits. Avoid injecting data into a script as now you could have an injection problem where things like the server value needs to be correctly escaped. You could even avoid a module altogether if this is a single task or placed inside a role by doing
- name: Get DHCP scopes
ansible.windows.win_powershell:
script: |
param ($Server)
Get-DhcpServerv4Scope -ComputerName $Server |
Select-Object @{
l = "scopeid"
e = { $_.scopeid.ipaddresstostring }
}, @{
l = "netmask"
e = { $_.subnetmask.ipaddresstostring }
}, name
parameters:
Server: '{{ dhcp_server }}'
We use an inventory per customer (whether this is the best way of doing things is another thing, but that’s the way this AWX environment was built, and right now changing that is more hassle than it’s worth).
The problem is that this code could potentially be run for any customer, which makes creating and coupling an inventory a nightmare. This way, I don’t need to pre-know which server this runs on, so I don’t have to add it to an inventory before running the code.
The server variable is of course sanitised before running this code.
I also use this technique for some inventory plugins which query a Windows DNS to create a dynamic inventory.
If you are defining a host at runtime then you could look at using add_host then either delegating subsequent tasks to that host or start a new play as that host/group. This way you can continue to use any PowerShell module against that target host including things like win_powershell to run anything you want and not have to worry about escaping values, how to pass them along to scripts, etc.
You can also just continue to do what you do right now but keep in mind it
is probably more difficult to maintain going forward
you have to deal with details like injecting data safely into the script to run
you have to worry about authentication whereas winrm/psrp allows you to use Kerberos without requiring a cached krb5 ccache
you are locked to using just WinRM rather than any of the other connection methods that Windows can use (psrp/ssh/etc)
lazy evaluation can trip people use when using templates making it harder to cache the value
the lookup syntax results in long lines if you have to start providing more values like the connection details on each invocation