dynflow 0.8.11 → 0.8.12
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.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/dynflow.gemspec +1 -0
- data/lib/dynflow/action.rb +4 -4
- data/lib/dynflow/coordinator.rb +28 -4
- data/lib/dynflow/middleware.rb +3 -0
- data/lib/dynflow/middleware/stack.rb +1 -1
- data/lib/dynflow/middleware/world.rb +1 -1
- data/lib/dynflow/persistence.rb +4 -2
- data/lib/dynflow/version.rb +1 -1
- data/lib/dynflow/web/console_helpers.rb +1 -1
- data/lib/dynflow/world.rb +5 -1
- data/test/coordinator_test.rb +6 -0
- data/test/middleware_test.rb +51 -0
- data/test/support/middleware_example.rb +33 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74ac597ce9af73467ae1ecbf398a2929f1595b14
|
4
|
+
data.tar.gz: 22cb74c9aef05391f93d8652888c9806fd9edde5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aec52cb41798f0730ef950e88195a3973b3d879f584b0e3341e8900147d66ff1b5642d394683894c4a0c33a1eb1d119296c08840dbbb8fb9a90d1b760d8fe0ef
|
7
|
+
data.tar.gz: 5e5908f5ad7938c036c948a1d925c23d714ea2384f3ef6ac0e1a40aa12c97ee71c044c598898e00e2942e04d4473738f975ceaa3b35ce0294b2a00ea0a969ede
|
data/Gemfile
CHANGED
data/dynflow.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency "concurrent-ruby-edge", '~> 0.2'
|
26
26
|
s.add_dependency "sequel"
|
27
27
|
|
28
|
+
s.add_development_dependency "rake"
|
28
29
|
s.add_development_dependency "rack-test"
|
29
30
|
s.add_development_dependency "minitest"
|
30
31
|
s.add_development_dependency "minitest-reporters"
|
data/lib/dynflow/action.rb
CHANGED
@@ -92,8 +92,8 @@ module Dynflow
|
|
92
92
|
|
93
93
|
@phase = Type! attributes.fetch(:phase), Phase
|
94
94
|
@world = Type! world, World
|
95
|
-
@step = Type!
|
96
|
-
|
95
|
+
@step = Type! attributes.fetch(:step), ExecutionPlan::Steps::Abstract, NilClass
|
96
|
+
raise ArgumentError, 'Step reference missing' if phase?(Executable) && @step.nil?
|
97
97
|
@execution_plan_id = Type! attributes.fetch(:execution_plan_id), String
|
98
98
|
@id = Type! attributes.fetch(:id), Integer
|
99
99
|
@plan_step_id = Type! attributes.fetch(:plan_step_id), Integer
|
@@ -240,7 +240,7 @@ module Dynflow
|
|
240
240
|
end
|
241
241
|
|
242
242
|
def state
|
243
|
-
|
243
|
+
raise "state data not available" if @step.nil?
|
244
244
|
@step.state
|
245
245
|
end
|
246
246
|
|
@@ -251,7 +251,7 @@ module Dynflow
|
|
251
251
|
end
|
252
252
|
|
253
253
|
def error
|
254
|
-
|
254
|
+
raise "error data not available" if @step.nil?
|
255
255
|
@step.error
|
256
256
|
end
|
257
257
|
|
data/lib/dynflow/coordinator.rb
CHANGED
@@ -146,6 +146,14 @@ module Dynflow
|
|
146
146
|
@data.merge!(owner_id: "world:#{world.id}", world_id: world.id)
|
147
147
|
end
|
148
148
|
|
149
|
+
def self.lock_id(*args)
|
150
|
+
raise NoMethodError
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.unique_filter(*args)
|
154
|
+
{ :class => self.name, :id => lock_id(*args) }
|
155
|
+
end
|
156
|
+
|
149
157
|
def validate!
|
150
158
|
super
|
151
159
|
raise Errors::InactiveWorldError.new(@world) if @world.terminating?
|
@@ -171,33 +179,49 @@ module Dynflow
|
|
171
179
|
class DelayedExecutorLock < LockByWorld
|
172
180
|
def initialize(world)
|
173
181
|
super
|
174
|
-
@data[:id] =
|
182
|
+
@data[:id] = self.class.lock_id
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.lock_id
|
186
|
+
"delayed-executor"
|
175
187
|
end
|
176
188
|
end
|
177
189
|
|
178
190
|
class WorldInvalidationLock < LockByWorld
|
179
191
|
def initialize(world, invalidated_world)
|
180
192
|
super(world)
|
181
|
-
@data[:id] =
|
193
|
+
@data[:id] = self.class.lock_id(invalidated_world.id)
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.lock_id(invalidated_world_id)
|
197
|
+
"world-invalidation:#{invalidated_world_id}"
|
182
198
|
end
|
183
199
|
end
|
184
200
|
|
185
201
|
class AutoExecuteLock < LockByWorld
|
186
202
|
def initialize(*args)
|
187
203
|
super
|
188
|
-
@data[:id] =
|
204
|
+
@data[:id] = self.class.lock_id
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.lock_id
|
208
|
+
"auto-execute"
|
189
209
|
end
|
190
210
|
end
|
191
211
|
|
192
212
|
class ExecutionLock < LockByWorld
|
193
213
|
def initialize(world, execution_plan_id, client_world_id, request_id)
|
194
214
|
super(world)
|
195
|
-
@data.merge!(id:
|
215
|
+
@data.merge!(id: self.class.lock_id(execution_plan_id),
|
196
216
|
execution_plan_id: execution_plan_id,
|
197
217
|
client_world_id: client_world_id,
|
198
218
|
request_id: request_id)
|
199
219
|
end
|
200
220
|
|
221
|
+
def self.lock_id(execution_plan_id)
|
222
|
+
"execution-plan:#{execution_plan_id}"
|
223
|
+
end
|
224
|
+
|
201
225
|
# we need to store the following data in case of
|
202
226
|
# invalidation of the lock from outside (after
|
203
227
|
# the owner world terminated unexpectedly)
|
data/lib/dynflow/middleware.rb
CHANGED
@@ -14,7 +14,7 @@ module Dynflow
|
|
14
14
|
@middleware_class = Child! middleware_class, Middleware
|
15
15
|
@middleware = middleware_class.new self
|
16
16
|
@action = Type! action, Dynflow::Action, NilClass
|
17
|
-
@method = Match! method, :delay, :plan, :run, :finalize, :plan_phase, :finalize_phase
|
17
|
+
@method = Match! method, :delay, :plan, :run, :finalize, :plan_phase, :finalize_phase, :present
|
18
18
|
@next_stack = Type! next_stack, Middleware::Stack, Proc
|
19
19
|
end
|
20
20
|
|
@@ -14,7 +14,7 @@ module Dynflow
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def execute(method, action_or_class, *args, &block)
|
17
|
-
Match! method, :delay, :plan, :run, :finalize, :plan_phase, :finalize_phase
|
17
|
+
Match! method, :delay, :plan, :run, :finalize, :plan_phase, :finalize_phase, :present
|
18
18
|
if Child? action_or_class, Dynflow::Action
|
19
19
|
action = nil
|
20
20
|
action_class = action_or_class
|
data/lib/dynflow/persistence.rb
CHANGED
@@ -21,9 +21,11 @@ module Dynflow
|
|
21
21
|
return Action.from_hash(attributes, step.world)
|
22
22
|
end
|
23
23
|
|
24
|
-
def load_action_for_presentation(execution_plan, action_id)
|
24
|
+
def load_action_for_presentation(execution_plan, action_id, step = nil)
|
25
25
|
attributes = adapter.load_action(execution_plan.id, action_id)
|
26
|
-
Action.from_hash(attributes.update(phase: Action::Present, execution_plan: execution_plan), @world)
|
26
|
+
Action.from_hash(attributes.update(phase: Action::Present, execution_plan: execution_plan, step: step), @world).tap do |present_action|
|
27
|
+
@world.middleware.execute(:present, present_action) {}
|
28
|
+
end
|
27
29
|
end
|
28
30
|
|
29
31
|
def save_action(execution_plan_id, action)
|
data/lib/dynflow/version.rb
CHANGED
data/lib/dynflow/world.rb
CHANGED
@@ -354,7 +354,11 @@ module Dynflow
|
|
354
354
|
coordinator.acquire(Coordinator::AutoExecuteLock.new(self)) do
|
355
355
|
planned_execution_plans =
|
356
356
|
self.persistence.find_execution_plans filters: { 'state' => %w(planned paused), 'result' => (ExecutionPlan.results - [:error]).map(&:to_s) }
|
357
|
-
planned_execution_plans.map
|
357
|
+
planned_execution_plans.map do |ep|
|
358
|
+
if coordinator.find_locks(Dynflow::Coordinator::ExecutionLock.unique_filter(ep.id)).empty?
|
359
|
+
execute(ep.id)
|
360
|
+
end
|
361
|
+
end.compact
|
358
362
|
end
|
359
363
|
end
|
360
364
|
|
data/test/coordinator_test.rb
CHANGED
@@ -32,6 +32,12 @@ module Dynflow
|
|
32
32
|
tester.finish
|
33
33
|
end
|
34
34
|
|
35
|
+
it 'supports checking about locks' do
|
36
|
+
world.coordinator.acquire(Coordinator::AutoExecuteLock.new(world))
|
37
|
+
locks = world.coordinator.find_locks(Coordinator::AutoExecuteLock.unique_filter)
|
38
|
+
locks.map(&:world_id).must_equal([world.id])
|
39
|
+
end
|
40
|
+
|
35
41
|
it 'deserializes the data from the adapter when searching for locks' do
|
36
42
|
lock = Coordinator::AutoExecuteLock.new(world)
|
37
43
|
world.coordinator.acquire(lock)
|
data/test/middleware_test.rb
CHANGED
@@ -132,6 +132,57 @@ module Dynflow
|
|
132
132
|
'run',
|
133
133
|
'output#message:finished']
|
134
134
|
end
|
135
|
+
|
136
|
+
describe 'Presnet middleware' do
|
137
|
+
let(:world_with_middleware) do
|
138
|
+
WorldFactory.create_world.tap do |world|
|
139
|
+
world.middleware.use(Support::MiddlewareExample::FilterSensitiveData)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
let :execution_plan do
|
144
|
+
result = world.trigger(Support::CodeWorkflowExample::IncomingIssue, issue_data)
|
145
|
+
result.must_be :planned?
|
146
|
+
result.finished.value
|
147
|
+
end
|
148
|
+
|
149
|
+
let :execution_plan_2 do
|
150
|
+
result = world.trigger(Support::MiddlewareExample::SecretAction)
|
151
|
+
result.must_be :planned?
|
152
|
+
result.finished.value
|
153
|
+
end
|
154
|
+
|
155
|
+
let :filtered_execution_plan do
|
156
|
+
world_with_middleware.persistence.load_execution_plan(execution_plan.id)
|
157
|
+
end
|
158
|
+
|
159
|
+
let :issue_data do
|
160
|
+
{ 'author' => 'Harry Potter', 'text' => 'Lord Voldemort is comming' }
|
161
|
+
end
|
162
|
+
|
163
|
+
let :presenter do
|
164
|
+
filtered_execution_plan.root_plan_step.action filtered_execution_plan
|
165
|
+
end
|
166
|
+
|
167
|
+
let :presenter_2 do
|
168
|
+
execution_plan_2.root_plan_step.action execution_plan_2
|
169
|
+
end
|
170
|
+
|
171
|
+
let :presenter_without_middleware do
|
172
|
+
execution_plan.root_plan_step.action execution_plan
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'filters the data ===' do
|
176
|
+
presenter.input['text'].must_equal('You-Know-Who is comming')
|
177
|
+
presenter_2.output['spell'].must_equal('***')
|
178
|
+
end
|
179
|
+
|
180
|
+
it "doesn't affect stored data" do
|
181
|
+
presenter.input['text'].must_equal('You-Know-Who is comming')
|
182
|
+
presenter_without_middleware.input['text'].must_equal('Lord Voldemort is comming')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
135
186
|
end
|
136
187
|
end
|
137
188
|
end
|
@@ -70,6 +70,39 @@ module Support
|
|
70
70
|
class AnotherLogRunMiddleware < LogRunMiddleware
|
71
71
|
end
|
72
72
|
|
73
|
+
class FilterSensitiveData < Dynflow::Middleware
|
74
|
+
def present
|
75
|
+
if action.respond_to?(:filter_sensitive_data)
|
76
|
+
action.filter_sensitive_data
|
77
|
+
end
|
78
|
+
filter_sensitive_data(action.input)
|
79
|
+
filter_sensitive_data(action.output)
|
80
|
+
end
|
81
|
+
|
82
|
+
def filter_sensitive_data(data)
|
83
|
+
case data
|
84
|
+
when Hash
|
85
|
+
data.values.each { |value| filter_sensitive_data(value) }
|
86
|
+
when Array
|
87
|
+
data.each { |value| filter_sensitive_data(value) }
|
88
|
+
when String
|
89
|
+
data.gsub!('Lord Voldemort', 'You-Know-Who')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class SecretAction < Dynflow::Action
|
95
|
+
middleware.use(FilterSensitiveData)
|
96
|
+
|
97
|
+
def run
|
98
|
+
output[:spell] = 'Wingardium Leviosa'
|
99
|
+
end
|
100
|
+
|
101
|
+
def filter_sensitive_data
|
102
|
+
output[:spell] = '***'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
73
106
|
class LoggingAction < Dynflow::Action
|
74
107
|
|
75
108
|
middleware.use LogMiddleware
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Necas
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-07-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -95,6 +95,20 @@ dependencies:
|
|
95
95
|
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: rake
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
98
112
|
- !ruby/object:Gem::Dependency
|
99
113
|
name: rack-test
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -528,7 +542,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
528
542
|
version: '0'
|
529
543
|
requirements: []
|
530
544
|
rubyforge_project:
|
531
|
-
rubygems_version: 2.4.
|
545
|
+
rubygems_version: 2.4.8
|
532
546
|
signing_key:
|
533
547
|
specification_version: 4
|
534
548
|
summary: DYNamic workFLOW engine
|
@@ -557,3 +571,4 @@ test_files:
|
|
557
571
|
- test/testing_test.rb
|
558
572
|
- test/web_console_test.rb
|
559
573
|
- test/world_test.rb
|
574
|
+
has_rdoc:
|