factor-connector-api 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/builders/action_builder.rb +20 -0
- data/lib/builders/listener_builder.rb +29 -0
- data/lib/builders/service_builder.rb +33 -0
- data/lib/builders/web_hook_builder.rb +34 -0
- data/lib/definitions/action_definition.rb +15 -0
- data/lib/definitions/listener_definition.rb +16 -0
- data/lib/definitions/service_definition.rb +19 -0
- data/lib/definitions/web_hook_definition.rb +13 -0
- data/lib/errors.rb +14 -0
- data/lib/factor-connector-api.rb +24 -0
- data/lib/instances/action_instance.rb +32 -0
- data/lib/instances/instance.rb +84 -0
- data/lib/instances/listener_instance.rb +95 -0
- data/lib/instances/service_instance.rb +81 -0
- data/lib/service_manager.rb +29 -0
- metadata +60 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# DSL for building actions
|
4
|
+
module Factor
|
5
|
+
module Connector
|
6
|
+
class ActionBuilder
|
7
|
+
def initialize(id, &block)
|
8
|
+
@id = id.to_s
|
9
|
+
@start = block
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
ad = ActionDefinition.new
|
14
|
+
ad.id = @id
|
15
|
+
ad.start = @start
|
16
|
+
ad
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# DSL for building listeners
|
4
|
+
module Factor
|
5
|
+
module Connector
|
6
|
+
class ListenerBuilder
|
7
|
+
def initialize(id, &block)
|
8
|
+
@id = id.to_s
|
9
|
+
instance_eval(&block) if block
|
10
|
+
end
|
11
|
+
|
12
|
+
def start(&code)
|
13
|
+
@start = code
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop(&code)
|
17
|
+
@stop = code
|
18
|
+
end
|
19
|
+
|
20
|
+
def build
|
21
|
+
ld = ListenerDefinition.new
|
22
|
+
ld.id = @id
|
23
|
+
ld.start = @start
|
24
|
+
ld.stop = @stop
|
25
|
+
ld
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# DSL for building services
|
4
|
+
module Factor
|
5
|
+
module Connector
|
6
|
+
class ServiceBuilder
|
7
|
+
def initialize(id, &block)
|
8
|
+
@listeners = {}
|
9
|
+
@actions = {}
|
10
|
+
@id = id.to_s
|
11
|
+
instance_eval(&block) if block
|
12
|
+
end
|
13
|
+
|
14
|
+
def listener(id, &block)
|
15
|
+
listener = ListenerBuilder.new(id, &block).build
|
16
|
+
@listeners[listener.id] = listener
|
17
|
+
end
|
18
|
+
|
19
|
+
def action(id, &block)
|
20
|
+
action = ActionBuilder.new(id, &block).build
|
21
|
+
@actions[action.id] = action
|
22
|
+
end
|
23
|
+
|
24
|
+
def build
|
25
|
+
sd = ServiceDefinition.new
|
26
|
+
sd.listeners = @listeners
|
27
|
+
sd.actions = @actions
|
28
|
+
sd.id = @id
|
29
|
+
sd
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# DSL for creating web hooks
|
4
|
+
module Factor
|
5
|
+
module Connector
|
6
|
+
class WebHookBuilder
|
7
|
+
def initialize(vals = {}, &block)
|
8
|
+
@id = vals[:id].to_s
|
9
|
+
@method = vals[:method] || 'POST'
|
10
|
+
instance_eval(&block) if block
|
11
|
+
end
|
12
|
+
|
13
|
+
def id(val)
|
14
|
+
@id = val.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def method(val)
|
18
|
+
@method = val
|
19
|
+
end
|
20
|
+
|
21
|
+
def start(&code)
|
22
|
+
@start = code
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
wd = WebHookDefinition.new
|
27
|
+
wd.id = @id
|
28
|
+
wd.method = @method
|
29
|
+
wd.start = @start
|
30
|
+
wd
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Definition of service as defined by DSL
|
4
|
+
class ServiceDefinition
|
5
|
+
attr_accessor :id, :listeners, :actions
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@listeners = {}
|
9
|
+
@actions = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_hash
|
13
|
+
{
|
14
|
+
id: @id,
|
15
|
+
listeners: @listeners.map { |k, v| v.to_hash },
|
16
|
+
actions: @actions.map { |k, v| v.to_hash },
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
data/lib/errors.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative './service_manager.rb'
|
2
|
+
|
3
|
+
module Factor
|
4
|
+
module Connector
|
5
|
+
@@service_managers={}
|
6
|
+
|
7
|
+
def self.load(filename)
|
8
|
+
service_manager = Factor::Connector::ServiceManager.load(filename)
|
9
|
+
service_id = service_manager.definition.id
|
10
|
+
@@service_managers[service_id] = service_manager
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.service(id, &block)
|
14
|
+
service_manager = Factor::Connector::ServiceManager.new
|
15
|
+
service_manager.service(id,&block)
|
16
|
+
@@service_managers[id] = service_manager
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.get_service_manager(service_id)
|
20
|
+
@@service_managers[service_id]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
require_relative './instance.rb'
|
3
|
+
|
4
|
+
module Factor
|
5
|
+
module Connector
|
6
|
+
class ActionInstance < Factor::Connector::Instance
|
7
|
+
include Celluloid
|
8
|
+
attr_accessor :service_id
|
9
|
+
|
10
|
+
def start(params)
|
11
|
+
begin
|
12
|
+
self.instance_exec params, &@definition.start
|
13
|
+
rescue Factor::Connector::Error => ex
|
14
|
+
respond type:'fail', message:ex.message
|
15
|
+
exception ex.exception,params:params if ex.exception
|
16
|
+
rescue => ex
|
17
|
+
respond type:'fail', message:"Couldn't run action for unexpected reason. We've been informed and looking into it."
|
18
|
+
exception ex,params:params
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def action_callback(params={})
|
23
|
+
respond type:'return', payload:params
|
24
|
+
end
|
25
|
+
|
26
|
+
def fail(message,params={})
|
27
|
+
respond type:'fail', message: message
|
28
|
+
raise Factor::Connector::Error, exception:params[:exception], message:message if !params[:throw]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'addressable/uri'
|
4
|
+
require 'zip/zipfilesystem'
|
5
|
+
require 'rubygems/package'
|
6
|
+
require 'zlib'
|
7
|
+
require 'open-uri'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
require_relative '../errors.rb'
|
11
|
+
|
12
|
+
module Factor
|
13
|
+
module Connector
|
14
|
+
class Instance
|
15
|
+
attr_accessor :definition, :callback, :instance_id
|
16
|
+
|
17
|
+
def initialize(options = {})
|
18
|
+
@definition = options[:definition] if options[:definition]
|
19
|
+
end
|
20
|
+
|
21
|
+
def callback=(block)
|
22
|
+
@callback = block if block
|
23
|
+
end
|
24
|
+
|
25
|
+
def respond(params)
|
26
|
+
@callback.call(params) if @callback
|
27
|
+
end
|
28
|
+
|
29
|
+
def id
|
30
|
+
@definition.id
|
31
|
+
end
|
32
|
+
|
33
|
+
def info(message)
|
34
|
+
log 'info', message
|
35
|
+
end
|
36
|
+
|
37
|
+
def error(message)
|
38
|
+
log 'error', message
|
39
|
+
end
|
40
|
+
|
41
|
+
def warn(message)
|
42
|
+
log 'warn', message
|
43
|
+
end
|
44
|
+
|
45
|
+
def debug(message)
|
46
|
+
log 'debug', message
|
47
|
+
end
|
48
|
+
|
49
|
+
def log(status, message)
|
50
|
+
respond type: 'log', status: status, message: message
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def exception(ex, parameters = {})
|
56
|
+
debug "exception: #{ex.message}"
|
57
|
+
debug 'backtrace:'
|
58
|
+
ex.backtrace.each do |line|
|
59
|
+
debug " #{line}"
|
60
|
+
end
|
61
|
+
debug "parameters: #{parameters}"
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def targz_to_zip(file)
|
67
|
+
stringio = Zip::ZipOutputStream.write_buffer do |zipio|
|
68
|
+
Gem::Package::TarReader.new(Zlib::GzipReader.open(file.path)) do |tar|
|
69
|
+
tar.each do |entry|
|
70
|
+
zipio.put_next_entry entry.full_name
|
71
|
+
zipio.write entry.read
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
stringio.rewind
|
77
|
+
file = File.new(file.path.gsub(/.gz/, '.zip').gsub(/.tar/, ''), 'w+')
|
78
|
+
file.write stringio.read
|
79
|
+
file.rewind
|
80
|
+
file
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require_relative './instance.rb'
|
4
|
+
|
5
|
+
|
6
|
+
module Factor
|
7
|
+
module Connector
|
8
|
+
class ListenerInstance < Factor::Connector::Instance
|
9
|
+
include Celluloid
|
10
|
+
attr_accessor :web_hooks, :service_id
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@web_hooks = {}
|
14
|
+
super(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def start(params)
|
18
|
+
@params = params
|
19
|
+
|
20
|
+
begin
|
21
|
+
instance_exec @params, &@definition.start if @definition && @definition.start
|
22
|
+
respond type: 'return'
|
23
|
+
rescue Factor::Connector::Error => ex
|
24
|
+
error ex.message
|
25
|
+
respond type: 'fail'
|
26
|
+
exception ex.exception, params: @params if ex.exception
|
27
|
+
rescue => ex
|
28
|
+
error "Couldn't start listener for unexpected reason. We've been informed and looking into it."
|
29
|
+
respond type: 'fail'
|
30
|
+
exception ex, params: @params
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop
|
35
|
+
begin
|
36
|
+
instance_exec @params, &@definition.stop if @definition && @definition.stop
|
37
|
+
respond type: 'stopped'
|
38
|
+
rescue Factor::Connector::Error => ex
|
39
|
+
error ex.message
|
40
|
+
respond type: 'fail'
|
41
|
+
exception ex.exception, params: @params if ex.exception
|
42
|
+
rescue ex
|
43
|
+
error "Couldn't stop listener for unexpected reason. We've been informed and looking into it."
|
44
|
+
respond type: 'fail'
|
45
|
+
exception ex, params: @params
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_workflow(params)
|
50
|
+
@callback.call(type: 'start_workflow', payload: params) if @callback
|
51
|
+
end
|
52
|
+
|
53
|
+
def call_web_hook(web_hook_id, hook_params, request, response)
|
54
|
+
web_hook = @web_hooks[web_hook_id]
|
55
|
+
begin
|
56
|
+
self.instance_exec @params, hook_params, request, response, &web_hook.start
|
57
|
+
rescue Factor::Connector::Error => ex
|
58
|
+
error ex.message
|
59
|
+
exception ex.exception, params: hook_params, hook_id: web_hook_id if ex.exception
|
60
|
+
rescue => ex
|
61
|
+
error "Couldn't call webhook for unexpected reason. We've been informed and looking into it."
|
62
|
+
exception ex, params: @params
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def web_hook(vals = {}, &block)
|
67
|
+
web_hook = WebHookBuilder.new(vals, &block).build
|
68
|
+
@web_hooks[web_hook.id] = web_hook
|
69
|
+
hook_url(@service_id, self.id, @instance_id, web_hook.id)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_web_hook(web_hook_id)
|
73
|
+
hook_url(@service_id, self.id, @instance_id, web_hook_id)
|
74
|
+
end
|
75
|
+
|
76
|
+
def fail(message, params = {})
|
77
|
+
raise Factor::Connector::Error, exception: params[:exception], message: message
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def hook_url(service_id, listener_id, instance_id, web_hook_id)
|
83
|
+
scheme = ENV['RACK_ENV'] == 'production' ? 'https' : 'http'
|
84
|
+
host = ENV['CONNECTOR_HOST'] || 'localhost:9294'
|
85
|
+
service_path = "/v0.4/#{service_id}"
|
86
|
+
listener_path = "/listeners/#{listener_id}"
|
87
|
+
instance_path = "/instances/#{instance_id}"
|
88
|
+
hooks_path = "/hooks/#{web_hook_id}"
|
89
|
+
path = service_path + listener_path + instance_path + hooks_path
|
90
|
+
|
91
|
+
"#{scheme}://#{host}#{path}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
|
3
|
+
require 'definitions/action_definition'
|
4
|
+
require 'definitions/listener_definition'
|
5
|
+
require 'definitions/service_definition'
|
6
|
+
require 'definitions/web_hook_definition'
|
7
|
+
|
8
|
+
require 'builders/action_builder'
|
9
|
+
require 'builders/listener_builder'
|
10
|
+
require 'builders/service_builder'
|
11
|
+
require 'builders/web_hook_builder'
|
12
|
+
|
13
|
+
require 'instances/instance'
|
14
|
+
require 'instances/action_instance'
|
15
|
+
require 'instances/listener_instance'
|
16
|
+
|
17
|
+
module Factor
|
18
|
+
module Connector
|
19
|
+
class ServiceInstance < Factor::Connector::Instance
|
20
|
+
attr_accessor :definition, :step_data, :callback, :listener_instances, :action_instances
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
@listener_instances = {}
|
24
|
+
@action_instances = {}
|
25
|
+
@instance_id = SecureRandom.hex
|
26
|
+
super(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def call_hook(listener_id,hook_id,data,request,response)
|
30
|
+
listener_instance = @listener_instances[listener_id]
|
31
|
+
listener_instance.async.call_web_hook(hook_id,data,request,response)
|
32
|
+
end
|
33
|
+
|
34
|
+
def call_action(action_id,params)
|
35
|
+
action_instance = ActionInstance.new
|
36
|
+
action_instance.service_id = self.id
|
37
|
+
action_instance.instance_id = @instance_id
|
38
|
+
action_instance.definition = @definition.actions[action_id]
|
39
|
+
action_instance.callback = @callback
|
40
|
+
action_instances[action_id] = action_instance
|
41
|
+
action_instance.async.start(params)
|
42
|
+
end
|
43
|
+
|
44
|
+
def start_listener(listener_id,params)
|
45
|
+
listener_instance = ListenerInstance.new
|
46
|
+
listener_instance.service_id = self.id
|
47
|
+
listener_instance.instance_id = @instance_id
|
48
|
+
listener_instance.definition = @definition.listeners[listener_id]
|
49
|
+
listener_instance.callback = @callback
|
50
|
+
@listener_instances[listener_id]=listener_instance
|
51
|
+
listener_instance.async.start(params)
|
52
|
+
end
|
53
|
+
|
54
|
+
def stop_listener(listener_id)
|
55
|
+
if !@listener_instances[listener_id]
|
56
|
+
warn "Listener isn't running, no need to stop"
|
57
|
+
respond type:'stopped'
|
58
|
+
else
|
59
|
+
@listener_instances[listener_id].stop
|
60
|
+
@listener_instances[listener_id].terminate
|
61
|
+
@listener_instances.delete listener_id
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def stop_action(action_id)
|
66
|
+
if @action_instances[action_id]
|
67
|
+
@action_instances[action_id].terminate
|
68
|
+
@action_instances.delete action_id
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_action?(action_id)
|
73
|
+
@definition.actions.include?(action_id)
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_listener?(listener_id)
|
77
|
+
@definition.listeners.include?(listener_id)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
Dir.glob('./lib/definitions/*.rb') { |p| require p }
|
4
|
+
Dir.glob('./lib/builders/*.rb') { |p| require p }
|
5
|
+
require_relative './instances/service_instance.rb'
|
6
|
+
# require 'instances/service_instance'
|
7
|
+
|
8
|
+
module Factor
|
9
|
+
module Connector
|
10
|
+
class ServiceManager
|
11
|
+
attr_accessor :definition
|
12
|
+
|
13
|
+
def service(id, &block)
|
14
|
+
@definition = Factor::Connector::ServiceBuilder.new(id, &block).build
|
15
|
+
end
|
16
|
+
|
17
|
+
def instance
|
18
|
+
instance = Factor::Connector::ServiceInstance.new(definition: @definition)
|
19
|
+
instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.load(filename)
|
23
|
+
dsl = new
|
24
|
+
dsl.instance_eval(File.read(filename))
|
25
|
+
dsl
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factor-connector-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Maciej Skierkowski
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-09-30 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Timer Factor.io Connector
|
15
|
+
email:
|
16
|
+
- maciej@factor.io
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- ./lib/builders/action_builder.rb
|
22
|
+
- ./lib/builders/listener_builder.rb
|
23
|
+
- ./lib/builders/service_builder.rb
|
24
|
+
- ./lib/builders/web_hook_builder.rb
|
25
|
+
- ./lib/definitions/action_definition.rb
|
26
|
+
- ./lib/definitions/listener_definition.rb
|
27
|
+
- ./lib/definitions/service_definition.rb
|
28
|
+
- ./lib/definitions/web_hook_definition.rb
|
29
|
+
- ./lib/errors.rb
|
30
|
+
- ./lib/factor-connector-api.rb
|
31
|
+
- ./lib/instances/action_instance.rb
|
32
|
+
- ./lib/instances/instance.rb
|
33
|
+
- ./lib/instances/listener_instance.rb
|
34
|
+
- ./lib/instances/service_instance.rb
|
35
|
+
- ./lib/service_manager.rb
|
36
|
+
homepage: https://factor.io
|
37
|
+
licenses: []
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.25
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Timer Factor.io Connector
|
60
|
+
test_files: []
|