我有一套RHEL / CentOS系统,我使用的是NetBSD pkgsrc系统
将各种包安装到某个树中(例如/opt/local
)。我想要
用Puppet管理这个。我开始只是使用pkgin
提供程序,但是
我很快遇到名称空间冲突。例如,yum和pkgin
提供商正在添加Package[openssl]
,他们发生冲突。
要解决这个问题,我一直在尝试在我的pkgsrc包上使用静态前缀,
然后在实际传递给pkgin
命令进行处理时将其剥离。
首先,我写了一个添加前缀并设置提供者的定义。
define mypkgin::package($ensure='latest') {
package { "mypkgin_${title}":
ensure => $ensure,
provider => 'mypkgin',
}
}
这将在命名空间中显示为Mypkgin::Package[openssl]
,这样做
本身并不与任何事物冲突。它的目标是添加一个名为的资源
Package[mypkgin_openssl]
,与yum Package[openssl]
不冲突。
然后,我复制了pkgin提供程序代码并对其进行了修改以提供一个东西
名为mypkgin
。我在这里有一个小方法来从中删除前缀
名称,并在少数地方使用,以便pkgin
命令接收
pkgsrc包名称而不是前缀版本。
require "puppet/provider/package"
Puppet::Type.type(:package).provide :mypkgin, :parent => Puppet::Provider::Package do
desc "Package management using pkgin/pkgsrc, my local edition."
# Specify full path since it's not in Puppet's exec path
commands :pkgin => "/opt/local/bin/pkgin"
has_feature :installable, :uninstallable, :upgradeable, :versionable
# Strip prefix off of package name
def my_pkgname(package)
package.gsub(/^mypkgin_/, '')
end
def self.parse_pkgin_line(package)
# e.g.
# vim-7.2.446 = Vim editor (vi clone) without GUI
match, name, version, status = *package.match(/(\S+)-(\S+)(?: (=|>|<))?\s+.+$/)
if match
{
:name => name,
:status => status,
:ensure => version
}
end
end
def self.prefetch(packages)
super
# Without -f, no fresh pkg_summary files are downloaded
pkgin("-yf", :update)
end
def self.instances
pkgin(:list).split("\n").map do |package|
new(parse_pkgin_line(package))
end
end
def query
packages = parse_pkgsearch_line
if packages.empty?
if @resource[:ensure] == :absent
notice "declared as absent but unavailable #{@resource.file}:#{resource.line}"
return false
else
@resource.fail "No candidate to be installed"
end
end
packages.first.update( :ensure => :absent )
end
def parse_pkgsearch_line
packages = pkgin(:search, my_pkgname(resource[:name])).split("\n")
return [] if packages.length == 1
packages.slice!(-4, 4)
pkglist = packages.map{ |line| self.class.parse_pkgin_line(line) }
pkglist.select{ |package| my_pkgname(resource[:name]) == package[:name] }
end
def install
if String === @resource[:ensure]
pkgin("-y", :install, "#{my_pkgname(resource[:name])}-#{resource[:ensure]}")
else
pkgin("-y", :install, my_pkgname(resource[:name]))
end
end
def uninstall
pkgin("-y", :remove, my_pkgname(resource[:name]))
end
def latest
package = parse_pkgsearch_line.detect{ |package| package[:status] == '<' }
return properties[:ensure] if not package
return package[:ensure]
end
def update
pkgin("-y", :install, my_pkgname(resource[:name]))
end
end
每次我运行puppet agent --test
时,它都会告诉我它已经添加了所有这些内容
包。很明显我有一些命名空间错误。它认为每次运行都是如此
包需要安装或升级,并尝试这样做。
我假设在一个或多个地方,我应该添加或删除调用
my_pkgname()
,但我似乎无法弄清楚我哪里出错了。
答案 0 :(得分:1)
您的提供商通过预取确定系统上已有哪些软件包。看起来你没有替换或覆盖导致该过程最终依赖于instances()
方法的位。
看一下这个方法,看起来它会像pkgin提供者那样生成实例,直到生成的包名。这对您来说是个问题,因为您的方案涉及翻译包名称。仅仅将Puppet使用的名称翻译为本地名称是不够的 - 您还必须将原生名称翻译为您希望Puppet在提供者端创建实例时看到的名称。
看起来self.parse_pkgin_line()
可以很容易地修改,以便在您的包名前加上所需的前缀。这似乎是正确的做法,但我不确定它是否会产生任何不良副作用。也可能需要进行其他更改,例如parse_pkgsearch_line()
,但这对我来说并不是很清楚。