maestro_plugin 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|