3 Using --parsable=0 option to obsolete pkg list -Hn |
3 Using --parsable=0 option to obsolete pkg list -Hn |
4 Fixing problem with ambiguous package names |
4 Fixing problem with ambiguous package names |
5 Wildcards support |
5 Wildcards support |
6 install_options/uninstall_options features support |
6 install_options/uninstall_options features support |
7 |
7 |
8 --- puppet-3.8.6/lib/puppet/provider/package/pkg.rb.orig 2016-04-19 15:09:14.789792650 -0700 |
8 diff --git a/lib/puppet/provider/package/pkg.rb b/lib/puppet/provider/package/pkg.rb |
9 +++ puppet-3.8.6/lib/puppet/provider/package/pkg.rb 2016-04-19 15:09:44.646514474 -0700 |
9 --- a/lib/puppet/provider/package/pkg.rb |
10 @@ -5,7 +5,7 @@ |
10 +++ b/lib/puppet/provider/package/pkg.rb |
|
11 @@ -1,7 +1,7 @@ |
11 require 'puppet/provider/package' |
12 require 'puppet/provider/package' |
12 |
13 |
13 Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package do |
14 Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package do |
14 - desc "OpenSolaris image packaging system. See pkg(5) for more information" |
15 - desc "OpenSolaris image packaging system. See pkg(5) for more information." |
15 + desc "Solaris image packaging system. See pkg(5) for more information" |
16 + desc "Solaris image packaging system. See pkg(5) for more information" |
16 # http://docs.oracle.com/cd/E19963-01/html/820-6572/managepkgs.html |
17 # https://docs.oracle.com/cd/E19963-01/html/820-6572/managepkgs.html |
17 # A few notes before we start : |
18 # A few notes before we start: |
18 # Opensolaris pkg has two slightly different formats (as of now.) |
19 # Opensolaris pkg has two slightly different formats (as of now.) |
19 @@ -18,10 +18,10 @@ |
20 @@ -14,10 +14,10 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
20 # TODO: We still have to allow packages to specify a preferred publisher. |
21 # TODO: We still have to allow packages to specify a preferred publisher. |
21 |
22 |
22 has_feature :versionable |
23 has_feature :versionable |
23 - |
24 - |
24 has_feature :upgradable |
25 has_feature :upgradable |
27 + has_feature :install_options |
28 + has_feature :install_options |
28 + has_feature :uninstall_options |
29 + has_feature :uninstall_options |
29 |
30 |
30 commands :pkg => "/usr/bin/pkg" |
31 commands :pkg => "/usr/bin/pkg" |
31 |
32 |
32 @@ -30,7 +30,7 @@ |
33 @@ -69,6 +69,10 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
33 defaultfor :osfamily => :solaris, :kernelrelease => ['5.11', '5.12'] |
|
34 |
|
35 def self.instances |
|
36 - pkg(:list, '-H').split("\n").map{|l| new(parse_line(l))} |
|
37 + pkg(:list, '-Hv').split("\n").map{|l| new(parse_line(l))} |
|
38 end |
|
39 |
|
40 # The IFO flag field is just what it names, the first field can have ether |
|
41 @@ -73,6 +73,10 @@ |
|
42 {} |
34 {} |
43 end |
35 end |
44 |
36 |
45 + def self.ufxi_flag(flags) |
37 + def self.ufxi_flag(flags) |
46 + {} |
38 + {} |
47 + end |
39 + end |
48 + |
40 + |
49 # pkg state was present in the older version of pkg (with UFOXI) but is |
41 # pkg state was present in the older version of pkg (with UFOXI) but is |
50 # no longer available with the IFO field version. When it was present, |
42 # no longer available with the IFO field version. When it was present, |
51 # it was used to indicate that a particular version was present (installed) |
43 # it was used to indicate that a particular version was present (installed) |
52 @@ -94,29 +98,73 @@ |
44 @@ -100,11 +104,74 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
53 # formats of output for different pkg versions. |
45 when %r'^pkg://([^/]+)/([^@]+)@(\S+) +(\S+) +(.....)$' |
54 def self.parse_line(line) |
46 {:publisher => $1, :name => $2, :ensure => $3}.merge pkg_state($4).merge(ufoxi_flag($5)) |
55 (case line.chomp |
47 |
56 - # NAME (PUBLISHER) VERSION IFO (new:630e1ffc7a19) |
|
57 - # system/core-os 0.5.11-0.169 i-- |
|
58 - when /^(\S+) +(\S+) +(...)$/ |
|
59 - {:name => $1, :ensure => $2}.merge ifo_flag($3) |
|
60 - |
|
61 - # x11/wm/fvwm (fvwm.org) 2.6.1-3 i-- |
|
62 - when /^(\S+) \((.+)\) +(\S+) +(...)$/ |
|
63 - {:name => $1, :publisher => $2, :ensure => $3}.merge ifo_flag($4) |
|
64 - |
|
65 - # NAME (PUBLISHER) VERSION STATE UFOXI (dvd:052adf36c3f4) |
|
66 - # SUNWcs 0.5.11-0.126 installed ----- |
|
67 - when /^(\S+) +(\S+) +(\S+) +(.....)$/ |
|
68 - {:name => $1, :ensure => $2}.merge pkg_state($3).merge(ufoxi_flag($4)) |
|
69 - |
|
70 - # web/firefox/plugin/flash (extra) 10.0.32.18-0.111 installed ----- |
|
71 - when /^(\S+) \((.+)\) +(\S+) +(\S+) +(.....)$/ |
|
72 - {:name => $1, :publisher => $2, :ensure => $3}.merge pkg_state($4).merge(ufoxi_flag($5)) |
|
73 - |
|
74 + #pkg list -vH output format since build 165 |
48 + #pkg list -vH output format since build 165 |
75 + #FMRI IFO |
49 + #FMRI IFO |
76 + #pkg://solaris/system/[email protected]:20151116T010109Z i-- |
50 + #pkg://solaris/system/[email protected]:20151116T010109Z i-- |
77 + when /^(\S+) +(...)$/ |
51 + when /^(\S+) +(...)$/ |
78 + full_fmri = $1.split('@') |
52 + full_fmri = $1.split('@') |
139 + end |
114 + end |
140 + |
115 + |
141 def hold |
116 def hold |
142 pkg(:freeze, @resource[:name]) |
117 pkg(:freeze, @resource[:name]) |
143 end |
118 end |
144 @@ -126,31 +174,22 @@ |
119 @@ -167,28 +234,28 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
145 raise Puppet::Error, "Unable to unfreeze #{r[:out]}" unless [0,4].include? r[:exit] |
120 false |
146 end |
121 end |
147 |
122 |
148 - # Return the version of the package. Note that the bug |
123 - # Return the version of the package. Note that the bug |
149 - # http://defect.opensolaris.org/bz/show_bug.cgi?id=19159% |
124 - # http://defect.opensolaris.org/bz/show_bug.cgi?id=19159% |
150 - # notes that we can't use -Ha for the same even though the manual page reads that way. |
125 - # notes that we can't use -Ha for the same even though the manual page reads that way. |
151 + # Return the version of the package. |
|
152 def latest |
126 def latest |
153 - lines = pkg(:list, "-Hn", @resource[:name]).split("\n") |
127 - lines = pkg(:list, "-Hvn", @resource[:name]).split("\n") |
154 - |
128 + # Dry-run package update to check the availability of the latest version |
155 - # remove certificate expiration warnings from the output, but report them |
129 + # -- return code -- |
156 - # Note: we'd like to use select! here to modify the lines array and avoid |
130 + # 0: latest version available |
157 - # the second select further down. But Solaris 11 comes with ruby 1.8.7 |
131 + # 1: error |
158 - # which doesn't support select!, so do this as two selects. |
132 + # 4: already up-to-date |
|
133 + r = exec_cmd(command(:pkg), 'update', '-n', '--parsable=0', @resource[:name]).split('\n') |
|
134 + package_versions = JSON.parse(r[:out])['change-packages'] |
|
135 |
|
136 # remove certificate expiration warnings from the output, but report them |
159 - cert_warnings = lines.select { |line| line =~ /^Certificate/ } |
137 - cert_warnings = lines.select { |line| line =~ /^Certificate/ } |
160 - if cert_warnings |
138 + cert_warnings = r[:out].select { |line| line =~ /^Certificate/ } |
161 - Puppet.warning("pkg warning: #{cert_warnings}") |
139 unless cert_warnings.empty? |
162 - end |
140 Puppet.warning("pkg warning: #{cert_warnings.join(', ')}") |
163 - |
141 end |
|
142 + lst = r[:out].select { |line| line !~ /^Certificate/ }.map { |line| self.class.parse_line(line) } |
|
143 |
164 - lst = lines.select { |line| line !~ /^Certificate/ }.map { |line| self.class.parse_line(line) } |
144 - lst = lines.select { |line| line !~ /^Certificate/ }.map { |line| self.class.parse_line(line) } |
165 - |
145 - |
166 - # Now we know there is a newer version. But is that installable? (i.e are there any constraints?) |
146 - # Now we know there is a newer version. But is that installable? (i.e are there any constraints?) |
167 - # return the first known we find. The only way that is currently available is to do a dry run of |
147 - # return the first known we find. The only way that is currently available is to do a dry run of |
168 - # pkg update and see if could get installed (`pkg update -n res`). |
148 - # pkg update and see if could get installed (`pkg update -n res`). |
169 - known = lst.find {|p| p[:status] == 'known' } |
149 - known = lst.find {|p| p[:status] == 'known' } |
170 - return known[:ensure] if known and exec_cmd(command(:pkg), 'update', '-n', @resource[:name])[:exit].zero? |
150 - return known[:ensure] if known and exec_cmd(command(:pkg), 'update', '-n', @resource[:name])[:exit].zero? |
171 - |
151 + raise Puppet::Error, "Cannot update to the latest package: #{r[:out]}\n" \ |
|
152 + unless [0, 4].include? r[:exit] |
|
153 |
172 - # If not, then return the installed, else nil |
154 - # If not, then return the installed, else nil |
173 - (lst.find {|p| p[:status] == 'installed' } || {})[:ensure] |
155 - (lst.find {|p| p[:status] == 'installed' } || {})[:ensure] |
174 + # Dry-run package update to check the availability of the latest version |
|
175 + # -- return code -- |
|
176 + # 0: latest version available |
|
177 + # 1: error |
|
178 + # 4: already up-to-date |
|
179 + r = exec_cmd(command(:pkg), 'update', '-n', '--parsable=0', @resource[:name]) |
|
180 + raise Puppet::Error, "Cannot update to the latest package: #{r[:out]}\n" \ |
|
181 + unless [0, 4].include? r[:exit] |
|
182 + |
|
183 + package_versions = JSON.parse(r[:out])['change-packages'] |
|
184 + |
|
185 + lst = parse_latest_query(r[:exit], package_versions) |
156 + lst = parse_latest_query(r[:exit], package_versions) |
186 + Puppet.debug "Desirable query status = #{lst}" |
157 + Puppet.debug "Desirable query status = #{lst}" |
187 + return lst[:ensure] |
158 + return lst[:ensure] |
188 end |
159 end |
189 |
160 |
190 # install the package and accept all licenses. |
161 # install the package and accept all licenses. |
191 @@ -166,19 +205,22 @@ |
162 @@ -206,7 +273,10 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
192 self.uninstall if Puppet::Util::Package.versioncmp(should, is[:ensure]) < 0 |
163 unless should.is_a? Symbol |
193 end |
164 name += "@#{should}" |
194 end |
165 end |
195 - r = exec_cmd(command(:pkg), 'install', '--accept', name) |
166 - r = exec_cmd(command(:pkg), command, '--accept', name) |
196 + |
167 + |
197 + cmd = ['--accept'] |
168 + opts = ['--accept'] |
198 + cmd << join_options(@resource[:install_options]) if @resource[:install_options] |
169 + opts << join_options(@resource[:install_options]) if @resource[:install_options] |
199 + r = exec_cmd(command(:pkg), 'install', cmd, name) |
170 + r = exec_cmd(command(:pkg), 'install', opts, name) |
200 return r if nofail |
171 return r if nofail |
201 raise Puppet::Error, "Unable to update #{r[:out]}" if r[:exit] != 0 |
172 raise Puppet::Error, "Unable to update #{r[:out]}" if r[:exit] != 0 |
202 end |
173 end |
203 |
174 @@ -219,6 +289,7 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
204 - # uninstall the package. The complication comes from the -r_ecursive flag which is no longer |
|
205 - # present in newer package version. |
|
206 + # uninstall the package. |
|
207 def uninstall |
|
208 cmd = [:uninstall] |
|
209 case (pkg :version).chomp |
|
210 when /052adf36c3f4/ |
175 when /052adf36c3f4/ |
211 cmd << '-r' |
176 cmd << '-r' |
212 end |
177 end |
213 + cmd << join_options(@resource[:uninstall_options]) if @resource[:uninstall_options] |
178 + cmd << join_options(@resource[:uninstall_options]) if @resource[:uninstall_options] |
214 cmd << @resource[:name] |
179 cmd << @resource[:name] |
215 pkg cmd |
180 pkg cmd |
216 end |
181 end |
217 @@ -191,10 +233,22 @@ |
182 @@ -231,10 +302,22 @@ Puppet::Type.type(:package).provide :pkg, :parent => Puppet::Provider::Package d |
218 raise Puppet::Error, "Unable to update #{r[:out]}" |
183 raise Puppet::Error, "Unable to update #{r[:out]}" |
219 end |
184 end |
220 |
185 |
221 + def wildcard? |
186 + def wildcard? |
222 + @resource[:name].include?("*") || @resource[:name].include?("?") |
187 + @resource[:name].include?("*") || @resource[:name].include?("?") |
223 + end |
188 + end |
224 + |
189 + |
225 # list a specific package |
190 # list a specific package |
226 def query |
191 def query |
227 - r = exec_cmd(command(:pkg), 'list', '-H', @resource[:name]) |
192 r = exec_cmd(command(:pkg), 'list', '-Hv', @resource[:name]) |
228 + r = exec_cmd(command(:pkg), 'list', '-Hv', @resource[:name]) |
|
229 return {:ensure => :absent, :name => @resource[:name]} if r[:exit] != 0 |
193 return {:ensure => :absent, :name => @resource[:name]} if r[:exit] != 0 |
230 + |
194 + |
231 + # Does input contain wildcard? just pass it down and let pkg decide |
195 + # Does input contain wildcard? just pass it down and let pkg decide |
232 + return {:ensure => :installed, :name => @resource[:name], :provider => self.class.name} if wildcard? |
196 + return {:ensure => :installed, :name => @resource[:name], :provider => self.class.name} if wildcard? |
233 + # If there are more than one results? this will fail due to the ambiguity. |
197 + # If there are more than one results? this will fail due to the ambiguity. |