[windows] Exit-Json fails / hangs

Hi,

currently developing / updating my setup.ps1 PR for custom facts.

`

$result = New-Object psobject @{
ansible_facts = New-Object psobject
changed = $false
}

Function Set-Attr($obj, $name, $value)
{

If the provided $obj is undefined, define one to be nice

If (-not $obj.GetType)
{
$obj = New-Object psobject
}

Try
{
$obj.$name = $value
}
Catch
{
$obj | Add-Member -Force -MemberType NoteProperty -Name $name -Value $value
}
}

Function Get-CustomFacts {
[cmdletBinding()]
param (
[Parameter(mandatory=$true)]
$factspath
)

if (-not (Test-Path -Path $factspath)) {
Fail-Json $result “The path $factspath does not exist. Typo?”
}

$FactsFiles = Get-ChildItem -Path $factspath | Where-Object -FilterScript {($PSItem.PSIsContainer -eq $false) -and ($PSItem.Extension -eq ‘.ps1’)}

foreach ($FactsFile in $FactsFiles) {
$out = . $($FactsFile.FullName)
Set-Attr $result.ansible_facts “ansible_$(($FactsFile.Name).Split(‘.’)[0])” $out
$out
}
}

Function Exit-Json($obj)
{

If the provided $obj is undefined, define one to be nice

If (-not $obj.GetType)
{
$obj = New-Object psobject
}

echo $obj | ConvertTo-Json -Compress -Depth 99
}

Get-CustomFacts -factspath ‘C:\temp’

$result

Exit-Json $result

`

Exit-Json in this case just hangs. Indefinitely.

I tested this on Windows Server 2012 R2 with PowerShell 4 and also PowerShell 5 Prod Preview.

This is the same issue I see with the win_msi module here https://github.com/ansible/ansible-modules-core/issues/2330

I had this working in 1.9.3 (hence my PR), but something lately changed. I rebuild my Ansible envs and neither 1.9.3, 1.9.4 or 2 dev branch and none of them work.

Any ideas?

All is fine up until the ConvertTo-Json call. In my tests commenting out the Depth parameter fixed my issues.

Is this something in my environment or can other people reproduce?

Also, here or Github Issue???

Hi,

I’m a bit confused by your code above - is that the whole of your module code? It seems to include some functions which I think are in the common code (that gets added to each module as a result of having the following line in the comments):

WANT_JSON # POWERSHELL_COMMON

If you want to see what functions are in the common code it is in a file called powershell.ps1 which is in

ansible/lib/ansible/module_utils

If you are trying to debug a windows module you have written sometimes I find best way to do so is to set
export ANSIBLE_KEEP_REMOTE_FILES=1
and then run a playbook that includes just your custom module

then, get onto the windows box and go to your users temp dir (probably something like C:\users<user ansible is running as>\AppData\Local\Temp - you may need to change explorer options to show hidden files and folders to see AppData

a folder gets created for each module that you use in your playbook, sorting by time stamp usually helps you to find the most recent one.

Then you can open up the module and run it in Powershell ISE which does a lot of helpful things like syntax highlighting.

latest dev ansible 2 includes embedds the module arguments that were passed into in the script, so you can just run the module. In 1.7 - to 1.9.x they were in a file in the same folder if I recall and you had to pass the arguments as a file name to the module (without the .\ that powershell likes to add to everything).

Hopefully this will get you going.

Here’s probably best if you are having trouble getting your code going - Github best for actual bugs and features I reckon.

Jon

Hi Jon,

I didn’t make myself clear.
Above is already the minimum syntax taken out of the resulting PowerShell script on a Windows host after a failed run. I just didn’t want to paste THE WHOLE script here, but only the code that needs to be there in order to reproduce the issue.

I’ve already reached out to the PowerShell Product Group and the other MVPs and hope to get a response from them.

Removing the “depth” parameter fixes my problem. Same with the win_msi issue I mentioned.

Hope that makes it a bit clearer.

My guess is you have something you aren’t expecting in your output pipe

I don’t know what the effect is of dereferencing a variable on a line on its own is, but I’m guessing it puts it into the output pipe - and there’s two places I can see in the code above where it happens.

In your Get-CustomFacts function, inside the foreach here ($out, shown in bold)

foreach ($FactsFile in $FactsFiles) { $out = . $($FactsFile.FullName) Set-Attr $result.ansible_facts "ansible_$(($FactsFile.Name).Split('.')[0])" $out **$out** }
and also just at the end of the module code ($result again just shown in bold).

`
Get-CustomFacts -factspath ‘C:\temp’

$result

Exit-Json $result
`
Ansible modules should just be outputting JSON - nothing else.

I could be completely wrong but I’d suggest reading up on powershell pipeline and bearing in mind that powershell doesn’t pipe text through | - it passes objects.

Hope that helps,

Jon

Yeah, hasn’t really got anything to do with me not understanding PowerShell, I guess I’m quite ok with that :wink:

My code snippet up there was for debugging in ISE, that’s why I’m outputting $out and $result. That’s obviously NOT in my module.

I can reproduce the behaviour even by calling

`

$obj = Get-Service

echo $obj | ConvertTo-Json -Depth 99 -Compress

`

So, that method of doing it just doesn’t seem to perform very well. Like I mentioned, win_msi has the same problem as soon as there’s content in the MSI log.

More testing…

I believe I don’t like the depth of 99 in Exit-Json. Why is that there? I mean, why was a decision made that we need to go 99 levels deep?

That’s why my example just kills my VM.

I agree with David, there seems to be something in the Convertto-Json cmdlet which fails.

According to the documentation, the default depth for Convertto-Json is 2, which is probably too shallow for Ansible. Maybe we should set this to 10 or something? I can’t thing of a situation where Ansible’s json output would need more than a few (3-5) levels. Any thoughts?

-Trond

Hmm, most nested structure I can think of is the setup facts (linux ones carry rather more info at the moment than windows).

Perhaps it should default to 10 but be made configurable ( or perhaps just overridable - I can’t think where else it would get used inside an ansible module except for in Exit-Json).

Should probably use Select-Object to filter for the properties that are interesting in cases where there is a lot of data to be returned from complex objects.

Jon

https://github.com/ansible/ansible/issues/13095

PR: https://github.com/ansible/ansible/pull/13117