I need to update a specific yum package version if there is currently a lower version installed (security patches).
I need it to do nothing if the package is not installed and also if there is already a newer version.
This is to ensure that on a host running a specific version of our security patch cookbook the packages are updated to the minimum versions for compliance if they are installed but as new versions appear in the repo they do not automatically get updated.
This is in a set of base cookbooks that the business units may then install their application cookbooks that might upgrade a version further so we don’t want it to break with “Installed package foo-1.2.3 is newer than candidate package foo-1.2.1”
Please help point me in the right direction to do this with yum_package. I can probably do it with a bash block but that is certainly not ideal.
Ok I did get past ignoring if it isn’t installed (only_if “rpm -qa | grep #{pkg}”) but still need to figure out a way to not run if a newer version is installed.
yum_package 'foo' do
version '1.2.3'
only_if "rpm -qa | grep foo" # whatever logic to check if package is installed
only_if { Gem::Requirement.create('<= 1.2.3').satisfied_by?(Gem::Version.create(node['packages']['foo']['version'])) }
end
Note, that in this case node['packages']['foo']['version'] is defined by ohai before the chef run starts, so if the package 'foo' is installed by another cookbook/recipe, it will not show as present until the next chef run.
If that is an issue you could refresh ohai before this resource.
Also is is possible for the package version to not match the ruby versioning constraints. (e.g. xz-utils on my ubutu machine returns 5.1.1alpha+20120614-2ubuntu2 ). In this case you would need to strip out parts of the version that don't match what Gem::Requirement expects.
Forgive me but I’ve been trying to test this and can’t figure out the right way to insert variables into the not_if ruby block. The code is a loop to update the packages from attributes.
node[‘security_patches’][‘packages’].each do |pkg, ver|
yum_package pkg do
action :install
version ver
options '–disablerepo=* --enablerepo=rhel-6-server-rpms_local’
allow_downgrade false #ignore_failure true
only_if “rpm -qa | grep #{pkg}“
only_if { Gem::Requirement.create(”>= ver”).satisfied_by?(Gem::Version.create(node[‘packages’][pkg][ver])) }
end
Depending on your version of chef-client you could use the action of :lock. Another option is to use yum-plugin-versionlock package that works much like apt preferences. Here is a cookbook I have done this in: https://github.com/Netuitive/chef-netuitive/blob/v0.17.1/libraries/provider_repo.rb#L42-L55 that supports both debian based and epel based systems with version pinning where possible.