问题
I'm adapting Apache cookbook to work with 2.4 Apache. Opscode cookbook is currently failing because it's generating conf file with LockFile keyword that is excluded from the list of the Apache 2.4 keywords.
I want to make a general solution, and populate my conf file depending on the version of software. To do so, I have to find out what's the version of already installed software. This same question has been bothering me for about a time now, but I've been managing to avoid it. Since I'm getting to it over and over again, I'd like to ask:
How to find out version of installed package/software, if cookbook doesn't specify it, i.e. installs latest available one?
Note: Please don't tell me to pass the command to the underlying shell. I'd like to know if there is a better, more... Chefy way? Maybe something related to Ohai?
EDIT: Seems I'm misunderstood. I wanted to know if there's a solution that abstracts the platform layer (just like Ohai does), where I'd say something like gimme_version('apache')
and get the installed apache version. I want to avoid writing case node['platform_family'] when... when... when
with platform specific code inside.
回答1:
I created Ohai plugin that solves the issue for me. Place the following code into a .rb file, and put the file into ohai/plugin/linux
folder. (Cannot provide absolute path since it varies depending on the platform and installation type)
Ohai.plugin(:PackageVersion) do
provides "package_version"
depends "platform_family"
collect_data do
pckg_list = Hash.new
case platform_family
when 'debian'
pckg_list = eval '{'+`dpkg-query -W -f='"${Package}"=> "${Version}", '`+'}'
when 'rhel' || 'fedora'
pckg_list = eval '{'+`rpm -qa --queryformat '"%{NAME}"=> "%{VERSION}", '`+'}'
when 'arch'
pckg_list = eval '{'+`package-query -Q -f '"%n"=> "%v", '`+'}'
when 'gentoo'
pckg_list = eval '{'+`equery list --format='"$name" => "$version", ' '*'`+'}'
end
package_version Mash.new pckg_list
end
end
Next time you run Chef, package version information will be in node["package_version"]["<package_name>"]
e.g. node["package_version"]["glibc"]
. I made it work for 5 platform families, but for Arch you'll have to make sure you have package-query
installed.
Important note: Ohai is loaded/populated before Chef recipe execution. This solution will not automatically update Ohai, so if you want to access data of the newly installed/upgraded packages, during current Chef run, you'll have to manually reload Ohai. To do it, place following block to your recipe under the package installation/upgrade block, just like shown below:
#example package instalation
package "whatever"
ohai "reload_ohai" do
action :reload
end
Thanks to @markoconnor. This solution is based on community plugins he pointed out. Those are no longer online. I adjusted them to work with Chef 11.0+ and here they are.
回答2:
An improvement on @Konzula's answer avoiding the use of eval. Also doesn't require package-query on archlinux. It does still make use of equery on gentoo, which can be installed from app-portage/gentoolkit if it is not already installed.
Ohai.plugin(:PackageVersion) do
provides 'package_version'
depends 'platform_family'
collect_data do
list = case platform_family
when 'debian'
`dpkg-query -W -f='${Package} ${Version}\\n'`
when 'rhel' || 'fedora'
`rpm -qa --queryformat '%{NAME} %{VERSION}\\n'`
when 'arch'
`pacman -Q`
when 'gentoo'
`equery list --format='$name $version' '*'`
end
package_version Mash[list.lines.map(&:split)]
end
end
来源:https://stackoverflow.com/questions/22179193/how-to-find-out-version-of-software-package-installed-on-the-node