cpee 2.1.2 → 2.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/cockpit/config.json +1 -1
  3. data/cockpit/css/ui.css +14 -7
  4. data/cockpit/edit.html +27 -23
  5. data/cockpit/graph.html +1 -0
  6. data/cockpit/index.html +26 -22
  7. data/cockpit/js/edit.js +8 -1
  8. data/cockpit/js/instance.js +103 -39
  9. data/cockpit/js/modifiers.js +188 -0
  10. data/cockpit/model.html +1 -8
  11. data/cockpit/themes/compact/rngs/call.rng +17 -8
  12. data/cockpit/themes/compact/rngs/callmanipulate.rng +18 -9
  13. data/cockpit/themes/compact/rngs/start.rng +9 -9
  14. data/cockpit/themes/compact/theme.js +1 -1
  15. data/cockpit/themes/control/rngs/call.rng +17 -8
  16. data/cockpit/themes/control/rngs/callmanipulate.rng +18 -9
  17. data/cockpit/themes/control/rngs/start.rng +9 -9
  18. data/cockpit/themes/default/rngs/call.rng +17 -8
  19. data/cockpit/themes/default/rngs/callmanipulate.rng +18 -9
  20. data/cockpit/themes/default/rngs/start.rng +9 -9
  21. data/cockpit/themes/extended/rngs/call.rng +17 -8
  22. data/cockpit/themes/extended/rngs/callmanipulate.rng +18 -9
  23. data/cockpit/themes/extended/rngs/start.rng +9 -9
  24. data/cockpit/themes/extended/theme.js +1 -1
  25. data/cockpit/themes/packed/rngs/call.rng +17 -8
  26. data/cockpit/themes/packed/rngs/callmanipulate.rng +18 -9
  27. data/cockpit/themes/packed/rngs/start.rng +9 -9
  28. data/cockpit/themes/packed/theme.js +1 -1
  29. data/cockpit/themes/preset/rngs/call.rng +17 -8
  30. data/cockpit/themes/preset/rngs/callmanipulate.rng +18 -9
  31. data/cockpit/themes/preset/rngs/start.rng +9 -9
  32. data/cockpit/track.html +1 -0
  33. data/cpee.gemspec +2 -2
  34. data/lib/cpee/implementation_notifications.rb +5 -5
  35. data/lib/cpee/redis.rb +13 -6
  36. data/server/routing/end.pid +1 -0
  37. data/server/routing/forward-events.pid +1 -0
  38. data/server/routing/forward-votes.pid +1 -0
  39. data/server/routing/persist.pid +1 -0
  40. data/tools/cpee +36 -8
  41. data/tools/cpee.sic +306 -0
  42. metadata +10 -5
  43. 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': null,
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="stream" rngui:header="Data Stream Handling" rngui:fold="closed">
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="sensors" rngui:header="Sensor Data Streams" rngui:fold="closed">
31
- <zeroOrMore rngui:label="Add Sensor">
32
- <element name="sensor">
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="extractor_url" rngui:label="Extractor Url">
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 &amp; 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 Extractor Argument Pairs">
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 Visualizer Argument Pairs">
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="stream" rngui:header="Data Stream Handling" rngui:fold="closed">
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="sensors" rngui:header="Sensor Data Streams" rngui:fold="closed">
31
- <zeroOrMore rngui:label="Add Sensor">
32
- <element name="sensor">
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="extractor_url" rngui:label="Extractor Url">
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 &amp; 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 Extractor Argument Pairs">
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:header="Visualizer Arguments">
51
- <zeroOrMore rngui:label="Create Visualizer Argument Pairs">
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 (internal context) in the process can be used as input for context data probes. All probes can be the basis for impact factors. Please go to individual tasks to define deal with data that is ">
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'>Extractor Code</value>
13
- <value id='service'>Extractor Service</value>
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="Service Url"/>
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 &amp; 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 Extractor Argument Pairs">
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 Visualizer Argument Pairs">
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.2"
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.108'
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 'subscribe'
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 'subscribe'
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('handler',key,'url'))
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
- rcmd = opts[:redis_cmd]
41
- rcmd.gsub! /#redis_path#/, File.join(opts[:basepath],opts[:redis_path])
42
- rcmd.gsub! /#redis_db_dir#/, opts[:basepath]
43
- rcmd.gsub! /#redis_db_name#/, opts[:redis_db_name]
44
- rcmd.gsub! /#redis_pid#/, File.join(opts[:basepath],opts[:redis_pid])
45
- res = system rcmd
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
- 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/ })
101
- puts "Directory already exists, updating ..."
102
- end
103
- js_libs(p1)
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
- Typhoeus.delete(File.join(p1,'/'))
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