-2

win_powershell seems to choke when I attempt to pass a Boolean variable through it to register a tested discrete state on a remote guest/target (for later consumption). For numerous attempts to provide compliant statements, I get errors such as ...

  • was not followed by a valid variable name character. Consider using ${} to delimit the name.
  • Last close parenthesis is an invalid character
  • Cannot convert string to bool
  • Colon is unexpected token
  • $True is unexpected token
  • Unable to convert to dictionary
  • Must either be a JSON string or in the key=value form

My goal was to use the win_powershell module to execute a powershell script ...

  $IsInstalled = ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0

... on a remote host and consume the IsInstalled variable later in the Playbook. (the p/s statement executes flawlessy when invoked directly).

My task ended up looking like the below with all of the various/unsuccessful attempts commented out. Notice that I resorted to the simplest of tests in the end which infers that processing a boolean via win_powershell is not do-able. I'm hoping somebody can prove me wrong and/or confirm that I need to get such resolve by processing a string variable instead.

BTW (for the innocent by-stander) there are no hits for the word bool in the Ansible documentation for win_powershell. However, the description for parameters includes the word dictionary and term key=value pairs. If these descriptions are restraints, it should be (I wish it were) stated as such (more emphatic).

Key points observed along the way, …

  • An = operator always produces a string; use json syntax for other variable types; a : (colon) for other types such as boolean.
  • Consider using ${} to delimit the variable name (but how?)
  • Enclose any boolean equates with single ‘
  • I found some other blogs/posts but nothing in layman (json newbie) terms (that I could understand).

Anybody have a solution to make a Boolean work as sought or should I (just) try to process the needed state as a string variable? Check out these blogs …

powershell - Variable reference is not valid. ':' was not followed by a valid variable name character How can you use an object's property in a double-quoted string?

Here's my task efforts (with failed statements being commented) ...

   - name: Test for installed SQL Server
      ansible.windows.win_powershell:
        script: |
          [CmdletBinding()]
          param (
            [bool]$IsInstalled
          )
          # $IsInstalled = ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0
          # $IsInstalled: ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0
          # $IsInstalled: ${ ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0 }
          # ${IsInstalled}: ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0
          # if ( ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0 ) # last close paren is invalid character
          # if ( '((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server").Length -gt 0' ) # cannot convert string to bool
          if ( $False ) # a sanity check ...
             # { $IsInstalled: $True }
             # { ${ $IsInstalled}: $True }
             # { ${IsInstalled}: $True } # colon is unexpected token 
             # { ${IsInstalled} = $True } # equals outputs a string; cannot convert to boolean (i knew that but what the hey)
             # { ${ $IsInstalled: } $True } # unexpected token $True
             { '$IsInstalled: $True' }
          else
             # { $IsInstalled: $False }
             # { ${ $IsInstalled}: $False }
             # { ${IsInstalled}: $False }
             # { ${IsInstalled} = $False }
             # { ${ $IsInstalled: } $False }
             { '$IsInstalled: $False' }
        parameters:
          # IsInstalled: $True # cannot convert string to bool
          # 'IsInstalled: $True' # is of type System.String ... unable to convert to dict ... must either be a JSON string or in the key=value form"
}
      register: SQLtest

I was expecting the first (commented) statement to work; done. That is, to register SQLtest.IsInstalled as a boolean state for later consumption.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66
GlennRA
  • 57
  • 3
  • 3
    That's a lot of text for a very simple problem. To start with and avoid confusion. more or less everything that goes through jinja2 templating in ansible is a string. To fix your problem, don't register a variable in your poswershell. Have your snippet output either `True` or `False` as a textual content on the standard output, call the script trhough ansible, register the varialble... and your result is next in `{{ SQLtest.stdout | bool }}` – Zeitounator Nov 04 '22 at 07:36
  • 1
    Moreover, you are doing all this to check if a software is installed when [there's already an existing module for that](https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_package_module.html) – Zeitounator Nov 04 '22 at 07:57
  • For your next question, please avoid pasting special characters for bullet lists, use the standard markdown formatting (i.e. `* `) and make sure your code and text are formatted correctly. I edited your question to make it readable on screen. You can have a look at those changes for reference by clicking the `Edited xxxx ago` link above. Thanks – Zeitounator Nov 04 '22 at 08:03
  • Sorry for the all the text; as an Ansible newbie, i just thought there must be a way to get a boolean thru this ... As for the win_package module, that's actually my root problem; when i run that against an instance with the subject software already installed, it takes 10 minutes for it fail with unexpected RC. My snippet executes instantly and i wanted to consume the boolean from that as a when-conditional for the win_package module. Yea; i'll go for the string output – GlennRA Nov 04 '22 at 14:21

1 Answers1

1

Here's an exact solution that did work; i couldn't get the templating to work, ...

    - name: Test for installed SQL Server
        ansible.windows.win_powershell:
          script: |
            ((gp HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*).DisplayName -Match "Microsoft SQL Server 2019 ").Length -gt 0
        register: SQLtest

... as consumed later in a when conditional ...

    when: not SQLtest.output

It's always simple (once you know how) ...

GlennRA
  • 57
  • 3