-
Notifications
You must be signed in to change notification settings - Fork 1
/
handlerUpdate.go
267 lines (232 loc) · 10.3 KB
/
handlerUpdate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
// Copyright (c) 2016 OpenM++
// This code is licensed under the MIT license (see LICENSE.txt for details)
package main
import (
"net/http"
"github.com/openmpp/go/ompp/db"
"github.com/openmpp/go/ompp/omppLog"
)
// profileReplaceHandler replace existing or insert new profile and all profile options.
// PATCH /api/model/:model/profile
// Json content: same as return of GET /api/model/:model/profile/:profile.
// Existing profile rows deleted from database and replaced with new content.
func profileReplaceHandler(w http.ResponseWriter, r *http.Request) {
dn := getRequestParam(r, "model")
var pm db.ProfileMeta
if !jsonRequestDecode(w, r, true, &pm) {
return // error at json decode, response done with http error
}
// replace profile in model catalog
ok, err := theCatalog.ReplaceProfile(dn, &pm)
if err != nil {
omppLog.Log(err.Error())
http.Error(w, "Profile update failed: "+pm.Name, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/profile/"+pm.Name) // respond with model and profile location
w.Header().Set("Content-Type", "text/plain")
}
}
// profileDeleteHandler delete profile and all profile options:
// DELETE /api/model/:model/profile/:profile
// If multiple models with same name exist then result is undefined.
// If no such profile exist in database then no error, empty operation.
func profileDeleteHandler(w http.ResponseWriter, r *http.Request) {
dn := getRequestParam(r, "model")
profile := getRequestParam(r, "profile")
ok, err := theCatalog.DeleteProfile(dn, profile)
if err != nil {
http.Error(w, "Profile delete failed "+dn+": "+profile, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/profile/"+profile)
w.Header().Set("Content-Type", "text/plain")
}
}
// profileOptionReplaceHandler insert new or replace existsing profile and profile option key-value:
// POST /api/model/:model/profile/:profile/key/:key/value/:value
// If multiple models with same name exist then result is undefined.
// If no such profile or option exist in database then new profile and option inserted.
func profileOptionReplaceHandler(w http.ResponseWriter, r *http.Request) {
dn := getRequestParam(r, "model")
profile := getRequestParam(r, "profile")
key := getRequestParam(r, "key")
val := getRequestParam(r, "value")
ok, err := theCatalog.ReplaceProfileOption(dn, profile, key, val)
if err != nil {
http.Error(w, "Profile option update failed: "+profile+": "+key, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/profile/"+profile+"/key/"+key)
w.Header().Set("Content-Type", "text/plain")
}
}
// profileOptionDeleteHandler delete profile option key-value pair:
// DELETE /api/model/:model/profile/:profile/key/:key
// If multiple models with same name exist then result is undefined.
// If no such profile or profile option key exist in database then no error, empty operation.
func profileOptionDeleteHandler(w http.ResponseWriter, r *http.Request) {
dn := getRequestParam(r, "model")
profile := getRequestParam(r, "profile")
key := getRequestParam(r, "key")
ok, err := theCatalog.DeleteProfileOption(dn, profile, key)
if err != nil {
http.Error(w, "Profile option delete failed: "+profile+": "+key, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/profile/"+profile+"/key/"+key)
w.Header().Set("Content-Type", "text/plain")
}
}
// runDeleteHandler delete model run including output table values and run input parameters
// by model digest-or-name and run digest-or-stamp-or-name:
// DELETE /api/model/:model/run/:run
// If multiple models with same name exist then result is undefined.
// If multiple runs with same stamp or name exist then result is undefined.
// If no such model run exist in database then no error, empty operation.
func runDeleteHandler(w http.ResponseWriter, r *http.Request) {
dn := getRequestParam(r, "model")
rdsn := getRequestParam(r, "run")
// delete model run
ok, err := theCatalog.DeleteRun(dn, rdsn)
if err != nil {
http.Error(w, "Model run delete failed "+dn+": "+rdsn, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/run/"+rdsn)
w.Header().Set("Content-Type", "text/plain")
}
}
// runTextMergeHandler merge model run text (description and notes) and run parameter value notes into database.
// PATCH /api/run/text
// Model can be identified by digest or name and model run also identified by run digest-or-stamp-or-name.
// If multiple models with same name exist then result is undefined.
// If multiple runs with same stamp or name exist then result is undefined.
// If no such model run exist in database then no error, empty operation.
func runTextMergeHandler(w http.ResponseWriter, r *http.Request) {
// decode json run "public" metadata
var rp db.RunPub
if !jsonRequestDecode(w, r, true, &rp) {
return // error at json decode, response done with http error
}
// update run text in model catalog
ok, dn, rdsn, err := theCatalog.UpdateRunText(&rp)
if err != nil {
omppLog.Log(err.Error())
http.Error(w, "Model run update failed "+dn+": "+rdsn, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/run/"+rdsn)
w.Header().Set("Content-Type", "text/plain")
}
}
// runParameterTextMergeHandler do merge (insert or update) run parameter(s) value notes, array of parameters expected.
// PATCH /api/model/:model/run/:run/parameter-text
// Model can be identified by digest or name and model run also identified by run digest-or-stamp-or-name.
// If multiple models with same name exist then result is undefined.
// If multiple runs with same stamp or name exist then result is undefined.
// If model run does not exist then return error.
// Input json must be array of ParamRunSetTxtPub,
// if parameters text array is empty then nothing updated, it is empty operation return is success
func runParameterTextMergeHandler(w http.ResponseWriter, r *http.Request) {
// url or query parameters
dn := getRequestParam(r, "model") // model digest-or-name
rdsn := getRequestParam(r, "run") // run digest-or-stamp-or-name
// decode json parameter value notes
var pvtLst []db.ParamRunSetTxtPub
if !jsonRequestDecode(w, r, true, &pvtLst) {
return // error at json decode, response done with http error
}
// update run parameter(s) value notes in model catalog
ok, err := theCatalog.UpdateRunParameterText(dn, rdsn, pvtLst)
if err != nil {
omppLog.Log(err.Error())
http.Error(w, "Run parameter(s) value notes update failed "+dn+": "+rdsn+": "+err.Error(), http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/run/"+rdsn+"/parameter-text")
w.Header().Set("Content-Type", "text/plain")
}
}
// taskDeleteHandler do delete modeling task, task run history from database.
// DELETE /api/model/:model/task/:task
// Task run history deleted only from task_run_lst and task_run_set tables,
// it does not delete model runs or any model input sets (worksets).
// If multiple models with same name exist then result is undefined.
// If task does not exists in database then it is empty operation.
// If modeling task is running during delete then result is undefined and model may fail with database error.
func taskDeleteHandler(w http.ResponseWriter, r *http.Request) {
dn := getRequestParam(r, "model")
tn := getRequestParam(r, "task")
// delete modeling task
ok, err := theCatalog.DeleteTask(dn, tn)
if err != nil {
http.Error(w, "Task delete failed "+dn+": "+tn, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/task/"+tn)
w.Header().Set("Content-Type", "text/plain")
}
}
// taskDefReplaceHandler replace task definition: task text (description and notes) and task input worksets into database.
// PUT /api/task-new
// It does delete existing and insert new rows into task_txt and task_set db tables.
// If task does not exist then new task created.
// If task name is empty in json request then automatically generate unique task name.
// Json body expected to contain TaskDefPub, any other TaskPub data silently ignored.
// Model can be identified by digest or name and model run also identified by run digest-or-name.
// If multiple models with same name exist then result is undefined.
func taskDefReplaceHandler(w http.ResponseWriter, r *http.Request) {
taskDefUpdateHandler(w, r, true)
}
// taskDefMergeHandler merge task definition: task text (description and notes) and task input worksets into database.
// PATCH /api/task
// It does update existing or insert new rows into task_txt and task_set db tables.
// If task does not exist then new task created.
// If task name is empty in json request then automatically generate unique task name.
// Json body expected to contain TaskDefPub, any other TaskPub data silently ignored.
// Model can be identified by digest or name and model run also identified by run digest-or-name.
// If multiple models with same name exist then result is undefined.
func taskDefMergeHandler(w http.ResponseWriter, r *http.Request) {
taskDefUpdateHandler(w, r, false)
}
// taskDefUpdateHandler replace or merge task definition: task text (description and notes) and task input worksets into database.
// It does replace or merge task_txt and task_set db rows.
// If task does not exist then new task created.
func taskDefUpdateHandler(w http.ResponseWriter, r *http.Request, isReplace bool) {
// decode json run "public" metadata
var tpd db.TaskDefPub
if !jsonRequestDecode(w, r, true, &tpd) {
return // error at json decode, response done with http error
}
// if task name is empty then automatically generate name
if tpd.Name == "" {
ts, _ := theCatalog.getNewTimeStamp()
tpd.Name = "task_" + ts
}
// update task definition in model catalog
ok, dn, tn, err := theCatalog.UpdateTaskDef(isReplace, &tpd)
if err != nil {
omppLog.Log(err.Error())
http.Error(w, "Modeling task merge failed "+dn+": "+tn, http.StatusBadRequest)
return
}
if ok {
w.Header().Set("Content-Location", "/api/model/"+dn+"/task/"+tn)
jsonResponse(w, r,
struct {
Name string // task name
}{
Name: tn,
},
)
}
}