summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/package/openbsd.rb
blob: bb07d894adaa1622a432a31673804fd686923736 (plain)
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
require 'puppet/provider/package'

# Packaging on OpenBSD.  Doesn't work anywhere else that I know of.
Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Package do
  desc "OpenBSD's form of `pkg_add` support."

  commands :pkginfo => "pkg_info", :pkgadd => "pkg_add", :pkgdelete => "pkg_delete"

  defaultfor :operatingsystem => :openbsd
  confine :operatingsystem => :openbsd

  has_feature :versionable

  def self.instances
    packages = []

    begin
      execpipe(listcmd) do |process|
        # our regex for matching pkg_info output
        regex = /^(.*)-(\d[^-]*)[-]?(\D*)(.*)$/
        fields = [:name, :ensure, :flavor ]
        hash = {}

        # now turn each returned line into a package object
        process.each { |line|
          if match = regex.match(line.split[0])
            fields.zip(match.captures) { |field,value|
              hash[field] = value
            }
            yup = nil
            name = hash[:name]

            hash[:provider] = self.name

            packages << new(hash)
            hash = {}
          else
            # Print a warning on lines we can't match, but move
            # on, since it should be non-fatal
            warning("Failed to match line #{line}")
          end
        }
      end

      return packages
    rescue Puppet::ExecutionFailure
      return nil
    end
  end

  def self.listcmd
    [command(:pkginfo), " -a"]
  end

  def install
    should = @resource.should(:ensure)

    unless @resource[:source]
      raise Puppet::Error,
        "You must specify a package source for BSD packages"
    end

    if @resource[:source][-1,1] == ::File::PATH_SEPARATOR
      e_vars = { :PKG_PATH => @resource[:source] }
      full_name = [ @resource[:name], get_version || @resource[:ensure], @resource[:flavor] ].join('-').chomp('-')
    else
      e_vars = {}
      full_name = @resource[:source]
    end

     Puppet::Util::Execution::withenv(e_vars) { pkgadd full_name }
  end

  def get_version
      execpipe([command(:pkginfo), " -I ", @resource[:name]]) do |process|
        # our regex for matching pkg_info output
        regex = /^(.*)-(\d[^-]*)[-]?(\D*)(.*)$/
        fields = [ :name, :version, :flavor ]
        master_version = 0

        process.each do |line|
          if match = regex.match(line.split[0])
            # now we return the first version, unless ensure is latest
            version = match.captures[1]
            return version unless @resource[:ensure] == "latest"

            master_version = version unless master_version > version
          end
        end

        return master_version unless master_version == 0
        raise Puppet::Error, "#{version} is not available for this package"
      end
  rescue Puppet::ExecutionFailure
      return nil
  end

  def query
    hash = {}
    info = pkginfo @resource[:name]

    # Search for the version info
    if info =~ /Information for (inst:)?#{@resource[:name]}-(\S+)/
      hash[:ensure] = $2
    else
      return nil
    end

    hash
  end

  def uninstall
    pkgdelete @resource[:name]
  end
end