4

AWS Opsworks: Chef version 11.10, Berkshelf version 3.2.0.

I can't figure out how to use a helper library from cookbook A in a ruby_block in cookbook B.

I found a post discussing how to include a method in a ruby_block and another discussing how to share libraries across cookbooks but I can't get both working at the same time.

cookbookA/libraries/helpers.rb

module libraryA
    module Helpers
        def log(output)
            Chef::Log.info("#{cookbook_name}:#{recipe_name}: #output}")
        end
    end
end

cookbookB/metadata.rb

depends 'cookbookA'

The following setup.rb works.

cookbookB/recipes/setup.rb

 ::Chef::Recipe.send(:include, libraryA::Helpers)
 log("this is a log")

However, when I use the log function in a ruby block, it fails. The following setup.rb does not work:

cookbookB/recipes/setup.rb

 ::Chef::Recipe.send(:include, libraryA::Helpers)
 ruby_block "logging-function" do
      block do
           log("this is a log")
      end
 end

P.S.: I have also tried using ::Chef::Resource.send(:include, libraryA::Helpers)

Updated code block:

::Chef::Recipe.send(:include, libraryA::Helpers) 
ruby_block "logging-test" do 
    block do 
        ::Chef::Recipe.send(:include, libraryA::Helpers)    
        ::libraryA::Helpers.ttlog("message") 
    end 
end

Received error: NoMethodError - undefined method ttlog for libraryA::Helpers:Module

Updated helpers

cookbookA/libraries/helpers.rb

def log(output)
    Chef::Log.info("#{cookbook_name}:#{recipe_name}: #output}")
end

P.S: Removed the modules structure

Community
  • 1
  • 1
ksm
  • 41
  • 1
  • 5
  • According to Sethvargo's answer on the first link you provided library's are loaded in the global namespace so you can use a fully qualified access to your method: `block { libraryA::Helpers.log("message") }` should do. (Side note: I did use brackets instead of do end as I wrote it as a one liner, but that does not change the behavior) – Tensibai Aug 24 '15 at 07:45
  • Hi. Thanks for the reply. I have tried using the fully qualified access. But I am receiving an error "undefined method `log' ". – ksm Aug 31 '15 at 15:26
  • May you update the question with the full error output ? (does it show fully qualified method or not ?) I would also recommend using another name to avoid conflict with chef `log` resource – Tensibai Aug 31 '15 at 15:28
  • @Tensibai Hi. Sorry for the delayed response. The error does not show fully qualified method. It shows (ttlog is method name - changed it from log) `NoMethodError ------------- undefined method ttlog for Chef::Resource::RubyBlock` – ksm Sep 09 '15 at 19:59
  • Are youvusing a full method inside the ruby block ? An update of the question could be great to see where the error comes from – Tensibai Sep 09 '15 at 20:01
  • This is how I am using it (included the helpers inside and out of the block just to be sure. Also the error is NoMethodError------------- undefined method ttlog for libraryA::Helpers:Module): `::Chef::Recipe.send(:include, libraryA::Helpers) ruby_block "logging-test" do block do ::Chef::Recipe.send(:include, libraryA::Helpers) ::libraryA::Helpers.ttlog("hey there") end end` – ksm Sep 09 '15 at 20:18
  • Thank you everyone for the help. I have been able to resolve the issue. I have changed the format of the helpers.rb to be pure definitions without wrapping them into modules. This way, I can access the functions both inside and outside of a resource. The new code looks as follows: * def ttlog(output) Chef::Log.info("#{cookbook_name}:#{recipe_name}: #output}") end * – ksm Sep 18 '15 at 18:11
  • **def ttlog(output) Chef::Log.info("#{cookbook_name}:#{recipe_name}: #output}") end** – ksm Sep 18 '15 at 18:17
  • You should add this as an answer and mark it as accepted answer after 1 or 2 days – Tensibai Sep 18 '15 at 19:12
  • Ho. And please [edit] the question to show last step before resolution so it can help others later ;) – Tensibai Sep 18 '15 at 19:14
  • @Tesibai Done !!! :) – ksm Oct 08 '15 at 21:43

1 Answers1

1

I think ruby_block runs in other context, under other object. You can try to include that library into provider, but I can't guarantee it would work.

::Chef::Provider::RubyBlock.send(:include, libraryA::Helpers)

ps. Resource does have definition and list of parameters, but code is executed from Provider.

Oleksandr Slynko
  • 787
  • 6
  • 11
  • Hi. Thanks for the reply. I do remember reading about providers. However, currently our code is not provider based. We are however planning to move to provider soon. I will definitely try this when we do. – ksm Aug 31 '15 at 15:28