Skip to content

Commit e6d4b04

Browse files
committed
Revamp OpenBSD package handling
* drop versionable * drop upgradeable * add support for package branches
1 parent ab43286 commit e6d4b04

File tree

1 file changed

+56
-148
lines changed

1 file changed

+56
-148
lines changed

lib/puppet/provider/package/openbsd.rb

Lines changed: 56 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Package do
77
desc "OpenBSD's form of `pkg_add` support.
88
9+
OpenBSD has the concept of package branches, providing multiple versions of the
10+
same package, i.e. `stable` vs. `snapshot`. To select a specific branch,
11+
suffix the package name with % sign follwed by the branch name, i.e. `gimp%stable`.
12+
913
This provider supports the `install_options` and `uninstall_options`
1014
attributes, which allow command-line flags to be passed to pkg_add and pkg_delete.
1115
These options should be specified as an array where each element is either a
@@ -18,193 +22,94 @@
1822
defaultfor 'os.name' => :openbsd
1923
confine 'os.name' => :openbsd
2024

21-
has_feature :versionable
2225
has_feature :install_options
2326
has_feature :uninstall_options
24-
has_feature :upgradeable
2527
has_feature :supports_flavors
2628

27-
mk_resource_methods
28-
2929
def self.instances
30-
packages = []
31-
30+
final = []
3231
begin
33-
execpipe(listcmd) do |process|
34-
# our regex for matching pkg_info output
35-
regex = /^(.*)-(\d[^-]*)-?([\w-]*)(.*)$/
36-
fields = [:name, :ensure, :flavor]
37-
hash = {}
38-
39-
# now turn each returned line into a package object
40-
process.each_line { |line|
41-
match = regex.match(line.split[0])
42-
next unless match
43-
44-
fields.zip(match.captures) { |field, value|
45-
hash[field] = value
46-
}
32+
packages = listcmd
33+
packages.each { |package, value|
34+
if !package.empty?()
35+
value[:provider] = self.name
36+
final << new(value)
37+
end
38+
}
39+
return final
4740

48-
hash[:provider] = name
49-
50-
packages << new(hash)
51-
hash = {}
52-
}
53-
end
54-
55-
packages
5641
rescue Puppet::ExecutionFailure
5742
nil
5843
end
5944
end
6045

6146
def self.listcmd
62-
[command(:pkginfo), "-a"]
63-
end
64-
65-
def latest
66-
if @resource[:flavor]
67-
query = "#{@resource[:name]}--#{@resource[:flavor]}"
68-
else
69-
query = @resource[:name] + "--"
70-
end
71-
72-
output = Puppet::Util.withenv({}) { pkginfo "-Q", query }
73-
74-
if output.nil? or output.size == 0 or output =~ /Error from /
75-
debug "Failed to query for #{resource[:name]}"
76-
return properties[:ensure]
77-
else
78-
# Remove all fuzzy matches first.
79-
output = output.split.select { |p| p =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*)/ }.join
80-
debug "pkg_info -Q for #{resource[:name]}: #{output}"
81-
end
82-
83-
if output =~ /^#{resource[:name]}-(\d[^-]*)-?(\w*) \(installed\)$/
84-
debug "Package is already the latest available"
85-
properties[:ensure]
86-
else
87-
match = /^(.*)-(\d[^-]*)-?(\w*)$/.match(output)
88-
debug "Latest available for #{resource[:name]}: #{match[2]}"
89-
90-
if properties[:ensure].to_sym == :absent
91-
return match[2]
92-
end
93-
94-
vcmp = properties[:ensure].split('.').map { |s| s.to_i } <=> match[2].split('.').map { |s| s.to_i }
95-
if vcmp > 0
96-
# The locally installed package may actually be newer than what a mirror
97-
# has. Log it at debug, but ignore it otherwise.
98-
debug "Package #{resource[:name]} #{properties[:ensure]} newer then available #{match[2]}"
99-
properties[:ensure]
100-
else
101-
match[2]
102-
end
47+
regex_fuzzy = /^(.*)--([\w-]+)?(%[^w]+)?$/
48+
f = []
49+
f = pkginfo("-a", "-z").split("\n")
50+
packages = {}
51+
f.each do |line|
52+
match = regex_fuzzy.match(line.split[0])
53+
name = match.captures[0]
54+
flavor = match.captures[1]
55+
branch = match.captures[2]
56+
if branch.nil?
57+
pname = name
58+
else
59+
pname = name + branch
60+
end
61+
packages[pname] = { :name => pname, :flavor => flavor, :branch => branch, :ensure => "present" }
10362
end
63+
packages
10464
end
10565

106-
def update
107-
install(true)
108-
end
109-
110-
def install(latest = false)
66+
def install
11167
cmd = []
11268

69+
full_name = get_full_name(action="install")
70+
11371
cmd << '-r'
11472
cmd << install_options
115-
cmd << get_full_name(latest)
116-
117-
if latest
118-
cmd.unshift('-z')
119-
end
73+
cmd << full_name
12074

12175
# pkg_add(1) doesn't set the return value upon failure so we have to peek
12276
# at it's output to see if something went wrong.
12377
output = Puppet::Util.withenv({}) { pkgadd cmd.flatten.compact }
124-
pp output
12578
if output =~ /Can't find /
12679
self.fail "pkg_add returned: #{output.chomp}"
12780
end
12881
end
12982

130-
def get_full_name(latest = false)
83+
def get_full_name(action="install")
13184
# In case of a real update (i.e., the package already exists) then
13285
# pkg_add(8) can handle the flavors. However, if we're actually
13386
# installing with 'latest', we do need to handle the flavors. This is
13487
# done so we can feed pkg_add(8) the full package name to install to
13588
# prevent ambiguity.
136-
if resource[:flavor]
137-
# If :ensure contains a version, use that instead of looking it up.
138-
# This allows for installing packages with the same stem, but multiple
139-
# version such as postfix-VERSION-flavor.
140-
if @resource[:ensure].to_s =~ /(\d[^-]*)$/
141-
use_version = @resource[:ensure]
142-
else
143-
use_version = ''
144-
end
145-
"#{resource[:name]}-#{use_version}-#{resource[:flavor]}"
146-
elsif resource[:name].to_s.match(/[a-z0-9]%[0-9a-z]/i)
147-
resource[:name].to_s
148-
elsif !latest
149-
"#{resource[:name]}--"
150-
else
151-
# If :ensure contains a version, use that instead of looking it up.
152-
# This allows for installing packages with the same stem, but multiple
153-
# version such as openldap-server.
154-
if @resource[:ensure].to_s =~ /(\d[^-]*)$/
155-
use_version = @resource[:ensure]
156-
else
157-
use_version = get_version
158-
end
159-
160-
if resource[:flavor]
161-
[@resource[:name], use_version, @resource[:flavor]].join('-').gsub(/-+$/, '')
162-
else
163-
[@resource[:name], use_version]
164-
end
165-
end
166-
end
16789

168-
def get_version
169-
pkg_search_name = @resource[:name]
170-
unless pkg_search_name.match(/[a-z0-9]%[0-9a-z]/i) and !@resource[:flavor]
171-
# we are only called when no flavor is specified
172-
# so append '--' to the :name to avoid patch versions on flavors
173-
pkg_search_name << "--"
90+
name_branch_regex = /^(\S*)(%\w*)$/
91+
match = name_branch_regex.match(@resource[:name])
92+
if match
93+
use_name = match.captures[0]
94+
use_branch = match.captures[1]
95+
else
96+
use_name = @resource[:name]
97+
use_branch = ''
17498
end
175-
# our regex for matching pkg_info output
176-
regex = /^(.*)-(\d[^-]*)[-]?(\w*)(.*)$/
177-
master_version = 0
178-
version = -1
179-
180-
# pkg_info -I might return multiple lines, i.e. flavors
181-
matching_pkgs = pkginfo("-I", "pkg_search_name")
182-
matching_pkgs.each_line do |line|
183-
next unless (match = regex.match(line.split[0]))
18499

185-
# now we return the first version, unless ensure is latest
186-
version = match.captures[1]
187-
return version unless @resource[:ensure] == "latest"
188-
189-
master_version = version unless master_version > version
100+
if @resource[:flavor]
101+
return "#{use_name}--#{@resource[:flavor]}#{use_branch}"
102+
else
103+
return "#{use_name}--#{use_branch}"
190104
end
191105

192-
return master_version unless master_version == 0
193-
194-
return '' if version == -1
195-
196-
raise Puppet::Error, _("%{version} is not available for this package") % { version: version }
197-
rescue Puppet::ExecutionFailure
198-
nil
199106
end
200107

201108
def query
202-
# Search for the version info
203-
if pkginfo(@resource[:name]) =~ /Information for (inst:)?#{@resource[:name]}-(\S+)/
204-
{ :ensure => Regexp.last_match(2) }
205-
else
206-
nil
109+
pkg = self.class.instances.find do |package|
110+
@resource[:name] == package.name
207111
end
112+
pkg ? pkg.properties : nil
208113
end
209114

210115
def install_options
@@ -215,12 +120,16 @@ def uninstall_options
215120
[join_options(resource[:uninstall_options])]
216121
end
217122

218-
def uninstall
219-
pkgdelete uninstall_options.flatten.compact, @resource[:name]
123+
def uninstall(purge = false)
124+
if purge
125+
pkgdelete "-c", "-qq", uninstall_options.flatten.compact, get_full_name(action="uninstall")
126+
else
127+
pkgdelete uninstall_options.flatten.compact, get_full_name(action="uninstall")
128+
end
220129
end
221130

222131
def purge
223-
pkgdelete "-c", "-q", @resource[:name]
132+
uninstall(purge=true)
224133
end
225134

226135
def flavor
@@ -229,7 +138,6 @@ def flavor
229138

230139
def flavor=(value)
231140
if flavor != @resource.should(:flavor)
232-
uninstall
233141
install
234142
end
235143
end

0 commit comments

Comments
 (0)