tap-server 0.3.0 → 0.4.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.
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