factor-connector-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,15 @@
1
+ # encoding: UTF-8
2
+
3
+ # action definition as defined by DSL
4
+ class ActionDefinition
5
+ attr_accessor :id, :start
6
+
7
+ def initialize
8
+ end
9
+
10
+ def to_hash
11
+ {
12
+ id: @id
13
+ }
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+
3
+ # Listener definition as defined by DSL
4
+ class ListenerDefinition
5
+ attr_accessor :id, :start, :stop, :web_hooks
6
+
7
+ def initialize
8
+ @web_hooks = {}
9
+ end
10
+
11
+ def to_hash
12
+ {
13
+ id: @id
14
+ }
15
+ end
16
+ 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
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ # web hook definition as generated by DSL
4
+ class WebHookDefinition
5
+ attr_accessor :id, :method, :start
6
+
7
+ def to_hash
8
+ {
9
+ id: @id,
10
+ method: @method
11
+ }
12
+ end
13
+ end
data/lib/errors.rb ADDED
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+
3
+ module Factor
4
+ module Connector
5
+ class Error < StandardError
6
+ attr_accessor :state, :exception
7
+
8
+ def initialize(params = {})
9
+ @exception = params[:exception]
10
+ super(params[:message] || '')
11
+ end
12
+ end
13
+ end
14
+ end
@@ -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: []