Search code examples
packagechef-infrarpmyumchef-solo

rpm and Yum don't believe a package is installed after Chef installs


Running chef-solo (Installing Chef Omnibus (12.3)) on centos6.6

My recipe has the following simple code:

package 'cloud-init' do
    action :install
end 
log 'rpm-qi' do
    message `rpm -qi cloud-init`
    level :warn
end
log 'yum list' do
    message `yum list cloud-init`
    level :warn
end

But it outputs the following:

       - install version 0.7.5-10.el6.centos.2 of package cloud-init

     * log[rpm-qi] action write[2015-07-16T16:46:35+00:00] WARN: package cloud-init is not installed

[2015-07-16T16:46:35+00:00] WARN: Loaded plugins: fastestmirror, presto
   Available Packages
   cloud-init.x86_64                  0.7.5-10.el6.centos.2                 extras

I am at a loss as to why rpm/yum and actually rpmquery don't see the package as installed.

EDIT: To clarify I am specifically looking for the following string post package install to then apply a change to the file (I understand this is not a very chef way to do something I am happy to accept suggestions):

rpmquery -l cloud-init | grep 'distros/__init__.py$'

I have found that by using the following:

install_report =  shell_out('yum install -y cloud-init').stdout 
cloudinit_source = shell_out("rpmquery -l cloud-init | grep 'distros/__init__.py$'").stdout

I can then get the file I am looking for and perform

Chef::Util::FileEdit.new(cloudinit_source.chomp(''))

The file moves based on the distribution but I need to edit that file specifically with in place changes.


Solution

  • Untested code, just to give the idea:

    package 'cloud-init' do
        action :install
        notifies :run,"ruby_block[update_cloud_init]"
    end 
    
    ruby_block 'update_cloud_init' do
      block do
        cloudinit_source = shell_out("rpmquery -l cloud-init | grep 'distros/__init__.py$'").stdout
        rc = Chef::Util::FileEdit.new(cloudinit_source.chomp(''))
        rc.search_file_replace_line(/^what to find$/,
       "replacement datas for the line")
        rc.write_file
      end
    end
    

    ruby_block example taken and adapted from here

    I would better go using a template to manage the whole file, what I don't understand is why you don't know where it will be at first...


    Previous answer

    I assume it's a compile vs converge problem. at the time the message is stored (and so your command is executed) the package is not already installed.

    Chef run in two phase, compile then converge.

    At compile time it build a collection of resources and at converge time it execute code for the resource to get them in the described state.

    When your log resource is compiled, the ugly back-ticks are evaluated, at this time there's a package resource in the collection but the resource has not been executed, so the output is correct.

    I don't understand what you want to achieve with those log resources at all. If you want to test your node state after chef-run use a handler maybe calling ServerSpec as in Test-Kitchen.