def execute_plan_by_web_hook(plan_id): content_type = request.headers.get("Content-Type") if "form" in content_type or "urlencoded" in content_type: request_data = request.form.to_dict() elif "json" in content_type: request_data = request.json if 'testEnvId' not in request_data or not request_data['testEnvId']: return jsonify({'status': 'failed', 'data': '尚未选择环境!'}), 400 else: test_env_id = request_data["testEnvId"] if 'planId' in request_data: plan_id = request_data["planId"] if not validate_plan_id(plan_id): return jsonify({ 'status': 'failed', 'data': 'plan_id is invalid!' }), 400 if "secretToken" not in request_data or not request_data['secretToken']: return jsonify({'status': 'failed', 'data': '请提供secretToken!'}), 400 if not check_secret_for_plan(plan_id, request_data["secretToken"]): return jsonify({'status': 'failed', 'data': 'secretToken校验失败!'}), 400 (env_name, protocol, domain) = get_env_name_and_domain(test_env_id) if not protocol or not domain or not env_name: return jsonify({ 'status': 'failed', 'data': '测试环境配置存在问题,请前往环境设置检查' }), 500 execution_mode = "webHook" execution_remark = request_data["executionRemark"] # 根据时间生成一个ObjectId作为reportId plan_report_id = str(common.get_object_id()) test_plan_report = { '_id': ObjectId(plan_report_id), 'planId': ObjectId(plan_id), 'testEnvId': ObjectId(test_env_id), 'testEnvName': env_name, 'executionMode': execution_mode, 'executionRemark': execution_remark } try: execute_plan_async(plan_id, plan_report_id, test_plan_report, test_env_id, env_name, protocol, domain, execution_mode=execution_mode) return jsonify({'status': 'ok', 'data': "测试已成功启动,请稍后前往「测试计划报告」查看报告"}) except BaseException as e: current_app.logger.error("execute_plan_by_web_hook failed. - %s" % str(e)) return jsonify({'status': 'failed', 'data': "出错了 - %s" % e})
def __init__(self, test_case_suite_id_list, test_domain, trigger_type, is_execute_forbiddened_case=False, test_case_id_list=None, alarm_mail_list=None, is_ding_ding_notify=False, ding_ding_access_token=None, ding_ding_notify_strategy=None, is_enterprise_wechat_notify=False, enterprise_wechat_access_token=None, enterprise_wechat_notify_strategy=None, is_web_hook=False, **trigger_args): if test_case_id_list is None: test_case_id_list = [] if isinstance(test_case_suite_id_list, list) and isinstance(test_case_id_list, list): self.test_case_suite_id_list = list(set(test_case_suite_id_list)) self.test_case_id_list = list(set(test_case_id_list)) else: raise TypeError('test_case_suite_id_list and test_case_id_list must be list!') if isinstance(test_domain, str): self.test_domain = test_domain else: raise TypeError('test_domain must be string!') if isinstance(trigger_type, str) and trigger_type in ["interval", "date", "cron"]: self.trigger_type = trigger_type else: raise TypeError('trigger_type is invalid!') self.trigger_args = trigger_args self.is_execute_forbiddened_case = is_execute_forbiddened_case self.status_history = {} self.ding_ding_access_token = ding_ding_access_token if is_ding_ding_notify else None self.ding_ding_notify_strategy = {'success': True, 'fail': True} \ if is_ding_ding_notify and ding_ding_notify_strategy is None else ding_ding_notify_strategy self.enterprise_wechat_access_token = enterprise_wechat_access_token if enterprise_wechat_access_token else None self.enterprise_wechat_notify_strategy = {'success': True, 'fail': True} \ if is_enterprise_wechat_notify and enterprise_wechat_notify_strategy is None \ else enterprise_wechat_notify_strategy self._id = str(common.get_object_id()) self.alarm_mail_list = [] if alarm_mail_list: if isinstance(alarm_mail_list, list): for alarm_mail in alarm_mail_list: if isinstance(alarm_mail, str) and common.is_valid_email(alarm_mail): self.alarm_mail_list.append(alarm_mail) else: raise TypeError('<%s> is invalid mail!' % alarm_mail) else: raise TypeError('mail_list must be list') self.is_web_hook = is_web_hook self.report_id = None # 告警时发送测试报告生成_id self.report_created_time = None # 告警时发送测试报告生成时间 self.failed_count = 0 # 用于判断是否邮件发送告警
def cron_mission(self): (env_name, domain) = get_env_name_and_domain(self.test_env_id) if not domain: return jsonify({'status': 'failed', 'data': '未找到任何「启用的」环境信息'}) if not env_name: return jsonify({'status': 'failed', 'data': '测试环境名称为空,请设置环境名称'}) global_env_vars = get_global_env_vars(self.test_env_id) # 根据时间生成一个ObjectId作为reportId report_id = str(common.get_object_id()) test_report = { '_id': ObjectId(report_id), 'testEnvId': ObjectId(self.test_env_id), 'testEnvName': env_name, 'executionMode': self.execution_mode } if self._id: test_report['cronJobId'] = ObjectId(self._id) if self.project_id: test_report['projectId'] = ObjectId(self.project_id) try: test_report_returned = execute_test_by_suite( report_id, test_report, self.test_env_id, self.test_suite_id_list, domain, global_env_vars) save_report(test_report_returned) if test_report_returned['totalCount'] > 0: is_send_mail = test_report_returned[ 'totalCount'] > test_report_returned[ 'passCount'] and isinstance( self.alarm_mail_list, list) and len(self.alarm_mail_list) > 0 print('========mail==========', is_send_mail) if is_send_mail: subject = 'Leo API Auto Test' content = "Dears:<br/>" \ " API test case failed!<br/>" \ " Please login platform for details!<br/>" \ " <a href=\"http://{}:{}/project/{}/testReport/{}\">Click here to see " \ "report detail!</a><br/>" \ " Report ID: {}<br/>" \ " Generated At: {}" \ .format(host_ip, host_port, self.project_id, report_id, report_id, test_report_returned['createAt'].strftime('%Y-%m-%d %H:%M:%S')) mail_result = send_cron_email(self.project_id, self.alarm_mail_list, subject, content) if mail_result.get('status') == 'failed': raise BaseException('邮件发送异常: {}'.format( mail_result.get('data'))) else: raise TypeError('无任何测试结果!') except BaseException as e: return False, "出错了 - %s" % e
def execute_plan_by_manual(plan_id): content_type = request.headers.get("Content-Type") if "form" in content_type: request_data = request.form.to_dict() elif "json" in content_type: request_data = request.json if 'testEnvId' not in request_data or not request_data['testEnvId']: return jsonify({'status': 'failed', 'data': '尚未选择环境!'}), 400 else: test_env_id = request_data["testEnvId"] if 'planId' in request_data: plan_id = request_data["planId"] if not validate_plan_id(plan_id): return jsonify({ 'status': 'failed', 'data': 'plan_id is invalid!' }), 400 (env_name, protocol, domain) = get_env_name_and_domain(test_env_id) if not protocol or not domain or not env_name: return jsonify({'status': 'failed', 'data': '测试环境配置存在问题,请前往环境设置检查'}) execution_mode = "planManual" execution_user = request_data["executionUser"] # 根据时间生成一个ObjectId作为reportId plan_report_id = str(common.get_object_id()) test_plan_report = { '_id': ObjectId(plan_report_id), 'planId': ObjectId(plan_id), 'testEnvId': ObjectId(test_env_id), 'testEnvName': env_name, 'executionMode': execution_mode, 'executionUser': execution_user } try: execute_plan_async(plan_id, plan_report_id, test_plan_report, test_env_id, env_name, protocol, domain, execution_mode=execution_mode) return jsonify({'status': 'ok', 'data': "测试已成功启动,请稍后前往「测试计划报告」查看报告"}) except BaseException as e: current_app.logger.error( "execute_plan_by_manual failed. User:{}, error:{}".format( current_user.email, str(e))) return jsonify({'status': 'failed', 'data': "出错了 - %s" % e})
def start_api_test_by_suite(): request_data = request.get_json() execution_user = None if 'testEnvId' not in request_data: return jsonify({'status': 'failed', 'data': '尚未选择环境!'}) else: test_env_id = request_data["testEnvId"] if 'projectId' in request_data: project_id = request_data['projectId'] if 'testSuiteIdList' in request_data: test_suite_id_list = request_data["testSuiteIdList"] if not test_suite_id_list or len(test_suite_id_list) < 1: return jsonify({'status': 'failed', 'data': '未找到任何「启用的」用例组'}) execution_mode = request_data["executionMode"] if execution_mode == 'manual': execution_user = request_data["executionUser"] (env_name, protocol, domain) = get_env_name_and_domain(test_env_id) if not protocol or not domain or not env_name: return jsonify({'status': 'failed', 'data': '测试环境配置存在问题,请前往环境设置检查'}) global_env_vars = get_global_env_vars(test_env_id) # 根据时间生成一个ObjectId作为reportId report_id = str(common.get_object_id()) test_report = { '_id': ObjectId(report_id), 'testEnvId': ObjectId(test_env_id), 'testEnvName': env_name, 'executionMode': execution_mode } if execution_user: test_report['executionUser'] = execution_user if project_id: test_report['projectId'] = ObjectId(project_id) try: execute_test_by_suite_async(report_id, test_report, test_env_id, test_suite_id_list, protocol, domain, global_env_vars) return jsonify({'status': 'ok', 'data': "测试已成功启动,请稍后前往「测试报告」查看报告"}) except BaseException as e: current_app.logger.error("start_api_test_by_suite failed. - %s" % str(e)) return jsonify({'status': 'failed', 'data': "出错了 - %s" % e})
def __init__(self, test_suite_id_list, project_id, test_env_id, trigger_type, include_forbidden=False, alarm_mail_list=None, is_web_hook=False, **trigger_args): if not isinstance(test_suite_id_list, list) or len(test_suite_id_list) < 1: raise TypeError('test_suite_id_list must be list and not empty!') if not test_env_id: raise ValueError('test_env_id should not be empty.') if not isinstance(trigger_type, str) or trigger_type not in [ "interval", "date", "cron" ]: raise TypeError('trigger_type is invalid!') # cronJob ID self._id = str(common.get_object_id()) self.test_suite_id_list = test_suite_id_list self.project_id = project_id self.test_env_id = test_env_id self.trigger_type = trigger_type self.include_forbidden = include_forbidden self.trigger_args = trigger_args self.status_history = {} self.alarm_mail_list = [] if alarm_mail_list: if isinstance(alarm_mail_list, list): for alarm_mail in alarm_mail_list: if isinstance(alarm_mail, str) and common.is_valid_email(alarm_mail): self.alarm_mail_list.append(alarm_mail) else: raise TypeError('<%s> is invalid mail!' % alarm_mail) else: raise TypeError('mail_list must be list') self.is_web_hook = is_web_hook self.execution_mode = 'cronJob'
def cron_mission(self): try: (env_name, protocol, domain) = get_env_name_and_domain(self.test_env_id) if not protocol or not domain or not env_name: return jsonify({ 'status': 'failed', 'data': '测试环境配置存在问题,请前往环境设置检查' }) global_env_vars = get_global_env_vars(self.test_env_id) alarm_mail_list = [] if self.alarm_mail_group_list: if isinstance(self.alarm_mail_group_list, list) and len(self.alarm_mail_group_list) > 0: alarm_mail_list = get_mails_by_group( self.alarm_mail_group_list) else: raise TypeError('alarm_mail_group_list must be list') # 根据时间生成一个ObjectId作为reportId report_id = str(common.get_object_id()) test_report = { '_id': ObjectId(report_id), 'testEnvId': ObjectId(self.test_env_id), 'testEnvName': env_name, 'executionMode': self.execution_mode } if self.cron_job_id: test_report['cronJobId'] = ObjectId(self.cron_job_id) if self.project_id: test_report['projectId'] = ObjectId(self.project_id) test_report_returned = execute_test_by_suite( report_id, test_report, self.test_env_id, self.test_suite_id_list, protocol, domain, global_env_vars) save_report(test_report_returned) if test_report_returned['totalCount'] > 0: notify_total_count = test_report_returned['totalCount'] notify_pass_count = test_report_returned['passCount'] notify_pass_rate = '{:.2%}'.format(notify_pass_count / notify_total_count) # 发送邮件通知 is_send_mail = ((self.always_send_mail and isinstance( alarm_mail_list, list) and len(alarm_mail_list) > 0) or (test_report_returned['totalCount'] > test_report_returned['passCount'] and isinstance(alarm_mail_list, list) and len(alarm_mail_list) > 0)) if is_send_mail: subject = 'Leo API Auto Test Notify' content_result = "<font color='green'>PASS</font>" if test_report_returned[ 'totalCount'] > test_report_returned['passCount']: content_result = "<font color='red'>FAIL</font>" content = "<h2>Dears:</h2>" \ "<div style='font-size:20px'> API Test CronJob executed successfully!<br/>" \ " Cron Job ID: <b>{}</b><br/>" \ " Environment: <b>{}</b><br/>" \ " Status: <b>{}</b><br/>" \ " TotalAPICount: <b>{}</b><br/>" \ " PassAPICount: <b>{}</b><br/>" \ " PassRate: <b>{}</b><br/>" \ " <a href=\"http://{}:{}/project/{}/testReport/{}\">Please login platform " \ "for details!</a><br/>" \ " Report ID: {}<br/>" \ " Generated At: {} CST</div>" \ .format(self.cron_job_id, env_name, content_result, notify_total_count, notify_pass_count, notify_pass_rate, host_ip, host_port, self.project_id, report_id, report_id, test_report_returned['createAt'].replace(tzinfo=pytz.utc).astimezone( pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S')) mail_result = send_cron_email(alarm_mail_list, subject, content) if mail_result.get('status') == 'failed': raise BaseException('邮件发送异常: {}'.format( mail_result.get('data'))) # 发送企业微信通知 if self.enable_wxwork_notify: if self.always_wxwork_notify \ or test_report_returned['totalCount'] > test_report_returned['passCount']: notify_title = 'Leo API Auto Test Notify' content_result = "<font color='green'>PASS</font>" if test_report_returned[ 'totalCount'] > test_report_returned[ 'passCount']: content_result = "<font color='red'>FAIL</font>" content_text = '''请注意''' content_markdown = '''{} > Dears: API Test CronJob executed successfully! Cron Job ID: **{}** Environment: **{}** Status: **{}** TotalAPICount: **{}** PassAPICount: **{}** PassRate: **{}** [Please login platform for details!](http://{}:{}/project/{}/testReport/{}) Report ID: {} Generated At: {} CST '''.format( notify_title, self.cron_job_id, env_name, content_result, notify_total_count, notify_pass_count, notify_pass_rate, host_ip, host_port, self.project_id, report_id, report_id, test_report_returned['createAt'].replace( tzinfo=pytz.utc).astimezone( pytz.timezone('Asia/Shanghai')).strftime( '%Y-%m-%d %H:%M:%S')) if self.wxwork_mention_mobile_list and len( self.wxwork_mention_mobile_list) > 0: notify_res_text = send_notify.send_wxwork_notify_text( content_text, self.wxwork_mention_mobile_list, self.wxwork_api_key) if notify_res_text.status_code != 200 or eval( str(notify_res_text.content, encoding="utf-8")).get('errcode') != 0: raise BaseException( '企业微信通知发送异常: ResponseCode:{}, ResponseBody:{}' .format(notify_res_text.status_code, notify_res_text.content)) notify_res_markdown = send_notify.send_wxwork_notify_markdown( content_markdown, self.wxwork_api_key) if notify_res_markdown.status_code != 200 or eval( str(notify_res_markdown.content, encoding="utf-8")).get('errcode') != 0: raise BaseException( '企业微信通知发送异常: ResponseCode:{}, ResponseBody:{}'. format(notify_res_markdown.status_code, notify_res_markdown.content)) # 发送钉钉通知 if self.enable_ding_talk_notify: if self.always_ding_talk_notify \ or test_report_returned['totalCount'] > test_report_returned['passCount']: notify_title = 'LEO API Auto Test Notify' content_result = "<font color='#00FF00'>PASS</font>" if test_report_returned[ 'totalCount'] > test_report_returned[ 'passCount']: content_result = "<font color='#FF0000'>FAIL</font>" content = "# {}\n" \ "API Test CronJob executed successfully!\n\n" \ " Cron Job ID: **{}** \n\n" \ " Environment: **{}** \n\n" \ " Status: **{}** \n\n" \ " TotalAPICount: **{}** \n\n" \ " PassAPICount: **{}** \n\n" \ " PassRate: **{}** \n\n" \ " [Please login platform for details!](http://{}:{}/project/{}/testReport/{})\n\n" \ " Report ID: **{}** \n\n" \ " Generated At: **{}** CST\n\n".format(notify_title, self.cron_job_id, env_name, content_result, notify_total_count, notify_pass_count, notify_pass_rate, host_ip, host_port, self.project_id, report_id, report_id, test_report_returned['createAt'].replace( tzinfo=pytz.utc).astimezone( pytz.timezone( 'Asia/Shanghai')).strftime( '%Y-%m-%d %H:%M:%S')) notify_res = send_notify.send_ding_talk_notify_markdown( notify_title, content, self.ding_talk_access_token, at_mobiles=self.ding_talk_at_mobiles, secret=self.ding_talk_secret) if notify_res.status_code != 200 or eval( str(notify_res.content, encoding="utf-8")).get('errcode') != 0: raise BaseException( '钉钉通知发送异常: ResponseCode:{}, ResponseBody:{}'. format(notify_res.status_code, notify_res.content)) else: raise TypeError('无任何测试结果!') except BaseException as e: with app.app_context(): current_app.logger.error( 'CronJob exception, cronJobID: {}, Exception:{}'.format( self.cron_job_id, str(e))) return False, "出错了 - %s" % e
def cron_mission(self): (env_name, protocol, domain) = get_env_name_and_domain(self.test_env_id) if not protocol or not domain or not env_name: return jsonify({ 'status': 'failed', 'data': '测试环境配置存在问题,请前往环境设置检查' }) global_env_vars = get_global_env_vars(self.test_env_id) alarm_mail_list = [] if self.alarm_mail_group_list: if isinstance(self.alarm_mail_group_list, list) and len(self.alarm_mail_group_list) > 0: alarm_mail_list = get_mails_by_group( self.alarm_mail_group_list) else: raise TypeError('alarm_mail_group_list must be list') # 根据时间生成一个ObjectId作为reportId report_id = str(common.get_object_id()) test_report = { '_id': ObjectId(report_id), 'testEnvId': ObjectId(self.test_env_id), 'testEnvName': env_name, 'executionMode': self.execution_mode } if self._id: test_report['cronJobId'] = ObjectId(self._id) if self.project_id: test_report['projectId'] = ObjectId(self.project_id) try: test_report_returned = execute_test_by_suite( report_id, test_report, self.test_env_id, self.test_suite_id_list, protocol, domain, global_env_vars) save_report(test_report_returned) if test_report_returned['totalCount'] > 0: is_send_mail = test_report_returned[ 'totalCount'] > test_report_returned[ 'passCount'] and isinstance( alarm_mail_list, list) and len(alarm_mail_list) > 0 if is_send_mail: subject = 'Leo API Auto Test' content = "<h2>Dears:</h2>" \ "<div style='font-size:20px'> API test case executed successfully! <br/>" \ " Status: <b><font color='red'>FAIL</font></b><br/>" \ " Please login platform for details!<br/>" \ " <a href=\"http://{}:{}/project/{}/testReport/{}\">Click here to view" \ " report detail!</a><br/>" \ " Report ID: {}<br/>" \ " Generated At: {} CST</div>" \ .format(host_ip, host_port, self.project_id, report_id, report_id, test_report_returned['createAt'].replace(tzinfo=pytz.utc).astimezone( pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S')) mail_result = send_cron_email(alarm_mail_list, subject, content) if mail_result.get('status') == 'failed': raise BaseException('邮件发送异常: {}'.format( mail_result.get('data'))) elif self.always_send_mail: subject = 'Leo API Auto Test' content = "<h2>Dears:</h2>" \ "<div style='font-size:20px'> API test case executed successfully!<br/>" \ " Status: <b><font color='green'>PASS</font></b><br/>" \ " Please login platform for details!<br/>" \ " <a href=\"http://{}:{}/project/{}/testReport/{}\">Click here to view" \ " report detail!</a><br/>" \ " Report ID: {}<br/>" \ " Generated At: {} CST</div>" \ .format(host_ip, host_port, self.project_id, report_id, report_id, test_report_returned['createAt'].replace(tzinfo=pytz.utc).astimezone( pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S')) mail_result = send_cron_email(alarm_mail_list, subject, content) if mail_result.get('status') == 'failed': raise BaseException('邮件发送异常: {}'.format( mail_result.get('data'))) else: raise TypeError('无任何测试结果!') except BaseException as e: return False, "出错了 - %s" % e
def add_cron_job(project_id): try: request_data = request.get_json() request_data["projectId"] = ObjectId(project_id) request_data["testEnvId"] = ObjectId(request_data["testEnvId"]) if "alarmMailGroupList" in request_data and len( request_data["alarmMailGroupList"]) > 0: for index, value in enumerate(request_data["alarmMailGroupList"]): request_data["alarmMailGroupList"][index] = ObjectId(value) request_data["createAt"] = datetime.utcnow() if 'interval' in request_data and request_data['interval'] < 60: return jsonify({'status': 'failed', 'data': '定时任务间隔不可小于60秒!'}) if 'interval' in request_data: request_data['interval'] = float(request_data['interval']) if 'runDate' in request_data: request_data['runDate'] = common.frontend_date_str2datetime( request_data['runDate']) filtered_data = CronJob.filter_field(request_data, use_set_default=True) new_cron_job_id = str(common.get_object_id()) if filtered_data.get('runDate'): cron = Cron( cron_job_id=new_cron_job_id, test_suite_id_list=filtered_data.get('testSuiteIdList'), project_id=project_id, test_env_id=filtered_data.get('testEnvId'), trigger_type=filtered_data.get('triggerType'), include_forbidden=filtered_data.get('includeForbidden'), enable_wxwork_notify=filtered_data.get('enableWXWorkNotify'), wxwork_api_key=filtered_data.get('WXWorkAPIKey'), wxwork_mention_mobile_list=filtered_data.get( 'WXWorkMentionMobileList'), always_wxwork_notify=filtered_data.get('alwaysWXWorkNotify'), enable_ding_talk_notify=filtered_data.get( 'enableDingTalkNotify'), ding_talk_access_token=filtered_data.get( 'DingTalkAccessToken'), ding_talk_at_mobiles=filtered_data.get('DingTalkAtMobiles'), ding_talk_secret=filtered_data.get('DingTalkSecret'), always_ding_talk_notify=filtered_data.get( 'alwaysDingTalkNotify'), alarm_mail_group_list=filtered_data.get('alarmMailGroupList'), always_send_mail=filtered_data.get('alwaysSendMail'), run_date=filtered_data.get('runDate')) else: cron = Cron( cron_job_id=new_cron_job_id, test_suite_id_list=filtered_data.get('testSuiteIdList'), project_id=project_id, test_env_id=filtered_data.get('testEnvId'), trigger_type=filtered_data.get('triggerType'), include_forbidden=filtered_data.get('includeForbidden'), enable_wxwork_notify=filtered_data.get('enableWXWorkNotify'), wxwork_api_key=filtered_data.get('WXWorkAPIKey'), wxwork_mention_mobile_list=filtered_data.get( 'WXWorkMentionMobileList'), always_wxwork_notify=filtered_data.get('alwaysWXWorkNotify'), enable_ding_talk_notify=filtered_data.get( 'enableDingTalkNotify'), ding_talk_access_token=filtered_data.get( 'DingTalkAccessToken'), ding_talk_at_mobiles=filtered_data.get('DingTalkAtMobiles'), ding_talk_secret=filtered_data.get('DingTalkSecret'), always_ding_talk_notify=filtered_data.get( 'alwaysDingTalkNotify'), alarm_mail_group_list=filtered_data.get('alarmMailGroupList'), always_send_mail=filtered_data.get('alwaysSendMail'), seconds=filtered_data.get('interval')) cron_id = cron_manager.add_cron(cron) filtered_data['lastUpdateTime'] = datetime.utcnow() update_response = CronJob.update({"_id": cron_id}, {'$set': filtered_data}) if update_response["n"] == 0: return jsonify({'status': 'failed', 'data': '新建成功但未找到相应更新数据!'}) current_app.logger.info("add cron job successfully. New Cron Id: %s" % str(cron_id)) return jsonify({'status': 'ok', 'data': '新建成功'}) except BaseException as e: current_app.logger.error("add cron job failed. - %s" % str(e)) return jsonify({'status': 'failed', 'data': '新建失败: %s' % e})