chef_gem vs gem_package vs the conundrum

Howdy Chefs!

Today I ran into a bit of a conundrum with the way chef_gem and
gem_package works, and I'm looking for feedback on either filing an
issue or taking a stab at providing a patch, but wanted to see how
others thought this should be implemented.

The issue I ran into (which appears that it'll be resolved in Chef
10.14.0 via CHEF-2848) is that ruby-shadow is required when using the
user resource with the password attribute.

jtimberman seems to have provided a work around for the issue I ran into:

  • chef_gem allows the use of the gem immediately, but requires
    build-essential to be installed, so installation fails due to it running
    prior to convergence
  • gem_package allows build-essential to be installed, but fails due to
    it not being immediately available to the recipe (thereby requiring a
    second run)

In CHEF-2848 he supplies the following work around that seems to work:

gem_package "ruby-shadow"

ruby_block "require shadow library" do
   block do
     Gem.clear_paths  # <-- Necessary to ensure that the new library is 
found
     require 'shadow' # <-- gem is 'ruby-shadow', but library is 'shadow'
   end
end

However, the issue I'm thinking, is that this isn't an issue just for
ruby-shadow. For example, I have a recipe that wants mysql gem
installed, so the same type of issue exists.

I could probably build an LWRP that added some sort of resource like
gem_immediate or gem_awesome, or perhaps a change that added a new
option to the gem_package that would cause it to execute Gem.clear_paths.

I'm curious if others think this is maybe the way gem_package should
"just work", if an option should be added to it, or perhaps a third type
of resource (not my favourite) for backwards compatibility. I suspect
the option added to gem_package could be backward compatible if the
default for the option was disabled.

Thoughts?

--
Leif Madsen
http://www.oreilly.com/catalog/asterisk

chef_gem already does call Gem.clear_paths. You can see the source code
herehttps://github.com/opscode/chef/blob/master/chef/lib/chef/resource/chef_gem.rb;
all it does is subclass gem_package, call .run_action(:install) on the
resource so it runs at compile-time and the clears the gem paths.

If you need build-essential at compile-time as well, you can set
node['build_essential']['compiletime']
to "true" and it the recipe will install those packages at compile-time as
well.

-Matt Moretti

On Thu, Aug 23, 2012 at 3:51 PM, Leif Madsen
leif.madsen@asteriskdocs.orgwrote:

Howdy Chefs!

Today I ran into a bit of a conundrum with the way chef_gem and
gem_package works, and I'm looking for feedback on either filing an issue
or taking a stab at providing a patch, but wanted to see how others thought
this should be implemented.

The issue I ran into (which appears that it'll be resolved in Chef 10.14.0
via CHEF-2848) is that ruby-shadow is required when using the user resource
with the password attribute.

jtimberman seems to have provided a work around for the issue I ran into:

  • chef_gem allows the use of the gem immediately, but requires
    build-essential to be installed, so installation fails due to it running
    prior to convergence
  • gem_package allows build-essential to be installed, but fails due to it
    not being immediately available to the recipe (thereby requiring a second
    run)

In CHEF-2848 he supplies the following work around that seems to work:

gem_package "ruby-shadow"

ruby_block "require shadow library" do
  block do
    Gem.clear_paths  # <-- Necessary to ensure that the new library is
found
    require 'shadow' # <-- gem is 'ruby-shadow', but library is 'shadow'
  end
end

However, the issue I'm thinking, is that this isn't an issue just for
ruby-shadow. For example, I have a recipe that wants mysql gem installed,
so the same type of issue exists.

I could probably build an LWRP that added some sort of resource like
gem_immediate or gem_awesome, or perhaps a change that added a new option
to the gem_package that would cause it to execute Gem.clear_paths.

I'm curious if others think this is maybe the way gem_package should "just
work", if an option should be added to it, or perhaps a third type of
resource (not my favourite) for backwards compatibility. I suspect the
option added to gem_package could be backward compatible if the default for
the option was disabled.

Thoughts?

--
Leif Madsen
http://www.oreilly.com/**catalog/asteriskhttp://www.oreilly.com/catalog/asterisk

On 23/08/12 06:27 PM, Matthew Moretti wrote:

chef_gem already does call Gem.clear_paths. You can see the source code
here
https://github.com/opscode/chef/blob/master/chef/lib/chef/resource/chef_gem.rb;
all it does is subclass gem_package, call .run_action(:install) on the
resource so it runs at compile-time and the clears the gem paths.

If you need build-essential at compile-time as well, you can set
node['build_essential']['compiletime'] to "true" and it the recipe will
install those packages at compile-time as well.

Ya I knew that chef_gem did a Gem.clear_paths, but the requirement of
development libraries was the sticking point there (since if the gem
requires compilation, and you try to install it prior to convergence,
you wouldn't have the build-essential stuff installed yet).

However, you taught me something new. I'll give that a shot and see if
it works!

I'm still under the impression that for usability, it might not be a bad
idea to allow gem_package to install inline and also be allowed to
utilize the gem right away.

Leif.

--
Leif Madsen

On Fri, Aug 24, 2012 at 1:33 PM, Leif Madsen
leif.madsen@asteriskdocs.org wrote:

Ya I knew that chef_gem did a Gem.clear_paths, but the requirement of
development libraries was the sticking point there (since if the gem
requires compilation, and you try to install it prior to convergence, you
wouldn't have the build-essential stuff installed yet).

Depending on what you are doing exactly, a good pattern is to put a
begin…rescue around your require and the code that uses the library.
The goal here is to make the case where you can't load the library
harmless, logging an error and moving on.
For example, if you are writing an LWRP, you could just make it no-op
if the gem can't be loaded.

As long as you have some monitoring system that will alert you to this
problem, this should be failproof.

Andrea