예제 #1
0
def InterfaceUpload():
    """上传任务流配置文件"""
    # 文件路径
    file_dir = './uploads'
    # 文件类型
    file_type = {'xlsx', 'xls', 'csv'}
    # 异常类型
    err_type = {
        0: '第%s行[序号]参数不为整型',
        1: '第%s行[任务流名称]参数不为字符串类型',
        2: '第%s行[任务流描述]参数不为字符串类型',
        3: '第%s行[任务流目录]参数不为字符串类型',
        5: '第%s行[重试次数]参数不为整型',
        6: '第%s行[依赖任务流序号(本次新建任务流)]参数不为整型或没按逗号分隔',
        7: '第%s行[依赖任务流id(已有任务流)]参数不为空或整型或没按逗号分隔'
    }
    file = request.files['file']
    # 获取文件名
    file_name = file.filename
    # 获取文件后缀
    file_suffix = '.' in file_name and file_name.rsplit('.', 1)[1]
    if file and file_suffix in file_type:
        # 保存文件到upload目录
        file_path = os.path.join(file_dir, file_name)
        file.save(file_path)
        # 异常原因
        err_msg = []
        # excel文件
        if file_suffix in {'xlsx', 'xls'}:
            data = xlrd.open_workbook(file_path)
            # 只取第一个sheet
            sheet = data.sheet_by_name(data.sheet_names()[0])
            # 从第2行开始读取
            data = []
            for i in range(1, sheet.nrows):
                # 取前8列
                item = sheet.row_values(i)[:8]
                try:
                    # 日期格式转换
                    if item[4]:
                        item[4] = xlrd.xldate_as_tuple(item[4], 0)
                        item[4] = datetime.date(*item[4][:3]).strftime('%Y-%m-%d')
                    else:
                        item[4] = None
                except:
                    item[4] = None
                    err_msg.append('第%s行[数据日期]参数格式错误' % (i + 1))
                data.append(item)
        # csv文件
        else:
            data = []
            with open(file_path, "r") as csv_file:
                reader = csv.reader(csv_file)
                for index, line in enumerate(reader):
                    if index > 0:
                        # 取前8列
                        item = line[:8]
                        try:
                            # 日期格式转换
                            date_value = re.findall(r'(\d{4}).(\d{1,2}).(\d{1,2})', item[4])
                            if date_value:
                                item[4] = '%04d-%02d-%02d' % tuple(int(item) for item in date_value[0])
                            else:
                                item[4] = (date.today() + timedelta(days=-1)).strftime('%Y-%m-%d')
                        except:
                            item[4] = None
                            err_msg.append('第%s行[数据日期]参数格式错误' % (index + 1))
                        data.append(item)
        # 任务流id列表
        interface_result = InterfaceModel.get_interface_id_list(db.etl_db)
        interface_ids = [i['interface_id'] for i in interface_result]
        # 文件为空
        if not data:
            err_msg.append('文件为空')
        # [依赖任务流序号(本次新建任务流)]列表
        curr_interface_num = []
        for index, row in enumerate(data):
            # Excel行号
            row_num = index + 2
            # 校验列数
            if len(row) < 8:
                err_msg.append('第%s行参数个数小于8个' % row_num)
            else:
                # 校验并处理每列参数
                for i, param in enumerate(row):
                    try:
                        # int类型参数
                        if i in [0, 5]:
                            row[i] = int(param)
                            # 添加[依赖任务流序号(本次新建任务流)]
                            if i == 0:
                                curr_interface_num.append(row[i])
                        # 字符串类型参数
                        elif i in [1, 2, 3]:
                            row[i] = str(param)
                        # 依赖任务流
                        elif i in [6, 7]:
                            if isinstance(param, str):
                                if param != '':
                                    row[i] = [int(i) for i in str(param).split(',')]
                                else:
                                    row[i] = []
                            else:
                                row[i] = [int(param)]
                    except:
                        err_msg.append(err_type[i] % row_num)
                for i, param in enumerate(row):
                    # [任务流名称]判空
                    if i == 1 and param == '':
                        err_msg.append('第%s行[任务流名称]参数不得为空' % row_num)
                    # [任务流名称]数据库查重
                    if i == 1 and param != '':
                        if InterfaceModel.get_interface_detail_by_name(db.etl_db, param):
                            err_msg.append('第%s行[任务流名称]参数已存在数据库中' % row_num)
                    # [任务流目录]判空
                    if i == 3 and param == '':
                        err_msg.append('第%s行[任务流目录]参数不得为空' % row_num)
                    # [重试次数]次数限制
                    if i == 5 and isinstance(param, int) and (param < 0 or param > 10):
                        err_msg.append('第%s行[重试次数]参数请限制在0-10之内' % row_num)
                    # [依赖任务流序号(本次新建任务流)]判空
                    if i == 6 and isinstance(param, list):
                        for item in param:
                            if item not in curr_interface_num:
                                err_msg.append('第%s行[依赖任务流序号(本次新建任务流)][%s]不存在' % (row_num, item))
                    # [依赖任务流id(已有任务流)]数据库判空
                    if i == 7 and isinstance(param, list):
                        for item in param:
                            if item not in interface_ids:
                                err_msg.append('第%s行[依赖任务流id(已有任务流)][%s]不存在' % (row_num, item))

        # [序号]是否重复
        serial_num = [row[0] for row in data]
        if len(serial_num) != len(set(serial_num)):
            err_msg.append('该文件中[序号]存在重复')

        # [任务流名称]文件内查重
        serial_name = [row[1] for row in data]
        if len(serial_name) != len(set(serial_name)):
            err_msg.append('该文件中[任务流名称]存在重复')
        # 返回异常信息
        if err_msg:
            # 删除文件
            os.remove(file_path)
            return jsonify({'status': 401, 'msg': '文件参数错误', 'data': {'err_msg': err_msg}})
        # 写入数据库
        else:
            # 用户id
            user_info = curr_session.get_info()
            user_id = user_info['id']
            # 依赖任务流序号 -> 任务流id映射
            interface_map = {}
            for item in data:
                # 新增任务流
                interface_id = InterfaceModel.add_interface(db.etl_db, item[1], item[2], item[3], item[4], item[5],
                                                            user_id)
                # 添加映射
                interface_map[item[0]] = interface_id
                # 表格数据中新增任务流id字段
                item.append(interface_id)
            # 新增任务流依赖
            parent_arr = []
            for line in data:
                parent_interface = []
                # [依赖任务流序号(本次新建任务流)]映射
                if line[6]:
                    parent_interface = [interface_map[i] for i in line[6]]
                # [依赖任务流id(已有任务流)]
                if line[7]:
                    # 合并数组
                    parent_interface += line[7]
                for parent_id in parent_interface:
                    parent_arr.append({
                        # 最后一位为新增的任务id字段
                        'interface_id': line[len(line) - 1],
                        'parent_id': parent_id,
                        'insert_time': int(time.time()),
                        'update_time': int(time.time()),
                        'creator_id': user_id,
                        'updater_id': user_id
                    })
            InterfaceModel.add_interface_parent(db.etl_db, parent_arr) if parent_arr else None
            # 删除文件
            os.remove(file_path)
            return jsonify({'status': 200, 'msg': '成功', 'data': {}})
    else:
        return jsonify({'status': 400, 'msg': '文件类型错误', 'data': {}})
예제 #2
0
def JobUpload():
    """上传任务配置文件"""
    # 文件路径
    file_dir = './uploads'
    # 文件类型
    file_type = {'xlsx', 'xls', 'csv'}
    # 异常类型
    err_type = {
        0: '第%s行[序号]参数不为整型',
        1: '第%s行[所属任务流id]参数不为整型',
        2: '第%s行[任务名称]参数不为字符串类型',
        3: '第%s行[任务描述]参数不为字符串类型',
        4: '第%s行[服务器id]参数不为整型',
        5: '第%s行[任务目录]参数不为字符串类型',
        6: '第%s行[脚本目录]参数不为字符串类型',
        7: '第%s行[脚本命令]参数不为字符串类型',
        8: '第%s行[依赖任务序号(本次新建任务)]参数不为整型或没按逗号分隔',
        9: '第%s行[依赖任务id(已有任务)]参数不为空或整型或没按逗号分隔',
        10: '第%s行[任务参数]不为空或整型或没按逗号分隔',
        11: '第%s行[返回值]参数不为整型'
    }
    file = request.files['file']
    # 获取文件名
    file_name = file.filename
    # 获取文件后缀
    file_suffix = '.' in file_name and file_name.rsplit('.', 1)[1]
    if file and file_suffix in file_type:
        # 保存文件到upload目录
        file_path = os.path.join(file_dir, file_name)
        file.save(file_path)
        # excel文件
        if file_suffix in {'xlsx', 'xls'}:
            data = xlrd.open_workbook(file_path)
            # 只取第一个sheet
            sheet = data.sheet_by_name(data.sheet_names()[0])
            # 从第2行开始读取
            data = []
            for i in range(1, sheet.nrows):
                # 取前12列
                data.append(sheet.row_values(i)[:12])
        # csv文件
        else:
            data = []
            with open(file_path, "r") as csv_file:
                reader = csv.reader(csv_file)
                for index, line in enumerate(reader):
                    if index > 0:
                        # 取前12列
                        data.append(line[:12])
        # 异常原因
        err_msg = []
        # 任务流id列表
        interface_result = InterfaceModel.get_interface_id_list(db.etl_db)
        interface_ids = [i['interface_id'] for i in interface_result]
        # 服务器id列表
        exec_host_result = ExecHostModel.get_exec_host_all(db.etl_db)
        exec_host_ids = [i['server_id'] for i in exec_host_result]
        # 依赖任务id(已有任务)列表
        job_result = JobModel.get_job_list_all(db.etl_db)
        job_ids = [i['job_id'] for i in job_result]
        # 任务参数列表
        job_params = ParamsModel.get_params_all(db.etl_db)
        job_params_ids = [i['param_id'] for i in job_params]
        # 文件为空
        if not data:
            err_msg.append('文件为空')
        # [依赖任务序号(本次新建任务)]列表
        curr_job_num = []
        for index, row in enumerate(data):
            # Excel行号
            row_num = index + 2
            # 校验列数
            if len(row) < 10:
                err_msg.append('第%s行参数个数小于10个' % row_num)
            else:
                # 校验并处理每列参数
                for i, param in enumerate(row):
                    try:
                        # int类型参数
                        if i in [0, 1, 4, 11]:
                            row[i] = int(param)
                            # 添加[依赖任务序号(本次新建任务)]
                            if i == 0:
                                curr_job_num.append(row[i])
                        # 字符串类型参数
                        elif i in [2, 3, 5, 6, 7]:
                            row[i] = str(param)
                        # 依赖任务
                        else:
                            if isinstance(param, str):
                                if param != '':
                                    row[i] = [int(i) for i in str(param).split(',')]
                                else:
                                    row[i] = []
                            else:
                                row[i] = [int(param)]
                    except:
                        err_msg.append(err_type[i] % row_num)
                for i, param in enumerate(row):
                    # [所属任务流id]判空
                    if i == 1 and isinstance(param, int):
                        if param not in interface_ids:
                            err_msg.append('第%s行[所属任务流id]不存在' % row_num)
                    # [任务名称]判空
                    if i == 2 and param == '':
                        err_msg.append('第%s行[任务名称]参数不得为空' % row_num)
                    # [任务名称]数据库查重
                    if i == 2 and param != '':
                        if JobModel.get_job_detail_by_name(db.etl_db, param):
                            err_msg.append('第%s行[任务名称]参数已存在数据库中' % row_num)
                    # [服务器id]判空
                    if i == 4 and isinstance(param, int):
                        if param not in exec_host_ids:
                            err_msg.append('第%s行[服务器id]不存在' % row_num)
                    # [任务目录]判空和","字符串
                    if i == 5:
                        if param == '':
                            err_msg.append('第%s行[任务目录]参数不得为空' % row_num)
                        elif re.findall(',', param):
                            err_msg.append('第%s行[任务目录]参数不得出现逗号字符","' % row_num)
                    # [脚本目录]判空
                    if i == 6 and param == '':
                        err_msg.append('第%s行[脚本目录]参数不得为空' % row_num)
                    # [脚本命令]判空
                    if i == 7 and param == '':
                        err_msg.append('第%s行[脚本命令]参数不得为空' % row_num)
                    # [依赖任务序号(本次新建任务)]数据库判空
                    if i == 8 and isinstance(param, list):
                        for job_num in param:
                            if job_num not in curr_job_num:
                                err_msg.append('第%s行[依赖任务序号(本次新建任务)][%s]不存在' % (row_num, job_num))
                    # [依赖任务id(已有任务)]数据库判空
                    if i == 9 and isinstance(param, list):
                        for job_id in param:
                            if job_id not in job_ids:
                                err_msg.append('第%s行[依赖任务id(已有任务)][%s]不存在' % (row_num, job_id))
                    # [任务参数]数据库判空
                    if i == 10 and isinstance(param, list):
                        for job_param in param:
                            if job_param not in job_params_ids:
                                err_msg.append('第%s行[任务参数][%s]不存在' % (row_num, job_param))

        # [序号]是否重复
        serial_num = [row[0] for row in data]
        if len(serial_num) != len(set(serial_num)):
            err_msg.append('该文件中[序号]存在重复')

        # 返回异常信息
        if err_msg:
            # 删除文件
            os.remove(file_path)
            return jsonify({'status': 401, 'msg': '文件类型错误', 'data': {'err_msg': err_msg}})
        # 写入数据库
        else:
            # 用户id
            user_info = curr_session.get_info()
            user_id = user_info['id']
            # 依赖任务序号 -> 任务id映射
            job_map = {}
            for line in data:
                # 新增任务详情
                job_id = JobModel.add_job_detail(db.etl_db, line[2], line[1], line[3], line[5], line[4], line[6],
                                                 line[7], line[11], user_id)
                # 添加映射
                job_map[line[0]] = job_id
                # 表格数据中新增任务id字段
                line.append(job_id)
            # 新增任务依赖
            prep_data = []
            for line in data:
                prep_job = []
                # 本次新增任务序号与任务id映射
                if line[8]:
                    prep_job = [job_map[i] for i in line[8]]
                if line[9]:
                    # 合并数组
                    prep_job += line[9]
                for prep_id in prep_job:
                    prep_data.append({
                        # 最后一位为新增的任务id字段
                        'job_id': line[len(line) - 1],
                        'prep_id': prep_id,
                        'user_id': user_id,
                        'insert_time': int(time.time()),
                        'update_time': int(time.time())
                    })
            JobModel.add_job_prep(db.etl_db, prep_data) if prep_data else None
            # 新增任务参数
            job_params = []
            for line in data:
                for param_id in line[10]:
                    job_params.append({
                        # 最后一位为新增的任务id字段
                        'job_id': line[len(line) - 1],
                        'param_id': param_id,
                        'insert_time': int(time.time()),
                        'update_time': int(time.time()),
                        'user_id': user_id
                    })
            JobModel.add_job_param(db.etl_db, job_params) if job_params else None
            # 删除文件
            os.remove(file_path)
            return jsonify({'status': 200, 'msg': '成功', 'data': {}})
    else:
        return jsonify({'status': 400, 'msg': '文件类型错误', 'data': {}})
예제 #3
0
 def get_interface_id_list():
     """获取接口id列表"""
     result = InterfaceModel.get_interface_id_list(db.etl_db)
     return Response(result=result)