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
126
127
128
129
130
131
132
133
134
|
require 'puppet/provider/package'
# RPM packaging. Should work anywhere that has rpm installed.
Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Provider::Package do
desc "RPM packaging support; should work anywhere with a working ``rpm``
binary."
has_feature :versionable
# The query format by which we identify installed packages
NEVRAFORMAT = "%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH}"
NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch]
commands :rpm => "rpm"
if command('rpm')
confine :true => begin
rpm('--version')
rescue Puppet::ExecutionFailure
false
else
true
end
end
def self.instances
packages = []
# rpm < 4.1 don't support --nosignature
output = rpm "--version"
sig = "--nosignature"
if output =~ /RPM version (([123].*)|(4\.0.*))/
sig = ""
end
# list out all of the packages
begin
execpipe("#{command(:rpm)} -qa #{sig} --nodigest --qf '#{NEVRAFORMAT}\n'") { |process|
# now turn each returned line into a package object
process.each { |line|
hash = nevra_to_hash(line)
packages << new(hash)
}
}
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
#NOTE: Prior to a fix for issue 1243, this method potentially returned a cached value
#IF YOU CALL THIS METHOD, IT WILL CALL RPM
#Use get(:property) to check if cached values are available
cmd = ["-q", @resource[:name], "--nosignature", "--nodigest", "--qf", "#{NEVRAFORMAT}\n"]
begin
output = rpm(*cmd)
rescue Puppet::ExecutionFailure
return nil
end
# FIXME: We could actually be getting back multiple packages
# for multilib
@property_hash.update(self.class.nevra_to_hash(output))
return @property_hash.dup
end
# Here we just retrieve the version from the file specified in the source.
def latest
unless source = @resource[:source]
@resource.fail "RPMs must specify a package source"
end
cmd = [command(:rpm), "-q", "--qf", "#{NEVRAFORMAT}\n", "-p", "#{@resource[:source]}"]
h = self.class.nevra_to_hash(execfail(cmd, Puppet::Error))
return h[:ensure]
end
def install
source = nil
unless source = @resource[:source]
@resource.fail "RPMs must specify a package source"
end
# RPM gets pissy if you try to install an already
# installed package
if @resource.should(:ensure) == @property_hash[:ensure] or
@resource.should(:ensure) == :latest && @property_hash[:ensure] == latest
return
end
flag = "-i"
if @property_hash[:ensure] and @property_hash[:ensure] != :absent
flag = "-U"
end
rpm flag, "--oldpackage", source
end
def uninstall
query unless get(:arch)
nvr = "#{get(:name)}-#{get(:version)}-#{get(:release)}"
arch = ".#{get(:arch)}"
# If they specified an arch in the manifest, erase that Otherwise,
# erase the arch we got back from the query. If multiple arches are
# installed and only the package name is specified (without the
# arch), this will uninstall all of them on successive runs of the
# client, one after the other
if @resource[:name][-arch.size, arch.size] == arch
nvr += arch
else
nvr += ".#{get(:arch)}"
end
rpm "-e", nvr
end
def update
self.install
end
def self.nevra_to_hash(line)
line.chomp!
hash = {}
NEVRA_FIELDS.zip(line.split) { |f, v| hash[f] = v }
hash[:provider] = self.name
hash[:ensure] = "#{hash[:version]}-#{hash[:release]}"
return hash
end
end
|