oration 0.0.2 → 0.0.3
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.
- data/templates/main.go +210 -0
- data/templates/main.py +160 -0
- metadata +6 -4
data/templates/main.go
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
// BEGIN CICERO-BOILERPLATE CODE
|
2
|
+
package CICERO_PKG_NAME
|
3
|
+
|
4
|
+
import (
|
5
|
+
"appengine"
|
6
|
+
"appengine/datastore"
|
7
|
+
"appengine/taskqueue"
|
8
|
+
"fmt"
|
9
|
+
"http"
|
10
|
+
"json"
|
11
|
+
"time"
|
12
|
+
)
|
13
|
+
|
14
|
+
type TaskInfo struct {
|
15
|
+
State string
|
16
|
+
StartTime datastore.Time
|
17
|
+
EndTime datastore.Time
|
18
|
+
}
|
19
|
+
|
20
|
+
type Text struct {
|
21
|
+
Content string
|
22
|
+
}
|
23
|
+
|
24
|
+
func init() {
|
25
|
+
http.HandleFunc("/task", taskRoute)
|
26
|
+
http.HandleFunc("/data", dataRoute)
|
27
|
+
http.HandleFunc("/compute", computeWorker)
|
28
|
+
http.HandleFunc("/", index)
|
29
|
+
}
|
30
|
+
|
31
|
+
func taskRoute(w http.ResponseWriter, r *http.Request) {
|
32
|
+
c := appengine.NewContext(r)
|
33
|
+
|
34
|
+
if r.Method == "GET" {
|
35
|
+
keyName := r.FormValue("task_id")
|
36
|
+
key := datastore.NewKey(c, "TaskInfo", keyName, 0, nil)
|
37
|
+
taskInfo := new(TaskInfo)
|
38
|
+
if err := datastore.Get(c, key, taskInfo); err == nil {
|
39
|
+
result := map[string]string{
|
40
|
+
"result": "success",
|
41
|
+
"state": taskInfo.State,
|
42
|
+
}
|
43
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
44
|
+
return
|
45
|
+
} else {
|
46
|
+
result := map[string]string{
|
47
|
+
"result": "failure",
|
48
|
+
"state": "not found",
|
49
|
+
}
|
50
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
51
|
+
return
|
52
|
+
}
|
53
|
+
} else if r.Method == "PUT" {
|
54
|
+
inputSource := r.FormValue("input1")
|
55
|
+
output := r.FormValue("output")
|
56
|
+
params := map[string][]string{
|
57
|
+
"input1": {inputSource},
|
58
|
+
"output": {output},
|
59
|
+
}
|
60
|
+
|
61
|
+
task := taskqueue.NewPOSTTask("/compute", params)
|
62
|
+
if newTask, err := taskqueue.Add(c, task, ""); err == nil {
|
63
|
+
result := map[string]string{
|
64
|
+
"result": "success",
|
65
|
+
"task_id": newTask.Name,
|
66
|
+
"output": output,
|
67
|
+
}
|
68
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
69
|
+
return
|
70
|
+
} else {
|
71
|
+
result := map[string]string{
|
72
|
+
"result": "failure",
|
73
|
+
"reason": err.String(),
|
74
|
+
}
|
75
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
76
|
+
return
|
77
|
+
}
|
78
|
+
} else {
|
79
|
+
// TODO - support deletion of tasks
|
80
|
+
http.Error(w, "method not supported", http.StatusInternalServerError)
|
81
|
+
return
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
func dataRoute(w http.ResponseWriter, r *http.Request) {
|
86
|
+
c := appengine.NewContext(r)
|
87
|
+
|
88
|
+
if r.Method == "GET" {
|
89
|
+
keyName := r.FormValue("location")
|
90
|
+
|
91
|
+
key := datastore.NewKey(c, "Text", keyName, 0, nil)
|
92
|
+
output := new(Text)
|
93
|
+
if err := datastore.Get(c, key, output); err != nil {
|
94
|
+
result := map[string]string{
|
95
|
+
"result": "failure",
|
96
|
+
"reason": err.String(),
|
97
|
+
}
|
98
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
99
|
+
return
|
100
|
+
}
|
101
|
+
|
102
|
+
if output.Content == "" {
|
103
|
+
result := map[string]string{
|
104
|
+
"result": "failure",
|
105
|
+
"reason": "key did not exist",
|
106
|
+
}
|
107
|
+
|
108
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
109
|
+
return
|
110
|
+
} else {
|
111
|
+
result := map[string]string{
|
112
|
+
"result": "success",
|
113
|
+
"output": output.Content,
|
114
|
+
}
|
115
|
+
|
116
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
117
|
+
return
|
118
|
+
}
|
119
|
+
} else if r.Method == "PUT" {
|
120
|
+
keyName := r.FormValue("location")
|
121
|
+
key := datastore.NewKey(c, "Text", keyName, 0, nil)
|
122
|
+
text := Text{
|
123
|
+
Content: r.FormValue("text"),
|
124
|
+
}
|
125
|
+
key, err := datastore.Put(c, key, &text)
|
126
|
+
if err == nil {
|
127
|
+
result := map[string]string{
|
128
|
+
"result": "success",
|
129
|
+
}
|
130
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
131
|
+
return
|
132
|
+
} else {
|
133
|
+
result := map[string]string{
|
134
|
+
"result": "failure",
|
135
|
+
"reason": err.String(),
|
136
|
+
}
|
137
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
138
|
+
return
|
139
|
+
}
|
140
|
+
} else if r.Method == "DELETE" {
|
141
|
+
keyName := r.FormValue("location")
|
142
|
+
|
143
|
+
key := datastore.NewKey(c, "Text", keyName, 0, nil)
|
144
|
+
err := datastore.Delete(c, key)
|
145
|
+
|
146
|
+
if err == nil {
|
147
|
+
result := map[string]string{
|
148
|
+
"result": "success",
|
149
|
+
}
|
150
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
151
|
+
return
|
152
|
+
} else {
|
153
|
+
result := map[string]string{
|
154
|
+
"result": "failure",
|
155
|
+
"reason": fmt.Sprintf("%s", err),
|
156
|
+
}
|
157
|
+
fmt.Fprintf(w, "%s", mapToJson(result))
|
158
|
+
return
|
159
|
+
}
|
160
|
+
} else {
|
161
|
+
http.Error(w, "method not supported", http.StatusInternalServerError)
|
162
|
+
return
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
func computeWorker(w http.ResponseWriter, r *http.Request) {
|
167
|
+
c := appengine.NewContext(r)
|
168
|
+
|
169
|
+
outputDest := r.FormValue("output")
|
170
|
+
|
171
|
+
keyName := outputDest // TODO - this should use the task id, not the output location
|
172
|
+
key := datastore.NewKey(c, "TaskInfo", keyName, 0, nil)
|
173
|
+
|
174
|
+
taskInfo := TaskInfo{
|
175
|
+
State: "started",
|
176
|
+
StartTime: datastore.SecondsToTime(time.Seconds()),
|
177
|
+
}
|
178
|
+
|
179
|
+
datastore.Put(c, key, &taskInfo)
|
180
|
+
|
181
|
+
outputTextKeyName := outputDest
|
182
|
+
outputTextKey := datastore.NewKey(c, "Text", outputTextKeyName, 0, nil)
|
183
|
+
outputText := Text{
|
184
|
+
Content: CICERO_FUNCTION_NAME(),
|
185
|
+
}
|
186
|
+
datastore.Put(c, outputTextKey, &outputText)
|
187
|
+
|
188
|
+
datastore.Get(c, key, &taskInfo)
|
189
|
+
taskInfo.State = "finished"
|
190
|
+
taskInfo.EndTime = datastore.SecondsToTime(time.Seconds())
|
191
|
+
datastore.Put(c, key, &taskInfo)
|
192
|
+
}
|
193
|
+
|
194
|
+
func index(w http.ResponseWriter, r *http.Request) {
|
195
|
+
fmt.Fprint(w, "Hello, world!")
|
196
|
+
}
|
197
|
+
|
198
|
+
func mapToJson(mapToConvert map[string]string) []byte {
|
199
|
+
jsonResult, err := json.Marshal(mapToConvert)
|
200
|
+
if err != nil {
|
201
|
+
fmt.Printf("json marshalling saw error: %s\n", err)
|
202
|
+
}
|
203
|
+
|
204
|
+
return jsonResult
|
205
|
+
}
|
206
|
+
|
207
|
+
// END CICERO-BOILERPLATE CODE
|
208
|
+
// BEGIN USER-PROVIDED FUNCTION
|
209
|
+
CICERO_FUNCTION_CONTENTS
|
210
|
+
// END USER-PROVIDED FUNCTION
|
data/templates/main.py
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
##### BEGIN CICERO-BOILERPLATE CODE #####
|
2
|
+
try:
|
3
|
+
import simplejson as json
|
4
|
+
except ImportError:
|
5
|
+
import json
|
6
|
+
|
7
|
+
import datetime
|
8
|
+
import logging
|
9
|
+
import os
|
10
|
+
import StringIO
|
11
|
+
import wsgiref.handlers
|
12
|
+
|
13
|
+
from google.appengine.api import taskqueue
|
14
|
+
|
15
|
+
from google.appengine.ext import db
|
16
|
+
from google.appengine.ext import webapp
|
17
|
+
from google.appengine.ext.webapp import template
|
18
|
+
from google.appengine.ext.webapp import util
|
19
|
+
|
20
|
+
import CICERO_PACKAGE_NAME
|
21
|
+
|
22
|
+
|
23
|
+
class TaskInfo(db.Model):
|
24
|
+
state = db.StringProperty()
|
25
|
+
start_time = db.DateTimeProperty()
|
26
|
+
end_time = db.DateTimeProperty()
|
27
|
+
|
28
|
+
|
29
|
+
class Text(db.Model):
|
30
|
+
content = db.TextProperty()
|
31
|
+
|
32
|
+
|
33
|
+
class TaskRoute(webapp.RequestHandler):
|
34
|
+
def get(self):
|
35
|
+
key_name = self.request.get('task_id')
|
36
|
+
task_info = TaskInfo.get_by_key_name(key_name)
|
37
|
+
result = {} # TODO - see if we can remove that
|
38
|
+
try:
|
39
|
+
result = {'result':'success', 'state':task_info.state}
|
40
|
+
except AttributeError:
|
41
|
+
result = {'result':'failure', 'state':'not found'}
|
42
|
+
|
43
|
+
self.response.out.write(json.dumps(result))
|
44
|
+
|
45
|
+
def put(self):
|
46
|
+
allowed_routes = ['CICERO_FUNCTION_NAME']
|
47
|
+
function = self.request.get('f')
|
48
|
+
input_source = self.request.get('input1')
|
49
|
+
json_data = {'f':function, 'input1':input_source}
|
50
|
+
|
51
|
+
output = ''
|
52
|
+
if self.request.get('output') == '':
|
53
|
+
key_length = 16 # for now, randomly generates keys 16 chars long
|
54
|
+
json_data['output'] = os.urandom(key_length) # TODO - does this work in app engine?
|
55
|
+
else:
|
56
|
+
json_data['output'] = str(self.request.get('output'))
|
57
|
+
output = str(json_data['output'])
|
58
|
+
|
59
|
+
if function in allowed_routes:
|
60
|
+
url = '/' + function
|
61
|
+
logging.debug('starting a request for url ' + url)
|
62
|
+
new_task = taskqueue.add(url=url, params={'data': json.dumps(json_data)})
|
63
|
+
# TODO - adding the task does not imply success - when does it not?
|
64
|
+
result = {'result':'success', 'task_id':new_task.name, 'output':output}
|
65
|
+
logging.debug('result of job with input data' + str(json_data) + ' was ' + str(result))
|
66
|
+
self.response.out.write(json.dumps(result))
|
67
|
+
else:
|
68
|
+
reason = 'Cannot add a task for function type ' + str(function)
|
69
|
+
result ={'result':'failure', 'reason':reason}
|
70
|
+
self.response.out.write(json.dumps(result))
|
71
|
+
|
72
|
+
def delete(self):
|
73
|
+
task_id = self.request.get('task_id')
|
74
|
+
task = taskqueue.Task(name=task_id)
|
75
|
+
q = taskqueue.Queue()
|
76
|
+
cancel_info = q.delete_tasks(task)
|
77
|
+
logging.debug('cancel_info is ' + str(cancel_info))
|
78
|
+
result = {'result':'unknown', 'reason':str(cancel_info)}
|
79
|
+
self.response.out.write(result)
|
80
|
+
|
81
|
+
|
82
|
+
class DataRoute(webapp.RequestHandler):
|
83
|
+
def get(self):
|
84
|
+
key_name = self.request.get('location')
|
85
|
+
output = Text.get_by_key_name(key_name)
|
86
|
+
result = {} # TODO - see if we can remove that
|
87
|
+
try:
|
88
|
+
result = {'result':'success', 'output':output.content}
|
89
|
+
except AttributeError:
|
90
|
+
result = {'result':'failure', 'reason':'key did not exist'}
|
91
|
+
|
92
|
+
self.response.out.write(json.dumps(result))
|
93
|
+
|
94
|
+
def put(self):
|
95
|
+
key_name = self.request.get('location')
|
96
|
+
output = Text(key_name = key_name)
|
97
|
+
output.content = self.request.get('text')
|
98
|
+
output.put()
|
99
|
+
|
100
|
+
result = {'result':'success'}
|
101
|
+
self.response.out.write(json.dumps(result))
|
102
|
+
|
103
|
+
def delete(self):
|
104
|
+
key_name = self.request.get('location')
|
105
|
+
|
106
|
+
text = Text(key_name = key_name)
|
107
|
+
result = {}
|
108
|
+
try:
|
109
|
+
text.delete()
|
110
|
+
result = {'result':'success'}
|
111
|
+
except Exception:
|
112
|
+
result = {'result':'failure', 'reason':'exception was thrown'} # TODO get the name of the exception here
|
113
|
+
|
114
|
+
self.response.out.write(result)
|
115
|
+
|
116
|
+
|
117
|
+
class ComputeWorker(webapp.RequestHandler):
|
118
|
+
def post(self):
|
119
|
+
raw_data = self.request.get('data')
|
120
|
+
json_data = json.loads(raw_data)
|
121
|
+
input_source = str(json_data['input1'])
|
122
|
+
output_dest = str(json_data['output'])
|
123
|
+
|
124
|
+
# TODO - this should use the task id, not the output location
|
125
|
+
task_info = TaskInfo(key_name = output_dest)
|
126
|
+
task_info.state = "started"
|
127
|
+
task_info.start_time = datetime.datetime.now()
|
128
|
+
task_info.put()
|
129
|
+
|
130
|
+
output_text = Text(key_name = output_dest)
|
131
|
+
output_text.content = str(CICERO_PACKAGE_AND_FUNCTION_NAME())
|
132
|
+
output_text.put()
|
133
|
+
|
134
|
+
task_info = TaskInfo.get_by_key_name(output_dest)
|
135
|
+
task_info.state = "finished"
|
136
|
+
task_info.end_time = datetime.datetime.now()
|
137
|
+
task_info.put()
|
138
|
+
|
139
|
+
|
140
|
+
class IndexPage(webapp.RequestHandler):
|
141
|
+
def get(self):
|
142
|
+
# TODO(cgb): write something nicer about oration here!
|
143
|
+
self.response.out.write("hello!")
|
144
|
+
|
145
|
+
def main():
|
146
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
147
|
+
application = webapp.WSGIApplication([('/task', TaskRoute),
|
148
|
+
('/data', DataRoute),
|
149
|
+
('/CICERO_FUNCTION_NAME', ComputeWorker),
|
150
|
+
('/', IndexPage),
|
151
|
+
],
|
152
|
+
debug=True)
|
153
|
+
util.run_wsgi_app(application)
|
154
|
+
|
155
|
+
|
156
|
+
if __name__ == '__main__':
|
157
|
+
main()
|
158
|
+
|
159
|
+
|
160
|
+
##### END CICERO-BOILERPLATE CODE #####
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Chris Bunch
|
@@ -15,7 +15,7 @@ autorequire: oration
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-25 00:00:00 -08:00
|
19
19
|
default_executable: oration
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -80,6 +80,8 @@ files:
|
|
80
80
|
- test/test_generator.rb
|
81
81
|
- test/test_oration.rb
|
82
82
|
- test/ts_all.rb
|
83
|
+
- templates/main.go
|
84
|
+
- templates/main.py
|
83
85
|
- LICENSE
|
84
86
|
has_rdoc: true
|
85
87
|
homepage: http://appscale.cs.ucsb.edu
|