File: pkgng.rb

package info (click to toggle)
puppet-agent 7.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 19,092 kB
  • sloc: ruby: 245,074; sh: 456; makefile: 38; xml: 33
file content (173 lines) | stat: -rw-r--r-- 4,228 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
require_relative '../../../puppet/provider/package'

Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package do
  desc "A PkgNG provider for FreeBSD and DragonFly."

  commands :pkg => "/usr/local/sbin/pkg"

  confine :operatingsystem => [:freebsd, :dragonfly]

  defaultfor :operatingsystem => [:freebsd, :dragonfly]

  has_feature :versionable
  has_feature :upgradeable
  has_feature :install_options

  def self.get_query
    pkg(['query', '-a', '%n %v %o'])
  end

  def self.get_resource_info(name)
    pkg(['query', '%n %v %o', name])
  end

  def self.cached_version_list
    @version_list ||= get_version_list
  end

  def self.get_version_list
    @version_list = pkg(['version', '-voRL='])
  end

  def self.get_latest_version(origin)
    latest_version = cached_version_list.lines.find { |l| l =~ /^#{origin} / }
    if latest_version
      _name, compare, status = latest_version.chomp.split(' ', 3)
      if ['!', '?'].include?(compare)
        return nil
      end
      latest_version = status.split(' ').last.split(')').first
      return latest_version
    end
    nil
  end

  def self.parse_pkg_query_line(line)
    name, version, origin = line.chomp.split(' ', 3)
    latest_version  = get_latest_version(origin) || version

    {
      :ensure   => version,
      :name     => name,
      :provider => self.name,
      :origin   => origin,
      :version  => version,
      :latest   => latest_version
    }
  end

  def self.instances
    packages = []
    begin
      info = self.get_query
      get_version_list

      unless info
        return packages
      end

      info.lines.each do |line|
        hash = parse_pkg_query_line(line)
        packages << new(hash)
      end

      return packages
    rescue Puppet::ExecutionFailure
      return []
    end
  end

  def self.prefetch(resources)
    packages = instances
    resources.each_key do |name|
      provider = packages.find{|p| p.name == name or p.origin == name }
      if provider
        resources[name].provider = provider
      end
    end
  end

  def repo_tag_from_urn(urn)
    # extract repo tag from URN: urn:freebsd:repo:<tag>
    match = /^urn:freebsd:repo:(.+)$/.match(urn)
    raise ArgumentError urn.inspect unless match
    match[1]
  end

  def install
    source = resource[:source]
    source = URI(source) unless source.nil?

    # Ensure we handle the version
    case resource[:ensure]
    when true, false, Symbol
      installname = resource[:name]
    else
      # If resource[:name] is actually an origin (e.g. 'www/curl' instead of
      # just 'curl'), drop the category prefix. pkgng doesn't support version
      # pinning with the origin syntax (pkg install curl-1.2.3 is valid, but
      # pkg install www/curl-1.2.3 is not).
      if resource[:name] =~ /\//
        installname = resource[:name].split('/')[1] + '-' + resource[:ensure]
      else
        installname = resource[:name] + '-' + resource[:ensure]
      end
    end

    if not source # install using default repo logic
      args = ['install', '-qy']
    elsif source.scheme == 'urn' # install from repo named in URN
      tag = repo_tag_from_urn(source.to_s)
      args = ['install', '-qy', '-r', tag]
    else # add package located at URL
      args = ['add', '-q']
      installname = source.to_s
    end
    args += install_options if @resource[:install_options]
    args << installname

    pkg(args)
  end

  def uninstall
    pkg(['remove', '-qy', resource[:name]])
  end

  def query
    begin
      output = self.class.get_resource_info(resource[:name])
    rescue Puppet::ExecutionFailure
      return nil
    end

    self.class.parse_pkg_query_line(output)
  end

  def version
    @property_hash[:version]
  end

  def version=
    pkg(['install', '-qfy', "#{resource[:name]}-#{resource[:version]}"])
  end

  # Upgrade to the latest version
  def update
    install
  end

  # Return the latest version of the package
  def latest
    debug "returning the latest #{@property_hash[:name].inspect} version #{@property_hash[:latest].inspect}"
    @property_hash[:latest]
  end

  def origin
    @property_hash[:origin]
  end

  def install_options
    join_options(@resource[:install_options])
  end

end