root/lib/cyborghood/cyborg/botnet/interface.rb @ 4761cd13
d1e614b5 | Marc Dequènes (Duck) | #--
|
|
# CyborgHood, a distributed system management software.
|
|||
# Copyright (c) 2009-2010 Marc Dequènes (Duck) <Duck@DuckCorp.org>
|
|||
#
|
|||
# This program is free software: you can redistribute it and/or modify
|
|||
# it under the terms of the GNU General Public License as published by
|
|||
# the Free Software Foundation, either version 3 of the License, or
|
|||
# (at your option) any later version.
|
|||
#
|
|||
# This program is distributed in the hope that it will be useful,
|
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
# GNU General Public License for more details.
|
|||
#
|
|||
# You should have received a copy of the GNU General Public License
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#++
|
|||
require 'singleton'
|
|||
7466fc08 | Marc Dequènes (Duck) | require 'ostruct'
|
|
d1e614b5 | Marc Dequènes (Duck) | ||
module CyborgHood
|
|||
7466fc08 | Marc Dequènes (Duck) | module DSL
|
|
class ServerApiNode < BaseDSL
|
|||
4761cd13 | Marc Dequènes (Duck) | attr_reader :bot, :node_name, :parent_node, :store
|
|
8fcaacd6 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | # needed for testing node existence
|
|
reveal :nil?
|
|||
4761cd13 | Marc Dequènes (Duck) | reveal :respond_to?
|
|
476368e8 | Marc Dequènes (Duck) | ||
4761cd13 | Marc Dequènes (Duck) | def initialize(bot, parent_node = nil, ldir = nil, &block)
|
|
7466fc08 | Marc Dequènes (Duck) | @bot = bot
|
|
@parent_node = parent_node
|
|||
4761cd13 | Marc Dequènes (Duck) | @ldir = ldir
|
|
7466fc08 | Marc Dequènes (Duck) | # don't call super because we need defered loading
|
|
4761cd13 | Marc Dequènes (Duck) | ||
@blocks = []
|
|||
add_behavior(&block)
|
|||
@ldir_loaded = false
|
|||
a3483167 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | cleanup
|
|
a3483167 | Marc Dequènes (Duck) | end
|
|
8fcaacd6 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def add_behavior(&block)
|
|
4761cd13 | Marc Dequènes (Duck) | if block_given?
|
|
@blocks << block
|
|||
else
|
|||
return if @ldir_loaded
|
|||
Dir.glob(File.join(self.lpath, '*.rb')) do |file|
|
|||
logger.debug "Interface: loading file '#{file}'"
|
|||
@blocks << File.read(file)
|
|||
end
|
|||
@ldir_loaded = true
|
|||
end
|
|||
8fcaacd6 | Marc Dequènes (Duck) | end
|
|
7466fc08 | Marc Dequènes (Duck) | # string, array (useful for aliases), or regex
|
|
# TODO: name validation
|
|||
4761cd13 | Marc Dequènes (Duck) | def node(match, ldir = nil, &block)
|
|
child_node = self.class.new(@bot, self, ldir, &block)
|
|||
7466fc08 | Marc Dequènes (Duck) | if match.is_a? Array
|
|
match.each{|n| @nodes[n] = child_node}
|
|||
else
|
|||
@nodes[match] = child_node
|
|||
end
|
|||
8fcaacd6 | Marc Dequènes (Duck) | end
|
|
69a12fdb | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def on_request(&cb)
|
|
@request_cb = cb
|
|||
69a12fdb | Marc Dequènes (Duck) | end
|
|
d1e614b5 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def _is_node?(session, node_path)
|
|
node = __send__(:find_node, session, node_path)
|
|||
not node.nil?
|
|||
end
|
|||
69a12fdb | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def _call(session, node_path, args = nil)
|
|
args ||= []
|
|||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "wrong format for arguments") unless args.is_a? Array
|
|||
d1e614b5 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | node = find_node(session, node_path)
|
|
raise CyberError.new(:unrecoverable, 'api/cyborghood', "unknown node") if node.nil?
|
|||
d1e614b5 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | logger.debug "[Server API] Node '#{node_path}' found"
|
|
afdc8d97 | Marc Dequènes (Duck) | node.__send__(:request, session, args)
|
|
7466fc08 | Marc Dequènes (Duck) | end
|
|
23b2305f | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | protected
|
|
23b2305f | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def root?
|
|
@parent_node.nil?
|
|||
end
|
|||
23b2305f | Marc Dequènes (Duck) | ||
4761cd13 | Marc Dequènes (Duck) | def base_lpath
|
|
File.join(Config::LIB_DIR, 'cyborghood-' + @bot.name.downcase, 'interface')
|
|||
end
|
|||
def lpath
|
|||
parent_lpath = @parent_node.nil? ? self.base_lpath : @parent_node.lpath
|
|||
@ldir.nil? ? parent_lpath : File.join(parent_lpath, @ldir)
|
|||
end
|
|||
7466fc08 | Marc Dequènes (Duck) | def load(node_element = '')
|
|
cleanup
|
|||
@node_name = node_element
|
|||
@blocks.each do |bl|
|
|||
4761cd13 | Marc Dequènes (Duck) | if bl.is_a? String
|
|
instance_eval bl
|
|||
else
|
|||
instance_eval &bl
|
|||
end
|
|||
7466fc08 | Marc Dequènes (Duck) | end
|
|
end
|
|||
1c89625f | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def find_node(session, node_path)
|
|
4761cd13 | Marc Dequènes (Duck) | # node_path is a string argument when interface root node is called, but is a list of node elements later on
|
|
7466fc08 | Marc Dequènes (Duck) | if root?
|
|
logger.debug "[Server API] Looking for node '#{node_path}'"
|
|||
node_path = node_path.split("/")
|
|||
# remove empty string before first "/"
|
|||
node_path.shift
|
|||
# initial load
|
|||
load
|
|||
end
|
|||
41802ec1 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | node_element = node_path.shift
|
|
logger.debug "[Server API] Looking for node element '#{node_element}'"
|
|||
if node_element.nil?
|
|||
return self
|
|||
41802ec1 | Marc Dequènes (Duck) | else
|
|
7466fc08 | Marc Dequènes (Duck) | next_node = find_child_node(node_element)
|
|
if next_node
|
|||
next_node.__send__(:load, node_element)
|
|||
return next_node.__send__(:find_node, session, node_path)
|
|||
else
|
|||
return
|
|||
end
|
|||
41802ec1 | Marc Dequènes (Duck) | end
|
|
end
|
|||
7466fc08 | Marc Dequènes (Duck) | def find_child_node(child_node)
|
|
return @nodes[child_node] if @nodes.has_key? child_node
|
|||
@nodes.each_pair do |match, node|
|
|||
found = if match.is_a? String
|
|||
child_node == match
|
|||
elsif match.is_a? Regexp
|
|||
child_node =~ Regexp.new(match)
|
|||
elsif match.is_a? Proc
|
|||
match.call.include? child_node
|
|||
end
|
|||
return node if found
|
|||
end
|
|||
f94d64b1 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | nil
|
|
d1e614b5 | Marc Dequènes (Duck) | end
|
|
7466fc08 | Marc Dequènes (Duck) | class Request
|
|
attr_reader :session, :args, :reply
|
|||
b7f7d214 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def initialize(session, args)
|
|
@session = session
|
|||
@args = args
|
|||
b7f7d214 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | @reply = {
|
|
:results => {},
|
|||
:infos => [],
|
|||
:warnings => [],
|
|||
:errors => []
|
|||
}.to_ostruct
|
|||
b7f7d214 | Marc Dequènes (Duck) | end
|
|
end
|
|||
7466fc08 | Marc Dequènes (Duck) | def request(session, args)
|
|
if @request_cb
|
|||
request = Request.new(session, args)
|
|||
begin
|
|||
@request_cb.call(request)
|
|||
# TODO: full reply needed
|
|||
request.reply.results
|
|||
rescue
|
|||
logger.debug "node request error message: " + $!
|
|||
logger.debug "node request error backtrace: " + $!.backtrace.join("\n")
|
|||
raise CyberError.new(:unrecoverable, 'api/cyborghood', "method call failed: " + $!)
|
|||
b7f7d214 | Marc Dequènes (Duck) | end
|
|
7466fc08 | Marc Dequènes (Duck) | else
|
|
@nodes.keys.collect do |match|
|
|||
if match.is_a? String
|
|||
match
|
|||
elsif match.is_a? Regexp
|
|||
'/' + match.to_s + '/'
|
|||
elsif match.is_a? Proc
|
|||
match.call
|
|||
end
|
|||
end.compact.flatten
|
|||
b7f7d214 | Marc Dequènes (Duck) | end
|
|
end
|
|||
d1e614b5 | Marc Dequènes (Duck) | ||
7466fc08 | Marc Dequènes (Duck) | def cleanup
|
|
@nodes = {}
|
|||
@request_cb = nil
|
|||
4761cd13 | Marc Dequènes (Duck) | ||
# data memorized during walk in the node tree
|
|||
if root?
|
|||
@store = OpenStruct.new
|
|||
else
|
|||
@store = @parent_node.store
|
|||
end
|
|||
a3483167 | Marc Dequènes (Duck) | end
|
|
end
|
|||
d1e614b5 | Marc Dequènes (Duck) | end
|
|
end
|