cpee 2.1.2 → 2.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/cockpit/config.json +1 -1
- data/cockpit/css/ui.css +14 -7
- data/cockpit/edit.html +27 -23
- data/cockpit/graph.html +1 -0
- data/cockpit/index.html +26 -22
- data/cockpit/js/edit.js +8 -1
- data/cockpit/js/instance.js +103 -39
- data/cockpit/js/modifiers.js +188 -0
- data/cockpit/model.html +1 -8
- data/cockpit/themes/compact/rngs/call.rng +17 -8
- data/cockpit/themes/compact/rngs/callmanipulate.rng +18 -9
- data/cockpit/themes/compact/rngs/start.rng +9 -9
- data/cockpit/themes/compact/theme.js +1 -1
- data/cockpit/themes/control/rngs/call.rng +17 -8
- data/cockpit/themes/control/rngs/callmanipulate.rng +18 -9
- data/cockpit/themes/control/rngs/start.rng +9 -9
- data/cockpit/themes/default/rngs/call.rng +17 -8
- data/cockpit/themes/default/rngs/callmanipulate.rng +18 -9
- data/cockpit/themes/default/rngs/start.rng +9 -9
- data/cockpit/themes/extended/rngs/call.rng +17 -8
- data/cockpit/themes/extended/rngs/callmanipulate.rng +18 -9
- data/cockpit/themes/extended/rngs/start.rng +9 -9
- data/cockpit/themes/extended/theme.js +1 -1
- data/cockpit/themes/packed/rngs/call.rng +17 -8
- data/cockpit/themes/packed/rngs/callmanipulate.rng +18 -9
- data/cockpit/themes/packed/rngs/start.rng +9 -9
- data/cockpit/themes/packed/theme.js +1 -1
- data/cockpit/themes/preset/rngs/call.rng +17 -8
- data/cockpit/themes/preset/rngs/callmanipulate.rng +18 -9
- data/cockpit/themes/preset/rngs/start.rng +9 -9
- data/cockpit/track.html +1 -0
- data/cpee.gemspec +2 -2
- data/lib/cpee/implementation_notifications.rb +5 -5
- data/lib/cpee/redis.rb +13 -6
- data/server/routing/end.pid +1 -0
- data/server/routing/forward-events.pid +1 -0
- data/server/routing/forward-votes.pid +1 -0
- data/server/routing/persist.pid +1 -0
- data/tools/cpee +36 -8
- data/tools/cpee.sic +306 -0
- metadata +10 -5
- data/lib/instantiation.xml +0 -125
@@ -1154,7 +1154,7 @@ function WFAdaptorManifestation(adaptor) {
|
|
1154
1154
|
},
|
1155
1155
|
'svg': self.adaptor.theme_dir + 'symbols/start.svg'
|
1156
1156
|
},//}}}
|
1157
|
-
'description':
|
1157
|
+
'description': self.adaptor.theme_dir + 'rngs/start.rng',
|
1158
1158
|
'permissible_children': function(node,mode) { //{{{
|
1159
1159
|
var func = null;
|
1160
1160
|
if (mode == 'into') { func = self.adaptor.description.insert_first_into }
|
@@ -25,19 +25,28 @@
|
|
25
25
|
</element>
|
26
26
|
</zeroOrMore>
|
27
27
|
</element>
|
28
|
-
<element name="
|
28
|
+
<element name="_context_data_analysis" rngui:header="Context Data Analysis" rngui:hint="All data returned from the endpoint implementing this task as well as arbitray external data streams can be consumed and transformed in data probes. All probes can be the basis for impact factors. Please go to start to define instance data probes.">
|
29
29
|
|
30
|
-
<element name="
|
31
|
-
<zeroOrMore rngui:label="Add
|
32
|
-
<element name="
|
30
|
+
<element name="probes" rngui:header="Data Probes - Context Data Extraction" rngui:fold="closed">
|
31
|
+
<zeroOrMore rngui:label="Add Probe">
|
32
|
+
<element name="probe">
|
33
33
|
<element name="name" rngui:label="Label">
|
34
34
|
<data type="string" rngui:label="Label"/>
|
35
35
|
</element>
|
36
|
-
<element name="
|
36
|
+
<element name="extractor_type" rngui:label="Extractor Type">
|
37
|
+
<choice>
|
38
|
+
<value id='code'>Code</value>
|
39
|
+
<value id='service'>Service</value>
|
40
|
+
</choice>
|
41
|
+
</element>
|
42
|
+
<element name="extractor_code" rngui:label="Extractor Code" rngui:hint='For extrinsic data'>
|
43
|
+
<text rngui:label="Code"/>
|
44
|
+
</element>
|
45
|
+
<element name="extractor_url" rngui:label="Extractor Service" rngui:hint='For extrinsic & discrete data'>
|
37
46
|
<data type="string" rngui:label="Service Url"/>
|
38
47
|
</element>
|
39
|
-
<element name="extractor_params" rngui:label="Extractor Arguments:">
|
40
|
-
<zeroOrMore rngui:label="Create
|
48
|
+
<element name="extractor_params" rngui:label="Extractor Service Arguments:">
|
49
|
+
<zeroOrMore rngui:label="Create Argument Pairs">
|
41
50
|
<element rngui:label="Name">
|
42
51
|
<anyName/>
|
43
52
|
<data type="string" rngui:label="Value / Json"/>
|
@@ -48,7 +57,7 @@
|
|
48
57
|
<data type="string" rngui:label="Service Url"/>
|
49
58
|
</element>
|
50
59
|
<element name="visualizer_params" rngui:label="Visualizer Arguments">
|
51
|
-
<zeroOrMore rngui:label="Create
|
60
|
+
<zeroOrMore rngui:label="Create Argument Pairs">
|
52
61
|
<element rngui:label="Name">
|
53
62
|
<anyName/>
|
54
63
|
<data type="string" rngui:label="Value / Json"/>
|
@@ -25,19 +25,28 @@
|
|
25
25
|
</element>
|
26
26
|
</zeroOrMore>
|
27
27
|
</element>
|
28
|
-
<element name="
|
28
|
+
<element name="_context_data_analysis" rngui:header="Context Data Analysis" rngui:hint="All data returned from the endpoint implementing this task as well as arbitray external data streams can be consumed and transformed in data probes. All probes can be the basis for impact factors. Please go to start to define instance data probes.">
|
29
29
|
|
30
|
-
<element name="
|
31
|
-
<zeroOrMore rngui:label="Add
|
32
|
-
<element name="
|
30
|
+
<element name="probes" rngui:header="Data Probes - Context Data Extraction" rngui:fold="closed">
|
31
|
+
<zeroOrMore rngui:label="Add Probe">
|
32
|
+
<element name="probe">
|
33
33
|
<element name="name" rngui:label="Label">
|
34
34
|
<data type="string" rngui:label="Label"/>
|
35
35
|
</element>
|
36
|
-
<element name="
|
36
|
+
<element name="extractor_type" rngui:label="Extractor Type">
|
37
|
+
<choice>
|
38
|
+
<value id='code'>Code</value>
|
39
|
+
<value id='service'>Service</value>
|
40
|
+
</choice>
|
41
|
+
</element>
|
42
|
+
<element name="extractor_code" rngui:label="Extractor Code" rngui:hint='For extrinsic data'>
|
43
|
+
<text rngui:label="Code"/>
|
44
|
+
</element>
|
45
|
+
<element name="extractor_url" rngui:label="Extractor Service" rngui:hint='For extrinsic & discrete data'>
|
37
46
|
<data type="string" rngui:label="Service Url"/>
|
38
47
|
</element>
|
39
|
-
<element name="extractor_params" rngui:label="Extractor Arguments:">
|
40
|
-
<zeroOrMore rngui:label="Create
|
48
|
+
<element name="extractor_params" rngui:label="Extractor Service Arguments:">
|
49
|
+
<zeroOrMore rngui:label="Create Argument Pairs">
|
41
50
|
<element rngui:label="Name">
|
42
51
|
<anyName/>
|
43
52
|
<data type="string" rngui:label="Value / Json"/>
|
@@ -47,8 +56,8 @@
|
|
47
56
|
<element name="visualizer_url" rngui:label="Visualizer Url">
|
48
57
|
<data type="string" rngui:label="Service Url"/>
|
49
58
|
</element>
|
50
|
-
<element name="visualizer_params" rngui:
|
51
|
-
<zeroOrMore rngui:label="Create
|
59
|
+
<element name="visualizer_params" rngui:label="Visualizer Arguments">
|
60
|
+
<zeroOrMore rngui:label="Create Argument Pairs">
|
52
61
|
<element rngui:label="Name">
|
53
62
|
<anyName/>
|
54
63
|
<data type="string" rngui:label="Value / Json"/>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<element xmlns="http://relaxng.org/ns/structure/1.0" xmlns:rngui="http://rngui.org" rngui:version="1.2" name="description" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" ns="http://cpee.org/ns/description/1.0">
|
2
|
-
<element name="_context_data_analysis" rngui:header="Context Data Analysis" rngui:hint="All data elements
|
2
|
+
<element name="_context_data_analysis" rngui:header="Context Data Analysis" rngui:hint="All changes to data elements in the process as well as arbitray external data streams can be consumed and transformed in data probes. All probes can be the basis for impact factors. Please go to individual tasks to define more restricted data probes.">
|
3
3
|
|
4
|
-
<element name="probes" rngui:header="Context Data Extraction" rngui:fold="closed">
|
4
|
+
<element name="probes" rngui:header="Data Probes - Context Data Extraction" rngui:fold="closed">
|
5
5
|
<zeroOrMore rngui:label="Add Probe">
|
6
6
|
<element name="probe">
|
7
7
|
<element name="name" rngui:label="Label">
|
@@ -9,18 +9,18 @@
|
|
9
9
|
</element>
|
10
10
|
<element name="extractor_type" rngui:label="Extractor Type">
|
11
11
|
<choice>
|
12
|
-
<value id='code'>
|
13
|
-
<value id='service'>
|
12
|
+
<value id='code'>Code</value>
|
13
|
+
<value id='service'>Service</value>
|
14
14
|
</choice>
|
15
15
|
</element>
|
16
|
-
<element name="extractor_code" rngui:label="Extractor Code">
|
17
|
-
<text rngui:label="
|
16
|
+
<element name="extractor_code" rngui:label="Extractor Code" rngui:hint='For intrinsic data'>
|
17
|
+
<text rngui:label="Code"/>
|
18
18
|
</element>
|
19
|
-
<element name="extractor_url" rngui:label="Extractor Service">
|
19
|
+
<element name="extractor_url" rngui:label="Extractor Service" rngui:hint='For intrinsic & discrete data'>
|
20
20
|
<data type="string" rngui:label="Service Url"/>
|
21
21
|
</element>
|
22
22
|
<element name="extractor_params" rngui:label="Extractor Service Arguments:">
|
23
|
-
<zeroOrMore rngui:label="Create
|
23
|
+
<zeroOrMore rngui:label="Create Argument Pairs">
|
24
24
|
<element rngui:label="Name">
|
25
25
|
<anyName/>
|
26
26
|
<data type="string" rngui:label="Value / Json"/>
|
@@ -31,7 +31,7 @@
|
|
31
31
|
<data type="string" rngui:label="Service Url"/>
|
32
32
|
</element>
|
33
33
|
<element name="visualizer_params" rngui:label="Visualizer Arguments">
|
34
|
-
<zeroOrMore rngui:label="Create
|
34
|
+
<zeroOrMore rngui:label="Create Argument Pairs">
|
35
35
|
<element rngui:label="Name">
|
36
36
|
<anyName/>
|
37
37
|
<data type="string" rngui:label="Value / Json"/>
|
data/cockpit/track.html
CHANGED
@@ -55,6 +55,7 @@
|
|
55
55
|
<script type="text/javascript" src="js/details.js"></script>
|
56
56
|
<script type="text/javascript" src="js/parameters.js"></script>
|
57
57
|
<script type="text/javascript" src="js/track.js"></script>
|
58
|
+
<script type="text/javascript" src="js/modifiers.js"></script>
|
58
59
|
<link rel="stylesheet" href="css/ui.css" type="text/css"/>
|
59
60
|
<link rel="stylesheet" href="css/track.css" type="text/css"/>
|
60
61
|
</head>
|
data/cpee.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "cpee"
|
3
|
-
s.version = "2.1.
|
3
|
+
s.version = "2.1.8"
|
4
4
|
s.platform = Gem::Platform::RUBY
|
5
5
|
s.license = "LGPL-3.0"
|
6
6
|
s.summary = "Preliminary release of cloud process execution engine (cpee.org). If you just need workflow execution, without a rest service exposing it, then use WEEL."
|
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.email = 'juergen.mangler@gmail.com'
|
22
22
|
s.homepage = 'http://cpee.org/'
|
23
23
|
|
24
|
-
s.add_runtime_dependency 'riddl', '~> 0.
|
24
|
+
s.add_runtime_dependency 'riddl', '~> 0.114'
|
25
25
|
s.add_runtime_dependency 'weel', '~> 1.99', '>= 1.99.99'
|
26
26
|
s.add_runtime_dependency 'highline', '~> 2.0'
|
27
27
|
s.add_runtime_dependency 'json', '~>2.1'
|
@@ -26,10 +26,10 @@ module CPEE
|
|
26
26
|
end
|
27
27
|
on resource "subscriptions" do
|
28
28
|
run CPEE::Notifications::Subscriptions, id, opts if get
|
29
|
-
run CPEE::Notifications::CreateSubscription, id, opts if post '
|
29
|
+
run CPEE::Notifications::CreateSubscription, id, opts if post 'create_subscription'
|
30
30
|
on resource do
|
31
31
|
run CPEE::Notifications::Subscription, id, opts if get
|
32
|
-
run CPEE::Notifications::UpdateSubscription, id, opts if put '
|
32
|
+
run CPEE::Notifications::UpdateSubscription, id, opts if put 'change_subscription'
|
33
33
|
run CPEE::Notifications::DeleteSubscription, id, opts if delete
|
34
34
|
on resource 'sse' do
|
35
35
|
run CPEE::Notifications::SSE, id, opts if sse
|
@@ -92,7 +92,8 @@ module CPEE
|
|
92
92
|
ret = XML::Smart::string <<-END
|
93
93
|
<subscription xmlns='http://riddl.org/ns/common-patterns/notifications-producer/2.0'/>
|
94
94
|
END
|
95
|
-
url = CPEE::Persistence::extract_item(id,opts,File.join('
|
95
|
+
url = CPEE::Persistence::extract_item(id,opts,File.join('handlers',key,'url'))
|
96
|
+
ret.root.attributes['id'] = key
|
96
97
|
ret.root.attributes['url'] = url if url && !url.empty?
|
97
98
|
items = {}
|
98
99
|
CPEE::Persistence::extract_handler(id,opts,key).each do |h|
|
@@ -121,8 +122,7 @@ module CPEE
|
|
121
122
|
id = @a[0]
|
122
123
|
opts = @a[1]
|
123
124
|
|
124
|
-
key = Digest::MD5.hexdigest(Kernel::rand().to_s)
|
125
|
-
|
125
|
+
key = @p[0].name == 'id' ? @p.shift.value : Digest::MD5.hexdigest(Kernel::rand().to_s)
|
126
126
|
url = @p[0].name == 'url' ? @p.shift.value : nil
|
127
127
|
values = []
|
128
128
|
while @p.length > 0
|
data/lib/cpee/redis.rb
CHANGED
@@ -33,18 +33,25 @@ module CPEE
|
|
33
33
|
end
|
34
34
|
else # we always assume file socket if redis is startet locally
|
35
35
|
opts[:redis_dyn] = Proc.new { Redis.new(path: File.join(opts[:basepath],opts[:redis_path]), db: opts[:redis_db].to_i) }
|
36
|
+
tried = false
|
36
37
|
begin
|
37
38
|
opts[:redis] = opts[:redis_dyn].call
|
38
39
|
opts[:redis].dbsize
|
39
40
|
rescue
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
res = if tried
|
42
|
+
rcmd = opts[:redis_cmd]
|
43
|
+
rcmd.gsub! /#redis_path#/, File.join(opts[:basepath],opts[:redis_path])
|
44
|
+
rcmd.gsub! /#redis_db_dir#/, opts[:basepath]
|
45
|
+
rcmd.gsub! /#redis_db_name#/, opts[:redis_db_name]
|
46
|
+
rcmd.gsub! /#redis_pid#/, File.join(opts[:basepath],opts[:redis_pid])
|
47
|
+
system rcmd
|
48
|
+
else
|
49
|
+
true
|
50
|
+
end
|
46
51
|
if res
|
52
|
+
tried = true
|
47
53
|
puts 'starting redis ... it will keep running, just to let you know ...'
|
54
|
+
puts 'waiting for successful start ...'
|
48
55
|
sleep 1
|
49
56
|
retry
|
50
57
|
else
|
@@ -0,0 +1 @@
|
|
1
|
+
742413
|
@@ -0,0 +1 @@
|
|
1
|
+
742401
|
@@ -0,0 +1 @@
|
|
1
|
+
742405
|
@@ -0,0 +1 @@
|
|
1
|
+
742409
|
data/tools/cpee
CHANGED
@@ -94,13 +94,13 @@ if command == 'ui'
|
|
94
94
|
s.start
|
95
95
|
end
|
96
96
|
elsif command == 'cpui'
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
97
|
+
if !File.exists?(p1)
|
98
|
+
FileUtils.cp_r(cockpit,p1)
|
99
|
+
else
|
100
|
+
FileUtils.cp_r(Dir.glob(File.join(cockpit,'*')).delete_if{|e| e =~ /\.json/ || e=~ /legacy/ },p1,remove_destination: true)
|
101
|
+
puts "Directory already exists, updating ..."
|
102
|
+
end
|
103
|
+
js_libs(p1)
|
104
104
|
elsif command == 'convert'
|
105
105
|
Dir['*.xml'].each do |f|
|
106
106
|
XML::Smart.modify(f) do |doc|
|
@@ -162,6 +162,7 @@ elsif command == 'archive'
|
|
162
162
|
names << File.basename(p2)
|
163
163
|
end
|
164
164
|
names.each do |name|
|
165
|
+
print "Working on: " + name.to_s + "\r"
|
165
166
|
res = Typhoeus.get(File.join(base,name.to_s,'/'))
|
166
167
|
if res.success?
|
167
168
|
if res.headers['Content-Type'] =~ /^(text|application)\/xml/
|
@@ -193,6 +194,7 @@ elsif command == 'archive'
|
|
193
194
|
end
|
194
195
|
end
|
195
196
|
end
|
197
|
+
puts
|
196
198
|
elsif command == 'abandon'
|
197
199
|
p1 = File.join(p1,'*') if p1 =~ /([a-zA-Z]|\/)$/
|
198
200
|
base = File.dirname(p1)
|
@@ -215,6 +217,7 @@ elsif command == 'abandon'
|
|
215
217
|
names << File.basename(p1)
|
216
218
|
end
|
217
219
|
names.each do |name|
|
220
|
+
print "Working on: " + name.to_s + "\r"
|
218
221
|
res1 = Typhoeus.get(File.join(base,name.to_s,'properties','state','/'))
|
219
222
|
if res1.success?
|
220
223
|
if res1.response_body == 'ready' || res1.response_body == 'stopped'
|
@@ -222,6 +225,7 @@ elsif command == 'abandon'
|
|
222
225
|
end
|
223
226
|
end
|
224
227
|
end
|
228
|
+
puts
|
225
229
|
elsif command == 'start'
|
226
230
|
p1 = File.join(p1,'*') if p1 =~ /([a-zA-Z]|\/)$/
|
227
231
|
base = File.dirname(p1)
|
@@ -256,7 +260,31 @@ elsif command == 'start'
|
|
256
260
|
end
|
257
261
|
end
|
258
262
|
elsif command == 'delete!'
|
259
|
-
|
263
|
+
p1 = File.join(p1,'*') if p1 =~ /([a-zA-Z]|\/)$/
|
264
|
+
base = File.dirname(p1)
|
265
|
+
names = []
|
266
|
+
if File.basename(p1) =~ /(\d+)-(\d+)/
|
267
|
+
names = ($1.to_i..$2.to_i).to_a
|
268
|
+
elsif File.basename(p1) == '*'
|
269
|
+
res = Typhoeus.get(File.join(base,'/'))
|
270
|
+
if res.success?
|
271
|
+
XML::Smart.string(res.response_body) do |doc|
|
272
|
+
doc.find('//instance/@id').each do |ele|
|
273
|
+
names << ele.value
|
274
|
+
end
|
275
|
+
end
|
276
|
+
names.reverse!
|
277
|
+
else
|
278
|
+
exit
|
279
|
+
end
|
280
|
+
else
|
281
|
+
names << File.basename(p1)
|
282
|
+
end
|
283
|
+
names.each do |name|
|
284
|
+
print "Working on: " + name.to_s + "\r"
|
285
|
+
Typhoeus.delete(File.join(base,name.to_s,'/'))
|
286
|
+
end
|
287
|
+
puts
|
260
288
|
elsif command == 'new'
|
261
289
|
if !File.exists?(p1)
|
262
290
|
FileUtils.cp_r("#{curpath}/server/",p1)
|
data/tools/cpee.sic
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
curpath = __dir__
|
3
|
+
require 'rubygems'
|
4
|
+
require 'optparse'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'webrick'
|
7
|
+
require 'typhoeus'
|
8
|
+
require 'xml/smart'
|
9
|
+
require 'zip'
|
10
|
+
require 'pp'
|
11
|
+
|
12
|
+
def wrap(s, width=78, indent=18)
|
13
|
+
lines = []
|
14
|
+
line, s = s[0..indent-2], s[indent..-1]
|
15
|
+
s.split(/\n/).each do |ss|
|
16
|
+
ss.split(/[ \t]+/).each do |word|
|
17
|
+
if line.size + word.size >= width
|
18
|
+
lines << line
|
19
|
+
line = (" " * (indent)) + word
|
20
|
+
else
|
21
|
+
line << " " << word
|
22
|
+
end
|
23
|
+
end
|
24
|
+
lines << line if line
|
25
|
+
line = (" " * (indent-1))
|
26
|
+
end
|
27
|
+
return lines.join "\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
ARGV.options { |opt|
|
31
|
+
opt.summary_indent = ' ' * 2
|
32
|
+
opt.summary_width = 15
|
33
|
+
opt.banner = "Usage:\n#{opt.summary_indent}#{File.basename($0)} [options] convert | ui | cpui DIR | new DIR | archive DIR URL | start URL | delete! URL | abandon URL\n"
|
34
|
+
opt.on("Options:")
|
35
|
+
opt.on("--help", "-h", "This text") { puts opt; exit }
|
36
|
+
opt.on("")
|
37
|
+
opt.on(wrap("[archive DIR URL] save properties from all finished instances listed at URL into DIR. Examples:\ncpee archive ./archive http://localhost:9298/1/\ncpee archive ./archive http://localhost:9298/1-200\ncpee archive ./archive http://localhost:9298/*"))
|
38
|
+
opt.on("")
|
39
|
+
opt.on(wrap("[abandon URL] running processes are stopped; ready or stopped processes are abandoned. Examples:\ncpee abandon http://localhost:9298/1/\ncpee abandon http://localhost:9298/1-200\ncpee abandon http://localhost:9298/*"))
|
40
|
+
opt.on("")
|
41
|
+
opt.on(wrap("[start URL] stopped processes are started; all others are not touched. Examples:\ncpee start http://localhost:9298/1\ncpee start http://localhost:9298/1-200\ncpee start http://localhost:9298/*"))
|
42
|
+
opt.on("")
|
43
|
+
opt.on(wrap("[delete! URL] DANGER ZONE. Vanishes forever. Not in archive. Examples:\ncpee delete! http://localhost:9298/1/"))
|
44
|
+
opt.on("")
|
45
|
+
opt.on(wrap("[new DIR] scaffolds a sample execution engine. Everything except instances can be removed for default behaviour."))
|
46
|
+
opt.on("")
|
47
|
+
opt.on(wrap("[cpui DIR] scaffolds a sample html client. New versions might require manual merging if you changed something."))
|
48
|
+
opt.on("")
|
49
|
+
opt.on(wrap("[ui] starts a simple static web server with the ui on http://localhost:8080. Use [cpui DIR] if you want stuff in apache or nginx."))
|
50
|
+
opt.on("")
|
51
|
+
opt.on(wrap("[convert] converts all testsets in the current directory to cpee2"))
|
52
|
+
opt.parse!
|
53
|
+
}
|
54
|
+
if (ARGV.length == 0) ||
|
55
|
+
(ARGV.length == 1 && !(%w(ui convert).include?(ARGV[0]))) ||
|
56
|
+
(ARGV.length == 2 && !(%w(abandon start delete! cpui new).include?(ARGV[0]))) ||
|
57
|
+
(ARGV.length == 3 && ARGV[0] != 'archive') ||
|
58
|
+
(ARGV.length > 3)
|
59
|
+
puts ARGV.options
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
command = ARGV[0]
|
63
|
+
p1 = ARGV[1]
|
64
|
+
p2 = ARGV[2]
|
65
|
+
cockpit = "#{curpath}/../cockpit/"
|
66
|
+
|
67
|
+
def js_libs(cockpit)
|
68
|
+
res = Typhoeus.get('https://cpee.org/js_libs/js_libs.zip')
|
69
|
+
if res.success?
|
70
|
+
File.write(File.join(cockpit,'js_libs.zip'),res.response_body)
|
71
|
+
Zip::File.open(File.join(cockpit,'js_libs.zip')) do |zip_file|
|
72
|
+
zip_file.each do |entry|
|
73
|
+
case entry.ftype
|
74
|
+
when :directory
|
75
|
+
Dir.mkdir(File.join(cockpit,entry.name)) rescue nil
|
76
|
+
when :file
|
77
|
+
File.write(File.join(cockpit,entry.name),entry.get_input_stream.read)
|
78
|
+
when :symlink
|
79
|
+
FileUtils.ln_s(File.join('.',entry.get_input_stream.read),File.join(cockpit,entry.name), force: true)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
true
|
84
|
+
else
|
85
|
+
puts 'Internet access required to download javascript libs from "http://cpee.org/js_libs/js_libs.zip".'
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if command == 'ui'
|
91
|
+
if js_libs(cockpit)
|
92
|
+
s = WEBrick::HTTPServer.new(:Port => 8080, :DocumentRoot => cockpit)
|
93
|
+
trap("INT"){ s.shutdown }
|
94
|
+
s.start
|
95
|
+
end
|
96
|
+
elsif command == 'cpui'
|
97
|
+
if !File.exists?(p1)
|
98
|
+
FileUtils.cp_r(cockpit,p1)
|
99
|
+
else
|
100
|
+
FileUtils.cp_r(Dir.glob(File.join(cockpit,'*')),p1,remove_destination: true)
|
101
|
+
puts "Directory already exists, updating ..."
|
102
|
+
end
|
103
|
+
js_libs(p1)
|
104
|
+
elsif command == 'convert'
|
105
|
+
Dir['*.xml'].each do |f|
|
106
|
+
XML::Smart.modify(f) do |doc|
|
107
|
+
doc.register_namespace 'd', 'http://cpee.org/ns/description/1.0'
|
108
|
+
doc.register_namespace 'p', 'http://riddl.org/ns/common-patterns/properties/1.0'
|
109
|
+
doc.register_namespace 'x', 'http://cpee.org/ns/properties/2.0'
|
110
|
+
if doc.root.qname.name == 'testset'
|
111
|
+
doc.root.namespaces[nil] = 'http://cpee.org/ns/properties/2.0'
|
112
|
+
doc.root.namespace = nil
|
113
|
+
|
114
|
+
doc.find('//x:handlerwrapper').each do |e|
|
115
|
+
if e.text == 'DefaultHandlerWrapper'
|
116
|
+
doc.root.prepend('x:executionhandler','ruby')
|
117
|
+
end
|
118
|
+
end rescue nil
|
119
|
+
doc.find('//x:handlerwrapper').delete_all!
|
120
|
+
doc.find('//x:start_url').each do |e|
|
121
|
+
e.text = 'https://cpee.org/flow/start/url/'
|
122
|
+
end rescue nil
|
123
|
+
doc.find('//x:start_git').each do |e|
|
124
|
+
e.text = 'https://cpee.org/flow/start/git/'
|
125
|
+
end rescue nil
|
126
|
+
doc.find('//d:finalize | //d:update | //d:prepare | //d:rescue').each do |e|
|
127
|
+
if e.parent.qname.name != 'code'
|
128
|
+
n = e.parent
|
129
|
+
if (x = n.find('d:code')).any?
|
130
|
+
x.first.add(e)
|
131
|
+
else
|
132
|
+
n.add('d:code').add(e)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end rescue nil
|
136
|
+
|
137
|
+
doc.find('//p:*').each do |e|
|
138
|
+
e.namespaces.delete_all!
|
139
|
+
end rescue nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
elsif command == 'archive'
|
144
|
+
p2 = File.join(p2,'*') if p2 =~ /([a-zA-Z]|\/)$/
|
145
|
+
base = File.dirname(p2)
|
146
|
+
names = []
|
147
|
+
if File.basename(p2) =~ /(\d+)-(\d+)/
|
148
|
+
names = ($1.to_i..$2.to_i).to_a
|
149
|
+
elsif File.basename(p2) == '*'
|
150
|
+
res = Typhoeus.get(File.join(base,'/'))
|
151
|
+
if res.success?
|
152
|
+
XML::Smart.string(res.response_body) do |doc|
|
153
|
+
doc.find('//instance/@id').each do |ele|
|
154
|
+
names << ele.value
|
155
|
+
end
|
156
|
+
end
|
157
|
+
names.reverse!
|
158
|
+
else
|
159
|
+
exit
|
160
|
+
end
|
161
|
+
else
|
162
|
+
names << File.basename(p2)
|
163
|
+
end
|
164
|
+
names.each do |name|
|
165
|
+
print "Working on: " + name.to_s + "\r"
|
166
|
+
res = Typhoeus.get(File.join(base,name.to_s,'/'))
|
167
|
+
if res.success?
|
168
|
+
if res.headers['Content-Type'] =~ /^(text|application)\/xml/
|
169
|
+
XML::Smart.string(res.response_body) do |doc|
|
170
|
+
if doc.root.qname.to_s == "instances"
|
171
|
+
doc.root.children.each do |i|
|
172
|
+
if ["finished","abandoned"].include?(i.attributes['state']) || (["ready"].include?(i.attributes['state']) && Time.parse(i.attributes['changed']).to_i < Time.now-(60*60*24))
|
173
|
+
prop = Typhoeus.get(File.join(base,name.to_s,i.attributes['id'],'properties','/'))
|
174
|
+
if prop.success?
|
175
|
+
File.write(File.join(p1,i.attributes['uuid'] + '.xml'),prop.response_body) if prop.headers['Content-Type'] =~ /^(text|application)\/xml/
|
176
|
+
Typhoeus.delete(File.join(base,name.to_s,i.attributes['id'],'/'))
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
elsif doc.root.qname.to_s == "info"
|
181
|
+
prop = Typhoeus.get(File.join(base,name.to_s,'properties','/'))
|
182
|
+
if prop.success?
|
183
|
+
xprop = XML::Smart::string(prop.response_body)
|
184
|
+
xprop.register_namespace 'p', 'http://cpee.org/ns/properties/2.0'
|
185
|
+
if ["finished","abandoned"].include?(xprop.find("string(/p:properties/p:state)")) || (["ready"].include?(xprop.find("string(/p:properties/p:state)")) && Time.parse(xprop.find("string(/p:properties/p:state/@changed)")) < Time.now-(60*60*12))
|
186
|
+
uuid = xprop.find("string(/p:properties/p:attributes/p:uuid)")
|
187
|
+
id = name.to_s
|
188
|
+
File.write(File.join(p1,uuid + '.xml'),prop.response_body) if prop.headers['Content-Type'] =~ /^(text|application)\/xml/
|
189
|
+
Typhoeus.delete(File.join(base,name.to_s,'/'))
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
puts
|
198
|
+
elsif command == 'abandon'
|
199
|
+
p1 = File.join(p1,'*') if p1 =~ /([a-zA-Z]|\/)$/
|
200
|
+
base = File.dirname(p1)
|
201
|
+
names = []
|
202
|
+
if File.basename(p1) =~ /(\d+)-(\d+)/
|
203
|
+
names = ($1.to_i..$2.to_i).to_a
|
204
|
+
elsif File.basename(p1) == '*'
|
205
|
+
res = Typhoeus.get(File.join(base,'/'))
|
206
|
+
if res.success?
|
207
|
+
XML::Smart.string(res.response_body) do |doc|
|
208
|
+
doc.find('//instance/@id').each do |ele|
|
209
|
+
names << ele.value
|
210
|
+
end
|
211
|
+
end
|
212
|
+
names.reverse!
|
213
|
+
else
|
214
|
+
exit
|
215
|
+
end
|
216
|
+
else
|
217
|
+
names << File.basename(p1)
|
218
|
+
end
|
219
|
+
names.each do |name|
|
220
|
+
print "Working on: " + name.to_s + "\r"
|
221
|
+
res1 = Typhoeus.get(File.join(base,name.to_s,'properties','state','/'))
|
222
|
+
if res1.success?
|
223
|
+
if res1.response_body == 'ready' || res1.response_body == 'stopped'
|
224
|
+
Typhoeus.put(File.join(base,name.to_s,'properties','state','/'), headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: "value=abandoned")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
puts
|
229
|
+
elsif command == 'start'
|
230
|
+
p1 = File.join(p1,'*') if p1 =~ /([a-zA-Z]|\/)$/
|
231
|
+
base = File.dirname(p1)
|
232
|
+
names = []
|
233
|
+
if File.basename(p1) =~ /(\d+)-(\d+)/
|
234
|
+
names = ($1.to_i..$2.to_i).to_a
|
235
|
+
elsif File.basename(p1) == '*'
|
236
|
+
res = Typhoeus.get(File.join(base,'/'))
|
237
|
+
if res.success?
|
238
|
+
XML::Smart.string(res.response_body) do |doc|
|
239
|
+
doc.find('//instance/@id').each do |ele|
|
240
|
+
names << ele.value
|
241
|
+
end
|
242
|
+
end
|
243
|
+
names.reverse!
|
244
|
+
else
|
245
|
+
exit
|
246
|
+
end
|
247
|
+
else
|
248
|
+
names << File.basename(p1)
|
249
|
+
end
|
250
|
+
names.each do |name|
|
251
|
+
res = Typhoeus.get(File.join(base,name.to_s,'properties','state','/'))
|
252
|
+
if res.success?
|
253
|
+
case res.response_body
|
254
|
+
when "stopped" then
|
255
|
+
keep_alive = Typhoeus.get(File.join(base,name.to_s,'properties','attributes','keep_alive','/'))
|
256
|
+
if keep_alive.success?
|
257
|
+
Typhoeus.put(File.join(base,name.to_s,'properties','state','/'), headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, body: "value=running")
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
elsif command == 'delete!'
|
263
|
+
p1 = File.join(p1,'*') if p1 =~ /([a-zA-Z]|\/)$/
|
264
|
+
base = File.dirname(p1)
|
265
|
+
names = []
|
266
|
+
if File.basename(p1) =~ /(\d+)-(\d+)/
|
267
|
+
names = ($1.to_i..$2.to_i).to_a
|
268
|
+
elsif File.basename(p1) == '*'
|
269
|
+
res = Typhoeus.get(File.join(base,'/'))
|
270
|
+
if res.success?
|
271
|
+
XML::Smart.string(res.response_body) do |doc|
|
272
|
+
doc.find('//instance/@id').each do |ele|
|
273
|
+
names << ele.value
|
274
|
+
end
|
275
|
+
end
|
276
|
+
names.reverse!
|
277
|
+
else
|
278
|
+
exit
|
279
|
+
end
|
280
|
+
else
|
281
|
+
names << File.basename(p1)
|
282
|
+
end
|
283
|
+
names.each do |name|
|
284
|
+
print "Working on: " + name.to_s + "\r"
|
285
|
+
Typhoeus.delete(File.join(base,name.to_s,'/'))
|
286
|
+
end
|
287
|
+
puts
|
288
|
+
elsif command == 'new'
|
289
|
+
if !File.exists?(p1)
|
290
|
+
FileUtils.cp_r("#{curpath}/server/",p1)
|
291
|
+
FileUtils.mkdir("#{p1}/archive") rescue nil
|
292
|
+
FileUtils.mkdir("#{p1}/instances") rescue nil
|
293
|
+
FileUtils.mkdir("#{p1}/resources") rescue nil
|
294
|
+
FileUtils.mkdir("#{p1}/executionhandler") rescue nil
|
295
|
+
Dir["#{curpath}/../systemd/*.service"].each do |f|
|
296
|
+
nam = File.basename f
|
297
|
+
cont = File.read(f)
|
298
|
+
cont.gsub!(/{CPEEUSER}/,`whoami`.strip)
|
299
|
+
cont.gsub!(/{CPEEWORKINGDIR}/,"#{File.realpath(p1)}")
|
300
|
+
cont.gsub!(/{CPEESERVER}/,"#{File.realpath(p1)}/server")
|
301
|
+
File.write("#{p1}/#{nam}",cont)
|
302
|
+
end
|
303
|
+
else
|
304
|
+
puts 'Directory already exists.'
|
305
|
+
end
|
306
|
+
end
|