在厨师食谱中做一点干燥的最好方法是什么?即只是打破了一些Ruby代码,所以我没有复制粘贴一遍又一遍.
以下情况当然不符合:
NoMethodError: undefined method `connect_root' for Chef::Resource::RubyBlock
我可能在一个食谱中有多个ruby_blocks,因为它们做不同的事情,需要有不同的not_if块来保持幂等幂.
def connect_root(root_password) m = MysqL.new("localhost","root",root_password) begin yield m ensure m.close end end ruby_block "set readonly" do block do connect_root node[:MysqL][:server_root_password] do |connection| command = 'SET GLOBAL read_only = ON' Chef::Log.info "#{command}" connection.query(command) end end not_if do ro = nil connect_root node[:MysqL][:server_root_password] do |connection| connection.query("SELECT @@read_only as ro") {|r| r.each_hash {|h| ro = h['ro'] } } end ro end end
解决方法
正如您已经想到的那样,您无法在食谱中定义功能.为提供图书馆.您应该在食谱中的库文件夹中创建一个文件(例如MysqL_helper.rb),具体如下:
module MysqLHelper def self.connect_root( root_password ) m = MysqL.new("localhost",root_password) begin yield m ensure m.close end end end
它必须是一个模块,而不是一个类.请注意,我们还将其定义为static(using self.method_name).然后,您将能够使用模块名称与方法名称在您的配方中使用本模块中定义的函数:
MysqLHelper.connect_root node[:MysqL][:server_root_password] do |connection| [...] end