Problem
You are using Chef with Windows (that is a problem in itself!) and are using powershell to install programs using a specific user account with winrm.
How do you ensure idempotence?
Solution
There are many possibilities, like using the windows cookbook from Opscode, but that doesn't handle installing and package as a specific user.
Here is a hack that will use Ruby to check the Windows registry for an installed product and if found, prevent the powershell resource block from executing.
Add this registry_helper.rb to your cookbook's libraries directory:
require 'win32/registry'
module RegistryHelper
INSTALLER_PRODUCTS = 'Installer\Products'
def RegistryHelper.is_in_classes_root?(path, product_name)
found = false
Win32::Registry::HKEY_CLASSES_ROOT.open(path) do |reg|
reg.each_key do |key|
k = reg.open(key)
if k['ProductName'] =~ /#{Regexp.quote(product_name)}/
found = true
break
end
end
end
return found
end
end
In your recipe, include this library, and add a not_if block to the powershell resource statement:
class Chef::Recipe
include RegistryHelper
end
# The name to search for in the registry for idempotence
registry_name = 'Java(TM) SE Development Kit 6 Update 26'
powershell "Install-jdk_6u26" do
...
# ensure idempotence
not_if do
RegistryHelper.is_in_classes_root?(RegistryHelper::INSTALLER_PRODUCTS, registry_name)
end
end