6
6
Puppet ::Type . type ( :package ) . provide :openbsd , :parent => Puppet ::Provider ::Package do
7
7
desc "OpenBSD's form of `pkg_add` support.
8
8
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
+
9
13
This provider supports the `install_options` and `uninstall_options`
10
14
attributes, which allow command-line flags to be passed to pkg_add and pkg_delete.
11
15
These options should be specified as an array where each element is either a
18
22
defaultfor 'os.name' => :openbsd
19
23
confine 'os.name' => :openbsd
20
24
21
- has_feature :versionable
22
25
has_feature :install_options
23
26
has_feature :uninstall_options
24
- has_feature :upgradeable
25
27
has_feature :supports_flavors
26
28
27
- mk_resource_methods
28
-
29
29
def self . instances
30
- packages = [ ]
31
-
30
+ final = [ ]
32
31
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
47
40
48
- hash [ :provider ] = name
49
-
50
- packages << new ( hash )
51
- hash = { }
52
- }
53
- end
54
-
55
- packages
56
41
rescue Puppet ::ExecutionFailure
57
42
nil
58
43
end
59
44
end
60
45
61
46
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" }
103
62
end
63
+ packages
104
64
end
105
65
106
- def update
107
- install ( true )
108
- end
109
-
110
- def install ( latest = false )
66
+ def install
111
67
cmd = [ ]
112
68
69
+ full_name = get_full_name ( action = "install" )
70
+
113
71
cmd << '-r'
114
72
cmd << install_options
115
- cmd << get_full_name ( latest )
116
-
117
- if latest
118
- cmd . unshift ( '-z' )
119
- end
73
+ cmd << full_name
120
74
121
75
# pkg_add(1) doesn't set the return value upon failure so we have to peek
122
76
# at it's output to see if something went wrong.
123
77
output = Puppet ::Util . withenv ( { } ) { pkgadd cmd . flatten . compact }
124
- pp output
125
78
if output =~ /Can't find /
126
79
self . fail "pkg_add returned: #{ output . chomp } "
127
80
end
128
81
end
129
82
130
- def get_full_name ( latest = false )
83
+ def get_full_name ( action = "install" )
131
84
# In case of a real update (i.e., the package already exists) then
132
85
# pkg_add(8) can handle the flavors. However, if we're actually
133
86
# installing with 'latest', we do need to handle the flavors. This is
134
87
# done so we can feed pkg_add(8) the full package name to install to
135
88
# 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
167
89
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 = ''
174
98
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
99
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 } "
190
104
end
191
105
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
199
106
end
200
107
201
108
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
207
111
end
112
+ pkg ? pkg . properties : nil
208
113
end
209
114
210
115
def install_options
@@ -215,12 +120,16 @@ def uninstall_options
215
120
[ join_options ( resource [ :uninstall_options ] ) ]
216
121
end
217
122
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
220
129
end
221
130
222
131
def purge
223
- pkgdelete "-c" , "-q" , @resource [ :name ]
132
+ uninstall ( purge = true )
224
133
end
225
134
226
135
def flavor
@@ -229,7 +138,6 @@ def flavor
229
138
230
139
def flavor = ( value )
231
140
if flavor != @resource . should ( :flavor )
232
- uninstall
233
141
install
234
142
end
235
143
end
0 commit comments