Example #1
0
def get_task_detail(request, task_id, project_id):
    """
    @summary: 获取任务详细信息
    @param request:
    @param task_id:
    @param project_id:
    @return:
    """
    project = request.project
    try:
        task = TaskFlowInstance.objects.get(id=task_id, project_id=project.id)
    except TaskFlowInstance.DoesNotExist:
        message = (
            "[API] get_task_detail task[id={task_id}] "
            "of project[project_id={project_id}, biz_id{biz_id}] does not exist"
            .format(task_id=task_id,
                    project_id=project.id,
                    biz_id=project.bk_biz_id))
        logger.exception(message)
        return {
            "result": False,
            "message": message,
            "code": err_code.CONTENT_NOT_EXIST.code
        }

    data = task.get_task_detail()
    return {"result": True, "data": data, "code": err_code.SUCCESS.code}
def get_user_project_detail(request, project_id):
    try:
        biz_detail = get_business_detail(request.user.username,
                                         request.project.bk_biz_id)
    except Exception as e:
        logger.exception(
            "[API] get_user_business_detail call fail: {}".format(e))
        return {
            "result":
            False,
            "message":
            "can not get business[{}] detail for user[{}]".format(
                request.user.username, request.project.bk_biz_id),
            "code":
            err_code.UNKNOWN_ERROR.code,
        }

    return {
        "result": True,
        "data": {
            "project_id": request.project.id,
            "project_name": request.project.name,
            "from_cmdb": request.project.from_cmdb,
            "bk_biz_id": biz_detail["bk_biz_id"],
            "bk_biz_name": biz_detail["bk_biz_name"],
            "bk_biz_developer": biz_detail["bk_biz_developer"],
            "bk_biz_maintainer": biz_detail["bk_biz_maintainer"],
            "bk_biz_tester": biz_detail["bk_biz_tester"],
            "bk_biz_productor": biz_detail["bk_biz_productor"],
        },
        "code": err_code.SUCCESS.code,
    }
Example #3
0
def node_callback(request, task_id, project_id):
    try:
        params = json.loads(request.body)
    except Exception:
        return {
            "result": False,
            "message": "invalid json format",
            "code": err_code.REQUEST_PARAM_INVALID.code
        }

    project = request.project

    try:
        task = TaskFlowInstance.objects.get(id=task_id, project_id=project.id)
    except TaskFlowInstance.DoesNotExist:
        message = (
            "[API] node_callback task[id={task_id}] "
            "of project[project_id={project_id}, biz_id{biz_id}] does not exist"
            .format(task_id=task_id,
                    project_id=project.id,
                    biz_id=project.bk_biz_id))
        logger.exception(message)
        return {
            "result": False,
            "message": message,
            "code": err_code.CONTENT_NOT_EXIST.code
        }

    node_id = params.get("node_id")
    callback_data = params.get("callback_data")
    version = params.get("version")

    return task.callback(node_id, callback_data, version)
Example #4
0
def preview_task_tree(request, project_id, template_id):
    try:
        req_data = json.loads(request.body)
    except Exception:
        return {
            "result": False,
            "message": "request body is not a valid json",
            "code": err_code.REQUEST_PARAM_INVALID.code,
        }

    version = req_data.get("version")
    exclude_task_nodes_id = req_data.get("exclude_task_nodes_id", [])

    if not isinstance(exclude_task_nodes_id, list):
        return {
            "result": False,
            "message": "invalid exclude_task_nodes_id",
            "code": err_code.REQUEST_PARAM_INVALID.code,
        }

    try:
        data = preview_template_tree(request.project.id, PROJECT, template_id,
                                     version, exclude_task_nodes_id)
    except Exception as e:
        logger.exception("[API] preview_task_tree fail: {}".format(e))
        return {
            "result": False,
            "message": "preview_task_tree fail: {}".format(e),
            "code": err_code.UNKNOWN_ERROR.code
        }

    return {"result": True, "data": data, "code": err_code.SUCCESS.code}
Example #5
0
def fast_create_task(request, project_id):

    params = request.params_json
    project = request.project
    logger.info(
        "[API] fast_create_task info, project_id: {project_id}, params: {params}".format(
            project_id=project.id, params=params
        )
    )

    try:
        pipeline_tree = params["pipeline_tree"]
        pipeline_instance_kwargs = {
            "name": standardize_name(params["name"], TASK_NAME_MAX_LENGTH),
            "creator": request.user.username,
            "pipeline_tree": pipeline_tree,
            "description": params.get("description", ""),
        }
    except (KeyError, ValueError) as e:
        return {"result": False, "message": "invalid params: %s" % str(e), "code": err_code.REQUEST_PARAM_INVALID.code}

    has_common_subprocess = params.get("has_common_subprocess", False)
    try:
        template = (
            CommonTemplate(pipeline_template=None) if has_common_subprocess else TaskTemplate(pipeline_template=None)
        )
        pipeline_instance = TaskFlowInstance.objects.create_pipeline_instance(
            template=template, **pipeline_instance_kwargs
        )
    except PipelineException as e:
        message = "[API] fast_create_task create pipeline error: %s" % str(e)
        logger.exception(message)
        return {"result": False, "message": message, "code": err_code.UNKNOWN_ERROR.code}

    taskflow_kwargs = {
        "project": project,
        "pipeline_instance": pipeline_instance,
        "template_source": ONETIME,
        "create_method": "api",
    }
    if params.get("category") in [cate[0] for cate in TASK_CATEGORY]:
        taskflow_kwargs["category"] = params["category"]
    # 职能化任务,新建后进入职能化认领阶段
    if params.get("flow_type", "common") == "common_func":
        taskflow_kwargs["flow_type"] = "common_func"
        taskflow_kwargs["current_flow"] = "func_claim"
    # 常规流程,新建后即可执行
    else:
        taskflow_kwargs["flow_type"] = "common"
        taskflow_kwargs["current_flow"] = "execute_task"
    task = TaskFlowInstance.objects.create(**taskflow_kwargs)
    return {
        "result": True,
        "data": {"task_id": task.id, "task_url": task.url, "pipeline_tree": task.pipeline_tree},
        "code": err_code.SUCCESS.code,
    }
def get_functionalization_task_list(request):
    id_in = request.GET.get("id_in")
    task_id_in = request.GET.get("task_id_in")
    status = request.GET.get("status")
    if id_in:
        try:
            id_in = id_in.split(",")
        except Exception:
            id_in = None
            logger.exception(
                "[API] get_functionalization_task_list id_in[{}] resolve fail, ignore."
                .format(id_in))
    if task_id_in:
        try:
            task_id_in = task_id_in.split(",")
        except Exception:
            task_id_in = None
            logger.exception(
                "[API] get_functionalization_task_list task_id_in[{}] resolve fail, ignore."
                .format(task_id_in))

    filter_kwargs = {}
    if status:
        filter_kwargs["status"] = status
    if id_in:
        filter_kwargs["id__in"] = id_in
    if task_id_in:
        filter_kwargs["task__id__in"] = task_id_in

    function_tasks = FunctionTask.objects.select_related("task").filter(
        **filter_kwargs)
    try:
        function_tasks, count = paginate_list_data(request, function_tasks)
    except Exception as e:
        return {
            "result": False,
            "data": "",
            "message": e,
            "code": err_code.INVALID_OPERATION.code
        }
    data = format_function_task_list_data(function_tasks)

    response = {
        "result": True,
        "data": data,
        "count": count,
        "code": err_code.SUCCESS.code
    }
    return response
Example #7
0
def get_template_list(request, project_id):
    template_source = request.GET.get("template_source", PROJECT)
    id_in = request.GET.get("id_in", None)
    name_keyword = request.GET.get("name_keyword", None)

    if id_in:
        try:
            id_in = id_in.split(",")
        except Exception:
            id_in = None
            logger.exception(
                "[API] id_in[{}] resolve fail, ignore.".format(id_in))

    filter_kwargs = dict(is_deleted=False)
    if id_in:
        filter_kwargs["id__in"] = id_in
    if name_keyword and name_keyword != "":
        filter_kwargs["pipeline_template__name__icontains"] = name_keyword

    project = request.project
    if template_source in NON_COMMON_TEMPLATE_TYPES:
        filter_kwargs["project_id"] = project.id
        templates = TaskTemplate.objects.select_related(
            "pipeline_template").filter(**filter_kwargs)
    else:
        templates = CommonTemplate.objects.select_related(
            "pipeline_template").filter(**filter_kwargs)

    template_list, template_id_list = format_template_list_data(
        templates, project, return_id_list=True)

    # 注入用户有权限的actions
    flow_allowed_actions = get_flow_allowed_actions_for_user(
        request.user.username, FLOW_ACTIONS, template_id_list)
    for template_info in template_list:
        template_id = template_info["id"]
        template_info.setdefault("auth_actions", [])
        for action, allowed in flow_allowed_actions.get(str(template_id),
                                                        {}).items():
            if allowed:
                template_info["auth_actions"].append(action)

    return {
        "result": True,
        "data": template_list,
        "code": err_code.SUCCESS.code
    }
def import_project_template(request, project_id):
    if not request.is_trust:
        return {
            "result": False,
            "message": "you have no permission to call this api.",
            "code": err_code.REQUEST_FORBIDDEN_INVALID.code,
        }

    try:
        req_data = json.loads(request.body)
    except Exception:
        return {
            "result": False,
            "message": "invalid json format",
            "code": err_code.REQUEST_PARAM_INVALID.code
        }

    template_data = req_data.get("template_data", None)
    if not template_data:
        return {
            "result": False,
            "message": "template data can not be none",
            "code": err_code.REQUEST_PARAM_INVALID.code,
        }
    r = read_encoded_template_data(template_data)
    if not r["result"]:
        return r

    try:
        import_result = TaskTemplate.objects.import_templates(
            template_data=r["data"]["template_data"],
            override=False,
            project_id=request.project.id,
            operator=request.user.username,
        )
    except Exception as e:
        logger.exception("[API] import common tempalte error: {}".format(e))
        return {
            "result": False,
            "message":
            "invalid flow data or error occur, please contact administrator",
            "code": err_code.UNKNOWN_ERROR.code,
        }

    return import_result
Example #9
0
def get_task_node_detail(request, task_id, project_id):
    """
    @summary: 获取节点输入输出
    @param request:
    @param task_id:
    @param project_id:
    @return:
    """
    project = request.project
    try:
        task = TaskFlowInstance.objects.get(id=task_id, project_id=project.id)
    except TaskFlowInstance.DoesNotExist:
        message = (
            "[API] get_task_node_detail task[id={task_id}] "
            "of project[project_id={project_id}, biz_id{biz_id}] does not exist"
            .format(task_id=task_id,
                    project_id=project.id,
                    biz_id=project.bk_biz_id))
        logger.exception(message)
        return {
            "result": False,
            "message": message,
            "code": err_code.CONTENT_NOT_EXIST.code
        }

    node_id = request.GET.get("node_id")
    component_code = request.GET.get("component_code")

    try:
        subprocess_stack = json.loads(request.GET.get("subprocess_stack",
                                                      "[]"))
    except Exception:
        return {
            "result": False,
            "message": "subprocess_stack is not a valid array json",
            "code": err_code.UNKNOWN_ERROR.code,
        }
    result = task.get_node_detail(
        node_id=node_id,
        username=request.user.username,
        component_code=component_code,
        subprocess_stack=subprocess_stack,
        project_id=project_id,
    )
    return result
Example #10
0
def get_user_project_list(request):
    try:
        projects = get_user_projects(request.user.username)
    except Exception as e:
        logger.exception("[API] get_user_project_list call fail: {}".format(e))
        return {
            "result":
            False,
            "message":
            "can not fetch project for user[{}]".format(request.user.username),
            "code":
            err_code.UNKNOWN_ERROR.code,
        }

    data = [{
        "project_id": proj.id,
        "bk_biz_id": proj.bk_biz_id,
        "name": proj.name
    } for proj in projects if not proj.is_disable]

    return {"result": True, "data": data, "code": err_code.SUCCESS.code}
Example #11
0
def claim_functionalization_task(request, task_id, project_id):
    try:
        params = json.loads(request.body)
    except Exception:
        return {
            "result": False,
            "message": "request body is not a valid json",
            "code": err_code.REQUEST_PARAM_INVALID.code,
        }

    constants = params.get("constants", {})
    name = params.get("name", "")

    try:
        task = TaskFlowInstance.objects.get(pk=task_id,
                                            project_id=request.project.id)
        result = task.task_claim(request.user.username, constants, name)
    except Exception as e:
        logger.exception(
            "[API] claim_functionalization_task fail: {}".format(e))
        return {
            "result": False,
            "message": "claim_functionalization_task fail: {}".format(e),
            "code": err_code.UNKNOWN_ERROR.code,
        }

    if result["result"] is False:
        return {
            "result": False,
            "message": result["message"],
            "code": err_code.UNKNOWN_ERROR.code
        }
    return {
        "result": True,
        "data": result["message"],
        "code": err_code.SUCCESS.code
    }
Example #12
0
def create_task(request, template_id, project_id):
    params = json.loads(request.body)
    project = request.project
    template_source = params.get("template_source", PROJECT)

    logger.info(
        "[API] create_task info, template_id: {template_id}, project_id: {project_id}, params: {params}"
        .format(template_id=template_id, project_id=project.id, params=params))

    # 兼容老版本的接口调用
    if template_source in NON_COMMON_TEMPLATE_TYPES:
        template_source = PROJECT
        try:
            tmpl = TaskTemplate.objects.select_related(
                "pipeline_template").get(id=template_id,
                                         project_id=project.id,
                                         is_deleted=False)
        except TaskTemplate.DoesNotExist:
            result = {
                "result":
                False,
                "message":
                "template[id={template_id}] of project[project_id={project_id},biz_id={biz_id}] "
                "does not exist".format(template_id=template_id,
                                        project_id=project.id,
                                        biz_id=project.bk_biz_id),
                "code":
                err_code.CONTENT_NOT_EXIST.code,
            }
            return result

    else:
        try:
            tmpl = CommonTemplate.objects.select_related(
                "pipeline_template").get(id=template_id, is_deleted=False)
        except CommonTemplate.DoesNotExist:
            result = {
                "result":
                False,
                "message":
                "common template[id={template_id}] does not exist".format(
                    template_id=template_id),
                "code":
                err_code.CONTENT_NOT_EXIST.code,
            }
            return result

    app_code = getattr(request.jwt.app, settings.APIGW_APP_CODE_KEY)
    if not app_code:
        message = "app_code cannot be empty, make sure api gateway has sent correct params"
        return {
            "result": False,
            "message": message,
            "code": err_code.CONTENT_NOT_EXIST.code
        }

    try:
        params.setdefault("flow_type", "common")
        params.setdefault("constants", {})
        params.setdefault("exclude_task_nodes_id", [])
        params.setdefault("simplify_vars", [])
        params.setdefault("execute_task_nodes_id", [])
        jsonschema.validate(params, APIGW_CREATE_TASK_PARAMS)
    except jsonschema.ValidationError as e:
        logger.exception("[API] create_task raise prams error: %s" % e)
        message = "task params is invalid: %s" % e
        return {
            "result": False,
            "message": message,
            "code": err_code.REQUEST_PARAM_INVALID.code
        }

    create_with_tree = "pipeline_tree" in params

    pipeline_instance_kwargs = {
        "name": params["name"],
        "creator": request.user.username,
        "description": params.get("description", ""),
    }

    if create_with_tree:
        try:
            pipeline_tree = params["pipeline_tree"]
            for key, value in params["constants"].items():
                if key in pipeline_tree["constants"]:
                    if pipeline_tree["constants"][key].get("is_meta", False):
                        meta = copy.deepcopy(pipeline_tree["constants"][key])
                        pipeline_tree["constants"][key]["meta"] = meta
                    pipeline_tree["constants"][key]["value"] = value
            standardize_pipeline_node_name(pipeline_tree)
            validate_web_pipeline_tree(pipeline_tree)
        except Exception as e:
            message = "[API] create_task get invalid pipeline_tree: %s" % str(
                e)
            logger.exception(message)
            return {
                "result": False,
                "message": message,
                "code": err_code.UNKNOWN_ERROR.code
            }

        pipeline_instance_kwargs["pipeline_tree"] = pipeline_tree

        try:
            data = TaskFlowInstance.objects.create_pipeline_instance(
                template=tmpl, **pipeline_instance_kwargs)
        except PipelineException as e:
            message = "[API] create_task create pipeline error: %s" % str(e)
            logger.exception(message)
            return {
                "result": False,
                "message": message,
                "code": err_code.UNKNOWN_ERROR.code
            }
    else:
        # 如果请求参数中含有非空的execute_task_nodes_id(要执行的节点),就将其转换为exclude_task_nodes_id(要排除的节点)
        if not params["execute_task_nodes_id"]:
            exclude_task_nodes_id = params["exclude_task_nodes_id"]
        else:
            exclude_task_nodes_id = get_exclude_nodes_by_execute_nodes(
                params["execute_task_nodes_id"], tmpl)
        try:
            data = TaskFlowInstance.objects.create_pipeline_instance_exclude_task_nodes(
                tmpl,
                pipeline_instance_kwargs,
                params["constants"],
                exclude_task_nodes_id,
                params["simplify_vars"],
            )
        except Exception as e:
            message = f"[API] create_task create pipeline without tree error: {e}"
            logger.exception(message)
            return {
                "result": False,
                "message": message,
                "code": err_code.UNKNOWN_ERROR.code
            }

    task = TaskFlowInstance.objects.create(
        project=project,
        pipeline_instance=data,
        category=tmpl.category,
        template_id=template_id,
        template_source=template_source,
        create_method="api",
        create_info=app_code,
        flow_type=params.get("flow_type", "common"),
        current_flow="execute_task"
        if params.get("flow_type", "common") == "common" else "func_claim",
        engine_ver=EngineConfig.objects.get_engine_ver(
            project_id=project.id,
            template_id=template_id,
            template_source=template_source),
    )

    # crete auto retry strategy
    arn_creator = AutoRetryNodeStrategyCreator(
        taskflow_id=task.id,
        root_pipeline_id=task.pipeline_instance.instance_id)
    arn_creator.batch_create_strategy(task.pipeline_instance.execution_data)

    # create timeout config
    TimeoutNodeConfig.objects.batch_create_node_timeout_config(
        taskflow_id=task.id,
        root_pipeline_id=task.pipeline_instance.instance_id,
        pipeline_tree=task.pipeline_instance.execution_data,
    )

    return {
        "result": True,
        "data": {
            "task_id": task.id,
            "task_url": task.url,
            "pipeline_tree": task.pipeline_tree
        },
        "code": err_code.SUCCESS.code,
    }
Example #13
0
def create_periodic_task(request, template_id, project_id):
    project = request.project

    # check if the periodic task of the project reach the limit
    periodic_task_limit = env.PERIODIC_TASK_PROJECT_MAX_NUMBER
    project_config = ProjectConfig.objects.filter(
        project_id=project.id).only("max_periodic_task_num").first()
    if project_config and project_config.max_periodic_task_num > 0:
        periodic_task_limit = project_config.max_periodic_task_num
    if PeriodicTask.objects.filter(
            project__id=project.id).count() >= periodic_task_limit:
        message = "Periodic task number reaches limit: {}".format(
            periodic_task_limit)
        return {
            "result": False,
            "message": message,
            "code": err_code.INVALID_OPERATION.code
        }

    params = json.loads(request.body)
    template_source = params.get("template_source", PROJECT)
    logger.info(
        "[API] apigw create_periodic_task info, "
        "template_id: {template_id}, project_id: {project_id}, params: {params}"
        .format(template_id=template_id, project_id=project.id, params=params))

    if template_source in NON_COMMON_TEMPLATE_TYPES:
        template_source = PROJECT
        try:
            template = TaskTemplate.objects.get(pk=template_id,
                                                project_id=project.id,
                                                is_deleted=False)
        except TaskTemplate.DoesNotExist:
            result = {
                "result":
                False,
                "message":
                "template[id={template_id}] of project[project_id={project_id} , biz_id{biz_id}] "
                "does not exist".format(
                    template_id=template_id,
                    project_id=project.id,
                    biz_id=project.bk_biz_id,
                ),
                "code":
                err_code.CONTENT_NOT_EXIST.code,
            }
            return result

    else:
        try:
            template = CommonTemplate.objects.get(id=template_id,
                                                  is_deleted=False)
        except CommonTemplate.DoesNotExist:
            result = {
                "result":
                False,
                "message":
                "common template[id={template_id}] does not exist".format(
                    template_id=template_id),
                "code":
                err_code.CONTENT_NOT_EXIST.code,
            }
            return result

    params.setdefault("constants", {})
    params.setdefault("exclude_task_nodes_id", [])
    try:
        jsonschema.validate(params, APIGW_CREATE_PERIODIC_TASK_PARAMS)
    except jsonschema.ValidationError as e:
        logger.warning("[API] create_periodic_task raise prams error: %s" % e)
        message = "task params is invalid: %s" % e
        return {
            "result": False,
            "message": message,
            "code": err_code.REQUEST_PARAM_INVALID.code
        }

    exclude_task_nodes_id = params["exclude_task_nodes_id"]
    pipeline_tree = template.pipeline_tree
    try:
        PipelineTemplateWebPreviewer.preview_pipeline_tree_exclude_task_nodes(
            pipeline_tree, exclude_task_nodes_id)
    except Exception as e:
        logger.exception(
            "[API] create_periodic_task preview tree error: {}".format(e))
        return {
            "result": False,
            "message": str(e),
            "code": err_code.UNKNOWN_ERROR.code
        }

    for key, val in list(params["constants"].items()):
        if key in pipeline_tree["constants"]:
            pipeline_tree["constants"][key]["value"] = val

    name = params["name"]
    cron = params["cron"]

    try:
        replace_template_id(TaskTemplate, pipeline_tree)
    except Exception as e:
        logger.exception(
            "[API] create_periodic_task replace id error: {}".format(e))
        return {
            "result": False,
            "message": str(e),
            "code": err_code.UNKNOWN_ERROR.code
        }

    try:
        task = PeriodicTask.objects.create(
            project=project,
            template=template,
            template_source=template_source,
            name=name,
            cron=cron,
            pipeline_tree=pipeline_tree,
            creator=request.user.username,
        )
    except Exception as e:
        logger.exception(
            "[API] create_periodic_task create error: {}".format(e))
        return {
            "result": False,
            "message": str(e),
            "code": err_code.UNKNOWN_ERROR.code
        }

    data = info_data_from_period_task(task)
    return {"result": True, "data": data, "code": err_code.SUCCESS.code}
Example #14
0
def dispatch_plugin_query(request):
    """
    转发插件表单渲染资源请求,暂时仅考虑GET/POST请求
    body = {
        "url": 被转发资源请求url, 比如:/pipeline/job_get_script_list/4/?type=public
        "method": 'GET|POST',
        "data": data, POST请求的数据
    }
    """

    try:
        params = json.loads(request.body)
    except Exception:
        return {
            "result": False,
            "message": "invalid json format",
            "code": err_code.REQUEST_PARAM_INVALID.code,
        }

    # proxy: url/method/data
    url = params.get("url")
    method = params.get("method", "GET")
    data = params.get("data", {})

    try:
        parsed = urlsplit(url)

        if method.lower() == "get":
            fake_request = RequestFactory().get(
                url, content_type="application/json")
        elif method.lower() == "post":
            fake_request = RequestFactory().post(
                url, data=data, content_type="application/json")
        else:
            return {
                "result":
                False,
                "code":
                err_code.INVALID_OPERATION.code,
                "message":
                "dispatch_plugin_query: only support get and post method.",
            }

        # transfer request.user
        setattr(fake_request, "user", request.user)

        # resolve view_func
        match = resolve(parsed.path, urlconf=None)
        view_func, kwargs = match.func, match.kwargs

        # call view_func
        return view_func(fake_request, **kwargs)

    except Resolver404:
        logger.warning(
            "dispatch_plugin_query: resolve view func 404 for: {}".format(url))
        return {
            "result":
            False,
            "code":
            err_code.REQUEST_PARAM_INVALID.code,
            "message":
            "dispatch_plugin_query: resolve view func 404 for: {}".format(url),
        }

    except Exception as e:
        logger.exception("dispatch_plugin_query: exception for {}".format(e))
        return {
            "result": False,
            "message": "dispatch_plugin_query: exception for {}".format(e),
            "code": err_code.UNKNOWN_ERROR.code,
        }