maestro_plugin 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +42 -0
- data/LICENSE.txt +22 -0
- data/README.md +63 -0
- data/Rakefile +27 -0
- data/lib/maestro_plugin/logging.rb +21 -0
- data/lib/maestro_plugin/maestro_worker.rb +279 -0
- data/lib/maestro_plugin/version.rb +5 -0
- data/lib/maestro_plugin.rb +8 -0
- data/maestro_plugin.gemspec +30 -0
- data/spec/maestro_worker_spec.rb +142 -0
- data/spec/spec_helper.rb +14 -0
- metadata +151 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use jruby-1.6.8
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
maestro_plugin (0.0.2)
|
5
|
+
json (>= 1.4.6)
|
6
|
+
logging (= 1.8.0)
|
7
|
+
rubyzip (= 0.9.8)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
bouncy-castle-java (1.5.0147)
|
13
|
+
diff-lcs (1.2.1)
|
14
|
+
jruby-openssl (0.8.7)
|
15
|
+
bouncy-castle-java (>= 1.5.0147)
|
16
|
+
json (1.7.7-java)
|
17
|
+
little-plugger (1.1.3)
|
18
|
+
logging (1.8.0)
|
19
|
+
little-plugger (>= 1.1.3)
|
20
|
+
multi_json (>= 1.3.6)
|
21
|
+
multi_json (1.3.6)
|
22
|
+
rake (10.0.4)
|
23
|
+
rspec (2.13.0)
|
24
|
+
rspec-core (~> 2.13.0)
|
25
|
+
rspec-expectations (~> 2.13.0)
|
26
|
+
rspec-mocks (~> 2.13.0)
|
27
|
+
rspec-core (2.13.0)
|
28
|
+
rspec-expectations (2.13.0)
|
29
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
30
|
+
rspec-mocks (2.13.0)
|
31
|
+
rubyzip (0.9.8)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
java
|
35
|
+
ruby
|
36
|
+
|
37
|
+
DEPENDENCIES
|
38
|
+
bundler (~> 1.3)
|
39
|
+
jruby-openssl
|
40
|
+
maestro_plugin!
|
41
|
+
rake
|
42
|
+
rspec (~> 2.13.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Etienne Pelletier
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
maestro_plugin Gem
|
2
|
+
===================
|
3
|
+
|
4
|
+
Library For Creating Ruby Based Maestro Plugins
|
5
|
+
=======
|
6
|
+
|
7
|
+
# Introduction
|
8
|
+
|
9
|
+
Maestro 4 provides support for plugins written in Java and Ruby. They are both permitted to have dependent libraries.
|
10
|
+
Ruby based plugins provide the worker source file (.rb) and any dependencies (.gem) are loaded using the Rubygems (gem)
|
11
|
+
executable. Both plugin types provide a manifest file (manifest.json) that details the contents and attributes of the
|
12
|
+
plugin.
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'maestro_plugin'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install maestro_plugin
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Directory Layout
|
31
|
+
|
32
|
+
Your plugin source directory should contain the following subdirectories:
|
33
|
+
|
34
|
+
* src - contains the plugin source code.
|
35
|
+
* spec - contains the plugin RSpec testing code.
|
36
|
+
* images - contains the plugin images displayed in the task list and composition bar.
|
37
|
+
|
38
|
+
### The Manifest
|
39
|
+
|
40
|
+
TBD
|
41
|
+
|
42
|
+
### The Worker Class
|
43
|
+
|
44
|
+
The logic for your plugin is implemented by a worker class. This class should extend the Maestro::MaestroWorker class.
|
45
|
+
Set it in the *class* parameter of your manifest. The command parameter for each task defined in the manifest must have
|
46
|
+
a matching method in your worker.
|
47
|
+
|
48
|
+
### Unit Testing Your Plugin
|
49
|
+
|
50
|
+
You can use RSpec to perform unit testing. If your plugin invokes any of the utility methods in the MaestroWorker class,
|
51
|
+
you should make sure to set the MaestroWorker class to "mock" mode so that it doesn't attempt to post messages on the
|
52
|
+
response queue. You can do this by calling the *Maestro::MaestroWorker.mock!* method.
|
53
|
+
|
54
|
+
### Packaging Your Plugin
|
55
|
+
|
56
|
+
You must package your plugin into a zip file. It must contain the following files and directory:
|
57
|
+
|
58
|
+
* src - the source directory
|
59
|
+
* images - the directory containing the image displayed on the Maestro UI in the task list and composition bar.
|
60
|
+
* vendor - the directory containing all the gem dependencies.
|
61
|
+
* manifest.json - the manifest.
|
62
|
+
* README.md - the README file (optional)
|
63
|
+
* LICENSE - the license file (optional)
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
require File.expand_path('../lib/maestro_plugin/version', __FILE__)
|
6
|
+
|
7
|
+
CLEAN.include([ 'pkg', '*.gem'])
|
8
|
+
|
9
|
+
task :default => [:build]
|
10
|
+
|
11
|
+
desc 'Run specs'
|
12
|
+
RSpec::Core::RakeTask.new do |t|
|
13
|
+
t.pattern = './spec/**/*_spec.rb' # don't need this, it's default.
|
14
|
+
t.rspec_opts = '--fail-fast --format p --color'
|
15
|
+
# Put spec opts in a file named .rspec in root
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Get dependencies with Bundler'
|
19
|
+
task :bundle do
|
20
|
+
system 'bundle install'
|
21
|
+
end
|
22
|
+
|
23
|
+
task :build => [:clean, :bundle, :spec]
|
24
|
+
task :build do
|
25
|
+
system 'gem build maestro_plugin.gemspec'
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Copyright 2013© MaestroDev. All rights reserved.
|
2
|
+
require 'logging'
|
3
|
+
|
4
|
+
module Maestro
|
5
|
+
|
6
|
+
unless Maestro.const_defined?('Logging')
|
7
|
+
|
8
|
+
module Logging
|
9
|
+
|
10
|
+
def log
|
11
|
+
::Logging::Logger.new(STDOUT)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
include Maestro::Logging unless Maestro.include?(Maestro::Logging)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Maestro
|
4
|
+
|
5
|
+
|
6
|
+
# Helper Class for Maestro Plugins written in Ruby. The lifecycle of the plugin
|
7
|
+
# starts with a call to the main entry point perform called by the Maestro agent, all the
|
8
|
+
# other methods are helpers that can be used to deal with parsing, errors, etc. The lifecycle ends with a call to
|
9
|
+
# run_callbacks which can be customized by specifying an on_complete_handler_method, or on_complete_handler_block.
|
10
|
+
#
|
11
|
+
class MaestroWorker
|
12
|
+
|
13
|
+
# Workitem constants
|
14
|
+
CONTEXT_OUTPUTS_META = '__context_outputs__'
|
15
|
+
OUTPUT_META = '__output__'
|
16
|
+
PREVIOUS_CONTEXT_OUTPUTS_META = '__previous_context_outputs__'
|
17
|
+
STREAMING_META = '__streaming__'
|
18
|
+
ERROR_META = '__error__'
|
19
|
+
WAITING_META = '__waiting__'
|
20
|
+
CANCEL_META = '__cancel__'
|
21
|
+
NOT_NEEDED = '__not_needed__'
|
22
|
+
LINKS_META = '__links__'
|
23
|
+
PERSIST_META = '__persist__'
|
24
|
+
MODEL_META = '__model__'
|
25
|
+
RECORD_ID_META = '__record_id__'
|
26
|
+
RECORD_FIELD_META = '__record_field__'
|
27
|
+
RECORD_VALUE_META = '__record_value__'
|
28
|
+
RECORD_FIELDS_META = '__record_fields__'
|
29
|
+
RECORD_VALUES_META = '__record_values__'
|
30
|
+
FILTER_META = '__filter__'
|
31
|
+
NAME_META = '__name__'
|
32
|
+
CREATE_META = '__create__'
|
33
|
+
UPDATE_META = '__update__'
|
34
|
+
DELETE_META = '__delete__'
|
35
|
+
|
36
|
+
class << self
|
37
|
+
|
38
|
+
attr_reader :exception_handler_method, :exception_handler_block, :on_complete_handler_method, :on_complete_handler_block
|
39
|
+
|
40
|
+
# Register a callback method or block that gets called when an exception
|
41
|
+
# occurs during the processing of an action. +handler+ can be a symbol or
|
42
|
+
# string with a method name, or a block. Both will get the exception as
|
43
|
+
# the first parameter, and the block handler will receive the participant
|
44
|
+
# instance as the second parameter
|
45
|
+
def on_exception(handler = nil, &block)
|
46
|
+
@exception_handler_method = handler
|
47
|
+
@exception_handler_block = block
|
48
|
+
end
|
49
|
+
|
50
|
+
# Register a callback method or block that gets called when the action
|
51
|
+
# was successfully completed. Block callbacks get the workitem as
|
52
|
+
# parameter.
|
53
|
+
def on_complete(handler = nil, &block)
|
54
|
+
@on_complete_handler_method = handler
|
55
|
+
@on_complete_handler_block = block
|
56
|
+
end
|
57
|
+
|
58
|
+
# Call this to mock calls to outbound systems.
|
59
|
+
def mock!
|
60
|
+
@mock = true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Call this to unmock calls to outbound systems.
|
64
|
+
def unmock!
|
65
|
+
@mock = false
|
66
|
+
end
|
67
|
+
|
68
|
+
def mock?
|
69
|
+
@mock
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
attr_accessor :workitem, :action
|
75
|
+
|
76
|
+
def is_json?(string)
|
77
|
+
JSON.parse string
|
78
|
+
true
|
79
|
+
rescue Exception
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
alias :is_json :is_json?
|
84
|
+
|
85
|
+
# Perform the specified action with the provided workitem. Invokes the method specified by the action parameter.
|
86
|
+
#
|
87
|
+
def perform(action, workitem)
|
88
|
+
@action, @workitem = action, workitem
|
89
|
+
send(action)
|
90
|
+
run_callbacks
|
91
|
+
rescue => e
|
92
|
+
handle_exception(e)
|
93
|
+
end
|
94
|
+
|
95
|
+
def handle_exception(e)
|
96
|
+
raise e if self.class.exception_handler_method.nil? && self.class.exception_handler_block.nil?
|
97
|
+
|
98
|
+
if self.class.exception_handler_method
|
99
|
+
send(self.class.exception_handler_method, e)
|
100
|
+
else
|
101
|
+
self.class.exception_handler_block.call(e, self)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def run_callbacks
|
106
|
+
return if self.class.on_complete_handler_block.nil? && self.class.on_complete_handler_method.nil?
|
107
|
+
|
108
|
+
if self.class.on_complete_handler_method
|
109
|
+
send(self.class.on_complete_handler_method)
|
110
|
+
else
|
111
|
+
self.class.on_complete_handler_block.call(workitem)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Set a value in the context output
|
116
|
+
def save_output_value(name, value)
|
117
|
+
set_field(CONTEXT_OUTPUTS_META, {}) if get_field(CONTEXT_OUTPUTS_META).nil?
|
118
|
+
get_field(CONTEXT_OUTPUTS_META)[name] = value
|
119
|
+
end
|
120
|
+
|
121
|
+
# Read a value from the context output
|
122
|
+
def read_output_value(name)
|
123
|
+
if get_field(PREVIOUS_CONTEXT_OUTPUTS_META).nil?
|
124
|
+
set_field(CONTEXT_OUTPUTS_META, {}) if get_field(CONTEXT_OUTPUTS_META).nil?
|
125
|
+
get_field(CONTEXT_OUTPUTS_META)[name]
|
126
|
+
else
|
127
|
+
get_field(PREVIOUS_CONTEXT_OUTPUTS_META)[name]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Sends the specified ouput string to the server for persistence
|
132
|
+
def write_output(output)
|
133
|
+
return if output.gsub(/\n/, '').empty?
|
134
|
+
|
135
|
+
workitem[OUTPUT_META] = output
|
136
|
+
workitem[STREAMING_META] = true
|
137
|
+
send_workitem_message
|
138
|
+
rescue Exception => e
|
139
|
+
Maestro.log.warn "Unable To Write Output To Server #{e.class} #{e}: #{e.backtrace.join("\n")}"
|
140
|
+
ensure
|
141
|
+
workitem.delete(STREAMING_META)
|
142
|
+
end
|
143
|
+
|
144
|
+
def error
|
145
|
+
fields[ERROR_META]
|
146
|
+
end
|
147
|
+
|
148
|
+
def error?
|
149
|
+
!(error.nil? or error.empty?)
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_error(error)
|
153
|
+
set_field(ERROR_META, error)
|
154
|
+
end
|
155
|
+
|
156
|
+
#control
|
157
|
+
|
158
|
+
# Sets the current task as waiting
|
159
|
+
def set_waiting(should_wait)
|
160
|
+
workitem[WAITING_META] = should_wait
|
161
|
+
send_workitem_message
|
162
|
+
rescue Exception => e
|
163
|
+
Maestro.log.warn "Failed To Send Waiting Message To Server #{e.class} #{e}: #{e.backtrace.join("\n")}"
|
164
|
+
ensure
|
165
|
+
workitem.delete(WAITING_META) unless should_wait
|
166
|
+
end
|
167
|
+
|
168
|
+
# Send the "cancel" message to the server
|
169
|
+
def cancel
|
170
|
+
workitem[CANCEL_META] = true
|
171
|
+
send_workitem_message
|
172
|
+
rescue Exception => e
|
173
|
+
Maestro.log.warn "Failed To Send Cancel Message To Server #{e.class} #{e}: #{e.backtrace.join("\n")}"
|
174
|
+
ensure
|
175
|
+
workitem.delete(CANCEL_META)
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
# Send the "not needed" message to the server.
|
180
|
+
def not_needed
|
181
|
+
workitem[NOT_NEEDED] = true
|
182
|
+
send_workitem_message
|
183
|
+
rescue Exception => e
|
184
|
+
Maestro.log.warn "Failed To Send Not Needed Message To Server #{e.class} #{e}: #{e.backtrace.join("\n")}"
|
185
|
+
ensure
|
186
|
+
workitem.delete(NOT_NEEDED)
|
187
|
+
end
|
188
|
+
|
189
|
+
# end control
|
190
|
+
|
191
|
+
# persistence
|
192
|
+
def update_fields_in_record(model, name_or_id, record_field, record_value)
|
193
|
+
workitem[PERSIST_META] = true
|
194
|
+
workitem[UPDATE_META] = true
|
195
|
+
workitem[MODEL_META] = model
|
196
|
+
workitem[RECORD_ID_META] = name_or_id.to_s
|
197
|
+
workitem[RECORD_FIELD_META] = record_field
|
198
|
+
workitem[RECORD_VALUE_META] = record_value
|
199
|
+
|
200
|
+
send_workitem_message
|
201
|
+
|
202
|
+
workitem.delete(PERSIST_META)
|
203
|
+
workitem.delete(UPDATE_META)
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
def create_record_with_fields(model, record_fields, record_values = nil)
|
208
|
+
workitem[PERSIST_META] = true
|
209
|
+
workitem[CREATE_META] = true
|
210
|
+
workitem[MODEL_META] = model
|
211
|
+
unless record_fields.is_a? Hash
|
212
|
+
Maestro.log.warn 'deprecation: create_record_with_fields should be called with a Hash'
|
213
|
+
record_fields = record_fields.join(',') if record_fields.respond_to? 'join'
|
214
|
+
record_values = record_values.join(',') if record_values.respond_to? 'join'
|
215
|
+
end
|
216
|
+
|
217
|
+
workitem[RECORD_FIELDS_META] = record_fields
|
218
|
+
workitem[RECORD_VALUES_META] = record_values
|
219
|
+
send_workitem_message
|
220
|
+
|
221
|
+
workitem.delete(PERSIST_META)
|
222
|
+
workitem.delete(CREATE_META)
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
def delete_record(model, filter)
|
227
|
+
workitem[PERSIST_META] = true
|
228
|
+
workitem[DELETE_META] = true
|
229
|
+
workitem[MODEL_META] = model
|
230
|
+
|
231
|
+
if filter.is_a? Hash
|
232
|
+
workitem[FILTER_META] = filter
|
233
|
+
else
|
234
|
+
Maestro.log.warn 'deprecation: delete_record should be called with a Hash'
|
235
|
+
workitem[NAME_META] = filter.to_s
|
236
|
+
end
|
237
|
+
|
238
|
+
send_workitem_message
|
239
|
+
|
240
|
+
workitem.delete(PERSIST_META)
|
241
|
+
workitem.delete(DELETE_META)
|
242
|
+
end
|
243
|
+
|
244
|
+
# end persistence
|
245
|
+
|
246
|
+
def get_field(field)
|
247
|
+
fields[field]
|
248
|
+
end
|
249
|
+
|
250
|
+
def fields
|
251
|
+
workitem['fields']
|
252
|
+
end
|
253
|
+
|
254
|
+
alias_method :get_fields, :fields
|
255
|
+
|
256
|
+
|
257
|
+
def set_field(field, value)
|
258
|
+
fields[field] = value
|
259
|
+
end
|
260
|
+
|
261
|
+
# Adds a link to be displayed in the Maestro UI.
|
262
|
+
def add_link(name, url)
|
263
|
+
set_field(LINKS_META, []) if fields[LINKS_META].nil?
|
264
|
+
fields[LINKS_META] << {'name' => name, 'url' => url}
|
265
|
+
end
|
266
|
+
|
267
|
+
private
|
268
|
+
|
269
|
+
def send_workitem_message
|
270
|
+
ruote_participants.send_workitem_message(workitem) unless MaestroWorker.mock?
|
271
|
+
end
|
272
|
+
|
273
|
+
def ruote_participants
|
274
|
+
Maestro::RuoteParticipants.instance
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
end
|
279
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'maestro_plugin/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'maestro_plugin'
|
8
|
+
spec.version = Maestro::Plugin::VERSION
|
9
|
+
spec.authors = ['Etienne Pelletier']
|
10
|
+
spec.email = ['epelletier@maestrodev.com']
|
11
|
+
spec.description = %q{A ruby library to help with the creation of Maestro plugins}
|
12
|
+
spec.summary = %q{Maestro ruby plugin}
|
13
|
+
spec.homepage = 'https://github.com/maestrodev/maestro-ruby-plugin'
|
14
|
+
spec.license = 'Apache 2.0'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'logging', '1.8.0'
|
22
|
+
spec.add_dependency 'rubyzip', '0.9.8'
|
23
|
+
spec.add_dependency 'json', '>= 1.4.6'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'jruby-openssl'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 2.13.0'
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Maestro::MaestroWorker do
|
4
|
+
|
5
|
+
describe 'Mock' do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
Maestro::MaestroWorker.mock!
|
9
|
+
end
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
Maestro::MaestroWorker.unmock!
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should mock send_workitem_message calls' do
|
16
|
+
@workitem = {'fields' => {}}
|
17
|
+
|
18
|
+
@worker = Maestro::MaestroWorker.new
|
19
|
+
@worker.stub(:workitem => @workitem)
|
20
|
+
@worker.should_not_receive(:ruote_participant)
|
21
|
+
|
22
|
+
@worker.write_output('Some test string')
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'Messaging' do
|
29
|
+
before :each do
|
30
|
+
@workitem = {'fields' => {}}
|
31
|
+
@ruote_participants = double("ruote_participants")
|
32
|
+
@ruote_participants.should_receive(:send_workitem_message).with(@workitem)
|
33
|
+
|
34
|
+
@worker = Maestro::MaestroWorker.new
|
35
|
+
@worker.stub(:ruote_participants => @ruote_participants)
|
36
|
+
@worker.stub(:workitem => @workitem)
|
37
|
+
@worker.should_receive(:send_workitem_message).at_least(:once).and_call_original
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should send a write_output message' do
|
42
|
+
@worker.write_output('Some Silly String')
|
43
|
+
@worker.workitem['__output__'].should eql('Some Silly String')
|
44
|
+
@worker.workitem['__streaming__'].should be_nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should send a not needed message' do
|
48
|
+
@worker.not_needed
|
49
|
+
@worker.workitem['__not_needed__'].should be_nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should send a cancel message' do
|
53
|
+
@worker.cancel
|
54
|
+
@worker.workitem['__cancel__'].should be_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should send a set_waiting message' do
|
58
|
+
@ruote_participants.should_receive(:send_workitem_message).with(@workitem)
|
59
|
+
@worker.set_waiting(true)
|
60
|
+
@worker.workitem['__waiting__'].should be_true
|
61
|
+
|
62
|
+
@worker.set_waiting(false)
|
63
|
+
@worker.workitem['__waiting__'].should be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should send a create record message' do
|
67
|
+
@worker.create_record_with_fields('cars', ['manu', 'date', 'name'], ['ferrari', '1964', '250 GTO'])
|
68
|
+
|
69
|
+
@worker.workitem['__model__'].should eql('cars')
|
70
|
+
@worker.workitem['__record_fields__'].should eql('manu,date,name')
|
71
|
+
@worker.workitem['__record_values__'].should eql('ferrari,1964,250 GTO')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should send a create record message with a hash' do
|
75
|
+
fields = {'manu' => 'ferrari', 'date' => '1964', 'name' => 'GTO'}
|
76
|
+
@worker.create_record_with_fields('cars', fields)
|
77
|
+
@worker.workitem['__model__'].should eql('cars')
|
78
|
+
@worker.workitem['__record_fields__'].should eql(fields)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should send an update record-field message' do
|
82
|
+
@worker.update_fields_in_record('animal', 'donkey', 'name', 'e-or')
|
83
|
+
|
84
|
+
@worker.workitem['__model__'].should eql('animal')
|
85
|
+
@worker.workitem['__record_id__'].should eql('donkey')
|
86
|
+
@worker.workitem['__record_field__'].should eql('name')
|
87
|
+
@worker.workitem['__record_value__'].should eql('e-or')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should send a delete record message' do
|
91
|
+
@worker.delete_record('animal', 1)
|
92
|
+
@worker.workitem['__model__'].should eql('animal')
|
93
|
+
@worker.workitem['__name__'].should eql('1')
|
94
|
+
@worker.workitem['__filter__'].should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should send a delete record message with a filter' do
|
98
|
+
filter = {'type' => 1}
|
99
|
+
@worker.delete_record('animal', filter)
|
100
|
+
@worker.workitem['__model__'].should eql('animal')
|
101
|
+
@worker.workitem['__filter__'].should eql(filter)
|
102
|
+
@worker.workitem['__name__'].should be_nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'Field handling' do
|
107
|
+
before :each do
|
108
|
+
@worker = Maestro::MaestroWorker.new
|
109
|
+
@worker.workitem = {'fields' => {}}
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should set and get errors' do
|
113
|
+
@worker.workitem['__error__'].should be_nil
|
114
|
+
@worker.error?.should be_false
|
115
|
+
@worker.set_error 'myerror'
|
116
|
+
@worker.error?.should be_true
|
117
|
+
@worker.workitem['fields']['__error__'].should eq('myerror')
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should set fields' do
|
121
|
+
@worker.workitem = {'fields' => {'a' => 'a'}}
|
122
|
+
@worker.fields['a'].should eq('a')
|
123
|
+
@worker.fields['b'] = 'b'
|
124
|
+
@worker.fields['b'].should eq('b')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'Helpers' do
|
129
|
+
before :each do
|
130
|
+
@worker = Maestro::MaestroWorker.new
|
131
|
+
@worker.workitem = {'fields' => {}}
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should validate JSON data contained in strings' do
|
135
|
+
@worker.is_json?('{"key": "a string"}').should be_true
|
136
|
+
@worker.is_json?('a string').should be_false
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib') unless $LOAD_PATH.include?(File.dirname(__FILE__) + '/../lib')
|
6
|
+
|
7
|
+
require 'maestro_plugin'
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: maestro_plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.2
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Etienne Pelletier
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2013-04-04 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: logging
|
17
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - "="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.8.0
|
23
|
+
requirement: *id001
|
24
|
+
prerelease: false
|
25
|
+
type: :runtime
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rubyzip
|
28
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - "="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.8
|
34
|
+
requirement: *id002
|
35
|
+
prerelease: false
|
36
|
+
type: :runtime
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: json
|
39
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.4.6
|
45
|
+
requirement: *id003
|
46
|
+
prerelease: false
|
47
|
+
type: :runtime
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: bundler
|
50
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "1.3"
|
56
|
+
requirement: *id004
|
57
|
+
prerelease: false
|
58
|
+
type: :development
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rake
|
61
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
requirement: *id005
|
68
|
+
prerelease: false
|
69
|
+
type: :development
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: jruby-openssl
|
72
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
requirement: *id006
|
79
|
+
prerelease: false
|
80
|
+
type: :development
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rspec
|
83
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ~>
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.13.0
|
89
|
+
requirement: *id007
|
90
|
+
prerelease: false
|
91
|
+
type: :development
|
92
|
+
description: A ruby library to help with the creation of Maestro plugins
|
93
|
+
email:
|
94
|
+
- epelletier@maestrodev.com
|
95
|
+
executables: []
|
96
|
+
|
97
|
+
extensions: []
|
98
|
+
|
99
|
+
extra_rdoc_files: []
|
100
|
+
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- .rvmrc
|
104
|
+
- Gemfile
|
105
|
+
- Gemfile.lock
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- lib/maestro_plugin.rb
|
110
|
+
- lib/maestro_plugin/logging.rb
|
111
|
+
- lib/maestro_plugin/maestro_worker.rb
|
112
|
+
- lib/maestro_plugin/version.rb
|
113
|
+
- maestro_plugin.gemspec
|
114
|
+
- spec/maestro_worker_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
homepage: https://github.com/maestrodev/maestro-ruby-plugin
|
117
|
+
licenses:
|
118
|
+
- Apache 2.0
|
119
|
+
post_install_message:
|
120
|
+
rdoc_options: []
|
121
|
+
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
hash: 2
|
130
|
+
segments:
|
131
|
+
- 0
|
132
|
+
version: "0"
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
hash: 2
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
version: "0"
|
142
|
+
requirements: []
|
143
|
+
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 1.8.24
|
146
|
+
signing_key:
|
147
|
+
specification_version: 3
|
148
|
+
summary: Maestro ruby plugin
|
149
|
+
test_files:
|
150
|
+
- spec/maestro_worker_spec.rb
|
151
|
+
- spec/spec_helper.rb
|