Who triggers the wrapper script generation on a Windows node ?

202 مرّة مشاهدة
التخطي إلى أول رسالة غير مقروءة

Prasoon Karunan

غير مقروءة،
15‏/08‏/2019، 12:23:45 م15‏/8‏/2019
إلى Ansible Development
Hi Folks,

I am now trying to understand how ansible module execution happens on a Windows node. I've understood about the wrapper scripts and the json file which contains everything, but cannot find the starting point of the below code

begin {
$path = 'C:\Users\Administrator\AppData\Local\Temp\ansible-tmp-1565881753.1183164-174629035055307\AnsiballZ_<module>.ps1'
$DebugPreference = "Continue"
$ErrorActionPreference = "Stop"
Set-StrictMode -Version 2
$fd = [System.IO.File]::Create($path)
$sha1 = [System.Security.Cryptography.SHA1CryptoServiceProvider]::Create()
$bytes = @() #initialize for empty file case
}
process {
$bytes = [System.Convert]::FromBase64String($input)
$sha1.TransformBlock($bytes, 0, $bytes.Length, $bytes, 0) | Out-Null
$fd.Write($bytes, 0, $bytes.Length)
}
end {
$sha1.TransformFinalBlock($bytes, 0, 0) | Out-Null
$hash = [System.BitConverter]::ToString($sha1.Hash).Replace("-", "").ToLowerInvariant()
$fd.Close()
Write-Output "{""sha1"":""$hash""}"
}



I am searching for the trigger point which give the automatic variable $input the encoded code.

Jordan Borean

غير مقروءة،
15‏/08‏/2019، 5:10:57 م15‏/8‏/2019
إلى Ansible Development
Hi

This particular script is part of the put_file operation for winrm [1] which is executed like "PowerShell.exe .... -EncodedCommand ScriptB64". Part of the put_file method is to read the bytes of the file to transfer across and send it over the stdin pipe of the process under the WSMan Send operation. There is an automatic trigger in PowerShell where the begin block runs then the process block will run for each input that is sent until we tell it there is no more until finally the end block runs. The '$input' variable is an automatic variable which contains the input from the stdin pipe for that process (each byte fragment of the file).

In saying all this, the put_file operation should not be running at all for standard module execution. We use pipelining in pretty much all cases to execute a module and the only times put_file is used are;
  • An action plugin on the controller needs to put a file for a module to use, e.g. win_copy, win_template, script
  • The ANSIBLE_KEEP_REMOTE_FILES=1 env var is set when running Ansible, this should only be used for debugging purposes and is not the standard operation
What normally happens in the pipelining scenario is that we run the bootstrap_wrapper.ps1 [2] which takes in data from the stdin pipe to execute. This data is a string split by null chars where the first part is the exec_wrapper and the second part is the module manifest info which drives the wrapper. This way no data touches the disk (unless we need to copy a file) making things a lot faster than before.


Thanks

Jordan

Prasoon Karunan

غير مقروءة،
16‏/08‏/2019، 2:15:08 م16‏/8‏/2019
إلى Ansible Development
Awesome, thanks for the brief explanation. So correct me if I'm wrong, func exec_command is the one which does the pipeliinig execution , which is then accepted by $input via and then call execwrapper scriptblock ?

Jordan Borean

غير مقروءة،
16‏/08‏/2019، 8:26:16 م16‏/8‏/2019
إلى Ansible Development
Yep that's correct, the exec_command function doesn't no or care about what it is executing, it just has the command to run passed in as cmd and option input data to send over the stdin pipe. It's up to the caller of exec_command to make sure the command that it wants to run accepts input data and the correct input data is sent in. The _execute_module [1] function in the action plugin base is where all the logic happens to build that script and input data to be run.


Thanks

Jordan
تم حذف الرسالة.

Prasoon Karunan

غير مقروءة،
17‏/08‏/2019، 2:21:29 م17‏/8‏/2019
إلى Ansible Development
Cool, that helped a lot. But now into another confusion. 

There is an array list getting created which is used to create complex_args in module_powershell_wrapper and there is a condition in Parse-Args/GetParam() to use complex_args if $args doesn't have any value. Since $complex_args variable is always created in module_wrapper , when will the $args be used ? is it used when pipelining is not used ?

Thanks,
Prasoon

Jordan Borean

غير مقروءة،
18‏/08‏/2019، 4:16:37 م18‏/8‏/2019
إلى Ansible Development
complex_args is actually a hashtable where the key is the module option and the value is the raw value for that option. You might be confusing the ArrayList with the generic list we use to store variable definitions, that include complex_args, that are passed to the module_wrapper process.

Anything that uses our exec_wrapper process will use $complex_args even in non-pipelined scenarios as pipelining just changes how the payload is delivered.

The only reason why we still read from $args is purely for legacy reasons and for people manually running the modules outside of our wrapper process, i.e. not Ansible.

Thanks

Jordan
الرد على الكل
رد على الكاتب
إعادة توجيه
0 رسالة جديدة