how to require my library in chef ruby_block

一笑奈何 提交于 2019-12-18 14:40:24

问题


I'm developing a cookbook to deploy a simple ROR application. I write an app_helper.rb and put it into the libraries directory of my cookbook, here is the content:

module AppHelper

    def self.find_gem
      if File.exists?("/usr/local/rvm/bin/rvm")
        return `/usr/local/rvm/bin/rvm default exec which gem`.chomp
      else
        return "/usr/bin/gem"
      end
    end
  end

In the recipes/default.rb, I mix in the above module into Chef::Recipe class

class Chef::Recipe
  include AppHelper
end

As you know, the find_gem function can be called from anywhere of the recipe.

when I'm trying to use the find_gem function in my ruby_block like this:

ruby_block "find gem" do
   block do
    gem_bin = Chef::Recipe::find_gem
    # or gem_bin = find_gem
  end
end

I got a NoMethodError: undefined method 'find_gem'.

Also try to mix in the module into Chef::Resource::RubyBlock, it doesn't work neither.

class Chef::Resource::RubyBlock
  include AppHelper
end

ruby_block "find gem" do
   block do
    gem_bin = Chef::Resource::RubyBlock::find_gem
    # or gem_bin = find_gem
  end
end

Is there any way to call the function in the module from the ruby_block? Or Is there an variable of chef to location the files in the libraries, so that I can be able to require the module in the ruby_block.

Thanks!


回答1:


Depending on load order, you might be including your module into an anonymous Ruby class instead of what you think.

If you want to use your method in a recipe, do this at the top of your recipe:

include AppHelper

You could alternatively use :send at the end of your library:

Chef::Recipe.send(:include, AppHelper)

This is different because it will raise an exception if Chef::Recipe is not defined (whereas you are creating a new class if it doesn't exist).

That's all you should need to do unless you want to use the helper in not_if and only_if guards. Then you need to include the helper in the resource:

Chef::Resource.send(:include, AppHelper)

Okay, now that I explained all of that, it won't actually help you. The Ruby Block provider simply calls the block - it doesn't instance eval it. So including the helper in the resource doesn't do anything.

So, you'll need to use a singleton object in this instance (it's the only solution I can reliably think of). The way you've defined your method, you can call it directly from the global namespace:

AppHelper.find_gem('...')

So:

ruby_block "find gem" do
  block do
    gem_bin = AppHelper.find_gem('...')
  end
end


来源:https://stackoverflow.com/questions/20835697/how-to-require-my-library-in-chef-ruby-block

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!