nestene 0.1.0
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 +15 -0
- data/.gitignore +15 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/TODO.txt +7 -0
- data/api.rb +8 -0
- data/autons.rb +13 -0
- data/bin/nestene.rb +5 -0
- data/config.ru +21 -0
- data/features/api/api_create_auton.feature +6 -0
- data/features/api/api_credentials.feature +11 -0
- data/features/api/api_list_of_autons.feature +6 -0
- data/features/callback.feature +13 -0
- data/features/create_auton.feature +11 -0
- data/features/credentials.feature +7 -0
- data/features/execute_step.feature +59 -0
- data/features/restart.feature +7 -0
- data/features/schedule_steps.feature +7 -0
- data/features/step_definitions/api/api_create_auton_steps.rb +16 -0
- data/features/step_definitions/api/api_credentials_steps.rb +22 -0
- data/features/step_definitions/api/api_list_of_autons_steps.rb +8 -0
- data/features/step_definitions/callback_steps.rb +75 -0
- data/features/step_definitions/create_auton_steps.rb +32 -0
- data/features/step_definitions/credentials_steps.rb +24 -0
- data/features/step_definitions/execute_step_steps.rb +177 -0
- data/features/step_definitions/restart_steps.rb +5 -0
- data/features/step_definitions/schedule_steps_steps.rb +29 -0
- data/features/step_definitions/time_delayed_steps_steps.rb +103 -0
- data/features/step_definitions/ui/create_auton_steps.rb +21 -0
- data/features/step_definitions/ui/list_of_autons_steps.rb +18 -0
- data/features/step_definitions/ui/schedule_auton_step_steps.rb +64 -0
- data/features/step_definitions/ui/show_auton_steps.rb +49 -0
- data/features/support/env.rb +36 -0
- data/features/time_delayed_steps.feature +28 -0
- data/features/ui/create_auton.feature +7 -0
- data/features/ui/list_of_autons.feature +7 -0
- data/features/ui/schedule_auton_step.feature +12 -0
- data/features/ui/show_auton.feature +14 -0
- data/lib/nestene/actor/auton_queue.rb +87 -0
- data/lib/nestene/actor/auton_storage.rb +50 -0
- data/lib/nestene/actor/core.rb +150 -0
- data/lib/nestene/actor/delayed_scheduler.rb +76 -0
- data/lib/nestene/auton_context.rb +31 -0
- data/lib/nestene/auton_execution_queue.rb +43 -0
- data/lib/nestene/auton_state.rb +27 -0
- data/lib/nestene/callback.rb +7 -0
- data/lib/nestene/delayed_method.rb +17 -0
- data/lib/nestene/executed_method.rb +29 -0
- data/lib/nestene/executing_method.rb +23 -0
- data/lib/nestene/execution_error.rb +39 -0
- data/lib/nestene/scheduled_method.rb +21 -0
- data/lib/nestene/storage.rb +72 -0
- data/lib/nestene/ui/app.rb +103 -0
- data/lib/nestene/ui/public/app/application.js +75 -0
- data/lib/nestene/ui/public/vendor/angular-ui-sortable/sortable.min.js +1 -0
- data/lib/nestene/ui/public/vendor/angular.min.js +248 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap-theme.css +347 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap-theme.min.css +7 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap.css +5785 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap.min.css +7 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/nestene/ui/public/vendor/bootstrap/js/bootstrap.js +1951 -0
- data/lib/nestene/ui/public/vendor/bootstrap/js/bootstrap.min.js +6 -0
- data/lib/nestene/ui/public/vendor/jquery-ui.min.js +13 -0
- data/lib/nestene/ui/public/vendor/jquery.bootstrap-growl.min.js +1 -0
- data/lib/nestene/ui/public/vendor/jquery.min.js +5 -0
- data/lib/nestene/ui/public/vendor/json-editor/directives.js +245 -0
- data/lib/nestene/ui/public/vendor/json-editor/styles.css +165 -0
- data/lib/nestene/ui/views/auton.haml +42 -0
- data/lib/nestene/ui/views/auton_form.haml +8 -0
- data/lib/nestene/ui/views/index.haml +35 -0
- data/lib/nestene/ui/views/layout.haml +40 -0
- data/lib/nestene/ui/views/schedule_step.haml +14 -0
- data/lib/nestene/version.rb +3 -0
- data/lib/nestene.rb +50 -0
- data/nestene.gemspec +39 -0
- data/spec/nestene/auton_execution_queue_spec.rb +78 -0
- data/spec/nestene/nestene_spec.rb +137 -0
- data/spec/nestene/storage_spec.rb +125 -0
- data/spec/spec_helper.rb +2 -0
- metadata +373 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'celluloid'
|
|
2
|
+
|
|
3
|
+
module Nestene
|
|
4
|
+
module Actor
|
|
5
|
+
class DelayedScheduler
|
|
6
|
+
|
|
7
|
+
include Celluloid
|
|
8
|
+
include Celluloid::Notifications
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
subscribe('state_update', :update_schedule)
|
|
12
|
+
@schedule = []
|
|
13
|
+
@timer = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def update_schedule topic, auton_id, state
|
|
18
|
+
|
|
19
|
+
@schedule.delete_if{|e| e.first == auton_id}
|
|
20
|
+
|
|
21
|
+
state.queue.delayed.each do |d|
|
|
22
|
+
@schedule << [auton_id, d]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
@schedule.sort_by!{|e| e[1].execute_at}
|
|
26
|
+
|
|
27
|
+
async.schedule_methods
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def schedule_methods
|
|
33
|
+
|
|
34
|
+
if @timer
|
|
35
|
+
@timer.cancel
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
now = Time.now
|
|
39
|
+
|
|
40
|
+
loop do
|
|
41
|
+
(auton_id, delayed_method) = @schedule.shift
|
|
42
|
+
|
|
43
|
+
if auton_id
|
|
44
|
+
execute_in = delayed_method.execute_at - now
|
|
45
|
+
if execute_in <= 0
|
|
46
|
+
Celluloid::Actor["storage:%s" % auton_id].update do |state|
|
|
47
|
+
delayed = state.queue.delayed.shift
|
|
48
|
+
execute_in = delayed.execute_at - now
|
|
49
|
+
if execute_in <= 0
|
|
50
|
+
method = ScheduledMethod.new(delayed)
|
|
51
|
+
state.queue.to_execute << method
|
|
52
|
+
end
|
|
53
|
+
if delayed.every
|
|
54
|
+
delayed.execute_at += delayed.every
|
|
55
|
+
state.queue.add_delayed(delayed)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
@schedule.unshift [auton_id, delayed_method]
|
|
60
|
+
break
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
break
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
unless @schedule.empty?
|
|
68
|
+
to_wait = @schedule.first[1].execute_at - now
|
|
69
|
+
@timer = after(to_wait){async.schedule_methods}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
class AutonContext
|
|
3
|
+
|
|
4
|
+
def initialize auton_id
|
|
5
|
+
@auton_id = auton_id
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
attr_accessor :steps_to_schedule
|
|
9
|
+
|
|
10
|
+
def schedule_callback auton_id, method, parameters, callback_method
|
|
11
|
+
Celluloid::Actor[:nestene_core].schedule_step auton_id, method, parameters, @auton_id, callback_method
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def schedule_step name, parameters=[]
|
|
15
|
+
Celluloid::Actor[:nestene_core].schedule_step @auton_id, name, parameters
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def schedule_delayed_step delay, name, parameters=[]
|
|
19
|
+
Celluloid::Actor[:nestene_core].schedule_delayed_step @auton_id, delay, name, parameters
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def schedule_repeating_delayed_step every, delay, name, parameters=[]
|
|
23
|
+
Celluloid::Actor[:nestene_core].schedule_repeating_delayed_step @auton_id, every, delay, name, parameters
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def credentials
|
|
27
|
+
Celluloid::Actor[:nestene_core].get_credentials
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'nestene/delayed_method'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
require 'structure_mapper'
|
|
4
|
+
|
|
5
|
+
module Nestene
|
|
6
|
+
class AutonExecutionQueue
|
|
7
|
+
include StructureMapper::Hash
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
self.to_execute = []
|
|
11
|
+
self.executed = []
|
|
12
|
+
self.delayed = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_delayed_method name, parameters, delay, every = nil
|
|
16
|
+
delayed_method = DelayedMethod.new
|
|
17
|
+
delayed_method.uuid = SecureRandom.uuid
|
|
18
|
+
delayed_method.name = name
|
|
19
|
+
delayed_method.parameters = parameters
|
|
20
|
+
delayed_method.execute_at = Time.now + delay
|
|
21
|
+
delayed_method.every = every
|
|
22
|
+
add_delayed(delayed_method)
|
|
23
|
+
delayed_method
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def add_delayed delayed_method
|
|
27
|
+
delayed << delayed_method
|
|
28
|
+
delayed.sort_by! {|x| x.execute_at}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def remove_delayed_method method_uuid
|
|
33
|
+
delayed.delete_if{|m| m.uuid == method_uuid}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
attribute failed: Boolean
|
|
37
|
+
attribute to_execute: [ScheduledMethod]
|
|
38
|
+
attribute executed: [ExecutedMethod]
|
|
39
|
+
attribute currently_executing: ExecutingMethod
|
|
40
|
+
attribute delayed: [DelayedMethod]
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
class AutonState
|
|
3
|
+
|
|
4
|
+
include StructureMapper::Hash
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
self.queue=AutonExecutionQueue.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def state
|
|
11
|
+
if queue.currently_executing == nil
|
|
12
|
+
queue.failed ? :failed : :ready
|
|
13
|
+
else
|
|
14
|
+
:running
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attribute type: String
|
|
19
|
+
attribute serialized: {}
|
|
20
|
+
attribute queue: AutonExecutionQueue
|
|
21
|
+
|
|
22
|
+
def type_as_class
|
|
23
|
+
self.type ? Nestene::class_from_string(self.type) : nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
class DelayedMethod
|
|
3
|
+
include StructureMapper::Hash
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
self.parameters = []
|
|
7
|
+
self.scheduled_at = Time.now
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
attribute name: Symbol
|
|
11
|
+
attribute parameters: []
|
|
12
|
+
attribute uuid: String
|
|
13
|
+
attribute scheduled_at: Time
|
|
14
|
+
attribute execute_at: Time
|
|
15
|
+
attribute every: Float
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
class ExecutedMethod
|
|
3
|
+
include StructureMapper::Hash
|
|
4
|
+
|
|
5
|
+
def initialize(executing_method = nil)
|
|
6
|
+
self.parameters = []
|
|
7
|
+
if executing_method
|
|
8
|
+
self.name = executing_method.name
|
|
9
|
+
self.parameters = executing_method.parameters
|
|
10
|
+
self.uuid = executing_method.uuid
|
|
11
|
+
self.scheduled_at = executing_method.scheduled_at
|
|
12
|
+
self.started_at = executing_method.started_at
|
|
13
|
+
self.duration = Time.now - executing_method.started_at
|
|
14
|
+
self.callback = executing_method.callback
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attribute name: Symbol
|
|
19
|
+
attribute parameters: []
|
|
20
|
+
attribute uuid: String
|
|
21
|
+
attribute result: {}
|
|
22
|
+
attribute error: Exception
|
|
23
|
+
attribute scheduled_at: Time
|
|
24
|
+
attribute started_at: Time
|
|
25
|
+
attribute duration: Float
|
|
26
|
+
attribute callback: Callback
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
class ExecutingMethod
|
|
3
|
+
include StructureMapper::Hash
|
|
4
|
+
|
|
5
|
+
def initialize(scheduled_method = nil)
|
|
6
|
+
if scheduled_method
|
|
7
|
+
self.name = scheduled_method.name
|
|
8
|
+
self.parameters = scheduled_method.parameters
|
|
9
|
+
self.uuid = scheduled_method.uuid
|
|
10
|
+
self.scheduled_at = scheduled_method.scheduled_at
|
|
11
|
+
self.started_at = Time.now
|
|
12
|
+
self.callback = scheduled_method.callback
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attribute name: Symbol
|
|
17
|
+
attribute parameters: []
|
|
18
|
+
attribute uuid: String
|
|
19
|
+
attribute scheduled_at: Time
|
|
20
|
+
attribute started_at: Time
|
|
21
|
+
attribute callback: Callback
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
|
|
3
|
+
class ExecutionError
|
|
4
|
+
include StructureMapper::Hash
|
|
5
|
+
|
|
6
|
+
def initialize(exception = nil)
|
|
7
|
+
|
|
8
|
+
if exception
|
|
9
|
+
self.message = exception.message
|
|
10
|
+
self.type = exception.class.name
|
|
11
|
+
self.backtrace = exception.backtrace
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attribute message: String
|
|
16
|
+
attribute type: String
|
|
17
|
+
attribute backtrace: [String]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def to_exception
|
|
21
|
+
exception = Nestene.class_from_string(type).new(message)
|
|
22
|
+
exception.set_backtrace self.backtrace
|
|
23
|
+
exception
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class Exception
|
|
30
|
+
|
|
31
|
+
def to_structure
|
|
32
|
+
Nestene::ExecutionError.new(self).to_structure
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.from_structure structure
|
|
36
|
+
structure ? Nestene::ExecutionError.from_structure(structure).to_exception : nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Nestene
|
|
2
|
+
class ScheduledMethod
|
|
3
|
+
include StructureMapper::Hash
|
|
4
|
+
|
|
5
|
+
def initialize(delayed_method = nil)
|
|
6
|
+
self.parameters = []
|
|
7
|
+
self.scheduled_at = Time.now
|
|
8
|
+
if delayed_method
|
|
9
|
+
self.uuid = delayed_method.uuid
|
|
10
|
+
self.name = delayed_method.name
|
|
11
|
+
self.parameters = delayed_method.parameters
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attribute name: Symbol
|
|
16
|
+
attribute parameters: []
|
|
17
|
+
attribute uuid: String
|
|
18
|
+
attribute scheduled_at: Time
|
|
19
|
+
attribute callback: Callback
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Nestene
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FileNameConverter
|
|
7
|
+
|
|
8
|
+
def key_to_file_name(key)
|
|
9
|
+
key.gsub(/[^a-zA-Z0-9]/){|x| "_%x" % x.ord}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def file_name_to_key file_name
|
|
13
|
+
file_name.gsub(/_[a-zA-Z0-9]{2}/){|x| x[1..-1].hex.chr}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class DiskStorage
|
|
19
|
+
|
|
20
|
+
def initialize(dir)
|
|
21
|
+
@dir=dir
|
|
22
|
+
@converter = FileNameConverter.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def list
|
|
26
|
+
entries = Dir.entries(@dir)
|
|
27
|
+
entries.delete('.')
|
|
28
|
+
entries.delete('..')
|
|
29
|
+
entries.delete('__credentials__')
|
|
30
|
+
entries.map{|fn| @converter.file_name_to_key(fn)}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def store(key, value)
|
|
34
|
+
final_name = "%s/%s" % [@dir,@converter.key_to_file_name(key)]
|
|
35
|
+
tmp_name = "%s.temp" % final_name
|
|
36
|
+
File.open(tmp_name,"w") do |f|
|
|
37
|
+
f.write(JSON.pretty_generate(value))
|
|
38
|
+
end
|
|
39
|
+
File.rename(tmp_name, final_name)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def load(key)
|
|
43
|
+
file_name = "%s/%s" % [@dir,@converter.key_to_file_name(key)]
|
|
44
|
+
if File.exist?(file_name)
|
|
45
|
+
File.open(file_name,"r"){|f| JSON.parse(f.read)}
|
|
46
|
+
else
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class MemoryStorage
|
|
54
|
+
|
|
55
|
+
def initialize
|
|
56
|
+
@storage = {}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def list
|
|
60
|
+
@storage.keys
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def load(key)
|
|
64
|
+
@storage[key]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def store(key, value)
|
|
68
|
+
@storage[key] = value
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require 'sinatra/base'
|
|
2
|
+
require 'haml'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Nestene
|
|
6
|
+
module Ui
|
|
7
|
+
class App < Sinatra::Base
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
get '/autons.json' do
|
|
11
|
+
content_type :json
|
|
12
|
+
Celluloid::Actor[:nestene_core].auton_names.to_json
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
get '/credentials' do
|
|
16
|
+
content_type :json
|
|
17
|
+
Celluloid::Actor[:nestene_core].get_credentials.to_json
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
post '/credentials' do
|
|
21
|
+
content_type :json
|
|
22
|
+
begin
|
|
23
|
+
credentials = JSON.parse(request.body.read)
|
|
24
|
+
auton_id = Celluloid::Actor[:nestene_core].set_credentials credentials
|
|
25
|
+
status 200
|
|
26
|
+
rescue Exception => e
|
|
27
|
+
puts e
|
|
28
|
+
status 500
|
|
29
|
+
{message: e.message}.to_json
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
post '/autons' do
|
|
34
|
+
content_type :json
|
|
35
|
+
begin
|
|
36
|
+
type = JSON.parse(request.body.read).fetch('auton_type')
|
|
37
|
+
raise "auton_type not set" unless type
|
|
38
|
+
auton_id = Celluloid::Actor[:nestene_core].create_auton type
|
|
39
|
+
status 201
|
|
40
|
+
{auton_id: auton_id}.to_json
|
|
41
|
+
rescue Exception => e
|
|
42
|
+
status 500
|
|
43
|
+
{message: e.message}.to_json
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
get '/' do
|
|
49
|
+
@auton_names = Celluloid::Actor[:nestene_core].auton_names
|
|
50
|
+
haml :index
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
get '/auton/create' do
|
|
54
|
+
haml :auton_form
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
get '/auton/:id' do
|
|
58
|
+
@auton_id = params[:id]
|
|
59
|
+
@auton_state = Celluloid::Actor[:nestene_core].get_state(@auton_id)
|
|
60
|
+
haml :auton
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
get '/auton/:id/schedule_step' do
|
|
64
|
+
@auton_id = params[:id]
|
|
65
|
+
@auton_state = Celluloid::Actor[:nestene_core].get_state(@auton_id)
|
|
66
|
+
auton_type = @auton_state.type_as_class
|
|
67
|
+
@available_methods = auton_type.instance_methods(false).map{|name| auton_type.instance_method(name)}
|
|
68
|
+
@number_of_params = 0
|
|
69
|
+
haml :schedule_step
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
post '/auton/:id/schedule_step' do
|
|
73
|
+
parameters = params[:parameters] || []
|
|
74
|
+
step_name = params[:step_name]
|
|
75
|
+
|
|
76
|
+
@auton_id = params[:id]
|
|
77
|
+
@auton_state = Celluloid::Actor[:nestene_core].get_state(@auton_id)
|
|
78
|
+
auton_type = @auton_state.type_as_class
|
|
79
|
+
@available_methods = auton_type.instance_methods(false).sort.map{|name| auton_type.instance_method(name)}
|
|
80
|
+
|
|
81
|
+
method = @available_methods.find{|m| m.name.to_s == step_name}
|
|
82
|
+
|
|
83
|
+
if method && method.arity == parameters.size
|
|
84
|
+
step_id = Celluloid::Actor[:nestene_core].schedule_step(params[:id],step_name, parameters)
|
|
85
|
+
headers['X-AUTON-STEP-ID'] = step_id
|
|
86
|
+
redirect '/auton/%s' % params[:id]
|
|
87
|
+
else
|
|
88
|
+
@method = method
|
|
89
|
+
@number_of_params = method ? method.arity : 0
|
|
90
|
+
@step_name = step_name
|
|
91
|
+
haml :schedule_step
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
post '/auton/create' do
|
|
96
|
+
Celluloid::Actor[:nestene_core].create_auton params[:auton_type]
|
|
97
|
+
redirect '/'
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
var nestene = angular.module('nestene', ['JSONedit']);
|
|
2
|
+
|
|
3
|
+
nestene.controller('AutonsController', function($scope, $http, $timeout) {
|
|
4
|
+
$scope.autons=[];
|
|
5
|
+
|
|
6
|
+
$scope.getAutons = function() {
|
|
7
|
+
var autonsPromise = $http.get("autons.json");
|
|
8
|
+
autonsPromise.success(function(data, status, headers, config) {
|
|
9
|
+
$scope.autons = data;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
autonsPromise.error(function(data, status, headers, config) {
|
|
13
|
+
$.bootstrapGrowl("getting autons failed!", { type: 'danger' });
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
$scope.intervalFunction = function() {
|
|
18
|
+
$timeout(function() {
|
|
19
|
+
$scope.getAutons();
|
|
20
|
+
$scope.intervalFunction();
|
|
21
|
+
}, 1000);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
$scope.intervalFunction();
|
|
25
|
+
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
nestene.controller('CreateAutonFormController', function($scope,$http) {
|
|
29
|
+
$scope.autonType = '';
|
|
30
|
+
$scope.createAuton = function() {
|
|
31
|
+
var postPromise = $http.post("autons",{auton_type: $scope.autonType});
|
|
32
|
+
postPromise.success(function(data, status, headers, config) {
|
|
33
|
+
$.bootstrapGrowl("Created "+data['auton_id'], { type: 'success' });
|
|
34
|
+
});
|
|
35
|
+
postPromise.error(function(data, status, headers, config) {
|
|
36
|
+
$.bootstrapGrowl("Could not create Auton: "+data['message'], { type: 'error' });
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
nestene.controller('CredentialsController', function($scope,$http) {
|
|
42
|
+
$scope.credentials={};
|
|
43
|
+
$scope.loaded = false;
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
$scope.loadCredentials = function() {
|
|
47
|
+
var getPromise = $http.get("credentials");
|
|
48
|
+
getPromise.success(function(data, status, headers, config) {
|
|
49
|
+
$scope.credentials = data;
|
|
50
|
+
$scope.loaded = true;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
getPromise.error(function(data, status, headers, config) {
|
|
54
|
+
$.bootstrapGrowl("getting credentials failed!", { type: 'danger' });
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
$scope.loadCredentials();
|
|
59
|
+
|
|
60
|
+
$scope.storeCredentials = function() {
|
|
61
|
+
var postPromise = $http.post("credentials",$scope.credentials);
|
|
62
|
+
postPromise.success(function(data, status, headers, config) {
|
|
63
|
+
$.bootstrapGrowl("Credentials saved", { type: 'success' });
|
|
64
|
+
});
|
|
65
|
+
postPromise.error(function(data, status, headers, config) {
|
|
66
|
+
$.bootstrapGrowl("Could not save credentials", { type: 'danger' });
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(a,b){"use strict";b.module("ui.sortable",[]).value("uiSortableConfig",{}).directive("uiSortable",["uiSortableConfig","$timeout","$log",function(a,c,d){return{require:"?ngModel",link:function(e,f,g,h){function i(a,b){return b&&"function"==typeof b?function(c,d){a(c,d),b(c,d)}:a}function j(a,b){var c=a.sortable("option","helper");return"clone"===c||"function"==typeof c&&b.item.sortable.isCustomHelperUsed()}var k,l={},m={receive:null,remove:null,start:null,stop:null,update:null},n={helper:null};return b.extend(l,a,e.$eval(g.uiSortable)),b.element.fn&&b.element.fn.jquery?(h?(e.$watch(g.ngModel+".length",function(){c(function(){f.data("ui-sortable")&&f.sortable("refresh")})}),m.start=function(a,b){b.item.sortable={index:b.item.index(),cancel:function(){b.item.sortable._isCanceled=!0},isCanceled:function(){return b.item.sortable._isCanceled},isCustomHelperUsed:function(){return!!b.item.sortable._isCustomHelperUsed},_isCanceled:!1,_isCustomHelperUsed:b.item.sortable._isCustomHelperUsed}},m.activate=function(){k=f.contents();var a=f.sortable("option","placeholder");if(a&&a.element&&"function"==typeof a.element){var c=a.element();c=b.element(c);var d=f.find('[class="'+c.attr("class")+'"]');k=k.not(d)}},m.update=function(a,b){b.item.sortable.received||(b.item.sortable.dropindex=b.item.index(),b.item.sortable.droptarget=b.item.parent(),f.sortable("cancel")),j(f,b)&&!b.item.sortable.received&&(k=k.not(k.last())),k.appendTo(f),b.item.sortable.received&&(k=null),b.item.sortable.received&&!b.item.sortable.isCanceled()&&e.$apply(function(){h.$modelValue.splice(b.item.sortable.dropindex,0,b.item.sortable.moved)})},m.stop=function(a,b){!b.item.sortable.received&&"dropindex"in b.item.sortable&&!b.item.sortable.isCanceled()?e.$apply(function(){h.$modelValue.splice(b.item.sortable.dropindex,0,h.$modelValue.splice(b.item.sortable.index,1)[0])}):"dropindex"in b.item.sortable&&!b.item.sortable.isCanceled()||j(f,b)||k.appendTo(f),k=null},m.receive=function(a,b){b.item.sortable.received=!0},m.remove=function(a,b){"dropindex"in b.item.sortable||(f.sortable("cancel"),b.item.sortable.cancel()),b.item.sortable.isCanceled()||e.$apply(function(){b.item.sortable.moved=h.$modelValue.splice(b.item.sortable.index,1)[0]})},n.helper=function(a){return a&&"function"==typeof a?function(b,c){var d=a(b,c);return c.sortable._isCustomHelperUsed=c!==d,d}:a},e.$watch(g.uiSortable,function(a){f.data("ui-sortable")&&b.forEach(a,function(a,b){m[b]?("stop"===b&&(a=i(a,function(){e.$apply()})),a=i(m[b],a)):n[b]&&(a=n[b](a)),f.sortable("option",b,a)})},!0),b.forEach(m,function(a,b){l[b]=i(a,l[b])})):d.info("ui.sortable: ngModel not provided!",f),void f.sortable(l)):void d.error("ui.sortable: jQuery should be included before AngularJS!")}}}])}(window,window.angular);
|