summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/package/rpm.rb
blob: e35091ad44904dba27d24b11add000d277d8a39d (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# RPM packaging.  Should work anywhere that has rpm installed.
Puppet::Type.type(:package).provide :rpm do
    desc "RPM packaging support; should work anywhere with a working ``rpm``
        binary."

    # The query format by which we identify installed packages
    NVRFORMAT = "%{NAME}-%{VERSION}-%{RELEASE}"

    VERSIONSTRING = "%{VERSION}-%{RELEASE}"

    commands :rpm => "rpm"

    def self.list
        packages = []

        # list out all of the packages
        begin
            execpipe("#{command(:rpm)} -qa --nosignature --nodigest --qf '%{NAME} #{VERSIONSTRING}\n'") { |process|
                # our regex for matching dpkg output
                regex = %r{^(\S+)\s+(\S+)}
                fields = [:name, :ensure]
                hash = {}

                # now turn each returned line into a package object
                process.each { |line|
                    if match = regex.match(line)
                        hash.clear

                        fields.zip(match.captures) { |field,value|
                            hash[field] = value
                        }
                        hash[:provider] = self.name
                        packages.push Puppet.type(:package).installedpkg(hash)
                    else
                        raise "failed to match rpm line %s" % line
                    end
                }
            }
        rescue Puppet::ExecutionFailure
            raise Puppet::Error, "Failed to list packages"
        end

        return packages
    end

    # Find the fully versioned package name and the version alone. Returns
    # a hash with entries :instance => fully versioned package name, and 
    # :ensure => version-release
    def query
        cmd = ["-q", @model[:name], "--nosignature", "--nodigest", "--qf", "#{NVRFORMAT} #{VERSIONSTRING}\n"]

        begin
            output = rpm *cmd
        rescue Puppet::ExecutionFailure
            return nil
        end

        regex = %r{^(\S+)\s+(\S+)}
        fields = [:instance, :ensure]
        hash = {}
        if match = regex.match(output)
            fields.zip(match.captures) { |field,value|
                hash[field] = value
            }
        else
            raise Puppet::DevError,
                "Failed to match rpm output '%s'" %
                output
        end

        @nvr = hash[:instance]

        return hash
    end

    # Here we just retrieve the version from the file specified in the source.
    def latest
        unless source = @model[:source]
            @model.fail "RPMs must specify a package source"
        end
        
        cmd = [command(:rpm), "-q", "--qf", "#{VERSIONSTRING}", "-p", "#{@model[:source]}"]
        version = execfail(cmd, Puppet::Error)
        return version
    end

    def install
        source = nil
        unless source = @model[:source]
            @model.fail "RPMs must specify a package source"
        end
        if @model.should(:ensure) == @model.is(:ensure) ||
           @model.should(:ensure) == :latest && @model.is(:ensure) == latest
            # RPM gets pissy if you try to install an already 
            # installed package
            return
        end

        flag = "-i"
        if @model.is(:ensure) != :absent
            flag = "-U"
        end

        rpm flag, "--oldpackage", source
    end

    def uninstall
        rpm "-e", nvr
    end

    def update
        self.install
    end

    def versionable?
        true
    end

    def nvr
        query unless @nvr
        @nvr
    end
end

# $Id$