How to use library module in Cookbook recipes
Asked Answered
M

2

5

In a cookbook I have a library(client_helper.rb). A module is defined inside it. Module name is Client_helper. Here is the module code.

module Client_helper
# This module contains helper methods

def network_zone
        Chef::Log.debug('network zone called...********')
        Chef::Log.debug("inside-::::"+self.class.to_s)
end    

end
Chef::Recipe.send(:include, Client_helper)

Now I have default recipe. Where I am calling the method network_zone from direct recipe it is working.

But when I am calling the method network_zone inside ruby_block(eg. Client_helper.network_zone) it is not working.

Please find the recipe code.

# Cookbook: client
# Recipe: default

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


  host_network_zone = network_zone # This is working

Log.info("inside-::::"+self.class.to_s)

ruby_block 'parse auto generated templates' do
  block do
    host_network_zone = Client_helper.network_zone #This is not working
    Log.info("inside ruby block-::::"+self.class.to_s)
end
end

My cookbook directory structure-

enter image description here

Please help me.

Marko answered 25/5, 2016 at 10:36 Comment(0)
B
8

Its unnecessary to inject the method into any provider class, and its better to inject it only into the classes that you require:

Chef::Recipe.send(:include, Client_helper)
Chef::Resource::RubyBlock.send(:include, Client_helper)

By injecting methods you are monkeypatching those classes, and that comes with all the risks associated with 'monkeypatching' (a google search will probably be educational).

If you inject your #network_zone helper into the Chef::Provider and Chef::Resource base classes that will overwrite any similarly named method in any core resource or provider, or any cookbook resource or provider. If anyone else uses a method of that name, you'll break their code.

Businessman answered 26/5, 2016 at 22:51 Comment(1)
Perfect and understandable.Marko
M
2

Found the solution!! You need to include module to Chef::Recipe , Chef::Resource and Chef::Provider. So the complete code will be-

# This module contains helper methods
module Client_helper     

def network_zone
        Chef::Log.debug('network zone called...********')
        Chef::Log.debug("inside-::::"+self.class.to_s)
end    

end
Chef::Recipe.send(:include, Client_helper)
Chef::Resource.send(:include, Client_helper)
Chef::Provider.send(:include, Client_helper) 

I hope this helps.

Marko answered 25/5, 2016 at 13:8 Comment(1)
Its better to specifically target the Chef::Resource::RubyBlock class rather than Chef::Resource and Chef::Provider. By doing what you're doing you're injecting methods into every resource and provider in the base O/S, including every future provider that we'll write, plus the entire universe of resources and providers in cookbooks that the user has or will ever use. If we ever use a #network_zone method in any core chef resource or provider, you will overwrite it and break our code. And we won't consider ourselves responsible for that breakage.Businessman

© 2022 - 2024 — McMap. All rights reserved.