summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/package/pkgdmg.rb
blob: e325840b1717c37f81af918d0f26c427dadbc0fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Jeff McCune <mccune.jeff@gmail.com>
# Mac OS X Package Installer which handles .pkg and .mpkg
# bundles inside an Apple Disk Image.
#
# Motivation: DMG files provide a true HFS file system
# and are easier to manage and .pkg bundles.
#
# Note: the 'apple' Provider checks for the package name
# in /L/Receipts.  Since we install multiple pkg's from a single
# source, we treat the source .pkg.dmg file as the package name.
# As a result, we store installed .pkg.dmg file names
# in /var/db/.puppet_pkgdmg_installed_<name>

# require 'ruby-debug'
# Debugger.start

Puppet::Type.type(:package).provide :pkgdmg do
    desc "Package management based on Apple's Installer.app and DiskUtility.app"

    confine :exists => "/Library/Receipts"
    commands :installer => "/usr/sbin/installer"
    commands :hdiutil => "/usr/bin/hdiutil"

    # JJM We store a cookie for each installed .pkg.dmg in /var/db
    def self.listbyname
        Dir.entries("/var/db").find_all { |f|
            f =~ /^\.puppet_pkgdmg_installed_/
        }.collect { |f|
            name = f.sub(/^\.puppet_pkgdmg_installed_/, '')
            yield name if block_given?

            name
        }
    end

    def self.list
        listbyname.collect do |name|
            Puppet.type(:package).installedpkg(
                :name => name,
                :provider => :pkgdmg,
                :ensure => :installed
            )
        end
    end

    def self.installpkg(source, name, orig_source)
      installer "-pkg", source, "-target", "/"
      File.open("/var/db/.puppet_pkgdmg_installed_#{name}", "w") do |t|
          t.print "name: '#{name}'\n"
          t.print "source: '#{orig_source}'\n"
      end      
    end
    
    def self.installpkgdmg(source, name)
        unless source =~ /\.dmg$/i
            self.fail "Mac OS X PKG DMG's must specificy a source string ending in .dmg"
        end
        require 'open-uri'
        require 'puppet/util/plist'
        open(source) do |dmg|
            cmd = "#{command(:hdiutil)} mount -plist -nobrowse -readonly -mountrandom /tmp #{dmg.path}"
            IO.popen(cmd) do |pipe|
                xml_str = pipe.read
                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 }
                mounts.each do |fspath|
                    Dir.entries(fspath).select { |f|
                        f =~ /\.m{0,1}pkg$/i
                    }.each { |pkg|
                        installpkg("#{fspath}/#{pkg}", name, source)
                    }
                end
            hdiutil "eject", mounts[0]
            end
        end
    end

    def query
        if FileTest.exists?("/var/db/.puppet_pkgdmg_installed_#{@model[:name]}")
            return {:name => @model[:name], :ensure => :present}
        else
            return nil
        end
    end

    def install
        source = nil
        unless source = @model[:source]
            self.fail "Mac OS X PKG DMG's must specify a package source."
        end
        unless name = @model[:name]
            self.fail "Mac OS X PKG DMG's must specify a package name."
        end
        self.class.installpkgdmg(source,name)
    end
end

# $Id$