lib/puppet/provider/package/msi.rb in puppet-2.7.26 vs lib/puppet/provider/package/msi.rb in puppet-3.0.0.rc4
- old
+ new
@@ -1,41 +1,38 @@
require 'puppet/provider/package'
+require 'puppet/util/windows'
Puppet::Type.type(:package).provide(:msi, :parent => Puppet::Provider::Package) do
desc "Windows package management by installing and removing MSIs.
- This provider requires a `source` attribute, and will accept paths to local
- files, mapped drives, or UNC paths."
+ The `msi` provider is deprecated. Use the `windows` provider instead."
confine :operatingsystem => :windows
- defaultfor :operatingsystem => :windows
has_feature :installable
has_feature :uninstallable
has_feature :install_options
+ has_feature :uninstall_options
class MsiPackage
extend Enumerable
+ include Puppet::Util::Windows::Registry
+ extend Puppet::Util::Windows::Registry
- # From msi.h
- INSTALLSTATE_DEFAULT = 5 # product is installed for the current user
- INSTALLUILEVEL_NONE = 2 # completely silent installation
-
def self.installer
- require 'win32ole'
WIN32OLE.new("WindowsInstaller.Installer")
end
def self.each(&block)
inst = installer
- inst.UILevel = INSTALLUILEVEL_NONE
+ inst.UILevel = 2
inst.Products.each do |guid|
# products may be advertised, installed in a different user
# context, etc, we only want to know about products currently
# installed in our context.
- next unless inst.ProductState(guid) == INSTALLSTATE_DEFAULT
+ next unless inst.ProductState(guid) == 5
package = {
:name => inst.ProductInfo(guid, 'ProductName'),
# although packages have a version, the provider isn't versionable,
# so we can't return a version
@@ -49,15 +46,19 @@
yield package
end
end
end
- # Get an array of provider instances for currently installed packages
def self.instances
- MsiPackage.enum_for.map { |package| new(package) }
+ []
end
+ def initialize(resource = nil)
+ Puppet.deprecation_warning "The `:msi` package provider is deprecated, use the `:windows` provider instead."
+ super(resource)
+ end
+
# Find first package whose PackageCode, e.g. {B2BE95D2-CD2C-46D6-8D27-35D150E58EC9},
# matches the resource name (case-insensitively due to hex) or the ProductName matches
# the resource name. The ProductName is not guaranteed to be unique, but the PackageCode
# should be if the package is authored correctly.
def query
@@ -79,39 +80,35 @@
end
def uninstall
fail("The productcode property is missing.") unless properties[:productcode]
- command = ['msiexec.exe', '/qn', '/norestart', '/x', properties[:productcode]].flatten.compact.join(' ')
+ command = ['msiexec.exe', '/qn', '/norestart', '/x', properties[:productcode], uninstall_options].flatten.compact.join(' ')
execute(command, :combine => true)
check_result(exit_status)
end
def exit_status
$CHILD_STATUS.exitstatus
end
- # http://msdn.microsoft.com/en-us/library/windows/desktop/aa368542(v=vs.85).aspx
- ERROR_SUCCESS = 0
- ERROR_SUCCESS_REBOOT_INITIATED = 1641
- ERROR_SUCCESS_REBOOT_REQUIRED = 3010
-
# (Un)install may "fail" because the package requested a reboot, the system requested a
# reboot, or something else entirely. Reboot requests mean the package was installed
# successfully, but we warn since we don't have a good reboot strategy.
def check_result(hr)
operation = resource[:ensure] == :absent ? 'uninstall' : 'install'
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/aa368542(v=vs.85).aspx
case hr
- when ERROR_SUCCESS
+ when 0
# yeah
when 194
warning("The package requested a reboot to finish the operation.")
- when ERROR_SUCCESS_REBOOT_INITIATED
+ when 1641
warning("The package #{operation}ed successfully and the system is rebooting now.")
- when ERROR_SUCCESS_REBOOT_REQUIRED
+ when 3010
warning("The package #{operation}ed successfully, but the system must be rebooted.")
else
raise Puppet::Util::Windows::Error.new("Failed to #{operation}", hr)
end
end
@@ -119,23 +116,31 @@
def validate_source(value)
fail("The source parameter cannot be empty when using the MSI provider.") if value.empty?
end
def install_options
- # properties is a string delimited by spaces, so each key value must be quoted
- properties_for_command = nil
- if resource[:install_options]
- properties_for_command = resource[:install_options].collect do |k,v|
- property = shell_quote k
- value = shell_quote v
+ join_options(resource[:install_options])
+ end
- "#{property}=#{value}"
- end
- end
-
- properties_for_command
+ def uninstall_options
+ join_options(resource[:uninstall_options])
end
def shell_quote(value)
value.include?(' ') ? %Q["#{value.gsub(/"/, '\"')}"] : value
+ end
+
+ def join_options(options)
+ return unless options
+
+ options.collect do |val|
+ case val
+ when Hash
+ val.keys.sort.collect do |k|
+ "#{k}=#{val[k]}"
+ end.join(' ')
+ else
+ val
+ end
+ end
end
end