Search code examples
rubypowershellpuppet

how do I use Regex in powershell commands with ruby using puppet


I need to create a fact in puppet to get which versions of .netcore are installed in the servers.

Facter.add('common_dotnetcore_version') do
  confine :kernel => 'windows'
  powershell = 'C:\Windows\system32\WindowsPowershell\v1.0\powershell.exe'
  setcode do
    dotnetVersion = Hash.new 
    if Facter::Util::Resolution.which('dotnet')
      dotNetList = Facter::Core::Execution.exec(%Q{#{powershell} -command "(((dotnet --list-runtimes ) -replace '(?!\d*\.\d*)[A-Za-z([():\]\\)]') | select -Unique)"})
      dotNetList.each_line { |line| dotnetVersion[line] = true }
    end
    dotnetVersion
  end
  
end

please note that when I run this command in PowerShell

(((dotnet --list-runtimes ) -replace '(?!\d*\.\d*)[A-Za-z([():\]\\)]') | select -Unique)

I got this output:

.. 2.1.26  ..
.. 2.1.28  ..
.. 3.1.13  ..
.. 3.1.15  ..
.. 5.0.4  ..
.. 5.0.6  ..

But when its executed by Puppet I got this output:

Microsoft.AspNetCore.All 2.1.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

It's not doing the -replace with the Regex

Does anyone know why Puppet does not recognize the Regex and | select -Unique?


Solution

  • The problem is that backslashes inside a Ruby %Q{...} quoted string have a meaning. For example, %Q{\n} is a newline. So the backslashes in your regex are being interpreted by the %Q{...} string before they get to PowerShell.

    If you look at the string:

    puts %Q{'(?!\d*\.\d*)[A-Za-z([():\]\\)]'}
    # '(?!d*.d*)[A-Za-z([():]\)]'
    

    you'll see that the backslashes are going away.

    The easiest thing to do is to escape all the backslashes by doubling them:

    dotNetList = Facter::Core::Execution.exec(%Q{#{powershell} -command "(((dotnet --list-runtimes ) -replace '(?!\\d*\\.\\d*)[A-Za-z([():\\]\\\\)]') | select -Unique)"})