1ceeedd0a656e395f1fa28caafe525dd270f8a35
[bottlenecks.git] / test-scheduler / server / src / rest / router.py
1 ##############################################################################
2 # Copyright (c) 2018 HUAWEI TECHNOLOGIES CO.,LTD and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 from flask import Flask
11 from flask import jsonify
12 from flask import request
13 from flask_cors import CORS
14 import os
15 import json
16 import time
17 import pyaml
18 import yaml
19 import traceback
20
21 import src.test_parser as test_parser
22
23
24 BASE_DIR = os.path.abspath(os.path.dirname(__file__))
25 TESTSUITE_DIR = os.path.join(BASE_DIR, "..", "..", "test", "test_case")
26 SERVICE_DIR = os.path.join(BASE_DIR, "..", "env", "service")
27 CONTEXT_FILE_DIR = os.path.join(BASE_DIR, "..", "env", "context",
28                                 "context.yaml")
29 app = Flask(__name__)
30 CORS(app)
31
32
33 ###############
34 # 1. EXECUTE API
35 ###########################################################################
36 @app.route("/")
37 def hello():
38     return "Hello, World! This is a greet from parser." + SERVICE_DIR
39
40
41 @app.route("/execute/testcase", methods=['POST'])
42 def runTestcase():
43     suiteName = request.values.get('suiteName')
44     caseName = request.values.get('caseName')
45     try:
46         casePath = os.path.join(TESTSUITE_DIR, suiteName, caseName)
47         if os.path.exists(casePath):
48             workflowId = test_parser.parse(casePath)
49             if workflowId is None or workflowId == '':
50                 return jsonify({"code": 500, "error": "Server Error."})
51             return jsonify({"code": 200, "result": {"workflowId": workflowId}})
52         else:
53             return jsonify({"code": 300, "error": "no such test case:  %s" %
54                            (os.path.join(suiteName, caseName))})
55     except BaseException, e:
56         return returnServerError(e)
57
58
59 @app.route("/story-content")
60 def getStoryContent():
61     try:
62         story_name = request.args['story']
63         service_name = request.args['service']
64         storyFileDir = os.path.join("/tmp", "generate_workflow.json")
65         with open(storyFileDir, "r") as f:
66             storyContent = f.read()
67     except BaseException, e:
68         return returnServerError(e)
69
70     result = {"code": 200, "result":
71               {"service": service_name, "story": story_name,
72                "content": storyContent}}
73     return jsonify(result)
74
75
76 ###############
77 # 2. TESTCASE CRUD
78 ###########################################################################
79 @app.route("/testsuite/list")
80 def getAllSuite():
81     res = []
82     id = 1
83     try:
84         for fileName in os.listdir(TESTSUITE_DIR):
85             suiteInfo = {}
86             suiteInfo["id"] = id
87             suiteInfo["testsuite"] = fileName
88             res.append(suiteInfo)
89             id = id + 1
90     except BaseException, e:
91         print e
92         app.logger.error(traceback.format_exc())
93         return jsonify({"code": 500, "error": "Server error"})
94
95     return jsonify({"code": 200, "result": res})
96
97
98 @app.route("/testsuite/content")
99 def getSuiteContent():
100     res = []
101     id = 1
102     try:
103         suiteName = request.values.get("suiteName")
104         exSuitePath = os.path.join(TESTSUITE_DIR, suiteName)
105         if os.path.exists(exSuitePath):
106             for fileName in os.listdir(exSuitePath):
107                 tcInfo = {}
108                 tcInfo["id"] = id
109                 tcInfo["testcase"] = fileName
110                 res.append(tcInfo)
111                 id = id + 1
112         else:
113             return jsonify({"code": 300, "error": "no such test suite!"})
114     except BaseException, e:
115         print e
116         app.logger.error(traceback.format_exc())
117         return jsonify({"code": 500, "error": "Server error"})
118
119     return jsonify({"code": 200, "result": res})
120
121
122 @app.route("/testcase/content")
123 def getTCContent():
124     res = ""
125     editorRes = ""
126     try:
127         suiteName = request.values.get("suiteName")
128         caseName = request.values.get("caseName")
129         casePath = os.path.join(suiteName, caseName)
130         casePath = os.path.join(TESTSUITE_DIR, casePath)
131         if os.path.exists(casePath):
132             with open(casePath, "r") as f:
133                 fileContent = f.read()
134             res = fileContent
135             editorRes = test_parser.getWebTestcase(yaml.load(res))
136         else:
137             return jsonify({"code": 300, "error": "no such file!"})
138     except BaseException, e:
139         print e
140         app.logger.error(traceback.format_exc())
141         return jsonify({"code": 500, "error": "Server error"})
142
143     return jsonify({"code": 200, "result":
144                     {"content": res, "editorContent": editorRes}})
145
146
147 @app.route("/testsuite/new", methods=['POST'])
148 def addNewSuite():
149     try:
150         suiteName = request.values.get("suiteName")
151         for fileName in os.listdir(TESTSUITE_DIR):
152             if fileName == suiteName:
153                 return jsonify({"code": 300,
154                                 "error": "testsuite already exists!"})
155         testSuitePath = os.path.join(TESTSUITE_DIR, suiteName)
156         os.mkdir(testSuitePath)
157     except BaseException, e:
158         return returnServerError(e)
159
160     return jsonify({"code": 200, "result": "ok"})
161
162
163 @app.route("/testsuite/delete", methods=['POST'])
164 def deleteSuite():
165     try:
166         suiteName = request.values.get("suiteName")
167         for fileName in os.listdir(TESTSUITE_DIR):
168             if fileName == suiteName:
169                 testSuitePath = os.path.join(TESTSUITE_DIR, fileName)
170                 del_file(testSuitePath)
171                 os.rmdir(testSuitePath)
172                 return jsonify({"code": 200, "result": "ok"})
173     except BaseException, e:
174         return returnServerError(e)
175
176     return jsonify({"code": 300, "error": "no such testsuite!"})
177
178
179 def del_file(path):
180     for i in os.listdir(path):
181         path_file = os.path.join(path, i)
182         if os.path.isfile(path_file):
183             os.remove(path_file)
184         else:
185             del_file(path_file)
186
187
188 @app.route("/testcase/new", methods=['POST'])
189 def createTestcase():
190     try:
191         suiteName = request.values.get("suiteName")
192         caseName = request.values.get("caseName")
193         exSuitePath = os.path.join(TESTSUITE_DIR, suiteName)
194         if os.path.exists(exSuitePath):
195             for fileName in os.listdir(exSuitePath):
196                 if fileName == caseName:
197                     return jsonify({"code": 301,
198                                     "error": "testcase already exists!"})
199             casePath = os.path.join(exSuitePath, caseName)
200             with open(casePath, "w") as f:
201                 # the next line is a placeholder.
202                 print f
203         else:
204             return jsonify({"code": 300, "error": "no such test suite!"})
205     except BaseException, e:
206         return returnServerError(e)
207
208     return jsonify({"code": 200, "result": "ok"})
209
210
211 @app.route("/testcase/delete", methods=['POST'])
212 def deleteTestcase():
213     try:
214         suiteName = request.values.get("suiteName")
215         caseName = request.values.get("caseName")
216         exSuitePath = os.path.join(TESTSUITE_DIR, suiteName)
217         if os.path.exists(exSuitePath):
218             for fileName in os.listdir(exSuitePath):
219                 if fileName == caseName:
220                     casePath = os.path.join(exSuitePath, caseName)
221                     os.remove(casePath)
222                     return jsonify({"code": 200, "result": "ok"})
223             return jsonify({"code": 301, "error": "no such test case!"})
224         else:
225             return jsonify({"code": 300, "error": "no such test suite!"})
226     except BaseException, e:
227         return returnServerError(e)
228
229
230 @app.route("/testcase/save", methods=["POST"])
231 def saveTCContent():
232     try:
233         suiteName = request.values.get("suiteName")
234         caseName = request.values.get("caseName")
235         stepList = json.loads(request.values.get("stepList"))
236         subflowList = json.loads(request.values.get("subflowList"))
237         mainOrdersList = json.loads(request.values.get("mainOrdersList"))
238         jsonObj = {"stepList": stepList, "subflowList": subflowList,
239                    "mainOrdersList": mainOrdersList}
240         parseData = test_parser.parseWebTestcase(jsonObj)
241
242         casePath = os.path.join(suiteName, caseName)
243         casePath = os.path.join(TESTSUITE_DIR, casePath)
244         if os.path.exists(casePath):
245             with open(casePath, "w") as f:
246                 pyaml.dump(parseData, f, safe=True)
247         else:
248             return jsonify({"code": 300, "error": "no such file!"})
249     except BaseException, e:
250         return returnServerError(e)
251
252     return jsonify({"code": 200, "result": "save success"})
253
254
255 ###############
256 # 3.1 API FOR SERVICE
257 ############################################################
258 @app.route("/service/list")
259 def getAllServices():
260     res = []
261     try:
262         for fileName in os.listdir(SERVICE_DIR):
263             serviceName = os.path.splitext(fileName)[0]
264             res.append(serviceName)
265     except BaseException, e:
266         return returnServerError(e)
267
268     return jsonify({"code": 200, "result": res})
269
270
271 @app.route("/service/content")
272 def getServiceContent():
273     res = {}
274     try:
275         serviceName = request.values.get("serviceName")
276         for fileName in os.listdir(SERVICE_DIR):
277             if serviceName == os.path.splitext(fileName)[0]:
278                 res["actions"] = []
279                 filePath = os.path.join(SERVICE_DIR, fileName)
280                 with open(filePath, "r") as f:
281                     content = yaml.load(f)
282                     apisArr = content[serviceName]['apis']
283                     for i in range(len(apisArr)):
284                         apisArr[i].pop("method")
285                         apisArr[i].pop("baseuri")
286                     res["actions"] = apisArr
287     except BaseException, e:
288         return returnServerError(e)
289
290     if res == {}:
291         return jsonify({"code": 300, "error": "no such service!"})
292
293     return jsonify({"code": 200, "result": res})
294
295
296 def paramTransform(paramDict):
297     res = []
298     for (key, value) in paramDict.items():
299         paramJson = {}
300         paramJson["name"] = key
301         paramJson["description"] = value["help"]
302         if "params" in value:
303             paramJson["params"] = paramTransform(value["params"])
304         res.append(paramJson)
305     return res
306
307
308 @app.route("/service/action_response")
309 def actionResponse():
310     res = {}
311     try:
312         serviceName = request.values.get("serviceName")
313         actionName = request.values.get("actionName")
314         for fileName in os.listdir(SERVICE_DIR):
315             if serviceName == os.path.splitext(fileName)[0]:
316                 res["responseParams"] = []
317                 filePath = os.path.join(SERVICE_DIR, fileName)
318                 with open(filePath, "r") as f:
319                     content = yaml.load(f)
320                     apisArr = content[serviceName]['apis']
321                 for i in range(len(apisArr)):
322                     if actionName == apisArr[i]['name'] and (
323                        "response" in apisArr[i]):
324                         res["responseParams"] = apisArr[i]["response"]
325     except BaseException, e:
326         return returnServerError(e)
327     if res == {}:
328         return jsonify({"code": 300, "error": "no such service!"})
329     return jsonify({"code": 200, "result": res})
330
331
332 ###############
333 # 3.2 API FOR ENVIRONMENT SERVICE AND CONTEXT
334 ###########################################################################
335 @app.route('/env/getAllServices')
336 def getAllService():
337     res = []
338     id = 1
339     try:
340         for fileName in os.listdir(SERVICE_DIR):
341             item = {}
342             item['id'] = id
343             item['name'] = os.path.splitext(fileName)[0]
344             filePath = os.path.join(SERVICE_DIR, fileName)
345             filemt = time.localtime(os.stat(filePath).st_mtime)
346             item['time'] = time.strftime("%Y-%m-%d", filemt)
347             res.append(item)
348             id = id + 1
349     except BaseException, e:
350         return returnServerError(e)
351     return jsonify({"code": 200, "result": res})
352
353
354 @app.route('/env/getService')
355 def getService():
356     try:
357         serviceName = request.values.get('serviceName')
358         serviceFile = serviceName + '.yaml'
359         servicePath = os.path.join(SERVICE_DIR, serviceFile)
360         if os.path.exists(servicePath):
361             with open(servicePath, "r") as f:
362                 serviceDict = yaml.load(f)
363                 serviceDict = serviceDict[serviceName]
364             return jsonify({"code": 200, "result": serviceDict})
365         else:
366             return jsonify({"code": 300, "error": "no such service!"})
367     except BaseException, e:
368         return returnServerError(e)
369
370
371 @app.route('/env/createService', methods=['POST'])
372 def createService():
373     try:
374         name = str(request.values.get('name'))
375         ip = str(request.values.get('ip'))
376         port = int(request.values.get('port'))
377         apis = json.loads(request.values.get('apis'))
378         service = {
379             name: {
380                 'ip': ip,
381                 'port': port,
382                 'apis': apis
383             }
384         }
385         serviceJson = json.dumps(service, indent=True)
386         print serviceJson
387         app.logger.debug(service)
388
389         serviceFile = name + '.yaml'
390         servicePath = os.path.join(SERVICE_DIR, serviceFile)
391         with open(servicePath, 'w') as f:
392             pyaml.dump(service, f, safe=True)
393     except BaseException, e:
394         return returnServerError(e)
395     return jsonify({"code": 200, "result": "create success!"})
396
397
398 @app.route('/env/editService', methods=['POST'])
399 def editService():
400     try:
401         oldName = str(request.values.get('oldName'))
402         name = str(request.values.get('newName'))
403         ip = str(request.values.get('ip'))
404         port = int(request.values.get('port'))
405         apis = json.loads(request.values.get('apis'))
406         app.logger.debug(apis)
407         service = {
408             name: {
409                 'ip': ip,
410                 'port': port,
411                 'apis': apis
412             }
413         }
414         serviceJson = json.dumps(service, indent=True)
415         print serviceJson
416         app.logger.debug(service)
417
418         for fileName in os.listdir(SERVICE_DIR):
419             serviceName = os.path.splitext(fileName)[0]
420             if serviceName == oldName:
421                 filePath = os.path.join(SERVICE_DIR, fileName)
422                 os.remove(filePath)
423
424         serviceFile = name + '.yaml'
425         servicePath = os.path.join(SERVICE_DIR, serviceFile)
426         with open(servicePath, 'w') as f:
427             pyaml.dump(service, f, safe=True)
428     except BaseException, e:
429         return returnServerError(e)
430     return jsonify({"code": 200, "result": "edit success!"})
431
432
433 @app.route('/env/deleteService', methods=['POST'])
434 def deleteService():
435     try:
436         name = str(request.values.get('serviceName'))
437
438         for fileName in os.listdir(SERVICE_DIR):
439             serviceName = os.path.splitext(fileName)[0]
440             if serviceName == name:
441                 filePath = os.path.join(SERVICE_DIR, fileName)
442                 os.remove(filePath)
443     except BaseException, e:
444         return returnServerError(e)
445     return jsonify({"code": 200, "result": "delete success!"})
446
447
448 @app.route('/env/getContext')
449 def getContext():
450     try:
451         with open(CONTEXT_FILE_DIR, "r") as f:
452             fileContent = f.read()
453         res = fileContent
454     except BaseException, e:
455         return returnServerError(e)
456     return jsonify({"code": 200, "result": {"context": res}})
457
458
459 @app.route('/env/editContext', methods=['POST'])
460 def editContext():
461     try:
462         context = request.values.get("context")
463         test = yaml.load(context)
464         print test
465         with open(CONTEXT_FILE_DIR, "w") as f:
466             f.write(context)
467     except yaml.constructor.ConstructorError, e:
468         app.logger.error(traceback.format_exc())
469         return jsonify({"code": 500, "error":
470                         "context content error: not a .yaml file!"})
471     except BaseException, e:
472         return returnServerError(e)
473
474     return jsonify({"code": 200, "result": "edit context success!"})
475 ###########################################################################
476
477
478 def returnServerError(e, msg="Server Error"):
479     print e
480     app.logger.error(traceback.format_exc())
481     return jsonify({"code": 500, "error": msg})
482
483
484 if __name__ == "__main__":
485     app.run(host='0.0.0.0', port=5310)