很喜欢ruby元编程,puppet和chef用到了很多ruby的语言特性,来定义一个新的部署语言。
分享几个在实际项目中用到的场景,能力有限,如果有更优方案,请留言给我:)
rpc接口模板化——使用eval、alias、defind_method
require 'rack/rpc'class Server < Rack::RPC::Server def hello_world "Hello, world!" end rpc 'hello_world' => :hello_worldend
上面是一个rpc server,编写一个函数,调用rpc命令进行注册。
采用define_method、eval、alias方法,可以实现一个判断rpc/目录下的*.rb文件,进行加载和rpc接口注册的功能,实现代码如下:
module RPC require 'rack/rpc' #require rpc/*.rb文件 Dir.glob(File.join(File.dirname(__FILE__), 'rpc', "*.rb")) do |file| require file end class Runner < Rack::RPC::Server #include rpc/*.rb and regsiter rpc call #eg. rpc/god.rb god.hello @@rpc_list = [] Dir.glob(File.join(File.dirname(__FILE__), 'rpc', "*.rb")) do |file| rpc_class = File.basename(file).split('.rb')[0].capitalize rpc_list = [] #加载module下的方法到Runner这个类下面 eval "include Frigga::RPC::#{rpc_class}" #获取声明的RPC接口 eval "rpc_list = Frigga::RPC::#{rpc_class}::RPC_LIST" rpc_list.each do |rpc_name| #alias一个新的rpc方法,叫old_xxxx_xxxx eval "alias :old_#{rpc_class.downcase}_#{rpc_name} :#{rpc_name}" #重新定义rpc方法,添加一行日志打印功能,然后再调用old_xxxx_xxxx rpc方法 define_method "#{rpc_class.downcase}_#{rpc_name}".to_sym do |*arg| Logger.info "[#{request.ip}] called #{rpc_class.downcase}.#{rpc_name} #{arg.join(', ')}" eval "old_#{rpc_class.downcase}_#{rpc_name} *arg" end #注册RPC调用 rpc "#{rpc_class.downcase}.#{rpc_name}" => "#{rpc_class.downcase}_#{rpc_name}".to_sym #添加到全局变量,汇总所有的rpc方法 @@rpc_list << "#{rpc_class.downcase}.#{rpc_name}" end end def help rpc_methods = (['help'] + @@rpc_list.sort).join("/n") end rpc "help" => :help end end #RPC
完成上述功能后,可以非常方便的开发rpc接口,例如下面这个IP地址增、删、查的代码,注册ip.list, ip.add和ip.del方法:
module RPC module Ip #RPC_LIST used for regsiter rpc_call RPC_LIST = %w(list add del) def list $white_lists end def add(ip) if ip =~ /^((25[0-5]|2[0-4]/d|[0-1]?/d/d?)/.){3}(25[0-5]|2[0-4]/d|[0-1]?/d/d?)$/ $white_lists << ip write_to_file return "succ" else return "fail" end end def del(ip) if $white_lists.include?(ip) $white_lists.delete ip write_to_file return "succ" else return "fail" end end def write_to_file File.open(IP_yml, "w") do |f| $white_lists.uniq.each {|i| f << "- #{i}/n"} end end end end
新闻热点
疑难解答