tap-server 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/History +5 -0
  2. data/cmd/server.rb +36 -8
  3. data/lib/tap/controller/rest_routes.rb +77 -0
  4. data/lib/tap/controller/utils.rb +29 -0
  5. data/lib/tap/controller.rb +244 -145
  6. data/lib/tap/controllers/app.rb +97 -55
  7. data/lib/tap/controllers/data.rb +132 -0
  8. data/lib/tap/controllers/schema.rb +137 -223
  9. data/lib/tap/controllers/server.rb +70 -27
  10. data/lib/tap/server/data.rb +178 -0
  11. data/lib/tap/server/runner.rb +71 -0
  12. data/lib/tap/server/server_error.rb +35 -0
  13. data/lib/tap/server.rb +60 -275
  14. data/lib/tap/tasks/echo.rb +39 -6
  15. data/lib/tap/tasks/render.rb +65 -0
  16. data/public/stylesheets/tap.css +15 -2
  17. data/views/configurable/_config.erb +1 -0
  18. data/views/configurable/_configs.erb +28 -0
  19. data/views/configurable/_flag.erb +2 -0
  20. data/views/configurable/_list_select.erb +8 -0
  21. data/views/configurable/_select.erb +6 -0
  22. data/views/configurable/_switch.erb +2 -0
  23. data/views/layout.erb +1 -1
  24. data/views/object/obj.erb +1 -0
  25. data/views/tap/controllers/app/_action.erb +3 -0
  26. data/views/tap/controllers/app/build.erb +18 -0
  27. data/views/tap/controllers/app/enque.erb +13 -0
  28. data/views/tap/controllers/app/info.erb +20 -7
  29. data/views/tap/controllers/data/_controls.erb +21 -0
  30. data/views/tap/controllers/data/_index_entry.erb +1 -0
  31. data/views/tap/controllers/data/_upload.erb +8 -0
  32. data/views/tap/controllers/data/entry.erb +8 -0
  33. data/views/tap/controllers/data/index.erb +14 -0
  34. data/views/tap/controllers/schema/_build.erb +6 -0
  35. data/views/tap/controllers/schema/_index_entry.erb +6 -0
  36. data/views/tap/controllers/schema/entry.erb +135 -0
  37. data/views/tap/controllers/schema/join.erb +6 -4
  38. data/views/tap/controllers/schema/task.erb +6 -0
  39. data/views/tap/controllers/server/access.erb +4 -0
  40. data/views/tap/controllers/server/admin.erb +21 -0
  41. data/views/tap/controllers/server/help.erb +23 -0
  42. data/views/tap/controllers/server/index.erb +43 -3
  43. data/views/tap/task/input.erb +17 -0
  44. data/views/tap/tasks/load/input.erb +11 -0
  45. metadata +35 -17
  46. data/lib/tap/server_error.rb +0 -34
  47. data/lib/tap/support/persistence.rb +0 -71
  48. data/lib/tap/tasks/server.rb +0 -30
  49. data/views/tap/controllers/app/index.erb +0 -44
  50. data/views/tap/controllers/schema/config/default.erb +0 -4
  51. data/views/tap/controllers/schema/config/flag.erb +0 -3
  52. data/views/tap/controllers/schema/config/switch.erb +0 -6
  53. data/views/tap/controllers/schema/configurations.erb +0 -27
  54. data/views/tap/controllers/schema/node.erb +0 -47
  55. data/views/tap/controllers/schema/preview.erb +0 -3
  56. data/views/tap/controllers/schema/round.erb +0 -30
  57. data/views/tap/controllers/schema/schema.erb +0 -28
  58. data/views/tap/tasks/echo/result.html +0 -1
@@ -1,59 +1,109 @@
1
1
  require 'tap/controller'
2
- require 'rack/mime'
3
- require 'time'
2
+ require 'tap/controllers/schema'
4
3
 
5
4
  module Tap
6
5
  module Controllers
7
6
 
8
- # ::controller
7
+ # :startdoc::controller builds and runs workflows
9
8
  class App < Tap::Controller
10
- set :default_layout, 'layout.erb'
11
-
12
- def call(env)
13
- # serve public files before actions
14
- server = env['tap.server'] ||= Tap::Server.new
15
-
16
- if path = server.search(:public, env['PATH_INFO'])
17
- content = File.read(path)
18
- headers = {
19
- "Last-Modified" => [File.mtime(path).httpdate],
20
- "Content-Type" => [Rack::Mime.mime_type(File.extname(path), 'text/plain')],
21
- "Content-Length" => [content.size.to_s]
22
- }
9
+ set :default_action, :info
23
10
 
24
- [200, headers, [content]]
25
- else
26
- super
11
+ nest :schema, Schema do
12
+ def dispatch(route)
13
+ route.unshift rest_action(route)
14
+ super(route)
27
15
  end
28
16
  end
29
-
30
- def index
31
- env_names = {}
32
- server.env.minimap.each do |name, environment|
33
- env_names[environment] = name
34
- end
35
-
36
- render('index.erb', :locals => {:env => server.env, :env_names => env_names}, :layout => true)
17
+
18
+ # Returns the state of app.
19
+ def state
20
+ app.state.to_s
37
21
  end
38
22
 
23
+ # Returns the controls and current application info.
39
24
  def info
25
+ render 'info.erb', :locals => {
26
+ :actions => [:run, :stop, :terminate, :reset],
27
+ }, :layout => true
28
+ end
29
+
30
+ # Runs app on a separate thread (on post).
31
+ def run
40
32
  if request.post?
41
- app.info
33
+ server.thread ||= Thread.new { app.run; server.thread = nil; }
34
+ end
35
+
36
+ redirect uri(:info)
37
+ end
38
+
39
+ def reset
40
+ app.reset if request.post?
41
+ redirect uri(:info)
42
+ end
43
+
44
+ # Stops app (on post).
45
+ def stop
46
+ app.stop if request.post?
47
+ redirect uri(:info)
48
+ end
49
+
50
+ # Teminates app (on post).
51
+ def terminate
52
+ app.terminate if request.post?
53
+ redirect uri(:info)
54
+ end
55
+
56
+ def build
57
+ schema = request[:schema] || server.data.read(:schema, request[:id])
58
+
59
+ unless request.post?
60
+ return render('build.erb', :schema => schema, :layout => true)
61
+ end
62
+
63
+ schema = Tap::Schema.load(schema).resolve! do |type, key, data|
64
+ server.env.manifest(type)[key]
65
+ end.validate!
66
+
67
+ if request[:reset] == "on"
68
+ app.reset
69
+ end
70
+
71
+ tasks.merge!(server.env.build(schema, app))
72
+
73
+ if request[:run] == "on"
74
+ run
42
75
  else
43
- render('info.erb', :locals => {:update => true, :content => app.info}, :layout => true)
76
+ redirect uri(:enque)
44
77
  end
45
78
  end
46
-
47
- #--
48
- # Currently tail is hard-coded to tail the server log only.
49
- def tail(id=nil)
50
- begin
51
- path = root.subpath(:log, 'server.log')
52
- raise unless File.exists?(path)
53
- rescue
54
- raise Tap::ServerError.new("invalid path", 404)
79
+
80
+ def enque
81
+ unless request.post?
82
+ return render('enque.erb', :layout => true)
55
83
  end
56
-
84
+
85
+ queue = if request[:load]
86
+ YAML.load(request[:queue] || "{}")
87
+ else
88
+ request[:queue] || {}
89
+ end
90
+
91
+ queue.each do |(key, inputs)|
92
+ unless task = tasks[key]
93
+ raise "no task for: #{key}"
94
+ end
95
+ app.enq(task, *inputs)
96
+ end
97
+
98
+ redirect uri(:info)
99
+ end
100
+
101
+ def tail(id)
102
+ unless data.has?("#{id}.log")
103
+ raise Tap::ServerError.new("invalid id: #{id}", 404)
104
+ end
105
+
106
+ path = data.path("#{id}.log")
57
107
  pos = request['pos'].to_i
58
108
  if pos > File.size(path)
59
109
  raise Tap::ServerError.new("tail position out of range (try update)", 500)
@@ -75,23 +125,15 @@ module Tap
75
125
  }, :layout => true)
76
126
  end
77
127
  end
78
-
79
- def run
80
- Thread.new { app.run }
81
- redirect("/app/tail")
82
- end
83
-
84
- def stop
85
- app.stop
86
- redirect("/app/info")
87
- end
88
-
89
- def terminate
90
- app.terminate
91
- redirect("/app/info")
128
+
129
+ protected
130
+
131
+ def tasks
132
+ app.cache[:tasks] ||= {}
92
133
  end
93
-
94
- def help(key=nil)
134
+
135
+ def app
136
+ server.app
95
137
  end
96
138
  end
97
139
  end
@@ -0,0 +1,132 @@
1
+ require 'tap/controller'
2
+
3
+ module Tap
4
+ module Controllers
5
+ # ::controller
6
+ class Data < Tap::Controller
7
+ include RestRoutes
8
+ include Utils
9
+
10
+ set :default_layout, 'layout.erb'
11
+
12
+ # GET /projects
13
+ def index
14
+ render 'index.erb', :layout => true
15
+ end
16
+
17
+ # GET /projects/id
18
+ # GET /projects?id=id&as=
19
+ def show(id)
20
+ case request['as']
21
+ when 'preview'
22
+ response.headers['Content-Type'] = 'text/plain'
23
+ data.read(type, id)
24
+
25
+ when 'download'
26
+ unless path = data.find(type, id)
27
+ raise "unknown #{type}: #{id.inspect}"
28
+ end
29
+
30
+ download(path)
31
+ else
32
+ display(id)
33
+ end
34
+ end
35
+
36
+ # POST /projects/id
37
+ # POST /projects?id=id
38
+ # POST /projects?type=
39
+ def create(id)
40
+ if id == "new"
41
+ id = data.next_id(type).to_s
42
+ end
43
+
44
+ data.create(type, id) {|io| io << parse_entry }
45
+ redirect uri(id)
46
+ end
47
+
48
+ # PUT /projects/id
49
+ # POST /projects/id?_method=put
50
+ # POST /projects?_method=put&_action=select&id=id
51
+ def update(id)
52
+ data.update(type, id) {|io| io << parse_entry }
53
+ redirect uri(id)
54
+ end
55
+
56
+ # DELETE /projects/id
57
+ # POST /projects/id?_method=delete
58
+ # POST /projects?_method=put&id=id
59
+ def destroy(id)
60
+ data.destroy(type, id)
61
+ redirect uri
62
+ end
63
+
64
+ def upload(id=nil)
65
+ check_id(id)
66
+ data.import(type, request[type], id)
67
+ redirect uri
68
+ end
69
+
70
+ def select(ids=[])
71
+ data.cache[type] = ids
72
+ redirect uri
73
+ end
74
+
75
+ # Renames id to request['name'] in the schema data.
76
+ def rename(id)
77
+ redirect data.move(type, id, request['new_id'])
78
+ end
79
+
80
+ def duplicate(id)
81
+ redirect data.copy(type, id, request['new_id'] || "#{id}_copy")
82
+ end
83
+
84
+ # Helper methods
85
+ protected
86
+
87
+ def type
88
+ :data
89
+ end
90
+
91
+ def data
92
+ server.data
93
+ end
94
+
95
+ #--
96
+ # args remains an array, ie methods can take one or no inputs (but note
97
+ # that if id is specified as an array, methods can receive and array of
98
+ # ids.)
99
+ def dispatch(route)
100
+ action, *args = route
101
+
102
+ if args.empty?
103
+ if id = request['id']
104
+ args << id
105
+ end
106
+ else
107
+ args = [File.join(*args)]
108
+ end
109
+
110
+ args.unshift(action)
111
+ super(args)
112
+ end
113
+
114
+ def display(id)
115
+ render "entry.erb", :locals => {
116
+ :id => id,
117
+ :content => data.read(type, id)
118
+ }, :layout => true
119
+ end
120
+
121
+ def parse_entry
122
+ request[type]
123
+ end
124
+
125
+ def check_id(id)
126
+ if id == "new"
127
+ raise "reserved id: #{id.inspect}"
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end