Skip to content

Commit ee87505

Browse files
committed
Revamp OpenBSD package handling
* pkg.conf file is long gone * drop versionable * drop upgradeable * add support for package branches
1 parent ab43286 commit ee87505

File tree

6 files changed

+98
-295
lines changed

6 files changed

+98
-295
lines changed

lib/puppet/provider/package/openbsd.rb

+50-141
Original file line numberDiff line numberDiff line change
@@ -6,49 +6,56 @@
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
1216
string or a hash."
1317

14-
commands :pkginfo => "pkg_info",
15-
:pkgadd => "pkg_add",
18+
commands :pkgadd => "pkg_add",
19+
:pkginfo => "pkg_info",
1620
:pkgdelete => "pkg_delete"
1721

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
3030
packages = []
3131

3232
begin
3333
execpipe(listcmd) do |process|
3434
# our regex for matching pkg_info output
35-
regex = /^(.*)-(\d[^-]*)-?([\w-]*)(.*)$/
36-
fields = [:name, :ensure, :flavor]
35+
regex = /^(.*)--([\w-]+)?(%[^w]+)?$/
36+
fields = [:name, :flavor, :branch]
3737
hash = {}
3838

3939
# now turn each returned line into a package object
4040
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-
}
47-
48-
hash[:provider] = name
49-
50-
packages << new(hash)
51-
hash = {}
41+
match = regex.match(line.split("\n")[0])
42+
if match
43+
fields.zip(match.captures) { |field, value|
44+
hash[field] = value
45+
}
46+
47+
hash[:name] = "#{hash[:name]}#{hash[:branch]}" if hash[:branch]
48+
49+
hash[:provider] = name
50+
packages << new(hash)
51+
hash = {}
52+
else
53+
unless line =~ /Updating the pkgdb/
54+
# Print a warning on lines we can't match, but move
55+
# on, since it should be non-fatal
56+
warning(_("Failed to match line %{line}") % { line: line })
57+
end
58+
end
5259
}
5360
end
5461

@@ -59,168 +66,71 @@ def self.instances
5966
end
6067

6168
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
103-
end
69+
[command(:pkginfo), "-a", "-z"]
10470
end
10571

106-
def update
107-
install(true)
108-
end
109-
110-
def install(latest = false)
72+
def install
11173
cmd = []
11274

75+
full_name = get_full_name
76+
11377
cmd << '-r'
11478
cmd << install_options
115-
cmd << get_full_name(latest)
116-
117-
if latest
118-
cmd.unshift('-z')
119-
end
79+
cmd << full_name
12080

12181
# pkg_add(1) doesn't set the return value upon failure so we have to peek
12282
# at it's output to see if something went wrong.
12383
output = Puppet::Util.withenv({}) { pkgadd cmd.flatten.compact }
124-
pp output
12584
if output =~ /Can't find /
12685
self.fail "pkg_add returned: #{output.chomp}"
12786
end
12887
end
12988

130-
def get_full_name(latest = false)
89+
def get_full_name
13190
# In case of a real update (i.e., the package already exists) then
13291
# pkg_add(8) can handle the flavors. However, if we're actually
13392
# installing with 'latest', we do need to handle the flavors. This is
13493
# done so we can feed pkg_add(8) the full package name to install to
13594
# 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
16795

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 << "--"
96+
name_branch_regex = /^(\S*)(%\w*)$/
97+
match = name_branch_regex.match(@resource[:name])
98+
if match
99+
use_name = match.captures[0]
100+
use_branch = match.captures[1]
101+
else
102+
use_name = @resource[:name]
103+
use_branch = ''
174104
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]))
184-
185-
# now we return the first version, unless ensure is latest
186-
version = match.captures[1]
187-
return version unless @resource[:ensure] == "latest"
188105

189-
master_version = version unless master_version > version
106+
if @resource[:flavor]
107+
"#{use_name}--#{@resource[:flavor]}#{use_branch}"
108+
else
109+
"#{use_name}--#{use_branch}"
190110
end
191-
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
199111
end
200112

201113
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
114+
pkg = self.class.instances.find do |package|
115+
@resource[:name] == package.name
207116
end
117+
pkg ? pkg.properties : nil
208118
end
209119

210120
def install_options
211121
join_options(resource[:install_options])
212122
end
213123

214124
def uninstall_options
215-
[join_options(resource[:uninstall_options])]
125+
join_options(resource[:uninstall_options]) || []
216126
end
217127

218128
def uninstall
219-
pkgdelete uninstall_options.flatten.compact, @resource[:name]
129+
pkgdelete uninstall_options.flatten.compact, get_full_name
220130
end
221131

222132
def purge
223-
pkgdelete "-c", "-q", @resource[:name]
133+
pkgdelete "-c", "-qq", uninstall_options.flatten.compact, get_full_name
224134
end
225135

226136
def flavor
@@ -229,7 +139,6 @@ def flavor
229139

230140
def flavor=(value)
231141
if flavor != @resource.should(:flavor)
232-
uninstall
233142
install
234143
end
235144
end

spec/fixtures/unit/provider/package/openbsd/pkginfo.detail

-19
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
bash-3.1.17 GNU Bourne Again Shell
2-
bzip2-1.0.3 block-sorting file compressor, unencumbered
3-
expat-2.0.0 XML 1.0 parser written in C
4-
gettext-0.14.5p1 GNU gettext
5-
libiconv-1.9.2p3 character set conversion library
6-
lzo-1.08p1 portable speedy lossless data compression library
7-
openvpn-2.0.6 easy-to-use, robust, and highly configurable VPN
8-
python-2.4.3p0 interpreted object-oriented programming language
9-
vim-7.0.42-no_x11 vi clone, many additional features
10-
wget-1.10.2p0 retrieve files from the web via HTTP, HTTPS and FTP
1+
autoconf--%2.13
2+
autoconf--%2.56
3+
bash--
4+
postfix--ldap%stable
5+
puppet--%8
6+
zstd--

spec/fixtures/unit/provider/package/openbsd/pkginfo.query

-1
This file was deleted.

spec/fixtures/unit/provider/package/openbsd/pkginfo_flavors.list

-2
This file was deleted.

0 commit comments

Comments
 (0)