diff --git a/lib/puppet/provider/package/quicklookdmg.rb b/lib/puppet/provider/package/quicklookdmg.rb
new file mode 100644
index 0000000..a059724
--- /dev/null
+++ b/lib/puppet/provider/package/quicklookdmg.rb
@@ -0,0 +1,148 @@
+# Udo Waechter <udo.wa...@uni-osnabrueck.de>
+# Mac OS X QuickLook package provider to (un)install quicklook plugins
+#
+# Motivation: DMG files provide a true HFS file system
+# and are easier to manage.
+#
+# Note: the 'apple' Provider checks for the package name
+# in /L/Receipts. Since we possibly install multiple plugins from
+# a single source, we treat the source .dmg file as the package name.
+# As a result, we store installed .dmg file names
+# in /var/db/.puppet_quicklookdmg_installed_<name>
+
+require 'puppet/provider/package'
+require 'yaml'
+require "FileUtils"
+
+Puppet::Type.type(:package).provide(:quicklookdmg, :parent => Puppet::Provider::Package) do
+ desc "Package management which copies application bundles to a target."
+ $quicklookdmg_target = "/Library/QuickLook"
+ confine :operatingsystem => :darwin
+
+ commands :hdiutil => "/usr/bin/hdiutil"
+ commands :curl => "/usr/bin/curl"
+ commands :ditto => "/usr/bin/ditto"
+ commands :qlmanage => "/usr/bin/qlmanage"
+ # Save information about installed plugins in /var/db
+ def self.instances_by_name
+ Dir.entries("/var/db").find_all { |f|
+ f =~ /^\.puppet_quicklook_installed_/
+ }.collect do |f|
+ name = f.sub(/^\.puppet_quicklook_installed_/, '')
+ yield name if block_given?
+ name
+ end
+ end
+
+ def self.instances
+ instances_by_name.collect do |name|
+ new(:name => name, :provider => :quicklookdmg, :ensure => :installed)
+ end
+ end
+
+ def self.installapp(source, name, orig_source)
+ appname = File.basename(source);
+ ditto "--rsrc", source, "#{$quicklookdmg_target}/#{appname}"
+ dbfile = "/var/db/.puppet_quicklook_installed_#{name}.yaml"
+ receipthash = {}
+ receipthash["files"] = []
+ if File.exist?(dbfile)
+ receipthash = YAML::load_file(dbfile)
+ end
+ receipthash["name"] = name
+ receipthash["source"] = orig_source
+ receipthash["files"].include?(appname) or receipthash["files"].push(appname)
+ f = File.open(dbfile,"w")
+ f.print receipthash.to_yaml
+ f.close
+ # refresh plugins
+ qlmanage "-r"
+ end
+
+ def self.uninstallquicklookdmg(name)
+ dbfile = "/var/db/.puppet_quicklook_installed_#{name}.yaml"
+ unless File.exist?(dbfile)
+ raise Puppet::Error.new("QuickLook DMG Package #{name} not installed.")
+ end
+ receipthash = YAML::load_file(dbfile)
+ receipthash["files"].each do |appname|
+ FileUtils.remove_entry_secure("#{$quicklookdmg_target}/#{appname}")
+ unless $? == 0
+ raise Puppet::Error.new("QuickLook DMG could not remove \"#{$quicklookdmg_target}/#{appname}\"")
+ end
+ end
+ File.unlink(dbfile)
+ qlmanage "-r"
+ end
+
+ def self.installquicklookdmg(source, name)
+ unless source =~ /\.dmg$/i
+ raise Puppet::Error.new("Mac OS X QuickLook DMG's must specificy a source string ending in .dmg")
+ end
+ require 'open-uri'
+ require 'facter/util/plist'
+ cached_source = source
+ if %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ cached_source
+ cached_source = "/tmp/#{name}"
+ begin
+ curl "-o", cached_source, "-C", "-", "-k", "-s", "--url", source
+ Puppet.debug "Success: curl transfered [#{name}]"
+ rescue Puppet::ExecutionFailure
+ Puppet.debug "curl did not transfer [#{name}]. Falling back to slower open-uri transfer methods."
+ cached_source = source
+ end
+ end
+
+ begin
+ open(cached_source) do |dmg|
+ xml_str = hdiutil "mount", "-plist", "-nobrowse", "-readonly", "-mountrandom", "/tmp", dmg.path
+ ptable = Plist::parse_xml xml_str
+ # JJM Filter out all mount-paths into a single array, discard the rest.
+ mounts = ptable['system-entities'].collect { |entity|
+ entity['mount-point']
+ }.select { |mountloc|; mountloc }
+ begin
+ mounts.each do |fspath|
+ Dir.entries(fspath).select { |f|
+ f =~ /\.qlgenerator$/i
+ }.each do |app|
+ installapp("#{fspath}/#{app}", name, source)
+ end
+ end # mounts.each do
+ ensure
+ hdiutil "eject", mounts[0]
+ end # begin
+ end # open() do
+ ensure
+ # JJM Remove the file if open-uri didn't already do so.
+ File.unlink(cached_source) if File.exist?(cached_source)
+ end # begin
+ end # def self.installquicklookdmg
+
+ def query
+ if FileTest.exists?("/var/db/.puppet_quicklook_installed_#{@resource[:name]}.yaml")
+ return {:name => @resource[:name], :ensure => :present}
+ else
+ return nil
+ end
+ end
+
+ def install
+ source = nil
+ unless source = @resource[:source]
+ raise Puppet::Error.new("Mac OS X quicklook DMG's must specify a package source.")
+ end
+ unless name = @resource[:name]
+ raise Puppet::Error.new("Mac OS X quicklook DMG's must specify a package name.")
+ end
+ self.class.installquicklookdmg(source,name)
+ end
+
+ def uninstall
+ unless name = @resource[:name]
+ raise Puppet::Error.new("Mac OS X QuickLook DMG's must specify a package name.")
+ end
+ self.class.uninstallquicklookdmg(name)
+ end
+end
+
--
1.6.0.6
Can't we just subclass the app/pkg dmg provider instead? There looks to be a lot of duplicated code here...
On 15.11.2009, at 05:00, Nigel Kersten wrote:
> I'm so unhappy that we do our Mac pkg tracking this way. :( but I just can't see a way around it.
>
nope, as long as the apple-people do not come up with a proper package-management (apt would be great ;)).
> The more I think about it, I can't quite see that this really justifies a whole provider.
>
> Isn't this simply installing the package just like pkgdmg does but running [qlmanage "-r"] after each install?
>
In principle yes, but in fact no:
- The appdmg and quicklookdmg provider use ditto to copy .app or .ql<whatever> files to their appropriate places.
> This seems best suited to the postflight of the package itself don't you think? How many QuickLook plugins are you really managing?
>
Well, I like the appdmg provider, since not all .dmgs come with installer-packages inside. That would then mean that one has to create a package first, then put it in a .dmg
For us, this really is a lot of work. Thus we mostly use appdmg.
We are currently trying to figure out how to get all the files that were installed from .pkgs Then we could implement uninstall caps for pkgdmg also.
> Does qlmanage run happily when run as root via puppet when no-one is logged in btw?
Did not try it out, I hope it does.
udo.
Hi,
nope, as long as the apple-people do not come up with a proper package-management (apt would be great ;)).
On 15.11.2009, at 05:00, Nigel Kersten wrote:
> I'm so unhappy that we do our Mac pkg tracking this way. :( but I just can't see a way around it.
>
In principle yes, but in fact no:
> The more I think about it, I can't quite see that this really justifies a whole provider.
>
> Isn't this simply installing the package just like pkgdmg does but running [qlmanage "-r"] after each install?
>
- The appdmg and quicklookdmg provider use ditto to copy .app or .ql<whatever> files to their appropriate places.
Well, I like the appdmg provider, since not all .dmgs come with installer-packages inside. That would then mean that one has to create a package first, then put it in a .dmg
> This seems best suited to the postflight of the package itself don't you think? How many QuickLook plugins are you really managing?
>
For us, this really is a lot of work. Thus we mostly use appdmg.
We are currently trying to figure out how to get all the files that were installed from .pkgs Then we could implement uninstall caps for pkgdmg also.
Did not try it out, I hope it does.
> Does qlmanage run happily when run as root via puppet when no-one is logged in btw?
udo.
--
:: udo waechter - ro...@zoide.net :: N 52º16'30.5" E 8º3'10.1"
:: genuine input for your ears: http://auriculabovinari.de
:: your eyes: http://ezag.zoide.net
:: your brain: http://zoide.net