components/ruby/puppet/patches/puppet-12-pkg-provider-latest.patch
changeset 7565 48aa82a0931f
parent 5860 afd31ba91ee9
equal deleted inserted replaced
7564:f958607559a6 7565:48aa82a0931f
     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('@')
    89 +    #FMRI                                               STATE       UFXI
    63 +    #FMRI                                               STATE       UFXI
    90 +    #pkg:/[email protected],5.11-0.86:20080426T180612Z    installed   ----
    64 +    #pkg:/[email protected],5.11-0.86:20080426T180612Z    installed   ----
    91 +    when /^(\S+) +(\S+) +(....)$/
    65 +    when /^(\S+) +(\S+) +(....)$/
    92 +      full_fmri = $1.split('@')
    66 +      full_fmri = $1.split('@')
    93 +      {:name => full_fmri[0], :ensure => full_fmri[1]}.merge pkg_state($2).merge(ufxi_flag($3))
    67 +      {:name => full_fmri[0], :ensure => full_fmri[1]}.merge pkg_state($2).merge(ufxi_flag($3))
       
    68 +
    94      else
    69      else
    95        raise ArgumentError, 'Unknown line format %s: %s' % [self.name, line]
    70        raise ArgumentError, 'Unknown line format %s: %s' % [self.name, line]
    96      end).merge({:provider => self.name})
    71      end).merge({:provider => self.name})
    97    end
    72    end
    98  
    73  
   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.