Chef Gem Compile Time Compatibility
TL;DR, if you’re using Chef 11 and chef-sugar
, upgrade chef-sugar
to version 3.0.1. If you cannot upgrade, use the following in your chef_gem
resources in your recipes:
compile_time true if Chef::Resource::ChefGem.instance_methods(false).include?(:compile_time)
As you may be aware, Chef 12.1.0 introduces a change to the chef_gem
resource that prints out warning messages like this:
WARN: chef_gem[chef-vault] chef_gem compile_time installation is deprecated
WARN: chef_gem[chef-vault] Please set `compile_time false` on the resource to use the new behavior.
WARN: chef_gem[chef-vault] or set `compile_time true` on the resource if compile_time behavior is required.
These messages are just warnings, but if you’re installing a lot of gems in your recipes, you may be annoyed by the output. As the warning indicates, you can set compile_time true
property. This doesn’t work on versions of Chef before 12.1, though:
NoMethodError: undefined method `compile_time' for Chef::Resource::ChefGem
So, as a workaround, we can ask whether we respond to the compile_time
method in the chef_gem
resource:
chef_gem 'chef-vault' do
compile_time false if respond_to?(:compile_time)
end
This appears to get around the problem for most cases. However, if you’re using chef-sugar
, you’ll note that until version 3.0.0, chef-sugar
includes a compile_time
DSL method that gets injected into Chef::Resource
(and Chef::Recipe
). This has been modified to at_compile_time
in chef-sugar
version 3.0.0 to work around Chef’s introduction of a compile_time
method in the chef_gem
resource. The simple thing to do is make sure that your chef-sugar
gem/cookbook are updated to v3.0.1. However if that isn’t an option for some reason, you can use this conditional check:
chef_gem 'chef-vault' do
compile_time true if Chef::Resource::ChefGem.instance_methods(false).include?(:compile_time)
end
Hat tip to Anthony Scalisi, who added this in a pull request for the aws cookbook. The instance_methods
method comes from Ruby’s Module class. Per the documentation:
Returns an array containing the names of the public and protected instance methods in the receiver. For a module, these are the public and protected methods; for a class, they are the instance (not singleton) methods. If the optional parameter is false, the methods of any ancestors are not included.
If we look at this in, e.g., chef-shell
under Chef 12.1.0:
chef:recipe > Chef::Resource::ChefGem.instance_methods(false)
=> [:gem_binary, :compile_time, :after_created]
And in Chef 12.0.3 or 11.18.6:
chef > Chef::Resource::ChefGem.instance_methods(false)
=> [:gem_binary, :after_created]