Consuming a resource/provider from within another provider


#1

Hi,

I’m trying to extend the ‘Feature’ resource in the Windows cookbook to also
support using the Powershell module that is available in Windows 2008 R2.

I was intending on using the Powershell resource/provider to actually
execute the necessary commands, but am struggling to get this working -
I’ve tried various combinations without much success but am new to Ruby so
feel like I’m stumbling in the dark really.

Here is how I’m trying to use it in my implementation of the 'installed?'
method:

def installed?
poshOutFile = Tempfile.new(‘feature_smm’)
@installed ||= begin
Chef::Resource::Powershell.new(“query feature”) do
code <<-EOH
import-module ServerManager
$feature = Get-WindowsFeature "#{@new_resource.feature_name}"
Set-Content -Path “#{poshOutFile.path}” -Value $feature.Installed
EOH
end

!(poshOutFile.nil?) && ((poshOutFile.read).casecmp 'true')

end
end

This particular attempt doesn’t throw any errors but nothing actually
happens, presumably because I’m only only instantiating the resource and
not actually executing it. Other attempts typically resulted in
’method_missing’ or ‘undefined method’ exceptions.

As a side question, I didn’t see any way to pass information back from the
invoked Powershell command (standard out doesn’t seem to be accessible in
the same way as with the ‘shell_out’ provider - or have I missed something
here too?) so have resorted to using a file to store the result - is this
the best approach?

Thanks in advance for any help.

Cheers,
James.


#2

On Thu, Apr 12, 2012 at 1:49 AM, James Dawson jd4wson@gmail.com wrote:

Hi,

I’m trying to extend the ‘Feature’ resource in the Windows cookbook to also
support using the Powershell module that is available in Windows 2008 R2.

I was intending on using the Powershell resource/provider to actually
execute the necessary commands, but am struggling to get this working - I’ve
tried various combinations without much success but am new to Ruby so feel
like I’m stumbling in the dark really.

Here is how I’m trying to use it in my implementation of the 'installed?'
method:

def installed?
poshOutFile = Tempfile.new(‘feature_smm’)
@installed ||= begin
Chef::Resource::Powershell.new(“query feature”) do
code <<-EOH
import-module ServerManager
$feature = Get-WindowsFeature "#{@new_resource.feature_name}"
Set-Content -Path “#{poshOutFile.path}” -Value $feature.Installed
EOH
end

!(poshOutFile.nil?) && ((poshOutFile.read).casecmp 'true')

end
end

This particular attempt doesn’t throw any errors but nothing actually
happens, presumably because I’m only only instantiating the resource and not
actually executing it. Other attempts typically resulted in ‘method_missing’

Correct. You need:

resource.run_action(:create)

Note that this is in principle, I haven’t taken the time do understand
the details—but you seem to be on right way to figure it out anyway :wink:

As a side question, I didn’t see any way to pass information back from the
invoked Powershell command (standard out doesn’t seem to be accessible in
the same way as with the ‘shell_out’ provider - or have I missed something
here too?) so have resorted to using a file to store the result - is this
the best approach?

You could probably take the guts out of that LWRP, create a helper in
libraries, and use that instead of the resource.
That’s the approach I use when I need a return value; YMMV.

Andrea


#3

Many thanks for the pointer Andrea, it definitely helped me move forward
and understand a bit more - but I’m still not quite there.

The method I included before now looks like this:

def installed?
poshOutFile = “#{ENV[‘TEMP’]}\feature_smm_poshoutput.tmp”
@installed ||= begin
poshResource = Chef::Resource::Powershell.new(“query feature”,
run_context) do
code <<-EOH
Import-Module ServerManager
$feature = Get-WindowsFeature "#{@new_resource.feature_name}"
Set-Content -Path “#{poshOutFile}” -Value $feature.Installed
EOH
end

poshResource.run_action(:run)

( ::File.exist?(poshOutFile) &&

::File.read(poshOutFile).include?(‘True’) )
end
end

The resulting chef-run completes without error and the logging indicates
that the resource was executed:

[Tue, 17 Apr 2012 02:15:58 +0100] INFO: Processing
windows_feature[AS-NET-Framework] action install (sandbox::poshtest line
/chef/cache/cookbooks/sandbox/recipes/poshtest.rb)
DEBUG: C:\Users\ADMINI~1\AppData\Local\Temp\feature_smm_poshoutput.tmp
DEBUG: Checking for ‘AS-NET-Framework’
[Tue, 17 Apr 2012 02:15:58 +0100] INFO: Processing powershell[query
feature] action run (dynamically defined)
[Tue, 17 Apr 2012 02:15:58 +0100] INFO: powershell[query feature]
sh(C:\Windows\sysnative\WindowsPowershell\v1.0\powershell.exe
-ExecutionPolicy RemoteSigned -inputformat none -Command “& {
C:\Users\ADMINI~1\AppData\Local\Temp\chef-script20120417-2360-ok3rgn.ps1 }”)
[Tue, 17 Apr 2012 02:16:03 +0100] INFO: powershell[query feature] ran
successfully
DEBUG: poshOutFile not found
DEBUG: is_installed=false
[Tue, 17 Apr 2012 02:16:03 +0100] INFO: Processing powershell[add feature]
action run (dynamically defined)
[Tue, 17 Apr 2012 02:16:03 +0100] INFO: powershell[add feature]
sh(C:\Windows\sysnative\WindowsPowershell\v1.0\powershell.exe
-ExecutionPolicy RemoteSigned -inputformat none -Command “& {
C:\Users\ADMINI~1\AppData\Local\Temp\chef-script20120417-2360-1o6935p.ps1
}”)
[Tue, 17 Apr 2012 02:16:08 +0100] INFO: powershell[add feature] ran
successfully
[Tue, 17 Apr 2012 02:16:08 +0100] INFO: windows_feature[AS-NET-Framework]
installed feature

…but the ‘poshOutFile’ is never created suggesting that the Powershell is
not actually executed. As a test I implemented similar logic in a simple
recipe calling the powershell resource directly and, as expected, this
works fine.

Am I missing anything else that is needed to allow a resource to execute
properly when defined dynamically?

Cheers,
James.