chef-infrachef-recipechef-solo

How to find out version of software package installed on the node?


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.


Solution

  • 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.