freebsd-ports/sysutils/puppet27/files/optpatch-package_origin
Steve Wills 8b3517b3bb - Update puppet to 3.0.1
- Add sysutils/puppet27 for those who will still need the older version

Feature safe:	yes
2012-10-22 13:39:41 +00:00

200 lines
5.9 KiB
Text

$FreeBSD$
--- lib/puppet/provider/package/freebsd.rb.orig
+++ lib/puppet/provider/package/freebsd.rb
@@ -1,37 +1,163 @@
-Puppet::Type.type(:package).provide :freebsd, :parent => :openbsd do
- desc "The specific form of package management on FreeBSD. This is an
- extremely quirky packaging system, in that it freely mixes between
- ports and packages. Apparently all of the tools are written in Ruby,
- so there are plans to rewrite this support to directly use those
- libraries."
+require 'open-uri'
+require 'net/ftp'
+require 'bzip2'
- commands :pkginfo => "/usr/sbin/pkg_info",
- :pkgadd => "/usr/sbin/pkg_add",
- :pkgdelete => "/usr/sbin/pkg_delete"
+Puppet::Type.type(:package).provide :freebsd, :parent => Puppet::Provider::Package do
+ include Puppet::Util::Execution
+
+ desc "The specific form of package management on FreeBSD. Resource names must be
+ specified as the port origin: <port_category>/<port_name>."
+
+ commands :pkginfo => "/usr/sbin/pkg_info",
+ :pkgadd => "/usr/sbin/pkg_add",
+ :pkgdelete => "/usr/sbin/pkg_delete"
confine :operatingsystem => :freebsd
+ defaultfor :operatingsystem => :freebsd
- def self.listcmd
- command(:pkginfo)
+ @@lock = Mutex.new
+ @@ports_index = nil
+
+ # fix bug in URI::FTP merge method that tries to set typecode
+ # even when other is a string.
+ class URI::FTP
+ def merge(other)
+ tmp = super(other)
+ if self != tmp
+ tmp.set_typecode(other.typecode) rescue NoMethodError
+ end
+ return tmp
+ end
end
- def install
- should = @resource.should(:ensure)
+ def self.parse_pkg_string(pkg_string)
+ {
+ :pkg_name => pkg_string.split("-").slice(0..-2).join("-"),
+ :pkg_version => pkg_string.split("-")[-1],
+ }
+ end
- if @resource[:source] =~ /\/$/
- if @resource[:source] =~ /^(ftp|https?):/
- Puppet::Util::Execution::withenv :PACKAGESITE => @resource[:source] do
- pkgadd "-r", @resource[:name]
+ def self.unparse_pkg_info(pkg_info)
+ [:pkg_name, :pkg_version].map { |key| pkg_info[key] }.join("-")
+ end
+
+ def self.parse_origin(origin_path)
+ begin
+ origin = {
+ :port_category => origin_path.split("/").fetch(-2),
+ :port_name => origin_path.split("/").fetch(-1),
+ }
+ rescue IndexError
+ raise Puppet::Error.new "#{origin_path}: not in required origin format: .*/<port_category>/<port_name>"
+ end
+ origin
+ end
+
+ def self.instances
+ packages = []
+ output = pkginfo "-aoQ"
+ output.split("\n").each do |data|
+ pkg_string, pkg_origin = data.split(":")
+ pkg_info = self.parse_pkg_string(pkg_string)
+
+ packages << new({
+ :provider => self.name,
+ :name => pkg_origin,
+ :ensure => pkg_info[:pkg_version],
+ })
+ end
+ packages
+ end
+
+ def ports_index
+ @@lock.synchronize do
+ if @@ports_index.nil?
+ @@ports_index = {}
+ uri = source.merge "INDEX.bz2"
+ Puppet.debug "Fetching INDEX: #{uri.inspect}"
+ begin
+ Bzip2::Reader.open(uri) do |f|
+ while (line = f.gets)
+ fields = line.split("|")
+ pkg_info = self.class.parse_pkg_string(fields[0])
+ origin = self.class.parse_origin(fields[1])
+ @@ports_index[origin] = pkg_info
+ end
+ end
+ rescue IOError, OpenURI::HTTPError, Net::FTPError
+ @@ports_index = nil
+ raise Puppet::Error.new "Could not fetch ports INDEX: #{$!}"
end
- else
- Puppet::Util::Execution::withenv :PKG_PATH => @resource[:source] do
- pkgadd @resource[:name]
+ end
+ end
+ @@ports_index
+ end
+
+ def uri_path
+ Facter.loadfacts
+ File.join(
+ "/", "pub", "FreeBSD", "ports",
+ Facter.value(:hardwareisa),
+ [
+ "packages",
+ Facter.value(:kernelmajversion).split(".")[0],
+ "stable",
+ ].join("-")
+ ) << "/"
+ end
+
+ def source
+ if !defined? @source
+ if @resource[:source]
+ @source = URI.parse(@resource[:source])
+ if @source.path.empty?
+ @source.merge! uri_path
end
+ else # source parameter not set; build default source URI
+ @source = URI::FTP.build({
+ :host => "ftp.freebsd.org",
+ :path => uri_path,
+ })
end
+ Puppet.debug "Package: #{@resource[:name]}: source => #{@source.inspect}"
+ end
+ @source
+ end
+
+ def origin
+ if !defined? @origin
+ @origin = self.class.parse_origin(@resource[:name])
+ Puppet.debug "Package: #{@resource[:name]}: origin => #{@origin.inspect}"
+ end
+ @origin
+ end
+
+ def package_uri
+ begin
+ pkg_name = self.class.unparse_pkg_info(ports_index.fetch(origin))
+ rescue IndexError
+ raise Puppet::Error.new "package not found in INDEX"
+ end
+ uri = source.merge File.join("All", pkg_name + ".tbz")
+ Puppet.debug "Package: #{@resource[:name]}: package_uri => #{uri.inspect}"
+ uri
+ end
+
+ def install
+ should = @resource.should(:ensure)
+ origin # call origin so we check the package name for correctness early
+
+ # Source URI is for local file path.
+ if !source.absolute? or source.scheme == "file"
+ pkgadd source.path
+ # Source URI is to specific package file
+ elsif source.absolute? && source.path.end_with?(".tbz")
+ pkgadd source.to_s
+ # Source URI is to a package repository
else
- Puppet.warning "source is defined but does not have trailing slash, ignoring #{@resource[:source]}" if @resource[:source]
- pkgadd "-r", @resource[:name]
+ pkgadd "-f", package_uri.to_s
end
+ nil
end
def query
@@ -44,6 +170,7 @@
end
def uninstall
- pkgdelete "#{@resource[:name]}-#{@resource.should(:ensure)}"
+ output = pkginfo "-qO", @resource[:name]
+ output.split("\n").each { |pkg_name| pkgdelete([pkg_name]) }
end
end