api.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import os
  2. import requests
  3. from flask import jsonify, request, url_for, send_file
  4. from werkzeug.utils import secure_filename
  5. from app import app, utils
  6. #from app.models import init_db, TestRunTask
  7. import uuid
  8. from rq.job import Job
  9. #from baangt.base.DataBaseORM import TestrunLog, DATABASE_URL
  10. from baangt.base.DataBaseORM import engine, TestrunLog
  11. from sqlalchemy.orm import sessionmaker
  12. import datetime
  13. import pickle
  14. from baangt.base.ExportResults.ExportResults import ExportResults
  15. from baangt.base.PathManagement import ManagedPaths
  16. #db_session = init_db()
  17. @app.route('/')
  18. def index():
  19. return 'Welcome to baangt API service'
  20. @app.route(f'/{app.config["API_BASE"]}/run/<string:input_format>', methods=['POST'])
  21. def run_xlsx(input_format):
  22. #
  23. # runs Testrun defined in posted json or xlsx file 'testrun'
  24. #
  25. # validate input format
  26. if not input_format in ['xlsx', 'json']:
  27. app.logger.error(f'Test Run: unsupported input format requested: {input_format}')
  28. return jsonify({'error': 'Invalid input format.'}), 400
  29. # default json Testrun definition
  30. testRunDict = None
  31. globalsDict = None
  32. # process JSON input
  33. if input_format == 'json':
  34. app.logger.info('Test Run: processing JSON input')
  35. data = request.get_json()
  36. if data is None:
  37. app.logger.error('The request does not contain JSON TestRun')
  38. return jsonify({'error': 'The request does not contain JSON TestRun.'}), 400
  39. name = data['name']
  40. testRunName = utils.validateTestrunName(data.get('name'))
  41. testRunDict = data.get('testrun')
  42. globalsDict = data.get('globals')
  43. app.logger.info(f'Test Run Read: name "{testRunName}", definition {"+" if testRunDict else None}, globals {"+" if globalsDict else None}')
  44. # proces XLSX input
  45. if input_format == 'xlsx':
  46. app.logger.info('Test Run: processing XLSX input')
  47. try:
  48. xlsx = request.files.get('testrun')
  49. # get filename and save file
  50. filename = secure_filename(xlsx.filename)
  51. testRunName = os.path.join(os.path.abspath(os.path.dirname(__file__)), app.config['UPLOAD_FOLDER'], filename)
  52. xlsx.save(testRunName)
  53. except Exception as e:
  54. app.logger.error(f'Unable to process input: {e}')
  55. return jsonify({'error': f'{e}'}), 400
  56. # generate UUID
  57. testRunUUID = uuid.uuid4()
  58. # queue job
  59. job = app.task_queue.enqueue(
  60. 'app.tasks.run_testrun',
  61. testRunName=testRunName,
  62. globalSettings=globalsDict,
  63. testRunDict=testRunDict,
  64. testRunId=testRunUUID,
  65. job_id=str(testRunUUID),
  66. )
  67. app.logger.info(f'Test Run queued: {testRunUUID}')
  68. return jsonify({'id': str(job.get_id())}), 202
  69. @app.route(f'/{app.config["API_BASE"]}/results/json/<string:uuid_str>')
  70. def get_testrun(uuid_str):
  71. #
  72. # returns results of the specified Testrun as JSON
  73. #
  74. app.logger.info(f'Testrun results requested: {uuid_str}')
  75. jsonResponse = {'id': uuid_str}
  76. # get TestrunLog from DB
  77. session = sessionmaker(bind=engine)()
  78. log = session.query(TestrunLog).get(uuid.UUID(uuid_str).bytes)
  79. if log:
  80. # Tetsrun completed and saved to DB
  81. jsonResponse.update(log.to_json())
  82. app.logger.info('Testrun results successfully fetched')
  83. return jsonify(jsonResponse), 200
  84. # get task status
  85. try:
  86. job = Job.fetch(uuid_str, connection=app.redis)
  87. app.logger.info(f'Testrun job status: {job.get_status()}')
  88. if job.get_status() == 'finished':
  89. jsonResponse['error'] = 'Failed to save results.'
  90. return jsonify(jsonResponse), 400
  91. if job.get_status() == 'failed':
  92. app.logger.error(f'Failed to finish Testrun: {job.exc_info}')
  93. jsonResponse['error'] = f'Failed to finish Testrun.'
  94. return jsonify(jsonResponse), 400
  95. except Exception as e:
  96. app.logger.error(f'{e}')
  97. jsonResponse['error'] = 'Testrun does not exist! If you are running it on your local system then please wait for completion of the run.'
  98. return jsonify(jsonResponse), 202
  99. return jsonify(jsonResponse), 202
  100. @app.route(f'/{app.config["UPLOAD_FOLDER"]}/<string:filename>')
  101. def uploads(filename):
  102. #
  103. # returns files from 'uploads'
  104. #
  105. filename_splitted = filename.split('.')
  106. if len(filename_splitted) > 1:
  107. if filename_splitted[-1].lower == 'json':
  108. return send_file(
  109. '/'.join((app.config['UPLOAD_FOLDER'], filename)),
  110. mimetype='application/json',
  111. )
  112. return send_file(
  113. '/'.join((app.config['UPLOAD_FOLDER'], filename)),
  114. attachment_filename=filename,
  115. as_attachment=True,
  116. mimetype='application/vnd.ms-excel',
  117. )
  118. return send_file(
  119. '/'.join((app.config['UPLOAD_FOLDER'], filename)),
  120. attachment_filename=f'{filename}.xlsx',
  121. as_attachment=True,
  122. mimetype='application/vnd.ms-excel',
  123. )
  124. @app.route(f'/{app.config["API_BASE"]}/results/update/<string:testRunId>', methods=["POST"])
  125. def update_testRunResult(testRunId):
  126. data = request.get_json(testRunId)
  127. ordt = data.copy()
  128. try:
  129. session = sessionmaker(bind=engine)()
  130. #data["id"] = uuid.UUID(data["id"]).bytes
  131. tr = TestrunLog(
  132. id = uuid.UUID(data["id"]).bytes,
  133. testrunName = data["testrunName"],
  134. logfileName = data["logfileName"],
  135. startTime = datetime.datetime.now(),
  136. endTime = datetime.datetime.now(),
  137. dataFile = data["dataFile"],
  138. statusOk = data["statusOk"],
  139. statusFailed = data["statusFailed"],
  140. statusPaused = data["statusPaused"],
  141. RLPJson = data["RLPJson"],
  142. )
  143. session.add(tr)
  144. session.commit()
  145. return jsonify({"update": "success"}), 200
  146. except Exception as ex:
  147. dat = {"ex": str(ex), "data": ordt}
  148. return jsonify(dat), 200
  149. @app.route(f"/exportresults", methods=["POST"])
  150. def export_result():
  151. try:
  152. data = pickle.loads(request.data)
  153. data["TESTRUNINSTANCE"].managedPaths = ManagedPaths()
  154. results = ExportResults(**data)
  155. return send_file(results.fileName, attachment_filename=results.fileName, mimetype='application/vnd.ms-excel', as_attachment=True), 200
  156. except Exception as ex:
  157. data = {"results": str(ex)}
  158. return jsonify(data), 200