Passing Parameters to Powershell

1,368 views
Skip to first unread message

Paul Ponzeka

unread,
Oct 9, 2014, 3:22:14 PM10/9/14
to puppet...@googlegroups.com
I am using Puppet installed with the powershell module.  I am struggling with how to pass a puppet variable through to powershell.  For instance I have the following in my module init.pp file:

class windows_dns(

$forwarders = '1.1.1.1'

) {
   anchor { 'windows_dns::begin': } ->
   class{'windows_dns::install': } ->
   class{'windows_dns::config': } ->
   class{'windows_dns::service': } ->
   anchor { 'windows_dns::end': }

}


Then in my config.pp file I have:

class windows_dns::config {

case $kernelmajversion {
6.3: {
                        $forwarder_execute = 'windows_dns/setdnsforwarders.ps1'
$forwarder_check = 'windows_dns/checkdnsforwarders.ps1'
$dnsforwarders = $windows_dns::forwarders

                }
6.1: {
                        $forwarder_execute = 'windows_dns/setdnsforwarders_legacy.ps1'
$forwarder_check = 'windows_dns/checkdnsforwarders_legacy.ps1'

                }
                }

exec { 'forwarderscreate':

command => template ($forwarder_execute),
unless => template ($forwarder_check),
provider => powershell,
logoutput => true,

}

I have stored as a template in the manifest a powershell script file as:

$dnsforwarders | out-file C:\test.log

I obviously want to use a more complex output.  I tried adding a parameter to the top of my powershell script but dont understand how to pass that as an option to puppet.  

The variable passes through fine.  I tested by changing the command to command=> template ($dnsforwarders) and i of course got an error from puppet about it not being able to find the template named 1.1.1.1 in the manifest.  I just dont know how to pass this through to the shell. 

Juan Andres Ramirez

unread,
Oct 9, 2014, 3:35:59 PM10/9/14
to puppet...@googlegroups.com
if you want execute a powershell file:

 command => "powershell.exe -ExecutionPolicy ByPass -File file.ps1 ${param1}"

Paul Ponzeka

unread,
Oct 9, 2014, 3:48:02 PM10/9/14
to puppet...@googlegroups.com
Thanks Juan.  Couple of questions on your reply.

  1. In my case would it be the following: command => "powershell.exe -ExecutionPolicy ByPass -File file.ps1 ${dnsforwarders}"  # or does this need to be adjusted?
  2. How do i do the same with the fact that I am using templates, and thus they are stored on Puppet and passed to the server.  I am not storing the powershell files on the agent server. Is there a way to do something like the following:
command => template ($forwarder_execute) ${Param1},  #

Juan Andres Ramirez

unread,
Oct 9, 2014, 3:59:36 PM10/9/14
to puppet...@googlegroups.com
Example:

I have my script on powershell in the next path

in Puppet:

define some::module() {
   $script = "\\\\server1\\shared\\script.ps1
       
    exec { "Executing a script":
          command => "powershell.exe -ExecutionPolicy ByPass -File ${script} ${param1}",
          unless      => "powershell.exe -ExecutionPolicy ByPass -command \"here any command on powershell \""

}



On Thursday, October 9, 2014 4:22:14 PM UTC-3, Paul Ponzeka wrote:

Josh Cooper

unread,
Oct 9, 2014, 4:52:04 PM10/9/14
to puppet...@googlegroups.com

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/c62b8af5-4890-4a84-905e-63e7b6132e13%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


I would recommend using the powershell provider as you were doing. In your powershell script 'windows_dns/setdnsforwarders.ps1', resolve parameters using ERB syntax found in https://docs.puppetlabs.com/guides/templating.html#referencing-variables, something like:

<%= scope['dnsforwarders'] %>

Josh

--
Josh Cooper
Developer, Puppet Labs

Paul Ponzeka

unread,
Oct 9, 2014, 5:18:05 PM10/9/14
to puppet...@googlegroups.com
Thanks josh, so in my template file setdnsforwarders.ps1 is this the correct syntax?

$outside = <%= scope['dnsforwarders'] %>
$outside | out-file C:\output.log -append

Paul Ponzeka

unread,
Oct 9, 2014, 7:56:30 PM10/9/14
to puppet...@googlegroups.com
I tried that and it just came up blank.  Am I suppose to pass it as a powershell parameter?

Rob Reynolds

unread,
Oct 10, 2014, 5:28:06 PM10/10/14
to puppet...@googlegroups.com
On Thu, Oct 9, 2014 at 4:18 PM, Paul Ponzeka <ponz...@gmail.com> wrote:
Thanks josh, so in my template file setdnsforwarders.ps1 is this the correct syntax?

setdnsforwarders.ps1.erb
 

For more options, visit https://groups.google.com/d/optout.



--
Rob Reynolds
Developer, Puppet Labs

Rob Reynolds

unread,
Oct 10, 2014, 5:30:55 PM10/10/14
to puppet...@googlegroups.com
On Thu, Oct 9, 2014 at 2:35 PM, Juan Andres Ramirez <jandr...@gmail.com> wrote:
if you want execute a powershell file:

 command => "powershell.exe -ExecutionPolicy ByPass -File file.ps1 ${param1}"

I would recommend using -Command and staying away from the error prone -File. -Command has more consistency with passing the exit code back than -File does and you can still use it to execute against a file. For more details please see "PowerShell, batch files, and exit codes"[1].


 

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Paul Ponzeka

unread,
Oct 13, 2014, 10:15:05 AM10/13/14
to puppet...@googlegroups.com
Thanks for this rob.  I still cannot get the variable to pass into the script.  Now i have the setdnsforwarders.ps1.erb template, and here is the complete copy of what is in the template:

$outside = <%= scope['dnsforwarders'] %>
$outside | out-file C:\output.log -append


I've also tried the following:


<%= scope.lookupvar('@dnsforwarders') %> | out-file C:\output.log -append
<%= scope.lookupvar('windows_dns::forwarders') %> | out-file C:\output.log -append
<%= scope.lookupvar('windows_dns::config') %> | out-file C:\output.log -append

Each time the output.log file is blank.  

Here is my windows_dns::config file:

class windows_dns::config {

case $kernelmajversion {
6.3: {
                        $forwarder_execute = 'windows_dns/setdnsforwarders.ps1.erb'
$forwarder_check = 'windows_dns/checkdnsforwarders.ps1'
$dnsforwarders = $windows_dns::forwarders

                }
6.1: {
                        $forwarder_execute = 'windows_dns/setdnsforwarders_legacy.ps1'
$forwarder_check = 'windows_dns/checkdnsforwarders_legacy.ps1'

                }
                }

exec { 'forwarderscreate':

command => template ($forwarder_execute),
#unless => template ($forwarder_check),
provider => powershell,
logoutput => true,

}

And here is where the variable is originally defined in the windows_dns::init.pp

class windows_dns(

$forwarders = '1.1.1.1'

) {
   anchor { 'windows_dns::begin': } ->
   class{'windows_dns::install': } ->
   class{'windows_dns::config': } ->
   class{'windows_dns::service': } ->
   anchor { 'windows_dns::end': }

}

Any help would be amazing to get the variable to pass

Josh Cooper

unread,
Oct 13, 2014, 1:05:39 PM10/13/14
to puppet...@googlegroups.com
Hi Paul,

On Mon, Oct 13, 2014 at 7:15 AM, Paul Ponzeka <ponz...@gmail.com> wrote:
Thanks for this rob.  I still cannot get the variable to pass into the script.  Now i have the setdnsforwarders.ps1.erb template,

Note puppet doesn't care what the file extension is, so long as the template('path/to/file') refers to the correct file.
 
and here is the complete copy of what is in the template:

$outside = <%= scope['dnsforwarders'] %>
$outside | out-file C:\output.log -append


I've also tried the following:


<%= scope.lookupvar('@dnsforwarders') %> | out-file C:\output.log -append

Variables in the current scope can be accessed directly as <%= @dnsforwarders %>, as opposed to the variable named "@dnsforwarders"
 
<%= scope.lookupvar('windows_dns::forwarders') %> | out-file C:\output.log -append

I think the pipeline construct isn't doing what you would expect. I think you need to quote the ERB snippet, so that powershell sees a literal string:

'<%= scope.lookupvar('windows_dns::forwarders') %>' | out-file C:\output.log -append
If you are using a recent version of puppet, you don't need the anchor pattern. See https://docs.puppetlabs.com/puppet/latest/reference/lang_containment.html
 

Any help would be amazing to get the variable to pass

Here's an example using an inline template that works correctly. Note I have to escape the backslash c:\\output.log due to the double quoted string. You won't need to do that if the template is in an external file:

class windows_dns::config {
  $dnsforwarder = "www.example.com"

  exec { 'command':
    command   => inline_template("'<%= scope['dnsforwarder'] %>' | out-file c:\\output.log -append"),
    logoutput => true,
    provider  => powershell
  }
}

include windows_dns::config

C:\>puppet apply powershell.pp
Notice: Compiled catalog for win-agent in environment production in 0.11 seconds
Notice: /Stage[main]/Windows_dns::Config/Exec[command]/returns: executed successfully
Notice: Finished catalog run in 1.09 seconds

Note this will create a UTF-16LE encoded file with a byte-order mark. You may want to specify the encoding of the file you're writing to.


For more options, visit https://groups.google.com/d/optout.



--

Paul Ponzeka

unread,
Oct 13, 2014, 1:48:46 PM10/13/14
to puppet...@googlegroups.com
Josh, your a god among men.  Thank you so much.  It was the literal string for the variable that resolved it.  

Paul Ponzeka

unread,
Oct 15, 2014, 11:39:49 AM10/15/14
to puppet...@googlegroups.com
Hopefully this is my last question.  How do i get the variable that passes through to powershell to be a proper array?  The reason is that i need to run a foreach loop on it, but it sees the variable as one long item instead of multiples if its configured as such:

$forwarders = ["1.1.1.1","2.2.2.2"]

Rob Reynolds

unread,
Oct 23, 2014, 4:54:26 PM10/23/14
to puppet...@googlegroups.com
On Wed, Oct 15, 2014 at 10:39 AM, Paul Ponzeka <ponz...@gmail.com> wrote:
Hopefully this is my last question.  How do i get the variable that passes through to powershell to be a proper array?  The reason is that i need to run a foreach loop on it, but it sees the variable as one long item instead of multiples if its configured as such:

$forwarders = ["1.1.1.1","2.2.2.2"]

You could pass a string with a known delimiter and use that to split into an array. There are probably other options for this as well, but I'm not sure a ruby array is going to directly transfer to a posh array.

 

For more options, visit https://groups.google.com/d/optout.



--
Rob Reynolds
Developer, Puppet Labs

Join us at PuppetConf 2015, October 5-9 in Portland, OR - http://2015.puppetconf.com/
Register early to save 40%!
Reply all
Reply to author
Forward
0 new messages