-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5bea5c4
Showing
10 changed files
with
459 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
require 'rubygems' | ||
require 'rake' | ||
|
||
begin | ||
require 'jeweler' | ||
Jeweler::Tasks.new do |gem| | ||
gem.name = "sk-hoth" | ||
gem.summary = %Q{Registry and deployment description abstraction for SOA-Services. Tweaked by SalesKing} | ||
gem.description = <<-DESCRIPTION | ||
Creating a SOA requires a centralized location to define all services within the | ||
SOA. Furthermore you want to know where to deploy those services. | ||
DESCRIPTION | ||
gem.email = "gl@salesking.eu" | ||
gem.homepage = "http://github.com/salesking/king_soa" | ||
gem.authors = ['Georg Leciejewski'] | ||
gem.files = FileList["[A-Z]*.*", "{lib,spec}/**/*"] | ||
|
||
gem.add_dependency "curb" | ||
gem.add_dependency "json" | ||
gem.add_dependency "king_hmac" | ||
|
||
gem.add_development_dependency "rspec" | ||
# gem.add_development_dependency "rack/test" | ||
gem.add_development_dependency "webmock" | ||
end | ||
Jeweler::GemcutterTasks.new | ||
rescue LoadError | ||
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" | ||
end | ||
|
||
require 'spec/rake/spectask' | ||
Spec::Rake::SpecTask.new(:spec) do |spec| | ||
spec.libs << 'lib' << 'spec' | ||
spec.spec_files = FileList['spec/**/*_spec.rb'] | ||
end | ||
|
||
Spec::Rake::SpecTask.new(:rcov) do |spec| | ||
spec.libs << 'lib' << 'spec' | ||
spec.pattern = 'spec/**/*_spec.rb' | ||
spec.rcov = true | ||
end | ||
|
||
task :spec => :check_dependencies | ||
|
||
task :default => :spec | ||
|
||
require 'rake/rdoctask' | ||
Rake::RDocTask.new do |rdoc| | ||
if File.exist?('VERSION') | ||
version = File.read('VERSION') | ||
else | ||
version = "" | ||
end | ||
|
||
rdoc.rdoc_dir = 'rdoc' | ||
rdoc.title = "KingSoa #{version}" | ||
rdoc.rdoc_files.include('README*') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
require 'singleton' | ||
require 'json' | ||
require 'typhoeus' | ||
#require 'king_hmac' | ||
require 'active_support/inflector' | ||
|
||
require 'king_soa/registry' | ||
require 'king_soa/service' | ||
require 'king_soa/rack/middleware' | ||
|
||
# Define available services. | ||
# | ||
# service: | ||
# name: sign_document | ||
# url: "https://msg.salesking.eu" | ||
# hmac: 'key:secret'# | ||
# queue: a-queue-name | ||
# | ||
# | ||
# | ||
# method: | ||
# name: sign_document | ||
# # if given the named resque queue will be used | ||
# queue: signings | ||
# | ||
# method: save_signed_document | ||
# url: "https://www.salesking.eu/soa" | ||
# | ||
# | ||
# after defining your services you can call each of them with | ||
# <tt>Hoth::Services.service_name(params)</tt> | ||
# | ||
# KingSoa.sign_document(counter) | ||
# current_number = Hoth::Services.value_of_counter(counter) | ||
# created_account = Hoth::Services.create_account(account) | ||
# | ||
module KingSoa | ||
|
||
class << self | ||
|
||
def init_from_yaml(loc) | ||
|
||
end | ||
# Locate service by a given name | ||
# ==== Params | ||
# service<String|Symbol>:: the name to lookup | ||
def find(service) | ||
Registry[service] | ||
end | ||
# this is where the services get called | ||
def method_missing(meth, *args, &blk) # :nodoc: | ||
if service = Registry[meth] | ||
service.execute(*args) | ||
else | ||
super | ||
end | ||
end | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
module KingSoa::Rack | ||
class Middleware | ||
|
||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
# Takes incoming soa requests and calls the passed in method with given params | ||
def call(env) | ||
# Hoth::Logger.debug "env: #{env.inspect}" | ||
if env["PATH_INFO"] =~ /^\/soa/ | ||
begin | ||
req = Rack::Request.new(env) | ||
# find service | ||
service = KingSoa.find(req.params["name"]) | ||
# authenticate | ||
authenticated?(service, req.params["auth_key"]) | ||
# execute method with decoded params | ||
result = service.execute(*service.decode( req.params["params"] )) | ||
# encode result | ||
encoded_result = service.encode({"result" => result}) | ||
# and return | ||
[ 200, | ||
{'Content-Type' => 'application/json', | ||
'Content-Length' => "#{encoded_result.length}"}, | ||
[encoded_result] ] | ||
rescue Exception => e | ||
#Hoth::Logger.debug "e: #{e.message}" | ||
if service | ||
encoded_error = service.encode({"error" => e}) | ||
[500, {'Content-Type' => 'application/json', 'Content-Length' => "#{encoded_error.length}"}, [encoded_error]] | ||
else | ||
encoded_error = {"error" => "An error occurred! (#{e.message})"}.to_json | ||
[500, {'Content-Type' => "application/json", 'Content-Length' => "#{encoded_error.length}"}, [encoded_error]] | ||
end | ||
end | ||
else | ||
@app.call(env) | ||
end | ||
end | ||
|
||
def authenticated?(service, key) | ||
raise "Please provide a valid authentication key" unless service.auth_key == key | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module KingSoa | ||
class Registry | ||
include Singleton | ||
|
||
############################################################################ | ||
# Class methods | ||
############################################################################ | ||
|
||
# Get a method by a given name | ||
def self.[](service_name) | ||
instance[service_name] | ||
end | ||
# add a service | ||
def self.<<(service) | ||
instance << service | ||
end | ||
# Return an array of defined services | ||
def self.services | ||
instance.services | ||
end | ||
|
||
############################################################################ | ||
# Instance methods - not accessible => Singleton | ||
############################################################################ | ||
|
||
# returns all available methods | ||
def services | ||
@services ||= [] | ||
end | ||
|
||
# Add a new method onto the stack | ||
def <<(service) | ||
(services || []) << service | ||
end | ||
|
||
# Get a method by a given name | ||
def [](service_name) | ||
name = service_name.to_sym | ||
services.detect {|s| s.name == name } | ||
end | ||
|
||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
module KingSoa | ||
class Service | ||
# endpoint url | ||
attr_accessor :debug, :name, :auth_key, :queue, :response | ||
attr_reader :request | ||
|
||
def initialize(opts) | ||
self.name = opts[:name].to_sym | ||
self.url = opts[:url] if opts[:url] | ||
self.queue = opts[:queue] if opts[:queue] | ||
self.auth_key = opts[:auth_key] if opts[:auth_key] | ||
end | ||
|
||
def call_remote(*args) | ||
set_request_opts(args) | ||
resp_code = @request.perform | ||
case resp_code | ||
when 200 | ||
#Hoth::Loggerequest.debug "response.body: #{response.body}" | ||
return self.decode(@request.response_body)["result"] | ||
else | ||
#Hoth::Loggerequest.debug "response.body: #{response.body}" | ||
return self.decode(@request.response_body)["error"] | ||
end | ||
end | ||
|
||
def execute(*args) | ||
result = local_class ? local_class.send(:execute, *args) : call_remote(*args) | ||
return result | ||
end | ||
|
||
def local_class | ||
@local_class_name ||= "#{self.name.to_s.camelize}" | ||
begin | ||
@local_class_name.constantize | ||
rescue NameError => e # no local implementation | ||
false | ||
end | ||
end | ||
|
||
def request | ||
@request ||= Typhoeus::Easy.new | ||
end | ||
|
||
def set_request_opts(args) | ||
r = request | ||
request.url = url | ||
request.method = :post | ||
request.user_agent = 'KingSoa' | ||
request.follow_location = true | ||
request.timeout = 100 # milliseconds | ||
request.params = params(args) | ||
request.verbose = 1 if debug | ||
|
||
end | ||
|
||
# Url receiving the request | ||
# TODO. if not present try to grab from endpoint | ||
def url | ||
@url | ||
end | ||
def url=(url) | ||
@url = "#{url}/soa" | ||
end | ||
|
||
def encode(string) | ||
string.to_json | ||
end | ||
|
||
def decode(string) | ||
begin | ||
JSON.parse(string) | ||
rescue JSON::ParserError => e | ||
raise e | ||
end | ||
end | ||
|
||
# The params for each soa request consisnt of two values: | ||
# name => the name of the method to call | ||
# params => the parameters for the method | ||
# ==== Parameter | ||
# params<Hash|Array|String>:: will be json encoded | ||
# === Returns | ||
# <Hash{String=>String}>:: params added to the POST body | ||
def params(payload) | ||
{ 'name' => name.to_s, | ||
'params' => encode(payload), | ||
'auth_key'=> auth_key } | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
require File.dirname(__FILE__) + '/../../spec_helper.rb' | ||
|
||
#set :environment, :test | ||
|
||
describe KingSoa::Rack::Middleware do | ||
include Rack::Test::Methods | ||
|
||
before(:each) do | ||
@service = KingSoa::Service.new(:url=>'localhost', :name=>'a_method') | ||
KingSoa::Registry << @service | ||
end | ||
|
||
|
||
def app | ||
dummy_app = lambda { |env| puts "in dummy"; [200, {}, ""] } | ||
KingSoa::Rack::Middleware.new(dummy_app) | ||
end | ||
|
||
it "says hello" do | ||
get '/soa', :name=>'a_method', :params=> "#{{:number=>1}.to_json}" | ||
last_response.should == 'ads'#be_ok | ||
last_response.body.should == 'Hello World' | ||
end | ||
|
||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
require File.dirname(__FILE__) + '/../spec_helper.rb' | ||
|
||
describe KingSoa::Registry do | ||
before(:each) do | ||
|
||
end | ||
|
||
it "should return empty services" do | ||
reg = KingSoa::Registry.new | ||
reg.services.should == [] | ||
end | ||
|
||
it "should add service" do | ||
reg = KingSoa::Registry.new | ||
s = KingSoa::Service.new(:url=>'http://localhost') | ||
reg << s | ||
reg.services.should == [s] | ||
end | ||
|
||
it "should return a service by name" do | ||
reg = KingSoa::Registry.new | ||
s = KingSoa::Service.new(:name=>:save_document, :url=>'http://localhost') | ||
reg << s | ||
reg[:save_document].should == s | ||
end | ||
|
||
|
||
end |
Oops, something went wrong.