Howto install a ruby gem that's a pre-req of a chef recipe

Hi guys,

Wondering if you can help me with a little ordering issue.

I want to create a library with an s3_file resource and provider: https://gist.github.com/470321

That code depends on the aws-s3 ruby gem http://amazon.rubyforge.org

My reading of http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run makes me think the gem won’t be installed until the execution phase but it’ll be ruby required in the compilation phase.

Is there a way to install a ruby gem earlier in the process? Seems like the sort of thing that’d be really useful every once in a while.

Thanks,

Josh

I believe the s3_file cookbook on the community site is now written in
pure ruby (uses OpenSSL to generate the headers), so this is no longer
necessary.

Regardless, the solution is to use the 'chef_gem' resource during
0.10.x (or the chef_gem cookbook for <= 0.10.10*)

chef_gem "aws-s3"

Also, you can manipulate and fire the resource created by the DSL (the
'old way') during compile time:

r = gem_package("aws-s3") { action :nothing }
r.run_action(:install)

Cheers,

--AJ

On 15 August 2012 14:55, Joshua Blatt jblatt@verticloud.com wrote:

Hi guys,

Wondering if you can help me with a little ordering issue.

I want to create a library with an s3_file resource and provider: https://gist.github.com/470321

That code depends on the aws-s3 ruby gem http://amazon.rubyforge.org

My reading of http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run makes me think the gem won't be installed until the execution phase but it'll be ruby required in the compilation phase.

Is there a way to install a ruby gem earlier in the process? Seems like the sort of thing that'd be really useful every once in a while.

Thanks,

Josh

Thanks for the tip

On Aug 14, 2012, at 8:15 PM, AJ Christensen aj@junglist.gen.nz wrote:

I believe the s3_file cookbook on the community site is now written in
pure ruby (uses OpenSSL to generate the headers), so this is no longer
necessary.

Regardless, the solution is to use the 'chef_gem' resource during
0.10.x (or the chef_gem cookbook for <= 0.10.10*)

chef_gem "aws-s3"

Also, you can manipulate and fire the resource created by the DSL (the
'old way') during compile time:

r = gem_package("aws-s3") { action :nothing }
r.run_action(:install)

Cheers,

--AJ

On 15 August 2012 14:55, Joshua Blatt jblatt@verticloud.com wrote:

Hi guys,

Wondering if you can help me with a little ordering issue.

I want to create a library with an s3_file resource and provider: https://gist.github.com/470321

That code depends on the aws-s3 ruby gem http://amazon.rubyforge.org

My reading of http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run makes me think the gem won't be installed until the execution phase but it'll be ruby required in the compilation phase.

Is there a way to install a ruby gem earlier in the process? Seems like the sort of thing that'd be really useful every once in a while.

Thanks,

Josh

After playing with this a bit, I found that chef loads libraries before the recipe is compiled so sometimes you can't use that gem_package resource in time.

I also noticed that the opscode database cookbook has this problem too. The 'added:' lines below addressed the problem for me, but is this a colossal hack? Would love to know if I'm doing something stupid here or depending on internals that may change in the future….

class Chef
class Provider
class Database
class MysqlUser < Chef::Provider::Database::Mysql
include Chef::Mixin::ShellOut

    def load_current_resource

added: gem_package = Chef::Resource::GemPackage.new('mysql')
added: gem_package.action(:nothing)
added: gem_package.run_action(:install)
Gem.clear_paths
require 'mysql'
@current_resource = Chef::Resource::DatabaseUser.new(@new_resource.name)
@current_resource.username(@new_resource.name)
@current_resource
end

Before I added those lines I saw this:

LoadError: no such file to load -- mysql
/opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:55:in require' /opt/chef/embedded/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:55:in require'
/tmp/exec/cookbooks/database/libraries/provider_database_mysql_user.rb:29:in load_current_resource' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource.rb:453:in run_action'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/runner.rb:49:in run_action' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/runner.rb:85:in block (2 levels) in converge'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/runner.rb:85:in each' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/runner.rb:85:in block in converge'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection.rb:94:in block in execute_each_resource' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection/stepable_iterator.rb:116:in call'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection/stepable_iterator.rb:116:in call_iterator_block' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection/stepable_iterator.rb:85:in step'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection/stepable_iterator.rb:104:in iterate' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection/stepable_iterator.rb:55:in each_with_index'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/resource_collection.rb:92:in execute_each_resource' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/runner.rb:80:in converge'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/client.rb:330:in converge' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/client.rb:163:in run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/application/solo.rb:207:in block in run_application' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/application/solo.rb:195:in loop'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/application/solo.rb:195:in run_application' /opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/lib/chef/application.rb:70:in run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-10.12.0/bin/chef-solo:25:in `<top (required)>'

Thanks,

Josh

On Aug 14, 2012, at 8:15 PM, AJ Christensen wrote:

I believe the s3_file cookbook on the community site is now written in
pure ruby (uses OpenSSL to generate the headers), so this is no longer
necessary.

Regardless, the solution is to use the 'chef_gem' resource during
0.10.x (or the chef_gem cookbook for <= 0.10.10*)

chef_gem "aws-s3"

Also, you can manipulate and fire the resource created by the DSL (the
'old way') during compile time:

r = gem_package("aws-s3") { action :nothing }
r.run_action(:install)

Cheers,

--AJ

On 15 August 2012 14:55, Joshua Blatt jblatt@verticloud.com wrote:

Hi guys,

Wondering if you can help me with a little ordering issue.

I want to create a library with an s3_file resource and provider: https://gist.github.com/470321

That code depends on the aws-s3 ruby gem http://amazon.rubyforge.org

My reading of http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run makes me think the gem won't be installed until the execution phase but it'll be ruby required in the compilation phase.

Is there a way to install a ruby gem earlier in the process? Seems like the sort of thing that'd be really useful every once in a while.

Thanks,

Josh

On Thu, Aug 16, 2012 at 7:12 PM, Joshua Blatt jblatt@verticloud.com wrote:

After playing with this a bit, I found that chef loads libraries before the recipe is compiled so sometimes you can't use that gem_package resource in time.

Did you try chef_gem as suggested, nay, strongly recommended?

On Thu, Aug 16, 2012 at 1:12 PM, Joshua Blatt jblatt@verticloud.com wrote:

After playing with this a bit, I found that chef loads libraries before the recipe is compiled so sometimes you can't use that gem_package resource in time.

libraries are evaluated before recipes in the compilation phase [1].
What you need to do is a) use chef_gem and b) move your requires in
your libraries where they aren't evaluated until the recipe is
converged.

library_gem/libraries/check_mysql.rb

module CheckMysql
def check
require 'mysql'

# do something

end
end

EOF

library_gem/recipes/default.rb

class Chef::Recipe
include CheckMysql
end

chef_gem "mysql"

check

EOF

I also noticed that the opscode database cookbook has this problem too. The 'added:' lines below addressed the problem for me, but is this a colossal hack? Would love to know if I'm doing something stupid here or depending on internals that may change in the future….

That is an unnecessary hack.

The mysql gem should (must) be installed with chef_gem (or the old
gem_package.run_action hack) in a recipe before the mysql library is
required in a chef cookbook library.

The simplest course of action for this part of the discussion is to
look at the database cookbook refactor that was recently completed
[1].

Bryan

[1] chef - [chef] Update on COOK-1441, database, mysql, postgresql cookbooks